diff --git a/lib/types/src/vmoffsets.rs b/lib/types/src/vmoffsets.rs index 81cd0b0422c..d894b446976 100644 --- a/lib/types/src/vmoffsets.rs +++ b/lib/types/src/vmoffsets.rs @@ -136,6 +136,7 @@ fn cast_to_u32(sz: usize) -> u32 { } /// Align an offset used in this module to a specific byte-width by rounding up +#[inline] const fn align(offset: u32, width: u32) -> u32 { (offset + (width - 1)) / width * width } @@ -145,29 +146,44 @@ const fn align(offset: u32, width: u32) -> u32 { #[derive(Clone, Debug)] pub struct VMOffsets { /// The size in bytes of a pointer on the target. - pub pointer_size: u8, + pointer_size: u8, /// The number of signature declarations in the module. - pub num_signature_ids: u32, + num_signature_ids: u32, /// The number of imported functions in the module. - pub num_imported_functions: u32, + num_imported_functions: u32, /// The number of imported tables in the module. - pub num_imported_tables: u32, + num_imported_tables: u32, /// The number of imported memories in the module. - pub num_imported_memories: u32, + num_imported_memories: u32, /// The number of imported globals in the module. - pub num_imported_globals: u32, + num_imported_globals: u32, /// The number of defined tables in the module. - pub num_local_tables: u32, + num_local_tables: u32, /// The number of defined memories in the module. - pub num_local_memories: u32, + num_local_memories: u32, /// The number of defined globals in the module. - pub num_local_globals: u32, + num_local_globals: u32, + + vmctx_signature_ids_begin: u32, + vmctx_imported_functions_begin: u32, + vmctx_imported_tables_begin: u32, + vmctx_imported_memories_begin: u32, + vmctx_imported_globals_begin: u32, + vmctx_tables_begin: u32, + vmctx_memories_begin: u32, + vmctx_globals_begin: u32, + vmctx_builtin_functions_begin: u32, + vmctx_trap_handler_begin: u32, + vmctx_gas_limiter_pointer: u32, + vmctx_stack_limit_begin: u32, + vmctx_stack_limit_initial_begin: u32, + size_of_vmctx: u32, } impl VMOffsets { /// Return a new `VMOffsets` instance, for a given pointer size. pub fn new(pointer_size: u8, module: &ModuleInfo) -> Self { - Self { + let mut ret = Self { pointer_size, num_signature_ids: cast_to_u32(module.signatures.len()), num_imported_functions: cast_to_u32(module.num_imported_functions), @@ -177,7 +193,23 @@ impl VMOffsets { num_local_tables: cast_to_u32(module.tables.len()), num_local_memories: cast_to_u32(module.memories.len()), num_local_globals: cast_to_u32(module.globals.len()), - } + vmctx_signature_ids_begin: 0, + vmctx_imported_functions_begin: 0, + vmctx_imported_tables_begin: 0, + vmctx_imported_memories_begin: 0, + vmctx_imported_globals_begin: 0, + vmctx_tables_begin: 0, + vmctx_memories_begin: 0, + vmctx_globals_begin: 0, + vmctx_builtin_functions_begin: 0, + vmctx_trap_handler_begin: 0, + vmctx_gas_limiter_pointer: 0, + vmctx_stack_limit_begin: 0, + vmctx_stack_limit_initial_begin: 0, + size_of_vmctx: 0, + }; + ret.precompute(); + ret } /// Return a new `VMOffsets` instance, for a given pointer size @@ -195,7 +227,101 @@ impl VMOffsets { num_local_tables: 0, num_local_memories: 0, num_local_globals: 0, + vmctx_signature_ids_begin: 0, + vmctx_imported_functions_begin: 0, + vmctx_imported_tables_begin: 0, + vmctx_imported_memories_begin: 0, + vmctx_imported_globals_begin: 0, + vmctx_tables_begin: 0, + vmctx_memories_begin: 0, + vmctx_globals_begin: 0, + vmctx_builtin_functions_begin: 0, + vmctx_trap_handler_begin: 0, + vmctx_gas_limiter_pointer: 0, + vmctx_stack_limit_begin: 0, + vmctx_stack_limit_initial_begin: 0, + size_of_vmctx: 0, + } + } + + /// Number of local tables defined in the module + pub fn num_local_tables(&self) -> u32 { + self.num_local_tables + } + + /// Number of local memories defined in the module + pub fn num_local_memories(&self) -> u32 { + self.num_local_memories + } + + fn precompute(&mut self) { + /// Offset base by num_items items of size item_size, panicking on overflow + fn offset_by(base: u32, num_items: u32, item_size: u32) -> u32 { + base.checked_add(num_items.checked_mul(item_size).unwrap()) + .unwrap() } + + self.vmctx_signature_ids_begin = 0; + self.vmctx_imported_functions_begin = offset_by( + self.vmctx_signature_ids_begin, + self.num_signature_ids, + u32::from(self.size_of_vmshared_signature_index()), + ); + self.vmctx_imported_tables_begin = offset_by( + self.vmctx_imported_functions_begin, + self.num_imported_functions, + u32::from(self.size_of_vmfunction_import()), + ); + self.vmctx_imported_memories_begin = offset_by( + self.vmctx_imported_tables_begin, + self.num_imported_tables, + u32::from(self.size_of_vmtable_import()), + ); + self.vmctx_imported_globals_begin = offset_by( + self.vmctx_imported_memories_begin, + self.num_imported_memories, + u32::from(self.size_of_vmmemory_import()), + ); + self.vmctx_tables_begin = offset_by( + self.vmctx_imported_globals_begin, + self.num_imported_globals, + u32::from(self.size_of_vmglobal_import()), + ); + self.vmctx_memories_begin = offset_by( + self.vmctx_tables_begin, + self.num_local_tables, + u32::from(self.size_of_vmtable_definition()), + ); + self.vmctx_globals_begin = align( + offset_by( + self.vmctx_memories_begin, + self.num_local_memories, + u32::from(self.size_of_vmmemory_definition()), + ), + 16, + ); + self.vmctx_builtin_functions_begin = offset_by( + self.vmctx_globals_begin, + self.num_local_globals, + u32::from(self.size_of_vmglobal_local()), + ); + self.vmctx_trap_handler_begin = offset_by( + self.vmctx_builtin_functions_begin, + VMBuiltinFunctionIndex::builtin_functions_total_number(), + u32::from(self.pointer_size), + ); + self.vmctx_gas_limiter_pointer = offset_by( + self.vmctx_trap_handler_begin, + 1, + u32::from(self.pointer_size), + ); + self.vmctx_stack_limit_begin = offset_by( + self.vmctx_gas_limiter_pointer, + 1, + u32::from(self.pointer_size), + ); + self.vmctx_stack_limit_initial_begin = self.vmctx_stack_limit_begin.checked_add(4).unwrap(); + self.size_of_vmctx = self.vmctx_stack_limit_begin.checked_add(4).unwrap(); } } @@ -432,296 +558,172 @@ impl VMOffsets { impl VMOffsets { /// The offset of the `signature_ids` array. pub fn vmctx_signature_ids_begin(&self) -> u32 { - 0 + self.vmctx_signature_ids_begin } /// The offset of the `tables` array. #[allow(clippy::erasing_op)] pub fn vmctx_imported_functions_begin(&self) -> u32 { - self.vmctx_signature_ids_begin() - .checked_add( - self.num_signature_ids - .checked_mul(u32::from(self.size_of_vmshared_signature_index())) - .unwrap(), - ) - .unwrap() + self.vmctx_imported_functions_begin } /// The offset of the `tables` array. #[allow(clippy::identity_op)] pub fn vmctx_imported_tables_begin(&self) -> u32 { - self.vmctx_imported_functions_begin() - .checked_add( - self.num_imported_functions - .checked_mul(u32::from(self.size_of_vmfunction_import())) - .unwrap(), - ) - .unwrap() + self.vmctx_imported_tables_begin } /// The offset of the `memories` array. pub fn vmctx_imported_memories_begin(&self) -> u32 { - self.vmctx_imported_tables_begin() - .checked_add( - self.num_imported_tables - .checked_mul(u32::from(self.size_of_vmtable_import())) - .unwrap(), - ) - .unwrap() + self.vmctx_imported_memories_begin } /// The offset of the `globals` array. pub fn vmctx_imported_globals_begin(&self) -> u32 { - self.vmctx_imported_memories_begin() - .checked_add( - self.num_imported_memories - .checked_mul(u32::from(self.size_of_vmmemory_import())) - .unwrap(), - ) - .unwrap() + self.vmctx_imported_globals_begin } /// The offset of the `tables` array. pub fn vmctx_tables_begin(&self) -> u32 { - self.vmctx_imported_globals_begin() - .checked_add( - self.num_imported_globals - .checked_mul(u32::from(self.size_of_vmglobal_import())) - .unwrap(), - ) - .unwrap() + self.vmctx_tables_begin } /// The offset of the `memories` array. pub fn vmctx_memories_begin(&self) -> u32 { - self.vmctx_tables_begin() - .checked_add( - self.num_local_tables - .checked_mul(u32::from(self.size_of_vmtable_definition())) - .unwrap(), - ) - .unwrap() + self.vmctx_memories_begin } /// The offset of the `globals` array. pub fn vmctx_globals_begin(&self) -> u32 { - let offset = self - .vmctx_memories_begin() - .checked_add( - self.num_local_memories - .checked_mul(u32::from(self.size_of_vmmemory_definition())) - .unwrap(), - ) - .unwrap(); - align(offset, 16) + self.vmctx_globals_begin } /// The offset of the builtin functions array. pub fn vmctx_builtin_functions_begin(&self) -> u32 { - self.vmctx_globals_begin() - .checked_add( - self.num_local_globals - .checked_mul(u32::from(self.size_of_vmglobal_local())) - .unwrap(), - ) - .unwrap() + self.vmctx_builtin_functions_begin } /// Return the size of the `VMContext` allocation. pub fn size_of_vmctx(&self) -> u32 { - self.vmctx_builtin_functions_begin() - .checked_add( - VMBuiltinFunctionIndex::builtin_functions_total_number() - .checked_mul(u32::from(self.pointer_size)) - .unwrap(), - ) - .unwrap() + self.size_of_vmctx } /// Return the offset to `VMSharedSignatureIndex` index `index`. pub fn vmctx_vmshared_signature_id(&self, index: SignatureIndex) -> u32 { assert_lt!(index.as_u32(), self.num_signature_ids); - self.vmctx_signature_ids_begin() - .checked_add( - index - .as_u32() - .checked_mul(u32::from(self.size_of_vmshared_signature_index())) - .unwrap(), - ) - .unwrap() + self.vmctx_signature_ids_begin + + index.as_u32() * u32::from(self.size_of_vmshared_signature_index()) } /// Return the offset to `VMFunctionImport` index `index`. pub fn vmctx_vmfunction_import(&self, index: FunctionIndex) -> u32 { assert_lt!(index.as_u32(), self.num_imported_functions); - self.vmctx_imported_functions_begin() - .checked_add( - index - .as_u32() - .checked_mul(u32::from(self.size_of_vmfunction_import())) - .unwrap(), - ) - .unwrap() + self.vmctx_imported_functions_begin + + index.as_u32() * u32::from(self.size_of_vmfunction_import()) } /// Return the offset to `VMTableImport` index `index`. pub fn vmctx_vmtable_import(&self, index: TableIndex) -> u32 { assert_lt!(index.as_u32(), self.num_imported_tables); - self.vmctx_imported_tables_begin() - .checked_add( - index - .as_u32() - .checked_mul(u32::from(self.size_of_vmtable_import())) - .unwrap(), - ) - .unwrap() + self.vmctx_imported_tables_begin + index.as_u32() * u32::from(self.size_of_vmtable_import()) } /// Return the offset to `VMMemoryImport` index `index`. pub fn vmctx_vmmemory_import(&self, index: MemoryIndex) -> u32 { assert_lt!(index.as_u32(), self.num_imported_memories); - self.vmctx_imported_memories_begin() - .checked_add( - index - .as_u32() - .checked_mul(u32::from(self.size_of_vmmemory_import())) - .unwrap(), - ) - .unwrap() + self.vmctx_imported_memories_begin + + index.as_u32() * u32::from(self.size_of_vmmemory_import()) } /// Return the offset to `VMGlobalImport` index `index`. pub fn vmctx_vmglobal_import(&self, index: GlobalIndex) -> u32 { assert_lt!(index.as_u32(), self.num_imported_globals); - self.vmctx_imported_globals_begin() - .checked_add( - index - .as_u32() - .checked_mul(u32::from(self.size_of_vmglobal_import())) - .unwrap(), - ) - .unwrap() + self.vmctx_imported_globals_begin + + index.as_u32() * u32::from(self.size_of_vmglobal_import()) } /// Return the offset to `VMTableDefinition` index `index`. pub fn vmctx_vmtable_definition(&self, index: LocalTableIndex) -> u32 { assert_lt!(index.as_u32(), self.num_local_tables); - self.vmctx_tables_begin() - .checked_add( - index - .as_u32() - .checked_mul(u32::from(self.size_of_vmtable_definition())) - .unwrap(), - ) - .unwrap() + self.vmctx_tables_begin + index.as_u32() * u32::from(self.size_of_vmtable_definition()) } /// Return the offset to `VMMemoryDefinition` index `index`. pub fn vmctx_vmmemory_definition(&self, index: LocalMemoryIndex) -> u32 { assert_lt!(index.as_u32(), self.num_local_memories); - self.vmctx_memories_begin() - .checked_add( - index - .as_u32() - .checked_mul(u32::from(self.size_of_vmmemory_definition())) - .unwrap(), - ) - .unwrap() + self.vmctx_memories_begin + index.as_u32() * u32::from(self.size_of_vmmemory_definition()) } /// Return the offset to the `VMGlobalDefinition` index `index`. pub fn vmctx_vmglobal_definition(&self, index: LocalGlobalIndex) -> u32 { assert_lt!(index.as_u32(), self.num_local_globals); - self.vmctx_globals_begin() - .checked_add( - index - .as_u32() - .checked_mul(u32::from(self.size_of_vmglobal_local())) - .unwrap(), - ) - .unwrap() + self.vmctx_globals_begin + index.as_u32() * u32::from(self.size_of_vmglobal_local()) } /// Return the offset to the `body` field in `*const VMFunctionBody` index `index`. + /// Remember updating precompute upon changes pub fn vmctx_vmfunction_import_body(&self, index: FunctionIndex) -> u32 { - self.vmctx_vmfunction_import(index) - .checked_add(u32::from(self.vmfunction_import_body())) - .unwrap() + self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_body()) } /// Return the offset to the `vmctx` field in `*const VMFunctionBody` index `index`. + /// Remember updating precompute upon changes pub fn vmctx_vmfunction_import_vmctx(&self, index: FunctionIndex) -> u32 { - self.vmctx_vmfunction_import(index) - .checked_add(u32::from(self.vmfunction_import_vmctx())) - .unwrap() + self.vmctx_vmfunction_import(index) + u32::from(self.vmfunction_import_vmctx()) } /// Return the offset to the `definition` field in `VMTableImport` index `index`. + /// Remember updating precompute upon changes pub fn vmctx_vmtable_import_definition(&self, index: TableIndex) -> u32 { - self.vmctx_vmtable_import(index) - .checked_add(u32::from(self.vmtable_import_definition())) - .unwrap() + self.vmctx_vmtable_import(index) + u32::from(self.vmtable_import_definition()) } /// Return the offset to the `base` field in `VMTableDefinition` index `index`. + /// Remember updating precompute upon changes pub fn vmctx_vmtable_definition_base(&self, index: LocalTableIndex) -> u32 { - self.vmctx_vmtable_definition(index) - .checked_add(u32::from(self.vmtable_definition_base())) - .unwrap() + self.vmctx_vmtable_definition(index) + u32::from(self.vmtable_definition_base()) } /// Return the offset to the `current_elements` field in `VMTableDefinition` index `index`. + /// Remember updating precompute upon changes pub fn vmctx_vmtable_definition_current_elements(&self, index: LocalTableIndex) -> u32 { - self.vmctx_vmtable_definition(index) - .checked_add(u32::from(self.vmtable_definition_current_elements())) - .unwrap() + self.vmctx_vmtable_definition(index) + u32::from(self.vmtable_definition_current_elements()) } /// Return the offset to the `from` field in `VMMemoryImport` index `index`. + /// Remember updating precompute upon changes pub fn vmctx_vmmemory_import_definition(&self, index: MemoryIndex) -> u32 { - self.vmctx_vmmemory_import(index) - .checked_add(u32::from(self.vmmemory_import_definition())) - .unwrap() + self.vmctx_vmmemory_import(index) + u32::from(self.vmmemory_import_definition()) } /// Return the offset to the `vmctx` field in `VMMemoryImport` index `index`. + /// Remember updating precompute upon changes pub fn vmctx_vmmemory_import_handle(&self, index: MemoryIndex) -> u32 { - self.vmctx_vmmemory_import(index) - .checked_add(u32::from(self.vmmemory_import_handle())) - .unwrap() + self.vmctx_vmmemory_import(index) + u32::from(self.vmmemory_import_handle()) } /// Return the offset to the `base` field in `VMMemoryDefinition` index `index`. + /// Remember updating precompute upon changes pub fn vmctx_vmmemory_definition_base(&self, index: LocalMemoryIndex) -> u32 { - self.vmctx_vmmemory_definition(index) - .checked_add(u32::from(self.vmmemory_definition_base())) - .unwrap() + self.vmctx_vmmemory_definition(index) + u32::from(self.vmmemory_definition_base()) } /// Return the offset to the `current_length` field in `VMMemoryDefinition` index `index`. + /// Remember updating precompute upon changes pub fn vmctx_vmmemory_definition_current_length(&self, index: LocalMemoryIndex) -> u32 { - self.vmctx_vmmemory_definition(index) - .checked_add(u32::from(self.vmmemory_definition_current_length())) - .unwrap() + self.vmctx_vmmemory_definition(index) + u32::from(self.vmmemory_definition_current_length()) } /// Return the offset to the `from` field in `VMGlobalImport` index `index`. + /// Remember updating precompute upon changes pub fn vmctx_vmglobal_import_definition(&self, index: GlobalIndex) -> u32 { - self.vmctx_vmglobal_import(index) - .checked_add(u32::from(self.vmglobal_import_definition())) - .unwrap() + self.vmctx_vmglobal_import(index) + u32::from(self.vmglobal_import_definition()) } /// Return the offset to builtin function in `VMBuiltinFunctionsArray` index `index`. + /// Remember updating precompute upon changes pub fn vmctx_builtin_function(&self, index: VMBuiltinFunctionIndex) -> u32 { - self.vmctx_builtin_functions_begin() - .checked_add( - index - .index() - .checked_mul(u32::from(self.pointer_size)) - .unwrap(), - ) - .unwrap() + self.vmctx_builtin_functions_begin + index.index() * u32::from(self.pointer_size) } } diff --git a/lib/vm/src/instance/allocator.rs b/lib/vm/src/instance/allocator.rs index 29804c7460e..ead0e9e27f4 100644 --- a/lib/vm/src/instance/allocator.rs +++ b/lib/vm/src/instance/allocator.rs @@ -130,7 +130,7 @@ impl InstanceAllocator { /// memory, i.e. `Self.instance_ptr` must have been allocated by /// `Self::new`. unsafe fn memory_definition_locations(&self) -> Vec> { - let num_memories = self.offsets.num_local_memories; + let num_memories = self.offsets.num_local_memories(); let num_memories = usize::try_from(num_memories).unwrap(); let mut out = Vec::with_capacity(num_memories); @@ -164,7 +164,7 @@ impl InstanceAllocator { /// memory, i.e. `Self.instance_ptr` must have been allocated by /// `Self::new`. unsafe fn table_definition_locations(&self) -> Vec> { - let num_tables = self.offsets.num_local_tables; + let num_tables = self.offsets.num_local_tables(); let num_tables = usize::try_from(num_tables).unwrap(); let mut out = Vec::with_capacity(num_tables);