...
 
Commits (1)
......@@ -58,6 +58,7 @@ docopt = "*"
petgraph = "*"
extprim = "*"
num-traits = "*"
scoped-pool = "*"
#built = "0.1"
[target.aarch64-unknown-linux-gnu.dependencies]
......
......@@ -31,11 +31,14 @@ extern crate maplit;
extern crate field_offset;
extern crate extprim;
extern crate num;
extern crate scoped_pool;
#[macro_use]
pub extern crate mu_ast as ast;
#[macro_use]
pub extern crate mu_utils as utils;
pub extern crate mu_gc as gc;
pub mod vm;
pub mod compiler;
pub mod runtime;
......
......@@ -1113,6 +1113,7 @@ impl<'a> VM {
info!("Making boot image...");
// Only store name info for whitelisted entities
info!("trim name/id map due to whitelisted entities...");
{
let mut new_id_name_map = HashMap::<MuID, MuName>::with_capacity(whitelist.len());
let mut new_name_id_map = HashMap::<MuName, MuID>::with_capacity(whitelist.len());
......@@ -1131,35 +1132,57 @@ impl<'a> VM {
*id_name_map = new_id_name_map;
*name_id_map = new_name_id_map;
}
// compile the whitelist functions
// trim whitelist so it only contains functions
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);
}
}
None => panic!("whitelist function {} has no version defined", f)
}
}
}
whitelist_funcs
};
// compile the whitelist functions
info!("compiling whitelist functions...");
{
use scoped_pool::Pool;
let n_compiler_threads = self.vm_options.flag_compiler_nthreads;
assert!(n_compiler_threads >= 1);
let pool = Pool::new(n_compiler_threads);
pool.scoped(|scope| for &id in whitelist_funcs.iter() {
scope.execute(move || {
let compiler = Compiler::new(CompilerPolicy::default(), self);
let funcs = self.funcs().read().expect("failed to get funcs lock");
let func_vers = self.func_vers()
.read()
.expect("failed to get func vers lock");
if let Some(f) = funcs.get(&id) {
let f: &MuFunction = &f.read().expect("failed to get function lock");
match f.cur_ver {
Some(fv_id) => {
let mut func_ver = func_vers
.get(&fv_id)
.unwrap()
.write()
.expect("failed to get func ver lock");
if !func_ver.is_compiled() {
compiler.compile(&mut func_ver);
}
}
None => panic!("whitelist function {} has no version defined", f)
}
}
});
});
};
if primordial_threadlocal.is_some() {
// we are going to need to persist this threadlocal
unimplemented!()
......@@ -1175,6 +1198,7 @@ impl<'a> VM {
name a entry function instead"
)
} else {
info!("set primordial thread...");
if has_primordial_func {
// extract func id
let func_id = primordial_func.unwrap().v.as_funcref();
......@@ -1185,43 +1209,45 @@ impl<'a> VM {
} else {
warn!("no entry function is passed");
}
}
// deal with relocation symbols, zip the two vectors into a hashmap
assert_eq!(sym_fields.len(), sym_strings.len());
let symbols: HashMap<Address, MuName> = sym_fields
info!("emit context...");
// deal with relocation symbols, zip the two vectors into a hashmap
assert_eq!(sym_fields.len(), sym_strings.len());
let symbols: HashMap<Address, MuName> = sym_fields
.into_iter()
.map(|handle| handle.v.as_address())
.zip(sym_strings.into_iter())
.collect();
// deal with relocation fields
// zip the two vectors into a hashmap, and add fields for pending funcref stores
assert_eq!(reloc_fields.len(), reloc_strings.len());
let fields = {
// init reloc fields with client-supplied field/symbol pair
let mut reloc_fields: HashMap<Address, MuName> = reloc_fields
.into_iter()
.map(|handle| handle.v.as_address())
.zip(sym_strings.into_iter())
.zip(reloc_strings.into_iter())
.collect();
// deal with relocation fields
// zip the two vectors into a hashmap, and add fields for pending funcref stores
assert_eq!(reloc_fields.len(), reloc_strings.len());
let fields = {
// init reloc fields with client-supplied field/symbol pair
let mut reloc_fields: HashMap<Address, MuName> = reloc_fields
.into_iter()
.map(|handle| handle.v.as_address())
.zip(reloc_strings.into_iter())
.collect();
// 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() {
reloc_fields.insert(addr, vl.to_relocatable());
}
// 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() {
reloc_fields.insert(addr, vl.to_relocatable());
}
}
reloc_fields
};
reloc_fields
};
// emit context (persist vm, etc)
backend::emit_context_with_reloc(self, symbols, fields);
// emit context (persist vm, etc)
backend::emit_context_with_reloc(self, symbols, fields);
// link
self.link_boot_image(whitelist_funcs, extra_sources_to_link, output_file);
}
// link
info!("link boot image...");
self.link_boot_image(whitelist_funcs, extra_sources_to_link, output_file);
}
/// links boot image (generates a dynamic library is the specified output file
......
......@@ -35,6 +35,7 @@ Compiler:
--disable-regalloc-validate disable register allocation validation
--disable-ir-validate disable IR validation
--emit-debug-info emit debugging information
--compiler-nthreads=<n> number of threads for parallel compilation [default: 4]
AOT Compiler:
--aot-emit-dir=<dir> the emit directory for ahead-of-time compiling
......@@ -65,6 +66,7 @@ pub struct VMOptions {
pub flag_disable_regalloc_validate: bool,
pub flag_disable_ir_validate: bool,
pub flag_emit_debug_info: bool,
pub flag_compiler_nthreads: usize,
// AOT compiler
pub flag_aot_emit_dir: String,
......@@ -81,6 +83,7 @@ pub struct VMOptions {
// The fields need to be listed here in the order rust stores them in
rodal_struct!(VMOptions {
flag_compiler_nthreads,
flag_aot_emit_dir,
flag_bootimage_external_lib,
flag_bootimage_external_libpath,
......