77use crate :: prelude:: * ;
88use crate :: runtime:: vm:: vmcontext:: { VMFuncRef , VMTableDefinition } ;
99use crate :: runtime:: vm:: { GcStore , SendSyncPtr , VMGcRef , VMStore } ;
10+ use core:: alloc:: Layout ;
11+ use core:: mem;
1012use core:: ops:: Range ;
1113use core:: ptr:: { self , NonNull } ;
1214use core:: slice;
@@ -267,6 +269,45 @@ fn wasm_to_table_type(ty: WasmRefType) -> TableElementType {
267269 }
268270}
269271
272+ /// Allocate dynamic table elements of the given length.
273+ ///
274+ /// Relies on the fact that our tables' elements are initialized to `None`,
275+ /// which is represented by zero, to allocate pre-zeroed memory from the global
276+ /// allocator and avoid manual zero-initialization.
277+ ///
278+ /// # Safety
279+ ///
280+ /// Should only ever be called with a `T` that is a table element type and where
281+ /// `Option<T>`'s `None` variant is represented with zero.
282+ unsafe fn alloc_dynamic_table_elements < T > ( len : usize ) -> Result < Vec < Option < T > > > {
283+ debug_assert ! (
284+ core:: mem:: MaybeUninit :: <Option <T >>:: zeroed( )
285+ . assume_init( )
286+ . is_none( ) ,
287+ "null table elements are represented with zeroed memory"
288+ ) ;
289+
290+ if len == 0 {
291+ return Ok ( vec ! [ ] ) ;
292+ }
293+
294+ let align = mem:: align_of :: < Option < T > > ( ) ;
295+
296+ let size = mem:: size_of :: < Option < T > > ( ) ;
297+ let size = size. next_multiple_of ( align) ;
298+ let size = size. checked_mul ( len) . unwrap ( ) ;
299+
300+ let layout = Layout :: from_size_align ( size, align) ?;
301+
302+ let ptr = alloc:: alloc:: alloc_zeroed ( layout) ;
303+ ensure ! ( !ptr. is_null( ) , "failed to allocate memory for table" ) ;
304+
305+ let elems = Vec :: < Option < T > > :: from_raw_parts ( ptr. cast ( ) , len, len) ;
306+ debug_assert ! ( elems. iter( ) . all( |e| e. is_none( ) ) ) ;
307+
308+ Ok ( elems)
309+ }
310+
270311impl Table {
271312 /// Create a new dynamic (movable) table instance for the specified table plan.
272313 pub fn new_dynamic (
@@ -277,12 +318,12 @@ impl Table {
277318 let ( minimum, maximum) = Self :: limit_new ( ty, store) ?;
278319 match wasm_to_table_type ( ty. ref_type ) {
279320 TableElementType :: Func => Ok ( Self :: from ( DynamicFuncTable {
280- elements : vec ! [ None ; minimum] ,
321+ elements : unsafe { alloc_dynamic_table_elements ( minimum) ? } ,
281322 maximum,
282323 lazy_init : tunables. table_lazy_init ,
283324 } ) ) ,
284325 TableElementType :: GcRef => Ok ( Self :: from ( DynamicGcRefTable {
285- elements : ( 0 .. minimum) . map ( |_| None ) . collect ( ) ,
326+ elements : unsafe { alloc_dynamic_table_elements ( minimum) ? } ,
286327 maximum,
287328 } ) ) ,
288329 }
0 commit comments