Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 43 additions & 2 deletions crates/wasmtime/src/runtime/vm/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@
use crate::prelude::*;
use crate::runtime::vm::vmcontext::{VMFuncRef, VMTableDefinition};
use crate::runtime::vm::{GcStore, SendSyncPtr, VMGcRef, VMStore};
use core::alloc::Layout;
use core::mem;
use core::ops::Range;
use core::ptr::{self, NonNull};
use core::slice;
Expand Down Expand Up @@ -267,6 +269,45 @@ fn wasm_to_table_type(ty: WasmRefType) -> TableElementType {
}
}

/// Allocate dynamic table elements of the given length.
///
/// Relies on the fact that our tables' elements are initialized to `None`,
/// which is represented by zero, to allocate pre-zeroed memory from the global
/// allocator and avoid manual zero-initialization.
///
/// # Safety
///
/// Should only ever be called with a `T` that is a table element type and where
/// `Option<T>`'s `None` variant is represented with zero.
unsafe fn alloc_dynamic_table_elements<T>(len: usize) -> Result<Vec<Option<T>>> {
debug_assert!(
core::mem::MaybeUninit::<Option<T>>::zeroed()
.assume_init()
.is_none(),
"null table elements are represented with zeroed memory"
);

if len == 0 {
return Ok(vec![]);
}

let align = mem::align_of::<Option<T>>();

let size = mem::size_of::<Option<T>>();
let size = size.next_multiple_of(align);
let size = size.checked_mul(len).unwrap();

let layout = Layout::from_size_align(size, align)?;

let ptr = alloc::alloc::alloc_zeroed(layout);
ensure!(!ptr.is_null(), "failed to allocate memory for table");

let elems = Vec::<Option<T>>::from_raw_parts(ptr.cast(), len, len);
debug_assert!(elems.iter().all(|e| e.is_none()));

Ok(elems)
}

impl Table {
/// Create a new dynamic (movable) table instance for the specified table plan.
pub fn new_dynamic(
Expand All @@ -277,12 +318,12 @@ impl Table {
let (minimum, maximum) = Self::limit_new(ty, store)?;
match wasm_to_table_type(ty.ref_type) {
TableElementType::Func => Ok(Self::from(DynamicFuncTable {
elements: vec![None; minimum],
elements: unsafe { alloc_dynamic_table_elements(minimum)? },
maximum,
lazy_init: tunables.table_lazy_init,
})),
TableElementType::GcRef => Ok(Self::from(DynamicGcRefTable {
elements: (0..minimum).map(|_| None).collect(),
elements: unsafe { alloc_dynamic_table_elements(minimum)? },
maximum,
})),
}
Expand Down