8340733: Add scope for relaxing constraint on JavaCalls from CompilerThread

Reviewed-by: dnsimon, kvn
This commit is contained in:
Tomas Zezula 2024-11-01 13:36:26 +00:00
parent 7e87c071b0
commit 751a914b0a
6 changed files with 120 additions and 16 deletions

View File

@ -55,8 +55,11 @@ CompilerThread::~CompilerThread() {
}
void CompilerThread::set_compiler(AbstractCompiler* c) {
// Only jvmci compiler threads can call Java
_can_call_java = c != nullptr && c->is_jvmci();
/*
* Compiler threads need to make Java upcalls to the jargraal compiler.
* Java upcalls are also needed by the InterpreterRuntime when using jargraal.
*/
_can_call_java = c != nullptr && c->is_jvmci() JVMCI_ONLY(&& !UseJVMCINativeLibrary);
_compiler = c;
}

View File

@ -54,26 +54,29 @@ volatile intx JVMCI::_first_error_tid = -1;
volatile int JVMCI::_fatal_log_fd = -1;
const char* JVMCI::_fatal_log_filename = nullptr;
CompilerThreadCanCallJava::CompilerThreadCanCallJava(JavaThread* current, bool new_state) {
_current = nullptr;
CompilerThread* CompilerThreadCanCallJava::update(JavaThread* current, bool new_state) {
if (current->is_Compiler_thread()) {
CompilerThread* ct = CompilerThread::cast(current);
if (ct->_can_call_java != new_state &&
ct->_compiler != nullptr &&
ct->_compiler->is_jvmci())
{
// Only enter a new context if the ability of the
// Only update the state if the ability of the
// current thread to call Java actually changes
_reset_state = ct->_can_call_java;
ct->_can_call_java = new_state;
_current = ct;
return ct;
}
}
return nullptr;
}
CompilerThreadCanCallJava::CompilerThreadCanCallJava(JavaThread* current, bool new_state) {
_current = CompilerThreadCanCallJava::update(current, new_state);
}
CompilerThreadCanCallJava::~CompilerThreadCanCallJava() {
if (_current != nullptr) {
_current->_can_call_java = _reset_state;
_current->_can_call_java = !_current->_can_call_java;
}
}

View File

@ -60,14 +60,13 @@ typedef struct _jmetadata *jmetadata;
class CompilerThreadCanCallJava : StackObj {
private:
CompilerThread* _current; // Only non-null if state of thread changed
bool _reset_state; // Value prior to state change, undefined
// if no state change.
public:
// Enters a scope in which the ability of the current CompilerThread
// to call Java is specified by `new_state`. This call only makes a
// change if the current thread is a CompilerThread associated with
// a JVMCI compiler whose CompilerThread::_can_call_java is not
// currently `new_state`.
// If the current thread is a CompilerThread associated with
// a JVMCI compiler where CompilerThread::_can_call_java != new_state,
// then _can_call_java is set to `new_state`
// Returns nullptr if no change was made, otherwise the current CompilerThread
static CompilerThread* update(JavaThread* current, bool new_state);
CompilerThreadCanCallJava(JavaThread* current, bool new_state);
// Resets CompilerThread::_can_call_java of the current thread if the

View File

@ -184,7 +184,8 @@ Handle JavaArgumentUnboxer::next_arg(BasicType expectedType) {
JVMCI_VM_ENTRY_MARK; \
ResourceMark rm; \
bool __is_hotspot = env == thread->jni_environment(); \
CompilerThreadCanCallJava ccj(thread, __is_hotspot); \
bool __block_can_call_java = __is_hotspot || !thread->is_Compiler_thread() || CompilerThread::cast(thread)->can_call_java(); \
CompilerThreadCanCallJava ccj(thread, __block_can_call_java); \
JVMCIENV_FROM_JNI(JVMCI::compilation_tick(thread), env); \
// Entry to native method implementation that transitions
@ -401,6 +402,11 @@ C2V_VMENTRY_NULL(jobject, asResolvedJavaMethod, (JNIEnv* env, jobject, jobject e
return JVMCIENV->get_jobject(result);
}
C2V_VMENTRY_PREFIX(jboolean, updateCompilerThreadCanCallJava, (JNIEnv* env, jobject, jboolean newState))
return CompilerThreadCanCallJava::update(thread, newState) != nullptr;
C2V_END
C2V_VMENTRY_NULL(jobject, getResolvedJavaMethod, (JNIEnv* env, jobject, jobject base, jlong offset))
Method* method = nullptr;
JVMCIObject base_object = JVMCIENV->wrap(base);
@ -3386,6 +3392,7 @@ JNINativeMethod CompilerToVM::methods[] = {
{CC "notifyCompilerPhaseEvent", CC "(JIII)V", FN_PTR(notifyCompilerPhaseEvent)},
{CC "notifyCompilerInliningEvent", CC "(I" HS_METHOD2 HS_METHOD2 "ZLjava/lang/String;I)V", FN_PTR(notifyCompilerInliningEvent)},
{CC "getOopMapAt", CC "(" HS_METHOD2 "I[J)V", FN_PTR(getOopMapAt)},
{CC "updateCompilerThreadCanCallJava", CC "(Z)Z", FN_PTR(updateCompilerThreadCanCallJava)},
};
int CompilerToVM::methods_count() {

View File

@ -0,0 +1,84 @@
/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package jdk.vm.ci.hotspot;
/**
* Scope used to potentially change whether the current thread can make VM-to-Java calls.
* A scope is exited by the {@link #close()} method so it should be used in a
* try-with-resources statement.
*
* The scope does nothing if the current thread is not a HotSpot VM CompilerThread
* for a JVMCI compiler.
*/
public class CompilerThreadCanCallJavaScope implements AutoCloseable {
/**
* Thread state used during the scope.
*/
private final boolean state;
/**
* Non-null iff the thread state needs resetting in {@link #close()}.
*/
private final CompilerToVM vm;
/**
* The thread on which the constructor was called.
*/
private final Thread thread;
/**
* Opens a scope to allow/disallow the current thread to make VM-to-Java calls.
* The scope is a no-op if the current thread is not a HotSpot VM CompilerThread
* for a JVMCI compiler.
*
* @param newState true/false to allow/disallow VM-to-Java calls within the scope
*/
public CompilerThreadCanCallJavaScope(boolean newState) {
this.state = newState;
this.thread = Thread.currentThread();
CompilerToVM vm = HotSpotJVMCIRuntime.runtime().getCompilerToVM();
if (vm.updateCompilerThreadCanCallJava(newState)) {
this.vm = vm;
} else {
this.vm = null;
}
}
/**
* Resets the state of the current thread with respect to whether it can make
* VM-to-Java calls to what it was before the constructor was called.
*
* @throws IllegalStateException if called on a different thread than the constructor
*/
@Override
public void close() {
if (this.thread != Thread.currentThread()) {
throw new IllegalStateException();
}
if (vm != null) {
vm.updateCompilerThreadCanCallJava(!state);
}
}
}

View File

@ -1514,4 +1514,12 @@ final class CompilerToVM {
}
native void getOopMapAt(HotSpotResolvedJavaMethodImpl method, long methodPointer, int bci, long[] oopMap);
/**
* If the current thread is a CompilerThread associated with a JVMCI compiler where
* newState != CompilerThread::_can_call_java, then _can_call_java is set to newState.
*
* @returns false if no change was made, otherwise true
*/
native boolean updateCompilerThreadCanCallJava(boolean newState);
}