GitLab will be upgraded on June 2nd 2020 at 2.00 pm (AEDT) to 3.00 pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to local Gitlab admin team.

Commit f79120b2 authored by qinsoon's avatar qinsoon

add VMOptions

1. see vm/vm_options.rs for usage and default values
2. added mu_fastimpl_new_with_opts under vm/api/api_impl/muvm.rs
parent 05e7b1cc
......@@ -32,3 +32,4 @@ memsec = "0.1.9"
rustc-serialize = "*"
time = "0.1.34"
maplit = "0.1.4"
docopt = "0.6"
\ No newline at end of file
......@@ -21,6 +21,6 @@ impl CompilerPass for InstructionSelection {
#[allow(unused_variables)]
fn start_function(&mut self, vm: &VM, func: &mut MuFunctionVersion) {
println!("{}", self.name());
debug!("{}", self.name());
}
}
#![allow(unused_variables)]
use compiler::backend::AOT_EMIT_CONTEXT_FILE;
use compiler::backend::AOT_EMIT_DIR;
use compiler::backend::RegGroup;
use utils::ByteSize;
use compiler::backend::x86_64;
......@@ -1525,22 +1524,22 @@ impl CodeGenerator for ASMCodeGen {
}
fn print_cur_code(&self) {
println!("");
debug!("");
if self.cur.is_some() {
let code = self.cur.as_ref().unwrap();
println!("code for {}: ", code.name);
debug!("code for {}: ", code.name);
let n_insts = code.code.len();
for i in 0..n_insts {
let ref line = code.code[i];
println!("#{}\t{}", i, line.code);
debug!("#{}\t{}", i, line.code);
}
} else {
println!("no current code");
debug!("no current code");
}
println!("");
debug!("");
}
fn start_block(&mut self, block_name: MuName) {
......@@ -2532,9 +2531,9 @@ impl CodeGenerator for ASMCodeGen {
}
}
fn create_emit_directory() {
fn create_emit_directory(vm: &VM) {
use std::fs;
match fs::create_dir(AOT_EMIT_DIR) {
match fs::create_dir(&vm.vm_options.flag_aot_emit_dir) {
Ok(_) => {},
Err(_) => {}
}
......@@ -2554,10 +2553,10 @@ pub fn emit_code(fv: &mut MuFunctionVersion, vm: &VM) {
let code = cf.mc.as_ref().unwrap().emit();
// create 'emit' directory
create_emit_directory();
create_emit_directory(vm);
let mut file_path = path::PathBuf::new();
file_path.push(AOT_EMIT_DIR);
file_path.push(&vm.vm_options.flag_aot_emit_dir);
file_path.push(func.name().unwrap().to_string() + ".s");
let mut file = match File::create(file_path.as_path()) {
Err(why) => panic!("couldn't create emission file {}: {}", file_path.to_str().unwrap(), why),
......@@ -2566,7 +2565,7 @@ pub fn emit_code(fv: &mut MuFunctionVersion, vm: &VM) {
match file.write_all(code.as_slice()) {
Err(why) => panic!("couldn'd write to file {}: {}", file_path.to_str().unwrap(), why),
Ok(_) => println!("emit code to {}", file_path.to_str().unwrap())
Ok(_) => info!("emit code to {}", file_path.to_str().unwrap())
}
}
......@@ -2577,10 +2576,10 @@ pub fn emit_context(vm: &VM) {
use rustc_serialize::json;
debug!("---Emit VM Context---");
create_emit_directory();
create_emit_directory(vm);
let mut file_path = path::PathBuf::new();
file_path.push(AOT_EMIT_DIR);
file_path.push(&vm.vm_options.flag_aot_emit_dir);
file_path.push(AOT_EMIT_CONTEXT_FILE);
let mut file = match File::create(file_path.as_path()) {
......
......@@ -8,7 +8,6 @@ use utils::ByteSize;
pub type Word = usize;
pub const WORD_SIZE : ByteSize = 8;
pub const AOT_EMIT_DIR : &'static str = "emit";
pub const AOT_EMIT_CONTEXT_FILE : &'static str = "context.s";
// this is not full name, but pro/epilogue name is generated from this
......
......@@ -200,26 +200,26 @@ impl InterferenceGraph {
}
pub fn print(&self, context: &FunctionContext) {
println!("");
println!("Interference Graph");
debug!("");
debug!("Interference Graph");
println!("nodes:");
debug!("nodes:");
for id in self.nodes.keys() {
let val = context.get_value(*id).unwrap().value();
println!("Reg {} -> {:?}", val, self.nodes.get(&id).unwrap());
debug!("Reg {} -> {:?}", val, self.nodes.get(&id).unwrap());
}
println!("color:");
debug!("color:");
for (node, color) in self.nodes_property.iter() {
let node_val = context.get_value(self.get_temp_of(*node)).unwrap().value();
let color_val = context.get_value(color.temp).unwrap().value();
println!("Reg {} of {:?} -> Color/Reg {}", node_val, node, color_val);
debug!("Reg {} of {:?} -> Color/Reg {}", node_val, node, color_val);
}
println!("moves:");
debug!("moves:");
for mov in self.moves.iter() {
println!("Move {:?} -> {:?}", mov.from, mov.to);
debug!("Move {:?} -> {:?}", mov.from, mov.to);
}
println!("graph:");
debug!("graph:");
{
let node_to_reg_id = {
let mut ret : HashMap<Node, MuID> = HashMap::new();
......@@ -241,12 +241,12 @@ impl InterferenceGraph {
let from_val = context.get_value(*from_node).unwrap().value();
let to_val = context.get_value(*to_node).unwrap().value();
println!("Reg {} -> Reg {}", from_val, to_val);
debug!("Reg {} -> Reg {}", from_val, to_val);
}
}
}
}
println!("");
debug!("");
}
}
......
......@@ -22,7 +22,6 @@ impl <T> AddressMap<T> where T: Copy{
}
pub fn init_all (&self, init: T) {
println!("check valid");
let mut cursor = self.start;
while cursor < self.end {
......
......@@ -113,7 +113,7 @@ impl Bitmap {
};
for i in 0..nwords {
println!("{}\t0b{:64b}", i * 64, unsafe {*ptr});
debug!("{}\t0b{:64b}", i * 64, unsafe {*ptr});
ptr = unsafe{ptr.offset(1)};
}
}
......
......@@ -112,7 +112,7 @@ impl ImmixMutatorLocal {
*mutator_count_lock = *mutator_count_lock - 1;
if cfg!(debug_assertions) {
println!("destroy mutator. Now live mutators = {}", *mutator_count_lock);
debug!("destroy mutator. Now live mutators = {}", *mutator_count_lock);
}
}
......@@ -131,12 +131,9 @@ impl ImmixMutatorLocal {
#[inline(always)]
pub fn alloc(&mut self, size: usize, align: usize) -> Address {
// println!("Fastpath allocation");
let start = self.cursor.align_up(align);
let end = start.plus(size);
// println!("cursor = {:#X}, after align = {:#X}", c, start);
if end > self.limit {
let ret = self.try_alloc_from_local(size, align);
......@@ -177,8 +174,6 @@ impl ImmixMutatorLocal {
#[inline(never)]
pub fn try_alloc_from_local(&mut self, size : usize, align: usize) -> Address {
// println!("Trying to allocate from local");
if self.line < immix::LINES_IN_BLOCK {
let opt_next_available_line = {
let cur_line = self.line;
......@@ -187,17 +182,13 @@ impl ImmixMutatorLocal {
match opt_next_available_line {
Some(next_available_line) => {
// println!("next available line is {}", next_available_line);
// we can alloc from local blocks
let end_line = self.block().get_next_unavailable_line(next_available_line);
// println!("next unavailable line is {}", end_line);
self.cursor = self.block().start().plus(next_available_line << immix::LOG_BYTES_IN_LINE);
self.limit = self.block().start().plus(end_line << immix::LOG_BYTES_IN_LINE);
self.line = end_line;
// println!("{}", self);
self.cursor.memset(0, self.limit.diff(self.cursor));
for line in next_available_line..end_line {
......@@ -207,7 +198,6 @@ impl ImmixMutatorLocal {
self.alloc(size, align)
},
None => {
// println!("no availalbe line in current block");
self.alloc_from_global(size, align)
}
}
......@@ -265,14 +255,14 @@ impl ImmixMutatorLocal {
}
pub fn print_object_static(obj: Address, length: usize) {
println!("===Object {:#X} size: {} bytes===", obj, length);
debug!("===Object {:#X} size: {} bytes===", obj, length);
let mut cur_addr = obj;
while cur_addr < obj.plus(length) {
println!("Address: {:#X} {:#X}", cur_addr, unsafe {cur_addr.load::<u64>()});
debug!("Address: {:#X} {:#X}", cur_addr, unsafe {cur_addr.load::<u64>()});
cur_addr = cur_addr.plus(8);
}
println!("----");
println!("=========");
debug!("----");
debug!("=========");
}
}
......
......@@ -269,9 +269,9 @@ impl ImmixSpace {
used_blocks_lock.append(&mut live_blocks);
if cfg!(debug_assertions) {
println!("free lines = {} of {} total ({} blocks)", free_lines, self.total_blocks * immix::LINES_IN_BLOCK, self.total_blocks);
println!("usable blocks = {}", usable_blocks);
println!("full blocks = {}", full_blocks);
debug!("free lines = {} of {} total ({} blocks)", free_lines, self.total_blocks * immix::LINES_IN_BLOCK, self.total_blocks);
debug!("usable blocks = {}", usable_blocks);
debug!("full blocks = {}", full_blocks);
}
if full_blocks == self.total_blocks {
......
......@@ -82,11 +82,11 @@ pub extern fn gc_init(immix_size: usize, lo_size: usize, n_gcthreads: usize) {
};
*MY_GC.write().unwrap() = Some(GC {immix_space: immix_space, lo_space: lo_space});
println!("heap is {} bytes (immix: {} bytes, lo: {} bytes) . ", immix_size + lo_size, immix_size, lo_size);
info!("heap is {} bytes (immix: {} bytes, lo: {} bytes) . ", immix_size + lo_size, immix_size, lo_size);
// gc threads
heap::gc::GC_THREADS.store(n_gcthreads, Ordering::SeqCst);
println!("{} gc threads", n_gcthreads);
info!("{} gc threads", n_gcthreads);
// init object model
objectmodel::init();
......
......@@ -23,7 +23,7 @@ pub fn flip_mark_state() {
#[allow(unused_variables)]
pub fn print_object(obj: Address, space_start: Address, trace_map: *mut u8, alloc_map: *mut u8) {
let mut cursor = obj;
println!("OBJECT 0x{:x}", obj);
trace!("OBJECT 0x{:x}", obj);
loop {
let hdr = get_ref_byte(alloc_map, space_start, unsafe {cursor.to_object_reference()});
let (ref_bits, short_encode) = (
......@@ -32,26 +32,26 @@ pub fn print_object(obj: Address, space_start: Address, trace_map: *mut u8, allo
);
println!("0x{:x} | val: 0x{:15x} | {}, hdr: {:b}",
trace!("0x{:x} | val: 0x{:15x} | {}, hdr: {:b}",
cursor, unsafe{cursor.load::<u64>()}, interpret_hdr_for_print_object(hdr, 0), hdr);
cursor = cursor.plus(POINTER_SIZE);
println!("0x{:x} | val: 0x{:15x} | {}",
trace!("0x{:x} | val: 0x{:15x} | {}",
cursor, unsafe{cursor.load::<u64>()}, interpret_hdr_for_print_object(hdr, 1));
cursor = cursor.plus(POINTER_SIZE);
println!("0x{:x} | val: 0x{:15x} | {}",
trace!("0x{:x} | val: 0x{:15x} | {}",
cursor, unsafe{cursor.load::<u64>()}, interpret_hdr_for_print_object(hdr, 2));
cursor = cursor.plus(POINTER_SIZE);
println!("0x{:x} | val: 0x{:15x} | {}",
trace!("0x{:x} | val: 0x{:15x} | {}",
cursor, unsafe{cursor.load::<u64>()}, interpret_hdr_for_print_object(hdr, 3));
cursor = cursor.plus(POINTER_SIZE);
println!("0x{:x} | val: 0x{:15x} | {}",
trace!("0x{:x} | val: 0x{:15x} | {}",
cursor, unsafe{cursor.load::<u64>()}, interpret_hdr_for_print_object(hdr, 4));
cursor = cursor.plus(POINTER_SIZE);
println!("0x{:x} | val: 0x{:15x} | {} {}",
trace!("0x{:x} | val: 0x{:15x} | {} {}",
cursor, unsafe{cursor.load::<u64>()}, interpret_hdr_for_print_object(hdr, 5),
{
if !short_encode {
......
......@@ -13,16 +13,16 @@
__thread void* mu_tls;
void set_thread_local(void* thread) {
printf("Thread%p: setting mu_tls to %p\n", (void*) pthread_self(), thread);
// printf("Thread%p: setting mu_tls to %p\n", (void*) pthread_self(), thread);
mu_tls = thread;
}
void* muentry_get_thread_local() {
printf("Thread%p: getting mu_tls as %p\n", (void*) pthread_self(), mu_tls);
// printf("Thread%p: getting mu_tls as %p\n", (void*) pthread_self(), mu_tls);
return mu_tls;
}
void* resolve_symbol(const char* sym) {
printf("%s\n", sym);
// printf("%s\n", sym);
return dlsym(RTLD_DEFAULT, sym);
}
......@@ -165,7 +165,7 @@ impl MuStack {
let mut cursor = self.upper_bound.sub(WORD_SIZE);
let mut count = 0;
println!("0x{:x} | UPPER_BOUND", self.upper_bound);
debug!("0x{:x} | UPPER_BOUND", self.upper_bound);
while cursor >= self.lower_bound {
let val = unsafe{cursor.load::<Word>()};
print!("0x{:x} | 0x{:x} ({})", cursor, val, val);
......@@ -174,18 +174,18 @@ impl MuStack {
print!(" <- SP");
}
println!("");
debug!("");
cursor = cursor.sub(WORD_SIZE);
count += 1;
if n_entries.is_some() && count > n_entries.unwrap() {
println!("...");
debug!("...");
break;
}
}
println!("0x{:x} | LOWER_BOUND", self.lower_bound);
debug!("0x{:x} | LOWER_BOUND", self.lower_bound);
}
}
......
use testutil::*;
use ast::ir::MuName;
use runtime;
use vm::VM;
use compiler::backend;
use std::path::PathBuf;
......@@ -68,22 +69,22 @@ fn link_dylib_internal (files: Vec<PathBuf>, out: PathBuf) -> PathBuf {
out
}
fn get_path_for_mu_func (f: MuName) -> PathBuf {
let mut ret = PathBuf::from(backend::AOT_EMIT_DIR);
fn get_path_for_mu_func (f: MuName, vm: &VM) -> PathBuf {
let mut ret = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
ret.push(f);
ret.set_extension("s");
ret
}
fn get_path_for_mu_context () -> PathBuf {
let mut ret = PathBuf::from(backend::AOT_EMIT_DIR);
fn get_path_for_mu_context (vm: &VM) -> PathBuf {
let mut ret = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
ret.push(backend::AOT_EMIT_CONTEXT_FILE);
ret
}
pub fn link_primordial (funcs: Vec<MuName>, out: &str) -> PathBuf {
let emit_dir = PathBuf::from(backend::AOT_EMIT_DIR);
pub fn link_primordial (funcs: Vec<MuName>, out: &str, vm: &VM) -> PathBuf {
let emit_dir = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
let files : Vec<PathBuf> = {
use std::fs;
......@@ -92,15 +93,15 @@ pub fn link_primordial (funcs: Vec<MuName>, out: &str) -> PathBuf {
// all interested mu funcs
for func in funcs {
ret.push(get_path_for_mu_func(func));
ret.push(get_path_for_mu_func(func, vm));
}
// mu context
ret.push(get_path_for_mu_context());
ret.push(get_path_for_mu_context(vm));
// copy primoridal entry
let source = PathBuf::from(runtime::PRIMORDIAL_ENTRY);
let mut dest = PathBuf::from(backend::AOT_EMIT_DIR);
let mut dest = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
dest.push("main.c");
fs::copy(source.as_path(), dest.as_path()).unwrap();
// include the primordial C main
......@@ -129,43 +130,43 @@ pub fn execute_nocheck(executable: PathBuf) -> Output {
exec_nocheck(run)
}
pub fn link_dylib (funcs: Vec<MuName>, out: &str) -> PathBuf {
pub fn link_dylib (funcs: Vec<MuName>, out: &str, vm: &VM) -> PathBuf {
let files = {
let mut ret = vec![];
for func in funcs {
ret.push(get_path_for_mu_func(func));
ret.push(get_path_for_mu_func(func, vm));
}
ret.push(get_path_for_mu_context());
ret.push(get_path_for_mu_context(vm));
ret
};
let mut out_path = PathBuf::from(backend::AOT_EMIT_DIR);
let mut out_path = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
out_path.push(out);
link_dylib_internal(files, out_path)
}
pub fn link_dylib_with_extra_srcs(funcs: Vec<MuName>, srcs: Vec<String>, out: &str) -> PathBuf{
pub fn link_dylib_with_extra_srcs(funcs: Vec<MuName>, srcs: Vec<String>, out: &str, vm: &VM) -> PathBuf{
let files = {
let mut ret = vec![];
for func in funcs {
ret.push(get_path_for_mu_func(func));
ret.push(get_path_for_mu_func(func, vm));
}
for src in srcs {
ret.push(PathBuf::from(src));
}
ret.push(get_path_for_mu_context());
ret.push(get_path_for_mu_context(vm));
ret
};
let mut out_path = PathBuf::from(backend::AOT_EMIT_DIR);
let mut out_path = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
out_path.push(out);
link_dylib_internal(files, out_path)
......
......@@ -63,6 +63,6 @@ pub fn compile_fnc<'a>(fnc_name: &'static str, build_fnc: &'a Fn() -> VM) -> ll:
}
backend::emit_context(&vm);
let libname = &format!("lib{}.dylib", fnc_name);
let dylib = aot::link_dylib(vec![Mu(fnc_name)], libname);
let dylib = aot::link_dylib(vec![Mu(fnc_name)], libname, &vm);
ll::Library::new(dylib.as_os_str()).unwrap()
}
......@@ -22,9 +22,9 @@ impl MuVM {
/**
* Create a new micro VM instance from scratch.
*/
pub fn new() -> MuVM {
pub fn new(opts: &str) -> MuVM {
MuVM {
vm: Arc::new(VM::new()),
vm: Arc::new(VM::new_with_opts(opts)),
// Cache C strings. The C client expects `char*` from `name_of`. We assume the client
// won't call `name_of` very often, so that we don't need to initialise this hashmap on
// startup.
......@@ -92,7 +92,7 @@ impl MuVM {
func_names.push(func.name().unwrap());
}
backend::emit_context(&self.vm);
aot::link_dylib_with_extra_srcs(func_names, extra_srcs, &lib_name);
aot::link_dylib_with_extra_srcs(func_names, extra_srcs, &lib_name, &self.vm);
}
pub fn current_thread_as_mu_thread(&self, threadlocal: CMuCPtr) {
......@@ -122,9 +122,14 @@ impl MuVM {
*/
#[no_mangle]
pub extern fn mu_fastimpl_new() -> *mut CMuVM {
mu_fastimpl_new_with_opts("")
}
#[no_mangle]
pub extern fn mu_fastimpl_new_with_opts(opts: &str) -> *mut CMuVM {
info!("Creating Mu micro VM fast implementation instance...");
let mvm = Box::new(MuVM::new());
let mvm = Box::new(MuVM::new(opts));
let mvm_ptr = Box::into_raw(mvm);
debug!("The MuVM instance address: {:?}", mvm_ptr);
......
......@@ -3,6 +3,7 @@ mod api_bridge; // This is mostly auto-generatd code, and should not be used
mod api_impl; // Mostly private.
pub use self::api_impl::mu_fastimpl_new;
pub use self::api_impl::mu_fastimpl_new_with_opts;
mod deps {
pub use ast::ir::WPID;
......
......@@ -7,13 +7,15 @@ use ast::types::*;
use compiler::backend;
use compiler::backend::BackendTypeInfo;
use compiler::machine_code::CompiledFunction;
use vm::vm_options::VMOptions;
use runtime::thread::*;
use runtime::ValueLocation;
use utils::ByteSize;
use runtime::mm as gc;
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
use vm::vm_options::VMOptions;
use vm::vm_options::MuLogLevel;
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
use log::LogLevel;
use std::path;
use std::sync::RwLock;
use std::sync::atomic::{AtomicUsize, AtomicBool, ATOMIC_BOOL_INIT, ATOMIC_USIZE_INIT, Ordering};
......@@ -49,13 +51,15 @@ pub struct VM {
pub primordial: RwLock<Option<MuPrimordialThread>>,
// 11
is_running: AtomicBool,
// 12
pub vm_options: VMOptions,
// partially serialize
// 12
// 13
compiled_funcs: RwLock<HashMap<MuID, RwLock<CompiledFunction>>>,
}
const VM_SERIALIZE_FIELDS : usize = 13;
const VM_SERIALIZE_FIELDS : usize = 14;
impl Encodable for VM {
fn encode<S: Encoder> (&self, s: &mut S) -> Result<(), S::Error> {
......@@ -196,6 +200,13 @@ impl Encodable for VM {
}
field_i += 1;
// options
trace!("...serializing vm_options");
{
try!(s.emit_struct_field("vm_options", field_i, |s| self.vm_options.encode(s)));
}
field_i += 1;
// compiled_funcs
trace!("...serializing compiled_funcs");
{
......@@ -316,9 +327,14 @@ impl Decodable for VM {
let primordial = try!(d.read_struct_field("primordial", field_i, |d| Decodable::decode(d)));
field_i += 1;
// is_running
let is_running = try!(d.read_struct_field("is_running", field_i, |d| Decodable::decode(d)));
field_i += 1;
// vm_options
let vm_options = try!(d.read_struct_field("vm_options", field_i, |d| Decodable::decode(d)));
field_i += 1;
// compiled funcs
let compiled_funcs = try!(d.read_struct_field("compiled_funcs", field_i, |d| {
d.read_map(|d, len| {
......@@ -346,6 +362,7 @@ impl Decodable for VM {
func_vers: RwLock::new(func_vers),
primordial: RwLock::new(primordial),
is_running: ATOMIC_BOOL_INIT,
vm_options: vm_options,
compiled_funcs: RwLock::new(compiled_funcs),
};
......@@ -359,11 +376,20 @@ impl Decodable for VM {
impl <'a> VM {
pub fn new() -> VM {
VM::start_logging();
VM::new_internal(VMOptions::default())
}
pub fn new_with_opts(str: &str) -> VM {
VM::new_internal(VMOptions::init(str))
}
fn new_internal(options: VMOptions) -> VM {
VM::start_logging(options.flag_log_level);
let ret = VM {
next_id: ATOMIC_USIZE_INIT,
is_running: ATOMIC_BOOL_INIT,
vm_options: options,
id_name_map: RwLock::new(HashMap::new()),
name_id_map: RwLock::new(HashMap::new()),
......@@ -402,20 +428,41 @@ impl <'a> VM {
// synchronise at the time of inter-thread communication, rather than creation of the VM.
ret.next_id.store(USER_ID_START, Ordering::Relaxed);
let options = VMOptions::default();
gc::gc_init(options.immix_size, options.lo_size, options.n_gcthreads);
ret.init_vm();
ret
}
pub fn start_logging() {
VM::start_logging_trace();
fn init_vm(&self) {
// init log
VM::start_logging(self.vm_options.flag_log_level);
// init gc
{
let ref options = self.vm_options;
gc::gc_init(options.flag_gc_immixspace_size, options.flag_gc_lospace_size, options.flag_gc_nthreads);
}
}
fn start_logging(level: MuLogLevel) {
match level {
MuLogLevel::None => {},
MuLogLevel::Error => VM::start_logging_internal(LogLevel::Error),
MuLogLevel::Warn => VM::start_logging_internal(LogLevel::Warn),
MuLogLevel::Info => VM::start_logging_internal(LogLevel::Info),
MuLogLevel::Debug => VM::start_logging_internal(LogLevel::Debug),
MuLogLevel::Trace => VM::start_logging_internal(LogLevel::Trace),
}
}
pub fn start_logging_trace() {
VM::start_logging_internal(LogLevel::Trace)
}
fn start_logging_internal(level: LogLevel) {
use simple_logger;
match simple_logger::init() {
match simple_logger::init_with_level(level) {
Ok(_) => {},
Err(_) => {}
}
......@@ -424,10 +471,9 @@ impl <'a> VM {
pub fn resume_vm(serialized_vm: &str) -> VM {
use rustc_serialize::json;
let vm = json::decode(serialized_vm).unwrap();
let vm : VM = json::decode(serialized_vm).unwrap();
let options = VMOptions::default();
gc::gc_init(options.immix_size, options.lo_size, options.n_gcthreads);
vm.init_vm();
vm
}
......
extern crate rustc_serialize;
extern crate docopt;
use self::docopt::Docopt;
use std::default::Default;
use utils::ByteSize;
const USAGE: &'static str = "
zebu (mu implementation). Pass arguments as a strings to init it.
Usage:
init_mu [options]
VM:
--log-level=<level> logging level: none, error, warn, info, debug, trace [default: trace]
AOT Compilation:
--aot-emit-dir=<dir> the emit directory for ahead-of-time compiling [default: emit]
Garbage Collection:
--gc-immixspace-size=<kb> immix space size (default 65536kb = 64mb) [default: 65536]
--gc-lospace-size=<kb> large object space size (default 65536kb = 64mb) [default: 65536]
--gc-nthreads=<n> number of threads for parallel gc [default: 8]
";
#[derive(Debug, RustcDecodable, RustcEncodable)]
pub struct VMOptions {
// gc options
pub immix_size: ByteSize,
pub lo_size: ByteSize,