WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

vm.rs 26.1 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;
qinsoon's avatar
qinsoon committed
10
use vm::vm_options::VMOptions;
11
12
use runtime::thread::*;
use runtime::ValueLocation;
qinsoon's avatar
qinsoon committed
13
use utils::ByteSize;
14
use runtime::mm as gc;
15
16
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};

qinsoon's avatar
qinsoon committed
17
use std::path;
qinsoon's avatar
qinsoon committed
18
use std::sync::RwLock;
19
use std::sync::atomic::{AtomicUsize, AtomicBool, ATOMIC_BOOL_INIT, ATOMIC_USIZE_INIT, Ordering};
20

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

qinsoon's avatar
qinsoon committed
58
const VM_SERIALIZE_FIELDS : usize = 13;
qinsoon's avatar
qinsoon committed
59

60
61
impl Encodable for VM {
    fn encode<S: Encoder> (&self, s: &mut S) -> Result<(), S::Error> {
62
63
        let mut field_i = 0;

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

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

qinsoon's avatar
qinsoon committed
184
            // primordial
qinsoon's avatar
qinsoon committed
185
            trace!("...serializing primordial");
qinsoon's avatar
qinsoon committed
186
187
            {
                let primordial = &self.primordial.read().unwrap();
188
                try!(s.emit_struct_field("primordial", field_i, |s| primordial.encode(s)));
qinsoon's avatar
qinsoon committed
189
            }
190
            field_i += 1;
qinsoon's avatar
qinsoon committed
191
192
            
            // is_running
qinsoon's avatar
qinsoon committed
193
            trace!("...serializing is_running");
qinsoon's avatar
qinsoon committed
194
            {
195
                try!(s.emit_struct_field("is_running", field_i, |s| self.is_running.load(Ordering::SeqCst).encode(s)));
196
            }
197
            field_i += 1;
198
            
qinsoon's avatar
qinsoon committed
199
            // compiled_funcs
qinsoon's avatar
qinsoon committed
200
            trace!("...serializing compiled_funcs");
qinsoon's avatar
qinsoon committed
201
202
            {
                let compiled_funcs : &HashMap<_, _> = &self.compiled_funcs.read().unwrap();
203
                try!(s.emit_struct_field("compiled_funcs", field_i, |s| {
qinsoon's avatar
qinsoon committed
204
205
206
207
208
209
210
211
212
213
214
215
                    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(())
                    })
                }));
            }
216
            field_i += 1;
qinsoon's avatar
qinsoon committed
217
            
qinsoon's avatar
qinsoon committed
218
            trace!("serializing finished");
219
220
221
            Ok(())
        })
    }
qinsoon's avatar
qinsoon committed
222
223
}

qinsoon's avatar
qinsoon committed
224
225
impl Decodable for VM {
    fn decode<D: Decoder>(d: &mut D) -> Result<VM, D::Error> {
226
227
228
        let mut field_i = 0;

        d.read_struct("VM", VM_SERIALIZE_FIELDS + 2, |d| {
qinsoon's avatar
qinsoon committed
229
            // next_id
230
            let next_id = try!(d.read_struct_field("next_id", field_i, |d| {
qinsoon's avatar
qinsoon committed
231
232
                d.read_usize()
            }));
233
            field_i += 1;
qinsoon's avatar
qinsoon committed
234
235
            
            // id_name_map
236
237
238
            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
239
            // name_id_map
240
241
            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
242
243
            
            // types
244
245
246
247
            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
248
            {
249
                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
250
251
252
253
254
255
                
                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);
                }
256
257
258
259
260
261
262
263
264
265
266
267
268
                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
269
            }
qinsoon's avatar
qinsoon committed
270
271
            
            // backend_type_info
272
273
            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
274
275
            
            // constants
276
277
            let constants = try!(d.read_struct_field("constants", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
278
279
            
            // globals
280
281
            let globals = try!(d.read_struct_field("globals", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
282
283
            
            // func sigs
284
285
            let func_sigs = try!(d.read_struct_field("func_sigs", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
286
287
            
            // funcs
288
            let funcs = try!(d.read_struct_field("funcs", field_i, |d| {
qinsoon's avatar
qinsoon committed
289
290
291
292
293
294
295
296
297
298
                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)
                })
            }));
299
            field_i += 1;
qinsoon's avatar
qinsoon committed
300
301
            
            // func_vers
302
            let func_vers = try!(d.read_struct_field("func_vers", field_i, |d| {
qinsoon's avatar
qinsoon committed
303
304
305
306
307
308
309
310
311
312
                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)
                })
            }));
313
            field_i += 1;
qinsoon's avatar
qinsoon committed
314
315
            
            // primordial
316
317
            let primordial = try!(d.read_struct_field("primordial", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
318
            
319
320
            let is_running = try!(d.read_struct_field("is_running", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
321
            
qinsoon's avatar
qinsoon committed
322
            // compiled funcs
323
            let compiled_funcs = try!(d.read_struct_field("compiled_funcs", field_i, |d| {
qinsoon's avatar
qinsoon committed
324
325
326
327
328
329
330
331
332
333
                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)
                })
            }));
334
            field_i += 1;
qinsoon's avatar
qinsoon committed
335
            
qinsoon's avatar
qinsoon committed
336
337
338
339
340
341
342
343
344
345
346
347
348
            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
349
                compiled_funcs: RwLock::new(compiled_funcs),
qinsoon's avatar
qinsoon committed
350
351
352
353
354
355
356
357
358
359
            };
            
            vm.next_id.store(next_id, Ordering::SeqCst);
            vm.is_running.store(is_running, Ordering::SeqCst);
            
            Ok(vm)
        })
    }
}

qinsoon's avatar
qinsoon committed
360
361
impl <'a> VM {
    pub fn new() -> VM {
qinsoon's avatar
qinsoon committed
362
363
        VM::start_logging();

qinsoon's avatar
qinsoon committed
364
        let ret = VM {
365
            next_id: ATOMIC_USIZE_INIT,
366
367
            is_running: ATOMIC_BOOL_INIT,
            
qinsoon's avatar
qinsoon committed
368
369
370
            id_name_map: RwLock::new(HashMap::new()),
            name_id_map: RwLock::new(HashMap::new()),
            
qinsoon's avatar
qinsoon committed
371
            constants: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
372
            
qinsoon's avatar
qinsoon committed
373
            types: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
374
            backend_type_info: RwLock::new(HashMap::new()),
375
            
qinsoon's avatar
qinsoon committed
376
377
378
            globals: RwLock::new(HashMap::new()),
            
            func_sigs: RwLock::new(HashMap::new()),
379
            func_vers: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
380
            funcs: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
381
382
            compiled_funcs: RwLock::new(HashMap::new()),
            
383
            primordial: RwLock::new(None)
384
385
        };
        
qinsoon's avatar
qinsoon committed
386
387
388
389
390
391
392
        {
            let mut types = ret.types.write().unwrap();
            for ty in INTERNAL_TYPES.iter() {
                types.insert(ty.id(), ty.clone());
            }
        }
        
393
        ret.is_running.store(false, Ordering::SeqCst);
Kunshan Wang's avatar
Kunshan Wang committed
394
395
396
397
398
399
400
401
402
403

        // 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);
404
        
qinsoon's avatar
qinsoon committed
405
406
407
        let options = VMOptions::default();
        gc::gc_init(options.immix_size, options.lo_size, options.n_gcthreads);
        
408
409
        ret
    }
qinsoon's avatar
qinsoon committed
410
411
412
413
414
415
416
417
418
419
420
421
422

    pub fn start_logging() {
        VM::start_logging_trace();
    }

    pub fn start_logging_trace() {
        use simple_logger;

        match simple_logger::init() {
            Ok(_) => {},
            Err(_) => {}
        }
    }
423
    
424
425
426
427
428
429
430
431
432
433
434
    pub fn resume_vm(serialized_vm: &str) -> VM {
        use rustc_serialize::json;
        
        let vm = json::decode(serialized_vm).unwrap();
        
        let options = VMOptions::default();
        gc::gc_init(options.immix_size, options.lo_size, options.n_gcthreads);
        
        vm
    }
    
435
    pub fn next_id(&self) -> MuID {
Kunshan Wang's avatar
Kunshan Wang committed
436
437
438
439
        // 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)
440
441
    }
    
442
443
444
445
446
447
    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
448
449
    }
    
450
    pub fn set_name(&self, entity: &MuEntity, name: MuName) {
qinsoon's avatar
qinsoon committed
451
        let id = entity.id();
452
        entity.set_name(name.clone());
qinsoon's avatar
qinsoon committed
453
454
        
        let mut map = self.id_name_map.write().unwrap();
455
        map.insert(id, name.clone());
qinsoon's avatar
qinsoon committed
456
457
458
459
460
        
        let mut map2 = self.name_id_map.write().unwrap();
        map2.insert(name, id);
    }
    
Kunshan Wang's avatar
Kunshan Wang committed
461
    pub fn id_of_by_refstring(&self, name: &String) -> MuID {
qinsoon's avatar
qinsoon committed
462
        let map = self.name_id_map.read().unwrap();
Kunshan Wang's avatar
Kunshan Wang committed
463
464
465
466
467
        *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
468
469
470
471
    }
    
    pub fn name_of(&self, id: MuID) -> MuName {
        let map = self.id_name_map.read().unwrap();
472
        map.get(&id).unwrap().clone()
qinsoon's avatar
qinsoon committed
473
474
    }
    
qinsoon's avatar
qinsoon committed
475
    pub fn declare_const(&self, id: MuID, ty: P<MuType>, val: Constant) -> P<Value> {
qinsoon's avatar
qinsoon committed
476
        let mut constants = self.constants.write().unwrap();
qinsoon's avatar
qinsoon committed
477
        debug_assert!(!constants.contains_key(&id));
qinsoon's avatar
qinsoon committed
478
        
479
        let ret = P(Value{hdr: MuEntityHeader::unnamed(id), ty: ty, v: Value_::Constant(val)});
qinsoon's avatar
qinsoon committed
480
        constants.insert(id, ret.clone());
qinsoon's avatar
qinsoon committed
481
482
483
484
        
        ret
    }
    
485
486
487
488
489
490
491
492
    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
493
494
    pub fn declare_global(&self, id: MuID, ty: P<MuType>) -> P<Value> {
        let global = P(Value{
495
496
497
            hdr: MuEntityHeader::unnamed(id),
            ty: P(MuType::new(self.next_id(), MuType_::iref(ty.clone()))),
            v: Value_::Global(ty)
qinsoon's avatar
qinsoon committed
498
        });
qinsoon's avatar
qinsoon committed
499
500
        
        let mut globals = self.globals.write().unwrap();
qinsoon's avatar
qinsoon committed
501
        globals.insert(id, global.clone());
qinsoon's avatar
qinsoon committed
502
        
qinsoon's avatar
qinsoon committed
503
        global
qinsoon's avatar
qinsoon committed
504
505
    }
    
qinsoon's avatar
qinsoon committed
506
    pub fn declare_type(&self, id: MuID, ty: MuType_) -> P<MuType> {
507
        let ty = P(MuType{hdr: MuEntityHeader::unnamed(id), v: ty});
qinsoon's avatar
qinsoon committed
508
        
qinsoon's avatar
qinsoon committed
509
        let mut types = self.types.write().unwrap();
qinsoon's avatar
qinsoon committed
510
        debug_assert!(!types.contains_key(&id));
qinsoon's avatar
qinsoon committed
511
        
qinsoon's avatar
qinsoon committed
512
        types.insert(ty.id(), ty.clone());
qinsoon's avatar
qinsoon committed
513
514
515
516
        
        ty
    }
    
517
518
519
520
521
522
523
524
    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
525
    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
526
        let mut func_sigs = self.func_sigs.write().unwrap();
qinsoon's avatar
qinsoon committed
527
        debug_assert!(!func_sigs.contains_key(&id));
qinsoon's avatar
qinsoon committed
528
        
529
        let ret = P(MuFuncSig{hdr: MuEntityHeader::unnamed(id), ret_tys: ret_tys, arg_tys: arg_tys});
qinsoon's avatar
qinsoon committed
530
        func_sigs.insert(id, ret.clone());
qinsoon's avatar
qinsoon committed
531
532
533
534
        
        ret
    }
    
535
536
537
538
539
540
541
542
    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)
        }
    }
    
543
    pub fn declare_func (&self, func: MuFunction) {
qinsoon's avatar
qinsoon committed
544
        info!("declare function {}", func);
qinsoon's avatar
qinsoon committed
545
        let mut funcs = self.funcs.write().unwrap();
qinsoon's avatar
qinsoon committed
546
        funcs.insert(func.id(), RwLock::new(func));
547
548
    }
    
549
550
551
552
553
554
555
556
557
    /// 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)
        }
    }    
    
558
    pub fn define_func_version (&self, func_ver: MuFunctionVersion) {
qinsoon's avatar
qinsoon committed
559
        info!("define function version {}", func_ver);
560
        // record this version
qinsoon's avatar
qinsoon committed
561
        let func_ver_id = func_ver.id();
562
563
        {
            let mut func_vers = self.func_vers.write().unwrap();
qinsoon's avatar
qinsoon committed
564
            func_vers.insert(func_ver_id, RwLock::new(func_ver));
565
566
567
568
        }
        
        // acquire a reference to the func_ver
        let func_vers = self.func_vers.read().unwrap();
qinsoon's avatar
qinsoon committed
569
        let func_ver = func_vers.get(&func_ver_id).unwrap().write().unwrap();
570
571
572
        
        // change current version to this (obsolete old versions)
        let funcs = self.funcs.read().unwrap();
qinsoon's avatar
qinsoon committed
573
        debug_assert!(funcs.contains_key(&func_ver.func_id)); // it should be declared before defining
qinsoon's avatar
qinsoon committed
574
        let mut func = funcs.get(&func_ver.func_id).unwrap().write().unwrap();
575
        
576
577
578
579
        func.new_version(func_ver.id());
        
        // redefinition happens here
        // do stuff        
580
    }
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646

    /// 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
    }
647
    
648
    pub fn add_compiled_func (&self, func: CompiledFunction) {
qinsoon's avatar
qinsoon committed
649
        debug_assert!(self.funcs.read().unwrap().contains_key(&func.func_id));
qinsoon's avatar
qinsoon committed
650
        debug_assert!(self.func_vers.read().unwrap().contains_key(&func.func_ver_id));
qinsoon's avatar
qinsoon committed
651

qinsoon's avatar
qinsoon committed
652
        self.compiled_funcs.write().unwrap().insert(func.func_ver_id, RwLock::new(func));
qinsoon's avatar
qinsoon committed
653
654
    }
    
qinsoon's avatar
qinsoon committed
655
    pub fn get_backend_type_info(&self, tyid: MuID) -> Box<BackendTypeInfo> {        
qinsoon's avatar
qinsoon committed
656
657
658
        {
            let read_lock = self.backend_type_info.read().unwrap();
        
659
            match read_lock.get(&tyid) {
qinsoon's avatar
qinsoon committed
660
661
662
663
                Some(info) => {return info.clone();},
                None => {}
            }
        }
664
665

        let types = self.types.read().unwrap();
qinsoon's avatar
qinsoon committed
666
667
668
669
        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
670
        let resolved = Box::new(backend::resolve_backend_type_info(ty, self));
qinsoon's avatar
qinsoon committed
671
672
        
        let mut write_lock = self.backend_type_info.write().unwrap();
673
        write_lock.insert(tyid, resolved.clone());
qinsoon's avatar
qinsoon committed
674
675
676
677
        
        resolved        
    }
    
qinsoon's avatar
qinsoon committed
678
679
680
681
    pub fn get_type_size(&self, tyid: MuID) -> ByteSize {
        self.get_backend_type_info(tyid).size
    }
    
qinsoon's avatar
qinsoon committed
682
    pub fn globals(&self) -> &RwLock<HashMap<MuID, P<Value>>> {
qinsoon's avatar
qinsoon committed
683
684
685
        &self.globals
    }
    
qinsoon's avatar
qinsoon committed
686
    pub fn funcs(&self) -> &RwLock<HashMap<MuID, RwLock<MuFunction>>> {
qinsoon's avatar
qinsoon committed
687
        &self.funcs
688
    }
689
    
qinsoon's avatar
qinsoon committed
690
    pub fn func_vers(&self) -> &RwLock<HashMap<MuID, RwLock<MuFunctionVersion>>> {
691
692
693
        &self.func_vers
    }
    
qinsoon's avatar
qinsoon committed
694
    pub fn compiled_funcs(&self) -> &RwLock<HashMap<MuID, RwLock<CompiledFunction>>> {
695
696
        &self.compiled_funcs
    }
697
698
699
700
701
702
703
704
    
    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
705
    
706
707
708
709
710
711
712
    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 {
713
            ValueLocation::Relocatable(backend::RegGroup::GPR, func.name().unwrap())
714
715
716
        }
    }
    
qinsoon's avatar
qinsoon committed
717
    pub fn new_stack(&self, func_id: MuID) -> Box<MuStack> {
qinsoon's avatar
qinsoon committed
718
719
720
        let funcs = self.funcs.read().unwrap();
        let func : &MuFunction = &funcs.get(&func_id).unwrap().read().unwrap();
        
721
722
723
724
725
726
        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
727
728
    }
    
qinsoon's avatar
qinsoon committed
729
730
731
732
733
734
735
736
    #[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
737
}