RFR: 8242440: use separate, destroyable JavaVM instances per libgraal compiler thread
Kim Barrett
kbarrett at openjdk.java.net
Sun Apr 17 05:39:33 UTC 2022
On Fri, 15 Apr 2022 13:29:43 GMT, Doug Simon <dnsimon at openjdk.org> wrote:
> Currently, libgraal runs in a single, permanent JavaVM instance loaded from libjvmcicompiler.so. This poses 2 problems:
>
> 1. The memory used for libgraal is never released, even when the libgraal compiler queues are idle.
> 2. Since all libgraal HotSpot compiler threads share the same SVM heap, libgraal compilation is effectively paused when a GC occurs (SVM currently has a stop the world collector). The more compiler threads there are, the more often this happens.
>
> This PR implements the following solution to these problems:
> 1. Create a new JavaVM instance per libgraal compiler thread (i.e. a separate SVM isolate per thread). This prevents GC in one libgraal thread from impacting another libgraal thread.
> 2. Destroy the JavaVM instances when a libgraal compiler thread becomes idle and create a new one when subsequent compilation requests arrive.
>
> Most of the changes are in JVMCI specific files. The most significant change to shared code is the addition of the `JavaThread:: _libjvmci_runtime` field. This is required as any thread (not just a `CompilerThread`) can be associated with a specific `JVMCIRuntime` object.
I've only carefully looked at the runtime changes; only skimming the jvmci and compiler parts.
src/hotspot/share/jvmci/jvmciRuntime.cpp line 905:
> 903: object_handles()->release(ptrs, released);
> 904: }
> 905: _jobjects->clear();
`clear` doesn't free any memory from the growable-array, so a runtime's _jobjects will have a capacity based on the high-water usage. I don't know if that's intentional. I was going to suggest using `GrowableArray::clear_and_deallocate()` if not, but the initialization of the array specifies a non-zero initial capacity (100).
src/hotspot/share/jvmci/jvmciRuntime.cpp line 975:
> 973:
> 974: JVMCIRuntime::JVMCIRuntime(JVMCIRuntime* next, int id, bool for_compile_broker) {
> 975: _init_state = uninitialized;
Why is this constructor using assignments rather than a ctor-initializer? There's lots of old code that doesn't, and the Style Guide doesn't require it (yet - https://bugs.openjdk.java.net/browse/JDK-8252586), but that's the trend (and generally considered best practice).
src/hotspot/share/jvmci/jvmciRuntime.cpp line 976:
> 974: JVMCIRuntime::JVMCIRuntime(JVMCIRuntime* next, int id, bool for_compile_broker) {
> 975: _init_state = uninitialized;
> 976: _shared_library_javavm = NULL;
Prefer nullptr to NULL in new code.
src/hotspot/share/jvmci/jvmciRuntime.cpp line 1185:
> 1183: JNIEnv* JVMCIRuntime::init_shared_library_javavm() {
> 1184: MutexLocker locker(_lock);
> 1185: JavaVM* javaVM = (JavaVM*) _shared_library_javavm;
Pointless cast.
src/hotspot/share/jvmci/jvmciRuntime.hpp line 168:
> 166: // destroying remaining JNI handles when the JavaVM associated
> 167: // with this runtime is shutdown.
> 168: GrowableArray<jobject>* _jobjects;
I think _jobjects should be a nested object rather than a pointer.
src/hotspot/share/jvmci/jvmciRuntime.hpp line 168:
> 166: // destroying remaining JNI handles when the JavaVM associated
> 167: // with this runtime is shutdown.
> 168: GrowableArray<jobject>* _jobjects;
I wonder if it would simplify anything to use OopHandle instead of jobject as the element type?
src/hotspot/share/jvmci/jvmciRuntime.hpp line 177:
> 175: int _num_attached_threads;
> 176: enum {
> 177: cannot_be_attached = -1 // See _num_attached_threads
We no longer use enums (with unspecified type) to define constants. Use `static const` instead. (There's lots of old code that still does this, but new code should not.)
src/hotspot/share/runtime/mutexLocker.hpp line 151:
> 149:
> 150: #if INCLUDE_JVMCI
> 151: #define JVMCIRuntime_lock_rank safepoint
This shouldn't be a macro. Use `const Mutex::Rank JVMCIRuntime_lock_rank = safepoint;`.
src/hotspot/share/runtime/thread.hpp line 1230:
> 1228: JVMCIRuntime* libjvmci_runtime() const { return _libjvmci_runtime; }
> 1229: void set_libjvmci_runtime(JVMCIRuntime* rt) {
> 1230: assert((_libjvmci_runtime == NULL && rt != NULL) || (_libjvmci_runtime != NULL && rt == NULL), "must be");
Prefer nullptr to NULL in new code.
-------------
Changes requested by kbarrett (Reviewer).
PR: https://git.openjdk.java.net/jdk/pull/8262
More information about the hotspot-dev
mailing list