Skip to content

8360936: Test compiler/onSpinWait/TestOnSpinWaitAArch64.java fails after JDK-8359435 #26072

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 10 commits into from

Conversation

eastig
Copy link
Member

@eastig eastig commented Jul 1, 2025

Test compiler/onSpinWait/TestOnSpinWaitAArch64.java needs debug info to identify a position of spin wait instructions in generated code. The test switched to use XX:CompileCommand=print instead of XX:+PrintAssembly to have assembly only for a tested Java method. In release builds XX:+PrintAssembly prints out debug info but XX:CompileCommand=print does not.

This PR reimplements the test to parse instructions and to check them. The test does not rely on debug info anymore.

Tested on Linux and MacOS with and without hsdis:

  • Fastdebug: test passed
  • Slowdebug: test passed.
  • Release: test passed.

Progress

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

Issue

  • JDK-8360936: Test compiler/onSpinWait/TestOnSpinWaitAArch64.java fails after JDK-8359435 (Bug - P4)

Reviewers

Reviewing

Using git

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

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

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 26072

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

Using diff file

Download this PR as a diff file:
https://git.openjdk.org/jdk/pull/26072.diff

Using Webrev

Link to Webrev Comment

@bridgekeeper
Copy link

bridgekeeper bot commented Jul 1, 2025

👋 Welcome back eastigeevich! A progress list of the required criteria for merging this PR into master 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

openjdk bot commented Jul 1, 2025

@eastig 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:

8360936: Test compiler/onSpinWait/TestOnSpinWaitAArch64.java fails after JDK-8359435

Reviewed-by: shade, aph

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 28 new commits pushed to the master 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 master branch, type /integrate in a new comment.

@openjdk openjdk bot added the rfr Pull request is ready for review label Jul 1, 2025
@openjdk
Copy link

openjdk bot commented Jul 1, 2025

@eastig The following label will be automatically applied to this pull request:

  • hotspot-compiler

When this pull request is ready to be reviewed, an "RFR" email will be sent to the corresponding mailing list. If you would like to change these labels, use the /label pull request command.

@openjdk openjdk bot added the hotspot-compiler hotspot-compiler-dev@openjdk.org label Jul 1, 2025
@mlbridge
Copy link

mlbridge bot commented Jul 1, 2025

Copy link
Member

@shipilev shipilev left a comment

Choose a reason for hiding this comment

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

Looks okay, but I am confused why the test did not fail before JDK-8359435?

@@ -29,6 +29,7 @@
*
* @requires vm.flagless
* @requires os.arch=="aarch64"
* @requires vm.debug==true
Copy link
Member

Choose a reason for hiding this comment

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

Can be just @requires vm.debug.

Copy link
Member Author

Choose a reason for hiding this comment

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

Done

@eastig
Copy link
Member Author

eastig commented Jul 1, 2025

Looks okay, but I am confused why the test did not fail before JDK-8359435?

Just checked. It's not because of JDK-8359435. There were some changes which disabled printing debug info in release build.

@eastig
Copy link
Member Author

eastig commented Jul 1, 2025

The test started failing after I had updated my branch.

@shipilev
Copy link
Member

shipilev commented Jul 1, 2025

OK, are you able to bisect which change? This fix to only do debug VM needs to be correctly linked to the actual cause, IMO.

@eastig
Copy link
Member Author

eastig commented Jul 2, 2025

I finished bisecting. This is my changes in the test which made it failing:

@@ -56,7 +58,6 @@ public static void main(String[] args) throws Exception {
         command.add("-showversion");
         command.add("-XX:-BackgroundCompilation");
         command.add("-XX:+UnlockDiagnosticVMOptions");
-        command.add("-XX:+PrintAssembly");
         if (compiler.equals("c2")) {
             command.add("-XX:-TieredCompilation");
         } else if (compiler.equals("c1")) {
@@ -69,13 +70,17 @@ public static void main(String[] args) throws Exception {
         command.add("-XX:OnSpinWaitInst=" + spinWaitInst);
         command.add("-XX:OnSpinWaitInstCount=" + spinWaitInstCount);
         command.add("-XX:CompileCommand=compileonly," + Launcher.class.getName() + "::" + "test");
+        command.add("-XX:CompileCommand=print," + Launcher.class.getName() + "::" + "test");
         command.add(Launcher.class.getName());

It looks like XX:+PrintAssembly prints out debug info in release builds but XX:CompileCommand=print does not.
I am switching back to XX:+PrintAssembly.

@theRealAph
Copy link
Contributor

It looks like XX:+PrintAssembly prints out debug info in release builds but XX:CompileCommand=print does not. I am switching back to XX:+PrintAssembly.

That's not great. What info do you need, exactly?

@eastig
Copy link
Member Author

eastig commented Jul 2, 2025

OK, are you able to bisect which change? This fix to only do debug VM needs to be correctly linked to the actual cause, IMO.

It looks like XX:+PrintAssembly prints out debug info in release builds but XX:CompileCommand=print does not. I am switching back to XX:+PrintAssembly.

That's not great. What info do you need, exactly?

  # {method} {0x0000ffff50400378} 'test' '()V' in 'compiler/onSpinWait/TestOnSpinWaitAArch64$Launcher'
  #           [sp+0x20]  (sp of caller)
  0x0000ffff985731c0: ff83 00d1 | fd7b 01a9 | 2803 0018 | 8923 40b9 | 1f01 09eb

  0x0000ffff985731d4: ;*synchronization entry
                      ; - compiler.onSpinWait.TestOnSpinWaitAArch64$Launcher::test@-1 (line 224)
  0x0000ffff985731d4: 2102 0054 | 1f20 03d5 | 1f20 03d5 | 1f20 03d5 | 1f20 03d5 | 1f20 03d5 | 1f20 03d5

  0x0000ffff985731f0: ;*invokestatic onSpinWait {reexecute=0 rethrow=0 return_oop=0}
                      ; - compiler.onSpinWait.TestOnSpinWaitAArch64$Launcher::test@0 (line 224)
  0x0000ffff985731f0: 1f20 03d5 | fd7b 41a9 | ff83 0091

  0x0000ffff985731fc: ;   {poll_return}
  0x0000ffff985731fc: 8817 40f9 | ff63 28eb | 4800 0054 | c003 5fd6

  0x0000ffff9857320c: ;   {internal_word}
  0x0000ffff9857320c: 88ff ff10 | 88a3 02f9

  0x0000ffff98573214: ;   {runtime_call SafepointBlob}
  0x0000ffff98573214: 5bc3 fe17

  0x0000ffff98573218: ;   {runtime_call Stub::method_entry_barrier}
  0x0000ffff98573218: 0850 96d2 | 480a b3f2 | e8ff dff2 | 0001 3fd6 | ecff ff17

The test searches for - compiler.onSpinWait.TestOnSpinWaitAArch64$Launcher::test@0 and invokestatic onSpinWait. They identify the place where to search instructions.

Assembly from all builds always has {poll_return}. I can use it as a search point.

@theRealAph
Copy link
Contributor


The test searches for - compiler.onSpinWait.TestOnSpinWaitAArch64$Launcher::test@0 and invokestatic onSpinWait. They identify the place where to search instructions.

That's not great. C2 is free to move stuff around, so it's not certain this test will keep working. If you just want to make sure that the pattern is used, a block_comment() would be more reliable.

@eastig
Copy link
Member Author

eastig commented Jul 3, 2025

I have rewritten the test not to use debug info at all. The test works with instructions instead.

@eastig
Copy link
Member Author

eastig commented Jul 7, 2025

@shipilev, @theRealAph
Any comments on the new version?

Comment on lines 53 to 55
private static String retInst = "ret";
private static String neededAddInst = "addsp,sp,#0x20";
private static String neededLdpInst = "ldpx29,x30,[sp,#16]";
Copy link
Member

Choose a reason for hiding this comment

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

Move these default inits down to analyzer.contains("[MachCode]") block, since it looks like it selects between two options based on [MachCode] presence. Something like:

boolean disassembly = analyzer.contains("[MachCode]");
retInst = disassembly ? "ret" : "c0035fd6";
...

Comment on lines 177 to 179
String s = instrReverseIter.previous();
instrReverseIter.next();
if (instrReverseIter.previous().startsWith(neededAddInst)) {
Copy link
Member

Choose a reason for hiding this comment

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

Multiple issues here:

  • Confusing: what's the use of s, did you mean to use it for startsWith?
  • Indenting is off

Copy link
Member

Choose a reason for hiding this comment

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

Overall, I think searching for this multi-instruction stencil gets fairly hairy with iterators. Would a more straight-forward looping work?

int found = 0;
for (int c = 0; c < instrs.size() - 2; c++) {
   if (instrs.get(c).startsWith(spinWaitInst) && 
       instrs.get(c+1).startsWith(neededLdpInst) &&
       instrs.get(c+2).startsWith(neededAddInst)) {
      found++;
   }
}

@shipilev
Copy link
Member

shipilev commented Jul 7, 2025

Then again, it does not address a central point: the test keeps relying on particular instruction scheduling, which is not reliable. Why do we even need to search for ldp+add anchor? Can we just blindly search for spin-wait-looking instructions? I would expect block_comment to be even more reliable, as @theRealAph suggested.

@eastig
Copy link
Member Author

eastig commented Jul 7, 2025

I would expect block_comment to be even more reliable

I have rewrote the test to use block_comment.

@openjdk openjdk bot removed the rfr Pull request is ready for review label Jul 7, 2025
@openjdk openjdk bot added the rfr Pull request is ready for review label Jul 7, 2025
@@ -6803,6 +6803,7 @@ void MacroAssembler::verify_cross_modify_fence_not_required() {
#endif

void MacroAssembler::spin_wait() {
block_comment("spin_wait");
Copy link
Contributor

Choose a reason for hiding this comment

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

You need something unique. e.g.

Suggested change
block_comment("spin_wait");
block_comment("spin_wait_ohthoo8H");

Copy link
Member

Choose a reason for hiding this comment

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

Erm, I don't see why?

Copy link
Contributor

Choose a reason for hiding this comment

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

Erm, I don't see why?

To make it unique? I don't see why you don't see that we need to ensure that the string is unique.

Copy link
Member Author

Choose a reason for hiding this comment

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

@theRealAph, what do you think to have it in the format: spin_wait_%INST-COUNT%_%INST_NAME%?
For example: spin_wait_1_isb

Copy link
Member

@shipilev shipilev Jul 8, 2025

Choose a reason for hiding this comment

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

But this is a generic macroAssembler block comment. It does not make sense to me to have a block comment that looks like a memory corrupted string, just to satisfy a single test. There should be a middle-ground here, e.g. spin_wait {, which looks reasonably enough as the block comment, and not anything else. Would also match nicely when we emit the closing } at the end of the instruction block.

Copy link
Member Author

Choose a reason for hiding this comment

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

I like the idea of having {, }.
IMO this should be informative:

 ;; spin_wait_3_nop {
 nop
 nop
 nop
 ;; }

Copy link
Member

Choose a reason for hiding this comment

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

Putting _3_nop might be convenient, but I think that would introduce too much hassle in macroAssembler? Just this looks okay to me:

;; spin_wait {
nop
nop
nop
;; }

Copy link
Member Author

Choose a reason for hiding this comment

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

@theRealAph, are you okay with the latest variant Aleksey proposes?

Copy link
Contributor

Choose a reason for hiding this comment

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

But this is a generic macroAssembler block comment. It does not make sense to me to have a block comment that looks like a memory corrupted string, just to satisfy a single test. There should be a middle-ground here, e.g. spin_wait {, which looks reasonably enough as the block comment, and not anything else. Would also match nicely when we emit the closing } at the end of the instruction block.

OK

Copy link
Member Author

Choose a reason for hiding this comment

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

I update the PR to use spin_wait { ... }

@eastig
Copy link
Member Author

eastig commented Jul 9, 2025

Two MacOS tests failed due to time out. This is not related to my change.

Copy link
Member

@shipilev shipilev left a comment

Choose a reason for hiding this comment

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

Good patch. I propose a few cosmetics: 8360936-cosmetics-1.patch.txt -- easier to express them as patch. Untested, see if it makes sense?

@eastig
Copy link
Member Author

eastig commented Jul 9, 2025

Good patch. I propose a few cosmetics: 8360936-cosmetics-1.patch.txt -- easier to express them as patch. Untested, see if it makes sense?

Thank you! It make sense.

@eastig
Copy link
Member Author

eastig commented Jul 9, 2025

Good patch. I propose a few cosmetics: 8360936-cosmetics-1.patch.txt -- easier to express them as patch. Untested, see if it makes sense?

Thank you! It make sense.

I tested it. It works as expected.

Copy link
Member

@shipilev shipilev left a comment

Choose a reason for hiding this comment

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

Looks good to me, thanks.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Jul 10, 2025
if (nextLine.contains(substring)) {
return nextLine;
String line = iter.next().trim();
if (line.startsWith(";;}")) {
Copy link
Member

Choose a reason for hiding this comment

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

Oh, apologies, I made a little mistake here when playing around with trims. Should be:

Suggested change
if (line.startsWith(";;}")) {
if (line.startsWith(";; }")) {

The test probably does not fail because it meets no instructions beyond the spin_wait block. Cleaner to fix it anyway.

Copy link
Member Author

Choose a reason for hiding this comment

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

I fixed this.
I have also added a specialized lambda function to count expected instructions:

  • for disassembled code, just check a line.
  • for hex code, split and count.

Copy link
Member

Choose a reason for hiding this comment

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

Not sure lambdas make this cleaner, TBH.

Copy link
Member Author

Choose a reason for hiding this comment

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

Ok, the lambda is removed.

@openjdk openjdk bot removed the ready Pull request is ready to be integrated label Jul 10, 2025
@openjdk openjdk bot added the ready Pull request is ready to be integrated label Jul 10, 2025
@eastig
Copy link
Member Author

eastig commented Jul 11, 2025

/integrate

@openjdk
Copy link

openjdk bot commented Jul 11, 2025

Going to push as commit a86dd56.
Since your change was applied there have been 28 commits pushed to the master branch:

Your commit was automatically rebased without conflicts.

@openjdk openjdk bot added the integrated Pull request has been integrated label Jul 11, 2025
@openjdk openjdk bot closed this Jul 11, 2025
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Jul 11, 2025
@openjdk
Copy link

openjdk bot commented Jul 11, 2025

@eastig Pushed as commit a86dd56.

💡 You may see a message that your pull request was closed with unmerged commits. This can be safely ignored.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
hotspot-compiler hotspot-compiler-dev@openjdk.org integrated Pull request has been integrated
Development

Successfully merging this pull request may close these issues.

3 participants