Simplify the list of builtin intrinsics Wasmtime needs
This commit slims down the list of builtin intrinsics. It removes the duplicated intrinsics for imported and locally defined items, instead always using one intrinsic for both. This was previously inconsistently applied where some intrinsics got two copies (one for imported one for local) and other intrinsics got only one copy. This does add an extra branch in intrinsics since they need to determine whether something is local or not, but that's generally much lower cost than the intrinsics themselves. This also removes the `memory32_size` intrinsic, instead inlining the codegen directly into the clif IR. This matches what the `table.size` instruction does and removes the need for a few functions on a `wasmtime_runtime::Instance`.
This commit is contained in:
@@ -184,52 +184,6 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the memory.grow function signature to call for the given index, along with the
|
|
||||||
/// translated index value to pass to it and its index in `VMBuiltinFunctionsArray`.
|
|
||||||
fn get_memory_grow_func(
|
|
||||||
&mut self,
|
|
||||||
func: &mut Function,
|
|
||||||
index: MemoryIndex,
|
|
||||||
) -> (ir::SigRef, usize, BuiltinFunctionIndex) {
|
|
||||||
if self.module.is_imported_memory(index) {
|
|
||||||
(
|
|
||||||
self.builtin_function_signatures
|
|
||||||
.imported_memory32_grow(func),
|
|
||||||
index.index(),
|
|
||||||
BuiltinFunctionIndex::imported_memory32_grow(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
self.builtin_function_signatures.memory32_grow(func),
|
|
||||||
self.module.defined_memory_index(index).unwrap().index(),
|
|
||||||
BuiltinFunctionIndex::memory32_grow(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Return the memory.size function signature to call for the given index, along with the
|
|
||||||
/// translated index value to pass to it and its index in `VMBuiltinFunctionsArray`.
|
|
||||||
fn get_memory_size_func(
|
|
||||||
&mut self,
|
|
||||||
func: &mut Function,
|
|
||||||
index: MemoryIndex,
|
|
||||||
) -> (ir::SigRef, usize, BuiltinFunctionIndex) {
|
|
||||||
if self.module.is_imported_memory(index) {
|
|
||||||
(
|
|
||||||
self.builtin_function_signatures
|
|
||||||
.imported_memory32_size(func),
|
|
||||||
index.index(),
|
|
||||||
BuiltinFunctionIndex::imported_memory32_size(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
self.builtin_function_signatures.memory32_size(func),
|
|
||||||
self.module.defined_memory_index(index).unwrap().index(),
|
|
||||||
BuiltinFunctionIndex::memory32_size(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_table_copy_func(
|
fn get_table_copy_func(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: &mut Function,
|
func: &mut Function,
|
||||||
@@ -260,47 +214,6 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
(sig, BuiltinFunctionIndex::elem_drop())
|
(sig, BuiltinFunctionIndex::elem_drop())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_memory_fill_func(
|
|
||||||
&mut self,
|
|
||||||
func: &mut Function,
|
|
||||||
memory_index: MemoryIndex,
|
|
||||||
) -> (ir::SigRef, usize, BuiltinFunctionIndex) {
|
|
||||||
if let Some(defined_memory_index) = self.module.defined_memory_index(memory_index) {
|
|
||||||
(
|
|
||||||
self.builtin_function_signatures.memory_fill(func),
|
|
||||||
defined_memory_index.index(),
|
|
||||||
BuiltinFunctionIndex::memory_fill(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
self.builtin_function_signatures.imported_memory_fill(func),
|
|
||||||
memory_index.index(),
|
|
||||||
BuiltinFunctionIndex::imported_memory_fill(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_memory_atomic_notify(
|
|
||||||
&mut self,
|
|
||||||
func: &mut Function,
|
|
||||||
memory_index: MemoryIndex,
|
|
||||||
) -> (ir::SigRef, usize, BuiltinFunctionIndex) {
|
|
||||||
if let Some(defined_memory_index) = self.module.defined_memory_index(memory_index) {
|
|
||||||
(
|
|
||||||
self.builtin_function_signatures.memory_atomic_notify(func),
|
|
||||||
defined_memory_index.index(),
|
|
||||||
BuiltinFunctionIndex::memory_atomic_notify(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
self.builtin_function_signatures
|
|
||||||
.imported_memory_atomic_notify(func),
|
|
||||||
memory_index.index(),
|
|
||||||
BuiltinFunctionIndex::imported_memory_atomic_notify(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn get_memory_atomic_wait(
|
fn get_memory_atomic_wait(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: &mut Function,
|
func: &mut Function,
|
||||||
@@ -308,38 +221,16 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
ty: ir::Type,
|
ty: ir::Type,
|
||||||
) -> (ir::SigRef, usize, BuiltinFunctionIndex) {
|
) -> (ir::SigRef, usize, BuiltinFunctionIndex) {
|
||||||
match ty {
|
match ty {
|
||||||
I32 => {
|
I32 => (
|
||||||
if let Some(defined_memory_index) = self.module.defined_memory_index(memory_index) {
|
|
||||||
(
|
|
||||||
self.builtin_function_signatures.memory_atomic_wait32(func),
|
self.builtin_function_signatures.memory_atomic_wait32(func),
|
||||||
defined_memory_index.index(),
|
memory_index.index(),
|
||||||
BuiltinFunctionIndex::memory_atomic_wait32(),
|
BuiltinFunctionIndex::memory_atomic_wait32(),
|
||||||
)
|
),
|
||||||
} else {
|
I64 => (
|
||||||
(
|
|
||||||
self.builtin_function_signatures
|
|
||||||
.imported_memory_atomic_wait32(func),
|
|
||||||
memory_index.index(),
|
|
||||||
BuiltinFunctionIndex::imported_memory_atomic_wait32(),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
I64 => {
|
|
||||||
if let Some(defined_memory_index) = self.module.defined_memory_index(memory_index) {
|
|
||||||
(
|
|
||||||
self.builtin_function_signatures.memory_atomic_wait64(func),
|
self.builtin_function_signatures.memory_atomic_wait64(func),
|
||||||
defined_memory_index.index(),
|
|
||||||
BuiltinFunctionIndex::memory_atomic_wait64(),
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
self.builtin_function_signatures
|
|
||||||
.imported_memory_atomic_wait64(func),
|
|
||||||
memory_index.index(),
|
memory_index.index(),
|
||||||
BuiltinFunctionIndex::imported_memory_atomic_wait64(),
|
BuiltinFunctionIndex::memory_atomic_wait64(),
|
||||||
)
|
),
|
||||||
}
|
|
||||||
}
|
|
||||||
x => panic!("get_memory_atomic_wait unsupported type: {:?}", x),
|
x => panic!("get_memory_atomic_wait unsupported type: {:?}", x),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1494,9 +1385,16 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
|||||||
_heap: ir::Heap,
|
_heap: ir::Heap,
|
||||||
val: ir::Value,
|
val: ir::Value,
|
||||||
) -> WasmResult<ir::Value> {
|
) -> WasmResult<ir::Value> {
|
||||||
let (func_sig, index_arg, func_idx) = self.get_memory_grow_func(&mut pos.func, index);
|
let func_sig = self
|
||||||
|
.builtin_function_signatures
|
||||||
|
.memory32_grow(&mut pos.func);
|
||||||
|
let index_arg = index.index();
|
||||||
|
|
||||||
let memory_index = pos.ins().iconst(I32, index_arg as i64);
|
let memory_index = pos.ins().iconst(I32, index_arg as i64);
|
||||||
let (vmctx, func_addr) = self.translate_load_builtin_function_address(&mut pos, func_idx);
|
let (vmctx, func_addr) = self.translate_load_builtin_function_address(
|
||||||
|
&mut pos,
|
||||||
|
BuiltinFunctionIndex::memory32_grow(),
|
||||||
|
);
|
||||||
let call_inst = pos
|
let call_inst = pos
|
||||||
.ins()
|
.ins()
|
||||||
.call_indirect(func_sig, func_addr, &[vmctx, val, memory_index]);
|
.call_indirect(func_sig, func_addr, &[vmctx, val, memory_index]);
|
||||||
@@ -1509,13 +1407,35 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
|||||||
index: MemoryIndex,
|
index: MemoryIndex,
|
||||||
_heap: ir::Heap,
|
_heap: ir::Heap,
|
||||||
) -> WasmResult<ir::Value> {
|
) -> WasmResult<ir::Value> {
|
||||||
let (func_sig, index_arg, func_idx) = self.get_memory_size_func(&mut pos.func, index);
|
let pointer_type = self.pointer_type();
|
||||||
let memory_index = pos.ins().iconst(I32, index_arg as i64);
|
let vmctx = self.vmctx(&mut pos.func);
|
||||||
let (vmctx, func_addr) = self.translate_load_builtin_function_address(&mut pos, func_idx);
|
let base = pos.ins().global_value(pointer_type, vmctx);
|
||||||
let call_inst = pos
|
let current_length_in_bytes = match self.module.defined_memory_index(index) {
|
||||||
|
Some(def_index) => {
|
||||||
|
let offset = i32::try_from(
|
||||||
|
self.offsets
|
||||||
|
.vmctx_vmmemory_definition_current_length(def_index),
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
pos.ins().load(I32, ir::MemFlags::trusted(), base, offset)
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
let offset = i32::try_from(self.offsets.vmctx_vmmemory_import_from(index)).unwrap();
|
||||||
|
let vmmemory_ptr =
|
||||||
|
pos.ins()
|
||||||
|
.load(pointer_type, ir::MemFlags::trusted(), base, offset);
|
||||||
|
pos.ins().load(
|
||||||
|
I32,
|
||||||
|
ir::MemFlags::trusted(),
|
||||||
|
vmmemory_ptr,
|
||||||
|
i32::from(self.offsets.vmmemory_definition_current_length()),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let current_length_in_pages = pos
|
||||||
.ins()
|
.ins()
|
||||||
.call_indirect(func_sig, func_addr, &[vmctx, memory_index]);
|
.udiv_imm(current_length_in_bytes, i64::from(WASM_PAGE_SIZE));
|
||||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
Ok(current_length_in_pages)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn translate_memory_copy(
|
fn translate_memory_copy(
|
||||||
@@ -1554,12 +1474,13 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
|||||||
val: ir::Value,
|
val: ir::Value,
|
||||||
len: ir::Value,
|
len: ir::Value,
|
||||||
) -> WasmResult<()> {
|
) -> WasmResult<()> {
|
||||||
let (func_sig, memory_index, func_idx) =
|
let func_sig = self.builtin_function_signatures.memory_fill(&mut pos.func);
|
||||||
self.get_memory_fill_func(&mut pos.func, memory_index);
|
let memory_index = memory_index.index();
|
||||||
|
|
||||||
let memory_index_arg = pos.ins().iconst(I32, memory_index as i64);
|
let memory_index_arg = pos.ins().iconst(I32, memory_index as i64);
|
||||||
|
|
||||||
let (vmctx, func_addr) = self.translate_load_builtin_function_address(&mut pos, func_idx);
|
let (vmctx, func_addr) = self
|
||||||
|
.translate_load_builtin_function_address(&mut pos, BuiltinFunctionIndex::memory_fill());
|
||||||
|
|
||||||
pos.ins().call_indirect(
|
pos.ins().call_indirect(
|
||||||
func_sig,
|
func_sig,
|
||||||
@@ -1724,12 +1645,16 @@ impl<'module_environment> cranelift_wasm::FuncEnvironment for FuncEnvironment<'m
|
|||||||
addr: ir::Value,
|
addr: ir::Value,
|
||||||
count: ir::Value,
|
count: ir::Value,
|
||||||
) -> WasmResult<ir::Value> {
|
) -> WasmResult<ir::Value> {
|
||||||
let (func_sig, memory_index, func_idx) =
|
let func_sig = self
|
||||||
self.get_memory_atomic_notify(&mut pos.func, memory_index);
|
.builtin_function_signatures
|
||||||
|
.memory_atomic_notify(&mut pos.func);
|
||||||
|
|
||||||
let memory_index_arg = pos.ins().iconst(I32, memory_index as i64);
|
let memory_index_arg = pos.ins().iconst(I32, memory_index.index() as i64);
|
||||||
|
|
||||||
let (vmctx, func_addr) = self.translate_load_builtin_function_address(&mut pos, func_idx);
|
let (vmctx, func_addr) = self.translate_load_builtin_function_address(
|
||||||
|
&mut pos,
|
||||||
|
BuiltinFunctionIndex::memory_atomic_notify(),
|
||||||
|
);
|
||||||
|
|
||||||
let call_inst =
|
let call_inst =
|
||||||
pos.ins()
|
pos.ins()
|
||||||
|
|||||||
@@ -5,12 +5,6 @@ macro_rules! foreach_builtin_function {
|
|||||||
$mac! {
|
$mac! {
|
||||||
/// Returns an index for wasm's `memory.grow` builtin function.
|
/// Returns an index for wasm's `memory.grow` builtin function.
|
||||||
memory32_grow(vmctx, i32, i32) -> (i32);
|
memory32_grow(vmctx, i32, i32) -> (i32);
|
||||||
/// Returns an index for wasm's imported `memory.grow` builtin function.
|
|
||||||
imported_memory32_grow(vmctx, i32, i32) -> (i32);
|
|
||||||
/// Returns an index for wasm's `memory.size` builtin function.
|
|
||||||
memory32_size(vmctx, i32) -> (i32);
|
|
||||||
/// Returns an index for wasm's imported `memory.size` builtin function.
|
|
||||||
imported_memory32_size(vmctx, i32) -> (i32);
|
|
||||||
/// Returns an index for wasm's `table.copy` when both tables are locally
|
/// Returns an index for wasm's `table.copy` when both tables are locally
|
||||||
/// defined.
|
/// defined.
|
||||||
table_copy(vmctx, i32, i32, i32, i32, i32) -> ();
|
table_copy(vmctx, i32, i32, i32, i32, i32) -> ();
|
||||||
@@ -20,10 +14,8 @@ macro_rules! foreach_builtin_function {
|
|||||||
elem_drop(vmctx, i32) -> ();
|
elem_drop(vmctx, i32) -> ();
|
||||||
/// Returns an index for wasm's `memory.copy`
|
/// Returns an index for wasm's `memory.copy`
|
||||||
memory_copy(vmctx, i32, i32, i32, i32, i32) -> ();
|
memory_copy(vmctx, i32, i32, i32, i32, i32) -> ();
|
||||||
/// Returns an index for wasm's `memory.fill` for locally defined memories.
|
/// Returns an index for wasm's `memory.fill` instruction.
|
||||||
memory_fill(vmctx, i32, i32, i32, i32) -> ();
|
memory_fill(vmctx, i32, i32, i32, i32) -> ();
|
||||||
/// Returns an index for wasm's `memory.fill` for imported memories.
|
|
||||||
imported_memory_fill(vmctx, i32, i32, i32, i32) -> ();
|
|
||||||
/// Returns an index for wasm's `memory.init` instruction.
|
/// Returns an index for wasm's `memory.init` instruction.
|
||||||
memory_init(vmctx, i32, i32, i32, i32, i32) -> ();
|
memory_init(vmctx, i32, i32, i32, i32, i32) -> ();
|
||||||
/// Returns an index for wasm's `data.drop` instruction.
|
/// Returns an index for wasm's `data.drop` instruction.
|
||||||
@@ -45,18 +37,12 @@ macro_rules! foreach_builtin_function {
|
|||||||
externref_global_get(vmctx, i32) -> (reference);
|
externref_global_get(vmctx, i32) -> (reference);
|
||||||
/// Returns an index for Wasm's `global.get` instruction for `externref`s.
|
/// Returns an index for Wasm's `global.get` instruction for `externref`s.
|
||||||
externref_global_set(vmctx, i32, reference) -> ();
|
externref_global_set(vmctx, i32, reference) -> ();
|
||||||
/// Returns an index for wasm's `memory.atomic.notify` for locally defined memories.
|
/// Returns an index for wasm's `memory.atomic.notify` instruction.
|
||||||
memory_atomic_notify(vmctx, i32, i32, i32) -> (i32);
|
memory_atomic_notify(vmctx, i32, i32, i32) -> (i32);
|
||||||
/// Returns an index for wasm's `memory.atomic.notify` for imported memories.
|
/// Returns an index for wasm's `memory.atomic.wait32` instruction.
|
||||||
imported_memory_atomic_notify(vmctx, i32, i32, i32) -> (i32);
|
|
||||||
/// Returns an index for wasm's `memory.atomic.wait32` for locally defined memories.
|
|
||||||
memory_atomic_wait32(vmctx, i32, i32, i32, i64) -> (i32);
|
memory_atomic_wait32(vmctx, i32, i32, i32, i64) -> (i32);
|
||||||
/// Returns an index for wasm's `memory.atomic.wait32` for imported memories.
|
/// Returns an index for wasm's `memory.atomic.wait64` instruction.
|
||||||
imported_memory_atomic_wait32(vmctx, i32, i32, i32, i64) -> (i32);
|
|
||||||
/// Returns an index for wasm's `memory.atomic.wait64` for locally defined memories.
|
|
||||||
memory_atomic_wait64(vmctx, i32, i32, i64, i64) -> (i32);
|
memory_atomic_wait64(vmctx, i32, i32, i64, i64) -> (i32);
|
||||||
/// Returns an index for wasm's `memory.atomic.wait64` for imported memories.
|
|
||||||
imported_memory_atomic_wait64(vmctx, i32, i32, i64, i64) -> (i32);
|
|
||||||
/// Invoked when fuel has run out while executing a function.
|
/// Invoked when fuel has run out while executing a function.
|
||||||
out_of_gas(vmctx) -> ();
|
out_of_gas(vmctx) -> ();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -386,68 +386,31 @@ impl Instance {
|
|||||||
///
|
///
|
||||||
/// Returns `None` if memory can't be grown by the specified amount
|
/// Returns `None` if memory can't be grown by the specified amount
|
||||||
/// of pages.
|
/// of pages.
|
||||||
pub(crate) fn memory_grow(
|
pub(crate) fn memory_grow(&mut self, index: MemoryIndex, delta: u32) -> Option<u32> {
|
||||||
&mut self,
|
let (idx, instance) = if let Some(idx) = self.module.defined_memory_index(index) {
|
||||||
memory_index: DefinedMemoryIndex,
|
(idx, self)
|
||||||
delta: u32,
|
} else {
|
||||||
) -> Option<u32> {
|
let import = self.imported_memory(index);
|
||||||
let limiter = unsafe { (*self.store()).limiter() };
|
unsafe {
|
||||||
let memory = self
|
let foreign_instance = (*import.vmctx).instance_mut();
|
||||||
.memories
|
let foreign_memory_def = &*import.from;
|
||||||
.get_mut(memory_index)
|
let foreign_memory_index = foreign_instance.memory_index(foreign_memory_def);
|
||||||
.unwrap_or_else(|| panic!("no memory for index {}", memory_index.index()));
|
(foreign_memory_index, foreign_instance)
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let limiter = unsafe { (*instance.store()).limiter() };
|
||||||
|
let memory = &mut instance.memories[idx];
|
||||||
|
|
||||||
let result = unsafe { memory.grow(delta, limiter) };
|
let result = unsafe { memory.grow(delta, limiter) };
|
||||||
|
let vmmemory = memory.vmmemory();
|
||||||
|
|
||||||
// Keep current the VMContext pointers used by compiled wasm code.
|
// Update the state used by wasm code in case the base pointer and/or
|
||||||
self.set_memory(memory_index, self.memories[memory_index].vmmemory());
|
// the length changed.
|
||||||
|
instance.set_memory(idx, vmmemory);
|
||||||
|
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Grow imported memory by the specified amount of pages.
|
|
||||||
///
|
|
||||||
/// Returns `None` if memory can't be grown by the specified amount
|
|
||||||
/// of pages.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
/// This and `imported_memory_size` are currently unsafe because they
|
|
||||||
/// dereference the memory import's pointers.
|
|
||||||
pub(crate) unsafe fn imported_memory_grow(
|
|
||||||
&mut self,
|
|
||||||
memory_index: MemoryIndex,
|
|
||||||
delta: u32,
|
|
||||||
) -> Option<u32> {
|
|
||||||
let import = self.imported_memory(memory_index);
|
|
||||||
let foreign_instance = (*import.vmctx).instance_mut();
|
|
||||||
let foreign_memory = &*import.from;
|
|
||||||
let foreign_index = foreign_instance.memory_index(foreign_memory);
|
|
||||||
|
|
||||||
foreign_instance.memory_grow(foreign_index, delta)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the number of allocated wasm pages.
|
|
||||||
pub(crate) fn memory_size(&self, memory_index: DefinedMemoryIndex) -> u32 {
|
|
||||||
self.memories
|
|
||||||
.get(memory_index)
|
|
||||||
.unwrap_or_else(|| panic!("no memory for index {}", memory_index.index()))
|
|
||||||
.size()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Returns the number of allocated wasm pages in an imported memory.
|
|
||||||
///
|
|
||||||
/// # Safety
|
|
||||||
/// This and `imported_memory_grow` are currently unsafe because they
|
|
||||||
/// dereference the memory import's pointers.
|
|
||||||
pub(crate) unsafe fn imported_memory_size(&self, memory_index: MemoryIndex) -> u32 {
|
|
||||||
let import = self.imported_memory(memory_index);
|
|
||||||
let foreign_instance = (&mut *import.vmctx).instance();
|
|
||||||
let foreign_memory = &mut *import.from;
|
|
||||||
let foreign_index = foreign_instance.memory_index(foreign_memory);
|
|
||||||
|
|
||||||
foreign_instance.memory_size(foreign_index)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn table_element_type(&mut self, table_index: TableIndex) -> TableElementType {
|
pub(crate) fn table_element_type(&mut self, table_index: TableIndex) -> TableElementType {
|
||||||
unsafe { (*self.get_table(table_index)).element_type() }
|
unsafe { (*self.get_table(table_index)).element_type() }
|
||||||
}
|
}
|
||||||
@@ -671,14 +634,14 @@ impl Instance {
|
|||||||
/// # Errors
|
/// # Errors
|
||||||
///
|
///
|
||||||
/// Returns a `Trap` error if the memory range is out of bounds.
|
/// Returns a `Trap` error if the memory range is out of bounds.
|
||||||
pub(crate) fn defined_memory_fill(
|
pub(crate) fn memory_fill(
|
||||||
&self,
|
&mut self,
|
||||||
memory_index: DefinedMemoryIndex,
|
memory_index: MemoryIndex,
|
||||||
dst: u32,
|
dst: u32,
|
||||||
val: u32,
|
val: u32,
|
||||||
len: u32,
|
len: u32,
|
||||||
) -> Result<(), Trap> {
|
) -> Result<(), Trap> {
|
||||||
let memory = self.memory(memory_index);
|
let memory = self.get_memory(memory_index);
|
||||||
|
|
||||||
if dst
|
if dst
|
||||||
.checked_add(len)
|
.checked_add(len)
|
||||||
@@ -700,27 +663,6 @@ impl Instance {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Perform the `memory.fill` operation on an imported memory.
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
///
|
|
||||||
/// Returns a `Trap` error if the memory range is out of bounds.
|
|
||||||
pub(crate) fn imported_memory_fill(
|
|
||||||
&self,
|
|
||||||
memory_index: MemoryIndex,
|
|
||||||
dst: u32,
|
|
||||||
val: u32,
|
|
||||||
len: u32,
|
|
||||||
) -> Result<(), Trap> {
|
|
||||||
let import = self.imported_memory(memory_index);
|
|
||||||
unsafe {
|
|
||||||
let foreign_instance = (&*import.vmctx).instance();
|
|
||||||
let foreign_memory = &*import.from;
|
|
||||||
let foreign_index = foreign_instance.memory_index(foreign_memory);
|
|
||||||
foreign_instance.defined_memory_fill(foreign_index, dst, val, len)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Performs the `memory.init` operation.
|
/// Performs the `memory.init` operation.
|
||||||
///
|
///
|
||||||
/// # Errors
|
/// # Errors
|
||||||
|
|||||||
@@ -63,8 +63,7 @@ use crate::vmcontext::{VMCallerCheckedAnyfunc, VMContext};
|
|||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr::{self, NonNull};
|
use std::ptr::{self, NonNull};
|
||||||
use wasmtime_environ::wasm::{
|
use wasmtime_environ::wasm::{
|
||||||
DataIndex, DefinedMemoryIndex, ElemIndex, GlobalIndex, MemoryIndex, TableElementType,
|
DataIndex, ElemIndex, GlobalIndex, MemoryIndex, TableElementType, TableIndex,
|
||||||
TableIndex,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const TOINT_32: f32 = 1.0 / f32::EPSILON;
|
const TOINT_32: f32 = 1.0 / f32::EPSILON;
|
||||||
@@ -192,46 +191,12 @@ pub unsafe extern "C" fn wasmtime_memory32_grow(
|
|||||||
memory_index: u32,
|
memory_index: u32,
|
||||||
) -> u32 {
|
) -> u32 {
|
||||||
let instance = (*vmctx).instance_mut();
|
let instance = (*vmctx).instance_mut();
|
||||||
let memory_index = DefinedMemoryIndex::from_u32(memory_index);
|
let memory_index = MemoryIndex::from_u32(memory_index);
|
||||||
|
|
||||||
instance
|
instance
|
||||||
.memory_grow(memory_index, delta)
|
.memory_grow(memory_index, delta)
|
||||||
.unwrap_or(u32::max_value())
|
.unwrap_or(u32::max_value())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of memory.grow for imported 32-bit memories.
|
|
||||||
pub unsafe extern "C" fn wasmtime_imported_memory32_grow(
|
|
||||||
vmctx: *mut VMContext,
|
|
||||||
delta: u32,
|
|
||||||
memory_index: u32,
|
|
||||||
) -> u32 {
|
|
||||||
let instance = (*vmctx).instance_mut();
|
|
||||||
let memory_index = MemoryIndex::from_u32(memory_index);
|
|
||||||
|
|
||||||
instance
|
|
||||||
.imported_memory_grow(memory_index, delta)
|
|
||||||
.unwrap_or(u32::max_value())
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implementation of memory.size for locally-defined 32-bit memories.
|
|
||||||
pub unsafe extern "C" fn wasmtime_memory32_size(vmctx: *mut VMContext, memory_index: u32) -> u32 {
|
|
||||||
let instance = (*vmctx).instance();
|
|
||||||
let memory_index = DefinedMemoryIndex::from_u32(memory_index);
|
|
||||||
|
|
||||||
instance.memory_size(memory_index)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implementation of memory.size for imported 32-bit memories.
|
|
||||||
pub unsafe extern "C" fn wasmtime_imported_memory32_size(
|
|
||||||
vmctx: *mut VMContext,
|
|
||||||
memory_index: u32,
|
|
||||||
) -> u32 {
|
|
||||||
let instance = (*vmctx).instance();
|
|
||||||
let memory_index = MemoryIndex::from_u32(memory_index);
|
|
||||||
|
|
||||||
instance.imported_memory_size(memory_index)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implementation of `table.grow`.
|
/// Implementation of `table.grow`.
|
||||||
pub unsafe extern "C" fn wasmtime_table_grow(
|
pub unsafe extern "C" fn wasmtime_table_grow(
|
||||||
vmctx: *mut VMContext,
|
vmctx: *mut VMContext,
|
||||||
@@ -243,13 +208,8 @@ pub unsafe extern "C" fn wasmtime_table_grow(
|
|||||||
) -> u32 {
|
) -> u32 {
|
||||||
let instance = (*vmctx).instance_mut();
|
let instance = (*vmctx).instance_mut();
|
||||||
let table_index = TableIndex::from_u32(table_index);
|
let table_index = TableIndex::from_u32(table_index);
|
||||||
match instance.table_element_type(table_index) {
|
let element = match instance.table_element_type(table_index) {
|
||||||
TableElementType::Func => {
|
TableElementType::Func => (init_value as *mut VMCallerCheckedAnyfunc).into(),
|
||||||
let func = init_value as *mut VMCallerCheckedAnyfunc;
|
|
||||||
instance
|
|
||||||
.table_grow(table_index, delta, func.into())
|
|
||||||
.unwrap_or(-1_i32 as u32)
|
|
||||||
}
|
|
||||||
TableElementType::Val(ty) => {
|
TableElementType::Val(ty) => {
|
||||||
debug_assert_eq!(ty, crate::ref_type());
|
debug_assert_eq!(ty, crate::ref_type());
|
||||||
|
|
||||||
@@ -258,13 +218,13 @@ pub unsafe extern "C" fn wasmtime_table_grow(
|
|||||||
} else {
|
} else {
|
||||||
Some(VMExternRef::clone_from_raw(init_value))
|
Some(VMExternRef::clone_from_raw(init_value))
|
||||||
};
|
};
|
||||||
|
init_value.into()
|
||||||
|
}
|
||||||
|
};
|
||||||
instance
|
instance
|
||||||
.table_grow(table_index, delta, init_value.into())
|
.table_grow(table_index, delta, element)
|
||||||
.unwrap_or(-1_i32 as u32)
|
.unwrap_or(-1_i32 as u32)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implementation of `table.fill`.
|
/// Implementation of `table.fill`.
|
||||||
pub unsafe extern "C" fn wasmtime_table_fill(
|
pub unsafe extern "C" fn wasmtime_table_fill(
|
||||||
@@ -377,29 +337,11 @@ pub unsafe extern "C" fn wasmtime_memory_fill(
|
|||||||
dst: u32,
|
dst: u32,
|
||||||
val: u32,
|
val: u32,
|
||||||
len: u32,
|
len: u32,
|
||||||
) {
|
|
||||||
let result = {
|
|
||||||
let memory_index = DefinedMemoryIndex::from_u32(memory_index);
|
|
||||||
let instance = (*vmctx).instance();
|
|
||||||
instance.defined_memory_fill(memory_index, dst, val, len)
|
|
||||||
};
|
|
||||||
if let Err(trap) = result {
|
|
||||||
raise_lib_trap(trap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implementation of `memory.fill` for imported memories.
|
|
||||||
pub unsafe extern "C" fn wasmtime_imported_memory_fill(
|
|
||||||
vmctx: *mut VMContext,
|
|
||||||
memory_index: u32,
|
|
||||||
dst: u32,
|
|
||||||
val: u32,
|
|
||||||
len: u32,
|
|
||||||
) {
|
) {
|
||||||
let result = {
|
let result = {
|
||||||
let memory_index = MemoryIndex::from_u32(memory_index);
|
let memory_index = MemoryIndex::from_u32(memory_index);
|
||||||
let instance = (*vmctx).instance_mut();
|
let instance = (*vmctx).instance_mut();
|
||||||
instance.imported_memory_fill(memory_index, dst, val, len)
|
instance.memory_fill(memory_index, dst, val, len)
|
||||||
};
|
};
|
||||||
if let Err(trap) = result {
|
if let Err(trap) = result {
|
||||||
raise_lib_trap(trap);
|
raise_lib_trap(trap);
|
||||||
@@ -517,18 +459,6 @@ pub unsafe extern "C" fn wasmtime_memory_atomic_notify(
|
|||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of `memory.atomic.notify` for imported memories.
|
|
||||||
pub unsafe extern "C" fn wasmtime_imported_memory_atomic_notify(
|
|
||||||
_vmctx: *mut VMContext,
|
|
||||||
_memory_index: u32,
|
|
||||||
_addr: u32,
|
|
||||||
_count: u32,
|
|
||||||
) -> u32 {
|
|
||||||
raise_lib_trap(Trap::User(Box::new(Unimplemented(
|
|
||||||
"wasm atomics (fn wasmtime_imported_memory_atomic_notify) unsupported",
|
|
||||||
))));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implementation of `memory.atomic.wait32` for locally defined memories.
|
/// Implementation of `memory.atomic.wait32` for locally defined memories.
|
||||||
pub unsafe extern "C" fn wasmtime_memory_atomic_wait32(
|
pub unsafe extern "C" fn wasmtime_memory_atomic_wait32(
|
||||||
_vmctx: *mut VMContext,
|
_vmctx: *mut VMContext,
|
||||||
@@ -542,19 +472,6 @@ pub unsafe extern "C" fn wasmtime_memory_atomic_wait32(
|
|||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of `memory.atomic.wait32` for imported memories.
|
|
||||||
pub unsafe extern "C" fn wasmtime_imported_memory_atomic_wait32(
|
|
||||||
_vmctx: *mut VMContext,
|
|
||||||
_memory_index: u32,
|
|
||||||
_addr: u32,
|
|
||||||
_expected: u32,
|
|
||||||
_timeout: u64,
|
|
||||||
) -> u32 {
|
|
||||||
raise_lib_trap(Trap::User(Box::new(Unimplemented(
|
|
||||||
"wasm atomics (fn wasmtime_imported_memory_atomic_wait32) unsupported",
|
|
||||||
))));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implementation of `memory.atomic.wait64` for locally defined memories.
|
/// Implementation of `memory.atomic.wait64` for locally defined memories.
|
||||||
pub unsafe extern "C" fn wasmtime_memory_atomic_wait64(
|
pub unsafe extern "C" fn wasmtime_memory_atomic_wait64(
|
||||||
_vmctx: *mut VMContext,
|
_vmctx: *mut VMContext,
|
||||||
@@ -568,19 +485,6 @@ pub unsafe extern "C" fn wasmtime_memory_atomic_wait64(
|
|||||||
))));
|
))));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Implementation of `memory.atomic.wait32` for imported memories.
|
|
||||||
pub unsafe extern "C" fn wasmtime_imported_memory_atomic_wait64(
|
|
||||||
_vmctx: *mut VMContext,
|
|
||||||
_memory_index: u32,
|
|
||||||
_addr: u32,
|
|
||||||
_expected: u64,
|
|
||||||
_timeout: u64,
|
|
||||||
) -> u32 {
|
|
||||||
raise_lib_trap(Trap::User(Box::new(Unimplemented(
|
|
||||||
"wasm atomics (fn wasmtime_imported_memory_atomic_wait64) unsupported",
|
|
||||||
))));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Hook for when an instance runs out of fuel.
|
/// Hook for when an instance runs out of fuel.
|
||||||
pub unsafe extern "C" fn wasmtime_out_of_gas(vmctx: *mut VMContext) {
|
pub unsafe extern "C" fn wasmtime_out_of_gas(vmctx: *mut VMContext) {
|
||||||
match (*(*vmctx).instance().store()).out_of_gas() {
|
match (*(*vmctx).instance().store()).out_of_gas() {
|
||||||
|
|||||||
@@ -597,12 +597,6 @@ impl VMBuiltinFunctionsArray {
|
|||||||
|
|
||||||
ptrs[BuiltinFunctionIndex::memory32_grow().index() as usize] =
|
ptrs[BuiltinFunctionIndex::memory32_grow().index() as usize] =
|
||||||
wasmtime_memory32_grow as usize;
|
wasmtime_memory32_grow as usize;
|
||||||
ptrs[BuiltinFunctionIndex::imported_memory32_grow().index() as usize] =
|
|
||||||
wasmtime_imported_memory32_grow as usize;
|
|
||||||
ptrs[BuiltinFunctionIndex::memory32_size().index() as usize] =
|
|
||||||
wasmtime_memory32_size as usize;
|
|
||||||
ptrs[BuiltinFunctionIndex::imported_memory32_size().index() as usize] =
|
|
||||||
wasmtime_imported_memory32_size as usize;
|
|
||||||
ptrs[BuiltinFunctionIndex::table_copy().index() as usize] = wasmtime_table_copy as usize;
|
ptrs[BuiltinFunctionIndex::table_copy().index() as usize] = wasmtime_table_copy as usize;
|
||||||
ptrs[BuiltinFunctionIndex::table_grow_funcref().index() as usize] =
|
ptrs[BuiltinFunctionIndex::table_grow_funcref().index() as usize] =
|
||||||
wasmtime_table_grow as usize;
|
wasmtime_table_grow as usize;
|
||||||
@@ -612,8 +606,6 @@ impl VMBuiltinFunctionsArray {
|
|||||||
ptrs[BuiltinFunctionIndex::elem_drop().index() as usize] = wasmtime_elem_drop as usize;
|
ptrs[BuiltinFunctionIndex::elem_drop().index() as usize] = wasmtime_elem_drop as usize;
|
||||||
ptrs[BuiltinFunctionIndex::memory_copy().index() as usize] = wasmtime_memory_copy as usize;
|
ptrs[BuiltinFunctionIndex::memory_copy().index() as usize] = wasmtime_memory_copy as usize;
|
||||||
ptrs[BuiltinFunctionIndex::memory_fill().index() as usize] = wasmtime_memory_fill as usize;
|
ptrs[BuiltinFunctionIndex::memory_fill().index() as usize] = wasmtime_memory_fill as usize;
|
||||||
ptrs[BuiltinFunctionIndex::imported_memory_fill().index() as usize] =
|
|
||||||
wasmtime_imported_memory_fill as usize;
|
|
||||||
ptrs[BuiltinFunctionIndex::memory_init().index() as usize] = wasmtime_memory_init as usize;
|
ptrs[BuiltinFunctionIndex::memory_init().index() as usize] = wasmtime_memory_init as usize;
|
||||||
ptrs[BuiltinFunctionIndex::data_drop().index() as usize] = wasmtime_data_drop as usize;
|
ptrs[BuiltinFunctionIndex::data_drop().index() as usize] = wasmtime_data_drop as usize;
|
||||||
ptrs[BuiltinFunctionIndex::drop_externref().index() as usize] =
|
ptrs[BuiltinFunctionIndex::drop_externref().index() as usize] =
|
||||||
@@ -630,16 +622,10 @@ impl VMBuiltinFunctionsArray {
|
|||||||
wasmtime_table_fill as usize;
|
wasmtime_table_fill as usize;
|
||||||
ptrs[BuiltinFunctionIndex::memory_atomic_notify().index() as usize] =
|
ptrs[BuiltinFunctionIndex::memory_atomic_notify().index() as usize] =
|
||||||
wasmtime_memory_atomic_notify as usize;
|
wasmtime_memory_atomic_notify as usize;
|
||||||
ptrs[BuiltinFunctionIndex::imported_memory_atomic_notify().index() as usize] =
|
|
||||||
wasmtime_imported_memory_atomic_notify as usize;
|
|
||||||
ptrs[BuiltinFunctionIndex::memory_atomic_wait32().index() as usize] =
|
ptrs[BuiltinFunctionIndex::memory_atomic_wait32().index() as usize] =
|
||||||
wasmtime_memory_atomic_wait32 as usize;
|
wasmtime_memory_atomic_wait32 as usize;
|
||||||
ptrs[BuiltinFunctionIndex::imported_memory_atomic_wait32().index() as usize] =
|
|
||||||
wasmtime_imported_memory_atomic_wait32 as usize;
|
|
||||||
ptrs[BuiltinFunctionIndex::memory_atomic_wait64().index() as usize] =
|
ptrs[BuiltinFunctionIndex::memory_atomic_wait64().index() as usize] =
|
||||||
wasmtime_memory_atomic_wait64 as usize;
|
wasmtime_memory_atomic_wait64 as usize;
|
||||||
ptrs[BuiltinFunctionIndex::imported_memory_atomic_wait64().index() as usize] =
|
|
||||||
wasmtime_imported_memory_atomic_wait64 as usize;
|
|
||||||
ptrs[BuiltinFunctionIndex::out_of_gas().index() as usize] = wasmtime_out_of_gas as usize;
|
ptrs[BuiltinFunctionIndex::out_of_gas().index() as usize] = wasmtime_out_of_gas as usize;
|
||||||
|
|
||||||
if cfg!(debug_assertions) {
|
if cfg!(debug_assertions) {
|
||||||
|
|||||||
Reference in New Issue
Block a user