Skip to content

8362193: Re-work MacOS/AArch64 SpinPause to handle SB #26387

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

Draft
wants to merge 12 commits into
base: master
Choose a base branch
from

Conversation

eastig
Copy link
Member

@eastig eastig commented Jul 18, 2025

Background

With JDK-8359435 "AArch64: add support for SB instruction to MacroAssembler::spin_wait" we have an option to use the speculation barrier (SB) instruction for j.l.Thread::onSpinWait and SpinPause. On Linux AArch64 SpinPause uses a stub which is generated with MacroAssembler::spin_wait. j.l.Thread::onSpinWait uses it as well. As a result tests for j.l.Thread::onSpinWait, e.g.compiler/onSpinWait/TestOnSpinWaitAArch64.java, cover both j.l.Thread::onSpinWait and SpinPause. Also we don't need to update SpinPause when we add support for a new instruction to MacroAssembler::spin_wait.

On Mac AArch64 SpinPause does not use the generated stub to avoid a costly call to os::current_thread_enable_wx(). It uses inline assembly instead. As a result we have SpinWait implementation details leaking into SpinPause. Besides asserts there are no tests covering Mac implementation of SpinPause. Testing on Apple M3 Pro showed that compiler/onSpinWait/TestOnSpinWaitAArch64.java could not reliably trigger those asserts. ArchiveWorkers::run_task_multi did not invoke spin.wait(). The inline assembly in Mac AArch64 SpinPause has another issue. It uses a jump table. An offset in the table is calculated based on the value of enum SpinWait::Inst. When a new value SB was added the offset became out of bounds. The jump goes out of the assembly code.

Summary of changes

  • Rewrote Mac AArch64 SpinPause not to use a jump table.
  • Added SpinWait::supports() and SpinWait::from_name() methods to validate and convert instruction names into corresponding enum values.
  • Updated SpinWait::Inst enum to use bit flags for simplified assembly testing and added a constructor to initialize SpinWait using instruction names.
  • src/hotspot/cpu/aarch64/macroAssembler_aarch64.cpp: Added an assertion to ensure the sb instruction is supported by the CPU before generation.
  • Updated the OnSpinWaitInst flag description to clarify valid values and added runtime constraints.
  • Added a basic gtest to verify the functionality of SpinPause.
  • Added a jtreg test to run the gtest forSpinPause with various instructions, including a separate test for the sb instruction if supported by the CPU.

Testing results: fastdebug, release

  • Linux, Graviton 2
    • tier1: Passed
    • test/hotspot/jtreg/gtest/TestSpinPauseAArch64.java: Passed
    • test/hotspot/jtreg/compiler/onSpinWait: Passed
  • Linux, Graviton 4
    • tier1: TBD
    • test/hotspot/jtreg/gtest/TestSpinPauseAArch64.java: TBD
    • test/hotspot/jtreg/compiler/onSpinWait: TBD
  • MacOS, M3 Pro
    • tier1: TBD
    • test/hotspot/jtreg/gtest/TestSpinPauseAArch64.java: TBD
    • test/hotspot/jtreg/compiler/onSpinWait: TBD

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-8362193: Re-work MacOS/AArch64 SpinPause to handle SB (Bug - P3)

Reviewing

Using git

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

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

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 26387

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

Using diff file

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

@bridgekeeper
Copy link

bridgekeeper bot commented Jul 18, 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 18, 2025

❗ This change is not yet ready to be integrated.
See the Progress checklist in the description for automated requirements.

@openjdk
Copy link

openjdk bot commented Jul 18, 2025

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

  • hotspot

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.

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.

Overall, I think it is not very reasonable to pull things into shared parts, when that deviates significantly from the common Hotspot way of handling things. I don't think it even saves us any duplication to move implementations to spin_wait_aarch64.(inline.)pp? So I suggest we don't.

* @requires vm.flagless
* @requires os.arch=="aarch64"
* @requires vm.cpu.features ~= ".*sb.*"
* @run main/native GTestWrapper --gtest_filter=SpinPause* -XX:+UnlockDiagnosticVMOptions -XX:OnSpinWaitInst=sb
Copy link
Member

Choose a reason for hiding this comment

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

This configuration is for @requires vm.cpu.features ~= ".*sb.*", correct?

If so, you can put this entire @test block in the TestSpinPauseAArch64.java, then jtreg would just execute them as subtests. Here is an inspiration: https://github.com/openjdk/jdk/blob/master/test/hotspot/jtreg/gc/shenandoah/TestAllocObjects.java

* questions.
*/

/**
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
/**
/*

@@ -114,10 +115,11 @@ define_pd_global(intx, InlineSmallCode, 1000);
"Use prfm hint with specified distance in compiled code." \
"Value -1 means off.") \
range(-1, 4096) \
product(ccstr, OnSpinWaitInst, "yield", DIAGNOSTIC, \
product(ccstr, OnSpinWaitInst, DEFAULT_SPIN_WAIT_INST, DIAGNOSTIC, \
Copy link
Member

Choose a reason for hiding this comment

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

It is somewhat weird to introduce references to macros here. At some point, this might lead to interesting include circularities, as I think globals.* are supposed to be at the leaves of include trees. Other options do not do this, see for example UseBranchProtection below. So, keep this part intact?

@eastig
Copy link
Member Author

eastig commented Jul 18, 2025

Overall, I think it is not very reasonable to pull things into shared parts, when that deviates significantly from the common Hotspot way of handling things. I don't think it even saves us any duplication to move implementations to spin_wait_aarch64.(inline.)pp? So I suggest we don't.

Do I understand you correctly we should not have exec_spin_wait_inst and generate_spin_wait?

@shipilev
Copy link
Member

shipilev commented Jul 18, 2025

Overall, I think it is not very reasonable to pull things into shared parts, when that deviates significantly from the common Hotspot way of handling things. I don't think it even saves us any duplication to move implementations to spin_wait_aarch64.(inline.)pp? So I suggest we don't.

Do I understand you correctly we should not have exec_spin_wait_inst and generate_spin_wait?

Yes. I don't see a benefit for them? Collecting everything related to spin wait implementation is not worth it, IMO. We have duplication by asm-stubs, macroassembler, c1_assembler, c2.ad rules for the arch-specific code already.

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.

More reviews.

I think the PR drifted from my initial "oh, just assert range problem" to "Re-work MacOS/AArch64 spin-waits to handle SB". Rewrite the JBS/PR title accordingly?

*/

/*
* @test TestSpinPauseAArch64
Copy link
Member

Choose a reason for hiding this comment

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

A common way to tag the tests:

@test id=default

I assume all these are supported in ARMv8.0 (default? baseline?) profile. That's why I put default. Put something else if that is incorrect.

Same for the second @test block.

return SpinWait(SpinWait::SB, OnSpinWaitInstCount);
} else if (strcmp(OnSpinWaitInst, "none") != 0) {
vm_exit_during_initialization("The options for OnSpinWaitInst are nop, isb, yield, sb, and none", OnSpinWaitInst);
if (!SpinWait::supports(OnSpinWaitInst)) {
Copy link
Member

Choose a reason for hiding this comment

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

So this is not about the actual spin-wait hints support, correct? This only checks the option string is in expected domain? A common way to deal with this is to use constraint functions, see for example:

  product(ccstr, AOTCache, nullptr,                                         \
          "Cache for improving start up and warm up")                       \
          constraint(AOTCacheConstraintFunc, AtParse)                       \
                                                                            \

assert(inst_id == 0 || is_power_of_2(inst_id), "Values of SpinWait::Inst must be 0 or power of 2");
assert(inst_id != SpinWait::SB || VM_Version::supports_sb(), "current CPU does not support SB instruction");
if (inst_id > SpinWait::NOP) {
warining("Unsupported type of SpinWait::Inst: %d", inst_id);
Copy link
Member

Choose a reason for hiding this comment

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

warning

Also, I think we want to minimize the amount of code we actually execute in SpinPause, since it likely sits in the hot loop. So checking this here is probably counter-productive.

@eastig eastig changed the title 8362193: compiler/onSpinWait/TestOnSpinWaitAArch64.java asserts on spin-wait insns range checks 8362193: Re-work MacOS/AArch64 SpinPause to handle SB Jul 18, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

Successfully merging this pull request may close these issues.

2 participants