Skip to content

Conversation

@kripken
Copy link
Member

@kripken kripken commented Jun 25, 2024

If an allocation does not escape, then we can compute ref.eq for it: when
compared to itself the result is 1, and when compared to anything else it
is 0 (since it did not escape, anything else must be different).

This unblocks a few cases on real-world Java code I am looking at.

@kripken kripken requested a review from tlively June 25, 2024 16:12
Comment on lines +711 to +713
if (!analyzer.reached.count(curr)) {
return;
}
Copy link
Member

Choose a reason for hiding this comment

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

Just to make sure I understand: we've done a data flow analysis and determined that this expression is not dead? Is it possible for reached to be nonzero and still have type Type::unreachable below?

Copy link
Member Author

Choose a reason for hiding this comment

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

Ah, yeah, "reach" is used in two ways here. reached means that the allocation, the struct.new / array.new, reaches this location. So this first check is just making sure that we only look in the places we traced the path of the allocation.

Copy link
Member Author

Choose a reason for hiding this comment

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

Consider

(ref.eq
  (unreachable)
  (struct.new ..)
)

That allocation reaches the ref.eq, but also the ref.eq is unreachable code, separately.

Comment on lines +724 to +725
int32_t result = analyzer.reached.count(curr->left) > 0 &&
analyzer.reached.count(curr->right) > 0;
Copy link
Member

Choose a reason for hiding this comment

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

How is this checking whether the expression is compared to itself?

Copy link
Member Author

Choose a reason for hiding this comment

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

reached is the places the allocation reaches. So if the allocation is on both sides, we must be equal. If the allocation reached only one, then since it did not escape to a place we can't analyze, the other arm must be something totally different.

Copy link
Member

Choose a reason for hiding this comment

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

What if one (or both) of the arms may or may not be the analyzed allocation?

Copy link
Member Author

Choose a reason for hiding this comment

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

We are never in an ambiguous situation. If one arm can contain a mixture of the analyzed allocation and something else then we consider that the Mixes situation, which we ignore:

if (interaction == ParentChildInteraction::Escapes ||
interaction == ParentChildInteraction::Mixes) {
// If the parent may let us escape, or the parent mixes other values
// up with us, give up.
return true;
}

In theory we could add runtime checks "is this the allocation", but it seems unpromising.

@kripken kripken merged commit d6b4f01 into WebAssembly:main Jun 26, 2024
@kripken kripken deleted the heap2local.ref.eq branch June 26, 2024 15:10
@gkdn gkdn mentioned this pull request Aug 31, 2024
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