Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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);
}