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

Commit

Permalink
[GR-24141] HotSpotNmethod.executeVarargs can try execute a zombie nme…
Browse files Browse the repository at this point in the history
…thod.

PullRequest: labsjdk-ce-11/97
  • Loading branch information
dougxc committed Jun 25, 2020
2 parents 3e88b1f + fbaba5d commit c39db3a
Show file tree
Hide file tree
Showing 4 changed files with 40 additions and 33 deletions.
4 changes: 2 additions & 2 deletions src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1027,7 +1027,7 @@ C2V_VMENTRY_NULL(jobject, executeHotSpotNmethod, (JNIEnv* env, jobject, jobject
JVMCIObject nmethod_mirror = JVMCIENV->wrap(hs_nmethod);
nmethodLocker locker;
nmethod* nm = JVMCIENV->get_nmethod(nmethod_mirror, locker);
if (nm == NULL) {
if (nm == NULL || !nm->is_in_use()) {
JVMCI_THROW_NULL(InvalidInstalledCodeException);
}
methodHandle mh = nm->method();
Expand All @@ -1036,7 +1036,7 @@ C2V_VMENTRY_NULL(jobject, executeHotSpotNmethod, (JNIEnv* env, jobject, jobject

JavaArgumentUnboxer jap(signature, &jca, (arrayOop) JNIHandles::resolve(args), mh->is_static());
JavaValue result(jap.get_ret_type());
jca.set_alternative_target(nm);
jca.set_alternative_target(Handle(THREAD, JNIHandles::resolve(nmethod_mirror.as_jobject())));
JavaCalls::call(&result, mh, &jca, CHECK_NULL);

if (jap.get_ret_type() == T_VOID) {
Expand Down
46 changes: 20 additions & 26 deletions src/hotspot/share/runtime/javaCalls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@
#include "compiler/compileBroker.hpp"
#include "interpreter/interpreter.hpp"
#include "interpreter/linkResolver.hpp"
#if INCLUDE_JVMCI
#include "jvmci/jvmciJavaClasses.hpp"
#endif
#include "memory/universe.hpp"
#include "oops/method.inline.hpp"
#include "oops/oop.inline.hpp"
Expand Down Expand Up @@ -348,27 +351,15 @@ void JavaCalls::call_helper(JavaValue* result, const methodHandle& method, JavaC

CHECK_UNHANDLED_OOPS_ONLY(thread->clear_unhandled_oops();)

#if INCLUDE_JVMCI
// Gets the nmethod (if any) that should be called instead of normal target
nmethod* alternative_target = args->alternative_target();
if (alternative_target == NULL) {
#endif
// Verify the arguments

if (CheckJNICalls) {
// Verify the arguments
if (JVMCI_ONLY(args->alternative_target().is_null() &&) (DEBUG_ONLY(true ||) CheckJNICalls)) {
args->verify(method, result->get_type());
}
else debug_only(args->verify(method, result->get_type()));
#if INCLUDE_JVMCI
}
#else

// Ignore call if method is empty
if (method->is_empty_method()) {
if (JVMCI_ONLY(args->alternative_target().is_null() &&) method->is_empty_method()) {
assert(result->get_type() == T_VOID, "an empty method must return a void value");
return;
}
#endif

#ifdef ASSERT
{ InstanceKlass* holder = method->method_holder();
Expand Down Expand Up @@ -420,21 +411,24 @@ void JavaCalls::call_helper(JavaValue* result, const methodHandle& method, JavaC
os::map_stack_shadow_pages(sp);
}

#if INCLUDE_JVMCI
if (alternative_target != NULL) {
if (alternative_target->is_alive()) {
thread->set_jvmci_alternate_call_target(alternative_target->verified_entry_point());
entry_point = method->adapter()->get_i2c_entry();
} else {
THROW(vmSymbols::jdk_vm_ci_code_InvalidInstalledCodeException());
}
}
#endif

// do call
{ JavaCallWrapper link(method, receiver, result, CHECK);
{ HandleMark hm(thread); // HandleMark used by HandleMarkCleaner

#if INCLUDE_JVMCI
// Gets the alternative target (if any) that should be called
Handle alternative_target = args->alternative_target();
if (!alternative_target.is_null()) {
// Must extract verified entry point from HotSpotNmethod after VM to Java
// transition in JavaCallWrapper constructor so that it is safe with
// respect to nmethod sweeping.
address verified_entry_point = (address) HotSpotJVMCI::InstalledCode::entryPoint(NULL, alternative_target());
if (verified_entry_point != NULL) {
thread->set_jvmci_alternate_call_target(verified_entry_point);
entry_point = method->adapter()->get_i2c_entry();
}
}
#endif
StubRoutines::call_stub()(
(address)&link,
// (intptr_t*)&(result->_value), // see NOTE above (compiler problem)
Expand Down
11 changes: 6 additions & 5 deletions src/hotspot/share/runtime/javaCalls.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,10 @@ class JavaCallArguments : public StackObj {
int _size;
int _max_size;
bool _start_at_zero; // Support late setting of receiver
JVMCI_ONLY(nmethod* _alternative_target;) // Nmethod that should be called instead of normal target
#if INCLUDE_JVMCI
Handle _alternative_target; // HotSpotNmethod wrapping an nmethod whose verified entry point
// should be called instead of the normal target
#endif

void initialize() {
// Starts at first element to support set_receiver.
Expand All @@ -98,7 +101,6 @@ class JavaCallArguments : public StackObj {
_max_size = _default_size;
_size = 0;
_start_at_zero = false;
JVMCI_ONLY(_alternative_target = NULL;)
}

// Helper for push_oop and the like. The value argument is a
Expand Down Expand Up @@ -138,18 +140,17 @@ class JavaCallArguments : public StackObj {
_max_size = max_size;
_size = 0;
_start_at_zero = false;
JVMCI_ONLY(_alternative_target = NULL;)
} else {
initialize();
}
}

#if INCLUDE_JVMCI
void set_alternative_target(nmethod* target) {
void set_alternative_target(Handle target) {
_alternative_target = target;
}

nmethod* alternative_target() {
Handle alternative_target() {
return _alternative_target;
}
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,18 @@ private boolean checkArgs(Object... args) {
return true;
}

/**
* {@inheritDoc}
*
* It's possible for the HotSpot runtime to sweep nmethods at any point in time. As a result,
* there is no guarantee that calling this method will execute the wrapped nmethod. Instead, it
* may end up executing the bytecode of the associated {@link #getMethod() Java method}. Only if
* {@link #isValid()} is {@code true} after returning can the caller be sure that the nmethod
* was executed. If {@link #isValid()} is {@code false}, then the only way to determine if the
* nmethod was executed is to test for some side-effect specific to the nmethod (e.g., update to
* a field) that is not performed by the bytecode of the associated {@link #getMethod() Java
* method}.
*/
@Override
public Object executeVarargs(Object... args) throws InvalidInstalledCodeException {
if (IS_IN_NATIVE_IMAGE) {
Expand Down

0 comments on commit c39db3a

Please sign in to comment.