wasmtime: Implement global.{get,set} for externref globals (#1969)
* wasmtime: Implement `global.{get,set}` for externref globals
We use libcalls to implement these -- unlike `table.{get,set}`, for which we
create inline JIT fast paths -- because no known toolchain actually uses
externref globals.
Part of #929
* wasmtime: Enable `{extern,func}ref` globals in the API
This commit is contained in:
@@ -60,9 +60,11 @@ use crate::externref::VMExternRef;
|
||||
use crate::table::Table;
|
||||
use crate::traphandlers::raise_lib_trap;
|
||||
use crate::vmcontext::{VMCallerCheckedAnyfunc, VMContext};
|
||||
use std::ptr::NonNull;
|
||||
use std::mem;
|
||||
use std::ptr::{self, NonNull};
|
||||
use wasmtime_environ::wasm::{
|
||||
DataIndex, DefinedMemoryIndex, ElemIndex, MemoryIndex, TableElementType, TableIndex,
|
||||
DataIndex, DefinedMemoryIndex, ElemIndex, GlobalIndex, MemoryIndex, TableElementType,
|
||||
TableIndex,
|
||||
};
|
||||
|
||||
/// Implementation of f32.ceil
|
||||
@@ -430,3 +432,47 @@ pub unsafe extern "C" fn wasmtime_activations_table_insert_with_gc(
|
||||
let registry = &**instance.stack_map_registry();
|
||||
activations_table.insert_with_gc(externref, registry);
|
||||
}
|
||||
|
||||
/// Perform a Wasm `global.get` for `externref` globals.
|
||||
pub unsafe extern "C" fn wasmtime_externref_global_get(
|
||||
vmctx: *mut VMContext,
|
||||
index: u32,
|
||||
) -> *mut u8 {
|
||||
let index = GlobalIndex::from_u32(index);
|
||||
let instance = (&mut *vmctx).instance();
|
||||
let global = instance.defined_or_imported_global_ptr(index);
|
||||
match (*global).as_externref().clone() {
|
||||
None => ptr::null_mut(),
|
||||
Some(externref) => {
|
||||
let raw = externref.as_raw();
|
||||
let activations_table = &**instance.externref_activations_table();
|
||||
let registry = &**instance.stack_map_registry();
|
||||
activations_table.insert_with_gc(externref, registry);
|
||||
raw
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Perform a Wasm `global.set` for `externref` globals.
|
||||
pub unsafe extern "C" fn wasmtime_externref_global_set(
|
||||
vmctx: *mut VMContext,
|
||||
index: u32,
|
||||
externref: *mut u8,
|
||||
) {
|
||||
let externref = if externref.is_null() {
|
||||
None
|
||||
} else {
|
||||
Some(VMExternRef::clone_from_raw(externref))
|
||||
};
|
||||
|
||||
let index = GlobalIndex::from_u32(index);
|
||||
let instance = (&mut *vmctx).instance();
|
||||
let global = instance.defined_or_imported_global_ptr(index);
|
||||
|
||||
// Swap the new `externref` value into the global before we drop the old
|
||||
// value. This protects against an `externref` with a `Drop` implementation
|
||||
// that calls back into Wasm and touches this global again (we want to avoid
|
||||
// it observing a halfway-deinitialized value).
|
||||
let old = mem::replace((*global).as_externref_mut(), externref);
|
||||
drop(old);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user