diff --git a/crates/cranelift/src/func_environ.rs b/crates/cranelift/src/func_environ.rs index 2260fa8d09..d021bf7ba9 100644 --- a/crates/cranelift/src/func_environ.rs +++ b/crates/cranelift/src/func_environ.rs @@ -120,7 +120,7 @@ pub struct FuncEnvironment<'module_environment> { builtin_function_signatures: BuiltinFunctionSignatures, /// Offsets to struct fields accessed by JIT code. - pub(crate) offsets: VMOffsets, + pub(crate) offsets: VMOffsets, tunables: &'module_environment Tunables, @@ -288,7 +288,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> { // If this changes that's ok, the `atomic_rmw` below just needs to be // preceded with an add instruction of `externref` and the offset. - assert_eq!(VMOffsets::vm_extern_data_ref_count(), 0); + assert_eq!(self.offsets.vm_extern_data_ref_count(), 0); let delta = builder.ins().iconst(pointer_type, delta); builder.ins().atomic_rmw( pointer_type, diff --git a/crates/environ/src/vmoffsets.rs b/crates/environ/src/vmoffsets.rs index dd79b499e6..bf21ab0121 100644 --- a/crates/environ/src/vmoffsets.rs +++ b/crates/environ/src/vmoffsets.rs @@ -52,9 +52,9 @@ fn align(offset: u32, width: u32) -> u32 { /// This class computes offsets to fields within `VMContext` and other /// related structs that JIT code accesses directly. #[derive(Debug, Clone, Copy)] -pub struct VMOffsets { +pub struct VMOffsets

{ /// The size in bytes of a pointer on the target. - pub pointer_size: u8, + pub ptr: P, /// The number of signature declarations in the module. pub num_signature_ids: u32, /// The number of imported functions in the module. @@ -91,11 +91,34 @@ pub struct VMOffsets { size: u32, } +/// Trait used for the `ptr` representation of the field of `VMOffsets` +pub trait PtrSize { + /// Returns the pointer size, in bytes, for the target. + fn size(&self) -> u8; +} + +/// Type representing the size of a pointer for the current compilation host +pub struct HostPtr; + +impl PtrSize for HostPtr { + #[inline] + fn size(&self) -> u8 { + std::mem::size_of::() as u8 + } +} + +impl PtrSize for u8 { + #[inline] + fn size(&self) -> u8 { + *self + } +} + /// Used to construct a `VMOffsets` #[derive(Debug, Clone, Copy)] -pub struct VMOffsetsFields { +pub struct VMOffsetsFields

{ /// The size in bytes of a pointer on the target. - pub pointer_size: u8, + pub ptr: P, /// The number of signature declarations in the module. pub num_signature_ids: u32, /// The number of imported functions in the module. @@ -116,11 +139,11 @@ pub struct VMOffsetsFields { pub num_defined_globals: u32, } -impl VMOffsets { +impl VMOffsets

{ /// Return a new `VMOffsets` instance, for a given pointer size. - pub fn new(pointer_size: u8, module: &Module) -> Self { + pub fn new(ptr: P, module: &Module) -> Self { VMOffsets::from(VMOffsetsFields { - pointer_size, + ptr, num_signature_ids: cast_to_u32(module.types.len()), num_imported_functions: cast_to_u32(module.num_imported_funcs), num_imported_tables: cast_to_u32(module.num_imported_tables), @@ -132,12 +155,18 @@ impl VMOffsets { num_defined_globals: cast_to_u32(module.globals.len()), }) } + + /// Returns the size, in bytes, of the target + #[inline] + pub fn pointer_size(&self) -> u8 { + self.ptr.size() + } } -impl From for VMOffsets { - fn from(fields: VMOffsetsFields) -> VMOffsets { +impl From> for VMOffsets

{ + fn from(fields: VMOffsetsFields

) -> VMOffsets

{ let mut ret = Self { - pointer_size: fields.pointer_size, + ptr: fields.ptr, num_signature_ids: fields.num_signature_ids, num_imported_functions: fields.num_imported_functions, num_imported_tables: fields.num_imported_tables, @@ -166,15 +195,15 @@ impl From for VMOffsets { ret.interrupts = 0; ret.externref_activations_table = ret .interrupts - .checked_add(u32::from(fields.pointer_size)) + .checked_add(u32::from(ret.ptr.size())) .unwrap(); ret.store = ret .externref_activations_table - .checked_add(u32::from(fields.pointer_size)) + .checked_add(u32::from(ret.ptr.size())) .unwrap(); ret.signature_ids = ret .store - .checked_add(u32::from(fields.pointer_size * 2)) + .checked_add(u32::from(ret.ptr.size() * 2)) .unwrap(); ret.imported_functions = ret .signature_ids @@ -257,7 +286,7 @@ impl From for VMOffsets { .builtin_functions .checked_add( BuiltinFunctionIndex::builtin_functions_total_number() - .checked_mul(u32::from(ret.pointer_size)) + .checked_mul(u32::from(ret.pointer_size())) .unwrap(), ) .unwrap(); @@ -266,74 +295,73 @@ impl From for VMOffsets { } } -/// Offsets for `VMFunctionImport`. -impl VMOffsets { +impl VMOffsets

{ /// The offset of the `body` field. #[allow(clippy::erasing_op)] #[inline] pub fn vmfunction_import_body(&self) -> u8 { - 0 * self.pointer_size + 0 * self.pointer_size() } /// The offset of the `vmctx` field. #[allow(clippy::identity_op)] #[inline] pub fn vmfunction_import_vmctx(&self) -> u8 { - 1 * self.pointer_size + 1 * self.pointer_size() } /// Return the size of `VMFunctionImport`. #[inline] pub fn size_of_vmfunction_import(&self) -> u8 { - 2 * self.pointer_size + 2 * self.pointer_size() } } /// Offsets for `*const VMFunctionBody`. -impl VMOffsets { +impl VMOffsets

{ /// The size of the `current_elements` field. #[allow(clippy::identity_op)] pub fn size_of_vmfunction_body_ptr(&self) -> u8 { - 1 * self.pointer_size + 1 * self.pointer_size() } } /// Offsets for `VMTableImport`. -impl VMOffsets { +impl VMOffsets

{ /// The offset of the `from` field. #[allow(clippy::erasing_op)] #[inline] pub fn vmtable_import_from(&self) -> u8 { - 0 * self.pointer_size + 0 * self.pointer_size() } /// The offset of the `vmctx` field. #[allow(clippy::identity_op)] #[inline] pub fn vmtable_import_vmctx(&self) -> u8 { - 1 * self.pointer_size + 1 * self.pointer_size() } /// Return the size of `VMTableImport`. #[inline] pub fn size_of_vmtable_import(&self) -> u8 { - 2 * self.pointer_size + 2 * self.pointer_size() } } /// Offsets for `VMTableDefinition`. -impl VMOffsets { +impl VMOffsets

{ /// The offset of the `base` field. #[allow(clippy::erasing_op)] #[inline] pub fn vmtable_definition_base(&self) -> u8 { - 0 * self.pointer_size + 0 * self.pointer_size() } /// The offset of the `current_elements` field. #[allow(clippy::identity_op)] pub fn vmtable_definition_current_elements(&self) -> u8 { - 1 * self.pointer_size + 1 * self.pointer_size() } /// The size of the `current_elements` field. @@ -345,7 +373,7 @@ impl VMOffsets { /// Return the size of `VMTableDefinition`. #[inline] pub fn size_of_vmtable_definition(&self) -> u8 { - 2 * self.pointer_size + 2 * self.pointer_size() } /// The type of the `current_elements` field. @@ -356,42 +384,42 @@ impl VMOffsets { } /// Offsets for `VMMemoryImport`. -impl VMOffsets { +impl VMOffsets

{ /// The offset of the `from` field. #[allow(clippy::erasing_op)] #[inline] pub fn vmmemory_import_from(&self) -> u8 { - 0 * self.pointer_size + 0 * self.pointer_size() } /// The offset of the `vmctx` field. #[allow(clippy::identity_op)] #[inline] pub fn vmmemory_import_vmctx(&self) -> u8 { - 1 * self.pointer_size + 1 * self.pointer_size() } /// Return the size of `VMMemoryImport`. #[inline] pub fn size_of_vmmemory_import(&self) -> u8 { - 2 * self.pointer_size + 2 * self.pointer_size() } } /// Offsets for `VMMemoryDefinition`. -impl VMOffsets { +impl VMOffsets

{ /// The offset of the `base` field. #[allow(clippy::erasing_op)] #[inline] pub fn vmmemory_definition_base(&self) -> u8 { - 0 * self.pointer_size + 0 * self.pointer_size() } /// The offset of the `current_length` field. #[allow(clippy::identity_op)] #[inline] pub fn vmmemory_definition_current_length(&self) -> u8 { - 1 * self.pointer_size + 1 * self.pointer_size() } /// The size of the `current_length` field. @@ -403,7 +431,7 @@ impl VMOffsets { /// Return the size of `VMMemoryDefinition`. #[inline] pub fn size_of_vmmemory_definition(&self) -> u8 { - 2 * self.pointer_size + 2 * self.pointer_size() } /// The type of the `current_length` field. @@ -414,24 +442,24 @@ impl VMOffsets { } /// Offsets for `VMGlobalImport`. -impl VMOffsets { +impl VMOffsets

{ /// The offset of the `from` field. #[allow(clippy::erasing_op)] #[inline] pub fn vmglobal_import_from(&self) -> u8 { - 0 * self.pointer_size + 0 * self.pointer_size() } /// Return the size of `VMGlobalImport`. #[allow(clippy::identity_op)] #[inline] pub fn size_of_vmglobal_import(&self) -> u8 { - 1 * self.pointer_size + 1 * self.pointer_size() } } /// Offsets for `VMGlobalDefinition`. -impl VMOffsets { +impl VMOffsets

{ /// Return the size of `VMGlobalDefinition`; this is the size of the largest value type (i.e. a /// V128). #[inline] @@ -441,7 +469,7 @@ impl VMOffsets { } /// Offsets for `VMSharedSignatureIndex`. -impl VMOffsets { +impl VMOffsets

{ /// Return the size of `VMSharedSignatureIndex`. #[inline] pub fn size_of_vmshared_signature_index(&self) -> u8 { @@ -450,7 +478,7 @@ impl VMOffsets { } /// Offsets for `VMInterrupts`. -impl VMOffsets { +impl VMOffsets

{ /// Return the offset of the `stack_limit` field of `VMInterrupts` #[inline] pub fn vminterrupts_stack_limit(&self) -> u8 { @@ -460,41 +488,41 @@ impl VMOffsets { /// Return the offset of the `fuel_consumed` field of `VMInterrupts` #[inline] pub fn vminterrupts_fuel_consumed(&self) -> u8 { - self.pointer_size + self.pointer_size() } } /// Offsets for `VMCallerCheckedAnyfunc`. -impl VMOffsets { +impl VMOffsets

{ /// The offset of the `func_ptr` field. #[allow(clippy::erasing_op)] #[inline] pub fn vmcaller_checked_anyfunc_func_ptr(&self) -> u8 { - 0 * self.pointer_size + 0 * self.pointer_size() } /// The offset of the `type_index` field. #[allow(clippy::identity_op)] #[inline] pub fn vmcaller_checked_anyfunc_type_index(&self) -> u8 { - 1 * self.pointer_size + 1 * self.pointer_size() } /// The offset of the `vmctx` field. #[inline] pub fn vmcaller_checked_anyfunc_vmctx(&self) -> u8 { - 2 * self.pointer_size + 2 * self.pointer_size() } /// Return the size of `VMCallerCheckedAnyfunc`. #[inline] pub fn size_of_vmcaller_checked_anyfunc(&self) -> u8 { - 3 * self.pointer_size + 3 * self.pointer_size() } } /// Offsets for `VMContext`. -impl VMOffsets { +impl VMOffsets

{ /// Return the offset to the `VMInterrupts` structure #[inline] pub fn vmctx_interrupts(&self) -> u32 { @@ -717,21 +745,21 @@ impl VMOffsets { /// Return the offset to builtin function in `VMBuiltinFunctionsArray` index `index`. #[inline] pub fn vmctx_builtin_function(&self, index: BuiltinFunctionIndex) -> u32 { - self.vmctx_builtin_functions_begin() + index.index() * u32::from(self.pointer_size) + self.vmctx_builtin_functions_begin() + index.index() * u32::from(self.pointer_size()) } } /// Offsets for `VMExternData`. -impl VMOffsets { +impl VMOffsets

{ /// Return the offset for `VMExternData::ref_count`. #[inline] - pub fn vm_extern_data_ref_count() -> u32 { + pub fn vm_extern_data_ref_count(&self) -> u32 { 0 } } /// Offsets for `VMExternRefActivationsTable`. -impl VMOffsets { +impl VMOffsets

{ /// Return the offset for `VMExternRefActivationsTable::next`. #[inline] pub fn vm_extern_ref_activation_table_next(&self) -> u32 { @@ -741,7 +769,7 @@ impl VMOffsets { /// Return the offset for `VMExternRefActivationsTable::end`. #[inline] pub fn vm_extern_ref_activation_table_end(&self) -> u32 { - self.pointer_size.into() + self.pointer_size().into() } } diff --git a/crates/lightbeam/wasmtime/src/lib.rs b/crates/lightbeam/wasmtime/src/lib.rs index acb69a11aa..10c9a0dceb 100644 --- a/crates/lightbeam/wasmtime/src/lib.rs +++ b/crates/lightbeam/wasmtime/src/lib.rs @@ -175,7 +175,7 @@ struct FuncEnvironment<'module_environment> { module: &'module_environment Module, /// Offsets to struct fields accessed by JIT code. - offsets: VMOffsets, + offsets: VMOffsets, } impl<'module_environment> FuncEnvironment<'module_environment> { diff --git a/crates/runtime/src/externref.rs b/crates/runtime/src/externref.rs index 4a6d250a10..55a8dae3e8 100644 --- a/crates/runtime/src/externref.rs +++ b/crates/runtime/src/externref.rs @@ -965,8 +965,20 @@ mod tests { let actual_offset = (ref_count_ptr as usize) - (extern_data_ptr as usize); + let offsets = wasmtime_environ::VMOffsets::from(wasmtime_environ::VMOffsetsFields { + ptr: 8, + num_signature_ids: 0, + num_imported_functions: 0, + num_imported_tables: 0, + num_imported_memories: 0, + num_imported_globals: 0, + num_defined_functions: 0, + num_defined_tables: 0, + num_defined_memories: 0, + num_defined_globals: 0, + }); assert_eq!( - wasmtime_environ::VMOffsets::vm_extern_data_ref_count(), + offsets.vm_extern_data_ref_count(), actual_offset.try_into().unwrap(), ); } @@ -981,7 +993,7 @@ mod tests { let actual_offset = (next_ptr as usize) - (table_ptr as usize); let offsets = wasmtime_environ::VMOffsets::from(wasmtime_environ::VMOffsetsFields { - pointer_size: 8, + ptr: 8, num_signature_ids: 0, num_imported_functions: 0, num_imported_tables: 0, @@ -1008,7 +1020,7 @@ mod tests { let actual_offset = (end_ptr as usize) - (table_ptr as usize); let offsets = wasmtime_environ::VMOffsets::from(wasmtime_environ::VMOffsetsFields { - pointer_size: 8, + ptr: 8, num_signature_ids: 0, num_imported_functions: 0, num_imported_tables: 0, diff --git a/crates/runtime/src/instance.rs b/crates/runtime/src/instance.rs index 0907f60681..216979bdf8 100644 --- a/crates/runtime/src/instance.rs +++ b/crates/runtime/src/instance.rs @@ -27,7 +27,7 @@ use wasmtime_environ::wasm::{ DataIndex, DefinedGlobalIndex, DefinedMemoryIndex, DefinedTableIndex, ElemIndex, EntityIndex, FuncIndex, GlobalIndex, MemoryIndex, TableElementType, TableIndex, WasmType, }; -use wasmtime_environ::{ir, Module, VMOffsets}; +use wasmtime_environ::{ir, HostPtr, Module, VMOffsets}; mod allocator; @@ -119,7 +119,7 @@ pub(crate) struct Instance { module: Arc, /// Offsets in the `vmctx` region, precomputed from the `module` above. - offsets: VMOffsets, + offsets: VMOffsets, /// WebAssembly linear memory data. /// diff --git a/crates/runtime/src/instance/allocator.rs b/crates/runtime/src/instance/allocator.rs index 463e78c63e..647b539e45 100644 --- a/crates/runtime/src/instance/allocator.rs +++ b/crates/runtime/src/instance/allocator.rs @@ -22,8 +22,8 @@ use wasmtime_environ::wasm::{ DefinedFuncIndex, DefinedMemoryIndex, DefinedTableIndex, GlobalInit, SignatureIndex, WasmType, }; use wasmtime_environ::{ - ir, MemoryInitialization, MemoryInitializer, Module, ModuleType, TableInitializer, VMOffsets, - WASM_PAGE_SIZE, + ir, HostPtr, MemoryInitialization, MemoryInitializer, Module, ModuleType, TableInitializer, + VMOffsets, WASM_PAGE_SIZE, }; mod pooling; @@ -643,7 +643,7 @@ unsafe impl InstanceAllocator for OnDemandInstanceAllocator { let mut handle = { let instance = Instance { module: req.module.clone(), - offsets: VMOffsets::new(std::mem::size_of::<*const u8>() as u8, &req.module), + offsets: VMOffsets::new(HostPtr, &req.module), memories, tables, dropped_elements: EntitySet::with_capacity(req.module.passive_elements.len()), diff --git a/crates/runtime/src/instance/allocator/pooling.rs b/crates/runtime/src/instance/allocator/pooling.rs index 806498ff86..41344b7aa7 100644 --- a/crates/runtime/src/instance/allocator/pooling.rs +++ b/crates/runtime/src/instance/allocator/pooling.rs @@ -21,7 +21,7 @@ use std::mem; use std::sync::{Arc, Mutex}; use wasmtime_environ::{ entity::{EntitySet, PrimaryMap}, - MemoryStyle, Module, Tunables, VMOffsets, VMOffsetsFields, WASM_PAGE_SIZE, + HostPtr, MemoryStyle, Module, Tunables, VMOffsets, VMOffsetsFields, WASM_PAGE_SIZE, }; cfg_if::cfg_if! { @@ -298,7 +298,7 @@ impl InstancePool { // Calculate the maximum size of an Instance structure given the limits let offsets = VMOffsets::from(VMOffsetsFields { - pointer_size: std::mem::size_of::<*const u8>() as u8, + ptr: HostPtr, num_signature_ids: module_limits.types, num_imported_functions: module_limits.imported_functions, num_imported_tables: module_limits.imported_tables, @@ -358,10 +358,7 @@ impl InstancePool { instance as _, Instance { module: self.empty_module.clone(), - offsets: VMOffsets::new( - std::mem::size_of::<*const u8>() as u8, - &self.empty_module, - ), + offsets: VMOffsets::new(HostPtr, &self.empty_module), memories: PrimaryMap::with_capacity(limits.memories as usize), tables: PrimaryMap::with_capacity(limits.tables as usize), dropped_elements: EntitySet::new(), @@ -383,10 +380,7 @@ impl InstancePool { let instance = self.instance(index); instance.module = req.module.clone(); - instance.offsets = VMOffsets::new( - std::mem::size_of::<*const u8>() as u8, - instance.module.as_ref(), - ); + instance.offsets = VMOffsets::new(HostPtr, instance.module.as_ref()); instance.host_state = std::mem::replace(&mut req.host_state, Box::new(())); let mut limiter = req.store.and_then(|s| (*s).limiter()); @@ -497,8 +491,7 @@ impl InstancePool { // should put everything back in a relatively pristine state for each // fresh allocation later on. instance.module = self.empty_module.clone(); - instance.offsets = - VMOffsets::new(std::mem::size_of::<*const u8>() as u8, &self.empty_module); + instance.offsets = VMOffsets::new(HostPtr, &self.empty_module); self.free_list.lock().unwrap().push(index); }