Skip to content
This repository has been archived by the owner on May 29, 2024. It is now read-only.

Commit

Permalink
[GR-44799] ZGC and nmethod entry barrier fixes
Browse files Browse the repository at this point in the history
PullRequest: labsjdk-ce-17/107
  • Loading branch information
tkrodriguez committed Mar 23, 2023
2 parents 90f5597 + e0434fb commit 51a5808
Show file tree
Hide file tree
Showing 14 changed files with 138 additions and 82 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,13 @@ class NativeNMethodBarrier {
address barrier_address;
#if INCLUDE_JVMCI
if (nm->is_compiled_by_jvmci()) {
_instruction_address = nm->code_begin() + nm->frame_complete_offset();
_guard_addr = reinterpret_cast<int*>(nm->consts_begin() + nm->jvmci_nmethod_data()->nmethod_entry_patch_offset());
address pc = nm->code_begin() + nm->jvmci_nmethod_data()->nmethod_entry_patch_offset();
RelocIterator iter(nm, pc, pc + 4);
guarantee(iter.next(), "missing relocs");
guarantee(iter.type() == relocInfo::section_word_type, "unexpected reloc");

_guard_addr = (int*) iter.section_word_reloc()->target();
_instruction_address = pc;
} else
#endif
{
Expand Down
4 changes: 0 additions & 4 deletions src/hotspot/cpu/aarch64/jvmciCodeInstaller_aarch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,10 +90,6 @@ void CodeInstaller::pd_patch_DataSectionReference(int pc_offset, int data_offset
if (inst->is_adr_aligned() || inst->is_ldr_literal()
|| (NativeInstruction::maybe_cpool_ref(pc))) {
address dest = _constants->start() + data_offset;
if (_nmethod_entry_patch_offset == pc_offset) {
// Remember the offset into constants
_nmethod_entry_patch_offset = data_offset;
}
_instructions->relocate(pc, section_word_Relocation::spec((address) dest, CodeBuffer::SECT_CONSTS));
JVMCI_event_3("relocating at " PTR_FORMAT " (+%d) with destination at %d", p2i(pc), pc_offset, data_offset);
} else {
Expand Down
108 changes: 73 additions & 35 deletions src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "oops/instanceMirrorKlass.hpp"
#include "oops/instanceKlass.inline.hpp"
#include "oops/method.inline.hpp"
#include "oops/objArrayKlass.inline.hpp"
#include "oops/typeArrayOop.inline.hpp"
#include "prims/jvmtiExport.hpp"
#include "prims/methodHandles.hpp"
Expand Down Expand Up @@ -403,56 +404,93 @@ C2V_VMENTRY_NULL(jobject, getConstantPool, (JNIEnv* env, jobject, ARGUMENT_PAIR(
}

C2V_VMENTRY_NULL(jobject, getResolvedJavaType0, (JNIEnv* env, jobject, jobject base, jlong offset, jboolean compressed))
JVMCIKlassHandle klass(THREAD);
JVMCIObject base_object = JVMCIENV->wrap(base);
jlong base_address = 0;
if (base_object.is_non_null() && offset == oopDesc::klass_offset_in_bytes()) {
if (base_object.is_null()) {
JVMCI_THROW_MSG_NULL(NullPointerException, "base object is null");
}

const char* base_desc = nullptr;
JVMCIKlassHandle klass(THREAD);
if (offset == oopDesc::klass_offset_in_bytes()) {
if (JVMCIENV->isa_HotSpotObjectConstantImpl(base_object)) {
Handle base_oop = JVMCIENV->asConstant(base_object, JVMCI_CHECK_NULL);
klass = base_oop->klass();
} else {
assert(false, "What types are we actually expecting here?");
goto unexpected;
}
} else if (!compressed) {
if (base_object.is_non_null()) {
if (JVMCIENV->isa_HotSpotResolvedJavaMethodImpl(base_object)) {
base_address = (intptr_t) JVMCIENV->asMethod(base_object);
} else if (JVMCIENV->isa_HotSpotConstantPool(base_object)) {
base_address = (intptr_t) JVMCIENV->asConstantPool(base_object);
} else if (JVMCIENV->isa_HotSpotResolvedObjectTypeImpl(base_object)) {
base_address = (intptr_t) JVMCIENV->asKlass(base_object);
} else if (JVMCIENV->isa_HotSpotObjectConstantImpl(base_object)) {
Handle base_oop = JVMCIENV->asConstant(base_object, JVMCI_CHECK_NULL);
if (base_oop->is_a(vmClasses::Class_klass())) {
base_address = cast_from_oop<jlong>(base_oop());
if (JVMCIENV->isa_HotSpotConstantPool(base_object)) {
ConstantPool* cp = JVMCIENV->asConstantPool(base_object);
if (offset == ConstantPool::pool_holder_offset_in_bytes()) {
klass = cp->pool_holder();
} else {
base_desc = FormatBufferResource("[constant pool for %s]", cp->pool_holder()->signature_name());
goto unexpected;
}
} else if (JVMCIENV->isa_HotSpotResolvedObjectTypeImpl(base_object)) {
Klass* base_klass = JVMCIENV->asKlass(base_object);
if (offset == in_bytes(Klass::subklass_offset())) {
klass = base_klass->subklass();
} else if (offset == in_bytes(Klass::super_offset())) {
klass = base_klass->super();
} else if (offset == in_bytes(Klass::next_sibling_offset())) {
klass = base_klass->next_sibling();
} else if (offset == in_bytes(ObjArrayKlass::element_klass_offset()) && base_klass->is_objArray_klass()) {
klass = ObjArrayKlass::cast(base_klass)->element_klass();
} else if (offset >= in_bytes(Klass::primary_supers_offset()) &&
offset < in_bytes(Klass::primary_supers_offset()) + (int) (sizeof(Klass*) * Klass::primary_super_limit()) &&
offset % sizeof(Klass*) == 0) {
// Offset is within the primary supers array
int index = (int) ((offset - in_bytes(Klass::primary_supers_offset())) / sizeof(Klass*));
klass = base_klass->primary_super_of_depth(index);
} else {
base_desc = FormatBufferResource("[%s]", base_klass->signature_name());
goto unexpected;
}
} else if (JVMCIENV->isa_HotSpotObjectConstantImpl(base_object)) {
Handle base_oop = JVMCIENV->asConstant(base_object, JVMCI_CHECK_NULL);
if (base_oop->is_a(vmClasses::Class_klass())) {
if (offset == java_lang_Class::klass_offset()) {
klass = java_lang_Class::as_Klass(base_oop());
} else if (offset == java_lang_Class::array_klass_offset()) {
klass = java_lang_Class::array_klass_acquire(base_oop());
} else {
base_desc = FormatBufferResource("[Class=%s]", java_lang_Class::as_Klass(base_oop())->signature_name());
goto unexpected;
}
} else {
if (!base_oop.is_null()) {
base_desc = FormatBufferResource("[%s]", base_oop()->klass()->signature_name());
}
goto unexpected;
}
if (base_address == 0) {
JVMCI_THROW_MSG_NULL(IllegalArgumentException,
err_msg("Unexpected arguments: %s " JLONG_FORMAT " %s", JVMCIENV->klass_name(base_object), offset, compressed ? "true" : "false"));
} else if (JVMCIENV->isa_HotSpotMethodData(base_object)) {
jlong base_address = (intptr_t) JVMCIENV->asMethodData(base_object);
klass = *((Klass**) (intptr_t) (base_address + offset));
if (klass == nullptr || !klass->is_loader_alive()) {
// Klasses in methodData might be concurrently unloading so return null in that case.
return nullptr;
}
} else {
goto unexpected;
}
klass = *((Klass**) (intptr_t) (base_address + offset));
} else {
goto unexpected;
}

{
if (klass == nullptr) {
return nullptr;
}
if (base_object.is_non_null()) {
// Reads from real objects are expected to be strongly reachable
guarantee(klass->is_loader_alive(), "klass must be alive");
} else if (!klass->is_loader_alive()) {
// Reads from other memory like the HotSpotMethodData might be concurrently unloading so
// return null in that case.
return nullptr;
}
} else {
JVMCI_THROW_MSG_NULL(IllegalArgumentException,
err_msg("Unexpected arguments: %s " JLONG_FORMAT " %s",
base_object.is_non_null() ? JVMCIENV->klass_name(base_object) : "null",
offset, compressed ? "true" : "false"));
JVMCIObject result = JVMCIENV->get_jvmci_type(klass, JVMCI_CHECK_NULL);
return JVMCIENV->get_jobject(result);
}
assert (klass == NULL || klass->is_klass(), "invalid read");
JVMCIObject result = JVMCIENV->get_jvmci_type(klass, JVMCI_CHECK_NULL);
return JVMCIENV->get_jobject(result);

unexpected:
JVMCI_THROW_MSG_NULL(IllegalArgumentException,
err_msg("Unexpected arguments: %s%s " JLONG_FORMAT " %s",
JVMCIENV->klass_name(base_object), base_desc == nullptr ? "" : base_desc,
offset, compressed ? "true" : "false"));
}

C2V_VMENTRY_NULL(jobject, findUniqueConcreteMethod, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), ARGUMENT_PAIR(method)))
Expand Down
13 changes: 11 additions & 2 deletions src/hotspot/share/jvmci/jvmciEnv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1169,16 +1169,19 @@ JVMCIObject JVMCIEnv::get_jvmci_method(const methodHandle& method, JVMCI_TRAPS)
if (method() == NULL) {
return method_object;
}
JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
JVMCIKlassHandle holder_klass(THREAD, method->method_holder());
JVMCIObject holder = get_jvmci_type(holder_klass, JVMCI_CHECK_(JVMCIObject()));

CompilerOracle::tag_blackhole_if_possible(method);

JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
jmetadata handle = _runtime->allocate_handle(method);
jboolean exception = false;
if (is_hotspot()) {
JavaValue result(T_OBJECT);
JavaCallArguments args;
args.push_long((jlong) handle);
args.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(holder)));
JavaCalls::call_static(&result, HotSpotJVMCI::HotSpotResolvedJavaMethodImpl::klass(),
vmSymbols::fromMetaspace_name(),
vmSymbols::method_fromMetaspace_signature(), &args, THREAD);
Expand All @@ -1191,7 +1194,7 @@ JVMCIObject JVMCIEnv::get_jvmci_method(const methodHandle& method, JVMCI_TRAPS)
JNIAccessMark jni(this, THREAD);
method_object = JNIJVMCI::wrap(jni()->CallStaticObjectMethod(JNIJVMCI::HotSpotResolvedJavaMethodImpl::clazz(),
JNIJVMCI::HotSpotResolvedJavaMethodImpl_fromMetaspace_method(),
(jlong) handle));
(jlong) handle, holder.as_jobject()));
exception = jni()->ExceptionCheck();
}

Expand All @@ -1214,6 +1217,9 @@ JVMCIObject JVMCIEnv::get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS)
return type;
}

guarantee(klass->is_klass(), "must be valid klass");
guarantee(klass->is_loader_alive(), "klass must be alive");

jlong pointer = (jlong) klass();
JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
jboolean exception = false;
Expand Down Expand Up @@ -1571,6 +1577,9 @@ void JVMCIEnv::initialize_installed_code(JVMCIObject installed_code, CodeBlob* c
set_HotSpotInstalledCode_codeSize(installed_code, cb->code_size());
}

MethodData* JVMCIEnv::asMethodData(JVMCIObject obj) {
return (MethodData*) get_HotSpotMethodData_methodDataPointer(obj);
}

void JVMCIEnv::invalidate_nmethod_mirror(JVMCIObject mirror, bool deoptimize, JVMCI_TRAPS) {
if (mirror.is_null()) {
Expand Down
4 changes: 4 additions & 0 deletions src/hotspot/share/jvmci/jvmciEnv.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@

#include "classfile/javaClasses.hpp"
#include "jvmci/jvmciJavaClasses.hpp"
#include "oops/klass.inline.hpp"
#include "runtime/jniHandles.hpp"
#include "runtime/thread.hpp"

Expand Down Expand Up @@ -376,6 +377,9 @@ class JVMCIEnv : public ResourceObj {
// Unpack an instance of HotSpotResolvedObjectTypeImpl into the original Klass*
Klass* asKlass(JVMCIObject jvmci_type);

// Unpack an instance of HotSpotMethodData into the original MethodData*
MethodData* asMethodData(JVMCIObject jvmci_method_data);

JVMCIObject get_jvmci_method(const methodHandle& method, JVMCI_TRAPS);

JVMCIObject get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS);
Expand Down
3 changes: 3 additions & 0 deletions src/hotspot/share/jvmci/jvmciJavaClasses.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@
start_class(HotSpotResolvedJavaMethodImpl, jdk_vm_ci_hotspot_HotSpotResolvedJavaMethodImpl) \
long_field(HotSpotResolvedJavaMethodImpl, methodHandle) \
end_class \
start_class(HotSpotMethodData, jdk_vm_ci_hotspot_HotSpotMethodData) \
long_field(HotSpotMethodData, methodDataPointer) \
end_class \
start_class(InstalledCode, jdk_vm_ci_code_InstalledCode) \
long_field(InstalledCode, address) \
long_field(InstalledCode, entryPoint) \
Expand Down
3 changes: 2 additions & 1 deletion src/hotspot/share/jvmci/vmSymbols_jvmci.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
template(jdk_vm_ci_hotspot_HotSpotResolvedJavaFieldImpl, "jdk/vm/ci/hotspot/HotSpotResolvedJavaFieldImpl") \
template(jdk_vm_ci_hotspot_HotSpotCompressedNullConstant, "jdk/vm/ci/hotspot/HotSpotCompressedNullConstant") \
template(jdk_vm_ci_hotspot_HotSpotObjectConstantImpl, "jdk/vm/ci/hotspot/HotSpotObjectConstantImpl") \
template(jdk_vm_ci_hotspot_HotSpotMethodData, "jdk/vm/ci/hotspot/HotSpotMethodData") \
template(jdk_vm_ci_hotspot_DirectHotSpotObjectConstantImpl, "jdk/vm/ci/hotspot/DirectHotSpotObjectConstantImpl") \
template(jdk_vm_ci_hotspot_IndirectHotSpotObjectConstantImpl, "jdk/vm/ci/hotspot/IndirectHotSpotObjectConstantImpl") \
template(jdk_vm_ci_hotspot_HotSpotStackFrameReference, "jdk/vm/ci/hotspot/HotSpotStackFrameReference") \
Expand Down Expand Up @@ -80,7 +81,7 @@
template(compileMethod_signature, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;IJI)Ljdk/vm/ci/hotspot/HotSpotCompilationRequestResult;") \
template(isGCSupported_name, "isGCSupported") \
template(fromMetaspace_name, "fromMetaspace") \
template(method_fromMetaspace_signature, "(J)Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;") \
template(method_fromMetaspace_signature, "(JLjdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;)Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;") \
template(constantPool_fromMetaspace_signature, "(J)Ljdk/vm/ci/hotspot/HotSpotConstantPool;") \
template(klass_fromMetaspace_signature, "(J)Ljdk/vm/ci/hotspot/HotSpotResolvedObjectTypeImpl;") \
template(primitive_fromMetaspace_signature, "(Ljdk/vm/ci/hotspot/HotSpotObjectConstantImpl;C)Ljdk/vm/ci/hotspot/HotSpotResolvedPrimitiveType;") \
Expand Down
4 changes: 4 additions & 0 deletions src/hotspot/share/oops/klass.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -367,6 +367,10 @@ class Klass : public Metadata {
static ByteSize modifier_flags_offset() { return in_ByteSize(offset_of(Klass, _modifier_flags)); }
static ByteSize layout_helper_offset() { return in_ByteSize(offset_of(Klass, _layout_helper)); }
static ByteSize access_flags_offset() { return in_ByteSize(offset_of(Klass, _access_flags)); }
#if INCLUDE_JVMCI
static ByteSize subklass_offset() { return in_ByteSize(offset_of(Klass, _subklass)); }
static ByteSize next_sibling_offset() { return in_ByteSize(offset_of(Klass, _next_sibling)); }
#endif

// Unpacking layout_helper:
static const int _lh_neutral_value = 0; // neutral non-array non-instance value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -868,23 +868,33 @@ HotSpotConstantPool getConstantPool(MetaspaceObject object) {

/**
* Read a {@code Klass*} value from the memory location described by {@code base} plus
* {@code displacement} and return the {@link HotSpotResolvedObjectTypeImpl} wrapping it. This
* method does no checking that the memory location actually contains a valid pointer and may
* crash the VM if an invalid location is provided. If the {@code base} is null then
* {@code displacement} is used by itself. If {@code base} is a
* {@link HotSpotResolvedJavaMethodImpl}, {@link HotSpotConstantPool} or
* {@link HotSpotResolvedObjectTypeImpl} then the metaspace pointer is fetched from that object
* and added to {@code displacement}. Any other non-null object type causes an
* {@link IllegalArgumentException} to be thrown.
* {@code displacement} and return the {@link HotSpotResolvedObjectTypeImpl} wrapping it. This method
* only performs the read if the memory location is known to contain a valid Klass*. If
* {@code base} is a {@link HotSpotConstantPool}, {@link HotSpotMethodData}, {@link HotSpotObjectConstantImpl},
* or {@link HotSpotResolvedObjectTypeImpl} then the field
* corresopnding to {@code displacement} is fetched using the appropriate HotSpot accessor. Any
* other object type or an unexpected displacement causes an {@link IllegalArgumentException} to
* be thrown. The set of fields which can be read in this fashion corresponds to the {@link VMField}
* with type {@code Klass*} that are described in the {@link HotSpotVMConfigStore#getFields()}.
* Additionally several injected fields in {@link Class} are also handled.
*
* @param base an object to read from or null
* @param base an object to read from
* @param displacement
* @param compressed true if the location contains a compressed Klass*
* @return null or the resolved method for this location
* @throws NullPointerException if {@code base == null}
*/
private native HotSpotResolvedObjectTypeImpl getResolvedJavaType0(Object base, long displacement, boolean compressed);

HotSpotResolvedObjectTypeImpl getResolvedJavaType(MetaspaceObject base, long displacement, boolean compressed) {
HotSpotResolvedObjectTypeImpl getResolvedJavaType(HotSpotConstantPool base, long displacement) {
return getResolvedJavaType0(base, displacement, false);
}

HotSpotResolvedObjectTypeImpl getResolvedJavaType(HotSpotMethodData base, long displacement) {
return getResolvedJavaType0(base, displacement, false);
}

HotSpotResolvedObjectTypeImpl getResolvedJavaType(HotSpotResolvedObjectTypeImpl base, long displacement, boolean compressed) {
return getResolvedJavaType0(base, displacement, compressed);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -238,7 +238,7 @@ private HotSpotConstantPool(long constantPoolHandle) {
*/
private HotSpotResolvedObjectType getHolder() {
if (holder == null) {
holder = compilerToVM().getResolvedJavaType(this, config().constantPoolHolderOffset, false);
holder = compilerToVM().getResolvedJavaType(this, config().constantPoolHolderOffset);
}
return holder;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
/**
* Access to a HotSpot {@code MethodData} structure (defined in methodData.hpp).
*/
final class HotSpotMethodData {
final class HotSpotMethodData implements MetaspaceObject {

/**
* VM state that can be reset when building an AOT image.
Expand Down Expand Up @@ -174,6 +174,11 @@ static VMState instance() {
this.state = VMState.instance();
}

@Override
public long getMetaspacePointer() {
return methodDataPointer;
}

/**
* @return value of the MethodData::_data_size field
*/
Expand Down Expand Up @@ -308,7 +313,7 @@ private HotSpotResolvedJavaMethod readMethod(int position, int offsetInBytes) {

private HotSpotResolvedObjectTypeImpl readKlass(int position, int offsetInBytes) {
long fullOffsetInBytes = state.computeFullOffset(position, offsetInBytes);
return compilerToVM().getResolvedJavaType(methodDataPointer + fullOffsetInBytes);
return compilerToVM().getResolvedJavaType(this, fullOffsetInBytes);
}

/**
Expand Down
Loading

0 comments on commit 51a5808

Please sign in to comment.