Replace the global-exports mechanism with a caller-vmctx mechanism. (#789)

* Replace the global-exports mechanism with a caller-vmctx mechanism.

This eliminates the global exports mechanism, and instead adds a
caller-vmctx argument to wasm functions so that WASI can obtain the
memory and other things from the caller rather than looking them up in a
global registry.

This replaces #390.

* Fixup some merge conflicts

* Rustfmt

* Ensure VMContext is aligned to 16 bytes

With the removal of `global_exports` it "just so happens" that this
isn't happening naturally any more.

* Fixup some bugs with double vmctx in wasmtime crate

* Trampoline stub needed adjusting
* Use pointer type instead of always using I64 for caller vmctx
* Don't store `ir::Signature` in `Func` since we don't know the pointer
  size at creation time.
* Skip the first 2 arguments in IR signatures since that's the two vmctx
  parameters.

* Update cranelift to 0.56.0

* Handle more merge conflicts

* Rustfmt

Co-authored-by: Alex Crichton <alex@alexcrichton.com>
This commit is contained in:
Dan Gohman
2020-01-21 14:50:59 -08:00
committed by GitHub
parent de72435576
commit 9a88d3d894
33 changed files with 362 additions and 330 deletions

View File

@@ -187,11 +187,13 @@ pub fn invoke(
// Make all JIT code produced thus far executable.
compiler.publish_compiled_code();
// Call the trampoline.
// Call the trampoline. Pass a null `caller_vmctx` argument as `invoke` is
// all about calling from the outside world rather than from an instance.
if let Err(trap) = unsafe {
instance.with_signals_on(|| {
wasmtime_call_trampoline(
callee_vmctx,
ptr::null_mut(),
exec_code_buf,
values_vec.as_mut_ptr() as *mut u8,
)

View File

@@ -282,11 +282,15 @@ fn make_trampoline(
let pointer_type = isa.pointer_type();
let mut wrapper_sig = ir::Signature::new(isa.frontend_config().default_call_conv);
// Add the `vmctx` parameter.
// Add the callee `vmctx` parameter.
wrapper_sig.params.push(ir::AbiParam::special(
pointer_type,
ir::ArgumentPurpose::VMContext,
));
// Add the caller `vmctx` parameter.
wrapper_sig.params.push(ir::AbiParam::new(pointer_type));
// Add the `values_vec` parameter.
wrapper_sig.params.push(ir::AbiParam::new(pointer_type));
@@ -302,9 +306,9 @@ fn make_trampoline(
builder.switch_to_block(block0);
builder.seal_block(block0);
let (vmctx_ptr_val, values_vec_ptr_val) = {
let (vmctx_ptr_val, caller_vmctx_ptr_val, values_vec_ptr_val) = {
let params = builder.func.dfg.ebb_params(block0);
(params[0], params[1])
(params[0], params[1], params[2])
};
// Load the argument values out of `values_vec`.
@@ -314,16 +318,19 @@ fn make_trampoline(
.iter()
.enumerate()
.map(|(i, r)| {
match r.purpose {
// i - 1 because vmctx isn't passed through `values_vec`.
ir::ArgumentPurpose::Normal => builder.ins().load(
r.value_type,
mflags,
values_vec_ptr_val,
((i - 1) * value_size) as i32,
),
ir::ArgumentPurpose::VMContext => vmctx_ptr_val,
other => panic!("unsupported argument purpose {}", other),
match i {
0 => vmctx_ptr_val,
1 => caller_vmctx_ptr_val,
_ =>
// i - 2 because vmctx and caller vmctx aren't passed through `values_vec`.
{
builder.ins().load(
r.value_type,
mflags,
values_vec_ptr_val,
((i - 2) * value_size) as i32,
)
}
}
})
.collect::<Vec<_>>();

View File

@@ -3,9 +3,6 @@ use crate::{
instantiate, ActionError, ActionOutcome, CompilationStrategy, CompiledModule, Compiler,
InstanceHandle, Namespace, RuntimeValue, SetupError,
};
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
use thiserror::Error;
use wasmparser::{validate, OperatorValidatorConfig, ValidatingParserConfig};
use wasmtime_environ::isa::TargetIsa;
@@ -61,7 +58,6 @@ impl Into<ValidatingParserConfig> for Features {
pub struct Context {
namespace: Namespace,
compiler: Box<Compiler>,
global_exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
debug_info: bool,
features: Features,
}
@@ -72,7 +68,6 @@ impl Context {
Self {
namespace: Namespace::new(),
compiler,
global_exports: Rc::new(RefCell::new(HashMap::new())),
debug_info: false,
features: Default::default(),
}
@@ -119,7 +114,6 @@ impl Context {
&data,
None,
&mut self.namespace,
Rc::clone(&self.global_exports),
debug_info,
)
}
@@ -152,13 +146,7 @@ impl Context {
self.validate(&data).map_err(SetupError::Validate)?;
let debug_info = self.debug_info();
CompiledModule::new(
&mut *self.compiler,
data,
None,
Rc::clone(&self.global_exports),
debug_info,
)
CompiledModule::new(&mut *self.compiler, data, None, debug_info)
}
/// If `name` isn't None, register it for the given instance.
@@ -239,12 +227,4 @@ impl Context {
) -> Result<&'instance [u8], ActionError> {
inspect_memory(instance, field_name, start, len)
}
/// Return a handle to the global_exports mapping, needed by some modules
/// for instantiation.
pub fn get_global_exports(
&mut self,
) -> Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>> {
Rc::clone(&self.global_exports)
}
}

View File

@@ -7,8 +7,6 @@ use crate::compiler::Compiler;
use crate::imports::resolve_imports;
use crate::link::link_module;
use crate::resolver::Resolver;
use std::cell::RefCell;
use std::collections::HashMap;
use std::io::Write;
use std::rc::Rc;
use thiserror::Error;
@@ -20,7 +18,7 @@ use wasmtime_environ::{
ModuleSyncString,
};
use wasmtime_runtime::{
Export, GdbJitImageRegistration, InstanceHandle, InstantiationError, VMFunctionBody,
GdbJitImageRegistration, InstanceHandle, InstantiationError, VMFunctionBody,
VMSharedSignatureIndex,
};
@@ -142,7 +140,6 @@ pub struct CompiledModule {
finished_functions: BoxedSlice<DefinedFuncIndex, *const VMFunctionBody>,
data_initializers: Box<[OwnedDataInitializer]>,
signatures: BoxedSlice<SignatureIndex, VMSharedSignatureIndex>,
global_exports: Rc<RefCell<HashMap<String, Option<Export>>>>,
dbg_jit_registration: Option<Rc<GdbJitImageRegistration>>,
}
@@ -152,14 +149,12 @@ impl CompiledModule {
compiler: &mut Compiler,
data: &'data [u8],
module_name: Option<&str>,
global_exports: Rc<RefCell<HashMap<String, Option<Export>>>>,
debug_info: bool,
) -> Result<Self, SetupError> {
let raw = RawCompiledModule::<'data>::new(compiler, data, module_name, debug_info)?;
Ok(Self::from_parts(
raw.module,
global_exports,
raw.finished_functions,
raw.data_initializers
.iter()
@@ -174,7 +169,6 @@ impl CompiledModule {
/// Construct a `CompiledModule` from component parts.
pub fn from_parts(
module: Module,
global_exports: Rc<RefCell<HashMap<String, Option<Export>>>>,
finished_functions: BoxedSlice<DefinedFuncIndex, *const VMFunctionBody>,
data_initializers: Box<[OwnedDataInitializer]>,
signatures: BoxedSlice<SignatureIndex, VMSharedSignatureIndex>,
@@ -182,7 +176,6 @@ impl CompiledModule {
) -> Self {
Self {
module: Rc::new(module),
global_exports: Rc::clone(&global_exports),
finished_functions,
data_initializers,
signatures,
@@ -210,7 +203,6 @@ impl CompiledModule {
let imports = resolve_imports(&self.module, resolver)?;
InstanceHandle::new(
Rc::clone(&self.module),
Rc::clone(&self.global_exports),
self.finished_functions.clone(),
imports,
&data_initializers,
@@ -260,7 +252,6 @@ pub fn instantiate(
data: &[u8],
module_name: Option<&str>,
resolver: &mut dyn Resolver,
global_exports: Rc<RefCell<HashMap<String, Option<Export>>>>,
debug_info: bool,
) -> Result<InstanceHandle, SetupError> {
let raw = RawCompiledModule::new(compiler, data, module_name, debug_info)?;
@@ -268,7 +259,6 @@ pub fn instantiate(
.map_err(|err| SetupError::Instantiate(InstantiationError::Link(err)))?;
InstanceHandle::new(
Rc::new(raw.module),
global_exports,
raw.finished_functions,
imports,
&*raw.data_initializers,