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

use ast::ptr::P;
use ast::ir::*;
qinsoon's avatar
qinsoon committed
5
use ast::types;
qinsoon's avatar
qinsoon committed
6
use ast::types::*;
qinsoon's avatar
qinsoon committed
7
8
use compiler::backend;
use compiler::backend::BackendTypeInfo;
qinsoon's avatar
qinsoon committed
9
use compiler::machine_code::CompiledFunction;
10
11
use runtime::thread::*;
use runtime::ValueLocation;
qinsoon's avatar
qinsoon committed
12
use utils::ByteSize;
13
use runtime::mm as gc;
qinsoon's avatar
qinsoon committed
14
15
use vm::vm_options::VMOptions;
use vm::vm_options::MuLogLevel;
16

qinsoon's avatar
qinsoon committed
17
18
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
use log::LogLevel;
qinsoon's avatar
qinsoon committed
19
use std::path;
qinsoon's avatar
qinsoon committed
20
use std::sync::RwLock;
21
use std::sync::atomic::{AtomicUsize, AtomicBool, ATOMIC_BOOL_INIT, ATOMIC_USIZE_INIT, Ordering};
22

qinsoon's avatar
qinsoon committed
23
24
25
26
27
// 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
28
pub struct VM {
29
    // serialize
qinsoon's avatar
qinsoon committed
30
    // 0
31
    next_id: AtomicUsize,
qinsoon's avatar
qinsoon committed
32
    // 1
qinsoon's avatar
qinsoon committed
33
    id_name_map: RwLock<HashMap<MuID, MuName>>,
qinsoon's avatar
qinsoon committed
34
    // 2
qinsoon's avatar
qinsoon committed
35
    name_id_map: RwLock<HashMap<MuName, MuID>>,
qinsoon's avatar
qinsoon committed
36
    // 3
qinsoon's avatar
qinsoon committed
37
    types: RwLock<HashMap<MuID, P<MuType>>>,
qinsoon's avatar
qinsoon committed
38
39
    // 4
    backend_type_info: RwLock<HashMap<MuID, Box<BackendTypeInfo>>>,
40
    // 5
qinsoon's avatar
qinsoon committed
41
    constants: RwLock<HashMap<MuID, P<Value>>>,
qinsoon's avatar
qinsoon committed
42
    // 6
qinsoon's avatar
qinsoon committed
43
    globals: RwLock<HashMap<MuID, P<Value>>>,
qinsoon's avatar
qinsoon committed
44
    // 7
qinsoon's avatar
qinsoon committed
45
    func_sigs: RwLock<HashMap<MuID, P<MuFuncSig>>>,
qinsoon's avatar
qinsoon committed
46
    // 8
qinsoon's avatar
qinsoon committed
47
    funcs: RwLock<HashMap<MuID, RwLock<MuFunction>>>,
qinsoon's avatar
qinsoon committed
48
49
    // 9
    func_vers: RwLock<HashMap<MuID, RwLock<MuFunctionVersion>>>,
50
51
    // 10
    pub primordial: RwLock<Option<MuPrimordialThread>>,
qinsoon's avatar
qinsoon committed
52
53
    // 11
    is_running: AtomicBool,
qinsoon's avatar
qinsoon committed
54
55
    // 12
    pub vm_options: VMOptions,
qinsoon's avatar
qinsoon committed
56
    
57
    // partially serialize
qinsoon's avatar
qinsoon committed
58
    // 13
qinsoon's avatar
qinsoon committed
59
    compiled_funcs: RwLock<HashMap<MuID, RwLock<CompiledFunction>>>,
60
61
}

qinsoon's avatar
qinsoon committed
62
const VM_SERIALIZE_FIELDS : usize = 14;
qinsoon's avatar
qinsoon committed
63

64
65
impl Encodable for VM {
    fn encode<S: Encoder> (&self, s: &mut S) -> Result<(), S::Error> {
66
67
        let mut field_i = 0;

qinsoon's avatar
qinsoon committed
68
69
        // serialize VM_SERIALIZE_FIELDS fields
        // PLUS ONE extra global STRUCT_TAG_MAP
70
        s.emit_struct("VM", VM_SERIALIZE_FIELDS + 2, |s| {
71
            // next_id
qinsoon's avatar
qinsoon committed
72
            trace!("...serializing next_id");
73
            try!(s.emit_struct_field("next_id", field_i, |s| {
74
75
                s.emit_usize(self.next_id.load(Ordering::SeqCst))
            }));
76
            field_i += 1;
77
78
                
            // id_name_map
qinsoon's avatar
qinsoon committed
79
            trace!("...serializing id_name_map");
80
81
            {
                let map : &HashMap<MuID, MuName> = &self.id_name_map.read().unwrap();            
82
                try!(s.emit_struct_field("id_name_map", field_i, |s| map.encode(s)));
83
            }
84
            field_i += 1;
85
86
            
            // name_id_map
qinsoon's avatar
qinsoon committed
87
            trace!("...serializing name_id_map");
88
89
            {
                let map : &HashMap<MuName, MuID> = &self.name_id_map.read().unwrap(); 
90
                try!(s.emit_struct_field("name_id_map", field_i, |s| map.encode(s)));
91
            }
92
            field_i += 1;
93
94
            
            // types
qinsoon's avatar
qinsoon committed
95
            trace!("...serializing types");
96
97
            {
                let types = &self.types.read().unwrap();
98
                try!(s.emit_struct_field("types", field_i, |s| types.encode(s)));
qinsoon's avatar
qinsoon committed
99
            }
100
101
            field_i += 1;

qinsoon's avatar
qinsoon committed
102
            // STRUCT_TAG_MAP
qinsoon's avatar
qinsoon committed
103
            trace!("...serializing struct_tag_map");
qinsoon's avatar
qinsoon committed
104
105
            {
                let struct_tag_map = types::STRUCT_TAG_MAP.read().unwrap();
106
107
108
109
110
111
112
113
114
                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
115
            }
116
            field_i += 1;
qinsoon's avatar
qinsoon committed
117
118
            
            // backend_type_info
qinsoon's avatar
qinsoon committed
119
            trace!("...serializing backend_type_info");
qinsoon's avatar
qinsoon committed
120
121
            {
                let backend_type_info : &HashMap<_, _> = &self.backend_type_info.read().unwrap();
122
                try!(s.emit_struct_field("backend_type_info", field_i, |s| backend_type_info.encode(s)));
qinsoon's avatar
qinsoon committed
123
            }
124
            field_i += 1;
qinsoon's avatar
qinsoon committed
125
126
            
            // constants
qinsoon's avatar
qinsoon committed
127
            trace!("...serializing constants");
qinsoon's avatar
qinsoon committed
128
129
            {
                let constants : &HashMap<_, _> = &self.constants.read().unwrap();
130
                try!(s.emit_struct_field("constants", field_i, |s| constants.encode(s)));
qinsoon's avatar
qinsoon committed
131
            }
132
            field_i += 1;
qinsoon's avatar
qinsoon committed
133
134
            
            // globals
qinsoon's avatar
qinsoon committed
135
            trace!("...serializing globals");
qinsoon's avatar
qinsoon committed
136
137
            {
                let globals: &HashMap<_, _> = &self.globals.read().unwrap();
138
                try!(s.emit_struct_field("globals", field_i, |s| globals.encode(s)));
qinsoon's avatar
qinsoon committed
139
            }
140
            field_i += 1;
qinsoon's avatar
qinsoon committed
141
142
            
            // func sigs
qinsoon's avatar
qinsoon committed
143
            trace!("...serializing func_sigs");
qinsoon's avatar
qinsoon committed
144
145
            {
                let func_sigs: &HashMap<_, _> = &self.func_sigs.read().unwrap();
146
                try!(s.emit_struct_field("func_sigs", field_i, |s| func_sigs.encode(s)));
qinsoon's avatar
qinsoon committed
147
            }
148
            field_i += 1;
qinsoon's avatar
qinsoon committed
149
150
            
            // funcs
qinsoon's avatar
qinsoon committed
151
            trace!("...serializing funcs");
qinsoon's avatar
qinsoon committed
152
153
            {
                let funcs : &HashMap<_, _> = &self.funcs.read().unwrap();
154
                try!(s.emit_struct_field("funcs", field_i, |s| {
qinsoon's avatar
qinsoon committed
155
156
157
158
159
160
161
162
163
164
165
166
                    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(())
                    })
                }));
            }
167
            field_i += 1;
qinsoon's avatar
qinsoon committed
168
169
            
            // func_vers
qinsoon's avatar
qinsoon committed
170
            trace!("...serializing func_vers");
qinsoon's avatar
qinsoon committed
171
172
            {
                let func_vers : &HashMap<_, _> = &self.func_vers.read().unwrap();
173
                try!(s.emit_struct_field("func_vers", field_i, |s| {
qinsoon's avatar
qinsoon committed
174
175
176
177
178
179
180
181
182
183
184
185
                    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(())
                    })
                }));
            }
186
187
            field_i += 1;

qinsoon's avatar
qinsoon committed
188
            // primordial
qinsoon's avatar
qinsoon committed
189
            trace!("...serializing primordial");
qinsoon's avatar
qinsoon committed
190
191
            {
                let primordial = &self.primordial.read().unwrap();
192
                try!(s.emit_struct_field("primordial", field_i, |s| primordial.encode(s)));
qinsoon's avatar
qinsoon committed
193
            }
194
            field_i += 1;
qinsoon's avatar
qinsoon committed
195
196
            
            // is_running
qinsoon's avatar
qinsoon committed
197
            trace!("...serializing is_running");
qinsoon's avatar
qinsoon committed
198
            {
199
                try!(s.emit_struct_field("is_running", field_i, |s| self.is_running.load(Ordering::SeqCst).encode(s)));
200
            }
201
            field_i += 1;
qinsoon's avatar
qinsoon committed
202
203
204
205
206
207
208

            // options
            trace!("...serializing vm_options");
            {
                try!(s.emit_struct_field("vm_options", field_i, |s| self.vm_options.encode(s)));
            }
            field_i += 1;
209
            
qinsoon's avatar
qinsoon committed
210
            // compiled_funcs
qinsoon's avatar
qinsoon committed
211
            trace!("...serializing compiled_funcs");
qinsoon's avatar
qinsoon committed
212
213
            {
                let compiled_funcs : &HashMap<_, _> = &self.compiled_funcs.read().unwrap();
214
                try!(s.emit_struct_field("compiled_funcs", field_i, |s| {
qinsoon's avatar
qinsoon committed
215
216
217
218
219
220
221
222
223
224
225
226
                    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(())
                    })
                }));
            }
227
            field_i += 1;
qinsoon's avatar
qinsoon committed
228
            
qinsoon's avatar
qinsoon committed
229
            trace!("serializing finished");
230
231
232
            Ok(())
        })
    }
qinsoon's avatar
qinsoon committed
233
234
}

qinsoon's avatar
qinsoon committed
235
236
impl Decodable for VM {
    fn decode<D: Decoder>(d: &mut D) -> Result<VM, D::Error> {
237
238
239
        let mut field_i = 0;

        d.read_struct("VM", VM_SERIALIZE_FIELDS + 2, |d| {
qinsoon's avatar
qinsoon committed
240
            // next_id
241
            let next_id = try!(d.read_struct_field("next_id", field_i, |d| {
qinsoon's avatar
qinsoon committed
242
243
                d.read_usize()
            }));
244
            field_i += 1;
qinsoon's avatar
qinsoon committed
245
246
            
            // id_name_map
247
248
249
            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
250
            // name_id_map
251
252
            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
253
254
            
            // types
255
256
257
258
            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
259
            {
260
                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
261
262
263
264
265
266
                
                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);
                }
267
268
269
270
271
272
273
274
275
276
277
278
279
                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
280
            }
qinsoon's avatar
qinsoon committed
281
282
            
            // backend_type_info
283
284
            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
285
286
            
            // constants
287
288
            let constants = try!(d.read_struct_field("constants", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
289
290
            
            // globals
291
292
            let globals = try!(d.read_struct_field("globals", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
293
294
            
            // func sigs
295
296
            let func_sigs = try!(d.read_struct_field("func_sigs", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
297
298
            
            // funcs
299
            let funcs = try!(d.read_struct_field("funcs", field_i, |d| {
qinsoon's avatar
qinsoon committed
300
301
302
303
304
305
306
307
308
309
                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)
                })
            }));
310
            field_i += 1;
qinsoon's avatar
qinsoon committed
311
312
            
            // func_vers
313
            let func_vers = try!(d.read_struct_field("func_vers", field_i, |d| {
qinsoon's avatar
qinsoon committed
314
315
316
317
318
319
320
321
322
323
                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)
                })
            }));
324
            field_i += 1;
qinsoon's avatar
qinsoon committed
325
326
            
            // primordial
327
328
            let primordial = try!(d.read_struct_field("primordial", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
329
330

            // is_running
331
332
            let is_running = try!(d.read_struct_field("is_running", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
333
334
335
336

            // 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
337
            
qinsoon's avatar
qinsoon committed
338
            // compiled funcs
339
            let compiled_funcs = try!(d.read_struct_field("compiled_funcs", field_i, |d| {
qinsoon's avatar
qinsoon committed
340
341
342
343
344
345
346
347
348
349
                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)
                })
            }));
350
            field_i += 1;
qinsoon's avatar
qinsoon committed
351
            
qinsoon's avatar
qinsoon committed
352
353
354
355
356
357
358
359
360
361
362
363
364
            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),
                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
365
                vm_options: vm_options,
qinsoon's avatar
qinsoon committed
366
                compiled_funcs: RwLock::new(compiled_funcs),
qinsoon's avatar
qinsoon committed
367
368
369
370
371
372
373
374
375
376
            };
            
            vm.next_id.store(next_id, Ordering::SeqCst);
            vm.is_running.store(is_running, Ordering::SeqCst);
            
            Ok(vm)
        })
    }
}

qinsoon's avatar
qinsoon committed
377
378
impl <'a> VM {
    pub fn new() -> VM {
qinsoon's avatar
qinsoon committed
379
380
381
382
383
384
385
386
387
        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
388

qinsoon's avatar
qinsoon committed
389
        let ret = VM {
390
            next_id: ATOMIC_USIZE_INIT,
391
            is_running: ATOMIC_BOOL_INIT,
qinsoon's avatar
qinsoon committed
392
393
            vm_options: options,

qinsoon's avatar
qinsoon committed
394
395
            id_name_map: RwLock::new(HashMap::new()),
            name_id_map: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
396

qinsoon's avatar
qinsoon committed
397
            constants: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
398

qinsoon's avatar
qinsoon committed
399
            types: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
400
            backend_type_info: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
401

qinsoon's avatar
qinsoon committed
402
            globals: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
403

qinsoon's avatar
qinsoon committed
404
            func_sigs: RwLock::new(HashMap::new()),
405
            func_vers: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
406
            funcs: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
407
            compiled_funcs: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
408

409
            primordial: RwLock::new(None)
410
        };
qinsoon's avatar
qinsoon committed
411

qinsoon's avatar
qinsoon committed
412
413
414
415
416
417
        {
            let mut types = ret.types.write().unwrap();
            for ty in INTERNAL_TYPES.iter() {
                types.insert(ty.id(), ty.clone());
            }
        }
qinsoon's avatar
qinsoon committed
418

419
        ret.is_running.store(false, Ordering::SeqCst);
Kunshan Wang's avatar
Kunshan Wang committed
420
421
422
423
424
425
426
427
428
429

        // 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.
        ret.next_id.store(USER_ID_START, Ordering::Relaxed);
qinsoon's avatar
qinsoon committed
430
431
432

        ret.init_vm();

433
434
        ret
    }
qinsoon's avatar
qinsoon committed
435

qinsoon's avatar
qinsoon committed
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
    fn init_vm(&self) {
        // init log
        VM::start_logging(self.vm_options.flag_log_level);

        // init gc
        {
            let ref options = self.vm_options;
            gc::gc_init(options.flag_gc_immixspace_size, options.flag_gc_lospace_size, options.flag_gc_nthreads);
        }
    }

    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
456
457
458
    }

    pub fn start_logging_trace() {
qinsoon's avatar
qinsoon committed
459
460
461
462
        VM::start_logging_internal(LogLevel::Trace)
    }

    fn start_logging_internal(level: LogLevel) {
qinsoon's avatar
qinsoon committed
463
464
        use simple_logger;

qinsoon's avatar
qinsoon committed
465
        match simple_logger::init_with_level(level) {
qinsoon's avatar
qinsoon committed
466
467
468
469
            Ok(_) => {},
            Err(_) => {}
        }
    }
470
    
471
472
473
    pub fn resume_vm(serialized_vm: &str) -> VM {
        use rustc_serialize::json;
        
qinsoon's avatar
qinsoon committed
474
        let vm : VM = json::decode(serialized_vm).unwrap();
475
        
qinsoon's avatar
qinsoon committed
476
        vm.init_vm();
qinsoon's avatar
qinsoon committed
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507

        // 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;

                        mm::add_gc_type(GCType::new_noreftype(0));
                        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;
            }
        }
508
509
510
511
        
        vm
    }
    
512
    pub fn next_id(&self) -> MuID {
Kunshan Wang's avatar
Kunshan Wang committed
513
514
515
516
        // 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.
        self.next_id.fetch_add(1, Ordering::Relaxed)
517
518
    }
    
519
520
521
522
523
524
    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
525
526
    }
    
527
    pub fn set_name(&self, entity: &MuEntity, name: MuName) {
qinsoon's avatar
qinsoon committed
528
        let id = entity.id();
529
        entity.set_name(name.clone());
qinsoon's avatar
qinsoon committed
530
531
        
        let mut map = self.id_name_map.write().unwrap();
532
        map.insert(id, name.clone());
qinsoon's avatar
qinsoon committed
533
534
535
536
537
        
        let mut map2 = self.name_id_map.write().unwrap();
        map2.insert(name, id);
    }
    
Kunshan Wang's avatar
Kunshan Wang committed
538
    pub fn id_of_by_refstring(&self, name: &String) -> MuID {
qinsoon's avatar
qinsoon committed
539
        let map = self.name_id_map.read().unwrap();
Kunshan Wang's avatar
Kunshan Wang committed
540
541
542
543
544
        *map.get(name).unwrap()
    }
    
    pub fn id_of(&self, name: &str) -> MuID {
        self.id_of_by_refstring(&name.to_string())
qinsoon's avatar
qinsoon committed
545
546
547
548
    }
    
    pub fn name_of(&self, id: MuID) -> MuName {
        let map = self.id_name_map.read().unwrap();
549
        map.get(&id).unwrap().clone()
qinsoon's avatar
qinsoon committed
550
551
    }
    
qinsoon's avatar
qinsoon committed
552
    pub fn declare_const(&self, id: MuID, ty: P<MuType>, val: Constant) -> P<Value> {
qinsoon's avatar
qinsoon committed
553
        let mut constants = self.constants.write().unwrap();
qinsoon's avatar
qinsoon committed
554
        debug_assert!(!constants.contains_key(&id));
qinsoon's avatar
qinsoon committed
555
        
556
        let ret = P(Value{hdr: MuEntityHeader::unnamed(id), ty: ty, v: Value_::Constant(val)});
qinsoon's avatar
qinsoon committed
557
        constants.insert(id, ret.clone());
qinsoon's avatar
qinsoon committed
558
559
560
561
        
        ret
    }
    
562
563
564
565
566
567
568
569
    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)
        }
    }
    
qinsoon's avatar
qinsoon committed
570
571
    pub fn declare_global(&self, id: MuID, ty: P<MuType>) -> P<Value> {
        let global = P(Value{
572
573
574
            hdr: MuEntityHeader::unnamed(id),
            ty: P(MuType::new(self.next_id(), MuType_::iref(ty.clone()))),
            v: Value_::Global(ty)
qinsoon's avatar
qinsoon committed
575
        });
qinsoon's avatar
qinsoon committed
576
577
        
        let mut globals = self.globals.write().unwrap();
qinsoon's avatar
qinsoon committed
578
        globals.insert(id, global.clone());
qinsoon's avatar
qinsoon committed
579
        
qinsoon's avatar
qinsoon committed
580
        global
qinsoon's avatar
qinsoon committed
581
582
    }
    
qinsoon's avatar
qinsoon committed
583
    pub fn declare_type(&self, id: MuID, ty: MuType_) -> P<MuType> {
584
        let ty = P(MuType{hdr: MuEntityHeader::unnamed(id), v: ty});
qinsoon's avatar
qinsoon committed
585
        
qinsoon's avatar
qinsoon committed
586
        let mut types = self.types.write().unwrap();
qinsoon's avatar
qinsoon committed
587
        debug_assert!(!types.contains_key(&id));
qinsoon's avatar
qinsoon committed
588
        
qinsoon's avatar
qinsoon committed
589
        types.insert(ty.id(), ty.clone());
qinsoon's avatar
qinsoon committed
590
591
592
593
        
        ty
    }
    
594
595
596
597
598
599
600
601
    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)
        }
    }    
    
qinsoon's avatar
qinsoon committed
602
    pub fn declare_func_sig(&self, id: MuID, ret_tys: Vec<P<MuType>>, arg_tys: Vec<P<MuType>>) -> P<MuFuncSig> {
qinsoon's avatar
qinsoon committed
603
        let mut func_sigs = self.func_sigs.write().unwrap();
qinsoon's avatar
qinsoon committed
604
        debug_assert!(!func_sigs.contains_key(&id));
qinsoon's avatar
qinsoon committed
605
        
606
        let ret = P(MuFuncSig{hdr: MuEntityHeader::unnamed(id), ret_tys: ret_tys, arg_tys: arg_tys});
qinsoon's avatar
qinsoon committed
607
        func_sigs.insert(id, ret.clone());
qinsoon's avatar
qinsoon committed
608
609
610
611
        
        ret
    }
    
612
613
614
615
616
617
618
619
    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)
        }
    }
    
620
    pub fn declare_func (&self, func: MuFunction) {
qinsoon's avatar
qinsoon committed
621
        info!("declare function {}", func);
qinsoon's avatar
qinsoon committed
622
        let mut funcs = self.funcs.write().unwrap();
qinsoon's avatar
qinsoon committed
623
        funcs.insert(func.id(), RwLock::new(func));
624
625
    }
    
626
627
628
629
630
631
632
633
634
    /// 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)
        }
    }    
    
635
    pub fn define_func_version (&self, func_ver: MuFunctionVersion) {
qinsoon's avatar
qinsoon committed
636
        info!("define function version {}", func_ver);
637
        // record this version
qinsoon's avatar
qinsoon committed
638
        let func_ver_id = func_ver.id();
639
640
        {
            let mut func_vers = self.func_vers.write().unwrap();
qinsoon's avatar
qinsoon committed
641
            func_vers.insert(func_ver_id, RwLock::new(func_ver));
642
643
644
645
        }
        
        // acquire a reference to the func_ver
        let func_vers = self.func_vers.read().unwrap();
qinsoon's avatar
qinsoon committed
646
        let func_ver = func_vers.get(&func_ver_id).unwrap().write().unwrap();
647
648
649
        
        // change current version to this (obsolete old versions)
        let funcs = self.funcs.read().unwrap();
qinsoon's avatar
qinsoon committed
650
        debug_assert!(funcs.contains_key(&func_ver.func_id)); // it should be declared before defining
qinsoon's avatar
qinsoon committed
651
        let mut func = funcs.get(&func_ver.func_id).unwrap().write().unwrap();
652
        
653
654
655
656
        func.new_version(func_ver.id());
        
        // redefinition happens here
        // do stuff        
657
    }
658
659
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
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723

    /// 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>>,
                        new_func_vers: &mut HashMap<MuID, Box<MuFunctionVersion>>
                        ) {
        // Make sure other components, if ever acquiring multiple locks at the same time, acquire
        // them in this order, to prevent deadlock.
        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();

        for (id, name) in new_id_name_map.drain() {
            id_name_map.insert(id, name.clone());
            name_id_map.insert(name, id);
        }

        for (id, obj) in new_types.drain() {
            types.insert(id, obj);
        }

        for (id, obj) in new_constants.drain() {
            constants.insert(id, obj);
        }

        for (id, obj) in new_globals.drain() {
            globals.insert(id, obj);
        }

        for (id, obj) in new_func_sigs.drain() {
            func_sigs.insert(id, obj);
        }

        for (id, obj) in new_funcs.drain() {
            funcs.insert(id, RwLock::new(*obj));
        }

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

            {
                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);
            }
        }

        // Locks released here
    }
724
    
725
    pub fn add_compiled_func (&self, func: CompiledFunction) {
qinsoon's avatar
qinsoon committed
726
        debug_assert!(self.funcs.read().unwrap().contains_key(&func.func_id));
qinsoon's avatar
qinsoon committed
727
        debug_assert!(self.func_vers.read().unwrap().contains_key(&func.func_ver_id));
qinsoon's avatar
qinsoon committed
728

qinsoon's avatar
qinsoon committed
729
        self.compiled_funcs.write().unwrap().insert(func.func_ver_id, RwLock::new(func));
qinsoon's avatar
qinsoon committed
730
731
    }
    
qinsoon's avatar
qinsoon committed
732
    pub fn get_backend_type_info(&self, tyid: MuID) -> Box<BackendTypeInfo> {        
qinsoon's avatar
qinsoon committed
733
734
735
        {
            let read_lock = self.backend_type_info.read().unwrap();
        
736
            match read_lock.get(&tyid) {
qinsoon's avatar
qinsoon committed
737
738
739
740
                Some(info) => {return info.clone();},
                None => {}
            }
        }
741
742

        let types = self.types.read().unwrap();
qinsoon's avatar
qinsoon committed
743
744
745
746
        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
747
        let resolved = Box::new(backend::resolve_backend_type_info(ty, self));
qinsoon's avatar
qinsoon committed
748
749
        
        let mut write_lock = self.backend_type_info.write().unwrap();
750
        write_lock.insert(tyid, resolved.clone());
qinsoon's avatar
qinsoon committed
751
752
753
754
        
        resolved        
    }
    
qinsoon's avatar
qinsoon committed
755
756
757
758
    pub fn get_type_size(&self, tyid: MuID) -> ByteSize {
        self.get_backend_type_info(tyid).size
    }
    
qinsoon's avatar
qinsoon committed
759
    pub fn globals(&self) -> &RwLock<HashMap<MuID, P<Value>>> {
qinsoon's avatar
qinsoon committed
760
761
762
        &self.globals
    }
    
qinsoon's avatar
qinsoon committed
763
    pub fn funcs(&self) -> &RwLock<HashMap<MuID, RwLock<MuFunction>>> {
qinsoon's avatar
qinsoon committed
764
        &self.funcs
765
    }
766
    
qinsoon's avatar
qinsoon committed
767
    pub fn func_vers(&self) -> &RwLock<HashMap<MuID, RwLock<MuFunctionVersion>>> {
768
769
        &self.func_vers
    }
qinsoon's avatar
qinsoon committed
770
771
772
773
774
775
776
777
778
779
780

    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
        }
    }
781
    
qinsoon's avatar
qinsoon committed
782
    pub fn compiled_funcs(&self) -> &RwLock<HashMap<MuID, RwLock<CompiledFunction>>> {
783
784
        &self.compiled_funcs
    }
785
786
787
788
789
790
791
792
    
    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
793
    
794
795
796
797
798
799
800
    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 {
801
            ValueLocation::Relocatable(backend::RegGroup::GPR, func.name().unwrap())
802
803
804
        }
    }
    
qinsoon's avatar
qinsoon committed
805
    pub fn new_stack(&self, func_id: MuID) -> Box<MuStack> {
qinsoon's avatar
qinsoon committed
806
807
808
        let funcs = self.funcs.read().unwrap();
        let func : &MuFunction = &funcs.get(&func_id).unwrap().read().unwrap();
        
809
810
811
812
813
814
        Box::new(MuStack::new(self.next_id(), self.resolve_function_address(func_id), func))
    }
    
    pub fn make_primordial_thread(&self, func_id: MuID, args: Vec<Constant>) {
        let mut guard = self.primordial.write().unwrap();
        *guard = Some(MuPrimordialThread{func_id: func_id, args: args});
qinsoon's avatar
qinsoon committed
815
816
    }
    
qinsoon's avatar
qinsoon committed
817
818
819
820
821
822
823
824
    #[allow(unused_variables)]
    pub fn make_boot_image(self, output: &path::Path) {
        use rustc_serialize::json;
        
        let serialized = json::encode(&self).unwrap();
        
        unimplemented!() 
    }
Kunshan Wang's avatar
Kunshan Wang committed
825
}