Skip to content

Commit

Permalink
Using tristate CompilerThread::_can_call_java.
Browse files Browse the repository at this point in the history
  • Loading branch information
Tomas Zezula committed Sep 27, 2024
1 parent 882cec4 commit 021fdc2
Show file tree
Hide file tree
Showing 8 changed files with 68 additions and 36 deletions.
4 changes: 3 additions & 1 deletion src/hotspot/share/compiler/compilerThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,9 @@ CompilerThread::~CompilerThread() {

void CompilerThread::set_compiler(AbstractCompiler* c) {
// Only jvmci compiler threads can call Java
_can_call_java = c != nullptr && c->is_jvmci();
if (c != nullptr && c->is_jvmci()) {
_can_call_java = TriBool{};
}
_compiler = c;
}

Expand Down
5 changes: 3 additions & 2 deletions src/hotspot/share/compiler/compilerThread.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#ifndef SHARE_COMPILER_COMPILERTHREAD_HPP
#define SHARE_COMPILER_COMPILERTHREAD_HPP

#include <utilities/tribool.hpp>
#include "runtime/javaThread.hpp"

class AbstractCompiler;
Expand All @@ -50,7 +51,7 @@ class CompilerThread : public JavaThread {
CompileTask* volatile _task; // print_threads_compiling can read this concurrently.
CompileQueue* _queue;
BufferBlob* _buffer_blob;
bool _can_call_java;
TriBool _can_call_java;

AbstractCompiler* _compiler;
TimeStamp _idle_time;
Expand All @@ -73,7 +74,7 @@ class CompilerThread : public JavaThread {

bool is_Compiler_thread() const { return true; }

virtual bool can_call_java() const { return _can_call_java; }
virtual bool can_call_java() const { return _can_call_java.is_default() || _can_call_java; }

// Returns true if this CompilerThread is hidden from JVMTI and FlightRecorder. C1 and C2 are
// always hidden but JVMCI compiler threads might be hidden.
Expand Down
18 changes: 11 additions & 7 deletions src/hotspot/share/jvmci/jvmci.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,29 +54,33 @@ volatile intx JVMCI::_fatal_log_init_thread = -1;
volatile int JVMCI::_fatal_log_fd = -1;
const char* JVMCI::_fatal_log_filename = nullptr;

CompilerThread* CompilerThreadCanCallJava::update(JavaThread* current, bool new_state) {
Pair<CompilerThread*,TriBool> CompilerThreadCanCallJava::update(JavaThread* current, const TriBool new_state, bool force) {
if (current->is_Compiler_thread()) {
CompilerThread* ct = CompilerThread::cast(current);
if (ct->_can_call_java != new_state &&
(force || ct->_can_call_java.is_default()) &&
ct->_compiler != nullptr &&
ct->_compiler->is_jvmci())
{
// Only update the state if the ability of the
// current thread to call Java actually changes
TriBool prev_state{ct->_can_call_java};
ct->_can_call_java = new_state;
return ct;
return {ct, prev_state};
}
}
return nullptr;
return {nullptr, {}};
}

CompilerThreadCanCallJava::CompilerThreadCanCallJava(JavaThread* current, bool new_state) {
_current = CompilerThreadCanCallJava::update(current, new_state);
CompilerThreadCanCallJava::CompilerThreadCanCallJava(JavaThread* current, bool new_state, bool force) {
Pair<CompilerThread*,TriBool> p = CompilerThreadCanCallJava::update(current, new_state, force);
_current = p.first;
_prev_can_call_java = p.second;
}

CompilerThreadCanCallJava::~CompilerThreadCanCallJava() {
if (_current != nullptr) {
_current->_can_call_java = !_current->_can_call_java;
_current->_can_call_java = _prev_can_call_java;
}
}

Expand Down Expand Up @@ -205,7 +209,7 @@ void JVMCI::ensure_box_caches_initialized(TRAPS) {

// Class resolution and initialization below
// requires calling into Java
CompilerThreadCanCallJava ccj(THREAD, true);
CompilerThreadCanCallJava ccj(THREAD, true, true);

for (unsigned i = 0; i < sizeof(box_classes) / sizeof(Symbol*); i++) {
Klass* k = SystemDictionary::resolve_or_fail(box_classes[i], true, CHECK);
Expand Down
26 changes: 19 additions & 7 deletions src/hotspot/share/jvmci/jvmci.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#ifndef SHARE_JVMCI_JVMCI_HPP
#define SHARE_JVMCI_JVMCI_HPP

#include <utilities/pair.hpp>
#include <utilities/tribool.hpp>
#include "compiler/compiler_globals.hpp"
#include "compiler/compilerDefinitions.hpp"
#include "utilities/exceptions.hpp"
Expand Down Expand Up @@ -60,14 +62,24 @@ typedef struct _jmetadata *jmetadata;
class CompilerThreadCanCallJava : StackObj {
private:
CompilerThread* _current; // Only non-null if state of thread changed
TriBool _prev_can_call_java;
public:
// 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);
// Updates the `_can_call_java` state for the current thread if it's a `CompilerThread`
// associated with a JVMCI compiler.
//
// Conditions for updating:
// - The current thread must be a `CompilerThread`.
// - The thread's `_can_call_java` field must not already match `new_state`.
// - Either the `force` flag must be `true`, or `_can_call_java` must be a default `TriBool` value.
// - The thread must be associated with a valid JVMCI compiler (`_compiler != nullptr` and `_compiler->is_jvmci()`).
//
// If the update is performed, `_can_call_java` is set to `new_state`, and the method returns a
// `Pair` containing the current `CompilerThread` and its previous `_can_call_java` value.
//
// If no update is performed, the method returns a `Pair` with `nullptr` and a default `TriBool` value.
static Pair<CompilerThread*,TriBool> update(JavaThread* current, TriBool new_state, bool force);

CompilerThreadCanCallJava(JavaThread* current, bool new_state, bool force=false);

// Resets CompilerThread::_can_call_java of the current thread if the
// constructor changed it.
Expand Down
30 changes: 20 additions & 10 deletions src/hotspot/share/jvmci/jvmciCompilerToVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -401,8 +401,18 @@ C2V_VMENTRY_NULL(jobject, asResolvedJavaMethod, (JNIEnv* env, jobject, jobject e
return JVMCIENV->get_jobject(result);
}

C2V_VMENTRY_0(jboolean, updateCompilerThreadCanCallJava, (JNIEnv* env, jobject, jboolean newState))
return CompilerThreadCanCallJava::update(THREAD, newState) != nullptr;
C2V_VMENTRY_PREFIX(jint, updateCompilerThreadCanCallJava, (JNIEnv* env, jobject, jint newState))
TriBool new_state{};
if (newState != -1) {
new_state = static_cast<bool>(newState);
}
Pair<CompilerThread*,TriBool> p = CompilerThreadCanCallJava::update(thread, new_state, true);
TriBool result = p.first == nullptr ? new_state : p.second;
if (result.is_default()) {
return -1;
} else {
return static_cast<bool>(p.second);
}
C2V_END


Expand Down Expand Up @@ -588,7 +598,7 @@ C2V_VMENTRY_0(jboolean, shouldInlineMethod,(JNIEnv* env, jobject, ARGUMENT_PAIR(
C2V_END

C2V_VMENTRY_NULL(jobject, lookupType, (JNIEnv* env, jobject, jstring jname, ARGUMENT_PAIR(accessing_klass), jint accessing_klass_loader, jboolean resolve))
CompilerThreadCanCallJava canCallJava(thread, resolve); // Resolution requires Java calls
CompilerThreadCanCallJava canCallJava(thread, resolve, true); // Resolution requires Java calls
JVMCIObject name = JVMCIENV->wrap(jname);
const char* str = JVMCIENV->as_utf8_string(name);
TempNewSymbol class_name = SymbolTable::new_symbol(str);
Expand Down Expand Up @@ -2036,7 +2046,7 @@ C2V_VMENTRY(void, ensureInitialized, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass)
C2V_END

C2V_VMENTRY(void, ensureLinked, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass)))
CompilerThreadCanCallJava canCallJava(thread, true); // Linking requires Java calls
CompilerThreadCanCallJava canCallJava(thread, true, true); // Linking requires Java calls
Klass* klass = UNPACK_PAIR(Klass, klass);
if (klass == nullptr) {
JVMCI_THROW(NullPointerException);
Expand Down Expand Up @@ -2802,7 +2812,7 @@ C2V_VMENTRY_0(jlong, translate, (JNIEnv* env, jobject, jobject obj_handle, jbool
return 0L;
}
PEER_JVMCIENV_FROM_THREAD(THREAD, !JVMCIENV->is_hotspot());
CompilerThreadCanCallJava canCallJava(thread, PEER_JVMCIENV->is_hotspot());
CompilerThreadCanCallJava canCallJava(thread, PEER_JVMCIENV->is_hotspot(), true);
PEER_JVMCIENV->check_init(JVMCI_CHECK_0);

JVMCIEnv* thisEnv = JVMCIENV;
Expand Down Expand Up @@ -3025,21 +3035,21 @@ static jbyteArray get_encoded_annotation_data(InstanceKlass* holder, AnnotationA

C2V_VMENTRY_NULL(jbyteArray, getEncodedClassAnnotationData, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass),
jobject filter, jint filter_length, jlong filter_klass_pointers))
CompilerThreadCanCallJava canCallJava(thread, true); // Requires Java support
CompilerThreadCanCallJava canCallJava(thread, true, true); // Requires Java support
InstanceKlass* holder = InstanceKlass::cast(UNPACK_PAIR(Klass, klass));
return get_encoded_annotation_data(holder, holder->class_annotations(), true, filter_length, filter_klass_pointers, THREAD, JVMCIENV);
C2V_END

C2V_VMENTRY_NULL(jbyteArray, getEncodedExecutableAnnotationData, (JNIEnv* env, jobject, ARGUMENT_PAIR(method),
jobject filter, jint filter_length, jlong filter_klass_pointers))
CompilerThreadCanCallJava canCallJava(thread, true); // Requires Java support
CompilerThreadCanCallJava canCallJava(thread, true, true); // Requires Java support
methodHandle method(THREAD, UNPACK_PAIR(Method, method));
return get_encoded_annotation_data(method->method_holder(), method->annotations(), false, filter_length, filter_klass_pointers, THREAD, JVMCIENV);
C2V_END

C2V_VMENTRY_NULL(jbyteArray, getEncodedFieldAnnotationData, (JNIEnv* env, jobject, ARGUMENT_PAIR(klass), jint index,
jobject filter, jint filter_length, jlong filter_klass_pointers))
CompilerThreadCanCallJava canCallJava(thread, true); // Requires Java support
CompilerThreadCanCallJava canCallJava(thread, true, true); // Requires Java support
InstanceKlass* holder = check_field(InstanceKlass::cast(UNPACK_PAIR(Klass, klass)), index, JVMCIENV);
fieldDescriptor fd(holder, index);
return get_encoded_annotation_data(holder, fd.annotations(), false, filter_length, filter_klass_pointers, THREAD, JVMCIENV);
Expand Down Expand Up @@ -3103,7 +3113,7 @@ C2V_VMENTRY(void, callSystemExit, (JNIEnv* env, jobject, jint status))
vm_exit_during_initialization();
}
}
CompilerThreadCanCallJava canCallJava(thread, true);
CompilerThreadCanCallJava canCallJava(thread, true, true);
JavaValue result(T_VOID);
JavaCallArguments jargs(1);
jargs.push_int(status);
Expand Down Expand Up @@ -3392,7 +3402,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)},
{CC "updateCompilerThreadCanCallJava", CC "(I)I", FN_PTR(updateCompilerThreadCanCallJava)},
};

int CompilerToVM::methods_count() {
Expand Down
2 changes: 1 addition & 1 deletion src/hotspot/share/jvmci/jvmciEnv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1372,7 +1372,7 @@ JVMCIObject JVMCIEnv::get_jvmci_type(const JVMCIKlassHandle& klass, JVMCI_TRAPS)
JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current()); // For exception macros.
jboolean exception = false;
if (is_hotspot()) {
CompilerThreadCanCallJava ccj(THREAD, true);
CompilerThreadCanCallJava ccj(THREAD, true, true);
JavaValue result(T_OBJECT);
JavaCallArguments args;
args.push_long(pointer);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public class CompilerThreadCanCallJavaScope implements AutoCloseable {
/**
* Thread state used during the scope.
*/
private final boolean state;
private final int rawPrevState;

/**
* Non-null iff the thread state needs resetting in {@link #close()}.
Expand All @@ -55,10 +55,11 @@ public class CompilerThreadCanCallJavaScope implements AutoCloseable {
* @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)) {
int rawNewState = newState ? 1 : 0;
this.rawPrevState = vm.updateCompilerThreadCanCallJava(rawNewState);
if (rawPrevState != rawNewState) {
this.vm = vm;
} else {
this.vm = null;
Expand All @@ -78,7 +79,7 @@ public void close() {
}

if (vm != null) {
vm.updateCompilerThreadCanCallJava(!state);
vm.updateCompilerThreadCanCallJava(rawPrevState);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1516,10 +1516,12 @@ void getOopMapAt(HotSpotResolvedJavaMethodImpl method, int bci, long[] oopMap) {
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.
* If the current thread is a {@code CompilerThread} associated with a JVMCI compiler where
* {@code newState != CompilerThread::_can_call_java}, then {@code _can_call_java} is set
* to {@code newState}.
*
* @returns false if no change was made, otherwise true
* @return the previous {@code _can_call_java} value if change was made,
* otherwise {@code newState}
*/
native boolean updateCompilerThreadCanCallJava(boolean newState);
native int updateCompilerThreadCanCallJava(int newState);
}

0 comments on commit 021fdc2

Please sign in to comment.