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:
Nick Fitzgerald
2020-07-02 14:04:01 -07:00
committed by GitHub
parent 3fa3ff2ece
commit bffd54c016
19 changed files with 520 additions and 79 deletions

View File

@@ -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);
}