Skip to content

Commit 46592f2

Browse files
committed
Partial evaluation method info uses JFR state.
1 parent 10a5d1a commit 46592f2

File tree

12 files changed

+85
-38
lines changed

12 files changed

+85
-38
lines changed

compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/HSTruffleCompilerRuntime.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@
6969
import jdk.vm.ci.meta.ResolvedJavaMethod;
7070
import jdk.vm.ci.meta.ResolvedJavaType;
7171
import jdk.vm.ci.meta.UnresolvedJavaType;
72+
import org.graalvm.nativeimage.c.type.CCharPointer;
7273

7374
public final class HSTruffleCompilerRuntime extends HSObject implements TruffleCompilerRuntime {
7475

@@ -78,14 +79,16 @@ public final class HSTruffleCompilerRuntime extends HSObject implements TruffleC
7879
private static final Class<?> TRANSLATED_EXCEPTION = LibGraalFeature.lookupClass("jdk.internal.vm.TranslatedException");
7980

8081
private final ResolvedJavaType classLoaderDelegate;
82+
private final CCharPointer javaInstrumentationActive;
8183
final TruffleFromLibGraalCalls calls;
8284

83-
HSTruffleCompilerRuntime(JNIEnv env, JObject handle, ResolvedJavaType classLoaderDelegate, JClass peer) {
85+
HSTruffleCompilerRuntime(JNIEnv env, JObject handle, ResolvedJavaType classLoaderDelegate, JClass peer, CCharPointer javaInstrumentationActive) {
8486
/*
8587
* Note global duplicates may happen if the compiler is initialized by a host compilation.
8688
*/
8789
super(env, handle, true, false);
8890
this.classLoaderDelegate = classLoaderDelegate;
91+
this.javaInstrumentationActive = javaInstrumentationActive;
8992
this.calls = new TruffleFromLibGraalCalls(env, peer);
9093
}
9194

@@ -212,4 +215,9 @@ public boolean isSuppressedFailure(TruffleCompilable compilable, Supplier<String
212215
public void notifyShutdown(JNIEnv env) {
213216
HSTruffleCompilerRuntimeGen.callOnIsolateShutdown(calls, env, IsolateUtil.getIsolateID());
214217
}
218+
219+
@Override
220+
public boolean isJavaInstrumentationActive() {
221+
return javaInstrumentationActive.isNonNull() && javaInstrumentationActive.read() != 0;
222+
}
215223
}

compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleEntryPoints.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@
4343
import org.graalvm.nativeimage.ObjectHandles;
4444
import org.graalvm.nativeimage.c.function.CEntryPoint;
4545
import org.graalvm.nativeimage.c.function.CEntryPoint.IsolateThreadContext;
46+
import org.graalvm.nativeimage.c.type.CCharPointer;
4647
import org.graalvm.nativeimage.c.type.CLongPointer;
4748
import org.graalvm.word.PointerBase;
4849

@@ -104,10 +105,12 @@ public static void initializeIsolate(JNIEnv env, JClass hsClazz, @IsolateThreadC
104105
@SuppressWarnings({"unused", "try"})
105106
@CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_registerRuntime", include = LibGraalFeature.IsEnabled.class)
106107
@TruffleToLibGraal(Id.RegisterRuntime)
107-
public static boolean registerRuntime(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, JObject truffleRuntime) {
108+
public static boolean registerRuntime(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress, JObject truffleRuntime,
109+
JObject javaInstrumentationActive) {
108110
try (JNIMethodScope s = openScope(Id.RegisterRuntime, env)) {
109111
long truffleRuntimeWeakRef = JNIUtil.NewWeakGlobalRef(env, truffleRuntime, "TruffleCompilerRuntime").rawValue();
110-
return LibGraalTruffleHostEnvironmentLookup.registerRuntime(truffleRuntimeWeakRef);
112+
long activeAddress = JNIUtil.GetDirectBufferAddress(env, javaInstrumentationActive).rawValue();
113+
return LibGraalTruffleHostEnvironmentLookup.registerRuntime(truffleRuntimeWeakRef, activeAddress);
111114
} catch (Throwable t) {
112115
JNIExceptionWrapper.throwInHotSpot(env, t);
113116
return false;
@@ -118,10 +121,11 @@ public static boolean registerRuntime(JNIEnv env, JClass hsClazz, @IsolateThread
118121
@CEntryPoint(name = "Java_com_oracle_truffle_runtime_hotspot_libgraal_TruffleToLibGraalCalls_initializeRuntime", include = LibGraalFeature.IsEnabled.class)
119122
@TruffleToLibGraal(Id.InitializeRuntime)
120123
public static long initializeRuntime(JNIEnv env, JClass hsClazz, @IsolateThreadContext long isolateThreadAddress,
121-
JObject truffleRuntime, JClass hsClassLoaderDelegate) {
124+
JObject truffleRuntime, JClass hsClassLoaderDelegate, JObject javaInstrumentationActive) {
122125
try (JNIMethodScope s = openScope(Id.InitializeRuntime, env)) {
123126
ResolvedJavaType classLoaderDelegate = HotSpotJVMCIRuntime.runtime().asResolvedJavaType(hsClassLoaderDelegate.rawValue());
124-
HSTruffleCompilerRuntime hsTruffleRuntime = new HSTruffleCompilerRuntime(env, truffleRuntime, classLoaderDelegate, hsClassLoaderDelegate);
127+
CCharPointer activeAddress = (CCharPointer) JNIUtil.GetDirectBufferAddress(env, javaInstrumentationActive);
128+
HSTruffleCompilerRuntime hsTruffleRuntime = new HSTruffleCompilerRuntime(env, truffleRuntime, classLoaderDelegate, hsClassLoaderDelegate, activeAddress);
125129
LibGraalSupportImpl.registerTruffleCompilerRuntime(hsTruffleRuntime);
126130
return LibGraalObjectHandles.create(hsTruffleRuntime);
127131
} catch (Throwable t) {

compiler/src/jdk.graal.compiler.libgraal/src/jdk/graal/compiler/libgraal/truffle/LibGraalTruffleHostEnvironmentLookup.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@
3636
import org.graalvm.jniutils.JNI.JObject;
3737
import org.graalvm.jniutils.JNIMethodScope;
3838
import org.graalvm.jniutils.JNIUtil;
39+
import org.graalvm.word.WordFactory;
3940

4041
/**
4142
* This handles the Truffle host environment lookup on HotSpot with Libgraal.
@@ -54,6 +55,7 @@ public final class LibGraalTruffleHostEnvironmentLookup implements TruffleHostEn
5455

5556
private static final int NO_TRUFFLE_REGISTERED = 0;
5657
private static final GlobalAtomicLong WEAK_TRUFFLE_RUNTIME_INSTANCE = new GlobalAtomicLong("WEAK_TRUFFLE_RUNTIME_INSTANCE", NO_TRUFFLE_REGISTERED);
58+
private static final GlobalAtomicLong JAVA_INSTRUMENTATION_ACTIVE_ADDRESS = new GlobalAtomicLong("JAVA_INSTRUMENTATION_ACTIVE_ADDRESS", NO_TRUFFLE_REGISTERED);
5759

5860
private TruffleHostEnvironment previousRuntime;
5961

@@ -89,7 +91,7 @@ public TruffleHostEnvironment lookup(ResolvedJavaType forType) {
8991
* per type. So in theory multiple truffle runtimes can be loaded.
9092
*/
9193
try (TruffleRuntimeScope truffleRuntimeScope = LibGraalTruffleHostEnvironment.openTruffleRuntimeScopeImpl()) {
92-
HSTruffleCompilerRuntime runtime = new HSTruffleCompilerRuntime(env, runtimeLocalRef, runtimeType, runtimeClass);
94+
HSTruffleCompilerRuntime runtime = new HSTruffleCompilerRuntime(env, runtimeLocalRef, runtimeType, runtimeClass, WordFactory.pointer(JAVA_INSTRUMENTATION_ACTIVE_ADDRESS.get()));
9395
this.previousRuntime = environment = new LibGraalTruffleHostEnvironment(runtime, HotSpotJVMCIRuntime.runtime().getHostJVMCIBackend().getMetaAccess());
9496
assert JNIUtil.IsSameObject(env, hsRuntime(environment).getHandle(), runtimeLocalRef);
9597
return environment;
@@ -100,8 +102,12 @@ private static HSTruffleCompilerRuntime hsRuntime(TruffleHostEnvironment environ
100102
return (HSTruffleCompilerRuntime) environment.runtime();
101103
}
102104

103-
public static boolean registerRuntime(long truffleRuntimeWeakRef) {
105+
public static boolean registerRuntime(long truffleRuntimeWeakRef, long javaInstrumentationActiveAddress) {
104106
// TODO GR-44222 support multiple runtimes.
105-
return WEAK_TRUFFLE_RUNTIME_INSTANCE.compareAndSet(0, truffleRuntimeWeakRef);
107+
boolean registered = WEAK_TRUFFLE_RUNTIME_INSTANCE.compareAndSet(0, truffleRuntimeWeakRef);
108+
if (registered) {
109+
JAVA_INSTRUMENTATION_ACTIVE_ADDRESS.set(javaInstrumentationActiveAddress);
110+
}
111+
return registered;
106112
}
107113
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/FlightRecorderInstrumentation.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,14 @@
2424
*/
2525
package jdk.graal.compiler.truffle;
2626

27+
import com.oracle.truffle.compiler.TruffleCompilerRuntime;
2728
import jdk.vm.ci.meta.JavaMethod;
2829
import jdk.vm.ci.meta.ResolvedJavaMethod;
2930
import jdk.vm.ci.meta.ResolvedJavaType;
3031

3132
import java.util.LinkedHashSet;
3233
import java.util.Set;
3334

34-
// TODO: Handle FlightRecorder enabling/disabling.
3535
final class FlightRecorderInstrumentation {
3636

3737
private static final Set<InstrumentedMethodPattern> instrumentedMethodPatterns = createInstrumentedPatterns();
@@ -50,7 +50,10 @@ private static Set<InstrumentedMethodPattern> createInstrumentedPatterns() {
5050
private FlightRecorderInstrumentation() {
5151
}
5252

53-
static boolean isInstrumented(ResolvedJavaMethod method, KnownTruffleTypes types) {
53+
static boolean isInstrumented(TruffleCompilerRuntime runtime, ResolvedJavaMethod method, KnownTruffleTypes types) {
54+
if (!runtime.isJavaInstrumentationActive()) {
55+
return false;
56+
}
5457
if (("traceThrowable".equals(method.getName()) || "traceError".equals(method.getName())) && "Ljdk/jfr/internal/instrument/ThrowableTracer;".equals(method.getDeclaringClass().getName())) {
5558
return true;
5659
}

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/PartialEvaluator.java

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -83,8 +83,6 @@
8383
import jdk.vm.ci.meta.ResolvedJavaType;
8484
import jdk.vm.ci.meta.SpeculationLog.SpeculationReason;
8585

86-
import static jdk.graal.compiler.annotation.AnnotationValueSupport.getDeclaredAnnotationValues;
87-
8886
/**
8987
* Class performing the partial evaluation starting from the root node of an AST.
9088
*/
@@ -203,7 +201,8 @@ public static ConstantFieldInfo computeConstantFieldInfo(ResolvedJavaField field
203201
return null;
204202
}
205203

206-
public static PartialEvaluationMethodInfo computePartialEvaluationMethodInfo(ResolvedJavaMethod method,
204+
public static PartialEvaluationMethodInfo computePartialEvaluationMethodInfo(TruffleCompilerRuntime runtime,
205+
ResolvedJavaMethod method,
207206
Map<ResolvedJavaType, AnnotationValue> declaredAnnotationValues,
208207
KnownTruffleTypes types) {
209208
AnnotationValue truffleBoundary = declaredAnnotationValues.get(types.CompilerDirectives_TruffleBoundary);
@@ -212,8 +211,8 @@ public static PartialEvaluationMethodInfo computePartialEvaluationMethodInfo(Res
212211
AnnotationValue explodeLoop = declaredAnnotationValues.get(types.ExplodeLoop);
213212

214213
return new PartialEvaluationMethodInfo(getLoopExplosionKind(explodeLoop),
215-
getInlineKind(truffleBoundary, truffleCallBoundary, method, true, types),
216-
getInlineKind(truffleBoundary, truffleCallBoundary, method, false, types),
214+
getInlineKind(runtime, truffleBoundary, truffleCallBoundary, method, true, types),
215+
getInlineKind(runtime, truffleBoundary, truffleCallBoundary, method, false, types),
217216
method.canBeInlined(),
218217
specialization);
219218
}
@@ -233,7 +232,7 @@ private static LoopExplosionKind getLoopExplosionKind(AnnotationValue value) {
233232
};
234233
}
235234

236-
private static InlineKind getInlineKind(AnnotationValue truffleBoundary, AnnotationValue truffleCallBoundary,
235+
private static InlineKind getInlineKind(TruffleCompilerRuntime runtime, AnnotationValue truffleBoundary, AnnotationValue truffleCallBoundary,
237236
ResolvedJavaMethod method, boolean duringPartialEvaluation,
238237
KnownTruffleTypes types) {
239238
if (truffleBoundary != null) {
@@ -252,7 +251,7 @@ private static InlineKind getInlineKind(AnnotationValue truffleBoundary, Annotat
252251
}
253252
} else if (truffleCallBoundary != null) {
254253
return InlineKind.DO_NOT_INLINE_WITH_EXCEPTION;
255-
} else if (FlightRecorderInstrumentation.isInstrumented(method, types)) {
254+
} else if (FlightRecorderInstrumentation.isInstrumented(runtime, method, types)) {
256255
return InlineKind.DO_NOT_INLINE_WITH_EXCEPTION;
257256
}
258257
return InlineKind.INLINE;

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/truffle/hotspot/HotSpotPartialEvaluator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ protected Object createKey(ResolvedJavaMethod method) {
180180
@Override
181181
protected PartialEvaluationMethodInfo computeValue(ResolvedJavaMethod method) {
182182
Map<ResolvedJavaType, AnnotationValue> declaredAnnotationValues = AnnotationValueSupport.getDeclaredAnnotationValues(method);
183-
PartialEvaluationMethodInfo methodInfo = computePartialEvaluationMethodInfo(method, declaredAnnotationValues, getTypes());
183+
PartialEvaluationMethodInfo methodInfo = computePartialEvaluationMethodInfo(config.runtime(), method, declaredAnnotationValues, getTypes());
184184
/*
185185
* We can canonicalize the instances to reduce space required in the cache. There are
186186
* only a small number of possible instances of PartialEvaluationMethodInfo as it just

substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/api/SubstrateTruffleUniverseFactory.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ static PartialEvaluationMethodInfo createPartialEvaluationMethodInfo(TruffleComp
9292
KnownTruffleTypes types) {
9393
SubstrateAnnotationExtractor extractor = (SubstrateAnnotationExtractor) ImageSingletons.lookup(AnnotationExtractor.class);
9494
Map<ResolvedJavaType, AnnotationValue> annotations = extractor.getDeclaredAnnotationValues((Annotated) method);
95-
var info = PartialEvaluator.computePartialEvaluationMethodInfo(method, annotations, types);
95+
var info = PartialEvaluator.computePartialEvaluationMethodInfo(runtime, method, annotations, types);
9696
if (Uninterruptible.Utils.isUninterruptible(method)) {
9797
Uninterruptible uninterruptibleAnnotation = Uninterruptible.Utils.getAnnotation(method);
9898
if (uninterruptibleAnnotation == null || !uninterruptibleAnnotation.mayBeInlined()) {

truffle/src/com.oracle.truffle.compiler/src/com/oracle/truffle/compiler/TruffleCompilerRuntime.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -358,4 +358,12 @@ default ResolvedJavaType resolveType(MetaAccessProvider metaAccess, String class
358358
* silent.
359359
*/
360360
boolean isSuppressedFailure(TruffleCompilable compilable, Supplier<String> serializedException);
361+
362+
/**
363+
* Returns {@code true} if Java VM level instrumentation, such as Java Flight Recorder, is
364+
* enabled.
365+
*/
366+
default boolean isJavaInstrumentationActive() {
367+
return false;
368+
}
361369
}

truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/OptimizedTruffleRuntime.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1158,6 +1158,11 @@ public boolean isSuppressedFailure(TruffleCompilable compilable, Supplier<String
11581158
return floodControlHandler != null && floodControlHandler.isSuppressedFailure(compilable, serializedException);
11591159
}
11601160

1161+
@Override
1162+
public boolean isJavaInstrumentationActive() {
1163+
return JFRListener.isActive();
1164+
}
1165+
11611166
/**
11621167
* Allows {@link OptimizedTruffleRuntime} subclasses to suppress exceptions such as an exception
11631168
* thrown during VM exit. Unlike {@link #isSuppressedFailure(TruffleCompilable, Supplier)} this

truffle/src/com.oracle.truffle.runtime/src/com/oracle/truffle/runtime/debug/JFRListener.java

Lines changed: 26 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
*/
4141
package com.oracle.truffle.runtime.debug;
4242

43+
import java.nio.ByteBuffer;
4344
import java.util.HashSet;
4445
import java.util.Iterator;
4546
import java.util.Set;
@@ -79,6 +80,7 @@ public final class JFRListener extends AbstractGraalTruffleRuntimeListener {
7980
// Support for JFRListener#isInstrumented
8081
private static final Set<InstrumentedMethodPattern> instrumentedMethodPatterns = createInstrumentedPatterns();
8182
private static final AtomicReference<InstrumentedFilterState> instrumentedFilterState = new AtomicReference<>(InstrumentedFilterState.NEW);
83+
private static final ByteBuffer nativeInstrumentedFilterState = ByteBuffer.allocateDirect(1);
8284
private static volatile ResolvedJavaType resolvedJfrEventClass;
8385

8486
private final ThreadLocal<CompilationData> currentCompilation = new ThreadLocal<>();
@@ -106,12 +108,29 @@ public static void install(OptimizedTruffleRuntime runtime) {
106108
}
107109

108110
public static boolean isInstrumented(ResolvedJavaMethod method) {
109-
// Initialization must be deferred into the image execution time
111+
if (!isActive()) {
112+
return false;
113+
}
114+
return isInstrumentedImpl(method);
115+
}
116+
117+
public static boolean isActive() {
110118
InstrumentedFilterState currentState = instrumentedFilterState.get();
111119
if (currentState == InstrumentedFilterState.INACTIVE) {
112120
return false;
113121
}
114-
return isInstrumentedImpl(method, currentState);
122+
if (currentState == InstrumentedFilterState.NEW) {
123+
currentState = initializeInstrumentedFilter();
124+
}
125+
// If JFR is not active or we are in the image build time return false
126+
return currentState != InstrumentedFilterState.NEW && currentState != InstrumentedFilterState.INACTIVE;
127+
}
128+
129+
public static ByteBuffer nativeState() {
130+
if (instrumentedFilterState.get() == InstrumentedFilterState.NEW) {
131+
initializeInstrumentedFilter();
132+
}
133+
return nativeInstrumentedFilterState;
115134
}
116135

117136
@Override
@@ -281,18 +300,7 @@ private static boolean isPermanentFailure(boolean bailout, boolean permanentBail
281300
}
282301

283302
// Support for JFRListener#isInstrumented
284-
private static boolean isInstrumentedImpl(ResolvedJavaMethod method, InstrumentedFilterState state) {
285-
286-
InstrumentedFilterState currentState = state;
287-
if (currentState == InstrumentedFilterState.NEW) {
288-
currentState = initializeInstrumentedFilter();
289-
}
290-
291-
// If JFR is not active or we are in the image build time return false
292-
if (currentState == InstrumentedFilterState.NEW || currentState == InstrumentedFilterState.INACTIVE) {
293-
return false;
294-
}
295-
303+
private static boolean isInstrumentedImpl(ResolvedJavaMethod method) {
296304
/*
297305
* Between JDK-11 and JDK-21, JFR utilizes instrumentation to inject calls to
298306
* jdk.jfr.internal.instrument.ThrowableTracer into constructors of Throwable and Error.
@@ -330,9 +338,12 @@ private static InstrumentedFilterState initializeInstrumentedFilter() {
330338
if (FACTORY != null) {
331339
FACTORY.addInitializationListener(() -> {
332340
instrumentedFilterState.set(InstrumentedFilterState.ACTIVE);
341+
nativeInstrumentedFilterState.put(0, (byte) 1);
333342
});
334343
InstrumentedFilterState currentState = FACTORY.isInitialized() ? InstrumentedFilterState.ACTIVE : InstrumentedFilterState.INACTIVE;
335-
instrumentedFilterState.compareAndSet(InstrumentedFilterState.NEW, currentState);
344+
if (instrumentedFilterState.compareAndSet(InstrumentedFilterState.NEW, currentState)) {
345+
nativeInstrumentedFilterState.put(0, (byte) (currentState == InstrumentedFilterState.ACTIVE ? 1 : 0));
346+
}
336347
} else {
337348
instrumentedFilterState.set(InstrumentedFilterState.INACTIVE);
338349
}

0 commit comments

Comments
 (0)