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

@@ -2,8 +2,6 @@ use cranelift_codegen::ir::types;
use cranelift_codegen::{ir, isa};
use cranelift_entity::PrimaryMap;
use cranelift_wasm::DefinedFuncIndex;
use std::cell::RefCell;
use std::collections::HashMap;
use std::fs::File;
use std::rc::Rc;
use target_lexicon::HOST;
@@ -19,15 +17,13 @@ pub fn create_wasi_instance(
argv: &[String],
environ: &[(String, String)],
) -> Result<wasmtime::Instance, InstantiationError> {
let global_exports = store.global_exports().clone();
let wasi = instantiate_wasi(global_exports, preopened_dirs, argv, environ)?;
let wasi = instantiate_wasi(preopened_dirs, argv, environ)?;
let instance = wasmtime::Instance::from_handle(&store, wasi);
Ok(instance)
}
/// Return an instance implementing the "wasi" interface.
pub fn instantiate_wasi(
global_exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
preopened_dirs: &[(String, File)],
argv: &[String],
environ: &[(String, String)],
@@ -52,14 +48,13 @@ pub fn instantiate_wasi(
let wasi_ctx = wasi_ctx_builder.build().map_err(|err| {
InstantiationError::Resource(format!("couldn't assemble WASI context object: {}", err))
})?;
instantiate_wasi_with_context(global_exports, wasi_ctx)
instantiate_wasi_with_context(wasi_ctx)
}
/// Return an instance implementing the "wasi" interface.
///
/// The wasi context is configured by
pub fn instantiate_wasi_with_context(
global_exports: Rc<RefCell<HashMap<String, Option<wasmtime_runtime::Export>>>>,
wasi_ctx: WasiCtx,
) -> Result<InstanceHandle, InstantiationError> {
let pointer_type = types::Type::triple_pointer_type(&HOST);
@@ -84,7 +79,6 @@ pub fn instantiate_wasi_with_context(
InstanceHandle::new(
Rc::new(module),
global_exports,
finished_functions.into_boxed_slice(),
imports,
&data_initializers,
@@ -109,24 +103,25 @@ fn get_wasi_ctx(vmctx: &mut VMContext) -> Result<&mut WasiCtx, wasi::__wasi_errn
}
// Used by `add_wrappers_to_module` defined in the macro above
fn get_memory(vmctx: &mut VMContext) -> Result<&mut [u8], wasi::__wasi_errno_t> {
unsafe {
match vmctx.lookup_global_export("memory") {
Some(wasmtime_runtime::Export::Memory {
definition,
vmctx: _,
memory: _,
}) => Ok(std::slice::from_raw_parts_mut(
(*definition).base,
(*definition).current_length,
)),
x => {
log::error!(
"no export named \"memory\", or the export isn't a mem: {:?}",
x
);
Err(wasi::__WASI_ERRNO_INVAL)
}
fn get_memory(caller_vmctx: &mut VMContext) -> Result<&mut [u8], wasi::__wasi_errno_t> {
match unsafe { InstanceHandle::from_vmctx(caller_vmctx) }.lookup("memory") {
Some(wasmtime_runtime::Export::Memory {
definition,
vmctx: _,
memory: _,
}) => unsafe {
let definition = &*definition;
let ptr = definition.base;
let len = definition.current_length;
Ok(std::slice::from_raw_parts_mut(ptr, len))
},
Some(export) => {
log::error!("export named \"memory\" isn't a memory: {:?}", export);
Err(wasi::__WASI_ERRNO_INVAL)
}
None => {
log::error!("no export named \"memory\" available from caller");
Err(wasi::__WASI_ERRNO_INVAL)
}
}
}