To protect your data, the CISO officer has suggested users to enable GitLab 2FA as soon as possible.

vm.rs 54 KB
Newer Older
qinsoon's avatar
qinsoon committed
1
2
use std::collections::HashMap;

qinsoon's avatar
qinsoon committed
3
use ast::ptr::*;
qinsoon's avatar
qinsoon committed
4
use ast::ir::*;
5
use ast::inst::*;
qinsoon's avatar
qinsoon committed
6
use ast::types;
qinsoon's avatar
qinsoon committed
7
use ast::types::*;
qinsoon's avatar
qinsoon committed
8
use compiler::{Compiler, CompilerPolicy};
qinsoon's avatar
qinsoon committed
9
10
use compiler::backend;
use compiler::backend::BackendTypeInfo;
qinsoon's avatar
qinsoon committed
11
use compiler::machine_code::CompiledFunction;
12
13
use runtime::thread::*;
use runtime::ValueLocation;
qinsoon's avatar
qinsoon committed
14
use utils::ByteSize;
15
use utils::BitSize;
16
use utils::Address;
17
use runtime::mm as gc;
18
use vm::handle::*;
qinsoon's avatar
qinsoon committed
19
20
use vm::vm_options::VMOptions;
use vm::vm_options::MuLogLevel;
21

qinsoon's avatar
qinsoon committed
22
23
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
use log::LogLevel;
24
use std::sync::Arc;
qinsoon's avatar
qinsoon committed
25
use std::sync::RwLock;
26
use std::sync::RwLockWriteGuard;
27
use std::sync::atomic::{AtomicUsize, AtomicBool, ATOMIC_BOOL_INIT, ATOMIC_USIZE_INIT, Ordering};
28

qinsoon's avatar
qinsoon committed
29
30
31
32
33
// FIXME:
// besides fields in VM, there are some 'globals' we need to persist
// such as STRUCT_TAG_MAP
// possibly INTERNAL_ID in ir.rs, internal types, etc

qinsoon's avatar
qinsoon committed
34
pub struct VM {
35
    // ---serialize---
qinsoon's avatar
qinsoon committed
36
    // 0
37
    next_id: AtomicUsize,
qinsoon's avatar
qinsoon committed
38
    // 1
qinsoon's avatar
qinsoon committed
39
    id_name_map: RwLock<HashMap<MuID, MuName>>,
qinsoon's avatar
qinsoon committed
40
    // 2
qinsoon's avatar
qinsoon committed
41
    name_id_map: RwLock<HashMap<MuName, MuID>>,
qinsoon's avatar
qinsoon committed
42
    // 3
qinsoon's avatar
qinsoon committed
43
    types: RwLock<HashMap<MuID, P<MuType>>>,
qinsoon's avatar
qinsoon committed
44
45
    // 4
    backend_type_info: RwLock<HashMap<MuID, Box<BackendTypeInfo>>>,
46
    // 5
qinsoon's avatar
qinsoon committed
47
    constants: RwLock<HashMap<MuID, P<Value>>>,
qinsoon's avatar
qinsoon committed
48
    // 6
qinsoon's avatar
qinsoon committed
49
    globals: RwLock<HashMap<MuID, P<Value>>>,
50
    pub global_locations: RwLock<HashMap<MuID, ValueLocation>>,
qinsoon's avatar
qinsoon committed
51
    // 7
qinsoon's avatar
qinsoon committed
52
    func_sigs: RwLock<HashMap<MuID, P<MuFuncSig>>>,
qinsoon's avatar
qinsoon committed
53
    // 8
qinsoon's avatar
qinsoon committed
54
    funcs: RwLock<HashMap<MuID, RwLock<MuFunction>>>,
qinsoon's avatar
qinsoon committed
55
56
    // 9
    func_vers: RwLock<HashMap<MuID, RwLock<MuFunctionVersion>>>,
57
58
    // 10
    pub primordial: RwLock<Option<MuPrimordialThread>>,
qinsoon's avatar
qinsoon committed
59
60
    // 11
    is_running: AtomicBool,
qinsoon's avatar
qinsoon committed
61
62
    // 12
    pub vm_options: VMOptions,
qinsoon's avatar
qinsoon committed
63
    
64
    // ---partially serialize---
qinsoon's avatar
qinsoon committed
65
    // 13
qinsoon's avatar
qinsoon committed
66
    compiled_funcs: RwLock<HashMap<MuID, RwLock<CompiledFunction>>>,
67
68
69
70
71
72

    // ---do not serialize---

    // client may try to store funcref to the heap, so that they can load it later, and call it
    // however the store may happen before we have an actual address to the func (in AOT scenario)
    aot_pending_funcref_store: RwLock<HashMap<Address, ValueLocation>>
73
74
}

75
76
77
use std::u64;
const PENDING_FUNCREF : u64 = u64::MAX;

qinsoon's avatar
qinsoon committed
78
const VM_SERIALIZE_FIELDS : usize = 14;
qinsoon's avatar
qinsoon committed
79

80
81
impl Encodable for VM {
    fn encode<S: Encoder> (&self, s: &mut S) -> Result<(), S::Error> {
82
83
        let mut field_i = 0;

qinsoon's avatar
qinsoon committed
84
85
        // serialize VM_SERIALIZE_FIELDS fields
        // PLUS ONE extra global STRUCT_TAG_MAP
86
        s.emit_struct("VM", VM_SERIALIZE_FIELDS + 2, |s| {
87
            // next_id
qinsoon's avatar
qinsoon committed
88
            trace!("...serializing next_id");
89
            try!(s.emit_struct_field("next_id", field_i, |s| {
90
91
                s.emit_usize(self.next_id.load(Ordering::SeqCst))
            }));
92
            field_i += 1;
93
94
                
            // id_name_map
qinsoon's avatar
qinsoon committed
95
            trace!("...serializing id_name_map");
96
97
            {
                let map : &HashMap<MuID, MuName> = &self.id_name_map.read().unwrap();            
98
                try!(s.emit_struct_field("id_name_map", field_i, |s| map.encode(s)));
99
            }
100
            field_i += 1;
101
102
            
            // name_id_map
qinsoon's avatar
qinsoon committed
103
            trace!("...serializing name_id_map");
104
105
            {
                let map : &HashMap<MuName, MuID> = &self.name_id_map.read().unwrap(); 
106
                try!(s.emit_struct_field("name_id_map", field_i, |s| map.encode(s)));
107
            }
108
            field_i += 1;
109
110
            
            // types
qinsoon's avatar
qinsoon committed
111
            trace!("...serializing types");
112
113
            {
                let types = &self.types.read().unwrap();
114
                try!(s.emit_struct_field("types", field_i, |s| types.encode(s)));
qinsoon's avatar
qinsoon committed
115
            }
116
117
            field_i += 1;

qinsoon's avatar
qinsoon committed
118
            // STRUCT_TAG_MAP
qinsoon's avatar
qinsoon committed
119
            trace!("...serializing struct_tag_map");
qinsoon's avatar
qinsoon committed
120
121
            {
                let struct_tag_map = types::STRUCT_TAG_MAP.read().unwrap();
122
123
124
125
126
127
128
129
130
                try!(s.emit_struct_field("struct_tag_map", field_i, |s| struct_tag_map.encode(s)));
            }
            field_i += 1;

            // HYBRID_TAG_MAP
            trace!("...serializing hybrid_tag_map");
            {
                let hybrid_tag_map = types::HYBRID_TAG_MAP.read().unwrap();
                try!(s.emit_struct_field("hybrid_tag_map", field_i, |s| hybrid_tag_map.encode(s)));
qinsoon's avatar
qinsoon committed
131
            }
132
            field_i += 1;
qinsoon's avatar
qinsoon committed
133
134
            
            // backend_type_info
qinsoon's avatar
qinsoon committed
135
            trace!("...serializing backend_type_info");
qinsoon's avatar
qinsoon committed
136
137
            {
                let backend_type_info : &HashMap<_, _> = &self.backend_type_info.read().unwrap();
138
                try!(s.emit_struct_field("backend_type_info", field_i, |s| backend_type_info.encode(s)));
qinsoon's avatar
qinsoon committed
139
            }
140
            field_i += 1;
qinsoon's avatar
qinsoon committed
141
142
            
            // constants
qinsoon's avatar
qinsoon committed
143
            trace!("...serializing constants");
qinsoon's avatar
qinsoon committed
144
145
            {
                let constants : &HashMap<_, _> = &self.constants.read().unwrap();
146
                try!(s.emit_struct_field("constants", field_i, |s| constants.encode(s)));
qinsoon's avatar
qinsoon committed
147
            }
148
            field_i += 1;
qinsoon's avatar
qinsoon committed
149
150
            
            // globals
qinsoon's avatar
qinsoon committed
151
            trace!("...serializing globals");
qinsoon's avatar
qinsoon committed
152
153
            {
                let globals: &HashMap<_, _> = &self.globals.read().unwrap();
154
                try!(s.emit_struct_field("globals", field_i, |s| globals.encode(s)));
qinsoon's avatar
qinsoon committed
155
            }
156
            field_i += 1;
qinsoon's avatar
qinsoon committed
157
158
            
            // func sigs
qinsoon's avatar
qinsoon committed
159
            trace!("...serializing func_sigs");
qinsoon's avatar
qinsoon committed
160
161
            {
                let func_sigs: &HashMap<_, _> = &self.func_sigs.read().unwrap();
162
                try!(s.emit_struct_field("func_sigs", field_i, |s| func_sigs.encode(s)));
qinsoon's avatar
qinsoon committed
163
            }
164
            field_i += 1;
qinsoon's avatar
qinsoon committed
165
166
            
            // funcs
qinsoon's avatar
qinsoon committed
167
            trace!("...serializing funcs");
qinsoon's avatar
qinsoon committed
168
169
            {
                let funcs : &HashMap<_, _> = &self.funcs.read().unwrap();
170
                try!(s.emit_struct_field("funcs", field_i, |s| {
qinsoon's avatar
qinsoon committed
171
172
173
174
175
176
177
178
179
180
181
182
                    s.emit_map(funcs.len(), |s| {
                        let mut i = 0;
                        for (k,v) in funcs.iter() {
                            s.emit_map_elt_key(i, |s| k.encode(s)).ok();
                            let func : &MuFunction = &v.read().unwrap();
                            s.emit_map_elt_val(i, |s| func.encode(s)).ok();
                            i += 1;
                        }
                        Ok(())
                    })
                }));
            }
183
            field_i += 1;
qinsoon's avatar
qinsoon committed
184
185
            
            // func_vers
qinsoon's avatar
qinsoon committed
186
            trace!("...serializing func_vers");
qinsoon's avatar
qinsoon committed
187
188
            {
                let func_vers : &HashMap<_, _> = &self.func_vers.read().unwrap();
189
                try!(s.emit_struct_field("func_vers", field_i, |s| {
qinsoon's avatar
qinsoon committed
190
191
192
193
194
195
196
197
198
199
200
201
                    s.emit_map(func_vers.len(), |s| {
                        let mut i = 0;
                        for (k, v) in func_vers.iter() {
                            try!(s.emit_map_elt_key(i, |s| k.encode(s)));
                            let func_ver : &MuFunctionVersion = &v.read().unwrap();
                            try!(s.emit_map_elt_val(i, |s| func_ver.encode(s)));
                            i += 1;
                        }
                        Ok(())
                    })
                }));
            }
202
203
            field_i += 1;

qinsoon's avatar
qinsoon committed
204
            // primordial
qinsoon's avatar
qinsoon committed
205
            trace!("...serializing primordial");
qinsoon's avatar
qinsoon committed
206
207
            {
                let primordial = &self.primordial.read().unwrap();
208
                try!(s.emit_struct_field("primordial", field_i, |s| primordial.encode(s)));
qinsoon's avatar
qinsoon committed
209
            }
210
            field_i += 1;
qinsoon's avatar
qinsoon committed
211
212
            
            // is_running
qinsoon's avatar
qinsoon committed
213
            trace!("...serializing is_running");
qinsoon's avatar
qinsoon committed
214
            {
215
                try!(s.emit_struct_field("is_running", field_i, |s| self.is_running.load(Ordering::SeqCst).encode(s)));
216
            }
217
            field_i += 1;
qinsoon's avatar
qinsoon committed
218
219
220
221
222
223
224

            // options
            trace!("...serializing vm_options");
            {
                try!(s.emit_struct_field("vm_options", field_i, |s| self.vm_options.encode(s)));
            }
            field_i += 1;
225
            
qinsoon's avatar
qinsoon committed
226
            // compiled_funcs
qinsoon's avatar
qinsoon committed
227
            trace!("...serializing compiled_funcs");
qinsoon's avatar
qinsoon committed
228
229
            {
                let compiled_funcs : &HashMap<_, _> = &self.compiled_funcs.read().unwrap();
230
                try!(s.emit_struct_field("compiled_funcs", field_i, |s| {
qinsoon's avatar
qinsoon committed
231
232
233
234
235
236
237
238
239
240
241
242
                    s.emit_map(compiled_funcs.len(), |s| {
                        let mut i = 0;
                        for (k, v) in compiled_funcs.iter() {
                            try!(s.emit_map_elt_key(i, |s| k.encode(s)));
                            let compiled_func : &CompiledFunction = &v.read().unwrap();
                            try!(s.emit_map_elt_val(i, |s| compiled_func.encode(s)));
                            i += 1;
                        }
                        Ok(())
                    })
                }));
            }
243
            field_i += 1;
qinsoon's avatar
qinsoon committed
244
            
qinsoon's avatar
qinsoon committed
245
            trace!("serializing finished");
246
247
248
            Ok(())
        })
    }
qinsoon's avatar
qinsoon committed
249
250
}

qinsoon's avatar
qinsoon committed
251
252
impl Decodable for VM {
    fn decode<D: Decoder>(d: &mut D) -> Result<VM, D::Error> {
253
254
255
        let mut field_i = 0;

        d.read_struct("VM", VM_SERIALIZE_FIELDS + 2, |d| {
qinsoon's avatar
qinsoon committed
256
            // next_id
257
            let next_id = try!(d.read_struct_field("next_id", field_i, |d| {
qinsoon's avatar
qinsoon committed
258
259
                d.read_usize()
            }));
260
            field_i += 1;
qinsoon's avatar
qinsoon committed
261
262
            
            // id_name_map
263
264
265
            let id_name_map = try!(d.read_struct_field("id_name_map", field_i, |d| Decodable::decode(d)));
            field_i += 1;

qinsoon's avatar
qinsoon committed
266
            // name_id_map
267
268
            let name_id_map = try!(d.read_struct_field("name_id_map", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
269
270
            
            // types
271
272
273
274
            let types = try!(d.read_struct_field("types", field_i, |d| Decodable::decode(d)));
            field_i += 1;

            // struct tag map
qinsoon's avatar
qinsoon committed
275
            {
276
                let mut struct_tag_map : HashMap<MuName, StructType_> = try!(d.read_struct_field("struct_tag_map", field_i, |d| Decodable::decode(d)));
qinsoon's avatar
qinsoon committed
277
278
279
280
281
282
                
                let mut map_guard = types::STRUCT_TAG_MAP.write().unwrap();
                map_guard.clear();
                for (k, v) in struct_tag_map.drain() {
                    map_guard.insert(k, v);
                }
283
284
285
286
287
288
289
290
291
292
293
294
295
                field_i += 1;
            }

            // hybrid tag map
            {
                let mut hybrid_tag_map : HashMap<MuName, HybridType_> = try!(d.read_struct_field("hybrid_tag_map", field_i, |d| Decodable::decode(d)));

                let mut map_guard = types::HYBRID_TAG_MAP.write().unwrap();
                map_guard.clear();
                for (k, v) in hybrid_tag_map.drain() {
                    map_guard.insert(k, v);
                }
                field_i += 1;
qinsoon's avatar
qinsoon committed
296
            }
qinsoon's avatar
qinsoon committed
297
298
            
            // backend_type_info
299
300
            let backend_type_info = try!(d.read_struct_field("backend_type_info", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
301
302
            
            // constants
303
304
            let constants = try!(d.read_struct_field("constants", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
305
306
            
            // globals
307
308
            let globals = try!(d.read_struct_field("globals", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
309
310
            
            // func sigs
311
312
            let func_sigs = try!(d.read_struct_field("func_sigs", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
313
314
            
            // funcs
315
            let funcs = try!(d.read_struct_field("funcs", field_i, |d| {
qinsoon's avatar
qinsoon committed
316
317
318
319
320
321
322
323
324
325
                d.read_map(|d, len| {
                    let mut map = HashMap::new();
                    for i in 0..len {
                        let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                        let val = RwLock::new(try!(d.read_map_elt_val(i, |d| Decodable::decode(d))));
                        map.insert(key, val);
                    }
                    Ok(map)
                })
            }));
326
            field_i += 1;
qinsoon's avatar
qinsoon committed
327
328
            
            // func_vers
329
            let func_vers = try!(d.read_struct_field("func_vers", field_i, |d| {
qinsoon's avatar
qinsoon committed
330
331
332
333
334
335
336
337
338
339
                d.read_map(|d, len| {
                    let mut map = HashMap::new();
                    for i in 0..len {
                        let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                        let val = RwLock::new(try!(d.read_map_elt_val(i, |d| Decodable::decode(d))));
                        map.insert(key, val);
                    }
                    Ok(map)
                })
            }));
340
            field_i += 1;
qinsoon's avatar
qinsoon committed
341
342
            
            // primordial
343
344
            let primordial = try!(d.read_struct_field("primordial", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
345
346

            // is_running
347
348
            let is_running = try!(d.read_struct_field("is_running", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
349
350
351
352

            // vm_options
            let vm_options = try!(d.read_struct_field("vm_options", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
353
            
qinsoon's avatar
qinsoon committed
354
            // compiled funcs
355
            let compiled_funcs = try!(d.read_struct_field("compiled_funcs", field_i, |d| {
qinsoon's avatar
qinsoon committed
356
357
358
359
360
361
362
363
364
365
                d.read_map(|d, len| {
                    let mut map = HashMap::new();
                    for i in 0..len {
                        let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
                        let val = RwLock::new(try!(d.read_map_elt_val(i, |d| Decodable::decode(d))));
                        map.insert(key, val);
                    }
                    Ok(map)
                })
            }));
366
            field_i += 1;
qinsoon's avatar
qinsoon committed
367
            
qinsoon's avatar
qinsoon committed
368
369
370
371
372
373
374
375
            let vm = VM{
                next_id: ATOMIC_USIZE_INIT,
                id_name_map: RwLock::new(id_name_map),
                name_id_map: RwLock::new(name_id_map),
                types: RwLock::new(types),
                backend_type_info: RwLock::new(backend_type_info),
                constants: RwLock::new(constants),
                globals: RwLock::new(globals),
376
                global_locations: RwLock::new(hashmap!{}),
qinsoon's avatar
qinsoon committed
377
378
379
380
381
                func_sigs: RwLock::new(func_sigs),
                funcs: RwLock::new(funcs),
                func_vers: RwLock::new(func_vers),
                primordial: RwLock::new(primordial),
                is_running: ATOMIC_BOOL_INIT,
qinsoon's avatar
qinsoon committed
382
                vm_options: vm_options,
383
384
                compiled_funcs: RwLock::new(compiled_funcs),
                aot_pending_funcref_store: RwLock::new(HashMap::new())
qinsoon's avatar
qinsoon committed
385
386
387
388
389
390
391
392
393
394
            };
            
            vm.next_id.store(next_id, Ordering::SeqCst);
            vm.is_running.store(is_running, Ordering::SeqCst);
            
            Ok(vm)
        })
    }
}

395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
macro_rules! gen_handle_int {
    ($fn_from: ident, $fn_to: ident, $int_ty: ty) => {
        pub fn $fn_from (&self, num: $int_ty, len: BitSize) -> APIHandleResult {
            let handle_id = self.next_id();
            self.new_handle (APIHandle {
                id: handle_id,
                v: APIHandleValue::Int(num as u64, len)
            })
        }

        pub fn $fn_to (&self, handle: APIHandleArg) -> $int_ty {
            handle.v.as_int() as $int_ty
        }
    }
}

qinsoon's avatar
qinsoon committed
411
412
impl <'a> VM {
    pub fn new() -> VM {
qinsoon's avatar
qinsoon committed
413
414
415
416
417
418
419
420
421
        VM::new_internal(VMOptions::default())
    }

    pub fn new_with_opts(str: &str) -> VM {
        VM::new_internal(VMOptions::init(str))
    }

    fn new_internal(options: VMOptions) -> VM {
        VM::start_logging(options.flag_log_level);
qinsoon's avatar
qinsoon committed
422

qinsoon's avatar
qinsoon committed
423
        let ret = VM {
424
            next_id: ATOMIC_USIZE_INIT,
425
            is_running: ATOMIC_BOOL_INIT,
qinsoon's avatar
qinsoon committed
426
427
            vm_options: options,

qinsoon's avatar
qinsoon committed
428
429
            id_name_map: RwLock::new(HashMap::new()),
            name_id_map: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
430

qinsoon's avatar
qinsoon committed
431
            constants: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
432

qinsoon's avatar
qinsoon committed
433
            types: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
434
            backend_type_info: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
435

qinsoon's avatar
qinsoon committed
436
            globals: RwLock::new(HashMap::new()),
437
            global_locations: RwLock::new(hashmap!{}),
qinsoon's avatar
qinsoon committed
438

qinsoon's avatar
qinsoon committed
439
            func_sigs: RwLock::new(HashMap::new()),
440
            func_vers: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
441
            funcs: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
442
            compiled_funcs: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
443

444
445
446
            primordial: RwLock::new(None),

            aot_pending_funcref_store: RwLock::new(HashMap::new())
447
        };
qinsoon's avatar
qinsoon committed
448

449
        // insert all intenral types
qinsoon's avatar
qinsoon committed
450
451
452
453
454
455
        {
            let mut types = ret.types.write().unwrap();
            for ty in INTERNAL_TYPES.iter() {
                types.insert(ty.id(), ty.clone());
            }
        }
qinsoon's avatar
qinsoon committed
456

457
        ret.is_running.store(false, Ordering::SeqCst);
Kunshan Wang's avatar
Kunshan Wang committed
458
459
460
461
462
463
464
465
466

        // Does not need SeqCst.
        //
        // If VM creates Mu threads and Mu threads calls traps, the trap handler still "happens
        // after" the creation of the VM itself. Rust does not have a proper memory model, but this
        // is how C++ works.
        //
        // If the client needs to create client-level threads, however, the client should properly
        // synchronise at the time of inter-thread communication, rather than creation of the VM.
467
        ret.next_id.store(USER_ID_START, Ordering::Relaxed);
qinsoon's avatar
qinsoon committed
468

469
470
471
472
        // init types
        types::init_types();

        ret.init_runtime();
qinsoon's avatar
qinsoon committed
473

474
475
        ret
    }
qinsoon's avatar
qinsoon committed
476

477
    fn init_runtime(&self) {
qinsoon's avatar
qinsoon committed
478
479
480
481
482
483
        // init log
        VM::start_logging(self.vm_options.flag_log_level);

        // init gc
        {
            let ref options = self.vm_options;
484
            gc::gc_init(options.flag_gc_immixspace_size, options.flag_gc_lospace_size, options.flag_gc_nthreads, !options.flag_gc_disable_collection);
qinsoon's avatar
qinsoon committed
485
486
487
488
489
490
491
492
493
494
495
496
        }
    }

    fn start_logging(level: MuLogLevel) {
        match level {
            MuLogLevel::None  => {},
            MuLogLevel::Error => VM::start_logging_internal(LogLevel::Error),
            MuLogLevel::Warn  => VM::start_logging_internal(LogLevel::Warn),
            MuLogLevel::Info  => VM::start_logging_internal(LogLevel::Info),
            MuLogLevel::Debug => VM::start_logging_internal(LogLevel::Debug),
            MuLogLevel::Trace => VM::start_logging_internal(LogLevel::Trace),
        }
qinsoon's avatar
qinsoon committed
497
498
499
    }

    pub fn start_logging_trace() {
qinsoon's avatar
qinsoon committed
500
501
502
503
        VM::start_logging_internal(LogLevel::Trace)
    }

    fn start_logging_internal(level: LogLevel) {
504
505
506
507
508
509
510
511
512
        use stderrlog;

        let verbose = match level {
            LogLevel::Error => 0,
            LogLevel::Warn  => 1,
            LogLevel::Info  => 2,
            LogLevel::Debug => 3,
            LogLevel::Trace => 4,
        };
qinsoon's avatar
qinsoon committed
513

514
515
516
        match stderrlog::new().verbosity(verbose).init() {
            Ok(()) => info!("logger initialized"),
            Err(e) => error!("failed to init logger, probably already initialized: {:?}", e)
qinsoon's avatar
qinsoon committed
517
518
        }
    }
519
    
520
521
522
    pub fn resume_vm(serialized_vm: &str) -> VM {
        use rustc_serialize::json;
        
qinsoon's avatar
qinsoon committed
523
        let vm : VM = json::decode(serialized_vm).unwrap();
524
        
525
        vm.init_runtime();
qinsoon's avatar
qinsoon committed
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544

        // restore gc types
        {
            let type_info_guard = vm.backend_type_info.read().unwrap();
            let mut type_info_vec: Vec<Box<BackendTypeInfo>> = type_info_guard.values().map(|x| x.clone()).collect();
            type_info_vec.sort_by(|a, b| a.gc_type.id.cmp(&b.gc_type.id));

            let mut expect_id = 0;
            for ty_info in type_info_vec.iter() {
                use runtime::mm;

                let ref gc_type = ty_info.gc_type;

                if gc_type.id != expect_id {
                    debug_assert!(expect_id < gc_type.id);

                    while expect_id < gc_type.id {
                        use runtime::mm::common::gctype::GCType;

qinsoon's avatar
qinsoon committed
545
                        mm::add_gc_type(GCType::new_noreftype(0, 8));
qinsoon's avatar
qinsoon committed
546
547
548
549
550
551
552
553
554
555
556
                        expect_id += 1;
                    }
                }

                // now expect_id == gc_type.id
                debug_assert!(expect_id == gc_type.id);

                mm::add_gc_type(gc_type.as_ref().clone());
                expect_id += 1;
            }
        }
557
558
559
560
        
        vm
    }
    
561
    pub fn next_id(&self) -> MuID {
Kunshan Wang's avatar
Kunshan Wang committed
562
563
564
        // This only needs to be atomic, and does not need to be a synchronisation operation. The
        // only requirement for IDs is that all IDs obtained from `next_id()` are different. So
        // `Ordering::Relaxed` is sufficient.
565
        self.next_id.fetch_add(1, Ordering::Relaxed)
566
567
    }
    
568
569
570
571
572
573
    pub fn run_vm(&self) {
        self.is_running.store(true, Ordering::SeqCst);
    }
    
    pub fn is_running(&self) -> bool {
        self.is_running.load(Ordering::Relaxed)
qinsoon's avatar
qinsoon committed
574
575
    }
    
576
    pub fn set_name(&self, entity: &MuEntity) {
qinsoon's avatar
qinsoon committed
577
        let id = entity.id();
578
        let name = entity.name().unwrap();
qinsoon's avatar
qinsoon committed
579
580
        
        let mut map = self.id_name_map.write().unwrap();
581
        map.insert(id, name.clone());
qinsoon's avatar
qinsoon committed
582
583
584
585
586
        
        let mut map2 = self.name_id_map.write().unwrap();
        map2.insert(name, id);
    }
    
Kunshan Wang's avatar
Kunshan Wang committed
587
    pub fn id_of_by_refstring(&self, name: &String) -> MuID {
qinsoon's avatar
qinsoon committed
588
        let map = self.name_id_map.read().unwrap();
589
590
591
592
        match map.get(name) {
            Some(id) => *id,
            None => panic!("cannot find id for name: {}", name)
        }
Kunshan Wang's avatar
Kunshan Wang committed
593
594
595
596
    }
    
    pub fn id_of(&self, name: &str) -> MuID {
        self.id_of_by_refstring(&name.to_string())
qinsoon's avatar
qinsoon committed
597
598
599
600
    }
    
    pub fn name_of(&self, id: MuID) -> MuName {
        let map = self.id_name_map.read().unwrap();
601
        map.get(&id).unwrap().clone()
qinsoon's avatar
qinsoon committed
602
603
    }
    
604
    pub fn declare_const(&self, entity: MuEntityHeader, ty: P<MuType>, val: Constant) -> P<Value> {
qinsoon's avatar
qinsoon committed
605
        let mut constants = self.constants.write().unwrap();
606
        let ret = P(Value{hdr: entity, ty: ty, v: Value_::Constant(val)});
607

608
        self.declare_const_internal(&mut constants, ret.id(), ret.clone());
qinsoon's avatar
qinsoon committed
609
610
611
        
        ret
    }
612
613
614
615

    fn declare_const_internal(&self, map: &mut RwLockWriteGuard<HashMap<MuID, P<Value>>>, id: MuID, val: P<Value>) {
        debug_assert!(!map.contains_key(&id));

qinsoon's avatar
qinsoon committed
616
        trace!("declare const #{} = {}", id, val);
617
618
        map.insert(id, val);
    }
qinsoon's avatar
qinsoon committed
619
    
620
621
622
623
624
625
626
    pub fn get_const(&self, id: MuID) -> P<Value> {
        let const_lock = self.constants.read().unwrap();
        match const_lock.get(&id) {
            Some(ret) => ret.clone(),
            None => panic!("cannot find const #{}", id)
        }
    }
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645

    pub fn get_const_nocheck(&self, id: MuID) -> Option<P<Value>> {
        let const_lock = self.constants.read().unwrap();
        match const_lock.get(&id) {
            Some(ret) => Some(ret.clone()),
            None => None
        }
    }

    #[cfg(feature = "aot")]
    pub fn allocate_const(&self, val: P<Value>) -> ValueLocation {
        let id = val.id();
        let name = match val.name() {
            Some(name) => format!("CONST_{}_{}", id, name),
            None => format!("CONST_{}", id)
        };

        ValueLocation::Relocatable(backend::RegGroup::GPR, name)
    }
646
    
647
    pub fn declare_global(&self, entity: MuEntityHeader, ty: P<MuType>) -> P<Value> {
qinsoon's avatar
qinsoon committed
648
        let global = P(Value{
649
650
            hdr: entity,
            ty: self.declare_type(MuEntityHeader::unnamed(self.next_id()), MuType_::iref(ty.clone())),
651
            v: Value_::Global(ty)
qinsoon's avatar
qinsoon committed
652
        });
qinsoon's avatar
qinsoon committed
653
654
        
        let mut globals = self.globals.write().unwrap();
655
        let mut global_locs = self.global_locations.write().unwrap();
656

657
        self.declare_global_internal(&mut globals, &mut global_locs, global.id(), global.clone());
qinsoon's avatar
qinsoon committed
658
        
qinsoon's avatar
qinsoon committed
659
        global
qinsoon's avatar
qinsoon committed
660
    }
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693

    fn declare_global_internal(
        &self,
        globals: &mut RwLockWriteGuard<HashMap<MuID, P<Value>>>,
        global_locs: &mut RwLockWriteGuard<HashMap<MuID, ValueLocation>>,
        id: MuID, val: P<Value>
    ) {
        self.declare_global_internal_no_alloc(globals, id, val.clone());
        self.alloc_global(global_locs, id, val);
    }

    // when bulk declaring, we hold locks for everything, we cannot resolve backend type, and do alloc
    fn declare_global_internal_no_alloc(
        &self,
        globals: &mut RwLockWriteGuard<HashMap<MuID, P<Value>>>,
        id: MuID, val: P<Value>
    ) {
        debug_assert!(!globals.contains_key(&id));

        info!("declare global #{} = {}", id, val);
        globals.insert(id, val.clone());
    }

    fn alloc_global(
        &self,
        global_locs: &mut RwLockWriteGuard<HashMap<MuID, ValueLocation>>,
        id: MuID, val: P<Value>
    ) {
        let backend_ty = self.get_backend_type_info(val.ty.get_referenced_ty().unwrap().id());
        let loc = gc::allocate_global(val, backend_ty);
        info!("allocate global #{} as {}", id, loc);
        global_locs.insert(id, loc);
    }
qinsoon's avatar
qinsoon committed
694
    
695
696
    pub fn declare_type(&self, entity: MuEntityHeader, ty: MuType_) -> P<MuType> {
        let ty = P(MuType{hdr: entity, v: ty});
qinsoon's avatar
qinsoon committed
697
        
qinsoon's avatar
qinsoon committed
698
        let mut types = self.types.write().unwrap();
699

700
        self.declare_type_internal(&mut types, ty.id(), ty.clone());
qinsoon's avatar
qinsoon committed
701
702
703
        
        ty
    }
704
705
706
707
708

    fn declare_type_internal(&self, types: &mut RwLockWriteGuard<HashMap<MuID, P<MuType>>>, id: MuID, ty: P<MuType>) {
        debug_assert!(!types.contains_key(&id));

        types.insert(id, ty.clone());
qinsoon's avatar
qinsoon committed
709

qinsoon's avatar
qinsoon committed
710
        trace!("declare type #{} = {}", id, ty);
qinsoon's avatar
qinsoon committed
711
712
713
714
        if ty.is_struct() {
            let tag = ty.get_struct_hybrid_tag().unwrap();
            let struct_map_guard = STRUCT_TAG_MAP.read().unwrap();
            let struct_inner = struct_map_guard.get(&tag).unwrap();
qinsoon's avatar
qinsoon committed
715
            trace!("  {}", struct_inner);
qinsoon's avatar
qinsoon committed
716
717
718
719
        } else if ty.is_hybrid() {
            let tag = ty.get_struct_hybrid_tag().unwrap();
            let hybrid_map_guard = HYBRID_TAG_MAP.read().unwrap();
            let hybrid_inner = hybrid_map_guard.get(&tag).unwrap();
qinsoon's avatar
qinsoon committed
720
            trace!("  {}", hybrid_inner);
qinsoon's avatar
qinsoon committed
721
        }
722
    }
qinsoon's avatar
qinsoon committed
723
    
724
725
726
727
728
729
730
731
    pub fn get_type(&self, id: MuID) -> P<MuType> {
        let type_lock = self.types.read().unwrap();
        match type_lock.get(&id) {
            Some(ret) => ret.clone(),
            None => panic!("cannot find type #{}", id)
        }
    }    
    
732
733
    pub fn declare_func_sig(&self, entity: MuEntityHeader, ret_tys: Vec<P<MuType>>, arg_tys: Vec<P<MuType>>) -> P<MuFuncSig> {
        let ret = P(MuFuncSig{hdr: entity, ret_tys: ret_tys, arg_tys: arg_tys});
734
735

        let mut func_sigs = self.func_sigs.write().unwrap();
736
        self.declare_func_sig_internal(&mut func_sigs, ret.id(), ret.clone());
qinsoon's avatar
qinsoon committed
737
738
739
        
        ret
    }
740
741
742
743
744
745
746

    fn declare_func_sig_internal(&self, sigs: &mut RwLockWriteGuard<HashMap<MuID, P<MuFuncSig>>>, id: MuID, sig: P<MuFuncSig>) {
        debug_assert!(!sigs.contains_key(&id));

        info!("declare func sig #{} = {}", id, sig);
        sigs.insert(id, sig);
    }
qinsoon's avatar
qinsoon committed
747
    
748
749
750
751
752
753
754
755
    pub fn get_func_sig(&self, id: MuID) -> P<MuFuncSig> {
        let func_sig_lock = self.func_sigs.read().unwrap();
        match func_sig_lock.get(&id) {
            Some(ret) => ret.clone(),
            None => panic!("cannot find func sig #{}", id)
        }
    }
    
756
    pub fn declare_func (&self, func: MuFunction) {
qinsoon's avatar
qinsoon committed
757
        let mut funcs = self.funcs.write().unwrap();
758
759
760
761
762
763
764
765
766

        self.declare_func_internal(&mut funcs, func.id(), func);
    }

    fn declare_func_internal(&self, funcs: &mut RwLockWriteGuard<HashMap<MuID, RwLock<MuFunction>>>, id: MuID, func: MuFunction) {
        debug_assert!(!funcs.contains_key(&id));

        info!("declare func #{} = {}", id, func);
        funcs.insert(id, RwLock::new(func));
767
768
    }
    
769
770
771
772
773
774
775
776
777
    /// The IR builder needs to look-up the function signature from the existing function ID.
    pub fn get_func_sig_for_func(&self, id: MuID) -> P<MuFuncSig> {
        let funcs_lock = self.funcs.read().unwrap();
        match funcs_lock.get(&id) {
            Some(func) => func.read().unwrap().sig.clone(),
            None => panic!("cannot find Mu function #{}", id)
        }
    }    
    
778
    pub fn define_func_version (&self, func_ver: MuFunctionVersion) {
qinsoon's avatar
qinsoon committed
779
        info!("define function version {}", func_ver);
780
        // record this version
qinsoon's avatar
qinsoon committed
781
        let func_ver_id = func_ver.id();
782
783
        {
            let mut func_vers = self.func_vers.write().unwrap();
qinsoon's avatar
qinsoon committed
784
            func_vers.insert(func_ver_id, RwLock::new(func_ver));
785
786
787
788
        }
        
        // acquire a reference to the func_ver
        let func_vers = self.func_vers.read().unwrap();
qinsoon's avatar
qinsoon committed
789
        let func_ver = func_vers.get(&func_ver_id).unwrap().write().unwrap();
790
791
792
        
        // change current version to this (obsolete old versions)
        let funcs = self.funcs.read().unwrap();
qinsoon's avatar
qinsoon committed
793
        debug_assert!(funcs.contains_key(&func_ver.func_id)); // it should be declared before defining
qinsoon's avatar
qinsoon committed
794
        let mut func = funcs.get(&func_ver.func_id).unwrap().write().unwrap();
795
        
796
797
798
799
        func.new_version(func_ver.id());
        
        // redefinition happens here
        // do stuff        
800
    }
801
802
803
804
805
806
807
808
809
810
811
812
813
814

    /// Add a new bundle into VM.
    ///
    /// This function will drain the contents of all arguments.
    ///
    /// Ideally, this function should happen atomically. e.g. The client should not see a new type
    /// added without also seeing a new function added.
    pub fn declare_many(&self,
                        new_id_name_map: &mut HashMap<MuID, MuName>,
                        new_types: &mut HashMap<MuID, P<MuType>>,
                        new_func_sigs: &mut HashMap<MuID, P<MuFuncSig>>,
                        new_constants: &mut HashMap<MuID, P<Value>>,
                        new_globals: &mut HashMap<MuID, P<Value>>,
                        new_funcs: &mut HashMap<MuID, Box<MuFunction>>,
815
816
                        new_func_vers: &mut HashMap<MuID, Box<MuFunctionVersion>>,
                        arc_vm: Arc<VM>
817
818
819
                        ) {
        // Make sure other components, if ever acquiring multiple locks at the same time, acquire
        // them in this order, to prevent deadlock.
820
821
822
823
824
825
826
827
828
        {
            let mut id_name_map = self.id_name_map.write().unwrap();
            let mut name_id_map = self.name_id_map.write().unwrap();
            let mut types = self.types.write().unwrap();
            let mut constants = self.constants.write().unwrap();
            let mut globals = self.globals.write().unwrap();
            let mut func_sigs = self.func_sigs.write().unwrap();
            let mut funcs = self.funcs.write().unwrap();
            let mut func_vers = self.func_vers.write().unwrap();
829

830
831
832
833
            for (id, name) in new_id_name_map.drain() {
                id_name_map.insert(id, name.clone());
                name_id_map.insert(name, id);
            }
834

835
836
837
            for (id, obj) in new_types.drain() {
                self.declare_type_internal(&mut types, id, obj);
            }
838

839
840
841
            for (id, obj) in new_constants.drain() {
                self.declare_const_internal(&mut constants, id, obj);
            }
842

843
844
845
846
            for (id, obj) in new_globals.drain() {
                // we bulk allocate later (since we are holding all the locks, we cannot find ty info)
                self.declare_global_internal_no_alloc(&mut globals, id, obj);
            }
847

848
849
850
            for (id, obj) in new_func_sigs.drain() {
                self.declare_func_sig_internal(&mut func_sigs, id, obj);
            }
851

852
853
854
            for (id, obj) in new_funcs.drain() {
                self.declare_func_internal(&mut funcs, id, *obj);
            }
855

856
857
858
            for (id, obj) in new_func_vers.drain() {
                let func_id = obj.func_id;
                func_vers.insert(id, RwLock::new(*obj));
859

860
861
862
863
864
865
                {
                    trace!("Adding funcver {} as a version of {}...", id, func_id);
                    let func = funcs.get_mut(&func_id).unwrap();
                    func.write().unwrap().new_version(id);
                    trace!("Added funcver {} as a version of {} {:?}.", id, func_id, func);
                }
866
867
868
            }
        }
        // Locks released here
869
870
871
872
873
874
875

        // allocate all the globals defined
        {
            let globals = self.globals.read().unwrap();
            let mut global_locs = self.global_locations.write().unwrap();

            // make sure current thread has allocator
876
            let created = unsafe {MuThread::current_thread_as_mu_thread(Address::zero(), arc_vm.clone())};
877
878
879
880

            for (id, global) in globals.iter() {
                self.alloc_global(&mut global_locs, *id, global.clone());
            }
881
882
883
884

            if created {
                unsafe {MuThread::cleanup_current_mu_thread()};
            }
885
        }
886
    }
887
    
888
    pub fn add_compiled_func (&self, func: CompiledFunction) {
qinsoon's avatar
qinsoon committed
889
        debug_assert!(self.funcs.read().unwrap().contains_key(&func.func_id));
qinsoon's avatar
qinsoon committed
890
        debug_assert!(self.func_vers.read().unwrap().contains_key(&func.func_ver_id));
qinsoon's avatar
qinsoon committed
891

qinsoon's avatar
qinsoon committed
892
        self.compiled_funcs.write().unwrap().insert(func.func_ver_id, RwLock::new(func));
qinsoon's avatar
qinsoon committed
893
894
    }
    
qinsoon's avatar
qinsoon committed
895
    pub fn get_backend_type_info(&self, tyid: MuID) -> Box<BackendTypeInfo> {        
qinsoon's avatar
qinsoon committed
896
897
898
        {
            let read_lock = self.backend_type_info.read().unwrap();
        
899
            match read_lock.get(&tyid) {
qinsoon's avatar
qinsoon committed
900
901
902
903
                Some(info) => {return info.clone();},
                None => {}
            }
        }
904
905

        let types = self.types.read().unwrap();
qinsoon's avatar
qinsoon committed
906
907
908
909
        let ty = match types.get(&tyid) {
            Some(ty) => ty,
            None => panic!("invalid type id during get_backend_type_info(): {}", tyid)
        };
qinsoon's avatar
qinsoon committed
910
        let resolved = Box::new(backend::resolve_backend_type_info(ty, self));
qinsoon's avatar
qinsoon committed
911
912
        
        let mut write_lock = self.backend_type_info.write().unwrap();
913
        write_lock.insert(tyid, resolved.clone());
qinsoon's avatar
qinsoon committed
914
915
916
917
        
        resolved        
    }
    
qinsoon's avatar
qinsoon committed
918
919
920
921
    pub fn get_type_size(&self, tyid: MuID) -> ByteSize {
        self.get_backend_type_info(tyid).size
    }
    
qinsoon's avatar
qinsoon committed
922
    pub fn globals(&self) -> &RwLock<HashMap<MuID, P<Value>>> {
qinsoon's avatar
qinsoon committed
923
924
925
        &self.globals
    }
    
qinsoon's avatar
qinsoon committed
926
    pub fn funcs(&self) -> &RwLock<HashMap<MuID, RwLock<MuFunction>>> {
qinsoon's avatar
qinsoon committed
927
        &self.funcs
928
    }
929
    
qinsoon's avatar
qinsoon committed
930
    pub fn func_vers(&self) -> &RwLock<HashMap<MuID, RwLock<MuFunctionVersion>>> {
931
932
        &self.func_vers
    }
qinsoon's avatar
qinsoon committed
933
934
935
936
937
938
939
940
941
942
943

    pub fn get_cur_version_of(&self, fid: MuID) -> Option<MuID> {
        let funcs_guard = self.funcs.read().unwrap();
        match funcs_guard.get(&fid) {
            Some(rwlock_func) => {
                let func_guard = rwlock_func.read().unwrap();
                func_guard.cur_ver
            },
            None => None
        }
    }
944
    
qinsoon's avatar
qinsoon committed
945
    pub fn compiled_funcs(&self) -> &RwLock<HashMap<MuID, RwLock<CompiledFunction>>> {
946
947
        &self.compiled_funcs
    }
948
949
950
951
952
953
954
955
    
    pub fn types(&self) -> &RwLock<HashMap<MuID, P<MuType>>> {
        &self.types
    }
    
    pub fn func_sigs(&self) -> &RwLock<HashMap<MuID, P<MuFuncSig>>> {
        &self.func_sigs
    }
qinsoon's avatar
qinsoon committed
956
    
957
958
959
960
961
962
963
    pub fn resolve_function_address(&self, func_id: MuID) -> ValueLocation {
        let funcs = self.funcs.read().unwrap();
        let func : &MuFunction = &funcs.get(&func_id).unwrap().read().unwrap();
                
        if self.is_running() {
            unimplemented!()
        } else {
964
            ValueLocation::Relocatable(backend::RegGroup::GPR, func.name().unwrap())
965
966
967
        }
    }
    
qinsoon's avatar
qinsoon committed
968
    pub fn new_stack(&self, func_id: MuID) -> Box<MuStack> {
qinsoon's avatar
qinsoon committed
969
970
971
        let funcs = self.funcs.read().unwrap();
        let func : &MuFunction = &funcs.get(&func_id).unwrap().read().unwrap();
        
972
973
974
        Box::new(MuStack::new(self.next_id(), self.resolve_function_address(func_id), func))
    }
    
qinsoon's avatar
qinsoon committed
975
    pub fn make_primordial_thread(&self, func_id: MuID, has_const_args: bool, args: Vec<Constant>) {
976
        let mut guard = self.primordial.write().unwrap();
qinsoon's avatar
qinsoon committed
977
        *guard = Some(MuPrimordialThread{func_id: func_id, has_const_args: has_const_args, args: args});
qinsoon's avatar
qinsoon committed
978
979
    }
    
qinsoon's avatar
qinsoon committed
980
    #[allow(unused_variables)]
981
    pub fn make_boot_image(&self,
qinsoon's avatar
qinsoon committed
982
983
984
985
986
987
                           whitelist: Vec<MuID>,
                           primordial_func: Option<&APIHandle>, primordial_stack: Option<&APIHandle>,
                           primordial_threadlocal: Option<&APIHandle>,
                           sym_fields: Vec<&APIHandle>, sym_strings: Vec<String>,
                           reloc_fields: Vec<&APIHandle>, reloc_strings: Vec<String>,
                           output_file: String) {
988