Skip to content

Type ref.null as exact - #7371

Merged
tlively merged 4 commits into
mainfrom
null-exact-refs
Mar 13, 2025
Merged

Type ref.null as exact#7371
tlively merged 4 commits into
mainfrom
null-exact-refs

Conversation

@tlively

@tlively tlively commented Mar 13, 2025

Copy link
Copy Markdown
Member

RefNull expression now have type (ref exact null bot), allowing them
to be used wherever a nullable exact reference is expected. Update the
fuzzer and fix a few bugs with exactness propagation this uncovers.

`RefNull` expression now have type `(ref exact null bot)`, allowing them
to be used wherever a nullable exact reference is expected. Update the
fuzzer and fix a few bugs with exactness propagation this uncovers.
@tlively
tlively requested a review from kripken March 13, 2025 20:17
Comment thread src/ir/type-updating.cpp
if (type.isRef()) {
auto heapType = type.getHeapType();
if (auto it = typeIndices.find(heapType); it != typeIndices.end()) {
// TODO: Handle exactness.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

The fuzzer does not seem to trip over this (yet), so I left it unfixed for now. Eventually I expect us to trip over this bug, at which point we will be able to reduce the reproducer to a test case and ensure we have test coverage.

@tlively tlively left a comment

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Fuzzed for 80k iterations with no problems, so I think it's good enough to land in that regard.

@kripken kripken left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

lgtm % questions

if (exactness == Exact) {
auto inexact = getRelevantTypes(Type(heapType, nullability, Inexact));
ret.insert(ret.end(), inexact.begin(), inexact.end());
// Do not consider exact references to supertypes.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why not?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Because (ref exact $super) is not a supertype of (ref exact $sub).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Oh right 😆

Comment thread src/tools/fuzzing/fuzzing.cpp Outdated
// are better supported.
Type refType = ref->type;
if (refType.isExact()) {
refType = Type(refType.getHeapType(), refType.getNullability(), Inexact);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Suggested change
refType = Type(refType.getHeapType(), refType.getNullability(), Inexact);
refType = refType.as(Inexact);

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Will look for other instances of this, too.

Comment thread src/tools/fuzzing/fuzzing.cpp Outdated
// exact references because the binary writer can always generalize the exact
// reference types away.
//
// if (wasm.features.hasGC() && oneIn(2)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

when we do this, perhaps less of a chance for exact refs? they are probably rarer in real-world code.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Sure, will bump to one in 8.

Comment thread src/tools/fuzzing/fuzzing.cpp Outdated
heapType = getSubType(heapType);
if (type.isExact()) {
// The only other possible heap type is bottom.
if (!heapType.isBottom() && oneIn(8)) {

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Even 8 seems very high to me, since emitting more nulls is risky in terms of traps. And this is getSubType which is called constantly (unlike other places we have constants like 8). How about

Suggested change
if (!heapType.isBottom() && oneIn(8)) {
if (!heapType.isBottom() && oneIn(20)) {

;; CHECK-NEXT: (local.get $0)
;; CHECK-NEXT: )
;; CHECK-NEXT: (ref.null none)
;; CHECK-NEXT: )

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Why did this change?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Now that ref.null is exact, we could remove the early return in OptimizeInstructions.cpp that prevented us from removing the cast and rematerializing the null value instead.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Nice!

@tlively
tlively merged commit 425d7c8 into main Mar 13, 2025
@tlively
tlively deleted the null-exact-refs branch March 13, 2025 22:37
@tlively tlively mentioned this pull request Mar 24, 2025
tlively added a commit that referenced this pull request Mar 26, 2025
We decided that Custom Descriptors should introduce exact heap types
rather than exact reference types. Although these new features are very
similar, the APIs we need to change for them are completely different.

One option would have been to keep the existing exact reference type
implementation while additionally implementing exact heap types, but
there are not enough free bits in the type implementation to have both
at once without increasing the alignment of HeapTypeInfo allocations.
Portably increasing the alignment is annoying enough that it's easier to
just eagerly remove exact reference types to free up the bit for use
with exact heap types.

Fully or partially revert the following PRs:

 - #7371
 - #7365
 - #7360
 - #7357
 - #7356
 - #7355
 - #7354
 - #7353
 - #7347
 - #7342
 - #7328

Keep the new `.with(...)` Type APIs and the relevant parts of the type
relations gtest that were introduced as part of the reverted work.
tlively added a commit that referenced this pull request Mar 26, 2025
We decided that Custom Descriptors should introduce exact heap types
rather than exact reference types. Although these new features are very
similar, the APIs we need to change for them are completely different.

One option would have been to keep the existing exact reference type
implementation while additionally implementing exact heap types, but
there are not enough free bits in the type implementation to have both
at once without increasing the alignment of HeapTypeInfo allocations.
Portably increasing the alignment is annoying enough that it's easier to
just eagerly remove exact reference types to free up the bit for use
with exact heap types.

Fully or partially revert the following PRs:

 - #7371
 - #7365
 - #7360
 - #7357
 - #7356
 - #7355
 - #7354
 - #7353
 - #7347
 - #7342
 - #7328

Keep the new `.with(...)` Type APIs and the relevant parts of the type
relations gtest that were introduced as part of the reverted work.
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