Skip to content

Commit 58813d2

Browse files
authored
[NFC] Remove outdated mentions of nominal types (#8142)
Fix comments and tests mentioning the experimental nominal type system that existed before GC was standardized. As a drive-by, remove some adjacent dead code in OptimizeInstructions that has not been relevant since we updated If finalization to propage unreachability.
1 parent 38d3277 commit 58813d2

14 files changed

+117
-154
lines changed

src/ir/type-updating.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -580,11 +580,11 @@ Expression* fixLocalGet(LocalGet* get, Module& wasm);
580580
// Applies new types of parameters to a function. This does all the necessary
581581
// changes aside from altering the function type, which the caller is expected
582582
// to do after we run (the caller might simply change the type, but in other
583-
// cases the caller might be rewriting the types and need to preserve their
584-
// identity in terms of nominal typing, so we don't change the type here). The
585-
// specific things this function does are to update the types of local.get/tee
586-
// operations, refinalize, etc., basically all operations necessary to ensure
587-
// validation with the new types.
583+
// cases the caller might be rewriting the types and need to preserve their
584+
// identities, so we don't change the type here). The specific things this
585+
// function does are to update the types of local.get/tee operations,
586+
// refinalize, etc., basically all operations necessary to ensure validation
587+
// with the new types.
588588
//
589589
// While doing so, we can either update or not update the types of local.get and
590590
// local.tee operations. (We do not update them here if we'll be doing an update

src/passes/OptimizeInstructions.cpp

Lines changed: 22 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -5726,65 +5726,47 @@ struct OptimizeInstructions
57265726
// curr, and so they must be compatible to allow for a proper new
57275727
// type after the transformation.
57285728
//
5729-
// At minimum an LUB is required, as shown here:
5729+
// The children must have a shared supertype. For example, we cannot
5730+
// fold out the `drop` here because there would be no valid result
5731+
// type for the if afterward:
57305732
//
57315733
// (if
57325734
// (condition)
57335735
// (drop (i32.const 1))
57345736
// (drop (f64.const 2.0))
57355737
// )
57365738
//
5737-
// However, that may not be enough, as with nominal types we can
5738-
// have things like this:
5739+
// However, having a shared supertype may not be enough. If $A and
5740+
// $B have a shared supertype, but that supertype does not have a
5741+
// field at index 1, then we cannot fold the duplicated struct.get
5742+
// here:
57395743
//
57405744
// (if
57415745
// (condition)
57425746
// (struct.get $A 1 (..))
57435747
// (struct.get $B 1 (..))
57445748
// )
57455749
//
5746-
// It is possible that the LUB of $A and $B does not contain field
5747-
// "1". With structural types this specific problem is not possible,
5748-
// and it appears to be the case that with the GC MVP there is no
5749-
// instruction that poses a problem, but in principle it can happen
5750-
// there as well, if we add an instruction that returns the number
5751-
// of fields in a type, for example. For that reason, and to avoid
5752-
// a difference between structural and nominal typing here, disallow
5753-
// subtyping in both. (Note: In that example, the problem only
5754-
// happens because the type is not part of the struct.get - we infer
5755-
// it from the reference. That is why after hoisting the struct.get
5756-
// out, and computing a new type for the if that is now the child of
5757-
// the single struct.get, we get a struct.get of a supertype. So in
5758-
// principle we could fix this by modifying the IR as well, but the
5759-
// problem is more general, so avoid that.)
5750+
// (Note: In that example, the problem only happens because the type
5751+
// is not part of the struct.get - we infer it from the reference.
5752+
// That is why after hoisting the struct.get out, and computing a
5753+
// new type for the if that is now the child of the single
5754+
// struct.get, we get a struct.get of a supertype. So in principle
5755+
// we could fix this by modifying the IR as well, but the problem is
5756+
// more general, so avoid that.)
5757+
//
5758+
// For now, only support the case where the types of the children
5759+
// are the same.
5760+
//
5761+
// TODO: We could analyze whether the LUB of the children types
5762+
// would satisfy the constraints imposed by the shared parent
5763+
// instruction. This would require a version of ChildTyper that
5764+
// allows for generalizing type annotations.
57605765
ChildIterator ifFalseChildren(curr->ifFalse);
57615766
auto* ifTrueChild = *ifTrueChildren.begin();
57625767
auto* ifFalseChild = *ifFalseChildren.begin();
57635768
bool validTypes = ifTrueChild->type == ifFalseChild->type;
57645769

5765-
// In addition, after we move code outside of curr then we need to
5766-
// not change unreachability - if we did, we'd need to propagate
5767-
// that further, and we leave such work to DCE and Vacuum anyhow.
5768-
// This can happen in something like this for example, where the
5769-
// outer type changes from i32 to unreachable if we move the
5770-
// returns outside:
5771-
//
5772-
// (if (result i32)
5773-
// (local.get $x)
5774-
// (return
5775-
// (local.get $y)
5776-
// )
5777-
// (return
5778-
// (local.get $z)
5779-
// )
5780-
// )
5781-
assert(curr->ifTrue->type == curr->ifFalse->type);
5782-
auto newOuterType = curr->ifTrue->type;
5783-
if ((newOuterType == Type::unreachable) !=
5784-
(curr->type == Type::unreachable)) {
5785-
validTypes = false;
5786-
}
5787-
57885770
// If the expression we are about to move outside has side effects,
57895771
// then we cannot do so in general with a select: we'd be reducing
57905772
// the amount of the effects as well as moving them. For an if,

src/passes/SignaturePruning.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -279,13 +279,12 @@ struct SignaturePruning : public Pass {
279279

280280
// Create a new signature. When the TypeRewriter operates below it will
281281
// modify the existing heap type in place to change its signature to this
282-
// one (which preserves identity, that is, even if after pruning the new
283-
// signature is structurally identical to another one, it will remain
284-
// nominally different from those).
282+
// one. TypeRewriter will also ensure that distinct types remain
283+
// disctinct, even if they have the same signature after optimization.
285284
newSignatures[type] = Signature(Type(newParams), sig.results);
286285

287286
// removeParameters() updates the type as it goes, but in this pass we
288-
// need the type to match the other locations, nominally. That is, we need
287+
// need the type to be updated in all locations at once. That is, we need
289288
// all the functions of a particular type to still have the same type
290289
// after this operation, and that must be the exact same type at the
291290
// relevant call_refs and so forth. The TypeRewriter below will do the

src/passes/pass.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -569,7 +569,7 @@ void PassRegistry::registerPasses() {
569569
"merge types to their supertypes where possible",
570570
createTypeMergingPass);
571571
registerPass("type-ssa",
572-
"create new nominal types to help other optimizations",
572+
"create new types to help other optimizations",
573573
createTypeSSAPass);
574574
registerPass("type-unfinalizing",
575575
"mark all types as non-final (open)",

src/wasm-type.h

Lines changed: 7 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -139,21 +139,13 @@ class HeapType {
139139
// Choose an arbitrary heap type as the default.
140140
constexpr HeapType() : HeapType(func) {}
141141

142-
// Construct a HeapType referring to the single canonical HeapType for the
143-
// given signature. In nominal mode, this is the first HeapType created with
144-
// this signature.
142+
// Construct the single canonical HeapType for the given signature, struct,
143+
// array, or continuation.
145144
HeapType(Signature signature);
146-
147-
HeapType(Continuation cont);
148-
149-
// Create a HeapType with the given structure. In equirecursive mode, this may
150-
// be the same as a previous HeapType created with the same contents. In
151-
// nominal mode, this will be a fresh type distinct from all previously
152-
// created HeapTypes.
153-
// TODO: make these explicit to differentiate them.
154145
HeapType(const Struct& struct_);
155146
HeapType(Struct&& struct_);
156147
HeapType(Array array);
148+
HeapType(Continuation cont);
157149

158150
HeapTypeKind getKind() const;
159151

@@ -193,7 +185,7 @@ class HeapType {
193185
Array getArray() const;
194186

195187
// If there is a nontrivial (i.e. non-basic, one that was declared by the
196-
// module) nominal supertype, return it, else an empty optional.
188+
// module) supertype, return it, else an empty optional.
197189
std::optional<HeapType> getDeclaredSuperType() const;
198190

199191
// As |getDeclaredSuperType|, but also handles basic types, that is, if the
@@ -206,8 +198,8 @@ class HeapType {
206198
std::optional<HeapType> getDescribedType() const;
207199
DescriptorChain getDescriptorChain() const;
208200

209-
// Return the depth of this heap type in the nominal type hierarchy, i.e. the
210-
// number of supertypes in its supertype chain.
201+
// Return the depth of this heap type in the type hierarchy, i.e. the number
202+
// of supertypes in its supertype chain.
211203
size_t getDepth() const;
212204

213205
// Get the bottom heap type for this heap type's hierarchy.
@@ -898,10 +890,7 @@ struct TypeBuilder {
898890
};
899891

900892
// Returns all of the newly constructed heap types. May only be called once
901-
// all of the heap types have been initialized with `setHeapType`. In nominal
902-
// mode, all of the constructed HeapTypes will be fresh and distinct. In
903-
// nominal mode, will also produce a fatal error if the declared subtype
904-
// relationships are not valid.
893+
// all of the heap types have been initialized with `setHeapType`.
905894
BuildResult build();
906895

907896
// Utility for ergonomically using operator[] instead of explicit setHeapType

test/lit/help/wasm-metadce.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -557,8 +557,8 @@
557557
;; CHECK-NEXT: type fields where possible
558558
;; CHECK-NEXT: (using GUFA)
559559
;; CHECK-NEXT:
560-
;; CHECK-NEXT: --type-ssa create new nominal types to help
561-
;; CHECK-NEXT: other optimizations
560+
;; CHECK-NEXT: --type-ssa create new types to help other
561+
;; CHECK-NEXT: optimizations
562562
;; CHECK-NEXT:
563563
;; CHECK-NEXT: --type-unfinalizing mark all types as non-final
564564
;; CHECK-NEXT: (open)

test/lit/help/wasm-opt.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -589,8 +589,8 @@
589589
;; CHECK-NEXT: type fields where possible
590590
;; CHECK-NEXT: (using GUFA)
591591
;; CHECK-NEXT:
592-
;; CHECK-NEXT: --type-ssa create new nominal types to help
593-
;; CHECK-NEXT: other optimizations
592+
;; CHECK-NEXT: --type-ssa create new types to help other
593+
;; CHECK-NEXT: optimizations
594594
;; CHECK-NEXT:
595595
;; CHECK-NEXT: --type-unfinalizing mark all types as non-final
596596
;; CHECK-NEXT: (open)

test/lit/help/wasm2js.test

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -521,8 +521,8 @@
521521
;; CHECK-NEXT: type fields where possible
522522
;; CHECK-NEXT: (using GUFA)
523523
;; CHECK-NEXT:
524-
;; CHECK-NEXT: --type-ssa create new nominal types to help
525-
;; CHECK-NEXT: other optimizations
524+
;; CHECK-NEXT: --type-ssa create new types to help other
525+
;; CHECK-NEXT: optimizations
526526
;; CHECK-NEXT:
527527
;; CHECK-NEXT: --type-unfinalizing mark all types as non-final
528528
;; CHECK-NEXT: (open)
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
;; Test that incorrect nominal types result in the expected parse errors
1+
;; Test that missing supertypes result in the expected parse errors
22

33
;; RUN: foreach %s %t not wasm-opt -all 2>&1 | filecheck %s
44

test/lit/passes/gto_and_cfp_in_O.wast

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,8 @@
33
;; RUN: foreach %s %t wasm-opt -O -all --closed-world -S -o - | filecheck %s
44
;; RUN: foreach %s %t wasm-opt -O -all -S -o - | filecheck %s --check-prefix OPEN_WORLD
55

6-
;; Test that -O, with nominal typing + GC enabled, will run global type
7-
;; optimization in conjunction with constant field propagation etc. But, in an
8-
;; open world we do not run them.
6+
;; Test that -O with GC enabled will run global type optimization in conjunction
7+
;; with constant field propagation etc. in closed world mode only.
98

109
(module
1110
;; OPEN_WORLD: (type $struct (sub (struct (field (mut funcref)) (field (mut i32)))))

0 commit comments

Comments
 (0)