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
Pipeline #161 failed with stage
in 16 minutes and 50 seconds
......@@ -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,35 +23,35 @@ 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) = (
bit_utils::lower_bits(hdr, REF_BITS_LEN),
bit_utils::lower_bits(hdr, REF_BITS_LEN),
bit_utils::test_nth_bit(hdr, SHORT_ENCODE_BIT)
);
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);
......@@ -134,4 +139,4 @@ pub extern fn mu_fastimpl_new() -> *mut CMuVM {
debug!("The C-visible CMuVM struct address: {:?}", c_mvm);
c_mvm
}
}
\ No newline at end of file
......@@ -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> {
......@@ -195,6 +199,13 @@ impl Encodable for VM {
try!(s.emit_struct_field("is_running", field_i, |s| self.is_running.load(Ordering::SeqCst).encode(s)));
}
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");
......@@ -315,9 +326,14 @@ impl Decodable for VM {
// primordial
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| {
......@@ -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,37 +376,46 @@ 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()),
constants: RwLock::new(HashMap::new()),
types: RwLock::new(HashMap::new()),
backend_type_info: RwLock::new(HashMap::new()),
globals: RwLock::new(HashMap::new()),
func_sigs: RwLock::new(HashMap::new()),
func_vers: RwLock::new(HashMap::new()),
funcs: RwLock::new(HashMap::new()),
compiled_funcs: RwLock::new(HashMap::new()),
primordial: RwLock::new(None)
};
{
let mut types = ret.types.write().unwrap();
for ty in INTERNAL_TYPES.iter() {
types.insert(ty.id(), ty.clone());
}
}
ret.is_running.store(false, Ordering::SeqCst);
// Does not need SeqCst.
......@@ -401,21 +427,42 @@ impl <'a> VM {
// If the client needs to create client-level threads, however, the client should properly
// 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 {