Commit 58bcc18d authored by qinsoon's avatar qinsoon

add parallel compilation (but it doesnt improve compilation time much,

we might be blocked by certain lock. should further check this)
parent 9f41288e
Pipeline #1182 canceled with stages
in 166 minutes and 41 seconds
......@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment