Skip to content

Commit a94c18b

Browse files
committed
Fixed native-image universe factory.
1 parent 9552445 commit a94c18b

File tree

7 files changed

+122
-32
lines changed

7 files changed

+122
-32
lines changed

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

Lines changed: 50 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626

2727
import java.net.URI;
2828
import java.util.Map;
29+
import java.util.function.Function;
2930
import java.util.function.Supplier;
3031

3132
import jdk.graal.compiler.annotation.EnumElement;
@@ -181,48 +182,85 @@ private static int actualStableDimensions(ResolvedJavaField field, int dimension
181182
* Gets an object describing how a read of {@code field} can be constant folded based on Truffle
182183
* annotations.
183184
*
185+
* @param field the field for which to compute {@link ConstantFieldInfo}
186+
* @param declaredAnnotationValues a map of method annotations keyed by their declaring
187+
* {@link ResolvedJavaType}
188+
* @param types cached types known to the Truffle compiler
189+
* @param unwrapType a function that unwraps a {@link ResolvedJavaType} obtained from
190+
* {@code types} to its underlying host {@link ResolvedJavaType}. In native-image,
191+
* known Truffle types are represented as {@code AnalysisType}, while the keys in
192+
* {@code declaredAnnotationValues} correspond to host JVMCI types. Therefore, each
193+
* {@code AnalysisType} must be unwrapped via
194+
* {@code OriginalClassProvider.getOriginalType(JavaType)} to correctly access the
195+
* corresponding annotation entries in {@code declaredAnnotationValues}.
196+
*
184197
* @return {@code null} if there are no constant folding related Truffle annotations on
185198
* {@code field}
186199
*/
187200
public static ConstantFieldInfo computeConstantFieldInfo(ResolvedJavaField field,
188201
Map<ResolvedJavaType, AnnotationValue> declaredAnnotationValues,
189-
KnownTruffleTypes types) {
190-
if (declaredAnnotationValues.containsKey(types.Node_Child)) {
202+
KnownTruffleTypes types, Function<ResolvedJavaType, ResolvedJavaType> unwrapType) {
203+
if (declaredAnnotationValues.containsKey(unwrapType.apply(types.Node_Child))) {
191204
return ConstantFieldInfo.CHILD;
192205
}
193-
if (declaredAnnotationValues.containsKey(types.Node_Children)) {
206+
if (declaredAnnotationValues.containsKey(unwrapType.apply(types.Node_Children))) {
194207
return ConstantFieldInfo.CHILDREN;
195208
}
196-
AnnotationValue cf = declaredAnnotationValues.get(types.CompilerDirectives_CompilationFinal);
209+
AnnotationValue cf = declaredAnnotationValues.get(unwrapType.apply(types.CompilerDirectives_CompilationFinal));
197210
if (cf != null) {
198211
int dimensions = actualStableDimensions(field, cf.get("dimensions", Integer.class));
199212
return ConstantFieldInfo.forDimensions(dimensions);
200213
}
201214
return null;
202215
}
203216

217+
/**
218+
* Computes {@link PartialEvaluationMethodInfo} for the given {@code method} based on its
219+
* declared annotations.
220+
*
221+
* <p>
222+
* This method analyzes the annotations present on {@code method}, provided in
223+
* {@code declaredAnnotationValues}, and determines partial evaluation behavior such as loop
224+
* explosion, inlining, and specialization characteristics.
225+
* </p>
226+
*
227+
* @param runtime the Truffle runtime used to determine whether
228+
* {@linkplain TruffleCompilerRuntime#isJavaInstrumentationActive() flight recorder
229+
* instrumentation is active}
230+
* @param method the method for which to compute {@link PartialEvaluationMethodInfo}
231+
* @param declaredAnnotationValues a map of method annotations keyed by their declaring
232+
* {@link ResolvedJavaType}
233+
* @param types cached types known to the Truffle compiler
234+
* @param unwrapType a function that unwraps a {@link ResolvedJavaType} obtained from
235+
* {@code types} to its underlying host {@link ResolvedJavaType}. In native-image,
236+
* known Truffle types are represented as {@code AnalysisType}, while the keys in
237+
* {@code declaredAnnotationValues} correspond to host JVMCI types. Therefore, each
238+
* {@code AnalysisType} must be unwrapped via
239+
* {@code OriginalClassProvider.getOriginalType(JavaType)} to correctly access the
240+
* corresponding annotation entries in {@code declaredAnnotationValues}.
241+
*/
204242
public static PartialEvaluationMethodInfo computePartialEvaluationMethodInfo(TruffleCompilerRuntime runtime,
205243
ResolvedJavaMethod method,
206244
Map<ResolvedJavaType, AnnotationValue> declaredAnnotationValues,
207-
KnownTruffleTypes types) {
208-
AnnotationValue truffleBoundary = declaredAnnotationValues.get(types.CompilerDirectives_TruffleBoundary);
209-
AnnotationValue truffleCallBoundary = declaredAnnotationValues.get(types.TruffleCallBoundary);
210-
boolean specialization = declaredAnnotationValues.get(types.Specialization) != null;
211-
AnnotationValue explodeLoop = declaredAnnotationValues.get(types.ExplodeLoop);
245+
KnownTruffleTypes types, Function<ResolvedJavaType, ResolvedJavaType> unwrapType) {
246+
AnnotationValue truffleBoundary = declaredAnnotationValues.get(unwrapType.apply(types.CompilerDirectives_TruffleBoundary));
247+
AnnotationValue truffleCallBoundary = declaredAnnotationValues.get(unwrapType.apply(types.TruffleCallBoundary));
248+
boolean specialization = declaredAnnotationValues.get(unwrapType.apply(types.Specialization)) != null;
249+
AnnotationValue explodeLoop = declaredAnnotationValues.get(unwrapType.apply(types.ExplodeLoop));
212250

213-
return new PartialEvaluationMethodInfo(getLoopExplosionKind(explodeLoop, types),
251+
return new PartialEvaluationMethodInfo(getLoopExplosionKind(explodeLoop, unwrapType.apply(types.ExplodeLoop_LoopExplosionKind)),
214252
getInlineKind(runtime, truffleBoundary, truffleCallBoundary, method, true, types),
215253
getInlineKind(runtime, truffleBoundary, truffleCallBoundary, method, false, types),
216254
method.canBeInlined(),
217255
specialization);
218256
}
219257

220-
private static LoopExplosionKind getLoopExplosionKind(AnnotationValue value, KnownTruffleTypes types) {
258+
private static LoopExplosionKind getLoopExplosionKind(AnnotationValue value, ResolvedJavaType expectedType) {
221259
if (value == null) {
222260
return LoopExplosionKind.NONE;
223261
}
224262
EnumElement enumElement = value.get("kind", EnumElement.class);
225-
if (!types.ExplodeLoop_LoopExplosionKind.equals(enumElement.enumType)) {
263+
if (!expectedType.equals(enumElement.enumType)) {
226264
throw new IllegalStateException("Incompatible ExplodeLoop change. ExplodeLoop.kind must be LoopExplosionKind.");
227265
}
228266
return Enum.valueOf(LoopExplosionKind.class, enumElement.name);

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.concurrent.ConcurrentHashMap;
2929
import java.util.concurrent.ConcurrentMap;
3030
import java.util.concurrent.atomic.AtomicReference;
31+
import java.util.function.Function;
3132
import java.util.function.Supplier;
3233

3334
import org.graalvm.collections.EconomicMap;
@@ -181,7 +182,7 @@ protected Object createKey(ResolvedJavaMethod method) {
181182
@Override
182183
protected PartialEvaluationMethodInfo computeValue(ResolvedJavaMethod method) {
183184
Map<ResolvedJavaType, AnnotationValue> declaredAnnotationValues = AnnotationValueSupport.getDeclaredAnnotationValues(method);
184-
PartialEvaluationMethodInfo methodInfo = computePartialEvaluationMethodInfo(config.runtime(), method, declaredAnnotationValues, getTypes());
185+
PartialEvaluationMethodInfo methodInfo = computePartialEvaluationMethodInfo(config.runtime(), method, declaredAnnotationValues, getTypes(), Function.identity());
185186
/*
186187
* We can canonicalize the instances to reduce space required in the cache. There are
187188
* only a small number of possible instances of PartialEvaluationMethodInfo as it just
@@ -206,7 +207,7 @@ protected Object createKey(ResolvedJavaField field) {
206207
@Override
207208
protected ConstantFieldInfo computeValue(ResolvedJavaField field) {
208209
Map<ResolvedJavaType, AnnotationValue> declaredAnnotationValues = AnnotationValueSupport.getDeclaredAnnotationValues(field);
209-
return computeConstantFieldInfo(field, declaredAnnotationValues, getTypes());
210+
return computeConstantFieldInfo(field, declaredAnnotationValues, getTypes(), Function.identity());
210211
}
211212
}
212213
}

substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationFeature.java

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import static jdk.graal.compiler.java.BytecodeParserOptions.InlineDuringParsingMaxDepth;
3232

3333
import java.lang.reflect.Executable;
34+
import java.util.ArrayList;
3435
import java.util.Arrays;
3536
import java.util.Collection;
3637
import java.util.List;
@@ -236,6 +237,7 @@ enum InlineDecision {
236237
private Function<ConstantFieldProvider, ConstantFieldProvider> constantFieldProviderWrapper = Function.identity();
237238
private Consumer<CallTreeInfo> blocklistChecker = _ -> {
238239
};
240+
private List<Runnable> afterInstallRuntimeConfig;
239241

240242
public HostedProviders getHostedProviders() {
241243
return hostedProviders;
@@ -249,6 +251,27 @@ public void setUniverseFactory(SubstrateUniverseFactory universeFactory) {
249251
this.universeFactory = universeFactory;
250252
}
251253

254+
/**
255+
* Registers a {@code callback} to be invoked after
256+
* {@link #beforeAnalysis(BeforeAnalysisAccess)} completes the
257+
* {@link #installRuntimeConfig(BeforeAnalysisAccessImpl) runtime configuration setup}.
258+
*
259+
* <p>
260+
* This hook is used by {@code TruffleFeature} to initialize {@code KnownTruffleTypes}, which
261+
* are required by {@code SubstrateTruffleUniverseFactory}. The {@code KnownTruffleTypes} must
262+
* be initialized after {@link #installRuntimeConfig(BeforeAnalysisAccessImpl)} has executed,
263+
* but before the remaining logic in {@link #beforeAnalysis(BeforeAnalysisAccess)}, since that
264+
* phase already relies on {@link SubstrateUniverseFactory} to create {@link SubstrateMethod}
265+
* instances.
266+
* </p>
267+
*/
268+
public synchronized void addAfterInstallRuntimeConfigCallback(Runnable callback) {
269+
if (afterInstallRuntimeConfig == null) {
270+
afterInstallRuntimeConfig = new ArrayList<>();
271+
}
272+
afterInstallRuntimeConfig.add(callback);
273+
}
274+
252275
@SuppressWarnings("unused")
253276
private static boolean defaultAllowRuntimeCompilation(ResolvedJavaMethod method) {
254277
return false;
@@ -432,6 +455,18 @@ public void beforeAnalysis(BeforeAnalysisAccess c) {
432455
BeforeAnalysisAccessImpl config = (BeforeAnalysisAccessImpl) c;
433456
installRuntimeConfig(config);
434457

458+
List<Runnable> callbacks;
459+
synchronized (this) {
460+
if (afterInstallRuntimeConfig != null) {
461+
callbacks = List.copyOf(afterInstallRuntimeConfig);
462+
} else {
463+
callbacks = List.of();
464+
}
465+
}
466+
for (Runnable callback : callbacks) {
467+
callback.run();
468+
}
469+
435470
SubstrateGraalRuntime graalRuntime = new SubstrateGraalRuntime();
436471
objectReplacer.setGraalRuntime(graalRuntime);
437472
objectReplacer.setAnalysisAccess(config);

substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleFeature.java

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -136,11 +136,13 @@
136136
import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl;
137137
import com.oracle.svm.hosted.meta.HostedType;
138138
import com.oracle.svm.hosted.substitute.DeletedElementException;
139+
import com.oracle.svm.graal.TruffleRuntimeCompilationSupport;
139140
import com.oracle.svm.truffle.api.SubstrateThreadLocalHandshake;
140141
import com.oracle.svm.truffle.api.SubstrateThreadLocalHandshakeSnippets;
141142
import com.oracle.svm.truffle.api.SubstrateTruffleCompiler;
142143
import com.oracle.svm.truffle.api.SubstrateTruffleRuntime;
143144
import com.oracle.svm.truffle.api.SubstrateTruffleUniverseFactory;
145+
import com.oracle.svm.truffle.api.SubstrateKnownTruffleTypes;
144146
import com.oracle.svm.util.AnnotationUtil;
145147
import com.oracle.svm.util.LogUtils;
146148
import com.oracle.svm.util.ReflectionUtil;
@@ -233,6 +235,14 @@ public boolean getAsBoolean() {
233235
private final Set<ResolvedJavaMethod> warnMethods;
234236
private final Set<Pair<ResolvedJavaMethod, String>> neverPartOfCompilationViolations;
235237
Set<AnalysisMethod> runtimeCompiledMethods;
238+
/**
239+
* Holds the {@link KnownTruffleTypes} instance, which is initialized lazily after
240+
* {@link RuntimeCompilationFeature#beforeAnalysis(BeforeAnalysisAccess)} completes runtime
241+
* configuration setup.
242+
*
243+
* @see RuntimeCompilationFeature#addAfterInstallRuntimeConfigCallback(Runnable)
244+
*/
245+
private volatile KnownTruffleTypes types;
236246

237247
public TruffleFeature() {
238248
blocklistMethods = new HashSet<>();
@@ -241,6 +251,10 @@ public TruffleFeature() {
241251
neverPartOfCompilationViolations = ConcurrentHashMap.newKeySet();
242252
}
243253

254+
public KnownTruffleTypes getTypes() {
255+
return types;
256+
}
257+
244258
@Override
245259
public void registerForeignCalls(SubstrateForeignCallsProvider foreignCalls) {
246260
foreignCalls.register(SubstrateThreadLocalHandshake.FOREIGN_POLL);
@@ -290,6 +304,12 @@ public void afterRegistration(AfterRegistrationAccess access) {
290304
UserError.guarantee(runtime instanceof SubstrateTruffleRuntime, "TruffleFeature requires SubstrateTruffleRuntime");
291305
SubstrateTruffleRuntime truffleRuntime = (SubstrateTruffleRuntime) Truffle.getRuntime();
292306
truffleRuntime.resetHosted();
307+
RuntimeCompilationFeature runtimeCompilationFeature = RuntimeCompilationFeature.singleton();
308+
runtimeCompilationFeature.addAfterInstallRuntimeConfigCallback(() -> {
309+
Providers providers = TruffleRuntimeCompilationSupport.getRuntimeConfig().getProviders();
310+
types = new SubstrateKnownTruffleTypes(truffleRuntime, providers.getMetaAccess(), providers.getConstantReflection());
311+
});
312+
runtimeCompilationFeature.setUniverseFactory(new SubstrateTruffleUniverseFactory(truffleRuntime, this));
293313
}
294314

295315
@Override
@@ -382,10 +402,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
382402
truffleRuntime.initializeHostedKnownMethods(config.getUniverse().getOriginalMetaAccess());
383403

384404
PartialEvaluator partialEvaluator = truffleCompiler.getPartialEvaluator();
385-
KnownTruffleTypes types = partialEvaluator.getTypes();
386405
registerKnownTruffleFields(config, types);
387-
388-
runtimeCompilationFeature.setUniverseFactory(new SubstrateTruffleUniverseFactory(truffleRuntime, types));
389406
GraphBuilderConfiguration graphBuilderConfig = partialEvaluator.getGraphBuilderConfigPrototype();
390407

391408
TruffleAllowInliningPredicate allowInliningPredicate = new TruffleAllowInliningPredicate(runtimeCompilationFeature.getHostedProviders().getReplacements(),

substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleSupport.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
import java.util.function.Consumer;
2929
import java.util.function.Supplier;
3030

31+
import jdk.graal.compiler.truffle.KnownTruffleTypes;
3132
import org.graalvm.nativeimage.ImageSingletons;
3233

3334
import com.oracle.svm.core.SubstrateOptions;
@@ -36,7 +37,6 @@
3637
import com.oracle.svm.core.meta.SubstrateObjectConstant;
3738
import com.oracle.svm.graal.TruffleRuntimeCompilationSupport;
3839
import com.oracle.svm.graal.hosted.runtimecompilation.RuntimeCompilationFeature;
39-
import com.oracle.svm.truffle.api.SubstrateKnownTruffleTypes;
4040
import com.oracle.svm.truffle.api.SubstrateOptimizedCallTarget;
4141
import com.oracle.svm.truffle.api.SubstrateOptimizedCallTargetInstalledCode;
4242
import com.oracle.svm.truffle.api.SubstratePartialEvaluator;
@@ -57,7 +57,6 @@
5757
import com.oracle.truffle.runtime.OptimizedDirectCallNode;
5858

5959
import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
60-
import jdk.graal.compiler.phases.util.Providers;
6160
import jdk.graal.compiler.truffle.EconomyPartialEvaluatorConfiguration;
6261
import jdk.graal.compiler.truffle.PartialEvaluatorConfiguration;
6362
import jdk.graal.compiler.truffle.TruffleCompilerConfiguration;
@@ -107,8 +106,7 @@ protected static TruffleCompilerConfiguration createSubstrateTruffleCompilerConf
107106
final GraphBuilderConfiguration.Plugins graphBuilderPlugins = runtimeCompilationFeature.getHostedProviders().getGraphBuilderPlugins();
108107
SubstrateBackend substrateBackend = TruffleRuntimeCompilationSupport.getRuntimeConfig().getBackendForNormalMethod();
109108
substrateBackend.setRuntimeToRuntimeInvokeMethod(optimizedCallTargetMethod);
110-
Providers providers = TruffleRuntimeCompilationSupport.getRuntimeConfig().getProviders();
111-
SubstrateKnownTruffleTypes types = new SubstrateKnownTruffleTypes(runtime, providers.getMetaAccess(), providers.getConstantReflection());
109+
KnownTruffleTypes types = ImageSingletons.lookup(TruffleFeature.class).getTypes();
112110
final TruffleTierConfiguration firstTier = new TruffleTierConfiguration(new EconomyPartialEvaluatorConfiguration(), substrateBackend,
113111
TruffleRuntimeCompilationSupport.getFirstTierProviders(), TruffleRuntimeCompilationSupport.getFirstTierSuites(), TruffleRuntimeCompilationSupport.getFirstTierLirSuites(),
114112
types);

0 commit comments

Comments
 (0)