GitLab will be upgraded on June 2nd 2020 at 2.00 pm (AEDT) to 3.00 pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to local Gitlab admin team.

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