Skip to content

8384202: [lworld] C2: assert(offset == field->offset_in_bytes()) failed: offset mismatch#2433

Open
TobiHartmann wants to merge 3 commits into
openjdk:lworldfrom
TobiHartmann:JDK-8384202
Open

8384202: [lworld] C2: assert(offset == field->offset_in_bytes()) failed: offset mismatch#2433
TobiHartmann wants to merge 3 commits into
openjdk:lworldfrom
TobiHartmann:JDK-8384202

Conversation

@TobiHartmann
Copy link
Copy Markdown
Member

@TobiHartmann TobiHartmann commented May 13, 2026

The original failure was in test21 from compiler/valhalla/inlinetypes/TestNullableInlineTypes.java#id5. I extracted it into a standalone reproducer.

C2 asserts in InlineTypeNode::field_value_by_offset while looking up a field value by offset. The lookup reaches a flat field whose corresponding input is already TOP. This happens on the normal return path from test2() in test(). That path is dead because test2() always throws a NullPointerException when it tries to initialize a null restricted field with null. We only "know" this after incremental inlining though.

So at this point, with -XX:+StressIGVN, the impossible control path has not been removed yet, but the data path has already started dying: field values on the dead InlineTypeNode have been replaced by TOP. InlineTypeNode::field_value_by_offset already accounts for this with a value->is_top() check, but the offset assert in that case is too strict.

In this reproducer, the lookup is recursive: it asks for a field inside a flat field whose value is already TOP. Therefore, the requested offset is the offset of a nested field within the flattened payload, while field->offset_in_bytes() is the offset of the enclosing flat field. Those offsets are not expected to match.

I adjusted the assert accordingly.

Thanks,
Tobias



Progress

  • Change must not contain extraneous whitespace
  • Commit message must refer to an issue
  • Change must be properly reviewed (1 review required, with at least 1 Committer)

Issue

  • JDK-8384202: [lworld] C2: assert(offset == field->offset_in_bytes()) failed: offset mismatch (Bug - P4)

Reviewers

Reviewing

Using git

Checkout this PR locally:
$ git fetch https://git.openjdk.org/valhalla.git pull/2433/head:pull/2433
$ git checkout pull/2433

Update a local copy of the PR:
$ git checkout pull/2433
$ git pull https://git.openjdk.org/valhalla.git pull/2433/head

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 2433

View PR using the GUI difftool:
$ git pr show -t 2433

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/valhalla/pull/2433.diff

Using Webrev

Link to Webrev Comment

@bridgekeeper
Copy link
Copy Markdown

bridgekeeper Bot commented May 13, 2026

👋 Welcome back thartmann! A progress list of the required criteria for merging this PR into lworld will be added to the body of your pull request. There are additional pull request commands available for use with this pull request.

@openjdk
Copy link
Copy Markdown

openjdk Bot commented May 13, 2026

@TobiHartmann This change now passes all automated pre-integration checks.

ℹ️ This project also has non-automated pre-integration requirements. Please see the file CONTRIBUTING.md for details.

After integration, the commit message for the final commit will be:

8384202: [lworld] C2: assert(offset == field->offset_in_bytes()) failed: offset mismatch

Reviewed-by: mchevalier, qamai

You can use pull request commands such as /summary, /contributor and /issue to adjust it as needed.

At the time when this comment was updated there had been 3 new commits pushed to the lworld branch:

  • 6b9eb7d: 8384283: [lworld] Post-parse call devirtualization with unloaded return type fails
  • de6aff4: 8384364: [lworld] C2: assert(cloned_flat_array_check->req() == 3) failed: unexpected number of inputs for FlatArrayCheck
  • 2d330b1: 8384193: [lworld] Remove identity field from java.lang.Class

Please see this link for an up-to-date comparison between the source branch of this pull request and the lworld branch.
As there are no conflicts, your changes will automatically be rebased on top of these commits when integrating. If you prefer to avoid this automatic rebasing, please check the documentation for the /integrate command for further details.

➡️ To integrate this PR with the above commit message to the lworld branch, type /integrate in a new comment.

@openjdk openjdk Bot added the rfr Pull request is ready for review label May 13, 2026
@mlbridge
Copy link
Copy Markdown

mlbridge Bot commented May 13, 2026

Webrevs

@@ -230,7 +230,9 @@ Node* InlineTypeNode::field_value_by_offset(int offset, bool recursive) const {
assert(!field->is_flat() || field->type()->is_inlinetype(), "must be an inline type");

if (!recursive || !field->is_flat() || value->is_top()) {
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.

This looks a bit cluttered, can we move if (value->is_top()) into a separate case before this if instead?

Copy link
Copy Markdown
Member Author

@TobiHartmann TobiHartmann May 13, 2026

Choose a reason for hiding this comment

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

Sure. I had this version first and didn't like it but I don't have a strong opinion. Updated.

Copy link
Copy Markdown
Member

@marc-chevalier marc-chevalier left a comment

Choose a reason for hiding this comment

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

That makes sense. Do we want the bug number in the test?

* @modules java.base/jdk.internal.vm.annotation
* @run main ${test.main.class}
* @run main/othervm -XX:+UnlockDiagnosticVMOptions -XX:+IgnoreUnrecognizedVMOptions
* -XX:+StressIGVN -XX:StressSeed=8 -XX:+AlwaysIncrementalInline
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.

The hardcoded is on purpose? It reproduces so rarely otherwise?

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.

Yes, it's on purpose to make it reliably reproduce the issue and the usual way of how we design these tests. I.e. one run with fixed seed and one without. As we discussed offline, there are several alternatives to this approach, including RepeatCompilation etc. We decided on the current approach a while ago but we can surely revisit. It's out of scope of this PR though 🙂

Testing also revealed that PreloadClasses is required to make sure that the @NullRestricted annotation is respected, so I added a corresponding @requires.

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.

I think that means this test lacks a test that does not use a fixed seed?

@openjdk openjdk Bot added the ready Pull request is ready to be integrated label May 13, 2026
@TobiHartmann
Copy link
Copy Markdown
Member Author

Thanks for the reviews Quan Anh and Marc! I pushed an updated version.

Do we want the bug number in the test?

I added a bug number to the test.

Copy link
Copy Markdown
Member

@merykitty merykitty left a comment

Choose a reason for hiding this comment

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

Thanks, that looks good to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ready Pull request is ready to be integrated rfr Pull request is ready for review

Development

Successfully merging this pull request may close these issues.

3 participants