Commit 8e6d1230 authored by qinsoon's avatar qinsoon

[wip] keep implementing exception

parent f9e3d65e
......@@ -1104,7 +1104,7 @@ impl CompilerPass for InstructionSelection {
fn start_function(&mut self, vm: &VM, func_ver: &mut MuFunctionVersion) {
debug!("{}", self.name());
self.current_frame = Some(Frame::new());
self.current_frame = Some(Frame::new(func_ver.id()));
self.current_func_start = Some({
let funcs = vm.funcs().read().unwrap();
let func = funcs.get(&func_ver.func_id).unwrap().read().unwrap();
......
......@@ -6,8 +6,6 @@ use std::collections::HashMap;
use utils::POINTER_SIZE;
use vm::VM;
type SlotID = usize;
// | previous frame ...
// |---------------
// | return address
......@@ -21,16 +19,16 @@ use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
#[derive(RustcEncodable, RustcDecodable)]
pub struct Frame {
cur_slot_id: SlotID,
func_ver_id: MuID,
cur_offset: isize, // offset to rbp
allocated: HashMap<SlotID, FrameSlot>,
pub allocated: HashMap<MuID, FrameSlot>,
}
impl Frame {
pub fn new() -> Frame {
pub fn new(func_ver_id: MuID) -> Frame {
Frame {
cur_slot_id: 0,
func_ver_id: func_ver_id,
cur_offset: - (POINTER_SIZE as isize * 1), // reserve for old RBP
allocated: HashMap::new()
}
......@@ -47,28 +45,23 @@ impl Frame {
}
fn alloc_slot(&mut self, val: &P<Value>, vm: &VM) -> &FrameSlot {
let id = self.cur_slot_id;
let id = val.id();
let ret = FrameSlot {
id: id,
offset: self.cur_offset,
value: val.clone()
};
self.cur_slot_id += 1;
self.cur_offset -= vm.get_type_size(val.ty.id()) as isize;
self.allocated.insert(id, ret);
self.allocated.get(&id).unwrap()
}
}
#[derive(RustcEncodable, RustcDecodable)]
struct FrameSlot {
id: SlotID,
offset: isize,
value: P<Value>
pub struct FrameSlot {
pub offset: isize,
pub value: P<Value>
}
impl FrameSlot {
......
use utils::Address;
use runtime::thread;
#[no_mangle]
#[cfg(target_arch = "x86_64")]
pub extern fn mu_throw_exception(exception_obj: Address) {
trace!("throwing exception: {}", exception_obj);
thread::MuThread::current_mut().exception_obj = exception_obj;
}
\ No newline at end of file
use ast::ir::*;
use compiler::machine_code::CompiledFunction;
use compiler::frame::*;
use compiler::backend::x86_64;
use utils::Address;
use utils::POINTER_SIZE;
use runtime::thread;
use std::sync::RwLock;
use std::sync::RwLockReadGuard;
use std::collections::HashMap;
#[no_mangle]
pub extern fn mu_throw_exception(exception_obj: Address) {
trace!("throwing exception: {}", exception_obj);
let mut cur_thread = thread::MuThread::current_mut();
// set exception object
cur_thread.exception_obj = exception_obj;
let cf_lock = cur_thread.vm.compiled_funcs().read().unwrap();
// rbp of current frame (mu_throw_exception(), Rust frame)
let rust_frame_rbp = unsafe {thread::get_current_frame_rbp()};
let rust_frame_return_addr = unsafe {rust_frame_rbp.plus(POINTER_SIZE).load::<Address>()};
// the return address is within throwing frame
let throw_frame_callsite = rust_frame_return_addr;
let throw_func_id = find_func_for_address(&cf_lock, throw_frame_callsite);
// skip to previous frame
// this is the frame that throws the exception
let rbp = unsafe {rust_frame_rbp.load::<Address>()};
// set cursor to throwing frame
let mut cursor = FrameCursor {
rbp: rbp,
return_addr: unsafe {rbp.plus(POINTER_SIZE).load::<Address>()},
func_id: throw_func_id,
callee_saved_locs: HashMap::new()
};
loop {
// get return address (the slot above RBP slot)
// let return_addr = unsafe {rbp.plus(POINTER_SIZE).load::<Address>()};
// check if return_addr is valid
// FIXME: should use a sentinel value here
if cursor.return_addr.is_zero() {
panic!("cannot find exception catch block, throws by {}", throw_func_id);
}
let rwlock_cf = match cf_lock.get(&cursor.func_id) {
Some(ret) => ret,
None => panic!("cannot find compiled func with func_id {}, possibly didnt find the right frame for return address", cursor.func_id)
};
let rwlock_cf = rwlock_cf.read().unwrap();
let ref frame = rwlock_cf.frame;
// update callee saved register location
for reg in x86_64::CALLEE_SAVED_GPRs.iter() {
let reg_id = 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);
cursor.callee_saved_locs.insert(reg_id, reg_restore_addr);
}
}
cursor.to_previous_frame(&cf_lock);
// find exception block (if available)
}
}
struct FrameCursor {
rbp: Address,
return_addr: Address,
func_id: MuID,
callee_saved_locs: HashMap<MuID, Address>
}
impl FrameCursor {
fn to_previous_frame(&mut self, cf: &RwLockReadGuard<HashMap<MuID, RwLock<CompiledFunction>>>) {
let previous_rbp = unsafe {self.rbp.load::<Address>()};
let previous_return_addr = unsafe {previous_rbp.plus(POINTER_SIZE).load::<Address>()};
let previous_func_id = find_func_for_address(cf, self.return_addr);
self.rbp = previous_rbp;
self.return_addr = previous_return_addr;
self.func_id = previous_func_id;
}
}
fn find_func_for_address (cf: &RwLockReadGuard<HashMap<MuID, RwLock<CompiledFunction>>>, pc_addr: Address) -> MuID {
unimplemented!()
}
\ No newline at end of file
......@@ -16,6 +16,9 @@ use std::sync::Arc;
pub extern crate gc as mm;
pub mod thread;
pub mod entrypoints;
#[cfg(target_arch = "x86_64")]
#[path = "exception_x64.rs"]
pub mod exception;
// consider using libloading crate instead of the raw c functions for dynalic libraries
......
......@@ -61,3 +61,9 @@ _swap_back_to_native_stack:
popq %rbp
ret
# _get_current_frame_rbp() -> Address
.globl _get_current_frame_rbp
_get_current_frame_rbp:
movq %rbp, %rax
ret
......@@ -207,13 +207,13 @@ pub enum MuStackState {
pub struct MuThread {
pub hdr: MuEntityHeader,
allocator: mm::Mutator,
stack: Option<Box<MuStack>>,
pub stack: Option<Box<MuStack>>,
native_sp_loc: Address,
user_tls: Option<Address>,
vm: Arc<VM>,
exception_obj: Address
pub vm: Arc<VM>,
pub exception_obj: Address
}
// this depends on the layout of MuThread
......@@ -245,6 +245,7 @@ extern "C" {
extern "C" {
fn swap_to_mu_stack(new_sp: Address, entry: Address, old_sp_loc: Address);
fn swap_back_to_native_stack(sp_loc: Address);
pub fn get_current_frame_rbp() -> Address;
}
impl MuThread {
......@@ -260,12 +261,14 @@ impl MuThread {
}
}
#[inline(always)]
pub fn current() -> &'static MuThread {
unsafe{
get_thread_local().to_ptr::<MuThread>().as_ref().unwrap()
}
}
#[inline(always)]
pub fn current_mut() -> &'static mut MuThread {
unsafe{
get_thread_local().to_ptr_mut::<MuThread>().as_mut().unwrap()
......
#![allow(dead_code)]
use std::cmp;
use std::fmt;
use std::mem;
......@@ -11,13 +13,18 @@ impl Address {
pub fn plus(&self, bytes: usize) -> Self {
Address(self.0 + bytes)
}
#[allow(dead_code)]
#[inline(always)]
pub fn sub(&self, bytes: usize) -> Self {
Address(self.0 - bytes)
}
#[inline(always)]
pub fn offset<T>(&self, offset: isize) -> Self {
pub fn offset(&self, offset: isize) -> Self {
debug_assert!((self.0 as isize) < 0);
Address((self.0 as isize + offset) as usize)
}
#[inline(always)]
pub fn shift<T>(&self, offset: isize) -> Self {
debug_assert!((self.0 as isize) < 0);
Address((self.0 as isize + mem::size_of::<T>() as isize * offset) as usize)
}
#[inline(always)]
......
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