vm.rs 9.22 KB
Newer Older
1 2 3 4 5
use std::collections::HashMap;

use ast::ptr::P;
use ast::ir::*;
use ast::types::*;
qinsoon's avatar
qinsoon committed
6 7
use compiler::backend;
use compiler::backend::BackendTypeInfo;
8
use vm::machine_code::CompiledFunction;
qinsoon's avatar
qinsoon committed
9
use vm::vm_options::VMOptions;
qinsoon's avatar
qinsoon committed
10
use runtime::gc;
11 12
use runtime::thread::*;
use runtime::ValueLocation;
qinsoon's avatar
qinsoon committed
13
use utils::Address;
14

qinsoon's avatar
qinsoon committed
15
use std::sync::RwLock;
16
use std::sync::atomic::{AtomicUsize, AtomicBool, ATOMIC_BOOL_INIT, ATOMIC_USIZE_INIT, Ordering};
qinsoon's avatar
qinsoon committed
17
use std::thread::JoinHandle;
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 36 37
    func_vers: RwLock<HashMap<(MuID, MuID), RwLock<MuFunctionVersion>>>,
    funcs: RwLock<HashMap<MuID, RwLock<MuFunction>>>,
    
    compiled_funcs: RwLock<HashMap<MuID, RwLock<CompiledFunction>>>,
qinsoon's avatar
qinsoon committed
38
    
39 40
    threads: RwLock<Vec<JoinHandle<()>>>,
    pub primordial: RwLock<Option<MuPrimordialThread>>
41 42
}

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

qinsoon's avatar
qinsoon committed
188
        self.compiled_funcs.write().unwrap().insert(func.func_ver_id, RwLock::new(func));
qinsoon's avatar
qinsoon committed
189 190
    }
    
191
    pub fn get_backend_type_info(&self, tyid: MuID) -> P<BackendTypeInfo> {        
qinsoon's avatar
qinsoon committed
192 193 194
        {
            let read_lock = self.backend_type_info.read().unwrap();
        
195
            match read_lock.get(&tyid) {
qinsoon's avatar
qinsoon committed
196 197 198 199
                Some(info) => {return info.clone();},
                None => {}
            }
        }
200 201 202 203

        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
204 205
        
        let mut write_lock = self.backend_type_info.write().unwrap();
206
        write_lock.insert(tyid, resolved.clone());
qinsoon's avatar
qinsoon committed
207 208 209 210
        
        resolved        
    }
    
qinsoon's avatar
qinsoon committed
211 212 213 214 215 216 217 218
    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
219
    pub fn globals(&self) -> &RwLock<HashMap<MuID, P<Value>>> {
qinsoon's avatar
qinsoon committed
220 221 222
        &self.globals
    }
    
qinsoon's avatar
qinsoon committed
223
    pub fn funcs(&self) -> &RwLock<HashMap<MuID, RwLock<MuFunction>>> {
qinsoon's avatar
qinsoon committed
224
        &self.funcs
225
    }
226
    
qinsoon's avatar
qinsoon committed
227
    pub fn func_vers(&self) -> &RwLock<HashMap<(MuID, MuID), RwLock<MuFunctionVersion>>> {
228 229 230
        &self.func_vers
    }
    
qinsoon's avatar
qinsoon committed
231
    pub fn compiled_funcs(&self) -> &RwLock<HashMap<MuID, RwLock<CompiledFunction>>> {
232 233
        &self.compiled_funcs
    }
234 235 236 237 238 239 240 241
    
    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
242
    
243 244 245 246 247 248 249 250 251 252 253
    pub fn resolve_function_address(&self, func_id: MuID) -> ValueLocation {
        let funcs = self.funcs.read().unwrap();
        let func : &MuFunction = &funcs.get(&func_id).unwrap().read().unwrap();
                
        if self.is_running() {
            unimplemented!()
        } else {
            ValueLocation::Relocatable(backend::RegGroup::GPR, func.name().unwrap())
        }
    }
    
qinsoon's avatar
qinsoon committed
254
    pub fn new_stack(&self, func_id: MuID) -> Box<MuStack> {
qinsoon's avatar
qinsoon committed
255 256 257
        let funcs = self.funcs.read().unwrap();
        let func : &MuFunction = &funcs.get(&func_id).unwrap().read().unwrap();
        
258 259 260 261 262 263
        Box::new(MuStack::new(self.next_id(), self.resolve_function_address(func_id), func))
    }
    
    pub fn make_primordial_thread(&self, func_id: MuID, args: Vec<Constant>) {
        let mut guard = self.primordial.write().unwrap();
        *guard = Some(MuPrimordialThread{func_id: func_id, args: args});
qinsoon's avatar
qinsoon committed
264 265
    }
    
266 267
    #[deprecated]
    pub fn new_thread_normal(&self, mut stack: Box<MuStack>, threadlocal: Address, vals: Vec<ValueLocation>) {
qinsoon's avatar
qinsoon committed
268 269 270 271 272 273 274 275 276
        let user_tls = {
            if threadlocal.is_zero() {
                None
            } else {
                Some(threadlocal)
            }
        };
        
        // set up arguments on stack
277 278 279
        stack.runtime_load_args(vals);
        
        let handle = MuThread::mu_thread_launch(self.next_id(), stack, user_tls, self);
qinsoon's avatar
qinsoon committed
280
        
281 282
        let mut threads = self.threads.write().unwrap();
        threads.push(handle);
qinsoon's avatar
qinsoon committed
283
    }
284
}