mirror of
https://github.com/fluencelabs/wasm-bindgen
synced 2025-06-16 22:41:24 +00:00
Remove dependency on wasmi
This is a pretty heavyweight dependency which accounts for a surprising amount of runtime for larger modules in `wasm-bindgen`. We don't need 90% of the crate and so this commit bundles a small interpreter for instructions we know are only going to appear in describe-related functions.
This commit is contained in:
@ -4,14 +4,13 @@ extern crate parity_wasm;
|
||||
extern crate wasm_bindgen_shared as shared;
|
||||
extern crate serde_json;
|
||||
extern crate wasm_gc;
|
||||
extern crate wasmi;
|
||||
#[macro_use]
|
||||
extern crate failure;
|
||||
extern crate wasm_bindgen_wasm_interpreter as wasm_interpreter;
|
||||
|
||||
use std::any::Any;
|
||||
use std::collections::BTreeSet;
|
||||
use std::env;
|
||||
use std::fmt;
|
||||
use std::fs;
|
||||
use std::mem;
|
||||
use std::path::{Path, PathBuf};
|
||||
@ -184,13 +183,7 @@ impl Bindgen {
|
||||
// This means that whenever we encounter an import or export we'll
|
||||
// execute a shim function which informs us about its type so we can
|
||||
// then generate the appropriate bindings.
|
||||
//
|
||||
// TODO: avoid a `clone` here of the module if we can
|
||||
let instance = wasmi::Module::from_parity_wasm_module(module.clone())
|
||||
.with_context(|_| "failed to create wasmi module")?;
|
||||
let instance = wasmi::ModuleInstance::new(&instance, &MyResolver)
|
||||
.with_context(|_| "failed to instantiate wasm module")?;
|
||||
let instance = instance.not_started_instance();
|
||||
let mut instance = wasm_interpreter::Interpreter::new(&module);
|
||||
|
||||
let (js, ts) = {
|
||||
let mut cx = js::Context {
|
||||
@ -206,20 +199,7 @@ impl Bindgen {
|
||||
config: &self,
|
||||
module: &mut module,
|
||||
function_table_needed: false,
|
||||
run_descriptor: &|name| {
|
||||
let mut v = MyExternals(Vec::new());
|
||||
match instance.invoke_export(name, &[], &mut v) {
|
||||
Ok(None) => Some(v.0),
|
||||
Ok(Some(_)) => unreachable!(
|
||||
"there is only one export, and we only return None from it"
|
||||
),
|
||||
// Allow missing exported describe functions. This can
|
||||
// happen when a nested dependency crate exports things
|
||||
// but the root crate doesn't use them.
|
||||
Err(wasmi::Error::Function(_)) => None,
|
||||
Err(e) => panic!("unexpected error running descriptor: {}", e),
|
||||
}
|
||||
},
|
||||
interpreter: &mut instance,
|
||||
};
|
||||
for program in programs.iter() {
|
||||
js::SubContext {
|
||||
@ -409,106 +389,6 @@ to open an issue at https://github.com/rustwasm/wasm-bindgen/issues!
|
||||
Ok(ret)
|
||||
}
|
||||
|
||||
struct MyResolver;
|
||||
|
||||
impl wasmi::ImportResolver for MyResolver {
|
||||
fn resolve_func(
|
||||
&self,
|
||||
module_name: &str,
|
||||
field_name: &str,
|
||||
signature: &wasmi::Signature,
|
||||
) -> Result<wasmi::FuncRef, wasmi::Error> {
|
||||
// Route our special "describe" export to 1 and everything else to 0.
|
||||
// That way whenever the function 1 is invoked we know what to do and
|
||||
// when 0 is invoked (by accident) we'll trap and produce an error.
|
||||
let idx = (module_name == "__wbindgen_placeholder__" && field_name == "__wbindgen_describe")
|
||||
as usize;
|
||||
Ok(wasmi::FuncInstance::alloc_host(signature.clone(), idx))
|
||||
}
|
||||
|
||||
fn resolve_global(
|
||||
&self,
|
||||
_module_name: &str,
|
||||
_field_name: &str,
|
||||
descriptor: &wasmi::GlobalDescriptor,
|
||||
) -> Result<wasmi::GlobalRef, wasmi::Error> {
|
||||
// dummy implementation to ensure instantiation succeeds
|
||||
let val = match descriptor.value_type() {
|
||||
wasmi::ValueType::I32 => wasmi::RuntimeValue::I32(0),
|
||||
wasmi::ValueType::I64 => wasmi::RuntimeValue::I64(0),
|
||||
wasmi::ValueType::F32 => wasmi::RuntimeValue::F32(0.0.into()),
|
||||
wasmi::ValueType::F64 => wasmi::RuntimeValue::F64(0.0.into()),
|
||||
};
|
||||
Ok(wasmi::GlobalInstance::alloc(val, descriptor.is_mutable()))
|
||||
}
|
||||
|
||||
fn resolve_memory(
|
||||
&self,
|
||||
_module_name: &str,
|
||||
_field_name: &str,
|
||||
descriptor: &wasmi::MemoryDescriptor,
|
||||
) -> Result<wasmi::MemoryRef, wasmi::Error> {
|
||||
// dummy implementation to ensure instantiation succeeds
|
||||
use wasmi::memory_units::Pages;
|
||||
let initial = Pages(descriptor.initial() as usize);
|
||||
let maximum = descriptor.maximum().map(|i| Pages(i as usize));
|
||||
wasmi::MemoryInstance::alloc(initial, maximum)
|
||||
}
|
||||
|
||||
fn resolve_table(
|
||||
&self,
|
||||
_module_name: &str,
|
||||
_field_name: &str,
|
||||
descriptor: &wasmi::TableDescriptor,
|
||||
) -> Result<wasmi::TableRef, wasmi::Error> {
|
||||
// dummy implementation to ensure instantiation succeeds
|
||||
let initial = descriptor.initial();
|
||||
let maximum = descriptor.maximum();
|
||||
wasmi::TableInstance::alloc(initial, maximum)
|
||||
}
|
||||
}
|
||||
|
||||
struct MyExternals(Vec<u32>);
|
||||
|
||||
#[derive(Debug)]
|
||||
struct MyError(String);
|
||||
|
||||
impl wasmi::Externals for MyExternals {
|
||||
fn invoke_index(
|
||||
&mut self,
|
||||
index: usize,
|
||||
args: wasmi::RuntimeArgs,
|
||||
) -> Result<Option<wasmi::RuntimeValue>, wasmi::Trap> {
|
||||
macro_rules! bail {
|
||||
($($t:tt)*) => ({
|
||||
let s = MyError(format!($($t)*));
|
||||
return Err(wasmi::Trap::new(wasmi::TrapKind::Host(Box::new(s))))
|
||||
})
|
||||
}
|
||||
// We only recognize one function here which was mapped to the index 1
|
||||
// by the resolver above.
|
||||
if index != 1 {
|
||||
bail!("only __wbindgen_describe can be run at this time")
|
||||
}
|
||||
if args.len() != 1 {
|
||||
bail!("must have exactly one argument");
|
||||
}
|
||||
match args.nth_value_checked(0)? {
|
||||
wasmi::RuntimeValue::I32(i) => self.0.push(i as u32),
|
||||
_ => bail!("expected one argument of i32 type"),
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
}
|
||||
|
||||
impl wasmi::HostError for MyError {}
|
||||
|
||||
impl fmt::Display for MyError {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
self.0.fmt(f)
|
||||
}
|
||||
}
|
||||
|
||||
fn reset_indentation(s: &str) -> String {
|
||||
let mut indent: u32 = 0;
|
||||
let mut dst = String::new();
|
||||
|
Reference in New Issue
Block a user