8223794: applications/kitchensink/Kitchensink.java crash bad oop with Graal

Added new nmethod::oop_at_phantom() method for JVMCI to notify GC that oop should be kept alive

Reviewed-by: dlong, eosterlund
This commit is contained in:
Vladimir Kozlov 2019-06-20 10:32:25 -07:00
parent 4934681f19
commit 2ccecc495c
5 changed files with 20 additions and 8 deletions

View file

@ -1473,6 +1473,13 @@ oop nmethod::oop_at(int index) const {
return NativeAccess<AS_NO_KEEPALIVE>::oop_load(oop_addr_at(index)); return NativeAccess<AS_NO_KEEPALIVE>::oop_load(oop_addr_at(index));
} }
oop nmethod::oop_at_phantom(int index) const {
if (index == 0) {
return NULL;
}
return NativeAccess<ON_PHANTOM_OOP_REF>::oop_load(oop_addr_at(index));
}
// //
// Notify all classes this nmethod is dependent on that it is no // Notify all classes this nmethod is dependent on that it is no
// longer dependent. This should only be called in two situations. // longer dependent. This should only be called in two situations.

View file

@ -392,6 +392,7 @@ class nmethod : public CompiledMethod {
// Support for oops in scopes and relocs: // Support for oops in scopes and relocs:
// Note: index 0 is reserved for null. // Note: index 0 is reserved for null.
oop oop_at(int index) const; oop oop_at(int index) const;
oop oop_at_phantom(int index) const; // phantom reference
oop* oop_addr_at(int index) const { // for GC oop* oop_addr_at(int index) const { // for GC
// relocation indexes are biased by 1 (because 0 is reserved) // relocation indexes are biased by 1 (because 0 is reserved)
assert(index > 0 && index <= oops_count(), "must be a valid non-zero index"); assert(index > 0 && index <= oops_count(), "must be a valid non-zero index");

View file

@ -2416,7 +2416,7 @@ C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle))
if (peerEnv->is_hotspot()) { if (peerEnv->is_hotspot()) {
// Only the mirror in the HotSpot heap is accessible // Only the mirror in the HotSpot heap is accessible
// through JVMCINMethodData // through JVMCINMethodData
oop nmethod_mirror = data->get_nmethod_mirror(nm); oop nmethod_mirror = data->get_nmethod_mirror(nm, /* phantom_ref */ true);
if (nmethod_mirror != NULL) { if (nmethod_mirror != NULL) {
result = HotSpotJVMCI::wrap(nmethod_mirror); result = HotSpotJVMCI::wrap(nmethod_mirror);
} }
@ -2443,7 +2443,7 @@ C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle))
if (data == NULL) { if (data == NULL) {
JVMCI_THROW_MSG_0(IllegalArgumentException, "Cannot set HotSpotNmethod mirror for default nmethod"); JVMCI_THROW_MSG_0(IllegalArgumentException, "Cannot set HotSpotNmethod mirror for default nmethod");
} }
if (data->get_nmethod_mirror(nm) != NULL) { if (data->get_nmethod_mirror(nm, /* phantom_ref */ false) != NULL) {
JVMCI_THROW_MSG_0(IllegalArgumentException, "Cannot overwrite existing HotSpotNmethod mirror for nmethod"); JVMCI_THROW_MSG_0(IllegalArgumentException, "Cannot overwrite existing HotSpotNmethod mirror for nmethod");
} }
oop nmethod_mirror = HotSpotJVMCI::resolve(result); oop nmethod_mirror = HotSpotJVMCI::resolve(result);

View file

@ -700,11 +700,15 @@ void JVMCINMethodData::add_failed_speculation(nmethod* nm, jlong speculation) {
FailedSpeculation::add_failed_speculation(nm, _failed_speculations, data, length); FailedSpeculation::add_failed_speculation(nm, _failed_speculations, data, length);
} }
oop JVMCINMethodData::get_nmethod_mirror(nmethod* nm) { oop JVMCINMethodData::get_nmethod_mirror(nmethod* nm, bool phantom_ref) {
if (_nmethod_mirror_index == -1) { if (_nmethod_mirror_index == -1) {
return NULL; return NULL;
} }
if (phantom_ref) {
return nm->oop_at_phantom(_nmethod_mirror_index);
} else {
return nm->oop_at(_nmethod_mirror_index); return nm->oop_at(_nmethod_mirror_index);
}
} }
void JVMCINMethodData::set_nmethod_mirror(nmethod* nm, oop new_mirror) { void JVMCINMethodData::set_nmethod_mirror(nmethod* nm, oop new_mirror) {
@ -728,7 +732,7 @@ void JVMCINMethodData::clear_nmethod_mirror(nmethod* nm) {
} }
void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) { void JVMCINMethodData::invalidate_nmethod_mirror(nmethod* nm) {
oop nmethod_mirror = get_nmethod_mirror(nm); oop nmethod_mirror = get_nmethod_mirror(nm, /* phantom_ref */ true);
if (nmethod_mirror == NULL) { if (nmethod_mirror == NULL) {
return; return;
} }
@ -1530,7 +1534,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV,
JVMCINMethodData* data = nm->jvmci_nmethod_data(); JVMCINMethodData* data = nm->jvmci_nmethod_data();
assert(data != NULL, "must be"); assert(data != NULL, "must be");
if (install_default) { if (install_default) {
assert(!nmethod_mirror.is_hotspot() || data->get_nmethod_mirror(nm) == NULL, "must be"); assert(!nmethod_mirror.is_hotspot() || data->get_nmethod_mirror(nm, /* phantom_ref */ false) == NULL, "must be");
if (entry_bci == InvocationEntryBci) { if (entry_bci == InvocationEntryBci) {
if (TieredCompilation) { if (TieredCompilation) {
// If there is an old version we're done with it // If there is an old version we're done with it
@ -1565,7 +1569,7 @@ JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV,
InstanceKlass::cast(method->method_holder())->add_osr_nmethod(nm); InstanceKlass::cast(method->method_holder())->add_osr_nmethod(nm);
} }
} else { } else {
assert(!nmethod_mirror.is_hotspot() || data->get_nmethod_mirror(nm) == HotSpotJVMCI::resolve(nmethod_mirror), "must be"); assert(!nmethod_mirror.is_hotspot() || data->get_nmethod_mirror(nm, /* phantom_ref */ false) == HotSpotJVMCI::resolve(nmethod_mirror), "must be");
} }
nm->make_in_use(); nm->make_in_use();
} }

View file

@ -74,7 +74,7 @@ public:
void invalidate_nmethod_mirror(nmethod* nm); void invalidate_nmethod_mirror(nmethod* nm);
// Gets the mirror from nm's oops table. // Gets the mirror from nm's oops table.
oop get_nmethod_mirror(nmethod* nm); oop get_nmethod_mirror(nmethod* nm, bool phantom_ref);
// Sets the mirror in nm's oops table. // Sets the mirror in nm's oops table.
void set_nmethod_mirror(nmethod* nm, oop mirror); void set_nmethod_mirror(nmethod* nm, oop mirror);