vm.rs 24.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;
qinsoon's avatar
qinsoon committed
15

16 17
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};

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

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

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

61 62
impl Encodable for VM {
    fn encode<S: Encoder> (&self, s: &mut S) -> Result<(), S::Error> {
qinsoon's avatar
qinsoon committed
63 64
        // serialize VM_SERIALIZE_FIELDS fields
        // PLUS ONE extra global STRUCT_TAG_MAP
65
        s.emit_struct("VM", VM_SERIALIZE_FIELDS + 1, |s| {
66
            // next_id
qinsoon's avatar
qinsoon committed
67
            trace!("...serializing next_id");
68 69 70 71 72
            try!(s.emit_struct_field("next_id", 0, |s| {
                s.emit_usize(self.next_id.load(Ordering::SeqCst))
            }));
                
            // id_name_map
qinsoon's avatar
qinsoon committed
73
            trace!("...serializing id_name_map");
74 75 76 77 78 79
            {
                let map : &HashMap<MuID, MuName> = &self.id_name_map.read().unwrap();            
                try!(s.emit_struct_field("id_name_map", 1, |s| map.encode(s)));
            }
            
            // name_id_map
qinsoon's avatar
qinsoon committed
80
            trace!("...serializing name_id_map");
81 82 83 84 85 86
            {
                let map : &HashMap<MuName, MuID> = &self.name_id_map.read().unwrap(); 
                try!(s.emit_struct_field("name_id_map", 2, |s| map.encode(s)));
            }
            
            // types
qinsoon's avatar
qinsoon committed
87
            trace!("...serializing types");
88 89
            {
                let types = &self.types.read().unwrap();
qinsoon's avatar
qinsoon committed
90 91
                try!(s.emit_struct_field("types", 3, |s| types.encode(s)));
            }
qinsoon's avatar
qinsoon committed
92
            // STRUCT_TAG_MAP
qinsoon's avatar
qinsoon committed
93
            trace!("...serializing struct_tag_map");
qinsoon's avatar
qinsoon committed
94 95 96 97
            {
                let struct_tag_map = types::STRUCT_TAG_MAP.read().unwrap();
                try!(s.emit_struct_field("struct_tag_map", 4, |s| struct_tag_map.encode(s)));
            }
qinsoon's avatar
qinsoon committed
98 99
            
            // backend_type_info
qinsoon's avatar
qinsoon committed
100
            trace!("...serializing backend_type_info");
qinsoon's avatar
qinsoon committed
101 102
            {
                let backend_type_info : &HashMap<_, _> = &self.backend_type_info.read().unwrap();
qinsoon's avatar
qinsoon committed
103
                try!(s.emit_struct_field("backend_type_info", 5, |s| backend_type_info.encode(s)));
qinsoon's avatar
qinsoon committed
104 105 106
            }
            
            // constants
qinsoon's avatar
qinsoon committed
107
            trace!("...serializing constants");
qinsoon's avatar
qinsoon committed
108 109
            {
                let constants : &HashMap<_, _> = &self.constants.read().unwrap();
qinsoon's avatar
qinsoon committed
110
                try!(s.emit_struct_field("constants", 6, |s| constants.encode(s)));
qinsoon's avatar
qinsoon committed
111 112 113
            }
            
            // globals
qinsoon's avatar
qinsoon committed
114
            trace!("...serializing globals");
qinsoon's avatar
qinsoon committed
115 116
            {
                let globals: &HashMap<_, _> = &self.globals.read().unwrap();
qinsoon's avatar
qinsoon committed
117
                try!(s.emit_struct_field("globals", 7, |s| globals.encode(s)));
qinsoon's avatar
qinsoon committed
118 119 120
            }
            
            // func sigs
qinsoon's avatar
qinsoon committed
121
            trace!("...serializing func_sigs");
qinsoon's avatar
qinsoon committed
122 123
            {
                let func_sigs: &HashMap<_, _> = &self.func_sigs.read().unwrap();
qinsoon's avatar
qinsoon committed
124
                try!(s.emit_struct_field("func_sigs", 8, |s| func_sigs.encode(s)));
qinsoon's avatar
qinsoon committed
125 126 127
            }
            
            // funcs
qinsoon's avatar
qinsoon committed
128
            trace!("...serializing funcs");
qinsoon's avatar
qinsoon committed
129 130
            {
                let funcs : &HashMap<_, _> = &self.funcs.read().unwrap();
qinsoon's avatar
qinsoon committed
131
                try!(s.emit_struct_field("funcs", 9, |s| {
qinsoon's avatar
qinsoon committed
132 133 134 135 136 137 138 139 140 141 142 143 144 145
                    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(())
                    })
                }));
            }
            
            // func_vers
qinsoon's avatar
qinsoon committed
146
            trace!("...serializing func_vers");
qinsoon's avatar
qinsoon committed
147 148
            {
                let func_vers : &HashMap<_, _> = &self.func_vers.read().unwrap();
qinsoon's avatar
qinsoon committed
149
                try!(s.emit_struct_field("func_vers", 10, |s| {
qinsoon's avatar
qinsoon committed
150 151 152 153 154 155 156 157 158 159 160 161 162 163
                    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(())
                    })
                }));
            }
            
            // primordial
qinsoon's avatar
qinsoon committed
164
            trace!("...serializing primordial");
qinsoon's avatar
qinsoon committed
165 166
            {
                let primordial = &self.primordial.read().unwrap();
qinsoon's avatar
qinsoon committed
167
                try!(s.emit_struct_field("primordial", 11, |s| primordial.encode(s)));
qinsoon's avatar
qinsoon committed
168 169 170
            }
            
            // is_running
qinsoon's avatar
qinsoon committed
171
            trace!("...serializing is_running");
qinsoon's avatar
qinsoon committed
172
            {
qinsoon's avatar
qinsoon committed
173
                try!(s.emit_struct_field("is_running", 12, |s| self.is_running.load(Ordering::SeqCst).encode(s)));
174 175
            }
            
qinsoon's avatar
qinsoon committed
176
            // compiled_funcs
qinsoon's avatar
qinsoon committed
177
            trace!("...serializing compiled_funcs");
qinsoon's avatar
qinsoon committed
178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193
            {
                let compiled_funcs : &HashMap<_, _> = &self.compiled_funcs.read().unwrap();
                try!(s.emit_struct_field("compiled_funcs", 13, |s| {
                    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(())
                    })
                }));
            }
            
qinsoon's avatar
qinsoon committed
194
            trace!("serializing finished");
195 196 197
            Ok(())
        })
    }
qinsoon's avatar
qinsoon committed
198 199
}

qinsoon's avatar
qinsoon committed
200 201
impl Decodable for VM {
    fn decode<D: Decoder>(d: &mut D) -> Result<VM, D::Error> {
qinsoon's avatar
qinsoon committed
202
        d.read_struct("VM", VM_SERIALIZE_FIELDS + 1, |d| {
qinsoon's avatar
qinsoon committed
203 204 205 206 207 208 209 210 211 212 213 214 215
            // next_id
            let next_id = try!(d.read_struct_field("next_id", 0, |d| {
                d.read_usize()
            }));
            
            // id_name_map
            let id_name_map = try!(d.read_struct_field("id_name_map", 1, |d| Decodable::decode(d)));
            
            // name_id_map
            let name_id_map = try!(d.read_struct_field("name_id_map", 2, |d| Decodable::decode(d)));
            
            // types
            let types = try!(d.read_struct_field("types", 3, |d| Decodable::decode(d)));
qinsoon's avatar
qinsoon committed
216 217 218 219 220 221 222 223 224 225
            {
                // struct tag map
                let mut struct_tag_map : HashMap<MuName, StructType_> = try!(d.read_struct_field("struct_tag_map", 4, |d| Decodable::decode(d)));
                
                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);
                }
            }
qinsoon's avatar
qinsoon committed
226 227
            
            // backend_type_info
qinsoon's avatar
qinsoon committed
228
            let backend_type_info = try!(d.read_struct_field("backend_type_info", 5, |d| Decodable::decode(d)));
qinsoon's avatar
qinsoon committed
229 230
            
            // constants
qinsoon's avatar
qinsoon committed
231
            let constants = try!(d.read_struct_field("constants", 6, |d| Decodable::decode(d)));
qinsoon's avatar
qinsoon committed
232 233
            
            // globals
qinsoon's avatar
qinsoon committed
234
            let globals = try!(d.read_struct_field("globals", 7, |d| Decodable::decode(d)));
qinsoon's avatar
qinsoon committed
235 236
            
            // func sigs
qinsoon's avatar
qinsoon committed
237
            let func_sigs = try!(d.read_struct_field("func_sigs", 8, |d| Decodable::decode(d)));
qinsoon's avatar
qinsoon committed
238 239
            
            // funcs
qinsoon's avatar
qinsoon committed
240
            let funcs = try!(d.read_struct_field("funcs", 9, |d| {
qinsoon's avatar
qinsoon committed
241 242 243 244 245 246 247 248 249 250 251 252
                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)
                })
            }));
            
            // func_vers
qinsoon's avatar
qinsoon committed
253
            let func_vers = try!(d.read_struct_field("func_vers", 10, |d| {
qinsoon's avatar
qinsoon committed
254 255 256 257 258 259 260 261 262 263 264 265
                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)
                })
            }));
            
            // primordial
qinsoon's avatar
qinsoon committed
266
            let primordial = try!(d.read_struct_field("primordial", 11, |d| Decodable::decode(d)));
qinsoon's avatar
qinsoon committed
267
            
qinsoon's avatar
qinsoon committed
268
            let is_running = try!(d.read_struct_field("is_running", 12, |d| Decodable::decode(d)));
qinsoon's avatar
qinsoon committed
269
            
qinsoon's avatar
qinsoon committed
270 271 272 273 274 275 276 277 278 279 280 281 282
            // compiled funcs
            let compiled_funcs = try!(d.read_struct_field("compiled_funcs", 13, |d| {
                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)
                })
            }));
            
qinsoon's avatar
qinsoon committed
283 284 285 286 287 288 289 290 291 292 293 294 295
            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
296
                compiled_funcs: RwLock::new(compiled_funcs),
qinsoon's avatar
qinsoon committed
297 298 299 300 301 302 303 304 305 306
            };
            
            vm.next_id.store(next_id, Ordering::SeqCst);
            vm.is_running.store(is_running, Ordering::SeqCst);
            
            Ok(vm)
        })
    }
}

qinsoon's avatar
qinsoon committed
307 308 309
impl <'a> VM {
    pub fn new() -> VM {
        let ret = VM {
310
            next_id: ATOMIC_USIZE_INIT,
311 312
            is_running: ATOMIC_BOOL_INIT,
            
qinsoon's avatar
qinsoon committed
313 314 315
            id_name_map: RwLock::new(HashMap::new()),
            name_id_map: RwLock::new(HashMap::new()),
            
qinsoon's avatar
qinsoon committed
316
            constants: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
317
            
qinsoon's avatar
qinsoon committed
318
            types: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
319
            backend_type_info: RwLock::new(HashMap::new()),
320
            
qinsoon's avatar
qinsoon committed
321 322 323
            globals: RwLock::new(HashMap::new()),
            
            func_sigs: RwLock::new(HashMap::new()),
324
            func_vers: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
325
            funcs: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
326 327
            compiled_funcs: RwLock::new(HashMap::new()),
            
328
            primordial: RwLock::new(None)
329 330
        };
        
qinsoon's avatar
qinsoon committed
331 332 333 334 335 336 337
        {
            let mut types = ret.types.write().unwrap();
            for ty in INTERNAL_TYPES.iter() {
                types.insert(ty.id(), ty.clone());
            }
        }
        
338
        ret.is_running.store(false, Ordering::SeqCst);
339 340 341 342 343 344 345 346 347 348

        // 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);
349
        
qinsoon's avatar
qinsoon committed
350 351 352
        let options = VMOptions::default();
        gc::gc_init(options.immix_size, options.lo_size, options.n_gcthreads);
        
353 354 355
        ret
    }
    
356 357 358 359 360 361 362 363 364 365 366
    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
    }
    
367
    pub fn next_id(&self) -> MuID {
368 369 370 371
        // 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)
372 373
    }
    
374 375 376 377 378 379
    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
380 381
    }
    
382
    pub fn set_name(&self, entity: &MuEntity, name: MuName) {
qinsoon's avatar
qinsoon committed
383
        let id = entity.id();
384
        entity.set_name(name.clone());
qinsoon's avatar
qinsoon committed
385 386
        
        let mut map = self.id_name_map.write().unwrap();
387
        map.insert(id, name.clone());
qinsoon's avatar
qinsoon committed
388 389 390 391 392
        
        let mut map2 = self.name_id_map.write().unwrap();
        map2.insert(name, id);
    }
    
393
    pub fn id_of_by_refstring(&self, name: &String) -> MuID {
qinsoon's avatar
qinsoon committed
394
        let map = self.name_id_map.read().unwrap();
395 396 397 398 399
        *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
400 401 402 403
    }
    
    pub fn name_of(&self, id: MuID) -> MuName {
        let map = self.id_name_map.read().unwrap();
404
        map.get(&id).unwrap().clone()
qinsoon's avatar
qinsoon committed
405 406
    }
    
qinsoon's avatar
qinsoon committed
407
    pub fn declare_const(&self, id: MuID, ty: P<MuType>, val: Constant) -> P<Value> {
qinsoon's avatar
qinsoon committed
408
        let mut constants = self.constants.write().unwrap();
qinsoon's avatar
qinsoon committed
409
        debug_assert!(!constants.contains_key(&id));
qinsoon's avatar
qinsoon committed
410
        
411
        let ret = P(Value{hdr: MuEntityHeader::unnamed(id), ty: ty, v: Value_::Constant(val)});
qinsoon's avatar
qinsoon committed
412
        constants.insert(id, ret.clone());
qinsoon's avatar
qinsoon committed
413 414 415 416
        
        ret
    }
    
417 418 419 420 421 422 423 424
    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
425 426
    pub fn declare_global(&self, id: MuID, ty: P<MuType>) -> P<Value> {
        let global = P(Value{
427 428 429
            hdr: MuEntityHeader::unnamed(id),
            ty: P(MuType::new(self.next_id(), MuType_::iref(ty.clone()))),
            v: Value_::Global(ty)
qinsoon's avatar
qinsoon committed
430
        });
qinsoon's avatar
qinsoon committed
431 432
        
        let mut globals = self.globals.write().unwrap();
qinsoon's avatar
qinsoon committed
433
        globals.insert(id, global.clone());
qinsoon's avatar
qinsoon committed
434
        
qinsoon's avatar
qinsoon committed
435
        global
qinsoon's avatar
qinsoon committed
436 437
    }
    
qinsoon's avatar
qinsoon committed
438
    pub fn declare_type(&self, id: MuID, ty: MuType_) -> P<MuType> {
439
        let ty = P(MuType{hdr: MuEntityHeader::unnamed(id), v: ty});
qinsoon's avatar
qinsoon committed
440
        
qinsoon's avatar
qinsoon committed
441
        let mut types = self.types.write().unwrap();
qinsoon's avatar
qinsoon committed
442
        debug_assert!(!types.contains_key(&id));
qinsoon's avatar
qinsoon committed
443
        
qinsoon's avatar
qinsoon committed
444
        types.insert(ty.id(), ty.clone());
qinsoon's avatar
qinsoon committed
445 446 447 448
        
        ty
    }
    
449 450 451 452 453 454 455 456
    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
457
    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
458
        let mut func_sigs = self.func_sigs.write().unwrap();
qinsoon's avatar
qinsoon committed
459
        debug_assert!(!func_sigs.contains_key(&id));
qinsoon's avatar
qinsoon committed
460
        
461
        let ret = P(MuFuncSig{hdr: MuEntityHeader::unnamed(id), ret_tys: ret_tys, arg_tys: arg_tys});
qinsoon's avatar
qinsoon committed
462
        func_sigs.insert(id, ret.clone());
qinsoon's avatar
qinsoon committed
463 464 465 466
        
        ret
    }
    
467 468 469 470 471 472 473 474
    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)
        }
    }
    
475
    pub fn declare_func (&self, func: MuFunction) {
qinsoon's avatar
qinsoon committed
476
        info!("declare function {}", func);
qinsoon's avatar
qinsoon committed
477
        let mut funcs = self.funcs.write().unwrap();
qinsoon's avatar
qinsoon committed
478
        funcs.insert(func.id(), RwLock::new(func));
479 480
    }
    
481 482 483 484 485 486 487 488 489
    /// 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)
        }
    }    
    
490
    pub fn define_func_version (&self, func_ver: MuFunctionVersion) {
qinsoon's avatar
qinsoon committed
491
        info!("define function version {}", func_ver);
492
        // record this version
qinsoon's avatar
qinsoon committed
493
        let func_ver_id = func_ver.id();
494 495
        {
            let mut func_vers = self.func_vers.write().unwrap();
qinsoon's avatar
qinsoon committed
496
            func_vers.insert(func_ver_id, RwLock::new(func_ver));
497 498 499 500
        }
        
        // acquire a reference to the func_ver
        let func_vers = self.func_vers.read().unwrap();
qinsoon's avatar
qinsoon committed
501
        let func_ver = func_vers.get(&func_ver_id).unwrap().write().unwrap();
502 503 504
        
        // change current version to this (obsolete old versions)
        let funcs = self.funcs.read().unwrap();
qinsoon's avatar
qinsoon committed
505
        debug_assert!(funcs.contains_key(&func_ver.func_id)); // it should be declared before defining
qinsoon's avatar
qinsoon committed
506
        let mut func = funcs.get(&func_ver.func_id).unwrap().write().unwrap();
507
        
508 509 510 511
        func.new_version(func_ver.id());
        
        // redefinition happens here
        // do stuff        
512
    }
513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578

    /// 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
    }
579
    
580
    pub fn add_compiled_func (&self, func: CompiledFunction) {
qinsoon's avatar
qinsoon committed
581
        debug_assert!(self.funcs.read().unwrap().contains_key(&func.func_id));
qinsoon's avatar
qinsoon committed
582
        debug_assert!(self.func_vers.read().unwrap().contains_key(&func.func_ver_id));
qinsoon's avatar
qinsoon committed
583

qinsoon's avatar
qinsoon committed
584
        self.compiled_funcs.write().unwrap().insert(func.func_ver_id, RwLock::new(func));
qinsoon's avatar
qinsoon committed
585 586
    }
    
qinsoon's avatar
qinsoon committed
587
    pub fn get_backend_type_info(&self, tyid: MuID) -> Box<BackendTypeInfo> {        
qinsoon's avatar
qinsoon committed
588 589 590
        {
            let read_lock = self.backend_type_info.read().unwrap();
        
591
            match read_lock.get(&tyid) {
qinsoon's avatar
qinsoon committed
592 593 594 595
                Some(info) => {return info.clone();},
                None => {}
            }
        }
596 597

        let types = self.types.read().unwrap();
qinsoon's avatar
qinsoon committed
598 599 600 601
        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
602
        let resolved = Box::new(backend::resolve_backend_type_info(ty, self));
qinsoon's avatar
qinsoon committed
603 604
        
        let mut write_lock = self.backend_type_info.write().unwrap();
605
        write_lock.insert(tyid, resolved.clone());
qinsoon's avatar
qinsoon committed
606 607 608 609
        
        resolved        
    }
    
qinsoon's avatar
qinsoon committed
610 611 612 613
    pub fn get_type_size(&self, tyid: MuID) -> ByteSize {
        self.get_backend_type_info(tyid).size
    }
    
qinsoon's avatar
qinsoon committed
614
    pub fn globals(&self) -> &RwLock<HashMap<MuID, P<Value>>> {
qinsoon's avatar
qinsoon committed
615 616 617
        &self.globals
    }
    
qinsoon's avatar
qinsoon committed
618
    pub fn funcs(&self) -> &RwLock<HashMap<MuID, RwLock<MuFunction>>> {
qinsoon's avatar
qinsoon committed
619
        &self.funcs
620
    }
621
    
qinsoon's avatar
qinsoon committed
622
    pub fn func_vers(&self) -> &RwLock<HashMap<MuID, RwLock<MuFunctionVersion>>> {
623 624 625
        &self.func_vers
    }
    
qinsoon's avatar
qinsoon committed
626
    pub fn compiled_funcs(&self) -> &RwLock<HashMap<MuID, RwLock<CompiledFunction>>> {
627 628
        &self.compiled_funcs
    }
629 630 631 632 633 634 635 636
    
    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
637
    
638 639 640 641 642 643 644 645 646 647 648
    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 {
            ValueLocation::Relocatable(backend::RegGroup::GPR, func.name().unwrap())
        }
    }
    
qinsoon's avatar
qinsoon committed
649
    pub fn new_stack(&self, func_id: MuID) -> Box<MuStack> {
qinsoon's avatar
qinsoon committed
650 651 652
        let funcs = self.funcs.read().unwrap();
        let func : &MuFunction = &funcs.get(&func_id).unwrap().read().unwrap();
        
653 654 655 656 657 658
        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
659 660
    }
    
qinsoon's avatar
qinsoon committed
661 662 663 664 665 666 667 668
    #[allow(unused_variables)]
    pub fn make_boot_image(self, output: &path::Path) {
        use rustc_serialize::json;
        
        let serialized = json::encode(&self).unwrap();
        
        unimplemented!() 
    }
669
}