Commit 45882207 authored by qinsoon's avatar qinsoon

impl fake_mu_thread (not tested at all!!!)

going to test it with test_jit suite
parent 8f4e6891
......@@ -84,3 +84,30 @@ begin_func exception_restore
movq %rdx, %rsp
jmpq *%rdi
end_func exception_restore
# fake_swap_mu_thread(old_sp_loc: Address)
# %rdi
# (we do not actually swap stack, but we make the stack the same
# as if they are native stack that have been swapped out, so that
# when THREADEXIT (swap_back_to_native_stack) is called, we won't panic
# this function is untested!!!
begin_func fake_swap_mu_thread
# save return address
movq (%rsp), %rax
pushq %rbp
movq %rsp, %rbp
pushq %rbx
pushq %r12
pushq %r13
pushq %r14
pushq %r15
# save old sp to thread field
movq %rsp, 0(%rdi)
# return to caller, but preserve those pushed values (since THREADEXIT will pick them up)
pushq %rax
ret
\ No newline at end of file
......@@ -30,9 +30,9 @@ impl_mu_entity!(MuStack);
#[repr(C)]
pub struct MuStack {
pub hdr: MuEntityHeader,
func_addr: ValueLocation,
func_id: MuID,
// address, id
func: Option<(ValueLocation, MuID)>,
size: ByteSize,
// lo addr hi addr
......@@ -50,11 +50,9 @@ pub struct MuStack {
bp : Address,
ip : Address,
exception_obj : Option<Address>,
state: MuStackState,
#[allow(dead_code)]
mmap : memmap::Mmap
mmap : Option<memmap::Mmap>
}
impl MuStack {
......@@ -87,8 +85,7 @@ impl MuStack {
MuStack {
hdr: MuEntityHeader::unnamed(id),
func_addr: func_addr,
func_id: func.id(),
func: Some((func_addr, func.id())),
state: MuStackState::Ready(func.sig.arg_tys.clone()),
......@@ -102,9 +99,7 @@ impl MuStack {
bp: upper_bound,
ip: unsafe {Address::zero()},
exception_obj: None,
mmap: anon_mmap
mmap: Some(anon_mmap)
}
}
......@@ -245,6 +240,7 @@ extern "C" {
#[link(name = "swap_stack")]
extern "C" {
fn swap_to_mu_stack(new_sp: Address, entry: Address, old_sp_loc: Address);
fn fake_swap_mu_thread(old_sp_loc: Address);
fn muentry_swap_back_to_native_stack(sp_loc: Address);
pub fn get_current_frame_rbp() -> Address;
pub fn exception_restore(dest: Address, callee_saved: *const Word, rsp: Address) -> !;
......@@ -276,6 +272,72 @@ impl MuThread {
muentry_get_thread_local().to_ptr_mut::<MuThread>().as_mut().unwrap()
}
}
pub unsafe fn current_thread_as_mu_thread(threadlocal: Address, vm: Arc<VM>) {
use std::usize;
let user_tls = {
if threadlocal.is_zero() {
None
} else {
Some(threadlocal)
}
};
// fake a stack for current thread
let fake_mu_stack_for_cur = Box::new(MuStack {
hdr: MuEntityHeader::unnamed(vm.next_id()),
func: None,
state: MuStackState::Active,
// we do not know anything about current stack
// treat it as max size
size: usize::MAX,
overflow_guard: unsafe {Address::zero()},
lower_bound: unsafe {Address::zero()},
upper_bound: unsafe {Address::max()},
underflow_guard: unsafe {Address::max()},
// these will only be used when stack is not active (we still save to these fields)
// their values do not matter now
sp: unsafe {Address::zero()},
bp: unsafe {Address::zero()},
ip: unsafe {Address::zero()},
// we are not responsible for keeping the memory alive
mmap: None,
});
let fake_mu_thread = MuThread {
hdr: MuEntityHeader::unnamed(vm.next_id()),
// valid allocator and stack
allocator: mm::new_mutator(),
stack: Some(fake_mu_stack_for_cur),
// we do not need native_sp_loc (we do not expect the thread to call
native_sp_loc: unsafe {Address::zero()},
user_tls: user_tls,
vm: vm,
exception_obj: unsafe {Address::zero()}
};
let ptr_fake_mu_thread : *mut MuThread = Box::into_raw(Box::new(fake_mu_thread));
// set thread local
unsafe {set_thread_local(ptr_fake_mu_thread)};
// let addr = unsafe {muentry_get_thread_local()};
// let sp_threadlocal_loc = addr.plus(*NATIVE_SP_LOC_OFFSET);
//
// unsafe {
// fake_swap_mu_thread(sp_threadlocal_loc);
// }
debug!("returned to Rust thread (fake muthread)");
}
pub fn new_thread_normal(mut stack: Box<MuStack>, threadlocal: Address, vals: Vec<ValueLocation>, vm: Arc<VM>) -> JoinHandle<()> {
let user_tls = {
......@@ -290,13 +352,13 @@ impl MuThread {
stack.runtime_load_args(vals);
MuThread::mu_thread_launch(vm.next_id(), stack, user_tls, vm)
}
}
#[no_mangle]
#[allow(unused_variables)]
pub extern fn mu_thread_launch(id: MuID, stack: Box<MuStack>, user_tls: Option<Address>, vm: Arc<VM>) -> JoinHandle<()> {
let new_sp = stack.sp;
let entry = runtime::resolve_symbol(vm.name_of(stack.func_id));
let entry = runtime::resolve_symbol(vm.name_of(stack.func.as_ref().unwrap().1));
debug!("entry : 0x{:x}", entry);
match thread::Builder::new().name(format!("Mu Thread #{}", id)).spawn(move || {
......
......@@ -58,6 +58,7 @@ fn link_dylib_internal (files: Vec<PathBuf>, out: PathBuf) -> PathBuf {
for obj in object_files {
gcc.arg(obj.as_os_str());
}
gcc.arg("-o");
gcc.arg(out.as_os_str());
......
......@@ -86,6 +86,11 @@ impl Address {
pub unsafe fn zero() -> Address {
Address(0)
}
#[inline(always)]
pub unsafe fn max() -> Address {
use std::usize;
Address(usize::MAX)
}
}
impl PartialOrd for Address {
......
......@@ -7,6 +7,8 @@ use self::mu::ast::ir::*;
use self::mu::ast::inst::*;
use self::mu::vm::*;
use self::mu::compiler::*;
use self::mu::runtime::thread::MuThread;
use self::mu::utils::Address;
use std::sync::Arc;
use std::sync::RwLock;
......@@ -38,6 +40,43 @@ fn test_instruction_new() {
aot::execute(executable);
}
#[allow(dead_code)]
//#[test]
// The test won't work, since the generated dylib wants to use 'alloc_slow'.
// but in current process, there is no 'alloc_slow' (rust mangles it)
// The solution would be starting mu vm with libmu.so, then create IR from there.
// test_jit should contains a test for it. So I do not test it here
fn test_instruction_new_on_cur_thread() {
VM::start_logging_trace();
// compile
let vm = Arc::new(alloc_new());
let compiler = Compiler::new(CompilerPolicy::default(), vm.clone());
let func_id = vm.id_of("alloc_new");
{
let funcs = vm.funcs().read().unwrap();
let func = funcs.get(&func_id).unwrap().read().unwrap();
let func_vers = vm.func_vers().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
backend::emit_context(&vm);
// link
let libname = &format!("liballoc_new_on_cur_thraed.dylib");
let dylib = aot::link_dylib(vec![Mu("alloc_new")], libname);
let lib = libloading::Library::new(dylib.as_os_str()).unwrap();
unsafe {
MuThread::current_thread_as_mu_thread(Address::zero(), vm.clone());
let func : libloading::Symbol<unsafe extern fn() -> ()> = lib.get(b"alloc_new").unwrap();
func();
}
}
#[allow(unused_variables)]
pub fn alloc_new() -> VM {
let vm = VM::new();
......
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