https://github.com/openjdk/jdk/blob/64f7972a3d0c82ad7047f73f0b57c3d88f62935f/src/hotspot/share/cds/heapShared.cpp#L433-L438
void HeapShared::mark_native_pointers(oop orig_obj) {
if (java_lang_Class::is_instance(orig_obj)) {
ArchiveHeapWriter::mark_native_pointer(orig_obj, java_lang_Class::klass_offset());
ArchiveHeapWriter::mark_native_pointer(orig_obj, java_lang_Class::array_klass_offset());
}
}
We can avoid marking these pointers (and relocating them at runtime) by storing the Class::{klass, array_klass} as an offset instead of a direct pointer.
I.e.,
Klass* java_lang_Class::array_klass_acquire(oop java_class) {
- Klass* k = ((Klass*)java_class->metadata_field_acquire(_array_klass_offset));
+ intx delta = (intx)(java_class->long_field_acquire(_array_klass_offset)));
+ Klass* k = (Klass*)((intx)SharedBaseAddress + delta);
assert(k == nullptr || (k->is_klass() && k->is_array_klass()), "should be array klass");
return k;
}
void java_lang_Class::release_set_array_klass(oop java_class, Klass* klass) {
assert(klass->is_klass() && klass->is_array_klass(), "should be array klass");
- java_class->release_metadata_field_put(_array_klass_offset, klass);
+ intx delta = ((intx)klass) - ((intx)SharedBaseAddress);
+ java_class->release_long_field_put(_array_klass_offset, (jlong)klass);
}
======= Update 2024/10/11
We have lots of assembly code that loads off java_lang_Class::klass_offset(), so all of those places would need to updated. This *might* cause performance degradation. So this proposal is more complicated that I thought, and there might be a trade off between start-up (will be faster( vs steady state (might be slower)
./cpu/aarch64/methodHandles_aarch64.cpp: __ ldr(klass_reg, Address(klass_reg, java_lang_Class::klass_offset()));
./cpu/arm/c1_CodeStubs_arm.cpp: __ ldr(Rtemp, Address(_obj, java_lang_Class::klass_offset()));
./cpu/arm/methodHandles_arm.cpp: __ ldr(klass_reg, Address(klass_reg, java_lang_Class::klass_offset()));
./cpu/ppc/c1_CodeStubs_ppc.cpp: __ ld(_obj, java_lang_Class::klass_offset(), _obj);
./cpu/ppc/methodHandles_ppc.cpp: __ ld(klass_reg, java_lang_Class::klass_offset(), klass_reg);
./cpu/riscv/methodHandles_riscv.cpp: __ ld(klass_reg, Address(klass_reg, java_lang_Class::klass_offset()));
./cpu/s390/c1_CodeStubs_s390.cpp: __ z_lg(Z_R1_scratch, java_lang_Class::klass_offset(), _obj);
./cpu/s390/methodHandles_s390.cpp: __ z_lg(klass_reg, Address(klass_reg, java_lang_Class::klass_offset()));
./cpu/x86/c1_CodeStubs_x86.cpp: __ movptr(tmp2, Address(_obj, java_lang_Class::klass_offset()));
./cpu/x86/methodHandles_x86.cpp: __ movptr(klass_reg, Address(klass_reg, java_lang_Class::klass_offset()));
./share/c1/c1_LIRGenerator.cpp: __ move(new LIR_Address(rcvr.result(), java_lang_Class::klass_offset(), T_ADDRESS), temp, info);
./share/c1/c1_LIRGenerator.cpp: __ move(new LIR_Address(receiver.result(), java_lang_Class::klass_offset(), T_ADDRESS), recv_klass, info);
./share/cds/heapShared.cpp: ArchiveHeapWriter::mark_native_pointer(orig_obj, java_lang_Class::klass_offset());
./share/gc/shenandoah/shenandoahAsserts.cpp: Metadata* klass = obj->metadata_field(java_lang_Class::klass_offset());
./share/gc/shenandoah/shenandoahVerifier.cpp: Metadata* klass = obj->metadata_field(java_lang_Class::klass_offset());
./share/jvmci/jvmciCompilerToVM.cpp: if (offset == java_lang_Class::klass_offset()) {
./share/opto/compile.cpp: if (flat->offset() == java_lang_Class::klass_offset()
./share/opto/library_call.cpp: basic_plus_adr(cls, java_lang_Class::klass_offset()),
./share/opto/library_call.cpp: int class_klass_offset = java_lang_Class::klass_offset();
./share/opto/library_call.hpp: int offset = java_lang_Class::klass_offset();
./share/opto/memnode.cpp: && (offset == java_lang_Class::klass_offset() ||
./share/opto/memnode.cpp: && offset == java_lang_Class::klass_offset()) {
./share/opto/type.cpp: (_offset == java_lang_Class::klass_offset() ||
void HeapShared::mark_native_pointers(oop orig_obj) {
if (java_lang_Class::is_instance(orig_obj)) {
ArchiveHeapWriter::mark_native_pointer(orig_obj, java_lang_Class::klass_offset());
ArchiveHeapWriter::mark_native_pointer(orig_obj, java_lang_Class::array_klass_offset());
}
}
We can avoid marking these pointers (and relocating them at runtime) by storing the Class::{klass, array_klass} as an offset instead of a direct pointer.
I.e.,
Klass* java_lang_Class::array_klass_acquire(oop java_class) {
- Klass* k = ((Klass*)java_class->metadata_field_acquire(_array_klass_offset));
+ intx delta = (intx)(java_class->long_field_acquire(_array_klass_offset)));
+ Klass* k = (Klass*)((intx)SharedBaseAddress + delta);
assert(k == nullptr || (k->is_klass() && k->is_array_klass()), "should be array klass");
return k;
}
void java_lang_Class::release_set_array_klass(oop java_class, Klass* klass) {
assert(klass->is_klass() && klass->is_array_klass(), "should be array klass");
- java_class->release_metadata_field_put(_array_klass_offset, klass);
+ intx delta = ((intx)klass) - ((intx)SharedBaseAddress);
+ java_class->release_long_field_put(_array_klass_offset, (jlong)klass);
}
======= Update 2024/10/11
We have lots of assembly code that loads off java_lang_Class::klass_offset(), so all of those places would need to updated. This *might* cause performance degradation. So this proposal is more complicated that I thought, and there might be a trade off between start-up (will be faster( vs steady state (might be slower)
./cpu/aarch64/methodHandles_aarch64.cpp: __ ldr(klass_reg, Address(klass_reg, java_lang_Class::klass_offset()));
./cpu/arm/c1_CodeStubs_arm.cpp: __ ldr(Rtemp, Address(_obj, java_lang_Class::klass_offset()));
./cpu/arm/methodHandles_arm.cpp: __ ldr(klass_reg, Address(klass_reg, java_lang_Class::klass_offset()));
./cpu/ppc/c1_CodeStubs_ppc.cpp: __ ld(_obj, java_lang_Class::klass_offset(), _obj);
./cpu/ppc/methodHandles_ppc.cpp: __ ld(klass_reg, java_lang_Class::klass_offset(), klass_reg);
./cpu/riscv/methodHandles_riscv.cpp: __ ld(klass_reg, Address(klass_reg, java_lang_Class::klass_offset()));
./cpu/s390/c1_CodeStubs_s390.cpp: __ z_lg(Z_R1_scratch, java_lang_Class::klass_offset(), _obj);
./cpu/s390/methodHandles_s390.cpp: __ z_lg(klass_reg, Address(klass_reg, java_lang_Class::klass_offset()));
./cpu/x86/c1_CodeStubs_x86.cpp: __ movptr(tmp2, Address(_obj, java_lang_Class::klass_offset()));
./cpu/x86/methodHandles_x86.cpp: __ movptr(klass_reg, Address(klass_reg, java_lang_Class::klass_offset()));
./share/c1/c1_LIRGenerator.cpp: __ move(new LIR_Address(rcvr.result(), java_lang_Class::klass_offset(), T_ADDRESS), temp, info);
./share/c1/c1_LIRGenerator.cpp: __ move(new LIR_Address(receiver.result(), java_lang_Class::klass_offset(), T_ADDRESS), recv_klass, info);
./share/cds/heapShared.cpp: ArchiveHeapWriter::mark_native_pointer(orig_obj, java_lang_Class::klass_offset());
./share/gc/shenandoah/shenandoahAsserts.cpp: Metadata* klass = obj->metadata_field(java_lang_Class::klass_offset());
./share/gc/shenandoah/shenandoahVerifier.cpp: Metadata* klass = obj->metadata_field(java_lang_Class::klass_offset());
./share/jvmci/jvmciCompilerToVM.cpp: if (offset == java_lang_Class::klass_offset()) {
./share/opto/compile.cpp: if (flat->offset() == java_lang_Class::klass_offset()
./share/opto/library_call.cpp: basic_plus_adr(cls, java_lang_Class::klass_offset()),
./share/opto/library_call.cpp: int class_klass_offset = java_lang_Class::klass_offset();
./share/opto/library_call.hpp: int offset = java_lang_Class::klass_offset();
./share/opto/memnode.cpp: && (offset == java_lang_Class::klass_offset() ||
./share/opto/memnode.cpp: && offset == java_lang_Class::klass_offset()) {
./share/opto/type.cpp: (_offset == java_lang_Class::klass_offset() ||
- relates to
-
JDK-8326708 [premain] Preassign values in archived java.lang.Class objects
- Open