Skip to content

Commit

Permalink
Try #450:
Browse files Browse the repository at this point in the history
  • Loading branch information
bors[bot] committed May 16, 2019
2 parents 4e5ac24 + 6aec1c4 commit a9a03ac
Show file tree
Hide file tree
Showing 12 changed files with 231 additions and 11 deletions.
1 change: 1 addition & 0 deletions lib/llvm-backend/src/code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -472,6 +472,7 @@ impl FunctionCodeGenerator<CodegenError> for LLVMFunctionCodeGenerator {
fn feed_event(&mut self, event: Event, module_info: &ModuleInfo) -> Result<(), CodegenError> {
let op = match event {
Event::Wasm(x) => x,
Event::WasmOwned(ref x) => x,
Event::Internal(_x) => {
return Ok(());
}
Expand Down
4 changes: 4 additions & 0 deletions lib/llvm-backend/src/intrinsics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ impl Intrinsics {
let stack_lower_bound_ty = i8_ty;
let memory_base_ty = i8_ty;
let memory_bound_ty = void_ty;
let internals_ty = void_ty;
let local_function_ty = i8_ptr_ty;

let anyfunc_ty = context.struct_type(
Expand Down Expand Up @@ -218,6 +219,9 @@ impl Intrinsics {
memory_bound_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
internals_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
local_function_ty
.ptr_type(AddressSpace::Generic)
.as_basic_type_enum(),
Expand Down
2 changes: 1 addition & 1 deletion lib/middleware-common/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,4 @@ authors = ["The Wasmer Engineering Team <[email protected]>"]
edition = "2018"

[dependencies]
wasmer-runtime-core = { path = "../runtime-core", version = "0.4.1" }
wasmer-runtime-core = { path = "../runtime-core" }
1 change: 1 addition & 0 deletions lib/middleware-common/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#![deny(unused_imports, unused_variables, unused_unsafe, unreachable_patterns)]

pub mod call_trace;
pub mod metering;
90 changes: 90 additions & 0 deletions lib/middleware-common/src/metering.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use wasmer_runtime_core::{
codegen::{Event, EventSink, FunctionMiddleware, InternalEvent},
module::ModuleInfo,
wasmparser::{Operator, Type as WpType},
};

pub struct Metering {
limit: u64,
current_block: u64,
}

impl Metering {
pub fn new(limit: u64) -> Metering {
Metering {
limit,
current_block: 0,
}
}
}

impl FunctionMiddleware for Metering {
type Error = String;
fn feed_event<'a, 'b: 'a>(
&mut self,
op: Event<'a, 'b>,
_module_info: &ModuleInfo,
sink: &mut EventSink<'a, 'b>,
) -> Result<(), Self::Error> {
match op {
Event::Internal(InternalEvent::FunctionBegin(_)) => {
self.current_block = 0;
}
Event::Wasm(&ref op) | Event::WasmOwned(ref op) => {
self.current_block += 1;
match *op {
Operator::Loop { .. }
| Operator::Block { .. }
| Operator::End
| Operator::If { .. }
| Operator::Else
| Operator::Unreachable
| Operator::Br { .. }
| Operator::BrTable { .. }
| Operator::BrIf { .. }
| Operator::Call { .. }
| Operator::CallIndirect { .. }
| Operator::Return => {
sink.push(Event::Internal(InternalEvent::GetInternal(0)));
sink.push(Event::WasmOwned(Operator::I64Const {
value: self.current_block as i64,
}));
sink.push(Event::WasmOwned(Operator::I64Add));
sink.push(Event::Internal(InternalEvent::SetInternal(0)));
self.current_block = 0;
}
_ => {}
}
match *op {
Operator::Br { .. }
| Operator::BrTable { .. }
| Operator::BrIf { .. }
| Operator::Call { .. }
| Operator::CallIndirect { .. } => {
sink.push(Event::Internal(InternalEvent::GetInternal(0)));
sink.push(Event::WasmOwned(Operator::I64Const {
value: self.limit as i64,
}));
sink.push(Event::WasmOwned(Operator::I64GeU));
sink.push(Event::WasmOwned(Operator::If {
ty: WpType::EmptyBlockType,
}));
sink.push(Event::Internal(InternalEvent::Breakpoint(Box::new(
move |ctx| {
eprintln!("execution limit reached");
unsafe {
(ctx.throw)();
}
},
))));
sink.push(Event::WasmOwned(Operator::End));
}
_ => {}
}
}
_ => {}
}
sink.push(op);
Ok(())
}
}
16 changes: 15 additions & 1 deletion lib/runtime-core/src/backing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,17 @@ use crate::{
},
vm,
};
use std::slice;
use std::{fmt::Debug, slice};

pub const INTERNALS_SIZE: usize = 256;

pub(crate) struct Internals(pub(crate) [u64; INTERNALS_SIZE]);

impl Debug for Internals {
fn fmt(&self, formatter: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(formatter, "Internals({:?})", &self.0[..])
}
}

/// The `LocalBacking` "owns" the memory used by all the local resources of an Instance.
/// That is, local memories, tables, and globals (as well as some additional
Expand All @@ -40,6 +50,8 @@ pub struct LocalBacking {
/// as well) are subject to change.
pub(crate) dynamic_sigindices: BoxedMap<SigIndex, vm::SigId>,
pub(crate) local_functions: BoxedMap<LocalFuncIndex, *const vm::Func>,

pub(crate) internals: Internals,
}

impl LocalBacking {
Expand All @@ -66,6 +78,8 @@ impl LocalBacking {

dynamic_sigindices,
local_functions,

internals: Internals([0; INTERNALS_SIZE]),
}
}

Expand Down
5 changes: 4 additions & 1 deletion lib/runtime-core/src/codegen.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use wasmparser::{Operator, Type as WpType};
pub enum Event<'a, 'b> {
Internal(InternalEvent),
Wasm(&'b Operator<'a>),
WasmOwned(Operator<'a>),
}

pub enum InternalEvent {
Expand All @@ -39,7 +40,9 @@ impl fmt::Debug for InternalEvent {
}
}

pub struct BkptInfo {}
pub struct BkptInfo {
pub throw: unsafe extern "C" fn() -> !,
}

pub trait ModuleCodeGenerator<FCG: FunctionCodeGenerator<E>, RM: RunnableModule, E: Debug> {
/// Creates a new module code generator.
Expand Down
2 changes: 2 additions & 0 deletions lib/runtime-core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ pub use self::module::Module;
pub use self::typed_func::Func;
use std::sync::Arc;

pub use wasmparser;

use self::cache::{Artifact, Error as CacheError};

pub mod prelude {
Expand Down
21 changes: 19 additions & 2 deletions lib/runtime-core/src/vm.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
pub use crate::backing::{ImportBacking, LocalBacking};
pub use crate::backing::{ImportBacking, LocalBacking, INTERNALS_SIZE};
use crate::{
memory::{Memory, MemoryType},
module::{ModuleInfo, ModuleInner},
Expand Down Expand Up @@ -92,6 +92,8 @@ pub struct InternalCtx {

pub memory_base: *mut u8,
pub memory_bound: usize,

pub internals: *mut [u64; INTERNALS_SIZE], // TODO: Make this dynamic?
}

#[repr(C)]
Expand Down Expand Up @@ -200,6 +202,8 @@ impl Ctx {

memory_base: mem_base,
memory_bound: mem_bound,

internals: &mut local_backing.internals.0,
},
local_functions: local_backing.local_functions.as_ptr(),

Expand Down Expand Up @@ -249,6 +253,8 @@ impl Ctx {

memory_base: mem_base,
memory_bound: mem_bound,

internals: &mut local_backing.internals.0,
},
local_functions: local_backing.local_functions.as_ptr(),

Expand Down Expand Up @@ -356,9 +362,13 @@ impl Ctx {
11 * (mem::size_of::<usize>() as u8)
}

pub fn offset_local_functions() -> u8 {
pub fn offset_internals() -> u8 {
12 * (mem::size_of::<usize>() as u8)
}

pub fn offset_local_functions() -> u8 {
13 * (mem::size_of::<usize>() as u8)
}
}

enum InnerFunc {}
Expand Down Expand Up @@ -572,6 +582,11 @@ mod vm_offset_tests {
offset_of!(InternalCtx => memory_bound).get_byte_offset(),
);

assert_eq!(
Ctx::offset_internals() as usize,
offset_of!(InternalCtx => internals).get_byte_offset(),
);

assert_eq!(
Ctx::offset_local_functions() as usize,
offset_of!(Ctx => local_functions).get_byte_offset(),
Expand Down Expand Up @@ -684,6 +699,8 @@ mod vm_ctx_tests {

dynamic_sigindices: Map::new().into_boxed_map(),
local_functions: Map::new().into_boxed_map(),

internals: crate::backing::Internals([0; crate::backing::INTERNALS_SIZE]),
};
let mut import_backing = ImportBacking {
memories: Map::new().into_boxed_map(),
Expand Down
70 changes: 67 additions & 3 deletions lib/singlepass-backend/src/codegen_x64.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};

Expand Down Expand Up @@ -1496,6 +1496,7 @@ impl FunctionCodeGenerator<CodegenError> for X64FunctionCode {

let op = match ev {
Event::Wasm(x) => x,
Event::WasmOwned(ref x) => x,
Event::Internal(x) => {
match x {
InternalEvent::Breakpoint(callback) => {
Expand All @@ -1505,8 +1506,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(());
}
Expand Down
10 changes: 9 additions & 1 deletion lib/singlepass-backend/src/protect_unix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ 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;
}
}
Expand Down Expand Up @@ -128,6 +128,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.)
Expand Down
Loading

0 comments on commit a9a03ac

Please sign in to comment.