Merge pull request #1065 from alexcrichton/describe-closures

Move closure shims into the descriptor
This commit is contained in:
Alex Crichton
2018-11-29 17:30:58 -06:00
committed by GitHub
11 changed files with 137 additions and 194 deletions

View File

@ -70,11 +70,14 @@ pub enum Descriptor {
#[derive(Debug)]
pub struct Function {
pub arguments: Vec<Descriptor>,
pub shim_idx: u32,
pub ret: Descriptor,
}
#[derive(Debug)]
pub struct Closure {
pub shim_idx: u32,
pub dtor_idx: u32,
pub function: Function,
pub mutable: bool,
}
@ -293,9 +296,13 @@ fn get(a: &mut &[u32]) -> u32 {
impl Closure {
fn decode(data: &mut &[u32]) -> Closure {
let shim_idx = get(data);
let dtor_idx = get(data);
let mutable = get(data) == REFMUT;
assert_eq!(get(data), FUNCTION);
Closure {
shim_idx,
dtor_idx,
mutable,
function: Function::decode(data),
}
@ -304,11 +311,13 @@ impl Closure {
impl Function {
fn decode(data: &mut &[u32]) -> Function {
let shim_idx = get(data);
let arguments = (0..get(data))
.map(|_| Descriptor::_decode(data))
.collect::<Vec<_>>();
Function {
arguments,
shim_idx,
ret: Descriptor::_decode(data),
}
}

View File

@ -47,11 +47,12 @@ pub fn rewrite(input: &mut Context) -> Result<(), Error> {
// If this was an imported function we didn't reorder those, so nothing
// to do.
if idx < old_num_imports {
return idx
idx
} else {
// ... otherwise we're injecting a number of new imports, so offset
// everything.
idx + info.code_idx_to_descriptor.len() as u32
}
// ... otherwise we're injecting a number of new imports, so offset
// everything.
idx + info.code_idx_to_descriptor.len() as u32
}).remap_module(input.module);
info.delete_function_table_entries(input);
@ -252,9 +253,9 @@ impl ClosureDescriptors {
input.expose_add_heap_object();
input.function_table_needed = true;
let body = format!(
"function(a, b, fi, di, _ignored) {{
const f = wasm.__wbg_function_table.get(fi);
const d = wasm.__wbg_function_table.get(di);
"function(a, b, _ignored) {{
const f = wasm.__wbg_function_table.get({});
const d = wasm.__wbg_function_table.get({});
const cb = {};
cb.a = a;
cb.cnt = 1;
@ -262,6 +263,8 @@ impl ClosureDescriptors {
real.original = cb;
return addHeapObject(real);
}}",
closure.shim_idx,
closure.dtor_idx,
js,
);
input.export(&import_name, &body, None);

View File

@ -256,7 +256,6 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
self.cx.expose_uint64_cvt_shim()
};
self.cx.expose_uint32_memory();
self.cx.expose_global_argument_ptr()?;
self.js_arguments.push((name.clone(), "BigInt".to_string()));
self.prelude(&format!(
"
@ -374,7 +373,6 @@ impl<'a, 'b> Js2Rust<'a, 'b> {
self.cx.expose_uint64_cvt_shim()
};
self.cx.expose_uint32_memory();
self.cx.expose_global_argument_ptr()?;
self.js_arguments.push((name.clone(), "BigInt".to_string()));
self.prelude(&format!(
"

View File

@ -459,8 +459,10 @@ impl<'a> Context<'a> {
Ok(String::from("function(idx) { throw takeObject(idx); }"))
})?;
closures::rewrite(self).with_context(|_| {
"failed to generate internal closure shims"
})?;
self.unexport_unused_internal_exports();
closures::rewrite(self)?;
// Handle the `start` function, if one was specified. If we're in a
// --test mode (such as wasm-bindgen-test-runner) then we skip this
@ -1682,23 +1684,6 @@ impl<'a> Context<'a> {
}
}
fn expose_get_global_argument(&mut self) -> Result<(), Error> {
if !self.exposed_globals.insert("get_global_argument") {
return Ok(());
}
self.expose_uint32_memory();
self.expose_global_argument_ptr()?;
self.global(
"
function getGlobalArgument(arg) {
const idx = globalArgumentPtr() / 4 + arg;
return getUint32Memory()[idx];
}
",
);
Ok(())
}
fn expose_global_argument_ptr(&mut self) -> Result<(), Error> {
if !self.exposed_globals.insert("global_argument_ptr") {
return Ok(());
@ -2337,7 +2322,12 @@ impl<'a, 'b> SubContext<'a, 'b> {
self.generate_enum(e);
}
for s in self.program.structs.iter() {
self.generate_struct(s)?;
self.generate_struct(s).with_context(|_| {
format!(
"failed to generate bindings for Rust struct `{}`",
s.name,
)
})?;
}
for s in self.program.typescript_custom_sections.iter() {
self.cx.typescript.push_str(s);

View File

@ -252,6 +252,7 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
}
if let Some((f, mutable)) = arg.stack_closure() {
let arg2 = self.shim_argument();
let (js, _ts, _js_doc) = {
let mut builder = Js2Rust::new("", self.cx);
if mutable {
@ -268,20 +269,19 @@ impl<'a, 'b> Rust2Js<'a, 'b> {
.process(f)?
.finish("function", "this.f")
};
self.cx.expose_get_global_argument()?;
self.cx.function_table_needed = true;
let next_global = self.global_idx();
self.global_idx();
self.prelude(&format!(
"\
let cb{0} = {js};\n\
cb{0}.f = wasm.__wbg_function_table.get({0});\n\
cb{0}.a = getGlobalArgument({next_global});\n\
cb{0}.b = getGlobalArgument({next_global} + 1);\n\
cb{0}.f = wasm.__wbg_function_table.get({idx});\n\
cb{0}.a = {0};\n\
cb{0}.b = {1};\n\
",
abi,
arg2,
js = js,
next_global = next_global
idx = f.shim_idx,
));
self.finally(&format!("cb{0}.a = cb{0}.b = 0;", abi));
self.js_arguments.push(format!("cb{0}.bind(cb{0})", abi));