Skip to content

8356075: Support Shenandoah GC in JVMCI #25001

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 11 commits into from
6 changes: 6 additions & 0 deletions src/hotspot/share/gc/shenandoah/shenandoahHeap.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@
#include "utilities/events.hpp"
#include "utilities/globalDefinitions.hpp"
#include "utilities/powerOfTwo.hpp"
#if INCLUDE_JVMCI
#include "jvmci/jvmci.hpp"
#endif
#if INCLUDE_JFR
#include "gc/shenandoah/shenandoahJfrSupport.hpp"
#endif
Expand Down Expand Up @@ -2233,6 +2236,9 @@ void ShenandoahHeap::stw_unload_classes(bool full_gc) {
ShenandoahGCWorkerPhase worker_phase(phase);
bool unloading_occurred = SystemDictionary::do_unloading(gc_timer());

// Clean JVMCI metadata handles.
JVMCI_ONLY(JVMCI::do_unloading(unloading_occurred));

uint num_workers = _workers->active_workers();
ShenandoahClassUnloadingTask unlink_task(phase, num_workers, unloading_occurred);
_workers->run_task(&unlink_task);
Expand Down
3 changes: 3 additions & 0 deletions src/hotspot/share/gc/shenandoah/shenandoahRuntime.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class ShenandoahRuntime : public AllStatic {
static void arraycopy_barrier_narrow_oop(narrowOop* src, narrowOop* dst, size_t length);

static void write_ref_field_pre(oopDesc* orig, JavaThread* thread);
static void pre_barrier(JavaThread* thread, oopDesc* orig) {
write_ref_field_pre(orig, thread);
}
Copy link
Member

Choose a reason for hiding this comment

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

So, why not export write_ref_field_pre, instead of introducing this new method? Style/cleanliness, or something else? I am asking, because every time we add a new stub here, we would need to record it in AOTCache tables for Leyden benefit.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It's about the argument ordering. Graal expects the Thread* to be prependend, while other JITs call it with the Thread* appended. I guess we could change other JIT calls to also prepend the thread, or change the interface to not pass the Thread* at all. I chose to follow G1 and export both variants.

Copy link
Member

@shipilev shipilev May 5, 2025

Choose a reason for hiding this comment

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

Oh, so this matches JVMCIRuntime::write_barrier_pre for G1 (weird place to have it, but oh well).

Does Graal need the Thread* argument?

I think this method is only called when SATB buffer is full. So the performance of this method is likely not affected by getting the current thread down in caller. So I think it would be more straight-forward to sharpen ShenandoahRuntime::write_ref_field_pre by dropping Thread* and then exporting that. Maybe also under the SR::write_barrier_pre name to be even more consistent for everything else.

Maybe @JohnTortugo wants to clean up more mess in C2 related to this :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Graal does not need the Thread* argument, but the runtime code behind write_ref_pre() currently uses it. I agree, it does not look performance critical to pass it through. However, getting rid of it seems to blow the scope of this PR. I'd rather do this as a follow-up.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Actually, I'd probably add the new entry for Graal without the Thread* argument now, and fix the others in a follow-up. Otherwise we need to deal with it on the Graal side again later once we change the entry points.

Copy link
Member

Choose a reason for hiding this comment

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

OK, but that follow-up risks changing the JVMCI interface again? How about we introduce:

static void write_barrier_pre(oopDesc* pre_val) {
  write_ref_field_pre(pre_val, JavaThread::current());
}

...and then the follow-up purges the old write_ref_field_pre? The implementation might need to be in .cpp.


static oopDesc* load_reference_barrier_strong(oopDesc* src, oop* load_addr);
static oopDesc* load_reference_barrier_strong_narrow(oopDesc* src, narrowOop* load_addr);
Expand Down
4 changes: 4 additions & 0 deletions src/hotspot/share/jvmci/jvmciCompilerToVM.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,10 @@ class CompilerToVM {
#if INCLUDE_ZGC
static int sizeof_ZStoreBarrierEntry;
#endif
#if INCLUDE_SHENANDOAHGC
static address shenandoah_in_cset_fast_test_addr;
static int shenandoah_region_size_bytes_shift;
#endif

#ifdef X86
static int L1_line_size;
Expand Down
18 changes: 18 additions & 0 deletions src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,10 @@
#include "runtime/sharedRuntime.hpp"
#include "runtime/stubRoutines.hpp"
#include "utilities/resourceHash.hpp"
#if INCLUDE_SHENANDOAHGC
#include "gc/shenandoah/shenandoahHeap.hpp"
#include "gc/shenandoah/shenandoahHeapRegion.hpp"
#endif

int CompilerToVM::Data::oopDesc_klass_offset_in_bytes;
int CompilerToVM::Data::arrayOopDesc_length_offset_in_bytes;
Expand Down Expand Up @@ -86,6 +90,11 @@ address CompilerToVM::Data::ZPointerVectorLoadBadMask_address;
address CompilerToVM::Data::ZPointerVectorStoreBadMask_address;
address CompilerToVM::Data::ZPointerVectorStoreGoodMask_address;

#if INCLUDE_SHENANDOAHGC
address CompilerToVM::Data::shenandoah_in_cset_fast_test_addr;
int CompilerToVM::Data::shenandoah_region_size_bytes_shift;
#endif

bool CompilerToVM::Data::continuations_enabled;

#ifdef AARCH64
Expand Down Expand Up @@ -227,12 +236,21 @@ void CompilerToVM::Data::initialize(JVMCI_TRAPS) {
assert(base != nullptr, "unexpected byte_map_base");
cardtable_start_address = base;
cardtable_shift = CardTable::card_shift();
} else if (bs->is_a(BarrierSet::ShenandoahBarrierSet)) {
Copy link
Member

@dougxc dougxc May 6, 2025

Choose a reason for hiding this comment

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

This change is causing a failure in mach5 tier 1:

[2025-05-06T11:34:44,742Z] /workspace/open/src/hotspot/share/jvmci/jvmciCompilerToVMInit.cpp:239:35: error: no member named 'ShenandoahBarrierSet' in 'BarrierSet'
[2025-05-06T11:34:44,742Z]   } else if (bs->is_a(BarrierSet::ShenandoahBarrierSet)) {
[2025-05-06T11:34:44,742Z]                       ~~~~~~~~~~~~^
[2025-05-06T11:34:45,729Z] 1 error generated.

I assume it's missing #if INCLUDE_SHENANDOAHGC.

https://bugs.openjdk.org/browse/JDK-8356265

cardtable_shift = CardTable::card_shift();
} else {
// No card mark barriers
cardtable_start_address = nullptr;
cardtable_shift = 0;
}

#if INCLUDE_SHENANDOAHGC
if (UseShenandoahGC) {
shenandoah_in_cset_fast_test_addr = ShenandoahHeap::in_cset_fast_test_addr();
shenandoah_region_size_bytes_shift = ShenandoahHeapRegion::region_size_bytes_shift_jint();
}
#endif

#ifdef X86
L1_line_size = VM_Version::L1_line_size();
#endif
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/jvmci/jvmci_globals.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -229,7 +229,7 @@ bool JVMCIGlobals::enable_jvmci_product_mode(JVMFlagOrigin origin, bool use_graa
}

bool JVMCIGlobals::gc_supports_jvmci() {
return UseSerialGC || UseParallelGC || UseG1GC || UseZGC || UseEpsilonGC;
return UseSerialGC || UseParallelGC || UseG1GC || UseZGC || UseShenandoahGC || UseEpsilonGC;
}

void JVMCIGlobals::check_jvmci_supported_gc() {
Expand Down
27 changes: 27 additions & 0 deletions src/hotspot/share/jvmci/vmStructs_jvmci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@
#include "gc/z/zBarrierSetRuntime.hpp"
#include "gc/z/zThreadLocalData.hpp"
#endif
#if INCLUDE_SHENANDOAHGC
#include "gc/shenandoah/shenandoahRuntime.hpp"
#include "gc/shenandoah/shenandoahThreadLocalData.hpp"
#endif

#define VM_STRUCTS(nonstatic_field, static_field, unchecked_nonstatic_field, volatile_nonstatic_field) \
static_field(CompilerToVM::Data, oopDesc_klass_offset_in_bytes, int) \
Expand Down Expand Up @@ -129,6 +133,8 @@
static_field(CompilerToVM::Data, sizeof_arrayOopDesc, int) \
static_field(CompilerToVM::Data, sizeof_BasicLock, int) \
ZGC_ONLY(static_field(CompilerToVM::Data, sizeof_ZStoreBarrierEntry, int)) \
SHENANDOAHGC_ONLY(static_field(CompilerToVM::Data, shenandoah_in_cset_fast_test_addr, address)) \
SHENANDOAHGC_ONLY(static_field(CompilerToVM::Data, shenandoah_region_size_bytes_shift,int)) \
\
static_field(CompilerToVM::Data, dsin, address) \
static_field(CompilerToVM::Data, dcos, address) \
Expand Down Expand Up @@ -895,6 +901,13 @@
declare_function(JVMCIRuntime::load_and_clear_exception) \
G1GC_ONLY(declare_function(JVMCIRuntime::write_barrier_pre)) \
G1GC_ONLY(declare_function(JVMCIRuntime::write_barrier_post)) \
SHENANDOAHGC_ONLY(declare_function(ShenandoahRuntime::load_reference_barrier_strong)) \
SHENANDOAHGC_ONLY(declare_function(ShenandoahRuntime::load_reference_barrier_strong_narrow)) \
SHENANDOAHGC_ONLY(declare_function(ShenandoahRuntime::load_reference_barrier_weak)) \
SHENANDOAHGC_ONLY(declare_function(ShenandoahRuntime::load_reference_barrier_weak_narrow)) \
SHENANDOAHGC_ONLY(declare_function(ShenandoahRuntime::load_reference_barrier_phantom)) \
SHENANDOAHGC_ONLY(declare_function(ShenandoahRuntime::load_reference_barrier_phantom_narrow)) \
SHENANDOAHGC_ONLY(declare_function(ShenandoahRuntime::pre_barrier)) \
declare_function(JVMCIRuntime::validate_object) \
\
declare_function(JVMCIRuntime::test_deoptimize_call_int)
Expand Down Expand Up @@ -941,6 +954,15 @@

#endif // INCLUDE_ZGC

#if INCLUDE_SHENANDOAHGC

#define VM_INT_CONSTANTS_JVMCI_SHENANDOAH(declare_constant, declare_constant_with_value, declare_preprocessor_constant) \
declare_constant_with_value("ShenandoahThreadLocalData::gc_state_offset", in_bytes(ShenandoahThreadLocalData::gc_state_offset())) \
declare_constant_with_value("ShenandoahThreadLocalData::satb_mark_queue_index_offset", in_bytes(ShenandoahThreadLocalData::satb_mark_queue_index_offset())) \
declare_constant_with_value("ShenandoahThreadLocalData::satb_mark_queue_buffer_offset", in_bytes(ShenandoahThreadLocalData::satb_mark_queue_buffer_offset())) \
declare_constant_with_value("ShenandoahThreadLocalData::card_table_offset", in_bytes(ShenandoahThreadLocalData::card_table_offset())) \

#endif

#ifdef LINUX

Expand Down Expand Up @@ -1063,6 +1085,11 @@ VMIntConstantEntry JVMCIVMStructs::localHotSpotVMIntConstants[] = {
GENERATE_VM_INT_CONSTANT_WITH_VALUE_ENTRY,
GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
#endif
#if INCLUDE_SHENANDOAHGC
VM_INT_CONSTANTS_JVMCI_SHENANDOAH(GENERATE_VM_INT_CONSTANT_ENTRY,
GENERATE_VM_INT_CONSTANT_WITH_VALUE_ENTRY,
GENERATE_PREPROCESSOR_VM_INT_CONSTANT_ENTRY)
#endif
#ifdef VM_INT_CPU_FEATURE_CONSTANTS
VM_INT_CPU_FEATURE_CONSTANTS
#endif
Expand Down