Commit 116ec97c authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano

Tested new idea of incrementelly creating the exception table

parent 4df89048
Pipeline #589 failed with stages
in 50 minutes and 27 seconds
......@@ -1103,16 +1103,29 @@ impl Clone for MuEntityHeader {
}
}
pub fn name_check(name: MuName) -> MuName {
let name = name.replace('.', "$");
if name.starts_with("@") || name.starts_with("%") {
let (_, name) = name.split_at(1);
// WARNING: A name starting with a '.L' will be interpreted as a local label
// (and so will not be exported to the generated file), however .globl overrides this
pub fn name_mangle(name: MuName) -> MuName {
/*if name.chars().next().unwrap().is_digit(10) {
unimplemented!();
// TODO: we could prefix every name with 'mu_', but this will break things
// that expect mu entities to be named in a certain way
}*/
// Note: we don't wan't symbols starting with this??
let name = if name.starts_with("%") {
warn!("The name {} cannot be loslessly demangled (WE SHOULDN't be passing local names to the VM anyway)", name);
name.split_at(1).0.to_string()
} else {
name
};
return name.to_string();
}
name.replace('-', "$")
}
name
pub fn name_demangle(name: MuName) -> MuName {
name.replace('$', "-")
}
......@@ -1127,7 +1140,7 @@ impl MuEntityHeader {
pub fn named(id: MuID, name: MuName) -> MuEntityHeader {
MuEntityHeader {
id: id,
name: Some(name_check(name))
name: Some(name_mangle(name))
}
}
......
......@@ -11,7 +11,7 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#[macro_use]
extern crate log;
extern crate simple_logger;
#[macro_use]
......
......@@ -3507,7 +3507,6 @@ pub fn emit_context_with_reloc(vm: &VM,
fields : HashMap<Address, String>) {
use std::path;
use std::io::prelude::*;
use rustc_serialize::json;
emit_mu_types(vm);
......
......@@ -59,16 +59,14 @@ pub extern fn throw_exception_internal(exception_obj: Address, frame_cursor: Add
trace!("\tprevious_frame_pointer: 0x{:x}", previous_frame_pointer);
trace!("\tcurrent_frame_pointer: 0x{:x}", current_frame_pointer);
let table_entry = vm.compiled_exception_table.get(&callsite);
if table_entry.is_none() {
let exception_info = vm.get_exception_callsite(callsite);
if exception_info.is_none() {
error!("Cannot find Mu callsite (i.e. we have reached a native frame), either there isn't a catch block to catch the exception or your catch block is above a native function call");
print_backtrace(start_callsite, start_frame);
unreachable!(); // The above function will not return
panic!("Uncaught Mu Exception");
}
let &(catch_address, compiled_func) = table_entry.unwrap();
let (catch_address, compiled_func) = exception_info.unwrap();
// Check for a catch block at this callsite (there won't be one on the first iteration of this loop)
if !catch_address.is_zero() {
trace!("Found catch block: 0x{:x}", catch_address);
......@@ -121,7 +119,7 @@ fn print_frame(base: Address) {
// This function may segfault or panic when it reaches the bottom of the stack
// (TODO: Determine where the bottom is without segfaulting)
fn print_backtrace(start_callsite: Address, base: Address) -> !{
fn print_backtrace(start_callsite: Address, base: Address) {
error!("BACKTRACE: ");
let cur_thread = thread::MuThread::current();
......@@ -131,9 +129,11 @@ fn print_backtrace(start_callsite: Address, base: Address) -> !{
let mut frame_count = 0;
let mut callsite = start_callsite;
let compiled_exception_table = vm.compiled_exception_table.read().unwrap();
loop {
if vm.compiled_exception_table.contains_key(&callsite) {
let &(_, compiled_func_ptr) = vm.compiled_exception_table.get(&callsite).unwrap();
let info = compiled_exception_table.get(&callsite);
if info.is_some() {
let &(_, compiled_func_ptr) = info.unwrap();
unsafe {
let ref compiled_func = *compiled_func_ptr;
......@@ -149,7 +149,7 @@ fn print_backtrace(start_callsite: Address, base: Address) -> !{
frame_pointer = get_previous_frame_pointer(frame_pointer);
if frame_pointer.is_zero() {
panic!("Uncaught Mu Exception");
return;
}
callsite = get_return_address(frame_pointer);
......
......@@ -55,6 +55,7 @@ extern "C" {
// TODO: this actually returns the name and address of the nearest symbol (of any type)
// that starts before function_addr (instead we want the nearest function symbol)
// Note: this is not expected to be called on Mu entitiees
pub fn get_function_info(function_addr: Address) -> (CName, Address) {
use std::ptr;
......@@ -81,14 +82,35 @@ pub fn get_function_info(function_addr: Address) -> (CName, Address) {
} else {
("UNKOWN".to_string(), Address::from_ptr(info.dli_saddr))
}
}
// Returns None if the address isn't the address of a symbol
pub fn resolve_address(address: Address) -> Option<MuName> {
use std::ptr;
// Rust requires this to be initialised
let mut info = Dl_info {
dli_fname: ptr::null::<c_char>(),
dli_fbase: ptr::null_mut::<c_void>(),
dli_sname: ptr::null::<c_char>(),
dli_saddr: ptr::null_mut::<c_void>(),
};
unsafe {dladdr(address.to_ptr_mut::<c_void>(), &mut info)};
let error = unsafe {dlerror()};
if !error.is_null() || info.dli_sname.is_null() || Address::from_ptr(info.dli_saddr) != address {
// No symbol located at exactly address was found
None
} else {
Some(name_demangle(unsafe { CStr::from_ptr(info.dli_sname) }.to_str().unwrap().to_string()))
}
}
pub fn resolve_symbol(symbol: String) -> Address {
pub fn resolve_symbol(symbol: MuName) -> Address {
use std::ptr;
let symbol = name_check(symbol);
let symbol = name_mangle(symbol);
let rtld_default = unsafe {dlopen(ptr::null(), 0)};
let ret = unsafe {dlsym(rtld_default, CString::new(symbol.clone()).unwrap().as_ptr())};
......
......@@ -119,6 +119,12 @@ impl MuIRBuilder {
match name {
None => {},
Some(the_name) => {
let the_name = if the_name.starts_with("@") {
the_name.split_at(1).1.to_string()
} else {
the_name
};
let old = self.id_name_map.insert(my_id, the_name);
debug_assert!(old.is_none(), "ID already exists: {}, new name: {}, old name: {}",
my_id, self.id_name_map.get(&my_id).unwrap(), old.unwrap());
......
......@@ -85,7 +85,7 @@ pub struct VM {
// Maps each callsite to a tuple of the corresponding catch blocks label (or ""_
// and the id of the containing function-version
exception_table: RwLock<HashMap<MuName, (MuName, MuID)>>,
pub exception_table: RwLock<HashMap<MuName, (MuName, MuID)>>,
// ---do not serialize---
// client may try to store funcref to the heap, so that they can load it later, and call it
......@@ -93,9 +93,9 @@ pub struct VM {
#[serde(skip)]
aot_pending_funcref_store: RwLock<HashMap<Address, ValueLocation>>,
// Same as above but once the everything have been resolved to addreses
// Same as exception_table but once everything have been resolved to addresses
#[serde(skip)]
pub compiled_exception_table: HashMap<Address, (Address, *const CompiledFunction)>
pub compiled_exception_table: RwLock<HashMap<Address, (Address, *const CompiledFunction)>>
}
unsafe impl Sync for VM {}
unsafe impl Send for VM {}
......@@ -155,7 +155,7 @@ impl <'a> VM {
primordial: RwLock::new(None),
aot_pending_funcref_store: RwLock::new(HashMap::new()),
compiled_exception_table: HashMap::new(),
compiled_exception_table: RwLock::new(HashMap::new()),
};
// insert all intenral types
......@@ -233,10 +233,48 @@ impl <'a> VM {
self.exception_table.write().unwrap().insert(callsite, (catch, fv));
}
// Todo: This uses way to many lock aqcuires (up to 4 reads and 1 write)
pub fn get_exception_callsite(&self, callsite: Address) -> Option<(Address, *const CompiledFunction)> {
{
let compiled_exception_table = self.compiled_exception_table.read().unwrap();
let table_entry = compiled_exception_table.get(&callsite);
if table_entry.is_some() {
return Some(*table_entry.unwrap());
}
};
let name = resolve_address(callsite);
if name.is_none() {
return None;
}
// Get the entry in the table
let exception_table = self.exception_table.read().unwrap();
let except_entry = exception_table.get(&name.unwrap());
if except_entry.is_none() {
return None;
}
let &(ref catch, ref fv) = except_entry.unwrap();
let compiled_funcs = self.compiled_funcs.read().unwrap();
let ref compiled_func = *compiled_funcs.get(&fv).unwrap().read().unwrap();
let catch_addr = if catch.is_empty() {
unsafe { Address::zero() }
} else {
resolve_symbol(catch.clone())
};
self.compiled_exception_table.write().unwrap().insert(callsite, (catch_addr, &*compiled_func));
Some((catch_addr, &*compiled_func))
}
pub fn resume_vm(serialized_vm: &[u8]) -> VM {
use bincode;
use std::str;
let mut vm : VM = bincode::deserialize(serialized_vm).unwrap();
let vm : VM = bincode::deserialize(serialized_vm).unwrap();
vm.init_runtime();
// restore gc types
......@@ -270,22 +308,6 @@ impl <'a> VM {
}
}
// Construct Exception table
{
let exception_table = vm.exception_table.read().unwrap();
let compiled_funcs = vm.compiled_funcs.read().unwrap();
for (callsite, &(ref catch, ref fv)) in exception_table.iter() {
let ref compiled_func = *compiled_funcs.get(fv).unwrap().read().unwrap();
let catch_addr = if catch.is_empty() {
unsafe { Address::zero() }
} else {
resolve_symbol(catch.clone())
};
vm.compiled_exception_table.insert(resolve_symbol(callsite.clone()), (catch_addr, &*compiled_func));
}
}
vm
}
......@@ -807,7 +829,7 @@ impl <'a> VM {
let mut ret = hashmap!{};
for i in 0..sym_fields.len() {
let addr = sym_fields[i].v.as_address();
ret.insert(addr, name_check(sym_strings[i].clone()));
ret.insert(addr, name_mangle(sym_strings[i].clone()));
}
ret
};
......@@ -819,14 +841,14 @@ impl <'a> VM {
// client supplied relocation fields
for i in 0..reloc_fields.len() {
let addr = reloc_fields[i].v.as_address();
ret.insert(addr, name_check(reloc_strings[i].clone()));
ret.insert(addr, name_mangle(reloc_strings[i].clone()));
}
// pending funcrefs - we want to replace them as symbol
{
let mut pending_funcref = self.aot_pending_funcref_store.write().unwrap();
for (addr, vl) in pending_funcref.drain() {
ret.insert(addr, name_check(vl.to_relocatable()));
ret.insert(addr, name_mangle(vl.to_relocatable()));
}
}
......
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