[dart2wasm] Emit encoding for final types. This marks all types without subtypes as final and all types with subtypes as non-final. This makes the emitted types maximally final and is appropriate for a closed-world module. V8 currently ignores the finality of types for the temporary WasmGC encoding, which make our current encoding work even though it implicitly marks some types as final that shouldn't be. For the final WasmGC instruction encoding, V8 is likely to reject modules containing final types with subtypes. Change-Id: If3030c49e8fe60fec8099b731b6fcf618d6a7e64 Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/310163 Reviewed-by: Ömer Ağacan <omersa@google.com> Commit-Queue: Ömer Ağacan <omersa@google.com>
diff --git a/pkg/wasm_builder/lib/src/types.dart b/pkg/wasm_builder/lib/src/types.dart index 03524a4..d4b0f52 100644 --- a/pkg/wasm_builder/lib/src/types.dart +++ b/pkg/wasm_builder/lib/src/types.dart
@@ -602,8 +602,12 @@ /// The length of the supertype chain of this heap type. final int depth; + bool hasAnySubtypes = false; + DefType({this.superType}) - : depth = superType != null ? superType.depth + 1 : 0; + : depth = superType != null ? superType.depth + 1 : 0 { + superType?.hasAnySubtypes = true; + } int get index => _index ?? (throw "$runtimeType $this not added to module"); set index(int i) => _index = i; @@ -630,10 +634,13 @@ // if any. void serializeDefinition(Serializer s) { if (hasSuperType) { - s.writeByte(0x50); + s.writeByte(hasAnySubtypes ? 0x50 : 0x4E); s.writeUnsigned(1); assert(isStructuralSubtypeOf(superType!)); s.write(superType!); + } else if (hasAnySubtypes) { + s.writeByte(0x50); + s.writeUnsigned(0); } serializeDefinitionInner(s); }