From 260bb0676e1969dd7d7a6860475f5f9976752cb8 Mon Sep 17 00:00:00 2001 From: Doug Simon Date: Wed, 25 Sep 2024 00:46:45 +0200 Subject: [PATCH] added CompilerThreadCanCallJavaScope --- src/hotspot/share/jvmci/jvmci.cpp | 15 ++-- src/hotspot/share/jvmci/jvmci.hpp | 13 ++- src/hotspot/share/jvmci/jvmciCompilerToVM.cpp | 6 ++ .../CompilerThreadCanCallJavaScope.java | 84 +++++++++++++++++++ .../jdk/vm/ci/hotspot/CompilerToVM.java | 8 ++ 5 files changed, 113 insertions(+), 13 deletions(-) create mode 100644 src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerThreadCanCallJavaScope.java diff --git a/src/hotspot/share/jvmci/jvmci.cpp b/src/hotspot/share/jvmci/jvmci.cpp index 447792b6fcae6..f8a55f27614df 100644 --- a/src/hotspot/share/jvmci/jvmci.cpp +++ b/src/hotspot/share/jvmci/jvmci.cpp @@ -54,26 +54,29 @@ volatile intx JVMCI::_fatal_log_init_thread = -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; } } diff --git a/src/hotspot/share/jvmci/jvmci.hpp b/src/hotspot/share/jvmci/jvmci.hpp index 1e9fa08898fc3..dd679692ff593 100644 --- a/src/hotspot/share/jvmci/jvmci.hpp +++ b/src/hotspot/share/jvmci/jvmci.hpp @@ -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 diff --git a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp index d231fbe8a6a0e..9145cb7ae8301 100644 --- a/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp +++ b/src/hotspot/share/jvmci/jvmciCompilerToVM.cpp @@ -401,6 +401,11 @@ C2V_VMENTRY_NULL(jobject, asResolvedJavaMethod, (JNIEnv* env, jobject, jobject e return JVMCIENV->get_jobject(result); } +C2V_VMENTRY_0(jboolean, changeCompilerThreadCanCallJava, (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); @@ -3387,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 "changeCompilerThreadCanCallJava", CC "(Z)Z", FN_PTR(changeCompilerThreadCanCallJava)}, }; int CompilerToVM::methods_count() { diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerThreadCanCallJavaScope.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerThreadCanCallJavaScope.java new file mode 100644 index 0000000000000..7488c55207610 --- /dev/null +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerThreadCanCallJavaScope.java @@ -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.changeCompilerThreadCanCallJava(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.changeCompilerThreadCanCallJava(!state); + } + } +} diff --git a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java index 593697545266d..e7128fdc1e449 100644 --- a/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java +++ b/src/jdk.internal.vm.ci/share/classes/jdk/vm/ci/hotspot/CompilerToVM.java @@ -1514,4 +1514,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. + * + * @returns false if no change was made, otherwise true + */ + native boolean changeCompilerThreadCanCallJava(boolean newState); }