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

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

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

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

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

    // ---do not serialize---

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

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

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

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

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

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

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

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

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

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

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

            // is_running
314 315
            let is_running = try!(d.read_struct_field("is_running", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
316 317 318 319

            // 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
320
            
qinsoon's avatar
qinsoon committed
321
            // compiled funcs
322
            let compiled_funcs = try!(d.read_struct_field("compiled_funcs", field_i, |d| {
qinsoon's avatar
qinsoon committed
323 324 325 326 327 328 329 330 331 332
                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)
                })
            }));
333
            field_i += 1;
qinsoon's avatar
qinsoon committed
334
            
qinsoon's avatar
qinsoon committed
335 336 337 338 339 340 341 342
            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),
343
                global_locations: RwLock::new(hashmap!{}),
qinsoon's avatar
qinsoon committed
344 345
                func_sigs: RwLock::new(func_sigs),
                funcs: RwLock::new(funcs),
346
                func_vers: RwLock::new(hashmap!{}),
qinsoon's avatar
qinsoon committed
347 348
                primordial: RwLock::new(primordial),
                is_running: ATOMIC_BOOL_INIT,
qinsoon's avatar
qinsoon committed
349
                vm_options: vm_options,
350 351
                compiled_funcs: RwLock::new(compiled_funcs),
                aot_pending_funcref_store: RwLock::new(HashMap::new())
qinsoon's avatar
qinsoon committed
352 353 354 355 356 357 358 359 360 361
            };
            
            vm.next_id.store(next_id, Ordering::SeqCst);
            vm.is_running.store(is_running, Ordering::SeqCst);
            
            Ok(vm)
        })
    }
}

362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
macro_rules! gen_handle_int {
    ($fn_from: ident, $fn_to: ident, $int_ty: ty) => {
        pub fn $fn_from (&self, num: $int_ty, len: BitSize) -> APIHandleResult {
            let handle_id = self.next_id();
            self.new_handle (APIHandle {
                id: handle_id,
                v: APIHandleValue::Int(num as u64, len)
            })
        }

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

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

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

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

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

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

qinsoon's avatar
qinsoon committed
403
            globals: RwLock::new(HashMap::new()),
404
            global_locations: RwLock::new(hashmap!{}),
qinsoon's avatar
qinsoon committed
405

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

411 412 413
            primordial: RwLock::new(None),

            aot_pending_funcref_store: RwLock::new(HashMap::new())
414
        };
qinsoon's avatar
qinsoon committed
415

416
        // insert all intenral types
qinsoon's avatar
qinsoon committed
417 418 419 420 421 422
        {
            let mut types = ret.types.write().unwrap();
            for ty in INTERNAL_TYPES.iter() {
                types.insert(ty.id(), ty.clone());
            }
        }
qinsoon's avatar
qinsoon committed
423

424
        ret.is_running.store(false, Ordering::SeqCst);
425 426 427 428 429 430 431 432 433

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

436 437 438 439
        // init types
        types::init_types();

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

441 442
        ret
    }
qinsoon's avatar
qinsoon committed
443

444
    fn init_runtime(&self) {
qinsoon's avatar
qinsoon committed
445 446 447 448 449 450
        // init log
        VM::start_logging(self.vm_options.flag_log_level);

        // init gc
        {
            let ref options = self.vm_options;
451
            gc::gc_init(options.flag_gc_immixspace_size, options.flag_gc_lospace_size, options.flag_gc_nthreads, !options.flag_gc_disable_collection);
qinsoon's avatar
qinsoon committed
452 453 454 455 456 457 458 459 460 461 462 463
        }
    }

    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
464 465 466
    }

    pub fn start_logging_trace() {
qinsoon's avatar
qinsoon committed
467 468 469 470
        VM::start_logging_internal(LogLevel::Trace)
    }

    fn start_logging_internal(level: LogLevel) {
471 472 473 474 475 476 477 478 479
        use stderrlog;

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

481 482 483
        match stderrlog::new().verbosity(verbose).init() {
            Ok(()) => info!("logger initialized"),
            Err(e) => error!("failed to init logger, probably already initialized: {:?}", e)
qinsoon's avatar
qinsoon committed
484 485
        }
    }
486
    
487 488 489
    pub fn resume_vm(serialized_vm: &str) -> VM {
        use rustc_serialize::json;
        
qinsoon's avatar
qinsoon committed
490
        let vm : VM = json::decode(serialized_vm).unwrap();
491
        
492
        vm.init_runtime();
493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511

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

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

                let ref gc_type = ty_info.gc_type;

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

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

qinsoon's avatar
qinsoon committed
512
                        mm::add_gc_type(GCType::new_noreftype(0, 8));
513 514 515 516 517 518 519 520 521 522 523
                        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;
            }
        }
524 525 526 527
        
        vm
    }
    
528
    pub fn next_id(&self) -> MuID {
529 530 531
        // 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.
532
        self.next_id.fetch_add(1, Ordering::Relaxed)
533 534
    }
    
535 536 537 538 539 540
    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
541 542
    }
    
543
    pub fn set_name(&self, entity: &MuEntity) {
qinsoon's avatar
qinsoon committed
544
        let id = entity.id();
545
        let name = entity.name().unwrap();
qinsoon's avatar
qinsoon committed
546 547
        
        let mut map = self.id_name_map.write().unwrap();
548
        map.insert(id, name.clone());
qinsoon's avatar
qinsoon committed
549 550 551 552 553
        
        let mut map2 = self.name_id_map.write().unwrap();
        map2.insert(name, id);
    }
    
554
    pub fn id_of_by_refstring(&self, name: &String) -> MuID {
qinsoon's avatar
qinsoon committed
555
        let map = self.name_id_map.read().unwrap();
556 557 558 559
        match map.get(name) {
            Some(id) => *id,
            None => panic!("cannot find id for name: {}", name)
        }
560
    }
561 562 563

    /// should only used by client
    /// 'name' used internally may be slightly different to remove some special symbols
564 565
    pub fn id_of(&self, name: &str) -> MuID {
        self.id_of_by_refstring(&name.to_string())
qinsoon's avatar
qinsoon committed
566
    }
567 568 569

    /// should only used by client
    /// 'name' used internally may be slightly different to remove some special symbols
qinsoon's avatar
qinsoon committed
570 571
    pub fn name_of(&self, id: MuID) -> MuName {
        let map = self.id_name_map.read().unwrap();
572
        map.get(&id).unwrap().clone()
qinsoon's avatar
qinsoon committed
573 574
    }
    
575
    pub fn declare_const(&self, entity: MuEntityHeader, ty: P<MuType>, val: Constant) -> P<Value> {
qinsoon's avatar
qinsoon committed
576
        let mut constants = self.constants.write().unwrap();
577
        let ret = P(Value{hdr: entity, ty: ty, v: Value_::Constant(val)});
578

579
        self.declare_const_internal(&mut constants, ret.id(), ret.clone());
qinsoon's avatar
qinsoon committed
580 581 582
        
        ret
    }
583 584 585 586

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

587
        trace!("declare const #{} = {}", id, val);
588 589
        map.insert(id, val);
    }
qinsoon's avatar
qinsoon committed
590
    
591 592 593 594 595 596 597
    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)
        }
    }
598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616

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

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

        ValueLocation::Relocatable(backend::RegGroup::GPR, name)
    }
617
    
618
    pub fn declare_global(&self, entity: MuEntityHeader, ty: P<MuType>) -> P<Value> {
qinsoon's avatar
qinsoon committed
619
        let global = P(Value{
620 621
            hdr: entity,
            ty: self.declare_type(MuEntityHeader::unnamed(self.next_id()), MuType_::iref(ty.clone())),
622
            v: Value_::Global(ty)
qinsoon's avatar
qinsoon committed
623
        });
qinsoon's avatar
qinsoon committed
624 625
        
        let mut globals = self.globals.write().unwrap();
626
        let mut global_locs = self.global_locations.write().unwrap();
627

628
        self.declare_global_internal(&mut globals, &mut global_locs, global.id(), global.clone());
qinsoon's avatar
qinsoon committed
629
        
qinsoon's avatar
qinsoon committed
630
        global
qinsoon's avatar
qinsoon committed
631
    }
632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664

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

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

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

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

671
        self.declare_type_internal(&mut types, ty.id(), ty.clone());
qinsoon's avatar
qinsoon committed
672 673 674
        
        ty
    }
675 676 677 678 679

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

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

681
        trace!("declare type #{} = {}", id, ty);
qinsoon's avatar
qinsoon committed
682 683 684 685
        if ty.is_struct() {
            let tag = ty.get_struct_hybrid_tag().unwrap();
            let struct_map_guard = STRUCT_TAG_MAP.read().unwrap();
            let struct_inner = struct_map_guard.get(&tag).unwrap();
686
            trace!("  {}", struct_inner);
qinsoon's avatar
qinsoon committed
687 688 689 690
        } else if ty.is_hybrid() {
            let tag = ty.get_struct_hybrid_tag().unwrap();
            let hybrid_map_guard = HYBRID_TAG_MAP.read().unwrap();
            let hybrid_inner = hybrid_map_guard.get(&tag).unwrap();
691
            trace!("  {}", hybrid_inner);
qinsoon's avatar
qinsoon committed
692
        }
693
    }
qinsoon's avatar
qinsoon committed
694
    
695 696 697 698 699 700 701 702
    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)
        }
    }    
    
703 704
    pub fn declare_func_sig(&self, entity: MuEntityHeader, ret_tys: Vec<P<MuType>>, arg_tys: Vec<P<MuType>>) -> P<MuFuncSig> {
        let ret = P(MuFuncSig{hdr: entity, ret_tys: ret_tys, arg_tys: arg_tys});
705 706

        let mut func_sigs = self.func_sigs.write().unwrap();
707
        self.declare_func_sig_internal(&mut func_sigs, ret.id(), ret.clone());
qinsoon's avatar
qinsoon committed
708 709 710
        
        ret
    }
711 712 713 714 715 716 717

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

        info!("declare func sig #{} = {}", id, sig);
        sigs.insert(id, sig);
    }
qinsoon's avatar
qinsoon committed
718
    
719 720 721 722 723 724 725 726
    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)
        }
    }
    
727
    pub fn declare_func (&self, func: MuFunction) {
qinsoon's avatar
qinsoon committed
728
        let mut funcs = self.funcs.write().unwrap();
729 730 731 732 733 734 735 736 737

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

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

        info!("declare func #{} = {}", id, func);
        funcs.insert(id, RwLock::new(func));
738
    }
739 740 741 742 743 744 745 746 747

    /// this is different than vm.name_of()
    pub fn get_func_name(&self, id: MuID) -> MuName {
        let funcs_lock = self.funcs.read().unwrap();
        match funcs_lock.get(&id) {
            Some(func) => func.read().unwrap().name().unwrap(),
            None => panic!("cannot find name for Mu function #{}")
        }
    }
748
    
749 750 751 752 753 754 755 756 757
    /// 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)
        }
    }    
    
758
    pub fn define_func_version (&self, func_ver: MuFunctionVersion) {
qinsoon's avatar
qinsoon committed
759
        info!("define function version {}", func_ver);
760
        // record this version
qinsoon's avatar
qinsoon committed
761
        let func_ver_id = func_ver.id();
762 763
        {
            let mut func_vers = self.func_vers.write().unwrap();
qinsoon's avatar
qinsoon committed
764
            func_vers.insert(func_ver_id, RwLock::new(func_ver));
765 766 767 768
        }
        
        // acquire a reference to the func_ver
        let func_vers = self.func_vers.read().unwrap();
qinsoon's avatar
qinsoon committed
769
        let func_ver = func_vers.get(&func_ver_id).unwrap().write().unwrap();
770 771 772
        
        // change current version to this (obsolete old versions)
        let funcs = self.funcs.read().unwrap();
qinsoon's avatar
qinsoon committed
773
        debug_assert!(funcs.contains_key(&func_ver.func_id)); // it should be declared before defining
qinsoon's avatar
qinsoon committed
774
        let mut func = funcs.get(&func_ver.func_id).unwrap().write().unwrap();
775
        
776 777 778 779
        func.new_version(func_ver.id());
        
        // redefinition happens here
        // do stuff        
780
    }
781 782 783 784 785 786 787 788 789 790 791 792 793 794

    /// 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>>,
795 796
                        new_func_vers: &mut HashMap<MuID, Box<MuFunctionVersion>>,
                        arc_vm: Arc<VM>
797 798 799
                        ) {
        // Make sure other components, if ever acquiring multiple locks at the same time, acquire
        // them in this order, to prevent deadlock.
800 801 802 803 804 805 806 807 808
        {
            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();
809

810 811 812 813
            for (id, name) in new_id_name_map.drain() {
                id_name_map.insert(id, name.clone());
                name_id_map.insert(name, id);
            }
814

815 816 817
            for (id, obj) in new_types.drain() {
                self.declare_type_internal(&mut types, id, obj);
            }
818

819 820 821
            for (id, obj) in new_constants.drain() {
                self.declare_const_internal(&mut constants, id, obj);
            }
822

823 824 825 826
            for (id, obj) in new_globals.drain() {
                // we bulk allocate later (since we are holding all the locks, we cannot find ty info)
                self.declare_global_internal_no_alloc(&mut globals, id, obj);
            }
827

828 829 830
            for (id, obj) in new_func_sigs.drain() {
                self.declare_func_sig_internal(&mut func_sigs, id, obj);
            }
831

832 833 834
            for (id, obj) in new_funcs.drain() {
                self.declare_func_internal(&mut funcs, id, *obj);
            }
835

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

840 841 842 843 844 845
                {
                    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);
                }
846 847 848
            }
        }
        // Locks released here
849 850 851 852 853 854 855

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

            // make sure current thread has allocator
856
            let created = unsafe {MuThread::current_thread_as_mu_thread(Address::zero(), arc_vm.clone())};
857 858 859 860

            for (id, global) in globals.iter() {
                self.alloc_global(&mut global_locs, *id, global.clone());
            }
861 862 863 864

            if created {
                unsafe {MuThread::cleanup_current_mu_thread()};
            }
865
        }
866
    }
867
    
868
    pub fn add_compiled_func (&self, func: CompiledFunction) {
qinsoon's avatar
qinsoon committed
869
        debug_assert!(self.funcs.read().unwrap().contains_key(&func.func_id));
qinsoon's avatar
qinsoon committed
870
        debug_assert!(self.func_vers.read().unwrap().contains_key(&func.func_ver_id));
qinsoon's avatar
qinsoon committed
871

qinsoon's avatar
qinsoon committed
872
        self.compiled_funcs.write().unwrap().insert(func.func_ver_id, RwLock::new(func));
qinsoon's avatar
qinsoon committed
873 874
    }
    
qinsoon's avatar
qinsoon committed
875
    pub fn get_backend_type_info(&self, tyid: MuID) -> Box<BackendTypeInfo> {        
qinsoon's avatar
qinsoon committed
876 877 878
        {
            let read_lock = self.backend_type_info.read().unwrap();
        
879
            match read_lock.get(&tyid) {
qinsoon's avatar
qinsoon committed
880 881 882 883
                Some(info) => {return info.clone();},
                None => {}
            }
        }
884 885

        let types = self.types.read().unwrap();
qinsoon's avatar
qinsoon committed
886 887 888 889
        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
890
        let resolved = Box::new(backend::resolve_backend_type_info(ty, self));
qinsoon's avatar
qinsoon committed
891 892
        
        let mut write_lock = self.backend_type_info.write().unwrap();
893
        write_lock.insert(tyid, resolved.clone());
qinsoon's avatar
qinsoon committed
894 895 896 897
        
        resolved        
    }
    
qinsoon's avatar
qinsoon committed
898 899 900 901
    pub fn get_type_size(&self, tyid: MuID) -> ByteSize {
        self.get_backend_type_info(tyid).size
    }
    
qinsoon's avatar
qinsoon committed
902
    pub fn globals(&self) -> &RwLock<HashMap<MuID, P<Value>>> {
qinsoon's avatar
qinsoon committed
903 904 905
        &self.globals
    }
    
qinsoon's avatar
qinsoon committed
906
    pub fn funcs(&self) -> &RwLock<HashMap<MuID, RwLock<MuFunction>>> {
qinsoon's avatar
qinsoon committed
907
        &self.funcs
908
    }
909
    
qinsoon's avatar
qinsoon committed
910
    pub fn func_vers(&self) -> &RwLock<HashMap<MuID, RwLock<MuFunctionVersion>>> {
911 912
        &self.func_vers
    }
qinsoon's avatar
qinsoon committed
913 914 915 916 917 918 919 920 921 922 923

    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
        }
    }
924
    
qinsoon's avatar
qinsoon committed
925
    pub fn compiled_funcs(&self) -> &RwLock<HashMap<MuID, RwLock<CompiledFunction>>> {
926 927
        &self.compiled_funcs
    }
928 929 930 931 932 933 934 935
    
    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
936
    
937 938 939 940 941 942 943
    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 {
944
            ValueLocation::Relocatable(backend::RegGroup::GPR, func.name().unwrap())
945 946 947
        }
    }
    
qinsoon's avatar
qinsoon committed
948
    pub fn new_stack(&self, func_id: MuID) -> Box<MuStack> {
qinsoon's avatar
qinsoon committed
949 950 951
        let funcs = self.funcs.read().unwrap();
        let func : &MuFunction = &funcs.get(&func_id).unwrap().read().unwrap();
        
952 953 954
        Box::new(MuStack::new(self.next_id(), self.resolve_function_address(func_id), func))
    }
    
qinsoon's avatar
qinsoon committed
955
    pub fn make_primordial_thread(&self, func_id: MuID, has_const_args: bool, args: Vec<Constant>) {
956
        let mut guard = self.primordial.write().unwrap();
qinsoon's avatar
qinsoon committed
957
        *guard = Some(MuPrimordialThread{func_id: func_id, has_const_args: has_const_args, args: args});
qinsoon's avatar
qinsoon committed
958
    }
959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976

    pub fn make_boot_image(&self,
                            whitelist: Vec<MuID>,
                            primordial_func: Option<&APIHandle>, primordial_stack: Option<&APIHandle>,
                            primordial_threadlocal: Option<&APIHandle>,
                            sym_fields: Vec<&APIHandle>, sym_strings: Vec<String>,
                            reloc_fields: Vec<&APIHandle>, reloc_strings: Vec<String>,
                            output_file: String) {
        self.make_boot_image_internal(
            whitelist,
            primordial_func, primordial_stack,
            primordial_threadlocal,
            sym_fields, sym_strings,
            reloc_fields, reloc_strings,
            vec![],
            output_file
        )
    }
qinsoon's avatar
qinsoon committed
977
    
qinsoon's avatar
qinsoon committed
978
    #[allow(unused_variables)]
979 980 981 982 983 984 985 986
    pub fn make_boot_image_internal(&self,
                                   whitelist: Vec<MuID>,
                                   primordial_func: Option<&APIHandle>, primordial_stack: Option<&APIHandle>,
                                   primordial_threadlocal: Option<&APIHandle>,
                                   sym_fields: Vec<&APIHandle>, sym_strings: Vec<String>,
                                   reloc_fields: Vec<&APIHandle>, reloc_strings: Vec<String>,
                                   extra_sources_to_link: Vec<String>,
                                   output_file: String) {
987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
        trace!("Making boot image...");

        let whitelist_funcs = {
            let compiler = Compiler::new(CompilerPolicy::default(), self);
            let funcs = self.funcs().read().unwrap();
            let func_vers = self.func_vers().read().unwrap();

            // make sure all functions in whitelist are compiled
            let mut whitelist_funcs: Vec<MuID> = vec![];
            for &id in whitelist.iter() {
                if let Some(f) = funcs.get(&id) {
                    whitelist_funcs.push(id);

                    let f: &MuFunction = &f.read().unwrap();
                    match f.cur_ver {
                        Some(fv_id) => {
                            let mut func_ver = func_vers.get(&fv_id).unwrap().write().unwrap();

                            if !func_ver.is_compiled() {
                                compiler.compile(&mut func_ver);
                            }
qinsoon's avatar
qinsoon committed
1008
                        }
1009
                        None => panic!("whitelist function {} has no version defined", f)
qinsoon's avatar
qinsoon committed
1010 1011 1012
                    }
                }
            }
1013 1014 1015 1016 1017 1018 1019

            whitelist_funcs
        };

        if primordial_threadlocal.is_some() {
            // we are going to need to persist this threadlocal
            unimplemented!()
qinsoon's avatar
qinsoon committed
1020 1021 1022
        }

        // make sure only one of primordial_func or primoridial_stack is set
1023 1024 1025 1026 1027
        let has_primordial_func  = primordial_func.is_some();
        let has_primordial_stack = primordial_stack.is_some();

        // we assume client will start with a function (instead of a stack)
        if has_primordial_stack {
qinsoon's avatar
qinsoon committed
1028
            panic!("Zebu doesnt support creating primordial thread through a stack, name a entry function instead")
1029
        } else {
1030 1031 1032 1033 1034 1035 1036 1037 1038
            if has_primordial_func {
                // extract func id
                let func_id = primordial_func.unwrap().v.as_funcref();

                // make primordial thread in vm
                self.make_primordial_thread(func_id, false, vec![]);    // do not pass const args, use argc/argv
            } else {
                warn!("no entry function is passed");
            }
1039

qinsoon's avatar
qinsoon committed
1040 1041 1042 1043 1044 1045
            // deal with relocation symbols
            assert_eq!(sym_fields.len(), sym_strings.len());
            let symbols = {
                let mut ret = hashmap!{};
                for i in 0..sym_fields.len() {
                    let addr = sym_fields[i].v.as_address();
1046
                    ret.insert(addr, name_check(sym_strings[i].clone()));
qinsoon's avatar
qinsoon committed
1047 1048 1049 1050 1051 1052 1053
                }
                ret
            };

            assert_eq!(reloc_fields.len(), reloc_strings.len());
            let fields = {
                let mut ret = hashmap!{};
1054 1055

                // client supplied relocation fields
qinsoon's avatar
qinsoon committed
1056 1057
                for i in 0..reloc_fields.len() {
                    let addr = reloc_fields[i].v.as_address();
1058 1059 1060 1061 1062 1063 1064 1065 1066
                    ret.insert(addr, name_check(reloc_strings[i].clone()));
                }

                // pending funcrefs - we want to replace them as symbol
                {
                    let mut pending_funcref = self.aot_pending_funcref_store.write().unwrap();
                    for (addr, vl) in pending_funcref.drain() {
                        ret.insert(addr, name_check(vl.to_relocatable()));
                    }
qinsoon's avatar
qinsoon committed
1067
                }
1068

qinsoon's avatar
qinsoon committed
1069 1070 1071
                ret
            };

1072
            // emit context (serialized vm, etc)
qinsoon's avatar
qinsoon committed
1073
            backend::emit_context_with_reloc(self, symbols, fields);
1074 1075

            // link
1076
            self.link_boot_image(whitelist_funcs, extra_sources_to_link, output_file);
1077 1078 1079 1080
        }
    }

    #[cfg(feature = "aot")]
1081
    fn link_boot_image(&self, funcs: Vec<MuID>, extra_srcs: Vec<String>, output_file: String) {
qinsoon's avatar