Commit 7e5c1e7a authored by qinsoon's avatar qinsoon

[wip] fixed an exception bug: when finding a catch block, by mistake we

still restored callee-saved registers, should directly jump to it
parent c6bdd727
......@@ -470,7 +470,7 @@ impl ASMCode {
None
} else {
let mut cur = i;
while cur >= 0 {
loop {
if !asm[cur].is_symbol {
return Some(cur);
}
......@@ -481,8 +481,6 @@ impl ASMCode {
cur -= 1;
}
}
None
}
}
......
......@@ -81,7 +81,7 @@ macro_rules! FPR {
GPR_ALIAS!(RAX_ALIAS: (0, RAX) -> EAX, AX , AL, AH);
GPR_ALIAS!(RCX_ALIAS: (5, RCX) -> ECX, CX , CL, CH);
GPR_ALIAS!(RDX_ALIAS: (10, RDX) -> EDX, DX , DL, DH);
GPR_ALIAS!(RDX_ALIAS: (10,RDX) -> EDX, DX , DL, DH);
GPR_ALIAS!(RBX_ALIAS: (15,RBX) -> EBX, BX , BL, BH);
GPR_ALIAS!(RSP_ALIAS: (20,RSP) -> ESP, SP , SPL);
GPR_ALIAS!(RBP_ALIAS: (24,RBP) -> EBP, BP , BPL);
......
......@@ -102,41 +102,21 @@ pub extern fn throw_exception_internal(exception_obj: Address, last_frame_callee
rwlock_cf.frame.clone()
};
trace!("frame info: {}", frame);
// update callee saved register location
for reg in x86_64::CALLEE_SAVED_GPRs.iter() {
let reg_id = reg.id();
trace!("update callee saved register {}", reg_id);
if frame.allocated.contains_key(&reg_id) {
let offset_from_rbp = frame.allocated.get(&reg_id).unwrap().offset;
let reg_restore_addr = cursor.rbp.offset(offset_from_rbp);
trace!("update callee saved register {} with loc 0x{:x}", reg_id, reg_restore_addr);
cursor.callee_saved_locs.insert(reg_id, reg_restore_addr);
} else {
// rbp won't find a location
if reg_id == x86_64::RBP.id() {
} else {
info!("failed to find an entry for {} in current frame", reg_id);
}
}
}
// find exception block - comparing callsite with frame info
trace!("checking catch block: looking for callsite 0x{:x}", callsite);
let exception_callsites = frame.get_exception_callsites();
for &(ref possible_callsite, ref dest) in exception_callsites.iter() {
let possible_callsite_addr = possible_callsite.to_address();
trace!("..check {} at 0x{:x}", possible_callsite, possible_callsite_addr);
if callsite == possible_callsite_addr {
trace!("found catch block at {}", dest);
// found an exception block
let dest_addr = dest.to_address();
// restore callee saved register and jump to dest_addr
// prepare a plain array [rbx, rbp, r12, r13, r14, r15]
macro_rules! unpack_callee_saved_from_cursor {
($reg: expr) => {
......@@ -149,7 +129,7 @@ pub extern fn throw_exception_internal(exception_obj: Address, last_frame_callee
}
}
};
let rbx = unpack_callee_saved_from_cursor!(x86_64::RBX);
let r12 = unpack_callee_saved_from_cursor!(x86_64::R12);
let r13 = unpack_callee_saved_from_cursor!(x86_64::R13);
......@@ -157,16 +137,36 @@ pub extern fn throw_exception_internal(exception_obj: Address, last_frame_callee
let r15 = unpack_callee_saved_from_cursor!(x86_64::R15);
let rbp = cursor.rbp.as_usize() as Word;
let array = vec![rbx, rbp, r12, r13, r14, r15];
let rsp = cursor.rbp.offset(frame.cur_offset());
info!("going to restore thread to {} with RSP {}", dest_addr, rsp);
unsafe {thread::exception_restore(dest_addr, array.as_ptr(), rsp)};
unreachable!()
}
}
trace!("didnt find a catch block");
// update callee saved register location
for reg in x86_64::CALLEE_SAVED_GPRs.iter() {
let reg_id = reg.id();
trace!("update callee saved register {}", reg.name().unwrap());
if frame.allocated.contains_key(&reg_id) {
let offset_from_rbp = frame.allocated.get(&reg_id).unwrap().offset;
let reg_restore_addr = cursor.rbp.offset(offset_from_rbp);
trace!("update callee saved register {} with loc 0x{:x}", reg.name().unwrap(), reg_restore_addr);
cursor.callee_saved_locs.insert(reg_id, reg_restore_addr);
} else {
// rbp won't find a location
if reg_id == x86_64::RBP.id() {
info!("skip RBP");
} else {
info!("failed to find an entry for {} in current frame", reg.name().unwrap());
}
}
}
// keep unwinding
callsite = cursor.return_addr;
......@@ -239,7 +239,8 @@ impl fmt::Display for FrameCursor {
writeln!(f, " rbp=0x{:x}, return_addr=0x{:x}, func_id={}, func_version_id={}", self.rbp, self.return_addr, self.func_id, self.func_ver_id).unwrap();
writeln!(f, " callee_saved:").unwrap();
for (reg, addr) in self.callee_saved_locs.iter() {
writeln!(f, " #{} at 0x{:x}", reg, addr).unwrap()
let val = unsafe {addr.load::<u64>()};
writeln!(f, " #{} at 0x{:x} (value=0x{:x}", reg, addr, val).unwrap()
}
writeln!(f, "}}")
}
......
......@@ -312,7 +312,6 @@ fn throw_catch_dont_use_exception_arg() -> VM {
}
#[test]
#[ignore]
// issue: didn't restore callee-saved register correctly, temporarily ignore this test
// FIXME: fix the bug
fn test_exception_throw_catch_and_add() {
......@@ -455,13 +454,23 @@ fn create_catch_exception_and_add(vm: &VM) {
inst! ((vm, catch_and_add_v1) blk_exception_px4:
PRINTHEX ev4
);
// load and print exc_arg
let iref_int64 = vm.get_type(vm.id_of("iref_int64"));
ssa! ((vm, catch_and_add_v1) <iref_int64> exc_iref);
inst! ((vm, catch_and_add_v1) blk_exception_getiref:
exc_iref = GETIREF exc_arg
);
ssa! ((vm, catch_and_add_v1) <int64> exc_val);
inst! ((vm, catch_and_add_v1) blk_exception_load_exc:
exc_val = LOAD exc_iref (is_ptr: false, order: MemoryOrder::SeqCst)
);
inst! ((vm, catch_and_add_v1) blk_exception_px5:
PRINTHEX exc_arg
PRINTHEX exc_val
);
ssa! ((vm, catch_and_add_v1) <int64> res0);
inst! ((vm, catch_and_add_v1) blk_exception_add0:
res0 = BINOP (BinOp::Add) exc_arg ev0
res0 = BINOP (BinOp::Add) exc_val ev0
);
ssa! ((vm, catch_and_add_v1) <int64> res1);
......@@ -496,6 +505,9 @@ fn create_catch_exception_and_add(vm: &VM) {
blk_exception_px2,
blk_exception_px3,
blk_exception_px4,
blk_exception_getiref,
blk_exception_load_exc,
blk_exception_px5,
blk_exception_add0,
......
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