Add reference output tests for JS operations (#1894)

* Add reference output tests for JS operations

This commit starts adding a test suite which checks in, to the
repository, test assertions for both the JS and wasm file outputs of a
Rust crate compiled with `#[wasm_bindgen]`. These aren't intended to be
exhaustive or large scale tests, but rather micro-tests to help observe
the changes in `wasm-bindgen`'s output over time.

The motivation for this commit is basically overhauling how all the GC
passes work in `wasm-bindgen` today. The reorganization is also included
in this commit as well.

Previously `wasm-bindgen` would, in an ad-hoc fashion, run the GC passes
of `walrus` in a bunch of places to ensure that less "garbage" was seen
by future passes. This not only was a source of slowdown but it also was
pretty brittle since `wasm-bindgen` kept breaking if extra iteams leaked
through.

The strategy taken in this commit is to have one precise location for a
GC pass, and everything goes through there. This is achieved by:

* All internal exports are removed immediately when generating the
  nonstandard wasm interface types section. Internal exports,
  intrinsics, and runtime support are all referenced by the various
  instructions and/or sections that use them. This means that we now
  have precise tracking of what an adapter uses.

* This in turn enables us to implement the `add_gc_roots` function for
  `walrus` custom sections, which in turn allows walrus GC passes to do
  what `unexport_unused_intrinsics` did before. That function is now no
  longer necessary, but effectively works the same way. All intrinsics
  are unexported at the beginning and then they're selectively
  re-imported and re-exported through the JS glue generation pass as
  necessary and defined by the bindings.

* Passes like the `anyref` pass are now much more precise about the
  intrinsics that they work with. The `anyref` pass also deletes any
  internal intrinsics found and also does some rewriting of the adapters
  aftewards now to hook up calls to the heap count import to the heap
  count intrinsic in the wasm module.

* Fix handling of __wbindgen_realloc

The final user of the `require_internal_export` function was
`__wbindgen_realloc`. This usage has now been removed by updating how we
handle usage of the `realloc` function.

The wasm interface types standard doesn't have a `realloc` function
slot, nor do I think it ever will. This means that as a polyfill for
wasm interface types we'll always have to support the lack of `realloc`.
For direct Rust to JS, however, we can still optionally handle
`realloc`. This is all handled with a few internal changes.

* Custom `StringToMemory` instructions now exist. These have an extra
  `realloc` slot to store an intrinsic, if found.
* Our custom instructions are lowered to the standard instructions when
  generating an interface types section.
* The `realloc` function, if present, is passed as an argument like the
  malloc function when passing strings to wasm. If it's not present we
  use a slower fallback, but if it's present we use the faster
  implementation.

This should mean that there's little-to-no impact on existing users of
`wasm-bindgen`, but this should continue to still work for wasm
interface types polyfills and such. Additionally the GC passes now work
in that they don't delete `__wbindgen_realloc` which we later try to
reference.

* Add an empty test for the anyref pass

* Precisely track I32FromOptionAnyref's dependencies

This depends on the anyref table and a function to allocate an index if
the anyref pass is running, so be sure to track that in the instruction
itself for GC rooting.

* Trim extraneous exports from nop anyref module

Or if you're otherwise not using anyref slices, don't force some
intrinsics to exist.

* Remove globals from reference tests

Looks like these values adjust in slight but insignificant ways over
time

* Update the anyref xform tests
This commit is contained in:
Alex Crichton
2019-12-04 12:01:39 -06:00
committed by GitHub
parent 9469c1641b
commit d7a4a772cf
52 changed files with 1263 additions and 357 deletions

View File

@ -48,6 +48,7 @@ pub struct Meta {
pub table: TableId,
pub alloc: Option<FunctionId>,
pub drop_slice: Option<FunctionId>,
pub live_count: Option<FunctionId>,
}
struct Transform<'a> {
@ -178,20 +179,27 @@ impl Context {
let mut heap_alloc = None;
let mut heap_dealloc = None;
let mut drop_slice = None;
let mut live_count = None;
// Find exports of some intrinsics which we only need for a runtime
// implementation.
let mut to_delete = Vec::new();
for export in module.exports.iter() {
let f = match export.item {
walrus::ExportItem::Function(f) => f,
_ => continue,
};
match export.name.as_str() {
"__wbindgen_anyref_table_alloc" => heap_alloc = Some(f),
"__wbindgen_anyref_table_dealloc" => heap_dealloc = Some(f),
"__wbindgen_drop_anyref_slice" => drop_slice = Some(f),
"__anyref_table_alloc" => heap_alloc = Some(f),
"__anyref_table_dealloc" => heap_dealloc = Some(f),
"__anyref_drop_slice" => drop_slice = Some(f),
"__anyref_heap_live_count" => live_count = Some(f),
_ => continue,
}
to_delete.push(export.id());
}
for id in to_delete {
module.exports.delete(id);
}
let mut clone_ref = None;
if let Some(heap_alloc) = heap_alloc {
@ -240,6 +248,7 @@ impl Context {
table,
alloc: heap_alloc,
drop_slice,
live_count,
})
}
}

View File

@ -2,9 +2,9 @@
(module
(func $foo (export "foo") (param i32))
(func $alloc (export "__wbindgen_anyref_table_alloc") (result i32)
(func $alloc (export "__anyref_table_alloc") (result i32)
i32.const 0)
(func $dealloc (export "__wbindgen_anyref_table_dealloc") (param i32))
(func $dealloc (export "__anyref_table_dealloc") (param i32))
)
(; CHECK-ALL:
@ -23,9 +23,6 @@
(func $alloc (type 0) (result i32)
i32.const 0)
(func $foo (type 1) (param i32))
(func $dealloc (type 1) (param i32))
(table (;0;) 32 anyref)
(export "foo" (func $foo anyref shim))
(export "__wbindgen_anyref_table_alloc" (func $alloc))
(export "__wbindgen_anyref_table_dealloc" (func $dealloc)))
(export "foo" (func $foo anyref shim)))
;)

View File

@ -2,17 +2,16 @@
(module
(func $foo (export "foo") (param i32))
(func $alloc (export "__wbindgen_anyref_table_alloc") (result i32)
(func $alloc (export "__anyref_table_alloc") (result i32)
i32.const 0)
(func $dealloc (export "__wbindgen_anyref_table_dealloc") (param i32))
(func $dealloc (export "__anyref_table_dealloc") (param i32))
)
(; CHECK-ALL:
(module
(type (;0;) (func (result i32)))
(type (;1;) (func (param i32)))
(type (;2;) (func (param anyref)))
(func $foo anyref shim (type 2) (param anyref)
(type (;0;) (func (param i32)))
(type (;1;) (func (param anyref)))
(func $foo anyref shim (type 1) (param anyref)
(local i32)
global.get 0
i32.const 1
@ -31,13 +30,8 @@
i32.const 1
i32.add
global.set 0)
(func $alloc (type 0) (result i32)
i32.const 0)
(func $foo (type 1) (param i32))
(func $dealloc (type 1) (param i32))
(func $foo (type 0) (param i32))
(table (;0;) 32 anyref)
(global (;0;) (mut i32) (i32.const 32))
(export "foo" (func $foo anyref shim))
(export "__wbindgen_anyref_table_alloc" (func $alloc))
(export "__wbindgen_anyref_table_dealloc" (func $dealloc)))
(export "foo" (func $foo anyref shim)))
;)

View File

@ -6,9 +6,9 @@
(func $foo (export "foo") (param i32) (result i32)
local.get 0
call $clone)
(func $alloc (export "__wbindgen_anyref_table_alloc") (result i32)
(func $alloc (export "__anyref_table_alloc") (result i32)
i32.const 0)
(func $dealloc (export "__wbindgen_anyref_table_dealloc") (param i32))
(func $dealloc (export "__anyref_table_dealloc") (param i32))
)
(; CHECK-ALL:
@ -44,7 +44,5 @@
i32.const 0)
(func $dealloc (type 1) (param i32))
(table (;0;) 32 anyref)
(export "foo" (func $foo anyref shim))
(export "__wbindgen_anyref_table_alloc" (func $alloc))
(export "__wbindgen_anyref_table_dealloc" (func $dealloc)))
(export "foo" (func $foo anyref shim)))
;)

View File

@ -6,9 +6,9 @@
(func $foo (export "foo") (param i32)
local.get 0
call $drop)
(func $alloc (export "__wbindgen_anyref_table_alloc") (result i32)
(func $alloc (export "__anyref_table_alloc") (result i32)
i32.const 0)
(func $dealloc (export "__wbindgen_anyref_table_dealloc") (param i32))
(func $dealloc (export "__anyref_table_dealloc") (param i32))
)
(; CHECK-ALL:
@ -31,7 +31,5 @@
i32.const 0)
(func $dealloc (type 1) (param i32))
(table (;0;) 32 anyref)
(export "foo" (func $foo anyref shim))
(export "__wbindgen_anyref_table_alloc" (func $alloc))
(export "__wbindgen_anyref_table_dealloc" (func $dealloc)))
(export "foo" (func $foo anyref shim)))
;)

View File

@ -5,19 +5,18 @@
(func (export "foo")
i32.const 0
call $a)
(func $alloc (export "__wbindgen_anyref_table_alloc") (result i32)
(func $alloc (export "__anyref_table_alloc") (result i32)
i32.const 0)
(func $dealloc (export "__wbindgen_anyref_table_dealloc") (param i32))
(func $dealloc (export "__anyref_table_dealloc") (param i32))
)
(; CHECK-ALL:
(module
(type (;0;) (func))
(type (;1;) (func (result i32)))
(type (;2;) (func (param i32)))
(type (;3;) (func (param anyref)))
(import "" "a" (func $a (type 3)))
(func $a anyref shim (type 2) (param i32)
(type (;1;) (func (param i32)))
(type (;2;) (func (param anyref)))
(import "" "a" (func $a (type 2)))
(func $a anyref shim (type 1) (param i32)
local.get 0
table.get 0
local.get 0
@ -26,11 +25,7 @@
(func (;2;) (type 0)
i32.const 0
call $a anyref shim)
(func $alloc (type 1) (result i32)
i32.const 0)
(func $dealloc (type 2) (param i32))
(func $dealloc (type 1) (param i32))
(table (;0;) 32 anyref)
(export "foo" (func 2))
(export "__wbindgen_anyref_table_alloc" (func $alloc))
(export "__wbindgen_anyref_table_dealloc" (func $dealloc)))
(export "foo" (func 2)))
;)

View File

@ -4,16 +4,15 @@
(import "" "a" (func $a (result i32)))
(func (export "foo") (result i32)
call $a)
(func $alloc (export "__wbindgen_anyref_table_alloc") (result i32)
(func $alloc (export "__anyref_table_alloc") (result i32)
i32.const 0)
(func $dealloc (export "__wbindgen_anyref_table_dealloc") (param i32))
(func $dealloc (export "__anyref_table_dealloc") (param i32))
)
(; CHECK-ALL:
(module
(type (;0;) (func (result i32)))
(type (;1;) (func (result anyref)))
(type (;2;) (func (param i32)))
(import "" "a" (func $a (type 1)))
(func $a anyref shim (type 0) (result i32)
(local i32 anyref)
@ -28,9 +27,6 @@
call $a anyref shim)
(func $alloc (type 0) (result i32)
i32.const 0)
(func $dealloc (type 2) (param i32))
(table (;0;) 32 anyref)
(export "foo" (func 2))
(export "__wbindgen_anyref_table_alloc" (func $alloc))
(export "__wbindgen_anyref_table_dealloc" (func $dealloc)))
(export "foo" (func 2)))
;)

View File

@ -5,30 +5,24 @@
(func (export "foo")
i32.const 0
call $a)
(func $alloc (export "__wbindgen_anyref_table_alloc") (result i32)
(func $alloc (export "__anyref_table_alloc") (result i32)
i32.const 0)
(func $dealloc (export "__wbindgen_anyref_table_dealloc") (param i32))
(func $dealloc (export "__anyref_table_dealloc") (param i32))
)
(; CHECK-ALL:
(module
(type (;0;) (func))
(type (;1;) (func (result i32)))
(type (;2;) (func (param i32)))
(type (;3;) (func (param anyref)))
(import "" "a" (func $a (type 3)))
(func $a anyref shim (type 2) (param i32)
(type (;1;) (func (param i32)))
(type (;2;) (func (param anyref)))
(import "" "a" (func $a (type 2)))
(func $a anyref shim (type 1) (param i32)
local.get 0
table.get 0
call $a)
(func (;2;) (type 0)
i32.const 0
call $a anyref shim)
(func $alloc (type 1) (result i32)
i32.const 0)
(func $dealloc (type 2) (param i32))
(table (;0;) 32 anyref)
(export "foo" (func 2))
(export "__wbindgen_anyref_table_alloc" (func $alloc))
(export "__wbindgen_anyref_table_dealloc" (func $dealloc)))
(export "foo" (func 2)))
;)

View File

@ -2,18 +2,17 @@
(module
(func $a (export "a") (param f32 i32 i64 i32 i32))
(func $alloc (export "__wbindgen_anyref_table_alloc") (result i32)
(func $alloc (export "__anyref_table_alloc") (result i32)
i32.const 0)
(func $dealloc (export "__wbindgen_anyref_table_dealloc") (param i32))
(func $dealloc (export "__anyref_table_dealloc") (param i32))
)
(; CHECK-ALL:
(module
(type (;0;) (func (result i32)))
(type (;1;) (func (param i32)))
(type (;2;) (func (param f32 i32 i64 i32 i32)))
(type (;3;) (func (param f32 anyref i64 anyref i32)))
(func $a anyref shim (type 3) (param f32 anyref i64 anyref i32)
(type (;1;) (func (param f32 i32 i64 i32 i32)))
(type (;2;) (func (param f32 anyref i64 anyref i32)))
(func $a anyref shim (type 2) (param f32 anyref i64 anyref i32)
(local i32 i32)
global.get 0
i32.const 1
@ -42,11 +41,8 @@
global.set 0)
(func $alloc (type 0) (result i32)
i32.const 0)
(func $a (type 2) (param f32 i32 i64 i32 i32))
(func $dealloc (type 1) (param i32))
(func $a (type 1) (param f32 i32 i64 i32 i32))
(table (;0;) 32 anyref)
(global (;0;) (mut i32) (i32.const 32))
(export "a" (func $a anyref shim))
(export "__wbindgen_anyref_table_alloc" (func $alloc))
(export "__wbindgen_anyref_table_dealloc" (func $dealloc)))
(export "a" (func $a anyref shim)))
;)

View File

@ -9,20 +9,19 @@
i32.const 4
i32.const 5
call $a)
(func $alloc (export "__wbindgen_anyref_table_alloc") (result i32)
(func $alloc (export "__anyref_table_alloc") (result i32)
i32.const 0)
(func $dealloc (export "__wbindgen_anyref_table_dealloc") (param i32))
(func $dealloc (export "__anyref_table_dealloc") (param i32))
)
(; CHECK-ALL:
(module
(type (;0;) (func))
(type (;1;) (func (result i32)))
(type (;2;) (func (param i32)))
(type (;3;) (func (param f32 i32 i64 i32 i32)))
(type (;4;) (func (param f32 anyref i64 anyref i32)))
(import "" "a" (func $a (type 4)))
(func $a anyref shim (type 3) (param f32 i32 i64 i32 i32)
(type (;1;) (func (param i32)))
(type (;2;) (func (param f32 i32 i64 i32 i32)))
(type (;3;) (func (param f32 anyref i64 anyref i32)))
(import "" "a" (func $a (type 3)))
(func $a anyref shim (type 2) (param f32 i32 i64 i32 i32)
local.get 0
local.get 1
table.get 0
@ -40,11 +39,7 @@
i32.const 4
i32.const 5
call $a anyref shim)
(func $alloc (type 1) (result i32)
i32.const 0)
(func $dealloc (type 2) (param i32))
(func $dealloc (type 1) (param i32))
(table (;0;) 32 anyref)
(export "foo" (func 2))
(export "__wbindgen_anyref_table_alloc" (func $alloc))
(export "__wbindgen_anyref_table_dealloc" (func $dealloc)))
(export "foo" (func 2)))
;)

View File

@ -4,9 +4,9 @@
(func $foo (export "foo") (result i32)
i32.const 0)
(func $alloc (export "__wbindgen_anyref_table_alloc") (result i32)
(func $alloc (export "__anyref_table_alloc") (result i32)
i32.const 0)
(func $dealloc (export "__wbindgen_anyref_table_dealloc") (param i32))
(func $dealloc (export "__anyref_table_dealloc") (param i32))
)
(; CHECK-ALL:
@ -23,11 +23,7 @@
call $dealloc)
(func $foo (type 0) (result i32)
i32.const 0)
(func $alloc (type 0) (result i32)
i32.const 0)
(func $dealloc (type 2) (param i32))
(table (;0;) 32 anyref)
(export "foo" (func $foo anyref shim))
(export "__wbindgen_anyref_table_alloc" (func $alloc))
(export "__wbindgen_anyref_table_dealloc" (func $dealloc)))
(export "foo" (func $foo anyref shim)))
;)

View File

@ -7,9 +7,9 @@
i32.const 0
call $grow
drop)
(func $alloc (export "__wbindgen_anyref_table_alloc") (result i32)
(func $alloc (export "__anyref_table_alloc") (result i32)
i32.const 0)
(func $dealloc (export "__wbindgen_anyref_table_dealloc") (param i32))
(func $dealloc (export "__anyref_table_dealloc") (param i32))
)
(; CHECK-ALL:
@ -32,9 +32,6 @@
drop)
(func $alloc (type 0) (result i32)
i32.const 0)
(func $dealloc (type 1) (param i32))
(table (;0;) 32 anyref)
(export "foo" (func $foo anyref shim))
(export "__wbindgen_anyref_table_alloc" (func $alloc))
(export "__wbindgen_anyref_table_dealloc" (func $dealloc)))
(export "foo" (func $foo anyref shim)))
;)

View File

@ -6,9 +6,9 @@
(func $foo (export "foo") (param i32)
local.get 0
call $set-null)
(func $alloc (export "__wbindgen_anyref_table_alloc") (result i32)
(func $alloc (export "__anyref_table_alloc") (result i32)
i32.const 0)
(func $dealloc (export "__wbindgen_anyref_table_dealloc") (param i32))
(func $dealloc (export "__anyref_table_dealloc") (param i32))
)
(; CHECK-ALL:
@ -30,9 +30,6 @@
table.set 0)
(func $alloc (type 0) (result i32)
i32.const 0)
(func $dealloc (type 1) (param i32))
(table (;0;) 32 anyref)
(export "foo" (func $foo anyref shim))
(export "__wbindgen_anyref_table_alloc" (func $alloc))
(export "__wbindgen_anyref_table_dealloc" (func $dealloc)))
(export "foo" (func $foo anyref shim)))
;)

View File

@ -4,9 +4,9 @@
(func $foo (param i32))
(table (export "func") 0 funcref)
(elem (i32.const 0) 0)
(func $alloc (export "__wbindgen_anyref_table_alloc") (result i32)
(func $alloc (export "__anyref_table_alloc") (result i32)
i32.const 0)
(func $dealloc (export "__wbindgen_anyref_table_dealloc") (param i32))
(func $dealloc (export "__anyref_table_dealloc") (param i32))
)
(; CHECK-ALL:
@ -25,11 +25,8 @@
(func $alloc (type 0) (result i32)
i32.const 0)
(func $foo (type 1) (param i32))
(func $dealloc (type 1) (param i32))
(table (;0;) 2 funcref)
(table (;1;) 32 anyref)
(export "func" (table 0))
(export "__wbindgen_anyref_table_alloc" (func $alloc))
(export "__wbindgen_anyref_table_dealloc" (func $dealloc))
(elem (;0;) (i32.const 0) $foo $closure0 anyref shim))
;)