Address review feedback

This commit is contained in:
Nick Fitzgerald
2020-02-25 12:59:03 -08:00
parent 39307b2b36
commit ef0cabf8b4
15 changed files with 219 additions and 346 deletions

View File

@@ -1,14 +1,42 @@
//! Runtime library calls. Note that wasm compilers may sometimes perform these
//! inline rather than calling them, particularly when CPUs have special
//! instructions which compute them directly.
//! Runtime library calls.
//!
//! Note that Wasm compilers may sometimes perform these inline rather than
//! calling them, particularly when CPUs have special instructions which compute
//! them directly.
//!
//! These functions are called by compiled Wasm code, and therefore must take
//! certain care about some things:
//!
//! * They must always be `pub extern "C"` and should only contain basic, raw
//! i32/i64/f32/f64/pointer parameters that are safe to pass across the system
//! ABI!
//!
//! * If any nested function propagates an `Err(trap)` out to the library
//! function frame, we need to raise it. This involves some nasty and quite
//! unsafe code under the covers! Notable, after raising the trap, drops
//! **will not** be run for local variables! This can lead to things like
//! leaking `InstanceHandle`s which leads to never deallocating JIT code,
//! instances, and modules! Therefore, always use nested blocks to ensure
//! drops run before raising a trap:
//!
//! ```
//! pub extern "C" fn my_lib_function(...) {
//! let result = {
//! // Do everything in here so drops run at the end of the block.
//! ...
//! };
//! if let Err(trap) = result {
//! // Now we can safely raise the trap without leaking!
//! raise_lib_trap(trap);
//! }
//! }
//! ```
use crate::table::Table;
use crate::traphandlers::raise_lib_trap;
use crate::vmcontext::VMContext;
use wasmtime_environ::ir;
use wasmtime_environ::wasm::{
DefinedMemoryIndex, DefinedTableIndex, MemoryIndex, PassiveElemIndex, TableIndex,
};
use wasmtime_environ::wasm::{DefinedMemoryIndex, MemoryIndex, PassiveElemIndex, TableIndex};
/// Implementation of f32.ceil
pub extern "C" fn wasmtime_f32_ceil(x: f32) -> f32 {
@@ -93,7 +121,6 @@ pub extern "C" fn wasmtime_f64_nearest(x: f64) -> f64 {
}
/// Implementation of memory.grow for locally-defined 32-bit memories.
#[no_mangle]
pub unsafe extern "C" fn wasmtime_memory32_grow(
vmctx: *mut VMContext,
delta: u32,
@@ -108,7 +135,6 @@ pub unsafe extern "C" fn wasmtime_memory32_grow(
}
/// Implementation of memory.grow for imported 32-bit memories.
#[no_mangle]
pub unsafe extern "C" fn wasmtime_imported_memory32_grow(
vmctx: *mut VMContext,
delta: u32,
@@ -123,7 +149,6 @@ pub unsafe extern "C" fn wasmtime_imported_memory32_grow(
}
/// Implementation of memory.size for locally-defined 32-bit memories.
#[no_mangle]
pub unsafe extern "C" fn wasmtime_memory32_size(vmctx: *mut VMContext, memory_index: u32) -> u32 {
let instance = (&mut *vmctx).instance();
let memory_index = DefinedMemoryIndex::from_u32(memory_index);
@@ -132,7 +157,6 @@ pub unsafe extern "C" fn wasmtime_memory32_size(vmctx: *mut VMContext, memory_in
}
/// Implementation of memory.size for imported 32-bit memories.
#[no_mangle]
pub unsafe extern "C" fn wasmtime_imported_memory32_size(
vmctx: *mut VMContext,
memory_index: u32,
@@ -143,9 +167,8 @@ pub unsafe extern "C" fn wasmtime_imported_memory32_size(
instance.imported_memory_size(memory_index)
}
/// Implementation of `table.copy` when both tables are locally defined.
#[no_mangle]
pub unsafe extern "C" fn wasmtime_table_copy_defined_defined(
/// Implementation of `table.copy`.
pub unsafe extern "C" fn wasmtime_table_copy(
vmctx: *mut VMContext,
dst_table_index: u32,
src_table_index: u32,
@@ -154,87 +177,21 @@ pub unsafe extern "C" fn wasmtime_table_copy_defined_defined(
len: u32,
source_loc: u32,
) {
let dst_table_index = DefinedTableIndex::from_u32(dst_table_index);
let src_table_index = DefinedTableIndex::from_u32(src_table_index);
let source_loc = ir::SourceLoc::new(source_loc);
let instance = (&mut *vmctx).instance();
let dst_table = instance.get_defined_table(dst_table_index);
let src_table = instance.get_defined_table(src_table_index);
if let Err(trap) = Table::copy(dst_table, src_table, dst, src, len, source_loc) {
raise_lib_trap(trap);
}
}
/// Implementation of `table.copy` when the destination table is locally defined
/// and the source table is imported.
#[no_mangle]
pub unsafe extern "C" fn wasmtime_table_copy_defined_imported(
vmctx: *mut VMContext,
dst_table_index: u32,
src_table_index: u32,
dst: u32,
src: u32,
len: u32,
source_loc: u32,
) {
let dst_table_index = DefinedTableIndex::from_u32(dst_table_index);
let src_table_index = TableIndex::from_u32(src_table_index);
let source_loc = ir::SourceLoc::new(source_loc);
let instance = (&mut *vmctx).instance();
let dst_table = instance.get_defined_table(dst_table_index);
let src_table = instance.get_foreign_table(src_table_index);
if let Err(trap) = Table::copy(dst_table, src_table, dst, src, len, source_loc) {
raise_lib_trap(trap);
}
}
/// Implementation of `table.copy` when the destination table is imported
/// and the source table is locally defined.
#[no_mangle]
pub unsafe extern "C" fn wasmtime_table_copy_imported_defined(
vmctx: *mut VMContext,
dst_table_index: u32,
src_table_index: u32,
dst: u32,
src: u32,
len: u32,
source_loc: u32,
) {
let dst_table_index = TableIndex::from_u32(dst_table_index);
let src_table_index = DefinedTableIndex::from_u32(src_table_index);
let source_loc = ir::SourceLoc::new(source_loc);
let instance = (&mut *vmctx).instance();
let dst_table = instance.get_foreign_table(dst_table_index);
let src_table = instance.get_defined_table(src_table_index);
if let Err(trap) = Table::copy(dst_table, src_table, dst, src, len, source_loc) {
raise_lib_trap(trap);
}
}
/// Implementation of `table.copy` when both tables are imported.
#[no_mangle]
pub unsafe extern "C" fn wasmtime_table_copy_imported_imported(
vmctx: *mut VMContext,
dst_table_index: u32,
src_table_index: u32,
dst: u32,
src: u32,
len: u32,
source_loc: u32,
) {
let dst_table_index = TableIndex::from_u32(dst_table_index);
let src_table_index = TableIndex::from_u32(src_table_index);
let source_loc = ir::SourceLoc::new(source_loc);
let instance = (&mut *vmctx).instance();
let dst_table = instance.get_foreign_table(dst_table_index);
let src_table = instance.get_foreign_table(src_table_index);
if let Err(trap) = Table::copy(dst_table, src_table, dst, src, len, source_loc) {
let result = {
let dst_table_index = TableIndex::from_u32(dst_table_index);
let src_table_index = TableIndex::from_u32(src_table_index);
let source_loc = ir::SourceLoc::new(source_loc);
let instance = (&mut *vmctx).instance();
let dst_table = instance.get_table(dst_table_index);
let src_table = instance.get_table(src_table_index);
Table::copy(dst_table, src_table, dst, src, len, source_loc)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
/// Implementation of `table.init`.
#[no_mangle]
pub unsafe extern "C" fn wasmtime_table_init(
vmctx: *mut VMContext,
table_index: u32,
@@ -244,19 +201,19 @@ pub unsafe extern "C" fn wasmtime_table_init(
len: u32,
source_loc: u32,
) {
let table_index = TableIndex::from_u32(table_index);
let source_loc = ir::SourceLoc::new(source_loc);
let elem_index = PassiveElemIndex::from_u32(elem_index);
let instance = (&mut *vmctx).instance();
if let Err(trap) = instance.table_init(table_index, elem_index, dst, src, len, source_loc) {
let result = {
let table_index = TableIndex::from_u32(table_index);
let source_loc = ir::SourceLoc::new(source_loc);
let elem_index = PassiveElemIndex::from_u32(elem_index);
let instance = (&mut *vmctx).instance();
instance.table_init(table_index, elem_index, dst, src, len, source_loc)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
/// Implementation of `elem.drop`.
#[no_mangle]
pub unsafe extern "C" fn wasmtime_elem_drop(vmctx: *mut VMContext, elem_index: u32) {
let elem_index = PassiveElemIndex::from_u32(elem_index);
let instance = (&mut *vmctx).instance();
@@ -264,8 +221,7 @@ pub unsafe extern "C" fn wasmtime_elem_drop(vmctx: *mut VMContext, elem_index: u
}
/// Implementation of `memory.copy` for locally defined memories.
#[no_mangle]
pub unsafe extern "C" fn wasmtime_memory_copy(
pub unsafe extern "C" fn wasmtime_defined_memory_copy(
vmctx: *mut VMContext,
memory_index: u32,
dst: u32,
@@ -273,16 +229,18 @@ pub unsafe extern "C" fn wasmtime_memory_copy(
len: u32,
source_loc: u32,
) {
let memory_index = DefinedMemoryIndex::from_u32(memory_index);
let source_loc = ir::SourceLoc::new(source_loc);
let instance = (&mut *vmctx).instance();
if let Err(trap) = instance.defined_memory_copy(memory_index, dst, src, len, source_loc) {
let result = {
let memory_index = DefinedMemoryIndex::from_u32(memory_index);
let source_loc = ir::SourceLoc::new(source_loc);
let instance = (&mut *vmctx).instance();
instance.defined_memory_copy(memory_index, dst, src, len, source_loc)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
/// Implementation of `memory.copy` for imported memories.
#[no_mangle]
pub unsafe extern "C" fn wasmtime_imported_memory_copy(
vmctx: *mut VMContext,
memory_index: u32,
@@ -291,16 +249,18 @@ pub unsafe extern "C" fn wasmtime_imported_memory_copy(
len: u32,
source_loc: u32,
) {
let memory_index = MemoryIndex::from_u32(memory_index);
let source_loc = ir::SourceLoc::new(source_loc);
let instance = (&mut *vmctx).instance();
if let Err(trap) = instance.imported_memory_copy(memory_index, dst, src, len, source_loc) {
let result = {
let memory_index = MemoryIndex::from_u32(memory_index);
let source_loc = ir::SourceLoc::new(source_loc);
let instance = (&mut *vmctx).instance();
instance.imported_memory_copy(memory_index, dst, src, len, source_loc)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
/// Implementation of `memory.fill` for locally defined memories.
#[no_mangle]
pub unsafe extern "C" fn wasmtime_memory_fill(
vmctx: *mut VMContext,
memory_index: u32,
@@ -309,16 +269,18 @@ pub unsafe extern "C" fn wasmtime_memory_fill(
len: u32,
source_loc: u32,
) {
let memory_index = DefinedMemoryIndex::from_u32(memory_index);
let source_loc = ir::SourceLoc::new(source_loc);
let instance = (&mut *vmctx).instance();
if let Err(trap) = instance.defined_memory_fill(memory_index, dst, val, len, source_loc) {
let result = {
let memory_index = DefinedMemoryIndex::from_u32(memory_index);
let source_loc = ir::SourceLoc::new(source_loc);
let instance = (&mut *vmctx).instance();
instance.defined_memory_fill(memory_index, dst, val, len, source_loc)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}
/// Implementation of `memory.fill` for imported memories.
#[no_mangle]
pub unsafe extern "C" fn wasmtime_imported_memory_fill(
vmctx: *mut VMContext,
memory_index: u32,
@@ -327,10 +289,13 @@ pub unsafe extern "C" fn wasmtime_imported_memory_fill(
len: u32,
source_loc: u32,
) {
let memory_index = MemoryIndex::from_u32(memory_index);
let source_loc = ir::SourceLoc::new(source_loc);
let instance = (&mut *vmctx).instance();
if let Err(trap) = instance.imported_memory_fill(memory_index, dst, val, len, source_loc) {
let result = {
let memory_index = MemoryIndex::from_u32(memory_index);
let source_loc = ir::SourceLoc::new(source_loc);
let instance = (&mut *vmctx).instance();
instance.imported_memory_fill(memory_index, dst, val, len, source_loc)
};
if let Err(trap) = result {
raise_lib_trap(trap);
}
}