From 7ee695c9c36c6405c0f77ea16f651e9059271982 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Thu, 31 Oct 2024 09:41:37 -0700 Subject: [PATCH] Remove the `wasmtime_environ::TablePlan` type In my quest to simplify memory configuration and how things work internally in Wasmtime one thing I've identified to accomplish is the removal of the `TablePlan` and `MemoryPlan` types. These introduce an abstraction layer between table/memory implementations and `Tunables` and personally I find it simpler to directly reference `Tunables` and use that instead. The goal of this commit is to plumb `Tunables` closer to where it's directly read by removing the "indirection" through the `*Plan` types. The `TablePlan` and `MemoryPlan` types are pervasively used throughout Wasmtime so instead of having one large commit delete everything this is instead a piecemeal approach to incrementally get towards the goal of removal. Here just `TablePlan` is removed and `Tunables` is plumbed in a few more places. I plan to also in the future remove `TableStyle` and `MemoryStyle` in favor of directly reading `Tunables` but that's left for a future commit. For now `TableStyle` persists and its usage is a bit odd in isolation but I plan to follow this up with the removal of `TableStyle`. --- crates/cranelift/src/func_environ.rs | 32 ++++++------- crates/environ/src/compile/module_environ.rs | 26 ++++------- crates/environ/src/module.rs | 28 ++++------- crates/environ/src/vmoffsets.rs | 2 +- crates/wasmtime/src/engine.rs | 1 + .../wasmtime/src/runtime/externals/table.rs | 5 +- crates/wasmtime/src/runtime/instance.rs | 1 + crates/wasmtime/src/runtime/module.rs | 6 +-- crates/wasmtime/src/runtime/store.rs | 3 +- crates/wasmtime/src/runtime/trampoline.rs | 1 + .../wasmtime/src/runtime/trampoline/memory.rs | 8 ++-- .../wasmtime/src/runtime/trampoline/table.rs | 4 +- crates/wasmtime/src/runtime/vm/export.rs | 4 +- crates/wasmtime/src/runtime/vm/instance.rs | 13 ++---- .../src/runtime/vm/instance/allocator.rs | 18 +++++--- .../vm/instance/allocator/on_demand.rs | 8 ++-- .../runtime/vm/instance/allocator/pooling.rs | 10 ++-- .../instance/allocator/pooling/table_pool.rs | 16 ++++--- crates/wasmtime/src/runtime/vm/table.rs | 46 +++++++++++-------- winch/codegen/src/codegen/env.rs | 8 ++-- winch/codegen/src/visitor.rs | 26 ++++++----- 21 files changed, 132 insertions(+), 134 deletions(-) diff --git a/crates/cranelift/src/func_environ.rs b/crates/cranelift/src/func_environ.rs index 8821dfc287d3..87009b538b76 100644 --- a/crates/cranelift/src/func_environ.rs +++ b/crates/cranelift/src/func_environ.rs @@ -701,7 +701,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> { /// Get the Table for the given index. fn table(&self, index: TableIndex) -> Table { - self.module.table_plans[index].table + self.module.tables[index] } /// Cast the value to I64 and sign extend if necessary. @@ -817,7 +817,7 @@ impl<'module_environment> FuncEnvironment<'module_environment> { } }; - let table = &self.module.table_plans[index].table; + let table = &self.module.tables[index]; let element_size = if table.ref_type.is_vmgcref_type() { // For GC-managed references, tables store `Option`s. ir::types::I32.bytes() @@ -1325,8 +1325,9 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> { cold_blocks: bool, ) -> WasmResult> { // Get the funcref pointer from the table. - let table = &self.env.module.table_plans[table_index]; - let TableStyle::CallerChecksSignature { lazy_init } = table.style; + let table = &self.env.module.tables[table_index]; + let TableStyle::CallerChecksSignature { lazy_init } = + TableStyle::for_table(*table, self.env.tunables); let funcref_ptr = self.env.get_or_init_func_ref_table_elem( self.builder, table_index, @@ -1376,18 +1377,19 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> { ty_index: TypeIndex, funcref_ptr: ir::Value, ) -> CheckIndirectCallTypeSignature { - let table = &self.env.module.table_plans[table_index]; + let table = &self.env.module.tables[table_index]; let sig_id_size = self.env.offsets.size_of_vmshared_type_index(); let sig_id_type = Type::int(u16::from(sig_id_size) * 8).unwrap(); // Generate a rustc compile error here if more styles are added in // the future as the following code is tailored to just this style. - let TableStyle::CallerChecksSignature { .. } = table.style; + let TableStyle::CallerChecksSignature { .. } = + TableStyle::for_table(*table, self.env.tunables); // Test if a type check is necessary for this table. If this table is a // table of typed functions and that type matches `ty_index`, then // there's no need to perform a typecheck. - match table.table.ref_type.heap_type { + match table.ref_type.heap_type { // Functions do not have a statically known type in the table, a // typecheck is required. Fall through to below to perform the // actual typecheck. @@ -1403,7 +1405,7 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> { let specified_ty = self.env.module.types[ty_index]; if specified_ty == table_ty { return CheckIndirectCallTypeSignature::StaticMatch { - may_be_null: table.table.ref_type.nullable, + may_be_null: table.ref_type.nullable, }; } @@ -1421,7 +1423,7 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> { // a null pointer, then this was a call to null. Otherwise // if it succeeds then we know it won't match, so trap // anyway. - if table.table.ref_type.nullable { + if table.ref_type.nullable { if self.env.signals_based_traps() { let mem_flags = ir::MemFlags::trusted().with_readonly(); self.builder.ins().load( @@ -1446,7 +1448,7 @@ impl<'a, 'func, 'module_env> Call<'a, 'func, 'module_env> { // Tables of `nofunc` can only be inhabited by null, so go ahead and // trap with that. WasmHeapType::NoFunc => { - assert!(table.table.ref_type.nullable); + assert!(table.ref_type.nullable); self.env .trap(self.builder, crate::TRAP_INDIRECT_CALL_TO_NULL); return CheckIndirectCallTypeSignature::StaticTrap; @@ -1782,8 +1784,7 @@ impl<'module_environment> crate::translate::FuncEnvironment table_index: TableIndex, index: ir::Value, ) -> WasmResult { - let plan = &self.module.table_plans[table_index]; - let table = plan.table; + let table = self.module.tables[table_index]; self.ensure_table_exists(builder.func, table_index); let table_data = self.tables[table_index].clone().unwrap(); let heap_ty = table.ref_type.heap_type; @@ -1801,7 +1802,7 @@ impl<'module_environment> crate::translate::FuncEnvironment } // Function types. - WasmHeapTopType::Func => match plan.style { + WasmHeapTopType::Func => match TableStyle::for_table(table, self.tunables) { TableStyle::CallerChecksSignature { lazy_init } => Ok(self .get_or_init_func_ref_table_elem( builder, @@ -1821,8 +1822,7 @@ impl<'module_environment> crate::translate::FuncEnvironment value: ir::Value, index: ir::Value, ) -> WasmResult<()> { - let plan = &self.module.table_plans[table_index]; - let table = plan.table; + let table = self.module.tables[table_index]; self.ensure_table_exists(builder.func, table_index); let table_data = self.tables[table_index].clone().unwrap(); let heap_ty = table.ref_type.heap_type; @@ -1842,7 +1842,7 @@ impl<'module_environment> crate::translate::FuncEnvironment // Function types. WasmHeapTopType::Func => { - match plan.style { + match TableStyle::for_table(table, self.tunables) { TableStyle::CallerChecksSignature { lazy_init } => { let (elem_addr, flags) = table_data.prepare_table_addr(self, builder, index); diff --git a/crates/environ/src/compile/module_environ.rs b/crates/environ/src/compile/module_environ.rs index 26e5e646fa50..2a593b9f2585 100644 --- a/crates/environ/src/compile/module_environ.rs +++ b/crates/environ/src/compile/module_environ.rs @@ -1,6 +1,6 @@ use crate::module::{ FuncRefIndex, Initializer, MemoryInitialization, MemoryInitializer, MemoryPlan, Module, - TablePlan, TableSegment, TableSegmentElements, + TableSegment, TableSegmentElements, }; use crate::prelude::*; use crate::{ @@ -343,13 +343,12 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> { Payload::TableSection(tables) => { self.validator.table_section(&tables)?; let cnt = usize::try_from(tables.count()).unwrap(); - self.result.module.table_plans.reserve_exact(cnt); + self.result.module.tables.reserve_exact(cnt); for entry in tables { let wasmparser::Table { ty, init } = entry?; let table = self.convert_table_type(&ty)?; - let plan = TablePlan::for_table(table, &self.tunables); - self.result.module.table_plans.push(plan); + self.result.module.tables.push(table); let init = match init { wasmparser::TableInit::RefNull => TableInitialValue::Null { precomputed: Vec::new(), @@ -767,10 +766,7 @@ and for re-adding support for interface types you can see this issue: self.flag_func_escaped(func_index); func_index }), - EntityType::Table(ty) => { - let plan = TablePlan::for_table(ty, &self.tunables); - EntityIndex::Table(self.result.module.table_plans.push(plan)) - } + EntityType::Table(ty) => EntityIndex::Table(self.result.module.tables.push(ty)), EntityType::Memory(ty) => { let plan = MemoryPlan::for_memory(ty, &self.tunables); EntityIndex::Memory(self.result.module.memory_plans.push(plan)) @@ -1141,19 +1137,19 @@ impl ModuleTranslation<'_> { // First convert any element-initialized tables to images of just that // single function if the minimum size of the table allows doing so. - for ((_, init), (_, plan)) in self + for ((_, init), (_, table)) in self .module .table_initialization .initial_values .iter_mut() .zip( self.module - .table_plans + .tables .iter() .skip(self.module.num_imported_tables), ) { - let table_size = plan.table.limits.min; + let table_size = table.limits.min; if table_size > MAX_FUNC_TABLE_SIZE { continue; } @@ -1206,16 +1202,12 @@ impl ModuleTranslation<'_> { Some(top) => top, None => break, }; - let table_size = self.module.table_plans[segment.table_index] - .table - .limits - .min; + let table_size = self.module.tables[segment.table_index].limits.min; if top > table_size || top > MAX_FUNC_TABLE_SIZE { break; } - match self.module.table_plans[segment.table_index] - .table + match self.module.tables[segment.table_index] .ref_type .heap_type .top() diff --git a/crates/environ/src/module.rs b/crates/environ/src/module.rs index 8406eac025fc..52d8f0a3eafd 100644 --- a/crates/environ/src/module.rs +++ b/crates/environ/src/module.rs @@ -330,24 +330,6 @@ impl TableStyle { } } -/// A WebAssembly table description along with our chosen style for -/// implementing it. -#[derive(Debug, Clone, Hash, Serialize, Deserialize)] -pub struct TablePlan { - /// The WebAssembly table description. - pub table: Table, - /// Our chosen implementation style. - pub style: TableStyle, -} - -impl TablePlan { - /// Draw up a plan for implementing a `Table`. - pub fn for_table(table: Table, tunables: &Tunables) -> Self { - let style = TableStyle::for_table(table, tunables); - Self { table, style } - } -} - /// Table initialization data for all tables in the module. #[derive(Debug, Default, Serialize, Deserialize)] pub struct TableInitialization { @@ -481,7 +463,7 @@ pub struct Module { pub functions: PrimaryMap, /// WebAssembly tables. - pub table_plans: PrimaryMap, + pub tables: PrimaryMap, /// WebAssembly linear memory plans. pub memory_plans: PrimaryMap, @@ -651,7 +633,7 @@ impl Module { pub fn type_of(&self, index: EntityIndex) -> EntityType { match index { EntityIndex::Global(i) => EntityType::Global(self.globals[i]), - EntityIndex::Table(i) => EntityType::Table(self.table_plans[i].table), + EntityIndex::Table(i) => EntityType::Table(self.tables[i]), EntityIndex::Memory(i) => EntityType::Memory(self.memory_plans[i].memory), EntityIndex::Function(i) => { EntityType::Function(EngineOrModuleTypeIndex::Module(self.functions[i].signature)) @@ -674,6 +656,12 @@ impl Module { pub fn defined_func_indices(&self) -> impl Iterator { (0..self.functions.len() - self.num_imported_funcs).map(|i| DefinedFuncIndex::new(i)) } + + /// Returns the number of tables defined by this module itself: all tables + /// minus imported tables. + pub fn num_defined_tables(&self) -> usize { + self.tables.len() - self.num_imported_tables + } } /// Type information about functions in a wasm module. diff --git a/crates/environ/src/vmoffsets.rs b/crates/environ/src/vmoffsets.rs index 8b4accffed6d..9b09636c7bb6 100644 --- a/crates/environ/src/vmoffsets.rs +++ b/crates/environ/src/vmoffsets.rs @@ -351,7 +351,7 @@ impl VMOffsets

{ num_imported_tables: cast_to_u32(module.num_imported_tables), num_imported_memories: cast_to_u32(module.num_imported_memories), num_imported_globals: cast_to_u32(module.num_imported_globals), - num_defined_tables: cast_to_u32(module.table_plans.len() - module.num_imported_tables), + num_defined_tables: cast_to_u32(module.num_defined_tables()), num_defined_memories: cast_to_u32( module.memory_plans.len() - module.num_imported_memories, ), diff --git a/crates/wasmtime/src/engine.rs b/crates/wasmtime/src/engine.rs index e7874c745cdc..2a9b490a65fe 100644 --- a/crates/wasmtime/src/engine.rs +++ b/crates/wasmtime/src/engine.rs @@ -175,6 +175,7 @@ impl Engine { } } + #[inline] pub(crate) fn tunables(&self) -> &Tunables { &self.inner.tunables } diff --git a/crates/wasmtime/src/runtime/externals/table.rs b/crates/wasmtime/src/runtime/externals/table.rs index a839a20cd59c..cfb7a3eb81ce 100644 --- a/crates/wasmtime/src/runtime/externals/table.rs +++ b/crates/wasmtime/src/runtime/externals/table.rs @@ -128,7 +128,7 @@ impl Table { } fn _ty(&self, store: &StoreOpaque) -> TableType { - let ty = &store[self.0].table.table; + let ty = &store[self.0].table; TableType::from_wasmtime_table(store.engine(), ty) } @@ -404,7 +404,6 @@ impl Table { ) -> Table { // Ensure that the table's type is engine-level canonicalized. wasmtime_export - .table .table .ref_type .canonicalize_for_runtime_usage(&mut |module_index| { @@ -417,7 +416,7 @@ impl Table { } pub(crate) fn wasmtime_ty<'a>(&self, data: &'a StoreData) -> &'a wasmtime_environ::Table { - &data[self.0].table.table + &data[self.0].table } pub(crate) fn vmimport(&self, store: &StoreOpaque) -> crate::runtime::vm::VMTableImport { diff --git a/crates/wasmtime/src/runtime/instance.rs b/crates/wasmtime/src/runtime/instance.rs index 06c3e66ffa36..77a34065c8d3 100644 --- a/crates/wasmtime/src/runtime/instance.rs +++ b/crates/wasmtime/src/runtime/instance.rs @@ -289,6 +289,7 @@ impl Instance { store: StorePtr::new(store.traitobj()), wmemcheck: store.engine().config().wmemcheck, pkey: store.get_pkey(), + tunables: store.engine().tunables(), })?; // The instance still has lots of setup, for example diff --git a/crates/wasmtime/src/runtime/module.rs b/crates/wasmtime/src/runtime/module.rs index 1741d957c254..53a520715229 100644 --- a/crates/wasmtime/src/runtime/module.rs +++ b/crates/wasmtime/src/runtime/module.rs @@ -883,12 +883,12 @@ impl Module { .skip(em.num_imported_memories) .map(|plan| plan.memory.limits.min) .max(); - let num_tables = u32::try_from(em.table_plans.len() - em.num_imported_tables).unwrap(); + let num_tables = u32::try_from(em.num_defined_tables()).unwrap(); let max_initial_table_size = em - .table_plans + .tables .values() .skip(em.num_imported_tables) - .map(|plan| plan.table.limits.min) + .map(|table| table.limits.min) .max(); ResourcesRequired { num_memories, diff --git a/crates/wasmtime/src/runtime/store.rs b/crates/wasmtime/src/runtime/store.rs index 38eef67ca554..1c98af855367 100644 --- a/crates/wasmtime/src/runtime/store.rs +++ b/crates/wasmtime/src/runtime/store.rs @@ -602,6 +602,7 @@ impl Store { runtime_info: &shim, wmemcheck: engine.config().wmemcheck, pkey: None, + tunables: engine.tunables(), }) .expect("failed to allocate default callee") }; @@ -1293,7 +1294,7 @@ impl StoreOpaque { let module = module.env_module(); let memories = module.memory_plans.len() - module.num_imported_memories; - let tables = module.table_plans.len() - module.num_imported_tables; + let tables = module.num_defined_tables(); bump(&mut self.instance_count, self.instance_limit, 1, "instance")?; bump( diff --git a/crates/wasmtime/src/runtime/trampoline.rs b/crates/wasmtime/src/runtime/trampoline.rs index a060ea306127..be2148fed325 100644 --- a/crates/wasmtime/src/runtime/trampoline.rs +++ b/crates/wasmtime/src/runtime/trampoline.rs @@ -47,6 +47,7 @@ fn create_handle( runtime_info, wmemcheck: false, pkey: None, + tunables: store.engine().tunables(), })?; Ok(store.add_dummy_instance(handle)) diff --git a/crates/wasmtime/src/runtime/trampoline/memory.rs b/crates/wasmtime/src/runtime/trampoline/memory.rs index b2f67d2c308e..d56e1c62aa31 100644 --- a/crates/wasmtime/src/runtime/trampoline/memory.rs +++ b/crates/wasmtime/src/runtime/trampoline/memory.rs @@ -19,7 +19,7 @@ use wasmtime_environ::{ #[cfg(feature = "component-model")] use wasmtime_environ::{ component::{Component, VMComponentOffsets}, - StaticModuleIndex, + StaticModuleIndex, Tunables, }; /// Create a "frankenstein" instance with a single memory. @@ -64,6 +64,7 @@ pub fn create_memory( runtime_info, wmemcheck: false, pkey: None, + tunables: store.engine().tunables(), }; unsafe { @@ -234,10 +235,11 @@ unsafe impl InstanceAllocatorImpl for SingleMemoryInstance<'_> { unsafe fn allocate_table( &self, req: &mut InstanceAllocationRequest, - table_plan: &wasmtime_environ::TablePlan, + ty: &wasmtime_environ::Table, + tunables: &Tunables, table_index: DefinedTableIndex, ) -> Result<(TableAllocationIndex, Table)> { - self.ondemand.allocate_table(req, table_plan, table_index) + self.ondemand.allocate_table(req, ty, tunables, table_index) } unsafe fn deallocate_table( diff --git a/crates/wasmtime/src/runtime/trampoline/table.rs b/crates/wasmtime/src/runtime/trampoline/table.rs index cbf580b578dc..0edd10810481 100644 --- a/crates/wasmtime/src/runtime/trampoline/table.rs +++ b/crates/wasmtime/src/runtime/trampoline/table.rs @@ -8,7 +8,6 @@ pub fn create_table(store: &mut StoreOpaque, table: &TableType) -> Result Result table.init_gc_refs( dst, exprs.iter().map(|expr| unsafe { @@ -1288,7 +1283,7 @@ impl Instance { // Initialize the defined tables let mut ptr = self.vmctx_plus_offset_mut(offsets.vmctx_tables_begin()); - for i in 0..module.table_plans.len() - module.num_imported_tables { + for i in 0..module.num_defined_tables() { ptr::write(ptr, self.tables[DefinedTableIndex::new(i)].1.vmtable()); ptr = ptr.add(1); } @@ -1439,7 +1434,7 @@ impl InstanceHandle { pub fn all_tables<'a>( &'a mut self, ) -> impl ExactSizeIterator + 'a { - let indices = (0..self.module().table_plans.len()) + let indices = (0..self.module().tables.len()) .map(|i| TableIndex::new(i)) .collect::>(); indices.into_iter().map(|i| (i, self.get_exported_table(i))) diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator.rs b/crates/wasmtime/src/runtime/vm/instance/allocator.rs index 1fe3745177ae..8a0434ec20f0 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator.rs @@ -11,8 +11,8 @@ use crate::vm::VMGlobalDefinition; use core::{any::Any, mem, ptr}; use wasmtime_environ::{ DefinedMemoryIndex, DefinedTableIndex, HostPtr, InitMemory, MemoryInitialization, - MemoryInitializer, MemoryPlan, Module, PrimaryMap, SizeOverflow, TableInitialValue, TablePlan, - Trap, VMOffsets, WasmHeapTopType, + MemoryInitializer, MemoryPlan, Module, PrimaryMap, SizeOverflow, TableInitialValue, Trap, + Tunables, VMOffsets, WasmHeapTopType, }; #[cfg(feature = "gc")] @@ -74,6 +74,9 @@ pub struct InstanceAllocationRequest<'a> { /// Request that the instance's memories be protected by a specific /// protection key. pub pkey: Option, + + /// Tunable configuration options the engine is using. + pub tunables: &'a Tunables, } /// A pointer to a Store. This Option<*mut dyn Store> is wrapped in a struct @@ -263,7 +266,8 @@ pub unsafe trait InstanceAllocatorImpl { unsafe fn allocate_table( &self, req: &mut InstanceAllocationRequest, - table_plan: &TablePlan, + table: &wasmtime_environ::Table, + tunables: &Tunables, table_index: DefinedTableIndex, ) -> Result<(TableAllocationIndex, Table)>; @@ -385,7 +389,7 @@ pub trait InstanceAllocator: InstanceAllocatorImpl { let num_defined_memories = module.memory_plans.len() - module.num_imported_memories; let mut memories = PrimaryMap::with_capacity(num_defined_memories); - let num_defined_tables = module.table_plans.len() - module.num_imported_tables; + let num_defined_tables = module.num_defined_tables(); let mut tables = PrimaryMap::with_capacity(num_defined_tables); match (|| { @@ -498,12 +502,12 @@ pub trait InstanceAllocator: InstanceAllocatorImpl { InstanceAllocatorImpl::validate_module_impl(self, module, request.runtime_info.offsets()) .expect("module should have already been validated before allocation"); - for (index, plan) in module.table_plans.iter().skip(module.num_imported_tables) { + for (index, table) in module.tables.iter().skip(module.num_imported_tables) { let def_index = module .defined_table_index(index) .expect("should be a defined table since we skipped imported ones"); - tables.push(self.allocate_table(request, plan, def_index)?); + tables.push(self.allocate_table(request, table, request.tunables, def_index)?); } Ok(()) @@ -575,7 +579,7 @@ fn initialize_tables( }; let idx = module.table_index(table); let table = unsafe { context.instance.get_defined_table(table).as_mut().unwrap() }; - match module.table_plans[idx].table.ref_type.heap_type.top() { + match module.tables[idx].ref_type.heap_type.top() { WasmHeapTopType::Extern => { let gc_ref = VMGcRef::from_raw_u32(raw.get_externref()); let gc_store = unsafe { (*context.instance.store()).gc_store_mut()? }; diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator/on_demand.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/on_demand.rs index 1f2dcb292a05..59a5030b2c1b 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator/on_demand.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator/on_demand.rs @@ -9,7 +9,7 @@ use crate::runtime::vm::table::Table; use crate::runtime::vm::CompiledModuleId; use alloc::sync::Arc; use wasmtime_environ::{ - DefinedMemoryIndex, DefinedTableIndex, HostPtr, MemoryPlan, Module, TablePlan, VMOffsets, + DefinedMemoryIndex, DefinedTableIndex, HostPtr, MemoryPlan, Module, Tunables, VMOffsets, }; #[cfg(feature = "gc")] @@ -130,12 +130,14 @@ unsafe impl InstanceAllocatorImpl for OnDemandInstanceAllocator { unsafe fn allocate_table( &self, request: &mut InstanceAllocationRequest, - table_plan: &TablePlan, + ty: &wasmtime_environ::Table, + tunables: &Tunables, _table_index: DefinedTableIndex, ) -> Result<(TableAllocationIndex, Table)> { let allocation_index = TableAllocationIndex::default(); let table = Table::new_dynamic( - table_plan, + ty, + tunables, request .store .get() diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs index 2f5fea88c9be..2c865a1861be 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling.rs @@ -60,8 +60,7 @@ use std::{ sync::atomic::{AtomicU64, Ordering}, }; use wasmtime_environ::{ - DefinedMemoryIndex, DefinedTableIndex, HostPtr, MemoryPlan, Module, TablePlan, Tunables, - VMOffsets, + DefinedMemoryIndex, DefinedTableIndex, HostPtr, MemoryPlan, Module, Tunables, VMOffsets, }; #[cfg(feature = "gc")] @@ -515,7 +514,7 @@ unsafe impl InstanceAllocatorImpl for PoolingInstanceAllocator { self.validate_module_impl(module, &offsets)?; num_core_instances += 1; num_memories += module.memory_plans.len() - module.num_imported_memories; - num_tables += module.table_plans.len() - module.num_imported_tables; + num_tables += module.num_defined_tables(); } LowerImport { .. } | ExtractMemory(_) @@ -628,10 +627,11 @@ unsafe impl InstanceAllocatorImpl for PoolingInstanceAllocator { unsafe fn allocate_table( &self, request: &mut InstanceAllocationRequest, - table_plan: &TablePlan, + ty: &wasmtime_environ::Table, + tunables: &Tunables, _table_index: DefinedTableIndex, ) -> Result<(super::TableAllocationIndex, Table)> { - self.with_flush_and_retry(|| self.tables.allocate(request, table_plan)) + self.with_flush_and_retry(|| self.tables.allocate(request, ty, tunables)) } unsafe fn deallocate_table( diff --git a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/table_pool.rs b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/table_pool.rs index 8371bf44c56a..3232759cec2f 100644 --- a/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/table_pool.rs +++ b/crates/wasmtime/src/runtime/vm/instance/allocator/pooling/table_pool.rs @@ -9,7 +9,7 @@ use crate::runtime::vm::{ use crate::{runtime::vm::sys::vm::commit_pages, vm::round_usize_up_to_host_pages}; use std::mem; use std::ptr::NonNull; -use wasmtime_environ::{Module, TablePlan}; +use wasmtime_environ::{Module, Tunables}; /// Represents a pool of WebAssembly tables. /// @@ -63,7 +63,7 @@ impl TablePool { /// Validate whether this module's tables are allocatable by this pool. pub fn validate(&self, module: &Module) -> Result<()> { - let tables = module.table_plans.len() - module.num_imported_tables; + let tables = module.num_defined_tables(); if tables > usize::try_from(self.tables_per_instance).unwrap() { bail!( @@ -81,12 +81,12 @@ impl TablePool { ); } - for (i, plan) in module.table_plans.iter().skip(module.num_imported_tables) { - if plan.table.limits.min > u64::try_from(self.table_elements)? { + for (i, table) in module.tables.iter().skip(module.num_imported_tables) { + if table.limits.min > u64::try_from(self.table_elements)? { bail!( "table index {} has a minimum element size of {} which exceeds the limit of {}", i.as_u32(), - plan.table.limits.min, + table.limits.min, self.table_elements, ); } @@ -116,7 +116,8 @@ impl TablePool { pub fn allocate( &self, request: &mut InstanceAllocationRequest, - table_plan: &TablePlan, + ty: &wasmtime_environ::Table, + tunables: &Tunables, ) -> Result<(TableAllocationIndex, Table)> { let allocation_index = self .index_allocator @@ -140,7 +141,8 @@ impl TablePool { .unwrap(); unsafe { Table::new_static( - table_plan, + ty, + tunables, SendSyncPtr::new(ptr), &mut *request.store.get().unwrap(), ) diff --git a/crates/wasmtime/src/runtime/vm/table.rs b/crates/wasmtime/src/runtime/vm/table.rs index 19fafccd09b7..4e703ce6dc1d 100644 --- a/crates/wasmtime/src/runtime/vm/table.rs +++ b/crates/wasmtime/src/runtime/vm/table.rs @@ -13,7 +13,7 @@ use core::slice; use core::{cmp, usize}; use sptr::Strict; use wasmtime_environ::{ - IndexType, TablePlan, TableStyle, Trap, WasmHeapTopType, WasmRefType, FUNCREF_INIT_BIT, + IndexType, TableStyle, Trap, Tunables, WasmHeapTopType, WasmRefType, FUNCREF_INIT_BIT, FUNCREF_MASK, }; @@ -268,11 +268,16 @@ fn wasm_to_table_type(ty: WasmRefType) -> TableElementType { impl Table { /// Create a new dynamic (movable) table instance for the specified table plan. - pub fn new_dynamic(plan: &TablePlan, store: &mut dyn VMStore) -> Result { - let (minimum, maximum) = Self::limit_new(plan, store)?; - match wasm_to_table_type(plan.table.ref_type) { + pub fn new_dynamic( + ty: &wasmtime_environ::Table, + tunables: &Tunables, + store: &mut dyn VMStore, + ) -> Result { + let (minimum, maximum) = Self::limit_new(ty, store)?; + match wasm_to_table_type(ty.ref_type) { TableElementType::Func => { - let TableStyle::CallerChecksSignature { lazy_init } = plan.style; + let TableStyle::CallerChecksSignature { lazy_init } = + TableStyle::for_table(*ty, tunables); Ok(Self::from(DynamicFuncTable { elements: vec![None; minimum], maximum, @@ -288,15 +293,16 @@ impl Table { /// Create a new static (immovable) table instance for the specified table plan. pub unsafe fn new_static( - plan: &TablePlan, + ty: &wasmtime_environ::Table, + tunables: &Tunables, data: SendSyncPtr<[u8]>, store: &mut dyn VMStore, ) -> Result { - let (minimum, maximum) = Self::limit_new(plan, store)?; + let (minimum, maximum) = Self::limit_new(ty, store)?; let size = minimum; let max = maximum.unwrap_or(usize::MAX); - match wasm_to_table_type(plan.table.ref_type) { + match wasm_to_table_type(ty.ref_type) { TableElementType::Func => { let len = { let data = data.as_non_null().as_ref(); @@ -306,16 +312,17 @@ impl Table { data.len() }; ensure!( - usize::try_from(plan.table.limits.min).unwrap() <= len, + usize::try_from(ty.limits.min).unwrap() <= len, "initial table size of {} exceeds the pooling allocator's \ configured maximum table size of {len} elements", - plan.table.limits.min, + ty.limits.min, ); let data = SendSyncPtr::new(NonNull::slice_from_raw_parts( data.as_non_null().cast::(), cmp::min(len, max), )); - let TableStyle::CallerChecksSignature { lazy_init } = plan.style; + let TableStyle::CallerChecksSignature { lazy_init } = + TableStyle::for_table(*ty, tunables); Ok(Self::from(StaticFuncTable { data, size, @@ -331,10 +338,10 @@ impl Table { data.len() }; ensure!( - usize::try_from(plan.table.limits.min).unwrap() <= len, + usize::try_from(ty.limits.min).unwrap() <= len, "initial table size of {} exceeds the pooling allocator's \ configured maximum table size of {len} elements", - plan.table.limits.min, + ty.limits.min, ); let data = SendSyncPtr::new(NonNull::slice_from_raw_parts( data.as_non_null().cast::>(), @@ -348,20 +355,23 @@ impl Table { // Calls the `store`'s limiter to optionally prevent the table from being created. // // Returns the minimum and maximum size of the table if the table can be created. - fn limit_new(plan: &TablePlan, store: &mut dyn VMStore) -> Result<(usize, Option)> { + fn limit_new( + ty: &wasmtime_environ::Table, + store: &mut dyn VMStore, + ) -> Result<(usize, Option)> { // No matter how the table limits are specified // The table size is limited by the host's pointer size let absolute_max = usize::MAX; // If the minimum overflows the host's pointer size, then we can't satisfy this request. // We defer the error to later so the `store` can be informed. - let minimum = usize::try_from(plan.table.limits.min).ok(); + let minimum = usize::try_from(ty.limits.min).ok(); // The maximum size of the table is limited by: // * the host's pointer size. // * the table's maximum size if defined. // * if the table is 64-bit. - let maximum = match (plan.table.limits.max, plan.table.idx_type) { + let maximum = match (ty.limits.max, ty.idx_type) { (Some(max), _) => usize::try_from(max).ok(), (None, IndexType::I64) => usize::try_from(u64::MAX).ok(), (None, IndexType::I32) => usize::try_from(u32::MAX).ok(), @@ -371,7 +381,7 @@ impl Table { if !store.table_growing(0, minimum.unwrap_or(absolute_max), maximum)? { bail!( "table minimum size of {} elements exceeds table limits", - plan.table.limits.min + ty.limits.min ); } @@ -380,7 +390,7 @@ impl Table { let minimum = minimum.ok_or_else(|| { format_err!( "table minimum size of {} elements exceeds table limits", - plan.table.limits.min + ty.limits.min ) })?; Ok((minimum, maximum)) diff --git a/winch/codegen/src/codegen/env.rs b/winch/codegen/src/codegen/env.rs index 7ddc9ac0ba16..120ee75e8ad9 100644 --- a/winch/codegen/src/codegen/env.rs +++ b/winch/codegen/src/codegen/env.rs @@ -12,7 +12,7 @@ use std::mem; use wasmparser::BlockType; use wasmtime_environ::{ BuiltinFunctionIndex, FuncIndex, GlobalIndex, MemoryIndex, MemoryPlan, MemoryStyle, - ModuleTranslation, ModuleTypesBuilder, PrimaryMap, PtrSize, TableIndex, TablePlan, TypeConvert, + ModuleTranslation, ModuleTypesBuilder, PrimaryMap, PtrSize, Table, TableIndex, TypeConvert, TypeIndex, VMOffsets, WasmHeapType, WasmValType, }; @@ -311,9 +311,9 @@ impl<'a, 'translation, 'data, P: PtrSize> FuncEnv<'a, 'translation, 'data, P> { } } - /// Get a [`TablePlan`] from a [`TableIndex`]. - pub fn table_plan(&mut self, index: TableIndex) -> &TablePlan { - &self.translation.module.table_plans[index] + /// Get a [`Table`] from a [`TableIndex`]. + pub fn table(&mut self, index: TableIndex) -> &Table { + &self.translation.module.tables[index] } /// Returns true if Spectre mitigations are enabled for heap bounds check. diff --git a/winch/codegen/src/visitor.rs b/winch/codegen/src/visitor.rs index 86b770328e8b..bee8bc9e0e3d 100644 --- a/winch/codegen/src/visitor.rs +++ b/winch/codegen/src/visitor.rs @@ -1405,7 +1405,10 @@ where // Perform the indirect call. // This code assumes that [`Self::emit_lazy_init_funcref`] will // push the funcref to the value stack. - match self.env.translation.module.table_plans[table_index].style { + match TableStyle::for_table( + self.env.translation.module.tables[table_index], + self.tunables, + ) { TableStyle::CallerChecksSignature { lazy_init: true } => { let funcref_ptr = self.context.stack.peek().map(|v| v.unwrap_reg()).unwrap(); self.masm @@ -1454,12 +1457,11 @@ where fn visit_table_get(&mut self, table: u32) { let table_index = TableIndex::from_u32(table); - let plan = self.env.table_plan(table_index); - let heap_type = plan.table.ref_type.heap_type; - let style = &plan.style; + let table = self.env.table(table_index); + let heap_type = table.ref_type.heap_type; match heap_type { - WasmHeapType::Func => match style { + WasmHeapType::Func => match TableStyle::for_table(*table, self.tunables) { TableStyle::CallerChecksSignature { lazy_init: true } => { self.emit_lazy_init_funcref(table_index) } @@ -1477,8 +1479,8 @@ where fn visit_table_grow(&mut self, table: u32) { let table_index = TableIndex::from_u32(table); - let table_plan = self.env.table_plan(table_index); - let builtin = match table_plan.table.ref_type.heap_type { + let table_ty = self.env.table(table_index); + let builtin = match table_ty.ref_type.heap_type { WasmHeapType::Func => self.env.builtins.table_grow_func_ref::(), ty => unimplemented!("Support for HeapType: {ty}"), }; @@ -1515,8 +1517,8 @@ where fn visit_table_fill(&mut self, table: u32) { let table_index = TableIndex::from_u32(table); - let table_plan = self.env.table_plan(table_index); - let builtin = match table_plan.table.ref_type.heap_type { + let table_ty = self.env.table(table_index); + let builtin = match table_ty.ref_type.heap_type { WasmHeapType::Func => self.env.builtins.table_fill_func_ref::(), ty => unimplemented!("Support for heap type: {ty}"), }; @@ -1539,9 +1541,9 @@ where let ptr_type = self.env.ptr_type(); let table_index = TableIndex::from_u32(table); let table_data = self.env.resolve_table_data(table_index); - let plan = self.env.table_plan(table_index); - match plan.table.ref_type.heap_type { - WasmHeapType::Func => match plan.style { + let table = self.env.table(table_index); + match table.ref_type.heap_type { + WasmHeapType::Func => match TableStyle::for_table(*table, self.tunables) { TableStyle::CallerChecksSignature { lazy_init: true } => { let value = self.context.pop_to_reg(self.masm, None); let index = self.context.pop_to_reg(self.masm, None);