vm.rs 7.67 KB
Newer Older
qinsoon's avatar
qinsoon committed
1 2
extern crate immix_rust as gc;

3 4 5 6 7
use std::collections::HashMap;

use ast::ptr::P;
use ast::ir::*;
use ast::types::*;
qinsoon's avatar
qinsoon committed
8 9
use compiler::backend;
use compiler::backend::BackendTypeInfo;
10
use vm::machine_code::CompiledFunction;
qinsoon's avatar
qinsoon committed
11
use vm::vm_options::VMOptions;
qinsoon's avatar
qinsoon committed
12 13
use runtime::thread::MuStack;
use runtime::thread::MuThread;
14

qinsoon's avatar
qinsoon committed
15
use std::sync::RwLock;
16
use std::cell::RefCell;
17
use std::sync::atomic::{AtomicUsize, AtomicBool, ATOMIC_BOOL_INIT, ATOMIC_USIZE_INIT, Ordering};
18

qinsoon's avatar
qinsoon committed
19
pub struct VM {
20
    next_id: AtomicUsize,
qinsoon's avatar
qinsoon committed
21
    is_running: AtomicBool,
22
    
qinsoon's avatar
qinsoon committed
23 24
    id_name_map: RwLock<HashMap<MuID, MuName>>,
    name_id_map: RwLock<HashMap<MuName, MuID>>,
qinsoon's avatar
qinsoon committed
25
    
qinsoon's avatar
qinsoon committed
26
    types: RwLock<HashMap<MuID, P<MuType>>>,
27
    backend_type_info: RwLock<HashMap<MuID, P<BackendTypeInfo>>>,
28
    
qinsoon's avatar
qinsoon committed
29 30
    constants: RwLock<HashMap<MuID, P<Value>>>,
    globals: RwLock<HashMap<MuID, P<Value>>>,
qinsoon's avatar
qinsoon committed
31
    
qinsoon's avatar
qinsoon committed
32 33
    func_sigs: RwLock<HashMap<MuID, P<MuFuncSig>>>,
    // key: (func_id, func_ver_id)
qinsoon's avatar
qinsoon committed
34 35
    func_vers: RwLock<HashMap<(MuID, MuID), RefCell<MuFunctionVersion>>>,
    funcs: RwLock<HashMap<MuID, RefCell<MuFunction>>>,
qinsoon's avatar
qinsoon committed
36
    
qinsoon's avatar
qinsoon committed
37
    compiled_funcs: RwLock<HashMap<MuID, RefCell<CompiledFunction>>>
38 39
}

qinsoon's avatar
qinsoon committed
40 41 42
impl <'a> VM {
    pub fn new() -> VM {
        let ret = VM {
43
            next_id: ATOMIC_USIZE_INIT,
44 45
            is_running: ATOMIC_BOOL_INIT,
            
qinsoon's avatar
qinsoon committed
46 47 48
            id_name_map: RwLock::new(HashMap::new()),
            name_id_map: RwLock::new(HashMap::new()),
            
qinsoon's avatar
qinsoon committed
49
            constants: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
50
            
qinsoon's avatar
qinsoon committed
51
            types: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
52
            backend_type_info: RwLock::new(HashMap::new()),
53
            
qinsoon's avatar
qinsoon committed
54 55 56
            globals: RwLock::new(HashMap::new()),
            
            func_sigs: RwLock::new(HashMap::new()),
57
            func_vers: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
58 59
            funcs: RwLock::new(HashMap::new()),
            compiled_funcs: RwLock::new(HashMap::new())
60 61 62
        };
        
        ret.is_running.store(false, Ordering::SeqCst);
qinsoon's avatar
qinsoon committed
63
        ret.next_id.store(USER_ID_START, Ordering::SeqCst);
64
        
qinsoon's avatar
qinsoon committed
65 66 67
        let options = VMOptions::default();
        gc::gc_init(options.immix_size, options.lo_size, options.n_gcthreads);
        
68 69 70
        ret
    }
    
71 72 73 74
    pub fn next_id(&self) -> MuID {
        self.next_id.fetch_add(1, Ordering::SeqCst)
    }
    
75 76 77 78 79 80
    pub fn run_vm(&self) {
        self.is_running.store(true, Ordering::SeqCst);
    }
    
    pub fn is_running(&self) -> bool {
        self.is_running.load(Ordering::Relaxed)
81 82
    }
    
83
    pub fn set_name(&self, entity: &MuEntity, name: MuName) {
qinsoon's avatar
qinsoon committed
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
        let id = entity.id();
        entity.set_name(name);
        
        let mut map = self.id_name_map.write().unwrap();
        map.insert(id, name);
        
        let mut map2 = self.name_id_map.write().unwrap();
        map2.insert(name, id);
    }
    
    pub fn id_of(&self, name: MuName) -> MuID {
        let map = self.name_id_map.read().unwrap();
        *map.get(name).unwrap()
    }
    
    pub fn name_of(&self, id: MuID) -> MuName {
        let map = self.id_name_map.read().unwrap();
        map.get(&id).unwrap()
    }
    
qinsoon's avatar
qinsoon committed
104
    pub fn declare_const(&self, id: MuID, ty: P<MuType>, val: Constant) -> P<Value> {
qinsoon's avatar
qinsoon committed
105
        let mut constants = self.constants.write().unwrap();
qinsoon's avatar
qinsoon committed
106
        debug_assert!(!constants.contains_key(&id));
107
        
108
        let ret = P(Value{hdr: MuEntityHeader::unnamed(id), ty: ty, v: Value_::Constant(val)});
qinsoon's avatar
qinsoon committed
109
        constants.insert(id, ret.clone());
110 111 112 113
        
        ret
    }
    
qinsoon's avatar
qinsoon committed
114 115
    pub fn declare_global(&self, id: MuID, ty: P<MuType>) -> P<Value> {
        let global = P(Value{
116 117 118
            hdr: MuEntityHeader::unnamed(id),
            ty: P(MuType::new(self.next_id(), MuType_::iref(ty.clone()))),
            v: Value_::Global(ty)
qinsoon's avatar
qinsoon committed
119
        });
qinsoon's avatar
qinsoon committed
120 121
        
        let mut globals = self.globals.write().unwrap();
qinsoon's avatar
qinsoon committed
122
        globals.insert(id, global.clone());
qinsoon's avatar
qinsoon committed
123
        
qinsoon's avatar
qinsoon committed
124
        global
qinsoon's avatar
qinsoon committed
125 126
    }
    
qinsoon's avatar
qinsoon committed
127
    pub fn declare_type(&self, id: MuID, ty: MuType_) -> P<MuType> {
128
        let ty = P(MuType{hdr: MuEntityHeader::unnamed(id), v: ty});
qinsoon's avatar
qinsoon committed
129
        
qinsoon's avatar
qinsoon committed
130
        let mut types = self.types.write().unwrap();
qinsoon's avatar
qinsoon committed
131
        debug_assert!(!types.contains_key(&id));
132
        
qinsoon's avatar
qinsoon committed
133
        types.insert(ty.id(), ty.clone());
134 135 136 137
        
        ty
    }
    
qinsoon's avatar
qinsoon committed
138
    pub fn declare_func_sig(&self, id: MuID, ret_tys: Vec<P<MuType>>, arg_tys: Vec<P<MuType>>) -> P<MuFuncSig> {
qinsoon's avatar
qinsoon committed
139
        let mut func_sigs = self.func_sigs.write().unwrap();
qinsoon's avatar
qinsoon committed
140
        debug_assert!(!func_sigs.contains_key(&id));
141
        
142
        let ret = P(MuFuncSig{hdr: MuEntityHeader::unnamed(id), ret_tys: ret_tys, arg_tys: arg_tys});
qinsoon's avatar
qinsoon committed
143
        func_sigs.insert(id, ret.clone());
144 145 146 147
        
        ret
    }
    
148
    pub fn declare_func (&self, func: MuFunction) {
qinsoon's avatar
qinsoon committed
149
        info!("declare function {}", func);
qinsoon's avatar
qinsoon committed
150
        let mut funcs = self.funcs.write().unwrap();
151
        funcs.insert(func.id(), RefCell::new(func));
152 153
    }
    
154
    pub fn define_func_version (&self, func_ver: MuFunctionVersion) {
qinsoon's avatar
qinsoon committed
155
        info!("define function version {}", func_ver);
156
        // record this version
157
        let func_ver_key = (func_ver.func_id, func_ver.id());
158 159 160 161 162 163 164 165 166 167 168
        {
            let mut func_vers = self.func_vers.write().unwrap();
            func_vers.insert(func_ver_key, RefCell::new(func_ver));
        }
        
        // acquire a reference to the func_ver
        let func_vers = self.func_vers.read().unwrap();
        let func_ver = func_vers.get(&func_ver_key).unwrap().borrow();
        
        // change current version to this (obsolete old versions)
        let funcs = self.funcs.read().unwrap();
qinsoon's avatar
qinsoon committed
169 170
        debug_assert!(funcs.contains_key(&func_ver.func_id)); // it should be declared before defining
        let mut func = funcs.get(&func_ver.func_id).unwrap().borrow_mut();
171
        
172 173 174 175
        func.new_version(func_ver.id());
        
        // redefinition happens here
        // do stuff        
176 177
    }
    
178
    pub fn add_compiled_func (&self, func: CompiledFunction) {
qinsoon's avatar
qinsoon committed
179 180
        debug_assert!(self.funcs.read().unwrap().contains_key(&func.func_id));
        debug_assert!(self.func_vers.read().unwrap().contains_key(&(func.func_id, func.func_ver_id)));
qinsoon's avatar
qinsoon committed
181

qinsoon's avatar
qinsoon committed
182
        self.compiled_funcs.write().unwrap().insert(func.func_ver_id, RefCell::new(func));
qinsoon's avatar
qinsoon committed
183 184
    }
    
185
    pub fn get_backend_type_info(&self, tyid: MuID) -> P<BackendTypeInfo> {        
qinsoon's avatar
qinsoon committed
186 187 188
        {
            let read_lock = self.backend_type_info.read().unwrap();
        
189
            match read_lock.get(&tyid) {
qinsoon's avatar
qinsoon committed
190 191 192 193
                Some(info) => {return info.clone();},
                None => {}
            }
        }
194 195 196 197

        let types = self.types.read().unwrap();
        let ty = types.get(&tyid).unwrap();
        let resolved = P(backend::resolve_backend_type_info(ty, self));
qinsoon's avatar
qinsoon committed
198 199
        
        let mut write_lock = self.backend_type_info.write().unwrap();
200
        write_lock.insert(tyid, resolved.clone());
qinsoon's avatar
qinsoon committed
201 202 203 204
        
        resolved        
    }
    
qinsoon's avatar
qinsoon committed
205 206 207 208 209 210 211 212
    pub fn get_id_of(&self, name: MuName) -> MuID {
        *self.name_id_map.read().unwrap().get(&name).unwrap()
    }
    
    pub fn get_name_of(&self, id: MuID) -> MuName {
        *self.id_name_map.read().unwrap().get(&id).unwrap()
    }
    
qinsoon's avatar
qinsoon committed
213
    pub fn globals(&self) -> &RwLock<HashMap<MuID, P<Value>>> {
qinsoon's avatar
qinsoon committed
214 215 216
        &self.globals
    }
    
qinsoon's avatar
qinsoon committed
217
    pub fn funcs(&self) -> &RwLock<HashMap<MuID, RefCell<MuFunction>>> {
qinsoon's avatar
qinsoon committed
218
        &self.funcs
219
    }
220
    
qinsoon's avatar
qinsoon committed
221
    pub fn func_vers(&self) -> &RwLock<HashMap<(MuID, MuID), RefCell<MuFunctionVersion>>> {
222 223 224
        &self.func_vers
    }
    
qinsoon's avatar
qinsoon committed
225
    pub fn compiled_funcs(&self) -> &RwLock<HashMap<MuID, RefCell<CompiledFunction>>> {
226 227
        &self.compiled_funcs
    }
228 229 230 231 232 233 234 235
    
    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
236 237 238 239
    
    pub fn new_stack(&self, func_id: MuID) -> Box<MuStack> {
        Box::new(MuStack::new(self.next_id(), func_id))
    }
240
}