Skip to content

Conversation

@ashu-mehra
Copy link
Contributor

@ashu-mehra ashu-mehra commented Oct 7, 2025

This patch adds fast clinit barrier in the interpreter when resolving cp entry for a static field.

Testing: tested x86-64 by running hotspot_runtime group
Specifically, runtime/clinit/ClassInitBarrier.java fails if the block for adding clinit_barrier is commented out in TemplateTable::resolve_cache_and_index_for_field


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-8369296: Add fast class init checks in interpreter for resolving ConstantPool entries for static field (Enhancement - P4)

Reviewers

Contributors

  • Vladimir Ivanov <vlivanov@openjdk.org>
  • Amit Kumar <amitkumar@openjdk.org>
  • Fei Yang <fyang@openjdk.org>
  • Martin Doerr <mdoerr@openjdk.org>

Reviewing

Using git

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

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

Using Skara CLI tools

Checkout this PR locally:
$ git pr checkout 27676

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

Using diff file

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

Using Webrev

Link to Webrev Comment

…tantPool entries for static field

Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
@ashu-mehra
Copy link
Contributor Author

/contributor add @iwanowww

@bridgekeeper
Copy link

bridgekeeper bot commented Oct 7, 2025

👋 Welcome back asmehra! 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 Oct 7, 2025

@ashu-mehra 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:

8369296: Add fast class init checks in interpreter for resolving ConstantPool entries for static field

Co-authored-by: Vladimir Ivanov <vlivanov@openjdk.org>
Co-authored-by: Amit Kumar <amitkumar@openjdk.org>
Co-authored-by: Fei Yang <fyang@openjdk.org>
Co-authored-by: Martin Doerr <mdoerr@openjdk.org>
Reviewed-by: mdoerr, vlivanov, kvn, amitkumar, fyang, mli

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 144 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
Copy link

openjdk bot commented Oct 7, 2025

@ashu-mehra
Contributor Vladimir Ivanov <vlivanov@openjdk.org> successfully added.

@openjdk openjdk bot added the hotspot hotspot-dev@openjdk.org label Oct 7, 2025
@openjdk
Copy link

openjdk bot commented Oct 7, 2025

@ashu-mehra 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.

@openjdk openjdk bot added the rfr Pull request is ready for review label Oct 7, 2025
@mlbridge
Copy link

mlbridge bot commented Oct 7, 2025

Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
@ashu-mehra
Copy link
Contributor Author

@offamitkumar @Hamlin-Li @RealFYang @TheRealMDoerr
I need help in adding arch specific code for s390, risc-v and ppc for this PR. Would you be able to contribute the code for these platforms? Specifically, we need to add a call to clinit_barrier in TemplateTable::resolve_cache_and_index_for_field.

@vnkozlov @adinn @iwanowww can you please review this patch.

@offamitkumar
Copy link
Member

Hi @ashu-mehra,

This is fixing the test failure on s390:

diff --git a/src/hotspot/cpu/s390/templateTable_s390.cpp b/src/hotspot/cpu/s390/templateTable_s390.cpp
index 2b39cc8318c..cf34bff7746 100644
--- a/src/hotspot/cpu/s390/templateTable_s390.cpp
+++ b/src/hotspot/cpu/s390/templateTable_s390.cpp
@@ -2409,6 +2409,7 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
   assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");
 
   NearLabel resolved;
+  Label L_clinit_barrier_slow;
 
   Bytecodes::Code code = bytecode();
   switch (code) {
@@ -2425,6 +2426,8 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
   __ z_bre(resolved);
 
   // resolve first time through
+  // Class initialization barrier slow path lands here as well.
+  __ bind(L_clinit_barrier_slow);
   address entry = CAST_FROM_FN_PTR(address, InterpreterRuntime::resolve_from_cache);
   __ load_const_optimized(Z_ARG2, (int)code);
   __ call_VM(noreg, entry, Z_ARG2);
@@ -2434,6 +2437,15 @@ void TemplateTable::resolve_cache_and_index_for_field(int byte_no,
 
   __ bind(resolved);
 
+  // Class initialization barrier for static fields
+  if (VM_Version::supports_fast_class_init_checks() &&
+      (bytecode() == Bytecodes::_getstatic || bytecode() == Bytecodes::_putstatic)) {
+    const Register field_holder = index;
+
+    __ load_sized_value(field_holder, Address(cache, ResolvedFieldEntry::field_holder_offset()), sizeof(void*), false);
+    __ clinit_barrier(field_holder, Z_thread, nullptr /*L_fast_path*/, &L_clinit_barrier_slow);
+  }
+
   BLOCK_COMMENT("} resolve_cache_and_index_for_field");
 }

@iwanowww
Copy link
Contributor

iwanowww commented Oct 7, 2025

x86- and aarch64-specific changes look good.

There are 3 other platforms (ppc, s390, and riscv) which report VM_Version::supports_fast_class_init_checks() == true. All of them require similar changes in platform-specific code.

Copy link
Contributor

@vnkozlov vnkozlov left a comment

Choose a reason for hiding this comment

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

Can we loop to L_clinit_barrier_slow several times until class is initialized?

@iwanowww
Copy link
Contributor

iwanowww commented Oct 7, 2025

Can we loop to L_clinit_barrier_slow several times until class is initialized?

No, clinit_barrier either "blocks" (not yet initialized or being initialized, but not in init thread) or returns right away (fully initialized or being initialized and in init thread). No need for repeated attempts.

@vnkozlov
Copy link
Contributor

vnkozlov commented Oct 7, 2025

Can we loop to L_clinit_barrier_slow several times until class is initialized?

No, clinit_barrier either "blocks" (not yet initialized or being initialized, but not in init thread) or returns right away (fully initialized or being initialized and in init thread). No need for repeated attempts.

First, what do you mean "blocks"? It wait something with lock?

Second, my question was that slow path in clinit_barrier will jump to L_clinit_barrier_slow which is before clinit_barrier there are no branch there so after call_VM we again will call clinit_barrier? what I am missing?

@ashu-mehra
Copy link
Contributor Author

First, what do you mean "blocks"? It wait something with lock?

Second, my question was that slow path in clinit_barrier will jump to L_clinit_barrier_slow which is before clinit_barrier there are no branch there so after call_VM we again will call clinit_barrier? what I am missing?

clinit_barrier itself doesn't block. Its a quick check for class fully initialized or the current thread is the init thread. If not, then it jumps to the slow path. In this case slow path is the call to InterpreterRuntime::resolve_from_cache which may initialize the klass or get blocked if the klass is being initialized by another thread.
After returning it again executes clinit_barrier. But this time the class should have initialized, so it just falls through.

Also, I think clinit_barrier is not a very accurate name because it doesn't cause initialization of the klass. I think fast_clinit_check better conveys what it is doing, but that renaming can be done later if required.

@vnkozlov
Copy link
Contributor

vnkozlov commented Oct 7, 2025

Thank you @ashu-mehra for explanation. So we can call clinit_barrier second time but not more. Good.

fast_clinit_check better conveys what it is doing,

Agree.

@vnkozlov
Copy link
Contributor

vnkozlov commented Oct 7, 2025

I submitted our testing.

Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
@ashu-mehra
Copy link
Contributor Author

@offamitkumar thanks for the patch. I have added it.

@ashu-mehra
Copy link
Contributor Author

/contributor add @offamitkumar

@openjdk
Copy link

openjdk bot commented Oct 7, 2025

@ashu-mehra
Contributor Amit Kumar <amitkumar@openjdk.org> successfully added.

@iwanowww
Copy link
Contributor

iwanowww commented Oct 7, 2025

After returning it again executes clinit_barrier. But this time the class should have initialized, so it just falls through.

There are no guarantees that the class is initialized. But the only case when it doesn't hold is when the class is being initialized and current thread is initializing one. So, it is guaranteed that slow path is taken at most once.

I think fast_clinit_check better conveys what it is doing

clinit_barrier implements a fast path check, so clinit_barrier_fast_path maybe a more accurate variant.

@ashu-mehra
Copy link
Contributor Author

clinit_barrier implements a fast path check, so clinit_barrier_fast_path maybe a more accurate variant.

yes, clinit_barrier_fast_path is better.

@RealFYang
Copy link
Member

@ashu-mehra
Hi, Thanks for the ping! And here is the riscv-specific changes:
27676-riscv.diff.txt
hotspot:tier1 and hotspot_runtime passed with fastdebug build on linux-riscv64.

@adinn
Copy link
Contributor

adinn commented Oct 8, 2025

x86- and aarch64-specific changes look fine to me.

Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
@ashu-mehra
Copy link
Contributor Author

@RealFYang thanks for the patch. I added it.

@ashu-mehra
Copy link
Contributor Author

/contributor add @RealFYang

Copy link
Contributor

@TheRealMDoerr TheRealMDoerr left a comment

Choose a reason for hiding this comment

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

Unfortunately, this is no longer correct for PPC64 because the isync instruction is missing on some paths, now. While this looks good for other platforms, can you revert only PPC64 to the previous version, please?

Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
@ashu-mehra
Copy link
Contributor Author

Unfortunately, this is no longer correct for PPC64 because the isync instruction is missing on some paths, now. While this looks good for other platforms, can you revert only PPC64 to the previous version, please?

@TheRealMDoerr thanks for catching the bug. The resolved non-static case is missing the isync. Reverted the ppc changes as suggested.

Copy link
Contributor

@TheRealMDoerr TheRealMDoerr left a comment

Choose a reason for hiding this comment

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

Thank you for improving it for all platforms! I think it is better readably, now. Only a minor nit. We'll retest it over the weekend.

const Register klass = Rscratch;



Copy link
Contributor

Choose a reason for hiding this comment

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

Can you remove these extra empty lines, please?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

Copy link
Contributor

@vnkozlov vnkozlov left a comment

Choose a reason for hiding this comment

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

aarch64 and x64 changes looks good to me.
I need to run new testing.

Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
@openjdk openjdk bot added the ready Pull request is ready to be integrated label Oct 10, 2025
Copy link
Contributor

@vnkozlov vnkozlov left a comment

Choose a reason for hiding this comment

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

My v08 testing passed.

Copy link
Member

@RealFYang RealFYang left a comment

Choose a reason for hiding this comment

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

Update to RISC-V part looks fine. And hotspot_runtime still test good with fastdebug build on linux-riscv64.

@TheRealMDoerr
Copy link
Contributor

Test results look good on all SAP supported platforms (including linux and AIX on PPC64).

Copy link

@Hamlin-Li Hamlin-Li left a comment

Choose a reason for hiding this comment

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

Riscv part looks good, Thanks!

assert(byte_no == f1_byte || byte_no == f2_byte, "byte_no out of range");

Label resolved, clinit_barrier_slow;
Label Lclinit_barrier_slow, Ldone;
Copy link
Contributor

Choose a reason for hiding this comment

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

Minor comment: why don't you use L_name instead? Lname is a new idiom for naming labels on most of the platforms. (The convention is either L_name or simply name almost everywhere.)

Copy link
Contributor

Choose a reason for hiding this comment

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

Sorry, I guess that was my mistake. Changing it would be fine with me. Not a big deal, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I will update the label names to use the convention L_name.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

__ br(Assembler::EQ, resolved);

// Class initialization barrier for static methods
if (VM_Version::supports_fast_class_init_checks() && bytecode() == Bytecodes::_invokestatic) {
Copy link
Contributor

Choose a reason for hiding this comment

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

FTR VM_Version::supports_fast_class_init_checks() is redundant in platform-specific code.

The method is intended to be used in shared code to support dispatching between 2 execution modes, but for each platform is it known well ahead whether fast class init checks are supported or not.

(It does make sense to keep it as an assert through.)

Copy link
Contributor

Choose a reason for hiding this comment

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

True, but I also like the current implementation from a readability perspective.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Let's keep it for now. I will remove VM_Version::supports_fast_class_init_checks() from platform-specific code in a follow-up PR.

Copy link
Contributor

Choose a reason for hiding this comment

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

Sounds good, thanks!

Signed-off-by: Ashutosh Mehra <asmehra@redhat.com>
@openjdk openjdk bot removed the ready Pull request is ready to be integrated label Oct 14, 2025
@ashu-mehra
Copy link
Contributor Author

@iwanowww I addressed your suggestion to rename the labels.

@openjdk openjdk bot added the ready Pull request is ready to be integrated label Oct 14, 2025
@vnkozlov
Copy link
Contributor

No code change after v08 (only labels were renamed and empty lines removed) - no need to re-test.

@ashu-mehra
Copy link
Contributor Author

okay, lets get this in. Thanks everyone for the reviews and suggestions.

@ashu-mehra
Copy link
Contributor Author

/integrate

@openjdk
Copy link

openjdk bot commented Oct 14, 2025

Going to push as commit 622a611.
Since your change was applied there have been 149 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 Oct 14, 2025
@openjdk openjdk bot closed this Oct 14, 2025
@openjdk openjdk bot removed ready Pull request is ready to be integrated rfr Pull request is ready for review labels Oct 14, 2025
@openjdk
Copy link

openjdk bot commented Oct 14, 2025

@ashu-mehra Pushed as commit 622a611.

💡 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 hotspot-dev@openjdk.org integrated Pull request has been integrated

Development

Successfully merging this pull request may close these issues.

8 participants