8257020: [JVMCI] enable a JVMCICompiler to specify which GCs it supports

Reviewed-by: stefank, kvn
This commit is contained in:
Doug Simon 2020-12-03 13:42:50 +00:00
parent 129c37700f
commit fa58671f9f
21 changed files with 197 additions and 41 deletions

View File

@ -457,7 +457,7 @@ void CompilerConfig::ergo_initialize() {
#endif
#if INCLUDE_JVMCI
// Check that JVMCI compiler supports selested GC.
// Check that JVMCI supports selected GC.
// Should be done after GCConfig::initialize() was called.
JVMCIGlobals::check_jvmci_supported_gc();

View File

@ -635,6 +635,31 @@ void JVMCIEnv::fthrow_error(const char* file, int line, const char* format, ...)
}
}
jboolean JVMCIEnv::call_HotSpotJVMCIRuntime_isGCSupported (JVMCIObject runtime, jint gcIdentifier) {
JavaThread* THREAD = JavaThread::current();
if (is_hotspot()) {
JavaCallArguments jargs;
jargs.push_oop(Handle(THREAD, HotSpotJVMCI::resolve(runtime)));
jargs.push_int(gcIdentifier);
JavaValue result(T_BOOLEAN);
JavaCalls::call_special(&result,
HotSpotJVMCI::HotSpotJVMCIRuntime::klass(),
vmSymbols::isGCSupported_name(),
vmSymbols::int_bool_signature(), &jargs, CHECK_0);
return result.get_jboolean();
} else {
JNIAccessMark jni(this, THREAD);
jboolean result = jni()->CallNonvirtualBooleanMethod(runtime.as_jobject(),
JNIJVMCI::HotSpotJVMCIRuntime::clazz(),
JNIJVMCI::HotSpotJVMCIRuntime::isGCSupported_method(),
gcIdentifier);
if (jni()->ExceptionCheck()) {
return false;
}
return result;
}
}
JVMCIObject JVMCIEnv::call_HotSpotJVMCIRuntime_compileMethod (JVMCIObject runtime, JVMCIObject method, int entry_bci,
jlong compile_state, int id) {
JavaThread* THREAD = JVMCI::compilation_tick(JavaThread::current());

View File

@ -310,6 +310,8 @@ public:
JVMCIObject call_JavaConstant_forFloat(float value, JVMCI_TRAPS);
JVMCIObject call_JavaConstant_forDouble(double value, JVMCI_TRAPS);
jboolean call_HotSpotJVMCIRuntime_isGCSupported(JVMCIObject runtime, jint gcIdentifier);
BasicType kindToBasicType(JVMCIObject kind, JVMCI_TRAPS);
#define DO_THROW(name) \

View File

@ -348,6 +348,7 @@
start_class(HotSpotJVMCIRuntime, jdk_vm_ci_hotspot_HotSpotJVMCIRuntime) \
objectarray_field(HotSpotJVMCIRuntime, excludeFromJVMCICompilation, "[Ljava/lang/Module;") \
jvmci_method(CallNonvirtualObjectMethod, GetMethodID, call_special, JVMCIObject, HotSpotJVMCIRuntime, compileMethod, compileMethod_signature, (JVMCIObject runtime, JVMCIObject method, int entry_bci, jlong env, int id)) \
jvmci_method(CallNonvirtualObjectMethod, GetMethodID, call_special, JVMCIObject, HotSpotJVMCIRuntime, isGCSupported, int_bool_signature, (JVMCIObject runtime, int gcIdentifier)) \
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, encodeThrowable, encodeThrowable_signature, (JVMCIObject throwable)) \
jvmci_method(CallStaticObjectMethod, GetStaticMethodID, call_static, JVMCIObject, HotSpotJVMCIRuntime, decodeThrowable, decodeThrowable_signature, (JVMCIObject encodedThrowable)) \
jvmci_method(CallNonvirtualVoidMethod, GetMethodID, call_special, void, HotSpotJVMCIRuntime, bootstrapFinished, void_method_signature, (JVMCIObject runtime, JVMCI_TRAPS)) \

View File

@ -1516,6 +1516,15 @@ void JVMCIRuntime::compile_method(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, c
}
}
bool JVMCIRuntime::is_gc_supported(JVMCIEnv* JVMCIENV, CollectedHeap::Name name) {
JVMCI_EXCEPTION_CONTEXT
JVMCIObject receiver = get_HotSpotJVMCIRuntime(JVMCIENV);
if (JVMCIENV->has_pending_exception()) {
fatal_exception(JVMCIENV, "Exception during HotSpotJVMCIRuntime initialization");
}
return JVMCIENV->call_HotSpotJVMCIRuntime_isGCSupported(receiver, (int) name);
}
// ------------------------------------------------------------------
JVMCI::CodeInstallResult JVMCIRuntime::register_method(JVMCIEnv* JVMCIENV,

View File

@ -25,6 +25,7 @@
#define SHARE_JVMCI_JVMCIRUNTIME_HPP
#include "code/nmethod.hpp"
#include "gc/shared/collectedHeap.hpp"
#include "jvmci/jvmci.hpp"
#include "jvmci/jvmciExceptions.hpp"
#include "jvmci/jvmciObject.hpp"
@ -279,6 +280,9 @@ class JVMCIRuntime: public CHeapObj<mtJVMCI> {
// Compiles `target` with the JVMCI compiler.
void compile_method(JVMCIEnv* JVMCIENV, JVMCICompiler* compiler, const methodHandle& target, int entry_bci);
// Determines if the GC identified by `name` is supported by the JVMCI compiler.
bool is_gc_supported(JVMCIEnv* JVMCIENV, CollectedHeap::Name name);
// Register the result of a compilation.
JVMCI::CodeInstallResult register_method(JVMCIEnv* JVMCIENV,
const methodHandle& target,

View File

@ -200,11 +200,15 @@ bool JVMCIGlobals::enable_jvmci_product_mode(JVMFlagOrigin origin) {
return true;
}
bool JVMCIGlobals::gc_supports_jvmci() {
return UseSerialGC || UseParallelGC || UseG1GC;
}
void JVMCIGlobals::check_jvmci_supported_gc() {
if (EnableJVMCI) {
// Check if selected GC is supported by JVMCI and Java compiler
if (!(UseSerialGC || UseParallelGC || UseG1GC)) {
vm_exit_during_initialization("JVMCI Compiler does not support selected GC", GCConfig::hs_err_name());
if (!gc_supports_jvmci()) {
log_warning(gc, jvmci)("Setting EnableJVMCI to false as selected GC does not support JVMCI: %s", GCConfig::hs_err_name());
FLAG_SET_DEFAULT(EnableJVMCI, false);
FLAG_SET_DEFAULT(UseJVMCICompiler, false);
}

View File

@ -155,7 +155,10 @@ class JVMCIGlobals {
// Convert JVMCI experimental flags to product
static bool enable_jvmci_product_mode(JVMFlagOrigin);
// Check and exit VM with error if selected GC is not supported by JVMCI.
// Returns true iff the GC fully supports JVMCI.
static bool gc_supports_jvmci();
// Check and turn off EnableJVMCI if selected GC does not support JVMCI.
static void check_jvmci_supported_gc();
static fileStream* get_jni_config_file() { return _jni_config_file; }

View File

@ -482,6 +482,14 @@
declare_constant(CodeInstaller::VERIFY_OOP_MASK) \
declare_constant(CodeInstaller::INVOKE_INVALID) \
\
declare_constant(CollectedHeap::None) \
declare_constant(CollectedHeap::Serial) \
declare_constant(CollectedHeap::Parallel) \
declare_constant(CollectedHeap::G1) \
declare_constant(CollectedHeap::Epsilon) \
declare_constant(CollectedHeap::Z) \
declare_constant(CollectedHeap::Shenandoah) \
\
declare_constant(vmIntrinsics::FIRST_MH_SIG_POLY) \
declare_constant(vmIntrinsics::LAST_MH_SIG_POLY) \
declare_constant(vmIntrinsics::_invokeGeneric) \

View File

@ -103,6 +103,7 @@
template(visitFrame_signature, "(Ljdk/vm/ci/code/stack/InspectedFrame;)Ljava/lang/Object;") \
template(compileMethod_name, "compileMethod") \
template(compileMethod_signature, "(Ljdk/vm/ci/hotspot/HotSpotResolvedJavaMethod;IJI)Ljdk/vm/ci/hotspot/HotSpotCompilationRequestResult;") \
template(isGCSupported_name, "isGCSupported") \
template(encodeThrowable_name, "encodeThrowable") \
template(encodeThrowable_signature, "(Ljava/lang/Throwable;)Ljava/lang/String;") \
template(decodeThrowable_name, "decodeThrowable") \

View File

@ -94,6 +94,7 @@
LOG_TAG(jfr) \
LOG_TAG(jit) \
LOG_TAG(jni) \
LOG_TAG(jvmci) \
LOG_TAG(jvmti) \
LOG_TAG(lambda) \
LOG_TAG(library) \

View File

@ -108,6 +108,10 @@
#include "services/memTracker.hpp"
#include "utilities/nativeCallStack.hpp"
#endif // INCLUDE_NMT
#if INCLUDE_JVMCI
#include "jvmci/jvmciEnv.hpp"
#include "jvmci/jvmciRuntime.hpp"
#endif
#if INCLUDE_AOT
#include "aot/aotLoader.hpp"
#endif // INCLUDE_AOT
@ -354,6 +358,16 @@ WB_ENTRY(jboolean, WB_IsGCSupported(JNIEnv* env, jobject o, jint name))
return GCConfig::is_gc_supported((CollectedHeap::Name)name);
WB_END
WB_ENTRY(jboolean, WB_IsGCSupportedByJVMCICompiler(JNIEnv* env, jobject o, jint name))
#if INCLUDE_JVMCI
if (EnableJVMCI) {
JVMCIEnv jvmciEnv(thread, env, __FILE__, __LINE__);
return jvmciEnv.runtime()->is_gc_supported(&jvmciEnv, (CollectedHeap::Name)name);
}
#endif
return false;
WB_END
WB_ENTRY(jboolean, WB_IsGCSelected(JNIEnv* env, jobject o, jint name))
return GCConfig::is_gc_selected((CollectedHeap::Name)name);
WB_END
@ -1945,6 +1959,14 @@ WB_ENTRY(jboolean, WB_isC2OrJVMCIIncludedInVmBuild(JNIEnv* env))
#endif
WB_END
WB_ENTRY(jboolean, WB_IsJVMCISupportedByGC(JNIEnv* env))
#if INCLUDE_JVMCI
return JVMCIGlobals::gc_supports_jvmci();
#else
return false;
#endif
WB_END
WB_ENTRY(jboolean, WB_IsJavaHeapArchiveSupported(JNIEnv* env))
return HeapShared::is_heap_object_archiving_allowed();
WB_END
@ -2508,6 +2530,7 @@ static JNINativeMethod methods[] = {
{CC"isCDSIncludedInVmBuild", CC"()Z", (void*)&WB_IsCDSIncludedInVmBuild },
{CC"isJFRIncludedInVmBuild", CC"()Z", (void*)&WB_IsJFRIncludedInVmBuild },
{CC"isC2OrJVMCIIncludedInVmBuild", CC"()Z", (void*)&WB_isC2OrJVMCIIncludedInVmBuild },
{CC"isJVMCISupportedByGC", CC"()Z", (void*)&WB_IsJVMCISupportedByGC},
{CC"isJavaHeapArchiveSupported", CC"()Z", (void*)&WB_IsJavaHeapArchiveSupported },
{CC"cdsMemoryMappingFailed", CC"()Z", (void*)&WB_CDSMemoryMappingFailed },
@ -2520,6 +2543,7 @@ static JNINativeMethod methods[] = {
(void*)&WB_AddCompilerDirective },
{CC"removeCompilerDirective", CC"(I)V", (void*)&WB_RemoveCompilerDirective },
{CC"isGCSupported", CC"(I)Z", (void*)&WB_IsGCSupported},
{CC"isGCSupportedByJVMCICompiler", CC"(I)Z", (void*)&WB_IsGCSupportedByJVMCICompiler},
{CC"isGCSelected", CC"(I)Z", (void*)&WB_IsGCSelected},
{CC"isGCSelectedErgonomically", CC"()Z", (void*)&WB_IsGCSelectedErgonomically},
{CC"supportsConcurrentGCBreakpoints", CC"()Z", (void*)&WB_SupportsConcurrentGCBreakpoints},

View File

@ -69,6 +69,11 @@ final class HotSpotJVMCICompilerConfig {
public JVMCICompiler createCompiler(JVMCIRuntime rt) {
return this;
}
@Override
public boolean isGCSupported(int gcIdentifier) {
return false;
}
}
/**

View File

@ -712,6 +712,11 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
public CompilationRequestResult compileMethod(CompilationRequest request) {
throw t;
}
@Override
public boolean isGCSupported(int gcIdentifier) {
return false;
}
}
@Override
@ -814,6 +819,12 @@ public final class HotSpotJVMCIRuntime implements JVMCIRuntime {
return hsResult;
}
@SuppressWarnings("try")
@VMEntryPoint
private boolean isGCSupported(int gcIdentifier) {
return getCompiler().isGCSupported(gcIdentifier);
}
/**
* Guard to ensure shut down actions are performed at most once.
*/

View File

@ -33,4 +33,15 @@ public interface JVMCICompiler {
* install it in the code cache if the compilation is successful.
*/
CompilationRequestResult compileMethod(CompilationRequest request);
/**
* Determines if this compiler supports the {@code gcIdentifier} garbage collector. The default
* implementation of this method returns true as that is the effective answer given by a
* {@link JVMCICompiler} before this method was added.
*
* @param gcIdentifier a VM dependent GC identifier
*/
default boolean isGCSupported(int gcIdentifier) {
return true;
}
}

View File

@ -43,6 +43,7 @@ import org.graalvm.compiler.debug.DebugContext.Activation;
import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.debug.DebugOptions;
import org.graalvm.compiler.hotspot.CompilationCounters.Options;
import org.graalvm.compiler.hotspot.HotSpotGraalRuntime.HotSpotGC;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.hotspot.phases.OnStackReplacementPhase;
import org.graalvm.compiler.java.GraphBuilderPhase;
@ -323,4 +324,13 @@ public class HotSpotGraalCompiler implements GraalJVMCICompiler, Cancellable {
}
};
}
@Override
public boolean isGCSupported(int gcIdentifier) {
HotSpotGC gc = HotSpotGC.forName(gcIdentifier, graalRuntime.getVMConfig());
if (gc != null) {
return gc.supported;
}
return false;
}
}

View File

@ -247,38 +247,59 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
}
/**
* Constants denoting the GC algorithms available in HotSpot.
* Constants denoting the GC algorithms available in HotSpot. The names of the constants match
* the constants in the {@code CollectedHeap::Name} C++ enum.
*/
public enum HotSpotGC {
// Supported GCs
Serial(true, "UseSerialGC", true),
Parallel(true, "UseParallelGC", true, "UseParallelOldGC", JDK < 15, "UseParNewGC", JDK < 10),
CMS(true, "UseConcMarkSweepGC", JDK < 14),
G1(true, "UseG1GC", true),
Serial(true, JDK >= 11, "UseSerialGC", true),
Parallel(true, JDK >= 11, "UseParallelGC", true, "UseParallelOldGC", JDK < 15, "UseParNewGC", JDK < 10),
CMS(true, JDK >= 11 && JDK <= 14, "UseConcMarkSweepGC", JDK < 14),
G1(true, JDK >= 11, "UseG1GC", true),
// Unsupported GCs
Epsilon(false, "UseEpsilonGC", JDK >= 11),
Z(false, "UseZGC", JDK >= 11);
Epsilon(false, JDK >= 11, "UseEpsilonGC", JDK >= 11),
Z(false, JDK >= 11, "UseZGC", JDK >= 11),
Shenandoah(false, JDK >= 12, "UseShenandoahGC", JDK >= 12);
HotSpotGC(boolean supported,
HotSpotGC(boolean supported, boolean expectNamePresent,
String flag1, boolean expectFlagPresent1,
String flag2, boolean expectFlagPresent2,
String flag3, boolean expectFlagPresent3) {
this.supported = supported;
this.expectNamePresent = expectNamePresent;
this.expectFlagsPresent = new boolean[]{expectFlagPresent1, expectFlagPresent2, expectFlagPresent3};
this.flags = new String[]{flag1, flag2, flag3};
}
HotSpotGC(boolean supported, String flag, boolean expectFlagPresent) {
HotSpotGC(boolean supported, boolean expectNamePresent, String flag, boolean expectFlagPresent) {
this.supported = supported;
this.expectNamePresent = expectNamePresent;
this.expectFlagsPresent = new boolean[]{expectFlagPresent};
this.flags = new String[]{flag};
}
/**
* Specifies if this GC supported by Graal.
*/
final boolean supported;
final boolean[] expectFlagsPresent;
/**
* Specifies if {@link #name()} is expected to be present in the {@code CollectedHeap::Name}
* C++ enum.
*/
final boolean expectNamePresent;
/**
* The VM flags that will select this GC.
*/
private final String[] flags;
/**
* Specifies which {@link #flags} are expected to be present in the VM.
*/
final boolean[] expectFlagsPresent;
public boolean isSelected(GraalHotSpotVMConfig config) {
boolean selected = false;
for (int i = 0; i < flags.length; i++) {
@ -293,6 +314,20 @@ public final class HotSpotGraalRuntime implements HotSpotGraalRuntimeProvider {
}
return selected;
}
/**
* Gets the GC matching {@code name}.
*
* @param name the ordinal of a {@code CollectedHeap::Name} value
*/
static HotSpotGC forName(int name, GraalHotSpotVMConfig config) {
for (HotSpotGC gc : HotSpotGC.values()) {
if (config.getConstant("CollectedHeap::" + gc.name(), Integer.class, -1, gc.expectNamePresent) == name) {
return gc;
}
}
return null;
}
}
private HotSpotGC getSelectedGC() throws GraalError {

View File

@ -239,18 +239,12 @@ public class VMProps implements Callable<Map<String, String>> {
return "false";
}
switch (GC.selected()) {
case Serial:
case Parallel:
case G1:
// These GCs are supported with JVMCI
return "true";
default:
break;
// Not all GCs have full JVMCI support
if (!WB.isJVMCISupportedByGC()) {
return "false";
}
// Every other GC is not supported
return "false";
return "true";
}
/**
@ -271,21 +265,6 @@ public class VMProps implements Callable<Map<String, String>> {
return CPUInfo.getFeatures().toString();
}
private boolean isGcSupportedByGraal(GC gc) {
switch (gc) {
case Serial:
case Parallel:
case G1:
return true;
case Epsilon:
case Z:
case Shenandoah:
return false;
default:
throw new IllegalStateException("Unknown GC " + gc.name());
}
}
/**
* For all existing GC sets vm.gc.X property.
* Example vm.gc.G1=true means:
@ -296,11 +275,11 @@ public class VMProps implements Callable<Map<String, String>> {
* @param map - property-value pairs
*/
protected void vmGC(SafeMap map) {
var isGraalEnabled = Compiler.isGraalEnabled();
var isJVMCIEnabled = Compiler.isJVMCIEnabled();
for (GC gc: GC.values()) {
map.put("vm.gc." + gc.name(),
() -> "" + (gc.isSupported()
&& (!isGraalEnabled || isGcSupportedByGraal(gc))
&& (!isJVMCIEnabled || gc.isSupportedByJVMCICompiler())
&& (gc.isSelected() || GC.isSelectedErgonomically())));
}
}

View File

@ -232,6 +232,7 @@ public class WhiteBox {
// Compiler
public native boolean isC2OrJVMCIIncludedInVmBuild();
public native boolean isJVMCISupportedByGC();
public native int matchesMethod(Executable method, String pattern);
public native int matchesInline(Executable method, String pattern);
@ -415,6 +416,7 @@ public class WhiteBox {
// Don't use these methods directly
// Use sun.hotspot.gc.GC class instead.
public native boolean isGCSupported(int name);
public native boolean isGCSupportedByJVMCICompiler(int name);
public native boolean isGCSelected(int name);
public native boolean isGCSelectedErgonomically();

View File

@ -43,6 +43,20 @@ public class Compiler {
return WB.isC2OrJVMCIIncludedInVmBuild();
}
/**
* Check if JVMCI is enabled.
*
* @return true if JVMCI is enabled
*/
public static boolean isJVMCIEnabled() {
Boolean enableJvmci = WB.getBooleanVMFlag("EnableJVMCI");
if (enableJvmci == null || !enableJvmci) {
return false;
}
return true;
}
/**
* Check if Graal is used as JIT compiler.
*

View File

@ -55,6 +55,13 @@ public enum GC {
return WB.isGCSupported(name);
}
/**
* @return true if this GC is supported by the JVMCI compiler
*/
public boolean isSupportedByJVMCICompiler() {
return WB.isGCSupportedByJVMCICompiler(name);
}
/**
* @return true if this GC is currently selected/used
*/