Skip to content

Change the default type system to isorecursive #5239

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 12 commits into from
Nov 23, 2022
Merged

Conversation

tlively
Copy link
Member

@tlively tlively commented Nov 10, 2022

This makes Binaryen's default type system match the WasmGC spec.

Update the way type definitions without supertypes are printed to reduce the output diff for MVP tests that do not involve WasmGC. Also port some type-builder.cpp tests from test/example to test/gtest since they needed to be rewritten to work with isorecursive type anyway.

A follow-on PR will remove equirecursive types completely.

@tlively tlively requested a review from kripken November 10, 2022 21:20
Copy link
Member

@kripken kripken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we finish fuzzing this mode before switching to it? Atm the fuzzer runs on --nominal and it looks like this PR doesn't change that.

@@ -1,7 +1,7 @@
(module
(type $none_=>_none (func))
(memory $0 1 1)
(func $foo
(func $foo (type $none_=>_none)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not print these if GC is not on? That is, even if the type system is isorecursive, we don't need these types if the features don't require it. It would also make the diff here much smaller I think.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I added that logic and it helped some of the lit tests, but the problem is that most of these tests run with -all.

@tlively tlively force-pushed the default-isorecursive branch from 04b5d9f to 5a46d6f Compare November 10, 2022 22:50
@tlively
Copy link
Member Author

tlively commented Nov 10, 2022

Current dependencies on/for this PR:

This comment was auto-generated by Graphite.

@tlively
Copy link
Member Author

tlively commented Nov 10, 2022

Should we finish fuzzing this mode before switching to it? Atm the fuzzer runs on --nominal and it looks like this PR doesn't change that.

Given that the old default was also not fuzzed, I wouldn't consider this a blocker.

@kripken
Copy link
Member

kripken commented Nov 10, 2022

We did at least fuzz equirecursive quite a lot before we switched the fuzzer over. It was fully stable back then. So we lost fuzz coverage but it had a good starting point at least. But, maybe it shouldn't block here. I am mainly concerned for any interactions with MVP wasm, but I guess such things should have been caught by tests.

@tlively
Copy link
Member Author

tlively commented Nov 10, 2022

Certainly fuzzing is a good idea. I can fuzz with isorecursive types overnight before landing this.

@kripken
Copy link
Member

kripken commented Nov 10, 2022

This diff is too large to comment on in the web UI 😄

What is this part of the diff?

diff --git a/test/example/type-builder.cpp b/test/example/type-builder.cpp
index 7da2f8f0383..2ce064b5ffe 100644
--- a/test/example/type-builder.cpp
+++ b/test/example/type-builder.cpp
@@ -18,26 +18,26 @@ void test_canonicalization() {
 
   TypeBuilder builder(4);
 
-  Type tempSigRef1 = builder.getTempRefType(builder[2], Nullable);
-  Type tempSigRef2 = builder.getTempRefType(builder[3], Nullable);
+  Type tempSigRef1 = builder.getTempRefType(builder[0], Nullable);
+  Type tempSigRef2 = builder.getTempRefType(builder[1], Nullable);

@tlively
Copy link
Member Author

tlively commented Nov 10, 2022

The order of types in that test needed to change so that the earlier types no longer referred to later types. That kind of forward reference is only allowed in recursion groups in the isorecursive system, but this test doesn't really need a recursion group, so I just changed the type order instead.

@kripken
Copy link
Member

kripken commented Nov 11, 2022

I had to write a python script to get through this massive diff 😄

lgtm, but please fuzz this even without changing the fuzzer to hybrid, as I think I saw an error. It was on a branch that I merged this PR to, but the error may have been due to the branch in theory... it did look like a type error though. I can't reproduce it outside of the branch but that might just be different random choices in the fuzzer.

Probably not helpful, but here is part of the log:

ITERATION: 1 seed: 17155922667202884028 size: 44650 (mean: 44650.0, stddev: 0.0) speed: 10255.022004889976 iters/sec,  0.0 wasm_bytes/sec
[..]
initial contents: /binaryen/test/./lit/recursive-types.wast
avoiding --flatten due to GC not supporting it (spilling of non-nullable locals)
avoiding --flatten due to GC not supporting it (spilling of non-nullable locals)
randomized opts: 
  -O3
  --roundtrip
  --simplify-locals-nonesting
  --monomorphize-always
  --generate-global-effects
  --monomorphize-always
  --rse
  -O1
  --generate-stack-ir
  --optimize-stack-ir
  -fimfs=99999999

/binaryen/bin/wasm-opt /binaryen/out/test/input.dat -ttf -o /binaryen/out/test/a.wasm --denan --legalize-js-interface --all-features --disable-threads --disable-mutable-globals --disable-simd --disable-bulk-memory --disable-tail-call --disable-gc --disable-memory64 --disable-relaxed-simd --disable-multi-memories --disable-memory64 --disable-multivalue --initial-fuzz=/binaryen/test/./lit/recursive-types.wast
warning: cannot de-nan outside of function context
warning: cannot de-nan outside of function context
warning: cannot de-nan outside of function context
warning: cannot de-nan outside of function context
warning: cannot de-nan outside of function context
warning: cannot de-nan outside of function context
pre wasm size: 16143
/binaryen/bin/wasm-opt a.wasm --all-features --disable-threads --disable-mutable-globals --disable-simd --disable-bulk-memory --disable-tail-call --disable-gc --disable-memory64 --disable-relaxed-simd --disable-multi-memories --disable-memory64 --disable-multivalue --print-features
[parse exception: Bad type form 2 (at 0:612)]
Fatal: error parsing wasm

(the branch was this PR + monomorphize)

@kripken
Copy link
Member

kripken commented Nov 11, 2022

Ok, I got an error with just this PR. Seed: 11374867808572504832, using --auto-initial-contents. Reducing it now.

@kripken
Copy link
Member

kripken commented Nov 11, 2022

Oh, it could actually be array.new_data, perhaps related to #5236 . Probably best to fix that first.

@tlively tlively marked this pull request as draft November 14, 2022 16:32
@tlively tlively force-pushed the default-isorecursive branch 4 times, most recently from 7a446d2 to 11f9981 Compare November 15, 2022 21:39
@tlively tlively changed the base branch from main to fix-isorec-canon November 17, 2022 01:03
@tlively tlively force-pushed the default-isorecursive branch from 4e7579e to 7331510 Compare November 17, 2022 01:03
Base automatically changed from fix-isorec-canon to main November 17, 2022 21:30
@tlively tlively marked this pull request as ready for review November 18, 2022 15:34
@tlively tlively force-pushed the default-isorecursive branch from 7331510 to ab33f74 Compare November 18, 2022 15:34
@tlively
Copy link
Member Author

tlively commented Nov 18, 2022

This should be ready to land now soon. I'm doing final fuzzing now.

@tlively tlively mentioned this pull request Nov 18, 2022
tlively added a commit that referenced this pull request Nov 18, 2022
Validate that GC is enabled if struct and array types are used by the module and
validate that both GC and isorecursive types are enabled when nontrivial rec
groups are used.

This fixes a fuzz bug in #5239 where initial contents included a rec group but
the fuzzer disabled GC. Since the resulting module passed validation, the rec
groups made it into the binary output, making the type section malformed.
@tlively tlively changed the base branch from main to validate-types November 18, 2022 18:05
@tlively tlively force-pushed the default-isorecursive branch from ab33f74 to 4acf48d Compare November 18, 2022 18:05
@tlively
Copy link
Member Author

tlively commented Nov 18, 2022

Ran over 7k fuzzer iterations at this latest commit with TYPE_SYSTEM_FLAG set to --hybrid.

@kripken
Copy link
Member

kripken commented Nov 21, 2022

I can take another look now. I see force-pushes though, so it's a little hard to see what's changed since I read this last. Is there a way to do that on github?

About fuzzing, if we aren't also changing the default in fuzz_opt to the new mode, then I'd also fuzz the default in that file. I also recommend fuzzing for a larger amount, for a change like this - I often find bugs only after 50K or 100K.

@tlively
Copy link
Member Author

tlively commented Nov 21, 2022

Sounds good, will fuzz more both with and without the flag changed. Sorry about the force-pushes, I know they make review more difficult. That's the trade off I'm making to get to use stacked PRs. I would welcome feedback about whether that's a good trade off or not on the review side.

I'm not squashing or changing any existing commits during those force pushes (except that merge conflicts get resolved in whatever arbitrary commit the conflict occurred at), so you can always look at the individual new commits to see what has changed. GitHub doesn't have a good way of seeing how many commits are new since your last review in the presence of force pushes, though.

@tlively tlively force-pushed the default-isorecursive branch from 4acf48d to 6767c08 Compare November 21, 2022 23:47
@kripken
Copy link
Member

kripken commented Nov 21, 2022

Interesting, thanks, if the commit contents don't change then I could in theory remember by their names which I've reviewed...

Copy link
Member

@kripken kripken left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, pretty sure I've reviewed the first one before, and the others look ok together, so lgtm with that fuzzing.

@tlively tlively force-pushed the default-isorecursive branch from 6767c08 to 500e591 Compare November 22, 2022 15:41
Base automatically changed from validate-types to main November 22, 2022 16:16
tlively added a commit that referenced this pull request Nov 22, 2022
Update `HeapType::getFeatures` to report that GC is used for heap types that
have nontrivial recursion groups or supertypes. Update validation to check the
features on function heap types, not just their individual params and results.

This fixes a fuzz bug in #5239 where initial contents included a rec group but
the fuzzer disabled GC. Since the resulting module passed validation, the rec
groups made it into the binary output, making the type section malformed.
This makes Binaryen's default type system match the WasmGC spec.

Update the way type definitions without supertypes are printed to reduce the
output diff for MVP tests that do not involve WasmGC. Also port some
type-builder.cpp tests from test/example to test/gtest since they needed to be
rewritten to work with isorecursive type anyway.

A follow-on PR will remove equirecursive types completely.
@tlively tlively force-pushed the default-isorecursive branch from 500e591 to b6159e1 Compare November 23, 2022 02:26
@tlively tlively enabled auto-merge (squash) November 23, 2022 02:28
@tlively tlively merged commit 853b31e into main Nov 23, 2022
@tlively tlively deleted the default-isorecursive branch November 23, 2022 02:49
@tlively
Copy link
Member Author

tlively commented Nov 23, 2022

Fuzzed just under 50k iterations on this before merging.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants