Skip to content

Commit

Permalink
[GR-32177] Delay Graal runtime initialization in jargraal until Graal…
Browse files Browse the repository at this point in the history
… compiler initialization.

PullRequest: graal/9636
  • Loading branch information
dougxc committed Sep 1, 2021
2 parents bdc8ab8 + 693c297 commit e436895
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 13 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import org.graalvm.compiler.options.Option;
import org.graalvm.compiler.options.OptionKey;
import org.graalvm.compiler.options.OptionType;
import org.graalvm.word.Pointer;

/**
* Dynamically registers a {@link HotSpotGraalRuntimeMBean}s created in libgraal heap with an
Expand All @@ -64,8 +65,8 @@ static class Options {
/**
* Creates a {@link HotSpotGraalRuntimeMBean} for given {@code runtime}. It first defines the
* required classes in the HotSpot heap and starts the factory thread. Then it creates a
* {@link HotSpotGraalRuntimeMBean} for given {@code runtime} and notifies the factory thread
* about a new pending registration.
* {@link HotSpotGraalRuntimeMBean} for {@code runtime} and notifies the factory thread about a
* new pending registration.
*
* @param runtime the runtime to create {@link HotSpotGraalRuntimeMBean} for
* @param config the configuration used to obtain the {@code _jni_environment} offset
Expand All @@ -75,7 +76,13 @@ public void initialize(HotSpotGraalRuntime runtime, GraalHotSpotVMConfig config)
int delay = Options.LibGraalManagementDelay.getValue(runtime.getOptions());
if (delay < 0) {
return;
} else if (delay == 0) {
}
Pointer defineClassesStatePointer = getDefineClassesStatePointer();
long defineClassesState = defineClassesStatePointer.readLong(0);
if (delay == 0 || defineClassesState == HS_CLASSES_DEFINED) {
// No delay or this is not the first Graal runtime to be initialized
// in the process. As such there's no need to use a separate thread
// to create the HotSpotGraalRuntimeMBean.
initialize0(runtime, config);
} else {
Thread t = new GraalServiceThread(LibGraalHotSpotGraalManagement.class.getSimpleName() + "-init", new Runnable() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,12 @@ class MBeanProxy<T extends DynamicMBean> {
private static final ClassData HS_ENTRYPOINTS_CLASS = ClassData.create(JMXFromLibGraalEntryPoints.class);
private static final ClassData HS_AGGREGATED_MEMORY_POOL_BEAN_CLASS = ClassData.create(AggregatedMemoryPoolBean.class);

// Values for the global word used to synchronize definition
// of the above classes in the HotSpot heap
static final long HS_CLASSES_UNDEFINED = 0L;
static final long HS_CLASSES_DEFINING = 1L;
static final long HS_CLASSES_DEFINED = 2L;

/**
* Pending MBeans registrations on HotSpot side.
*
Expand Down Expand Up @@ -341,23 +347,20 @@ private static void runGuarded(Pointer barrier, Runnable defineAction, Runnable
if (barrier.isNull()) {
throw new IllegalStateException("Missing substitution for MBeanProxy.defineClassesInHotSpot");
}
final long undefined = 0L;
final long defining = 1L;
final long defined = 2L;
long defineClassState = barrier.readLong(0);
if (defineClassState == defined) {
if (defineClassState == HS_CLASSES_DEFINED) {
loadAction.run();
} else {
while (true) {
defineClassState = barrier.readLong(0);
if (defineClassState == undefined) {
if (barrier.compareAndSwapLong(0, undefined, defining, ANY_LOCATION) == undefined) {
if (defineClassState == HS_CLASSES_UNDEFINED) {
if (barrier.compareAndSwapLong(0, HS_CLASSES_UNDEFINED, HS_CLASSES_DEFINING, ANY_LOCATION) == HS_CLASSES_UNDEFINED) {
defineAction.run();
barrier.writeLong(0, defined);
barrier.writeLong(0, HS_CLASSES_DEFINED);
break;
}
} else {
if (defineClassState == defined) {
if (defineClassState == HS_CLASSES_DEFINED) {
loadAction.run();
break;
}
Expand Down Expand Up @@ -429,7 +432,7 @@ private static void unregister() {
/**
* Gets a pointer to a global word used as spin lock for safely defining classes in HotSpot.
*/
private static Pointer getDefineClassesStatePointer() {
static Pointer getDefineClassesStatePointer() {
// Substituted by Target_org_graalvm_compiler_hotspot_management_libgraal_MBeanProxy
return WordFactory.nullPointer();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,39 @@ public String getCompilerName() {
*/
private IllegalArgumentException optionsFailure;

private volatile boolean initialized;

private void ensureInitialized() {
if (!initialized) {
synchronized (this) {
if (!initialized) {
initialize();
initialized = true;
}
}
}
}

@Override
public void onSelection() {
if (Services.IS_IN_NATIVE_IMAGE) {
// When instantiating a JVMCI runtime in the libgraal heap there's no
// point in delaying HotSpotGraalRuntime initialization as it
// is very fast (it's compiled and does no class loading) and will
// usually be done immediately after this call anyway (i.e. in a
// Graal-as-JIT configuration).
initialize();
initialized = true;
} else {
// When instantiating a JVMCI runtime in the HotSpot heap, initialization
// of a HotSpotGraalRuntime is deferred until a compiler instance is
// requested. This avoids extra class loading when the JMX code in libgraal
// (i.e. MBeanProxy) calls back into HotSpot. The HotSpot side of this call
// only needs a few Graal classes (namely LibGraalScope and kin).
}
}

private void initialize() {
JVMCIVersionCheck.check(Services.getSavedProperties(), false);
assert options == null : "cannot select " + getClass() + " service more than once";
try {
Expand Down Expand Up @@ -121,6 +152,7 @@ private static void initializeGraalCompilePolicyFields(OptionValues options) {

@Override
public void printProperties(PrintStream out) {
ensureInitialized();
out.println("[Graal properties]");
if (optionsFailure != null) {
System.err.printf("Error parsing Graal options: %s%n", optionsFailure.getMessage());
Expand All @@ -145,6 +177,7 @@ static class Options {

@Override
public HotSpotGraalCompiler createCompiler(JVMCIRuntime runtime) {
ensureInitialized();
HotSpotJVMCIRuntime hsRuntime = (HotSpotJVMCIRuntime) runtime;
if (optionsFailure != null) {
System.err.printf("Error parsing Graal options: %s%nError: A fatal exception has occurred. Program will exit.%n", optionsFailure.getMessage());
Expand Down
2 changes: 1 addition & 1 deletion sdk/mx.sdk/mx_sdk_vm_impl.py
Original file line number Diff line number Diff line change
Expand Up @@ -797,7 +797,7 @@ def needsUpdate(self, newestInput):
output = self.get_output()
if exists(output):
ts = mx.TimeStampFile(output)
if ts.isOlderThan(newestInput):
if newestInput and ts.isOlderThan(newestInput):
return "{} is older than {}".format(ts, newestInput)
else:
return None
Expand Down

0 comments on commit e436895

Please sign in to comment.