context.rs 6.78 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
use vm::api::*;
13

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

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

qinsoon's avatar
qinsoon committed
39 40 41
impl <'a> VM {
    pub fn new() -> VM {
        let ret = VM {
42
            next_id: ATOMIC_USIZE_INIT,
43 44
            is_running: ATOMIC_BOOL_INIT,
            
qinsoon's avatar
qinsoon committed
45 46 47
            id_name_map: RwLock::new(HashMap::new()),
            name_id_map: RwLock::new(HashMap::new()),
            
qinsoon's avatar
qinsoon committed
48
            constants: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
49
            
qinsoon's avatar
qinsoon committed
50
            types: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
51
            backend_type_info: RwLock::new(HashMap::new()),
52
            
qinsoon's avatar
qinsoon committed
53 54 55
            globals: RwLock::new(HashMap::new()),
            
            func_sigs: RwLock::new(HashMap::new()),
56
            func_vers: RwLock::new(HashMap::new()),
qinsoon's avatar
qinsoon committed
57 58
            funcs: RwLock::new(HashMap::new()),
            compiled_funcs: RwLock::new(HashMap::new())
59 60 61
        };
        
        ret.is_running.store(false, Ordering::SeqCst);
qinsoon's avatar
qinsoon committed
62
        ret.next_id.store(USER_ID_START, Ordering::SeqCst);
63
        
qinsoon's avatar
qinsoon committed
64 65 66
        let options = VMOptions::default();
        gc::gc_init(options.immix_size, options.lo_size, options.n_gcthreads);
        
67 68 69
        ret
    }
    
70 71 72 73
    pub fn next_id(&self) -> MuID {
        self.next_id.fetch_add(1, Ordering::SeqCst)
    }
    
74 75 76 77 78 79
    pub fn run_vm(&self) {
        self.is_running.store(true, Ordering::SeqCst);
    }
    
    pub fn is_running(&self) -> bool {
        self.is_running.load(Ordering::Relaxed)
80 81
    }
    
qinsoon's avatar
qinsoon committed
82
    pub fn declare_const(&self, id: MuID, const_name: MuName, ty: P<MuType>, val: Constant) -> P<Value> {
qinsoon's avatar
qinsoon committed
83 84
        let mut constants = self.constants.write().unwrap();
        debug_assert!(!constants.contains_key(const_name));
85
        
qinsoon's avatar
qinsoon committed
86
        let ret = P(Value{id: id, name: Some(const_name), ty: ty, v: Value_::Constant(val)});
qinsoon's avatar
qinsoon committed
87
        constants.insert(const_name, ret.clone());
88 89 90 91
        
        ret
    }
    
qinsoon's avatar
qinsoon committed
92
    pub fn declare_global(&self, id: MuID, global_name: MuName, ty: P<MuType>) -> P<Value> {
qinsoon's avatar
qinsoon committed
93 94 95 96 97 98
        let global = P(GlobalCell{tag: global_name, ty: ty.clone()});
        
        let mut globals = self.globals.write().unwrap();
        globals.insert(global_name, global.clone());
        
        P(Value{
qinsoon's avatar
qinsoon committed
99 100
            id: id,
            name: Some(global_name),
qinsoon's avatar
qinsoon committed
101
            ty: P(MuType::new(self.next_id(), MuType_::iref(ty))),
qinsoon's avatar
qinsoon committed
102 103 104 105
            v: Value_::Global(global.clone())
        })
    }
    
qinsoon's avatar
qinsoon committed
106 107 108
    pub fn declare_type(&self, id: MuID, ty: MuType_) -> P<MuType> {
        let ty = P(MuType{id: id, name: None, v: ty});
        
qinsoon's avatar
qinsoon committed
109
        let mut types = self.types.write().unwrap();
qinsoon's avatar
qinsoon committed
110
        debug_assert!(!types.contains_key(&id));
111
        
qinsoon's avatar
qinsoon committed
112
        types.insert(ty.id(), ty.clone());
113 114 115 116
        
        ty
    }
    
qinsoon's avatar
qinsoon committed
117
    pub fn declare_func_sig(&self, sig_name: MuName, ret_tys: Vec<P<MuType>>, arg_tys: Vec<P<MuType>>) -> P<MuFuncSig> {
qinsoon's avatar
qinsoon committed
118
        let mut func_sigs = self.func_sigs.write().unwrap();
qinsoon's avatar
qinsoon committed
119
        debug_assert!(!func_sigs.contains_key(&sig_name));
120 121
        
        let ret = P(MuFuncSig{ret_tys: ret_tys, arg_tys: arg_tys});
qinsoon's avatar
qinsoon committed
122
        func_sigs.insert(sig_name, ret.clone());
123 124 125 126
        
        ret
    }
    
127
    pub fn declare_func (&self, func: MuFunction) {
qinsoon's avatar
qinsoon committed
128
        info!("declare function {:?}", func);
qinsoon's avatar
qinsoon committed
129
        let mut funcs = self.funcs.write().unwrap();
qinsoon's avatar
qinsoon committed
130
        funcs.insert(func.id, RefCell::new(func));
131 132
    }
    
133
    pub fn define_func_version (&self, func_ver: MuFunctionVersion) {
qinsoon's avatar
qinsoon committed
134
        info!("define function {} with version {}", func_ver.func_id, func_ver.id);
135
        // record this version
qinsoon's avatar
qinsoon committed
136
        let func_ver_key = (func_ver.func_id, func_ver.id);
137 138 139 140 141 142 143 144 145 146 147
        {
            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
148 149
        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();
150 151 152 153 154 155 156 157
        
        if func.cur_ver.is_some() {
            let obsolete_ver = func.cur_ver.unwrap();
            func.all_vers.push(obsolete_ver);
            
            // redefinition happens here
            // do stuff
        }
qinsoon's avatar
qinsoon committed
158
        func.cur_ver = Some(func_ver.id);        
159 160
    }
    
161
    pub fn add_compiled_func (&self, func: CompiledFunction) {
qinsoon's avatar
qinsoon committed
162
        debug_assert!(self.funcs.read().unwrap().contains_key(&func.func_ver_id));
qinsoon's avatar
qinsoon committed
163

qinsoon's avatar
qinsoon committed
164
        self.compiled_funcs.write().unwrap().insert(func.func_ver_id, RefCell::new(func));
qinsoon's avatar
qinsoon committed
165 166
    }
    
qinsoon's avatar
qinsoon committed
167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184
    pub fn get_backend_type_info(&self, ty: &P<MuType>) -> BackendTypeInfo {
        {
            let read_lock = self.backend_type_info.read().unwrap();
        
            match read_lock.get(ty) {
                Some(info) => {return info.clone();},
                None => {}
            }
        }
        
        let resolved = backend::resolve_backend_type_info(ty, self);
        
        let mut write_lock = self.backend_type_info.write().unwrap();
        write_lock.insert(ty.clone(), resolved.clone());
        
        resolved        
    }
    
qinsoon's avatar
qinsoon committed
185 186 187 188 189 190 191 192 193
    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()
    }
    
    pub fn globals(&self) -> &RwLock<HashMap<MuName, P<GlobalCell>>> {
qinsoon's avatar
qinsoon committed
194 195 196
        &self.globals
    }
    
qinsoon's avatar
qinsoon committed
197
    pub fn funcs(&self) -> &RwLock<HashMap<MuID, RefCell<MuFunction>>> {
qinsoon's avatar
qinsoon committed
198
        &self.funcs
199
    }
200
    
qinsoon's avatar
qinsoon committed
201
    pub fn func_vers(&self) -> &RwLock<HashMap<(MuID, MuID), RefCell<MuFunctionVersion>>> {
202 203 204
        &self.func_vers
    }
    
qinsoon's avatar
qinsoon committed
205
    pub fn compiled_funcs(&self) -> &RwLock<HashMap<MuID, RefCell<CompiledFunction>>> {
206 207
        &self.compiled_funcs
    }
208
}