Make the calls to wasm's memory.grow and memory.size indirect (#194)
* Make the calls to wasm's memory.grow and memory.size indirect
This commit is contained in:
@@ -8,9 +8,7 @@ use cranelift_codegen::ir;
|
|||||||
use cranelift_codegen::ir::condcodes::*;
|
use cranelift_codegen::ir::condcodes::*;
|
||||||
use cranelift_codegen::ir::immediates::{Offset32, Uimm64};
|
use cranelift_codegen::ir::immediates::{Offset32, Uimm64};
|
||||||
use cranelift_codegen::ir::types::*;
|
use cranelift_codegen::ir::types::*;
|
||||||
use cranelift_codegen::ir::{
|
use cranelift_codegen::ir::{AbiParam, ArgumentPurpose, Function, InstBuilder, Signature};
|
||||||
AbiParam, ArgumentPurpose, ExtFuncData, FuncRef, Function, InstBuilder, Signature,
|
|
||||||
};
|
|
||||||
use cranelift_codegen::isa::TargetFrontendConfig;
|
use cranelift_codegen::isa::TargetFrontendConfig;
|
||||||
use cranelift_entity::EntityRef;
|
use cranelift_entity::EntityRef;
|
||||||
use cranelift_wasm::{
|
use cranelift_wasm::{
|
||||||
@@ -50,6 +48,37 @@ pub fn get_imported_memory32_size_name() -> ir::ExternalName {
|
|||||||
ir::ExternalName::user(1, 3)
|
ir::ExternalName::user(1, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An index type for builtin functions.
|
||||||
|
pub struct BuiltinFunctionIndex(u32);
|
||||||
|
|
||||||
|
impl BuiltinFunctionIndex {
|
||||||
|
/// Returns an index for wasm's `memory.grow` builtin function.
|
||||||
|
pub const fn get_memory32_grow_index() -> Self {
|
||||||
|
Self(0)
|
||||||
|
}
|
||||||
|
/// Returns an index for wasm's imported `memory.grow` builtin function.
|
||||||
|
pub const fn get_imported_memory32_grow_index() -> Self {
|
||||||
|
Self(1)
|
||||||
|
}
|
||||||
|
/// Returns an index for wasm's `memory.size` builtin function.
|
||||||
|
pub const fn get_memory32_size_index() -> Self {
|
||||||
|
Self(2)
|
||||||
|
}
|
||||||
|
/// Returns an index for wasm's imported `memory.size` builtin function.
|
||||||
|
pub const fn get_imported_memory32_size_index() -> Self {
|
||||||
|
Self(3)
|
||||||
|
}
|
||||||
|
/// Returns the total number of builtin functions.
|
||||||
|
pub const fn builtin_functions_total_number() -> u32 {
|
||||||
|
4
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Return the index as an u32 number.
|
||||||
|
pub const fn index(&self) -> u32 {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The `FuncEnvironment` implementation for use by the `ModuleEnvironment`.
|
/// The `FuncEnvironment` implementation for use by the `ModuleEnvironment`.
|
||||||
pub struct FuncEnvironment<'module_environment> {
|
pub struct FuncEnvironment<'module_environment> {
|
||||||
/// Target-specified configuration.
|
/// Target-specified configuration.
|
||||||
@@ -61,21 +90,13 @@ pub struct FuncEnvironment<'module_environment> {
|
|||||||
/// The Cranelift global holding the vmctx address.
|
/// The Cranelift global holding the vmctx address.
|
||||||
vmctx: Option<ir::GlobalValue>,
|
vmctx: Option<ir::GlobalValue>,
|
||||||
|
|
||||||
/// The external function declaration for implementing wasm's `memory.size`
|
/// The external function signature for implementing wasm's `memory.size`
|
||||||
/// for locally-defined 32-bit memories.
|
/// for locally-defined 32-bit memories.
|
||||||
memory32_size_extfunc: Option<FuncRef>,
|
memory32_size_sig: Option<ir::SigRef>,
|
||||||
|
|
||||||
/// The external function declaration for implementing wasm's `memory.size`
|
/// The external function signature for implementing wasm's `memory.grow`
|
||||||
/// for imported 32-bit memories.
|
|
||||||
imported_memory32_size_extfunc: Option<FuncRef>,
|
|
||||||
|
|
||||||
/// The external function declaration for implementing wasm's `memory.grow`
|
|
||||||
/// for locally-defined memories.
|
/// for locally-defined memories.
|
||||||
memory_grow_extfunc: Option<FuncRef>,
|
memory_grow_sig: Option<ir::SigRef>,
|
||||||
|
|
||||||
/// The external function declaration for implementing wasm's `memory.grow`
|
|
||||||
/// for imported memories.
|
|
||||||
imported_memory_grow_extfunc: Option<FuncRef>,
|
|
||||||
|
|
||||||
/// Offsets to struct fields accessed by JIT code.
|
/// Offsets to struct fields accessed by JIT code.
|
||||||
offsets: VMOffsets,
|
offsets: VMOffsets,
|
||||||
@@ -87,10 +108,8 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
target_config,
|
target_config,
|
||||||
module,
|
module,
|
||||||
vmctx: None,
|
vmctx: None,
|
||||||
memory32_size_extfunc: None,
|
memory32_size_sig: None,
|
||||||
imported_memory32_size_extfunc: None,
|
memory_grow_sig: None,
|
||||||
memory_grow_extfunc: None,
|
|
||||||
imported_memory_grow_extfunc: None,
|
|
||||||
offsets: VMOffsets::new(target_config.pointer_bytes(), module),
|
offsets: VMOffsets::new(target_config.pointer_bytes(), module),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,106 +126,103 @@ impl<'module_environment> FuncEnvironment<'module_environment> {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_memory_grow_sig(&self, func: &mut Function) -> ir::SigRef {
|
fn get_memory_grow_sig(&mut self, func: &mut Function) -> ir::SigRef {
|
||||||
func.import_signature(Signature {
|
let sig = self.memory_grow_sig.unwrap_or_else(|| {
|
||||||
params: vec![
|
func.import_signature(Signature {
|
||||||
AbiParam::special(self.pointer_type(), ArgumentPurpose::VMContext),
|
params: vec![
|
||||||
AbiParam::new(I32),
|
AbiParam::special(self.pointer_type(), ArgumentPurpose::VMContext),
|
||||||
AbiParam::new(I32),
|
AbiParam::new(I32),
|
||||||
],
|
AbiParam::new(I32),
|
||||||
returns: vec![AbiParam::new(I32)],
|
],
|
||||||
call_conv: self.target_config.default_call_conv,
|
returns: vec![AbiParam::new(I32)],
|
||||||
})
|
call_conv: self.target_config.default_call_conv,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
self.memory_grow_sig = Some(sig);
|
||||||
|
sig
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the memory.grow function to call for the given index, along with the
|
/// Return the memory.grow function signature to call for the given index, along with the
|
||||||
/// translated index value to pass to it.
|
/// translated index value to pass to it and its index in `VMBuiltinFunctionsArray`.
|
||||||
fn get_memory_grow_func(
|
fn get_memory_grow_func(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: &mut Function,
|
func: &mut Function,
|
||||||
index: MemoryIndex,
|
index: MemoryIndex,
|
||||||
) -> (FuncRef, usize) {
|
) -> (ir::SigRef, usize, BuiltinFunctionIndex) {
|
||||||
if self.module.is_imported_memory(index) {
|
if self.module.is_imported_memory(index) {
|
||||||
let extfunc = self.imported_memory_grow_extfunc.unwrap_or_else(|| {
|
|
||||||
let sig_ref = self.get_memory_grow_sig(func);
|
|
||||||
func.import_function(ExtFuncData {
|
|
||||||
name: get_imported_memory32_grow_name(),
|
|
||||||
signature: sig_ref,
|
|
||||||
// We currently allocate all code segments independently, so nothing
|
|
||||||
// is colocated.
|
|
||||||
colocated: false,
|
|
||||||
})
|
|
||||||
});
|
|
||||||
self.imported_memory_grow_extfunc = Some(extfunc);
|
|
||||||
(extfunc, index.index())
|
|
||||||
} else {
|
|
||||||
let extfunc = self.memory_grow_extfunc.unwrap_or_else(|| {
|
|
||||||
let sig_ref = self.get_memory_grow_sig(func);
|
|
||||||
func.import_function(ExtFuncData {
|
|
||||||
name: get_memory32_grow_name(),
|
|
||||||
signature: sig_ref,
|
|
||||||
// We currently allocate all code segments independently, so nothing
|
|
||||||
// is colocated.
|
|
||||||
colocated: false,
|
|
||||||
})
|
|
||||||
});
|
|
||||||
self.memory_grow_extfunc = Some(extfunc);
|
|
||||||
(
|
(
|
||||||
extfunc,
|
self.get_memory_grow_sig(func),
|
||||||
|
index.index(),
|
||||||
|
BuiltinFunctionIndex::get_imported_memory32_grow_index(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
self.get_memory_grow_sig(func),
|
||||||
self.module.defined_memory_index(index).unwrap().index(),
|
self.module.defined_memory_index(index).unwrap().index(),
|
||||||
|
BuiltinFunctionIndex::get_memory32_grow_index(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_memory32_size_sig(&self, func: &mut Function) -> ir::SigRef {
|
fn get_memory32_size_sig(&mut self, func: &mut Function) -> ir::SigRef {
|
||||||
func.import_signature(Signature {
|
let sig = self.memory32_size_sig.unwrap_or_else(|| {
|
||||||
params: vec![
|
func.import_signature(Signature {
|
||||||
AbiParam::special(self.pointer_type(), ArgumentPurpose::VMContext),
|
params: vec![
|
||||||
AbiParam::new(I32),
|
AbiParam::special(self.pointer_type(), ArgumentPurpose::VMContext),
|
||||||
],
|
AbiParam::new(I32),
|
||||||
returns: vec![AbiParam::new(I32)],
|
],
|
||||||
call_conv: self.target_config.default_call_conv,
|
returns: vec![AbiParam::new(I32)],
|
||||||
})
|
call_conv: self.target_config.default_call_conv,
|
||||||
|
})
|
||||||
|
});
|
||||||
|
self.memory32_size_sig = Some(sig);
|
||||||
|
sig
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the memory.size function to call for the given index, along with the
|
/// Return the memory.size function signature to call for the given index, along with the
|
||||||
/// translated index value to pass to it.
|
/// translated index value to pass to it and its index in `VMBuiltinFunctionsArray`.
|
||||||
fn get_memory_size_func(
|
fn get_memory_size_func(
|
||||||
&mut self,
|
&mut self,
|
||||||
func: &mut Function,
|
func: &mut Function,
|
||||||
index: MemoryIndex,
|
index: MemoryIndex,
|
||||||
) -> (FuncRef, usize) {
|
) -> (ir::SigRef, usize, BuiltinFunctionIndex) {
|
||||||
if self.module.is_imported_memory(index) {
|
if self.module.is_imported_memory(index) {
|
||||||
let extfunc = self.imported_memory32_size_extfunc.unwrap_or_else(|| {
|
|
||||||
let sig_ref = self.get_memory32_size_sig(func);
|
|
||||||
func.import_function(ExtFuncData {
|
|
||||||
name: get_imported_memory32_size_name(),
|
|
||||||
signature: sig_ref,
|
|
||||||
// We currently allocate all code segments independently, so nothing
|
|
||||||
// is colocated.
|
|
||||||
colocated: false,
|
|
||||||
})
|
|
||||||
});
|
|
||||||
self.imported_memory32_size_extfunc = Some(extfunc);
|
|
||||||
(extfunc, index.index())
|
|
||||||
} else {
|
|
||||||
let extfunc = self.memory32_size_extfunc.unwrap_or_else(|| {
|
|
||||||
let sig_ref = self.get_memory32_size_sig(func);
|
|
||||||
func.import_function(ExtFuncData {
|
|
||||||
name: get_memory32_size_name(),
|
|
||||||
signature: sig_ref,
|
|
||||||
// We currently allocate all code segments independently, so nothing
|
|
||||||
// is colocated.
|
|
||||||
colocated: false,
|
|
||||||
})
|
|
||||||
});
|
|
||||||
self.memory32_size_extfunc = Some(extfunc);
|
|
||||||
(
|
(
|
||||||
extfunc,
|
self.get_memory32_size_sig(func),
|
||||||
|
index.index(),
|
||||||
|
BuiltinFunctionIndex::get_imported_memory32_size_index(),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
self.get_memory32_size_sig(func),
|
||||||
self.module.defined_memory_index(index).unwrap().index(),
|
self.module.defined_memory_index(index).unwrap().index(),
|
||||||
|
BuiltinFunctionIndex::get_memory32_size_index(),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Translates load of builtin function and returns a pair of values `vmctx`
|
||||||
|
/// and address of the loaded function.
|
||||||
|
fn translate_load_builtin_function_address(
|
||||||
|
&mut self,
|
||||||
|
pos: &mut FuncCursor<'_>,
|
||||||
|
callee_func_idx: BuiltinFunctionIndex,
|
||||||
|
) -> (ir::Value, ir::Value) {
|
||||||
|
// We use an indirect call so that we don't have to patch the code at runtime.
|
||||||
|
let pointer_type = self.pointer_type();
|
||||||
|
let vmctx = self.vmctx(&mut pos.func);
|
||||||
|
let base = pos.ins().global_value(pointer_type, vmctx);
|
||||||
|
|
||||||
|
let mut mem_flags = ir::MemFlags::trusted();
|
||||||
|
mem_flags.set_readonly();
|
||||||
|
|
||||||
|
// Load the callee address.
|
||||||
|
let body_offset =
|
||||||
|
i32::try_from(self.offsets.vmctx_builtin_function(callee_func_idx)).unwrap();
|
||||||
|
let func_addr = pos.ins().load(pointer_type, mem_flags, base, body_offset);
|
||||||
|
|
||||||
|
(base, func_addr)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "lightbeam")]
|
#[cfg(feature = "lightbeam")]
|
||||||
@@ -662,12 +678,12 @@ 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 (memory_grow_func, index_arg) = self.get_memory_grow_func(&mut pos.func, index);
|
let (func_sig, index_arg, func_idx) = self.get_memory_grow_func(&mut pos.func, 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 = pos.func.special_param(ArgumentPurpose::VMContext).unwrap();
|
let (vmctx, func_addr) = self.translate_load_builtin_function_address(&mut pos, func_idx);
|
||||||
let call_inst = pos
|
let call_inst = pos
|
||||||
.ins()
|
.ins()
|
||||||
.call(memory_grow_func, &[vmctx, val, memory_index]);
|
.call_indirect(func_sig, func_addr, &[vmctx, val, memory_index]);
|
||||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -677,10 +693,12 @@ 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 (memory_size_func, index_arg) = self.get_memory_size_func(&mut pos.func, index);
|
let (func_sig, index_arg, func_idx) = self.get_memory_size_func(&mut pos.func, 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 = pos.func.special_param(ArgumentPurpose::VMContext).unwrap();
|
let (vmctx, func_addr) = self.translate_load_builtin_function_address(&mut pos, func_idx);
|
||||||
let call_inst = pos.ins().call(memory_size_func, &[vmctx, memory_index]);
|
let call_inst = pos
|
||||||
|
.ins()
|
||||||
|
.call_indirect(func_sig, func_addr, &[vmctx, memory_index]);
|
||||||
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
Ok(*pos.func.dfg.inst_results(call_inst).first().unwrap())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ pub use crate::compilation::{
|
|||||||
Compilation, CompileError, Compiler, Relocation, RelocationTarget, Relocations,
|
Compilation, CompileError, Compiler, Relocation, RelocationTarget, Relocations,
|
||||||
};
|
};
|
||||||
pub use crate::cranelift::Cranelift;
|
pub use crate::cranelift::Cranelift;
|
||||||
|
pub use crate::func_environ::BuiltinFunctionIndex;
|
||||||
#[cfg(feature = "lightbeam")]
|
#[cfg(feature = "lightbeam")]
|
||||||
pub use crate::lightbeam::Lightbeam;
|
pub use crate::lightbeam::Lightbeam;
|
||||||
pub use crate::module::{
|
pub use crate::module::{
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
//! module.
|
//! module.
|
||||||
|
|
||||||
use crate::module::Module;
|
use crate::module::Module;
|
||||||
|
use crate::BuiltinFunctionIndex;
|
||||||
use core::convert::TryFrom;
|
use core::convert::TryFrom;
|
||||||
use cranelift_codegen::ir;
|
use cranelift_codegen::ir;
|
||||||
use cranelift_wasm::{
|
use cranelift_wasm::{
|
||||||
@@ -332,9 +333,8 @@ impl VMOffsets {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the size of the `VMContext` allocation.
|
/// The offset of the builtin functions array.
|
||||||
#[allow(dead_code)]
|
pub fn vmctx_builtin_functions_begin(&self) -> u32 {
|
||||||
pub fn size_of_vmctx(&self) -> u32 {
|
|
||||||
self.vmctx_globals_begin()
|
self.vmctx_globals_begin()
|
||||||
.checked_add(
|
.checked_add(
|
||||||
self.num_defined_globals
|
self.num_defined_globals
|
||||||
@@ -344,6 +344,17 @@ impl VMOffsets {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the size of the `VMContext` allocation.
|
||||||
|
pub fn size_of_vmctx(&self) -> u32 {
|
||||||
|
self.vmctx_builtin_functions_begin()
|
||||||
|
.checked_add(
|
||||||
|
BuiltinFunctionIndex::builtin_functions_total_number()
|
||||||
|
.checked_mul(u32::from(self.pointer_size))
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
/// Return the offset to `VMSharedSignatureId` index `index`.
|
/// Return the offset to `VMSharedSignatureId` index `index`.
|
||||||
pub fn vmctx_vmshared_signature_id(&self, index: SignatureIndex) -> u32 {
|
pub fn vmctx_vmshared_signature_id(&self, index: SignatureIndex) -> u32 {
|
||||||
assert!(index.as_u32() < self.num_signature_ids);
|
assert!(index.as_u32() < self.num_signature_ids);
|
||||||
@@ -517,6 +528,18 @@ impl VMOffsets {
|
|||||||
.checked_add(u32::from(self.vmglobal_import_from()))
|
.checked_add(u32::from(self.vmglobal_import_from()))
|
||||||
.unwrap()
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return the offset to builtin function in `VMBuiltinFunctionsArray` index `index`.
|
||||||
|
pub fn vmctx_builtin_function(&self, index: BuiltinFunctionIndex) -> u32 {
|
||||||
|
self.vmctx_builtin_functions_begin()
|
||||||
|
.checked_add(
|
||||||
|
index
|
||||||
|
.index()
|
||||||
|
.checked_mul(u32::from(self.pointer_size))
|
||||||
|
.unwrap(),
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Target specific type for shared signature index.
|
/// Target specific type for shared signature index.
|
||||||
|
|||||||
@@ -11,9 +11,9 @@ use crate::signalhandlers::{wasmtime_init_eager, wasmtime_init_finish};
|
|||||||
use crate::table::Table;
|
use crate::table::Table;
|
||||||
use crate::traphandlers::wasmtime_call;
|
use crate::traphandlers::wasmtime_call;
|
||||||
use crate::vmcontext::{
|
use crate::vmcontext::{
|
||||||
VMCallerCheckedAnyfunc, VMContext, VMFunctionBody, VMFunctionImport, VMGlobalDefinition,
|
VMBuiltinFunctionsArray, VMCallerCheckedAnyfunc, VMContext, VMFunctionBody, VMFunctionImport,
|
||||||
VMGlobalImport, VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex, VMTableDefinition,
|
VMGlobalDefinition, VMGlobalImport, VMMemoryDefinition, VMMemoryImport, VMSharedSignatureIndex,
|
||||||
VMTableImport,
|
VMTableDefinition, VMTableImport,
|
||||||
};
|
};
|
||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
use core::borrow::Borrow;
|
use core::borrow::Borrow;
|
||||||
@@ -360,6 +360,15 @@ impl Instance {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a pointer to the `VMBuiltinFunctionsArray`.
|
||||||
|
fn builtin_functions_ptr(&mut self) -> *mut VMBuiltinFunctionsArray {
|
||||||
|
unsafe {
|
||||||
|
(&mut self.vmctx as *mut VMContext as *mut u8)
|
||||||
|
.add(usize::try_from(self.offsets.vmctx_builtin_functions_begin()).unwrap())
|
||||||
|
as *mut VMBuiltinFunctionsArray
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Return a reference to the vmctx used by compiled wasm code.
|
/// Return a reference to the vmctx used by compiled wasm code.
|
||||||
pub fn vmctx(&self) -> &VMContext {
|
pub fn vmctx(&self) -> &VMContext {
|
||||||
&self.vmctx
|
&self.vmctx
|
||||||
@@ -723,6 +732,10 @@ impl InstanceHandle {
|
|||||||
instance.globals_ptr() as *mut VMGlobalDefinition,
|
instance.globals_ptr() as *mut VMGlobalDefinition,
|
||||||
vmctx_globals.len(),
|
vmctx_globals.len(),
|
||||||
);
|
);
|
||||||
|
ptr::write(
|
||||||
|
instance.builtin_functions_ptr() as *mut VMBuiltinFunctionsArray,
|
||||||
|
VMBuiltinFunctionsArray::initialized(),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check initializer bounds before initializing anything.
|
// Check initializer bounds before initializing anything.
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
use crate::instance::Instance;
|
use crate::instance::Instance;
|
||||||
use core::any::Any;
|
use core::any::Any;
|
||||||
use core::{ptr, u32};
|
use core::{ptr, u32};
|
||||||
|
use wasmtime_environ::BuiltinFunctionIndex;
|
||||||
|
|
||||||
/// An imported function.
|
/// An imported function.
|
||||||
#[derive(Debug, Copy, Clone)]
|
#[derive(Debug, Copy, Clone)]
|
||||||
@@ -472,6 +473,33 @@ impl Default for VMCallerCheckedAnyfunc {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// An array that stores addresses of builtin functions. We translate code
|
||||||
|
/// to use indirect calls. This way, we don't have to patch the code.
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct VMBuiltinFunctionsArray {
|
||||||
|
ptrs: [usize; Self::len()],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl VMBuiltinFunctionsArray {
|
||||||
|
pub const fn len() -> usize {
|
||||||
|
BuiltinFunctionIndex::builtin_functions_total_number() as usize
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn initialized() -> Self {
|
||||||
|
use crate::libcalls::*;
|
||||||
|
let mut ptrs = [0; Self::len()];
|
||||||
|
ptrs[BuiltinFunctionIndex::get_memory32_grow_index().index() as usize] =
|
||||||
|
wasmtime_memory32_grow as usize;
|
||||||
|
ptrs[BuiltinFunctionIndex::get_imported_memory32_grow_index().index() as usize] =
|
||||||
|
wasmtime_imported_memory32_grow as usize;
|
||||||
|
ptrs[BuiltinFunctionIndex::get_memory32_size_index().index() as usize] =
|
||||||
|
wasmtime_memory32_size as usize;
|
||||||
|
ptrs[BuiltinFunctionIndex::get_imported_memory32_size_index().index() as usize] =
|
||||||
|
wasmtime_imported_memory32_size as usize;
|
||||||
|
Self { ptrs }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// The VM "context", which is pointed to by the `vmctx` arg in Cranelift.
|
/// The VM "context", which is pointed to by the `vmctx` arg in Cranelift.
|
||||||
/// This has information about globals, memories, tables, and other runtime
|
/// This has information about globals, memories, tables, and other runtime
|
||||||
/// state associated with the current instance.
|
/// state associated with the current instance.
|
||||||
|
|||||||
Reference in New Issue
Block a user