Update singlepass backend to support metering.

This commit is contained in:
losfair
2019-05-17 01:11:22 +08:00
parent 7e79dd2cfe
commit e7297b9465
2 changed files with 79 additions and 4 deletions

View File

@ -23,7 +23,7 @@ use wasmer_runtime_core::{
FuncIndex, FuncSig, GlobalIndex, LocalFuncIndex, LocalOrImport, MemoryIndex, SigIndex,
TableIndex, Type,
},
vm::{self, LocalGlobal, LocalTable},
vm::{self, LocalGlobal, LocalTable, INTERNALS_SIZE},
};
use wasmparser::{Operator, Type as WpType};
@ -1494,8 +1494,10 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
let a = self.assembler.as_mut().unwrap();
let op = match ev {
Event::Wasm(x) => x,
Event::WasmOwned(ref x) => x,
Event::Internal(x) => {
match x {
InternalEvent::Breakpoint(callback) => {
@ -1505,8 +1507,71 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {
.unwrap()
.insert(a.get_offset(), callback);
}
InternalEvent::FunctionBegin(_) | InternalEvent::FunctionEnd => {}
_ => unimplemented!(),
InternalEvent::FunctionBegin(_) | InternalEvent::FunctionEnd => {},
InternalEvent::GetInternal(idx) => {
let idx = idx as usize;
assert!(idx < INTERNALS_SIZE);
let tmp = self.machine.acquire_temp_gpr().unwrap();
// Load `internals` pointer.
a.emit_mov(
Size::S64,
Location::Memory(
Machine::get_vmctx_reg(),
vm::Ctx::offset_internals() as i32,
),
Location::GPR(tmp),
);
let loc = self.machine.acquire_locations(
a,
&[WpType::I64],
false,
)[0];
self.value_stack.push((loc, LocalOrTemp::Temp));
// Move internal into the result location.
Self::emit_relaxed_binop(
a,
&mut self.machine,
Assembler::emit_mov,
Size::S64,
Location::Memory(tmp, (idx * 8) as i32),
loc,
);
self.machine.release_temp_gpr(tmp);
}
InternalEvent::SetInternal(idx) => {
let idx = idx as usize;
assert!(idx < INTERNALS_SIZE);
let tmp = self.machine.acquire_temp_gpr().unwrap();
// Load `internals` pointer.
a.emit_mov(
Size::S64,
Location::Memory(
Machine::get_vmctx_reg(),
vm::Ctx::offset_internals() as i32,
),
Location::GPR(tmp),
);
let loc = get_location_released(a, &mut self.machine, self.value_stack.pop().unwrap());
// Move internal into storage.
Self::emit_relaxed_binop(
a,
&mut self.machine,
Assembler::emit_mov,
Size::S64,
loc,
Location::Memory(tmp, (idx * 8) as i32),
);
self.machine.release_temp_gpr(tmp);
}
//_ => unimplemented!(),
}
return Ok(());
}

View File

@ -35,7 +35,9 @@ extern "C" fn signal_trap_handler(
let bkpt_map = BKPT_MAP.with(|x| x.borrow().last().map(|x| x.clone()));
if let Some(bkpt_map) = bkpt_map {
if let Some(ref x) = bkpt_map.get(&(ip as usize)) {
(x)(BkptInfo {});
(x)(BkptInfo {
throw: throw,
});
return;
}
}
@ -128,6 +130,14 @@ pub fn call_protected<T>(f: impl FnOnce() -> T) -> Result<T, CallProtError> {
}
}
pub unsafe extern "C" fn throw() -> ! {
let jmp_buf = SETJMP_BUFFER.with(|buf| buf.get());
if *jmp_buf == [0; SETJMP_BUFFER_LEN] {
::std::process::abort();
}
longjmp(jmp_buf as *mut ::nix::libc::c_void, 0xffff);
}
/// Unwinds to last protected_call.
pub unsafe fn do_unwind(signum: i32, siginfo: *const c_void, ucontext: *const c_void) -> ! {
// Since do_unwind is only expected to get called from WebAssembly code which doesn't hold any host resources (locks etc.)