Further optimize non-debug output

Remove a bunch of exception throws in favor of type casts in TypeScript and
remove some type assertions as well that TypeScript should uphold.
This commit is contained in:
Alex Crichton 2017-12-20 13:24:18 -08:00
parent 5d697c196f
commit 6aacff6a80
3 changed files with 157 additions and 51 deletions

View File

@ -14,6 +14,7 @@ thread_local!(static IDX: usize = CNT.fetch_add(1, Ordering::SeqCst));
pub struct Project { pub struct Project {
files: Vec<(String, String)>, files: Vec<(String, String)>,
debug: bool,
} }
pub fn project() -> Project { pub fn project() -> Project {
@ -25,6 +26,7 @@ pub fn project() -> Project {
fs::File::open(&dir.join("Cargo.lock")).unwrap() fs::File::open(&dir.join("Cargo.lock")).unwrap()
.read_to_string(&mut lockfile).unwrap(); .read_to_string(&mut lockfile).unwrap();
Project { Project {
debug: true,
files: vec![ files: vec![
("Cargo.toml".to_string(), format!(r#" ("Cargo.toml".to_string(), format!(r#"
[package] [package]
@ -57,8 +59,8 @@ pub fn project() -> Project {
instantiate(wasm, test.imports).then(m => { instantiate(wasm, test.imports).then(m => {
test.test(m); test.test(m);
if (m.assertHeapAndStackEmpty) if ((m as any).assertHeapAndStackEmpty)
m.assertHeapAndStackEmpty(); (m as any).assertHeapAndStackEmpty();
}).catch(error => { }).catch(error => {
console.error(error); console.error(error);
process.exit(1); process.exit(1);
@ -118,6 +120,11 @@ impl Project {
self self
} }
pub fn debug(&mut self, debug: bool) -> &mut Project {
self.debug = debug;
self
}
pub fn test(&mut self) { pub fn test(&mut self) {
let root = root(); let root = root();
drop(fs::remove_dir_all(&root)); drop(fs::remove_dir_all(&root));
@ -151,7 +158,7 @@ impl Project {
let obj = cli::Bindgen::new() let obj = cli::Bindgen::new()
.input_path(&out) .input_path(&out)
.nodejs(true) .nodejs(true)
.debug(true) .debug(self.debug)
.generate() .generate()
.expect("failed to run bindgen"); .expect("failed to run bindgen");
obj.write_ts_to(root.join("out.ts")).expect("failed to write ts"); obj.write_ts_to(root.join("out.ts")).expect("failed to write ts");

View File

@ -40,20 +40,31 @@ impl Js {
pub fn generate_struct(&mut self, s: &shared::Struct) { pub fn generate_struct(&mut self, s: &shared::Struct) {
let mut dst = String::new(); let mut dst = String::new();
self.expose_check_token();
self.expose_wasm_exports(); self.expose_wasm_exports();
dst.push_str(&format!(" dst.push_str(&format!("
export class {} {{ export class {} {{
", s.name));
if self.debug {
self.expose_check_token();
dst.push_str(&format!("
constructor(public __wasmPtr: number, sym: Symbol) {{ constructor(public __wasmPtr: number, sym: Symbol) {{
_checkToken(sym); _checkToken(sym);
}} }}
"));
} else {
dst.push_str(&format!("
constructor(public __wasmPtr: number) {{}}
"));
}
dst.push_str(&format!("
free(): void {{ free(): void {{
const ptr = this.__wasmPtr; const ptr = this.__wasmPtr;
this.__wasmPtr = 0; this.__wasmPtr = 0;
wasm_exports.{}(ptr); wasm_exports.{}(ptr);
}} }}
", s.name, s.free_function())); ", s.free_function()));
self.wasm_exports_bound.insert(s.name.clone()); self.wasm_exports_bound.insert(s.name.clone());
for function in s.functions.iter() { for function in s.functions.iter() {
@ -222,9 +233,15 @@ impl Js {
Some(&shared::Type::ByRef(_)) => panic!(), Some(&shared::Type::ByRef(_)) => panic!(),
Some(&shared::Type::ByValue(ref name)) => { Some(&shared::Type::ByValue(ref name)) => {
dst.push_str(name); dst.push_str(name);
if self.debug {
format!("\ format!("\
return new {name}(ret, token); return new {name}(ret, token);
", name = name) ", name = name)
} else {
format!("\
return new {name}(ret);
", name = name)
}
} }
Some(&shared::Type::String) => { Some(&shared::Type::String) => {
dst.push_str("string"); dst.push_str("string");
@ -484,22 +501,28 @@ impl Js {
if self.wasm_import_needed("__wbindgen_object_clone_ref", m) { if self.wasm_import_needed("__wbindgen_object_clone_ref", m) {
self.expose_add_heap_object(); self.expose_add_heap_object();
self.expose_get_object(); self.expose_get_object();
imports_object.push_str(" let bump_cnt = if self.debug {
__wbindgen_object_clone_ref: function(idx: number): number { String::from("
if (typeof(val) === 'number')
throw new Error('corrupt slab');
val.cnt += 1;
")
} else {
String::from("(val as {cnt:number}).cnt += 1;")
};
imports_object.push_str(&format!("
__wbindgen_object_clone_ref: function(idx: number): number {{
// If this object is on the stack promote it to the heap. // If this object is on the stack promote it to the heap.
if ((idx & 1) === 1) { if ((idx & 1) === 1)
return addHeapObject(getObject(idx)); return addHeapObject(getObject(idx));
}
// Otherwise if the object is on the heap just bump the // Otherwise if the object is on the heap just bump the
// refcount and move on // refcount and move on
const val = slab[idx >> 1]; const val = slab[idx >> 1];
if (typeof(val) === 'number') {}
throw new Error('corrupt slab');
val.cnt += 1;
return idx; return idx;
}, }},
"); ", bump_cnt));
} }
if self.wasm_import_needed("__wbindgen_object_drop_ref", m) { if self.wasm_import_needed("__wbindgen_object_drop_ref", m) {
@ -715,25 +738,41 @@ impl Js {
} }
self.expose_global_slab(); self.expose_global_slab();
self.expose_global_slab_next(); self.expose_global_slab_next();
self.globals.push_str(" let validate_owned = if self.debug {
function dropRef(idx: number): void { String::from("
if ((idx & 1) == 1) if ((idx & 1) === 1)
throw new Error('cannot drop ref of stack objects'); throw new Error('cannot drop ref of stack objects');
")
// Decrement our refcount, but if it's still larger than one } else {
// keep going String::new()
let obj = slab[idx >> 1]; };
let dec_ref = if self.debug {
String::from("
if (typeof(obj) === 'number') if (typeof(obj) === 'number')
throw new Error('corrupt slab'); throw new Error('corrupt slab');
obj.cnt -= 1; obj.cnt -= 1;
if (obj.cnt > 0) if (obj.cnt > 0)
return; return;
")
} else {
String::from("
(obj as {cnt:number}).cnt -= 1;
if ((obj as {cnt:number}).cnt > 0)
return;
")
};
self.globals.push_str(&format!("
function dropRef(idx: number): void {{
{}
let obj = slab[idx >> 1];
{}
// If we hit 0 then free up our space in the slab // If we hit 0 then free up our space in the slab
slab[idx >> 1] = slab_next; slab[idx >> 1] = slab_next;
slab_next = idx >> 1; slab_next = idx >> 1;
} }}
"); ", validate_owned, dec_ref));
} }
fn expose_global_stack(&mut self) { fn expose_global_stack(&mut self) {
@ -769,18 +808,28 @@ impl Js {
} }
self.expose_global_stack(); self.expose_global_stack();
self.expose_global_slab(); self.expose_global_slab();
self.globals.push_str("
function getObject(idx: number): any { let get_obj = if self.debug {
if ((idx & 1) === 1) { String::from("
return stack[idx >> 1];
} else {
const val = slab[idx >> 1];
if (typeof(val) === 'number') if (typeof(val) === 'number')
throw new Error('corrupt slab'); throw new Error('corrupt slab');
return val.obj; return val.obj;
} ")
} } else {
"); String::from("
return (val as {obj:any}).obj;
")
};
self.globals.push_str(&format!("
function getObject(idx: number): any {{
if ((idx & 1) === 1) {{
return stack[idx >> 1];
}} else {{
const val = slab[idx >> 1];
{}
}}
}}
", get_obj));
} }
fn expose_global_memory(&mut self) { fn expose_global_memory(&mut self) {
@ -945,19 +994,27 @@ impl Js {
} }
self.expose_global_slab(); self.expose_global_slab();
self.expose_global_slab_next(); self.expose_global_slab_next();
self.globals.push_str(" let set_slab_next = if self.debug {
function addHeapObject(obj: any): number { String::from("
if (slab_next == slab.length) {
slab.push(slab.length + 1);
}
const idx = slab_next;
const next = slab[idx];
if (typeof(next) !== 'number') if (typeof(next) !== 'number')
throw new Error('corrupt slab'); throw new Error('corrupt slab');
slab_next = next; slab_next = next;
slab[idx] = { obj, cnt: 1 }; ")
} else {
String::from("
slab_next = next as number;
")
};
self.globals.push_str(&format!("
function addHeapObject(obj: any): number {{
if (slab_next == slab.length)
slab.push(slab.length + 1);
const idx = slab_next;
const next = slab[idx];
{}
slab[idx] = {{ obj, cnt: 1 }};
return idx << 1; return idx << 1;
} }}
"); ", set_slab_next));
} }
} }

42
tests/non-debug.rs Normal file
View File

@ -0,0 +1,42 @@
extern crate test_support;
#[test]
fn works() {
test_support::project()
.debug(false)
.file("src/lib.rs", r#"
#![feature(proc_macro)]
extern crate wasm_bindgen;
use wasm_bindgen::prelude::*;
wasm_bindgen! {
pub struct A {}
impl A {
pub fn new() -> A {
A {}
}
}
pub fn clone(a: &JsObject) -> JsObject {
drop(a.clone());
a.clone()
}
}
"#)
.file("test.ts", r#"
import * as assert from "assert";
import { Exports, Imports } from "./out";
export const imports: Imports = {};
export function test(wasm: Exports) {
let sym = Symbol('a');
assert.strictEqual(wasm.clone(sym), sym);
let a = wasm.A.new();
a.free();
}
"#)
.test();
}