diff options
author | Alon Zakai <azakai@google.com> | 2022-12-19 15:45:34 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-19 23:45:34 +0000 |
commit | 12ad604c17407f6b36d52c6404f2dab32e5c7960 (patch) | |
tree | b62e320888558291edbf646fe8683654a718f645 | |
parent | 54079e9458e0d7ee2b4028ea888a74fed31f61d7 (diff) | |
download | binaryen-12ad604c17407f6b36d52c6404f2dab32e5c7960.tar.gz binaryen-12ad604c17407f6b36d52c6404f2dab32e5c7960.tar.bz2 binaryen-12ad604c17407f6b36d52c6404f2dab32e5c7960.zip |
[Wasm GC] Do not cache signature types in nominal mode if they have a super (#5364)
This reduces the amount of public types, since if there is a super then using the
type in a public place would make the super also public. It is safer for closed-world
mode to reuse types without supers.
-rw-r--r-- | src/wasm/wasm-type.cpp | 6 | ||||
-rw-r--r-- | test/lit/parse-nominal-types-no-sig-sharing.wast | 41 |
2 files changed, 46 insertions, 1 deletions
diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 284d6d7d6..b65debc73 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -2967,7 +2967,11 @@ TypeBuilder::BuildResult TypeBuilder::build() { // Note built signature types. See comment in `HeapType::HeapType(Signature)`. for (auto type : state.results) { - if (type.isSignature() && (getTypeSystem() == TypeSystem::Nominal)) { + // Do not cache types with explicit supertypes (that is, whose supertype is + // not HeapType::func). We don't want to reuse such types because then we'd + // be adding subtyping relationships that are not in the input. + if (type.isSignature() && (getTypeSystem() == TypeSystem::Nominal) && + !type.getSuperType()) { nominalSignatureCache.insertType(type); } } diff --git a/test/lit/parse-nominal-types-no-sig-sharing.wast b/test/lit/parse-nominal-types-no-sig-sharing.wast new file mode 100644 index 000000000..f3ebecc27 --- /dev/null +++ b/test/lit/parse-nominal-types-no-sig-sharing.wast @@ -0,0 +1,41 @@ +;; NOTE: Assertions have been generated by update_lit_checks.py --all-items and should not be edited. + +;; RUN: foreach %s %t wasm-opt --nominal -all -S -o - | filecheck %s +;; RUN: foreach %s %t wasm-opt --nominal -all --roundtrip -S -o - | filecheck %s +;; RUN: foreach %s %t wasm-opt --nominal -all --closed-world -S -o - | filecheck %s + +;; Test that we do not use the signature cache to share a function type that +;; has a supertype. $sub appears first, so it is the earliest example of a +;; signature of no params and no results, but we should not use it as the types +;; of $foo or $bar, as it has a supertype. Instead, we should use $super as the +;; canonical type for that signature. That is fine as at least it only makes +;; $super effectively a public type, instead of both $sub and $super (the latter +;; does not validate in closed world, but the former does - the closed-world +;; run that we do here would error). +;; +;; Note that this problem only happens in nominal mode, since $sub can appear +;; before $super in the list of types. + +(module + (type $sub (func_subtype $super)) + + ;; CHECK: (type $super (func)) + (type $super (func_subtype func)) + + ;; CHECK: (global $g (ref null $super) (ref.null nofunc)) + (global $g (ref null $super) (ref.null $sub)) + + ;; CHECK: (export "foo" (func $foo)) + + ;; CHECK: (func $foo (type $super) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $foo (export "foo") + ) + + ;; CHECK: (func $bar (type $super) + ;; CHECK-NEXT: (nop) + ;; CHECK-NEXT: ) + (func $bar + ) +) |