GitLab will be upgraded on 30 Jan 2023 from 2.00 pm (AEDT) to 3.00 pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

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

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

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

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

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

qinsoon's avatar
qinsoon committed
69
const VM_SERIALIZE_FIELDS : usize = 14;
qinsoon's avatar
qinsoon committed
70

71
72
impl Encodable for VM {
    fn encode<S: Encoder> (&self, s: &mut S) -> Result<(), S::Error> {
73
74
        let mut field_i = 0;

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

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

qinsoon's avatar
qinsoon committed
195
            // primordial
qinsoon's avatar
qinsoon committed
196
            trace!("...serializing primordial");
qinsoon's avatar
qinsoon committed
197
198
            {
                let primordial = &self.primordial.read().unwrap();
199
                try!(s.emit_struct_field("primordial", field_i, |s| primordial.encode(s)));
qinsoon's avatar
qinsoon committed
200
            }
201
            field_i += 1;
qinsoon's avatar
qinsoon committed
202
203
            
            // is_running
qinsoon's avatar
qinsoon committed
204
            trace!("...serializing is_running");
qinsoon's avatar
qinsoon committed
205
            {
206
                try!(s.emit_struct_field("is_running", field_i, |s| self.is_running.load(Ordering::SeqCst).encode(s)));
207
            }
208
            field_i += 1;
qinsoon's avatar
qinsoon committed
209
210
211
212
213
214
215

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

qinsoon's avatar
qinsoon committed
242
243
impl Decodable for VM {
    fn decode<D: Decoder>(d: &mut D) -> Result<VM, D::Error> {
244
245
246
        let mut field_i = 0;

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

            // is_running
338
339
            let is_running = try!(d.read_struct_field("is_running", field_i, |d| Decodable::decode(d)));
            field_i += 1;
qinsoon's avatar
qinsoon committed
340
341
342
343

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

385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
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
401
402
impl <'a> VM {
    pub fn new() -> VM {
qinsoon's avatar
qinsoon committed
403
404
405
406
407
408
409
410
411
        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
412

qinsoon's avatar
qinsoon committed
413
        let ret = VM {
414
            next_id: ATOMIC_USIZE_INIT,
415
            is_running: ATOMIC_BOOL_INIT,
qinsoon's avatar
qinsoon committed
416
417
            vm_options: options,

qinsoon's avatar
qinsoon committed
418
419
            id_name_map: RwLock::new(HashMap::new()),
            name_id_map: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
420

qinsoon's avatar
qinsoon committed
421
            constants: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
422

qinsoon's avatar
qinsoon committed
423
            types: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
424
            backend_type_info: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
425

qinsoon's avatar
qinsoon committed
426
            globals: RwLock::new(HashMap::new()),
427
            global_locations: RwLock::new(hashmap!{}),
qinsoon's avatar
qinsoon committed
428

qinsoon's avatar
qinsoon committed
429
            func_sigs: RwLock::new(HashMap::new()),
430
            func_vers: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
431
            funcs: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
432
            compiled_funcs: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
433

434
            primordial: RwLock::new(None)
435
        };
qinsoon's avatar
qinsoon committed
436

437
        // insert all intenral types
qinsoon's avatar
qinsoon committed
438
439
440
441
442
443
        {
            let mut types = ret.types.write().unwrap();
            for ty in INTERNAL_TYPES.iter() {
                types.insert(ty.id(), ty.clone());
            }
        }
qinsoon's avatar
qinsoon committed
444

445
        ret.is_running.store(false, Ordering::SeqCst);
Kunshan Wang's avatar
Kunshan Wang committed
446
447
448
449
450
451
452
453
454

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

457
458
459
460
        // init types
        types::init_types();

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

462
463
        ret
    }
qinsoon's avatar
qinsoon committed
464

465
    fn init_runtime(&self) {
qinsoon's avatar
qinsoon committed
466
467
468
469
470
471
        // init log
        VM::start_logging(self.vm_options.flag_log_level);

        // init gc
        {
            let ref options = self.vm_options;
472
            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
473
474
475
476
477
478
479
480
481
482
483
484
        }
    }

    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
485
486
487
    }

    pub fn start_logging_trace() {
qinsoon's avatar
qinsoon committed
488
489
490
491
        VM::start_logging_internal(LogLevel::Trace)
    }

    fn start_logging_internal(level: LogLevel) {
492
493
494
495
496
497
498
499
500
        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
501

502
503
504
        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
505
506
        }
    }
507
    
508
509
510
    pub fn resume_vm(serialized_vm: &str) -> VM {
        use rustc_serialize::json;
        
qinsoon's avatar
qinsoon committed
511
        let vm : VM = json::decode(serialized_vm).unwrap();
512
        
513
        vm.init_runtime();
qinsoon's avatar
qinsoon committed
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532

        // 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
533
                        mm::add_gc_type(GCType::new_noreftype(0, 8));
qinsoon's avatar
qinsoon committed
534
535
536
537
538
539
540
541
542
543
544
                        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;
            }
        }
545
546
547
548
        
        vm
    }
    
549
    pub fn next_id(&self) -> MuID {
Kunshan Wang's avatar
Kunshan Wang committed
550
551
552
        // 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.
553
        self.next_id.fetch_add(1, Ordering::Relaxed)
554
555
    }
    
556
557
558
559
560
561
    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
562
563
    }
    
564
    pub fn set_name(&self, entity: &MuEntity, name: MuName) {
qinsoon's avatar
qinsoon committed
565
        let id = entity.id();
566
        entity.set_name(name.clone());
qinsoon's avatar
qinsoon committed
567
568
        
        let mut map = self.id_name_map.write().unwrap();
569
        map.insert(id, name.clone());
qinsoon's avatar
qinsoon committed
570
571
572
573
574
        
        let mut map2 = self.name_id_map.write().unwrap();
        map2.insert(name, id);
    }
    
Kunshan Wang's avatar
Kunshan Wang committed
575
    pub fn id_of_by_refstring(&self, name: &String) -> MuID {
qinsoon's avatar
qinsoon committed
576
        let map = self.name_id_map.read().unwrap();
577
578
579
580
        match map.get(name) {
            Some(id) => *id,
            None => panic!("cannot find id for name: {}", name)
        }
Kunshan Wang's avatar
Kunshan Wang committed
581
582
583
584
    }
    
    pub fn id_of(&self, name: &str) -> MuID {
        self.id_of_by_refstring(&name.to_string())
qinsoon's avatar
qinsoon committed
585
586
587
588
    }
    
    pub fn name_of(&self, id: MuID) -> MuName {
        let map = self.id_name_map.read().unwrap();
589
        map.get(&id).unwrap().clone()
qinsoon's avatar
qinsoon committed
590
591
    }
    
qinsoon's avatar
qinsoon committed
592
    pub fn declare_const(&self, id: MuID, ty: P<MuType>, val: Constant) -> P<Value> {
qinsoon's avatar
qinsoon committed
593
        let mut constants = self.constants.write().unwrap();
594
        let ret = P(Value{hdr: MuEntityHeader::unnamed(id), ty: ty, v: Value_::Constant(val)});
595
596

        self.declare_const_internal(&mut constants, id, ret.clone());
qinsoon's avatar
qinsoon committed
597
598
599
        
        ret
    }
600
601
602
603
604
605
606

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

        info!("declare const #{} = {}", id, val);
        map.insert(id, val);
    }
qinsoon's avatar
qinsoon committed
607
    
608
609
610
611
612
613
614
    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)
        }
    }
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633

    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)
    }
634
    
qinsoon's avatar
qinsoon committed
635
636
    pub fn declare_global(&self, id: MuID, ty: P<MuType>) -> P<Value> {
        let global = P(Value{
637
            hdr: MuEntityHeader::unnamed(id),
638
            ty: self.declare_type(self.next_id(), MuType_::iref(ty.clone())),
639
            v: Value_::Global(ty)
qinsoon's avatar
qinsoon committed
640
        });
qinsoon's avatar
qinsoon committed
641
642
        
        let mut globals = self.globals.write().unwrap();
643
        let mut global_locs = self.global_locations.write().unwrap();
644
645

        self.declare_global_internal(&mut globals, &mut global_locs, id, global.clone());
qinsoon's avatar
qinsoon committed
646
        
qinsoon's avatar
qinsoon committed
647
        global
qinsoon's avatar
qinsoon committed
648
    }
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681

    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
682
    
qinsoon's avatar
qinsoon committed
683
    pub fn declare_type(&self, id: MuID, ty: MuType_) -> P<MuType> {
684
        let ty = P(MuType{hdr: MuEntityHeader::unnamed(id), v: ty});
qinsoon's avatar
qinsoon committed
685
        
qinsoon's avatar
qinsoon committed
686
        let mut types = self.types.write().unwrap();
687

688
        self.declare_type_internal(&mut types, id, ty.clone());
qinsoon's avatar
qinsoon committed
689
690
691
        
        ty
    }
692
693
694
695
696

    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
697
698
699
700
701
702
703
704
705
706
707
708
709

        info!("declare type #{} = {}", id, ty);
        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();
            info!("  {}", struct_inner);
        } 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();
            info!("  {}", hybrid_inner);
        }
710
    }
qinsoon's avatar
qinsoon committed
711
    
712
713
714
715
716
717
718
719
    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
720
    pub fn declare_func_sig(&self, id: MuID, ret_tys: Vec<P<MuType>>, arg_tys: Vec<P<MuType>>) -> P<MuFuncSig> {
721
        let ret = P(MuFuncSig{hdr: MuEntityHeader::unnamed(id), ret_tys: ret_tys, arg_tys: arg_tys});
722
723
724

        let mut func_sigs = self.func_sigs.write().unwrap();
        self.declare_func_sig_internal(&mut func_sigs, id, ret.clone());
qinsoon's avatar
qinsoon committed
725
726
727
        
        ret
    }
728
729
730
731
732
733
734

    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
735
    
736
737
738
739
740
741
742
743
    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)
        }
    }
    
744
    pub fn declare_func (&self, func: MuFunction) {
qinsoon's avatar
qinsoon committed
745
        let mut funcs = self.funcs.write().unwrap();
746
747
748
749
750
751
752
753
754

        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));
755
756
    }
    
757
758
759
760
761
762
763
764
765
    /// 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)
        }
    }    
    
766
    pub fn define_func_version (&self, func_ver: MuFunctionVersion) {
qinsoon's avatar
qinsoon committed
767
        info!("define function version {}", func_ver);
768
        // record this version
qinsoon's avatar
qinsoon committed
769
        let func_ver_id = func_ver.id();
770
771
        {
            let mut func_vers = self.func_vers.write().unwrap();
qinsoon's avatar
qinsoon committed
772
            func_vers.insert(func_ver_id, RwLock::new(func_ver));
773
774
775
776
        }
        
        // acquire a reference to the func_ver
        let func_vers = self.func_vers.read().unwrap();
qinsoon's avatar
qinsoon committed
777
        let func_ver = func_vers.get(&func_ver_id).unwrap().write().unwrap();
778
779
780
        
        // change current version to this (obsolete old versions)
        let funcs = self.funcs.read().unwrap();
qinsoon's avatar
qinsoon committed
781
        debug_assert!(funcs.contains_key(&func_ver.func_id)); // it should be declared before defining
qinsoon's avatar
qinsoon committed
782
        let mut func = funcs.get(&func_ver.func_id).unwrap().write().unwrap();
783
        
784
785
786
787
        func.new_version(func_ver.id());
        
        // redefinition happens here
        // do stuff        
788
    }
789
790
791
792
793
794
795
796
797
798
799
800
801
802

    /// 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>>,
803
804
                        new_func_vers: &mut HashMap<MuID, Box<MuFunctionVersion>>,
                        arc_vm: Arc<VM>
805
806
807
                        ) {
        // Make sure other components, if ever acquiring multiple locks at the same time, acquire
        // them in this order, to prevent deadlock.
808
809
810
811
812
813
814
815
816
        {
            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();
817

818
819
820
821
            for (id, name) in new_id_name_map.drain() {
                id_name_map.insert(id, name.clone());
                name_id_map.insert(name, id);
            }
822

823
824
825
            for (id, obj) in new_types.drain() {
                self.declare_type_internal(&mut types, id, obj);
            }
826

827
828
829
            for (id, obj) in new_constants.drain() {
                self.declare_const_internal(&mut constants, id, obj);
            }
830

831
832
833
834
            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);
            }
835

836
837
838
            for (id, obj) in new_func_sigs.drain() {
                self.declare_func_sig_internal(&mut func_sigs, id, obj);
            }
839

840
841
842
            for (id, obj) in new_funcs.drain() {
                self.declare_func_internal(&mut funcs, id, *obj);
            }
843

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

848
849
850
851
852
853
                {
                    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);
                }
854
855
856
            }
        }
        // Locks released here
857
858
859
860
861
862
863

        // 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
864
            let created = unsafe {MuThread::current_thread_as_mu_thread(Address::zero(), arc_vm.clone())};
865
866
867
868

            for (id, global) in globals.iter() {
                self.alloc_global(&mut global_locs, *id, global.clone());
            }
869
870
871
872

            if created {
                unsafe {MuThread::cleanup_current_mu_thread()};
            }
873
        }
874
    }
875
    
876
    pub fn add_compiled_func (&self, func: CompiledFunction) {
qinsoon's avatar
qinsoon committed
877
        debug_assert!(self.funcs.read().unwrap().contains_key(&func.func_id));
qinsoon's avatar
qinsoon committed
878
        debug_assert!(self.func_vers.read().unwrap().contains_key(&func.func_ver_id));
qinsoon's avatar
qinsoon committed
879

qinsoon's avatar
qinsoon committed
880
        self.compiled_funcs.write().unwrap().insert(func.func_ver_id, RwLock::new(func));
qinsoon's avatar
qinsoon committed
881
882
    }
    
qinsoon's avatar
qinsoon committed
883
    pub fn get_backend_type_info(&self, tyid: MuID) -> Box<BackendTypeInfo> {        
qinsoon's avatar
qinsoon committed
884
885
886
        {
            let read_lock = self.backend_type_info.read().unwrap();
        
887
            match read_lock.get(&tyid) {
qinsoon's avatar
qinsoon committed
888
889
890
891
                Some(info) => {return info.clone();},
                None => {}
            }
        }
892
893

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

    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
        }
    }
932
    
qinsoon's avatar
qinsoon committed
933
    pub fn compiled_funcs(&self) -> &RwLock<HashMap<MuID, RwLock<CompiledFunction>>> {
934
935
        &self.compiled_funcs
    }
936
937
938
939
940
941
942
943
    
    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
944
    
945
946
947
948
949
950
951
    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 {
952
            ValueLocation::Relocatable(backend::RegGroup::GPR, func.name().unwrap())
953
954
955
        }
    }
    
qinsoon's avatar
qinsoon committed
956
    pub fn new_stack(&self, func_id: MuID) -> Box<MuStack> {
qinsoon's avatar
qinsoon committed
957
958
959
        let funcs = self.funcs.read().unwrap();
        let func : &MuFunction = &funcs.get(&func_id).unwrap().read().unwrap();
        
960
961
962
        Box::new(MuStack::new(self.next_id(), self.resolve_function_address(func_id), func))
    }
    
qinsoon's avatar
qinsoon committed
963
    pub fn make_primordial_thread(&self, func_id: MuID, has_const_args: bool, args: Vec<Constant>) {
964
        let mut guard = self.primordial.write().unwrap();
qinsoon's avatar
qinsoon committed
965
        *guard = Some(MuPrimordialThread{func_id: func_id, has_const_args: has_const_args, args: args});
qinsoon's avatar
qinsoon committed
966
967
    }
    
qinsoon's avatar
qinsoon committed
968
    #[allow(unused_variables)]
969
    pub fn make_boot_image(&self,
qinsoon's avatar
qinsoon committed
970
971
972
973
974
975
                           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) {
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
        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
997
                        }
998
                        None => panic!("whitelist function {} has no version defined", f)
qinsoon's avatar
qinsoon committed
999
1000
1001
                    }
                }
            }
1002
1003
1004
1005
1006
1007
1008

            whitelist_funcs
        };

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

        // make sure only one of primordial_func or primoridial_stack is set