Skip to content

Commit 575e5a6

Browse files
authored
Use alloc_zeroed to allocate dynamic table elements (#10313)
* Use `alloc_zeroed` to allocate dynamic table elements This allows us to get pre-zeroed memory from the global allocator, rather than needing to manually zero-initialize the elements. * Don't ask the global allocator to allocate a block of size zero
1 parent d463cf4 commit 575e5a6

File tree

1 file changed

+43
-2
lines changed

1 file changed

+43
-2
lines changed

crates/wasmtime/src/runtime/vm/table.rs

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@
77
use crate::prelude::*;
88
use crate::runtime::vm::vmcontext::{VMFuncRef, VMTableDefinition};
99
use crate::runtime::vm::{GcStore, SendSyncPtr, VMGcRef, VMStore};
10+
use core::alloc::Layout;
11+
use core::mem;
1012
use core::ops::Range;
1113
use core::ptr::{self, NonNull};
1214
use 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+
270311
impl 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

Comments
 (0)