Skip to content
Merged
Show file tree
Hide file tree
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
14 changes: 9 additions & 5 deletions crates/environ/src/compile/module_environ.rs
Original file line number Diff line number Diff line change
Expand Up @@ -367,7 +367,7 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
precomputed: Vec::new(),
},
wasmparser::TableInit::Expr(expr) => {
let (init, escaped) = ConstExpr::from_wasmparser(expr)?;
let (init, escaped) = ConstExpr::from_wasmparser(self, expr)?;
for f in escaped {
self.flag_func_escaped(f);
}
Expand Down Expand Up @@ -413,7 +413,7 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {

for entry in globals {
let wasmparser::Global { ty, init_expr } = entry?;
let (initializer, escaped) = ConstExpr::from_wasmparser(init_expr)?;
let (initializer, escaped) = ConstExpr::from_wasmparser(self, init_expr)?;
for f in escaped {
self.flag_func_escaped(f);
}
Expand Down Expand Up @@ -488,7 +488,7 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
let mut exprs =
Vec::with_capacity(usize::try_from(items.count()).unwrap());
for expr in items {
let (expr, escaped) = ConstExpr::from_wasmparser(expr?)?;
let (expr, escaped) = ConstExpr::from_wasmparser(self, expr?)?;
exprs.push(expr);
for func in escaped {
self.flag_func_escaped(func);
Expand All @@ -504,7 +504,7 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
offset_expr,
} => {
let table_index = TableIndex::from_u32(table_index.unwrap_or(0));
let (offset, escaped) = ConstExpr::from_wasmparser(offset_expr)?;
let (offset, escaped) = ConstExpr::from_wasmparser(self, offset_expr)?;
debug_assert!(escaped.is_empty());

self.result
Expand Down Expand Up @@ -613,9 +613,13 @@ impl<'a, 'data> ModuleEnvironment<'a, 'data> {
} => {
let range = mk_range(&mut self.result.total_data)?;
let memory_index = MemoryIndex::from_u32(memory_index);
let (offset, escaped) = ConstExpr::from_wasmparser(offset_expr)?;
let (offset, escaped) = ConstExpr::from_wasmparser(self, offset_expr)?;
debug_assert!(escaped.is_empty());

let initializers = match &mut self.result.module.memory_initialization {
MemoryInitialization::Segmented(i) => i,
_ => unreachable!(),
};
initializers.push(MemoryInitializer {
memory_index,
offset,
Expand Down
18 changes: 13 additions & 5 deletions crates/environ/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ impl EngineOrModuleTypeIndex {
}

/// Get the underlying engine-level type index, if any.
#[inline]
pub fn as_engine_type_index(self) -> Option<VMSharedTypeIndex> {
match self {
Self::Engine(e) => Some(e),
Expand All @@ -381,6 +382,7 @@ impl EngineOrModuleTypeIndex {

/// Get the underlying engine-level type index, or panic.
#[track_caller]
#[inline]
pub fn unwrap_engine_type_index(self) -> VMSharedTypeIndex {
match self.as_engine_type_index() {
Some(x) => x,
Expand Down Expand Up @@ -645,7 +647,7 @@ impl WasmHeapType {
}

/// A top heap type.
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, Deserialize)]
pub enum WasmHeapTopType {
/// The common supertype of all external references.
Extern,
Expand Down Expand Up @@ -1800,6 +1802,7 @@ impl ConstExpr {
/// Returns the new const expression as well as the escaping function
/// indices that appeared in `ref.func` instructions, if any.
pub fn from_wasmparser(
env: &dyn TypeConvert,
expr: wasmparser::ConstExpr<'_>,
) -> WasmResult<(Self, SmallVec<[FuncIndex; 1]>)> {
let mut iter = expr
Expand All @@ -1825,12 +1828,13 @@ impl ConstExpr {
escaped.push(FuncIndex::from_u32(*function_index));
}

ops.push(ConstOp::from_wasmparser(op, offset)?);
ops.push(ConstOp::from_wasmparser(env, op, offset)?);
}
Ok((Self { ops }, escaped))
}

/// Get the opcodes that make up this const expression.
#[inline]
pub fn ops(&self) -> &[ConstOp] {
&self.ops
}
Expand Down Expand Up @@ -1875,7 +1879,7 @@ pub enum ConstOp {
V128Const(u128),
GlobalGet(GlobalIndex),
RefI31,
RefNull,
RefNull(WasmHeapTopType),
RefFunc(FuncIndex),
I32Add,
I32Sub,
Expand Down Expand Up @@ -1905,15 +1909,19 @@ pub enum ConstOp {

impl ConstOp {
/// Convert a `wasmparser::Operator` to a `ConstOp`.
pub fn from_wasmparser(op: wasmparser::Operator<'_>, offset: usize) -> WasmResult<Self> {
pub fn from_wasmparser(
env: &dyn TypeConvert,
op: wasmparser::Operator<'_>,
offset: usize,
) -> WasmResult<Self> {
use wasmparser::Operator as O;
Ok(match op {
O::I32Const { value } => Self::I32Const(value),
O::I64Const { value } => Self::I64Const(value),
O::F32Const { value } => Self::F32Const(value.bits()),
O::F64Const { value } => Self::F64Const(value.bits()),
O::V128Const { value } => Self::V128Const(u128::from_le_bytes(*value.bytes())),
O::RefNull { hty: _ } => Self::RefNull,
O::RefNull { hty } => Self::RefNull(env.convert_heap_type(hty)?.top()),
O::RefFunc { function_index } => Self::RefFunc(FuncIndex::from_u32(function_index)),
O::GlobalGet { global_index } => Self::GlobalGet(GlobalIndex::from_u32(global_index)),
O::RefI31 => Self::RefI31,
Expand Down
44 changes: 32 additions & 12 deletions crates/wasmtime/src/runtime/externals/global.rs
Original file line number Diff line number Diff line change
Expand Up @@ -139,10 +139,13 @@ impl Global {
///
/// Panics if `store` does not own this global.
pub fn get(&self, mut store: impl AsContextMut) -> Val {
let mut store = AutoAssertNoGc::new(store.as_context_mut().0);
self._get(&mut store)
}

pub(crate) fn _get(&self, store: &mut AutoAssertNoGc<'_>) -> Val {
unsafe {
let store = store.as_context_mut();
let definition = self.definition(store.0).as_ref();
let mut store = AutoAssertNoGc::new(store.0);
let definition = self.definition(store).as_ref();
match self._ty(&store).content() {
ValType::I32 => Val::from(*definition.as_i32()),
ValType::I64 => Val::from(*definition.as_i64()),
Expand All @@ -152,14 +155,14 @@ impl Global {
ValType::Ref(ref_ty) => {
let reference: Ref = match ref_ty.heap_type() {
HeapType::Func | HeapType::ConcreteFunc(_) => {
Func::_from_raw(&mut store, definition.as_func_ref().cast()).into()
Func::_from_raw(store, definition.as_func_ref().cast()).into()
}

HeapType::NoFunc => Ref::Func(None),

HeapType::Extern => Ref::Extern(definition.as_gc_ref().map(|r| {
let r = store.clone_gc_ref(r);
ExternRef::from_cloned_gc_ref(&mut store, r)
ExternRef::from_cloned_gc_ref(store, r)
})),

HeapType::NoCont | HeapType::ConcreteCont(_) | HeapType::Cont => {
Expand All @@ -181,7 +184,7 @@ impl Global {
.as_gc_ref()
.map(|r| {
let r = store.clone_gc_ref(r);
AnyRef::from_cloned_gc_ref(&mut store, r)
AnyRef::from_cloned_gc_ref(store, r)
})
.into(),

Expand Down Expand Up @@ -211,21 +214,38 @@ impl Global {
///
/// Panics if `store` does not own this global.
pub fn set(&self, mut store: impl AsContextMut, val: Val) -> Result<()> {
let mut store = AutoAssertNoGc::new(store.as_context_mut().0);
self._set(store.as_context_mut().0, val)
}

pub(crate) fn _set(&self, store: &mut StoreOpaque, val: Val) -> Result<()> {
let global_ty = self._ty(&store);
if global_ty.mutability() != Mutability::Var {
bail!("immutable global cannot be set");
}
val.ensure_matches_ty(&store, global_ty.content())
.context("type mismatch: attempt to set global to value of wrong type")?;

// SAFETY: mutability and a type-check above makes this safe to perform.
unsafe { self.set_unchecked(store, &val) }
}

/// Sets this global to `val`.
///
/// # Safety
///
/// This function requires that `val` is of the correct type for this
/// global. Furthermore this requires that the global is mutable or this is
/// the first time the global is initialized.
pub(crate) unsafe fn set_unchecked(&self, store: &mut StoreOpaque, val: &Val) -> Result<()> {
let mut store = AutoAssertNoGc::new(store);
unsafe {
let definition = self.definition(&store).as_mut();
match val {
Val::I32(i) => *definition.as_i32_mut() = i,
Val::I64(i) => *definition.as_i64_mut() = i,
Val::F32(f) => *definition.as_u32_mut() = f,
Val::F64(f) => *definition.as_u64_mut() = f,
Val::V128(i) => definition.set_u128(i.into()),
Val::I32(i) => *definition.as_i32_mut() = *i,
Val::I64(i) => *definition.as_i64_mut() = *i,
Val::F32(f) => *definition.as_u32_mut() = *f,
Val::F64(f) => *definition.as_u64_mut() = *f,
Val::V128(i) => definition.set_u128((*i).into()),
Val::FuncRef(f) => {
*definition.as_func_ref_mut() =
f.map_or(ptr::null_mut(), |f| f.vm_func_ref(&store).as_ptr().cast());
Expand Down
Loading