GitLab will continue to be upgraded from 11.4.5-ce.0 on November 25th 2019 at 4.00pm (AEDT) to 5.00pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available.

Commit 1fe63f37 authored by qinsoon's avatar qinsoon

test make_boot_image_simple should work (some path problems in the test

need to be fixed)
parent f1cec1aa
Pipeline #276 failed with stage
in 32 minutes and 26 seconds
......@@ -1046,7 +1046,7 @@ impl MuEntityHeader {
*name_guard = Some(MuEntityHeader::name_check(name));
}
fn name_check(name: MuName) -> MuName {
pub fn name_check(name: MuName) -> MuName {
if name.starts_with("@") || name.starts_with("%") {
let (_, name) = name.split_at(1);
......
......@@ -2918,50 +2918,28 @@ fn write_const_value(f: &mut File, constant: P<Value>) {
}
}
pub fn emit_context(vm: &VM) {
pub fn emit_context_with_reloc(vm: &VM,
symbols: HashMap<Address, String>,
fields : HashMap<Address, String>) {
use std::path;
use std::io::prelude::*;
use rustc_serialize::json;
debug!("---Emit VM Context---");
create_emit_directory(vm);
let mut file_path = path::PathBuf::new();
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()) {
Err(why) => panic!("couldn't create context file {}: {}", file_path.to_str().unwrap(), why),
Ok(file) => file
};
// bss
file.write_fmt(format_args!("\t.bss\n")).unwrap();
{
// put globals into bss section
// let globals = vm.globals().read().unwrap();
// for global in globals.values() {
// debug!("emit global: {}", global);
// let (size, align) = {
// let alloc_ty = {
// match global.v {
// Value_::Global(ref ty) => ty,
// _ => panic!("expected a global")
// }
// };
//
// debug!("getting type: {:?}", alloc_ty);
// let ty_info = vm.get_backend_type_info(alloc_ty.id());
// (ty_info.size, ty_info.alignment)
// };
//
// file.write_fmt(format_args!("\t{}\n", directive_globl(symbol(global.name().unwrap())))).unwrap();
// file.write_fmt(format_args!("\t{}\n", directive_comm(symbol(global.name().unwrap()), size, align))).unwrap();
// file.write("\n".as_bytes()).unwrap();
// }
}
// data
file.write("\t.data\n".as_bytes()).unwrap();
......@@ -2985,11 +2963,16 @@ pub fn emit_context(vm: &VM) {
// dump heap from globals
let global_addrs : Vec<Address> = global_locs_lock.values().map(|x| x.to_address()).collect();
debug!("going to dump these globals: {:?}", global_addrs);
let global_dump = mm::persist_heap(global_addrs);
let mut global_dump = mm::persist_heap(global_addrs);
debug!("Heap Dump from GC: {:?}", global_dump);
let ref objects = global_dump.objects;
let ref relocatable_refs = global_dump.relocatable_refs;
let ref mut relocatable_refs = global_dump.relocatable_refs;
// merge symbols with relocatable_refs
for (addr, str) in symbols {
relocatable_refs.insert(addr, str);
}
for obj_dump in objects.values() {
// .bytes xx,xx,xx,xx (between mem_start to reference_addr)
......@@ -3008,37 +2991,50 @@ pub fn emit_context(vm: &VM) {
}
// dump_label:
let dump_label = symbol(global_dump.relocatable_refs.get(&obj_dump.reference_addr).unwrap().clone());
let dump_label = symbol(relocatable_refs.get(&obj_dump.reference_addr).unwrap().clone());
file.write_fmt(format_args!("{}:\n", dump_label)).unwrap();
let base = obj_dump.reference_addr;
let mut cursor = obj_dump.reference_addr;
for ref_offset in obj_dump.reference_offsets.iter() {
let cur_ref_addr = base.plus(*ref_offset);
let end = obj_dump.mem_start.plus(obj_dump.mem_size);
assert!(base.is_aligned_to(POINTER_SIZE));
if cursor < cur_ref_addr {
// write all non-ref data
write_data_bytes(&mut file, cursor, cur_ref_addr);
}
let mut offset = 0;
// write ref with label
let load_ref = unsafe {cur_ref_addr.load::<Address>()};
if load_ref.is_zero() {
file.write("\t.quad 0\n".as_bytes()).unwrap();
} else {
let label = match global_dump.relocatable_refs.get(&load_ref) {
Some(label) => label,
None => panic!("cannot find label for address {}, it is not dumped by GC (why GC didn't trace to it)", load_ref)
};
while offset < obj_dump.mem_size {
let cur_addr = base.plus(offset);
if obj_dump.reference_offsets.contains(&offset) {
// write ref with label
let load_ref = unsafe {cur_addr.load::<Address>()};
if load_ref.is_zero() {
// write 0
file.write("\t.quad 0\n".as_bytes()).unwrap();
} else {
let label = match relocatable_refs.get(&load_ref) {
Some(label) => label,
None => panic!("cannot find label for address {}, it is not dumped by GC (why GC didn't trace to it)", load_ref)
};
file.write_fmt(format_args!("\t.quad {}\n", symbol(label.clone()))).unwrap();
}
} else if fields.contains_key(&cur_addr) {
// write uptr (or other relocatable value) with label
let label = fields.get(&cur_addr).unwrap();
file.write_fmt(format_args!("\t.quad {}\n", symbol(label.clone()))).unwrap();
} else {
// write plain word (as bytes)
let next_word_addr = cur_addr.plus(POINTER_SIZE);
if next_word_addr <= end {
write_data_bytes(&mut file, cur_addr, next_word_addr);
} else {
write_data_bytes(&mut file, cur_addr, end);
}
}
cursor = cur_ref_addr.plus(POINTER_SIZE);
offset += POINTER_SIZE;
}
// write whatever is after the last ref
write_data_bytes(&mut file, cursor, obj_dump.mem_start.plus(obj_dump.mem_size));
}
}
......@@ -3046,23 +3042,27 @@ pub fn emit_context(vm: &VM) {
trace!("start serializing vm");
{
let serialize_vm = json::encode(&vm).unwrap();
let vm_symbol = symbol("vm".to_string());
file.write_fmt(format_args!("{}\n", directive_globl(vm_symbol.clone()))).unwrap();
let escape_serialize_vm = serialize_vm.replace("\"", "\\\"");
file.write_fmt(format_args!("\t{}: .asciz \"{}\"", vm_symbol, escape_serialize_vm)).unwrap();
file.write("\n".as_bytes()).unwrap();
}
// main_thread
// let primordial = vm.primordial.read().unwrap();
// if primordial.is_some() {
// let primordial = primordial.as_ref().unwrap();
// }
// let primordial = vm.primordial.read().unwrap();
// if primordial.is_some() {
// let primordial = primordial.as_ref().unwrap();
// }
debug!("---finish---");
}
pub fn emit_context(vm: &VM) {
emit_context_with_reloc(vm, hashmap!{}, hashmap!{});
}
fn write_data_bytes(f: &mut File, from: Address, to: Address) {
use std::io::Write;
......
......@@ -2,9 +2,7 @@ extern crate hprof;
use ast::ir::*;
use vm::VM;
use std::cell::RefCell;
use std::sync::Arc;
pub mod passes;
pub mod backend;
......
......@@ -5,15 +5,8 @@
extern void* vm;
extern void mu_main(char*, int, char**);
extern void mu_trace_level_log();
int main(int argc, char** argv) {
mu_trace_level_log();
printf("main(), going to launch mu_main()\n");
char* serialize_vm = (char*) &vm;
printf("%s\n", serialize_vm);
mu_main(serialize_vm, argc, argv);
}
......@@ -34,6 +34,8 @@ extern "C" {
pub fn resolve_symbol(symbol: String) -> Address {
use std::ptr;
let symbol = MuEntityHeader::name_check(symbol);
let rtld_default = unsafe {dlopen(ptr::null(), 0)};
let ret = unsafe {dlsym(rtld_default, CString::new(symbol.clone()).unwrap().as_ptr())};
......
......@@ -102,15 +102,27 @@ pub fn link_primordial (funcs: Vec<MuName>, out: &str, vm: &VM) -> PathBuf {
ret.push(get_path_for_mu_context(vm));
// copy primoridal entry
let source = PathBuf::from(runtime::PRIMORDIAL_ENTRY);
let mut dest = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
dest.push("main.c");
let source = get_path_under_mu(runtime::PRIMORDIAL_ENTRY);
let dest = {
let mut ret = PathBuf::from(&vm.vm_options.flag_aot_emit_dir);
ret.push("main.c");
ret
};
trace!("copying from {:?} to {:?}", source, dest);
fs::copy(source.as_path(), dest.as_path()).unwrap();
// include the primordial C main
ret.push(dest);
// include mu static lib
let libmu = PathBuf::from("target/debug/libmu.a");
let libmu_path = if cfg!(debug_assertions) {
"target/debug/libmu.a"
} else {
"target/release/libmu.a"
};
let libmu = get_path_under_mu(libmu_path);
ret.push(libmu);
ret
......
......@@ -5,6 +5,7 @@ use ast::ir::*;
use vm::*;
use std::sync::Arc;
use std::path::PathBuf;
use std::process::Command;
use std::process::Output;
use std::os::unix::process::ExitStatusExt;
......@@ -48,6 +49,20 @@ pub fn exec_nocheck (mut cmd: Command) -> Output {
output
}
pub fn get_path_under_mu(str: &'static str) -> PathBuf {
use std::env;
match env::var("MU_RUST") {
Ok(v) => {
let mut ret = PathBuf::from(v);
ret.push(str);
ret
}
Err(_) => PathBuf::from(str)
}
}
#[cfg(target_os = "macos")]
pub fn get_dylib_name(name: &'static str) -> String {
format!("lib{}.dylib", name)
......
......@@ -47,7 +47,7 @@ impl Address {
pub fn align_up(&self, align: usize) -> Address {
Address((self.0 + align - 1) & !(align - 1))
}
pub fn is_aligned_to(&self, align: usize) -> bool {
self.0 % align == 0
}
......
......@@ -79,7 +79,6 @@ impl<K, V> Decodable for LinkedHashMap<K, V>
for i in 0..len {
let key = try!(d.read_map_elt_key(i, |d| Decodable::decode(d)));
let val = try!(d.read_map_elt_val(i, |d| Decodable::decode(d)));
println!("insert {}", i);
map.insert(key, val);
}
Ok(map)
......
......@@ -168,7 +168,7 @@ impl MuCtx {
}
pub fn handle_from_func(&mut self, id: MuID) -> *const APIHandle {
panic!("Not implemented")
prepare_handle(self.get_mvm().vm.handle_from_func(id))
}
pub fn handle_from_expose(&mut self, id: MuID) -> *const APIHandle {
......@@ -406,7 +406,7 @@ impl MuCtx {
}
pub fn make_boot_image(&mut self, whitelist: Vec<MuID>, primordial_func: Option<&APIHandle>, primordial_stack: Option<&APIHandle>, primordial_threadlocal: Option<&APIHandle>, sym_fields: Vec<&APIHandle>, sym_strings: Vec<String>, reloc_fields: Vec<&APIHandle>, reloc_strings: Vec<String>, output_file: String) {
panic!("Not implemented")
self.get_mvm().vm.make_boot_image(whitelist, primordial_func, primordial_stack, primordial_threadlocal, sym_fields, sym_strings, reloc_fields, reloc_strings, output_file);
}
}
......
......@@ -1976,7 +1976,14 @@ impl<'lb, 'lvm> BundleLoader<'lb, 'lvm> {
v: Instruction_::CommonInst_Unpin(0)
}
}
CMU_CI_UVM_THREAD_EXIT => {
Instruction {
hdr: hdr,
value: None,
ops: RwLock::new(vec![]),
v: Instruction_::ThreadExit
}
}
_ => unimplemented!()
}
}
......
......@@ -48,7 +48,7 @@ pub enum APIHandleValue {
// GenRef->IR->Child->Var->Global
Global(MuID),
Func,
Func(MuID),
ExpFunc,
// GenRef->IR->Child->Var->Local
......@@ -114,4 +114,11 @@ impl APIHandleValue {
_ => panic!("expected UFP handle")
}
}
pub fn as_func(&self) -> MuID {
match self {
&APIHandleValue::Func(id) => id,
_ => panic!("expected FuncRef")
}
}
}
\ No newline at end of file
......@@ -22,7 +22,6 @@ use vm::vm_options::MuLogLevel;
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
use log::LogLevel;
use std::sync::Arc;
use std::path;
use std::sync::RwLock;
use std::sync::RwLockWriteGuard;
use std::sync::atomic::{AtomicUsize, AtomicBool, ATOMIC_BOOL_INIT, ATOMIC_USIZE_INIT, Ordering};
......@@ -944,45 +943,99 @@ impl <'a> VM {
}
#[allow(unused_variables)]
pub fn make_boot_image(&mut self,
pub fn make_boot_image(&self,
whitelist: Vec<MuID>,
primordial_func: Option<&APIHandle>, primordial_stack: Option<&APIHandle>,
primordial_threadlocal: Option<&APIHandle>,
sym_fields: Vec<&APIHandle>, sym_strings: Vec<String>,
reloc_fields: Vec<&APIHandle>, reloc_strings: Vec<String>,
output_file: String) {
use rustc_serialize::json;
let compiler = Compiler::new(CompilerPolicy::default(), self);
let funcs = self.funcs().write().unwrap();
let func_vers = self.func_vers().write().unwrap();
// make sure all functions in whitelist are compiled
for &id in whitelist.iter() {
if let Some(f) = funcs.get(&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);
trace!("Making boot image...");
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)
}
None => panic!("whitelist function {} has no version defined", f)
}
}
whitelist_funcs
};
if primordial_threadlocal.is_some() {
// we are going to need to persist this threadlocal
unimplemented!()
}
// make sure only one of primordial_func or primoridial_stack is set
let has_primordial_func = primordial_func.is_some();
let has_primordial_stack = primordial_stack.is_some();
assert!(
(primordial_func.is_some() && primordial_stack.is_none())
|| (primordial_func.is_none() && primordial_stack.is_some())
// do not have promordial stack/func
(!has_primordial_func && !has_primordial_stack)
// have either stack or func
|| ((has_primordial_func && !has_primordial_stack) || (!has_primordial_func && has_primordial_stack))
);
let serialized = json::encode(self).unwrap();
unimplemented!()
// we assume client will start with a function (instead of a stack)
if has_primordial_stack {
unimplemented!()
} else {
// extract func id
let func_id = primordial_func.unwrap().v.as_func();
// make primordial thread in vm
self.make_primordial_thread(func_id, false, vec![]); // do not pass const args, use argc/argv
// emit context (serialized vm, etc)
backend::emit_context(self);
// link
self.link_boot_image(whitelist_funcs, output_file);
}
}
#[cfg(feature = "aot")]
fn link_boot_image(&self, funcs: Vec<MuID>, output_file: String) {
use testutil;
trace!("Linking boot image...");
let func_names = {
let funcs_guard = self.funcs().read().unwrap();
funcs.iter().map(|x| funcs_guard.get(x).unwrap().read().unwrap().name().unwrap()).collect()
};
trace!("functions: {:?}", func_names);
trace!("output : {}", output_file);
if output_file.ends_with("dylib") || output_file.ends_with("so") {
// compile as dynamic library
testutil::aot::link_dylib(func_names, &output_file, self);
} else {
// compile as executable
testutil::aot::link_primordial(func_names, &output_file, self);
}
trace!("Done!");
}
// -- API ---
......@@ -1197,6 +1250,15 @@ impl <'a> VM {
})
}
pub fn handle_from_func(&self, id: MuID) -> APIHandleResult {
let handle_id = self.next_id();
self.new_handle(APIHandle {
id: handle_id,
v : APIHandleValue::Func(id)
})
}
pub fn handle_from_global(&self, id: MuID) -> APIHandleResult {
let global_iref = {
let global_locs = self.global_locations.read().unwrap();
......
......@@ -989,7 +989,6 @@ def test_exception_stack_unwind():
assert fnp(100) == 10
@pytest.mark.xfail(reason='not implemented yet')
@may_spawn_proc
def test_make_boot_image_simple():
c_printf = rffi.llexternal('printf', [rffi.CCHARP], rffi.INT, _nowrapper=True)
......
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