From 1ed2a58a20f03bf5f00287386c8d405c90ae267f Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Sat, 16 Sep 2023 23:15:56 +0200 Subject: [PATCH 1/8] Redirect constant pool through the shadow heap. --- .../SnippetReflectionProvider.java | 7 +++ .../oracle/graal/pointsto/ObjectScanner.java | 1 + .../graal/pointsto/heap/ImageHeapScanner.java | 18 ++++---- .../pointsto/infrastructure/Universe.java | 6 ++- .../infrastructure/WrappedConstantPool.java | 14 ++++-- .../graal/pointsto/meta/AnalysisField.java | 2 +- .../graal/pointsto/meta/AnalysisUniverse.java | 9 ++++ .../SharedConstantReflectionProvider.java | 11 +++-- .../hosted/GraalGraphObjectReplacer.java | 4 ++ .../svm/hosted/NativeImageGenerator.java | 23 +++++----- .../AnalysisConstantReflectionProvider.java | 19 ++++++++ .../svm/hosted/c/CGlobalDataFeature.java | 7 ++- .../HostedRuntimeConfigurationBuilder.java | 9 ++-- .../image/NativeImageDebugInfoProvider.java | 38 ++++++++------- .../svm/hosted/image/NativeImageHeap.java | 4 +- .../AnalysisSnippetReflectionProvider.java | 46 +++++++++++++++++++ .../HostedConstantReflectionProvider.java | 10 ++++ .../meta/HostedSnippetReflectionProvider.java | 25 +++++++++- .../svm/hosted/meta/HostedUniverse.java | 10 ++++ ...trinsifyMethodHandlesInvocationPlugin.java | 31 ++++++------- 20 files changed, 221 insertions(+), 73 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/AnalysisSnippetReflectionProvider.java diff --git a/compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java b/compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java index 3051888f0af0..cdd4b4023b90 100644 --- a/compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java +++ b/compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java @@ -64,6 +64,13 @@ public interface SnippetReflectionProvider { */ T asObject(Class type, JavaConstant constant); + /** + * Get the wrapped constant object, if any. + */ + default JavaConstant unwrapConstant(JavaConstant constant) { + return constant; + } + /** * Creates a boxed constant for the given kind from an Object. The object needs to be of the * Java boxed type corresponding to the kind. diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java index e1ae398c1126..137038c3e15c 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java @@ -497,6 +497,7 @@ public String toString(BigBang bb) { } public static class OtherReason extends ScanReason { + public static final ScanReason UNKNOWN = new OtherReason("manually created constant"); public static final ScanReason RESCAN = new OtherReason("manually triggered rescan"); public static final ScanReason HUB = new OtherReason("scanning a class constant"); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java index 49b69ad2559c..ac9bc05140cb 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java @@ -49,7 +49,6 @@ import com.oracle.graal.pointsto.api.HostVM; import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException; import com.oracle.graal.pointsto.heap.value.ValueSupplier; -import com.oracle.graal.pointsto.infrastructure.UniverseMetaAccess; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; import com.oracle.graal.pointsto.meta.AnalysisType; @@ -196,9 +195,6 @@ protected ImageHeapConstant getOrCreateImageHeapConstant(JavaConstant javaConsta ScanReason nonNullReason = Objects.requireNonNull(reason); Object existingTask = imageHeap.getSnapshot(javaConstant); if (existingTask == null) { - if (universe.sealed()) { - throw AnalysisError.shouldNotReachHere("Universe is sealed. New constant reachable: " + javaConstant.toValueString()); - } AnalysisFuture newTask = new AnalysisFuture<>(() -> { ImageHeapConstant imageHeapConstant = createImageHeapObject(javaConstant, nonNullReason); /* When the image heap object is created replace the future in the map. */ @@ -434,11 +430,12 @@ private void notifyAnalysis(ImageHeapArray array, AnalysisType arrayType, int el } private boolean isNonNullObjectConstant(JavaConstant constant) { - return constant.getJavaKind() == JavaKind.Object && constant.isNonNull() && !isWordType(constant, metaAccess); + return constant.getJavaKind() == JavaKind.Object && constant.isNonNull() && !isWordType(constant); } - public static boolean isWordType(JavaConstant rawElementValue, UniverseMetaAccess metaAccess) { - return metaAccess.isInstanceOf(rawElementValue, WordBase.class); + public boolean isWordType(JavaConstant rawElementValue) { + Object obj = snippetReflection.asObject(Object.class, rawElementValue); + return obj instanceof WordBase; } private boolean notifyAnalysis(JavaConstant array, AnalysisType arrayType, JavaConstant elementValue, int elementIndex, ScanReason reason) { @@ -446,7 +443,7 @@ private boolean notifyAnalysis(JavaConstant array, AnalysisType arrayType, JavaC if (elementValue.isNull()) { analysisModified = scanningObserver.forNullArrayElement(array, arrayType, elementIndex, reason); } else { - if (isWordType(elementValue, metaAccess)) { + if (isWordType(elementValue)) { return false; } AnalysisType elementType = metaAccess.lookupJavaType(elementValue); @@ -682,7 +679,10 @@ protected Object asObject(JavaConstant constant) { } public JavaConstant asConstant(Object object) { - return snippetReflection.forObject(object); + if (object instanceof ImageHeapConstant constant) { + return constant; + } + return universe.getSnippetReflection().forObject(object); } public void cleanupAfterAnalysis() { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/Universe.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/Universe.java index 33c51291532e..4658bbd91fef 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/Universe.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/Universe.java @@ -24,9 +24,10 @@ */ package com.oracle.graal.pointsto.infrastructure; -import com.oracle.graal.pointsto.api.HostVM; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; +import com.oracle.graal.pointsto.api.HostVM; + import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaField; @@ -61,6 +62,9 @@ public interface Universe { JavaConstant lookup(JavaConstant constant); + /** Redirect constant lookup through the shadow heap. */ + JavaConstant shadowHeapLookup(JavaConstant constant); + ResolvedJavaMethod resolveSubstitution(ResolvedJavaMethod method); ResolvedJavaType objectType(); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedConstantPool.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedConstantPool.java index a739b3d49004..d7005e3c7af5 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedConstantPool.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedConstantPool.java @@ -33,6 +33,7 @@ import org.graalvm.compiler.core.common.BootstrapMethodIntrospection; import org.graalvm.compiler.debug.GraalError; +import org.graalvm.compiler.serviceprovider.GraalServices; import com.oracle.graal.pointsto.constraints.UnresolvedElementException; import com.oracle.svm.util.ReflectionUtil; @@ -44,7 +45,6 @@ import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; -import org.graalvm.compiler.serviceprovider.GraalServices; public class WrappedConstantPool implements ConstantPool, ConstantPoolPatch { @@ -63,6 +63,10 @@ public int length() { return wrapped.length(); } + private JavaConstant lookupConstant(JavaConstant constant) { + return universe.shadowHeapLookup(constant); + } + /** * The method jdk.vm.ci.meta.ConstantPool#lookupBootstrapMethodInvocation(int cpi, int opcode) * was introduced in JVMCI 22.1. @@ -155,7 +159,7 @@ public WrappedSignature lookupSignature(int cpi) { @Override public JavaConstant lookupAppendix(int cpi, int opcode) { - return universe.lookup(wrapped.lookupAppendix(cpi, opcode)); + return lookupConstant(wrapped.lookupAppendix(cpi, opcode)); } @Override @@ -179,7 +183,7 @@ public Object lookupConstant(int cpi, boolean resolve) { return con; } } else if (con instanceof JavaConstant) { - return universe.lookup((JavaConstant) con); + return lookupConstant((JavaConstant) con); } else if (con == null && resolve == false) { return null; } else { @@ -251,7 +255,7 @@ public String getName() { public JavaConstant getType() { if (bsmGetType != null) { try { - return universe.lookup((JavaConstant) bsmGetType.invoke(wrapped)); + return lookupConstant((JavaConstant) bsmGetType.invoke(wrapped)); } catch (Throwable t) { throw GraalError.shouldNotReachHere(t); // ExcludeFromJacocoGeneratedReport } @@ -264,7 +268,7 @@ public List getStaticArguments() { if (bsmGetStaticArguments != null) { try { List original = (List) bsmGetStaticArguments.invoke(wrapped); - return original.stream().map(e -> universe.lookup((JavaConstant) e)).collect(Collectors.toList()); + return original.stream().map(e -> lookupConstant((JavaConstant) e)).collect(Collectors.toList()); } catch (Throwable t) { throw GraalError.shouldNotReachHere(t); // ExcludeFromJacocoGeneratedReport } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisField.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisField.java index 6d0e783cfea8..5227392105bc 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisField.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisField.java @@ -537,7 +537,7 @@ public Field getJavaField() { @Override public JavaConstant getConstantValue() { - return getUniverse().lookup(getWrapped().getConstantValue()); + return getUniverse().shadowHeapLookup(getWrapped().getConstantValue()); } public void addAnalysisFieldObserver(AnalysisFieldObserver observer) { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java index 405711c47a72..18e4a91a51e8 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java @@ -45,6 +45,7 @@ import com.oracle.graal.pointsto.AnalysisPolicy; import com.oracle.graal.pointsto.BigBang; +import com.oracle.graal.pointsto.ObjectScanner; import com.oracle.graal.pointsto.api.HostVM; import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException; import com.oracle.graal.pointsto.heap.HeapSnapshotVerifier; @@ -516,6 +517,14 @@ public JavaConstant lookup(JavaConstant constant) { } } + @Override + public JavaConstant shadowHeapLookup(JavaConstant constant) { + if (constant == null || constant.isNull() || constant.getJavaKind().isPrimitive()) { + return constant; + } + return heapScanner.createImageHeapConstant(lookup(constant), ObjectScanner.OtherReason.UNKNOWN); + } + public JavaConstant toHosted(JavaConstant constant) { if (constant == null) { return null; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SharedConstantReflectionProvider.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SharedConstantReflectionProvider.java index 699dfd67bec2..2d4288ad4899 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SharedConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SharedConstantReflectionProvider.java @@ -75,7 +75,7 @@ public JavaConstant readArrayElement(JavaConstant array, int index) { if (a instanceof Object[]) { Object element = ((Object[]) a)[index]; - return SubstrateObjectConstant.forObject(element); + return forObject(element); } else { return JavaConstant.forBoxedPrimitive(Array.get(a, index)); } @@ -92,10 +92,9 @@ public void forEachArrayElement(JavaConstant array, ObjIntConsumer return; } - if (obj instanceof Object[]) { - Object[] a = (Object[]) obj; + if (obj instanceof Object[] a) { for (int index = 0; index < a.length; index++) { - consumer.accept((SubstrateObjectConstant.forObject(a[index])), index); + consumer.accept((forObject(a[index])), index); } } else { for (int index = 0; index < Array.getLength(obj); index++) { @@ -128,6 +127,10 @@ public JavaConstant forString(String value) { return SubstrateObjectConstant.forObject(value); } + protected JavaConstant forObject(Object object) { + return SubstrateObjectConstant.forObject(object); + } + @Override public MethodHandleAccessProvider getMethodHandleAccess() { throw shouldNotReachHereAtRuntime(); // ExcludeFromJacocoGeneratedReport diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalGraphObjectReplacer.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalGraphObjectReplacer.java index 5a5d2d8c5a69..8a340276fcbb 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalGraphObjectReplacer.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalGraphObjectReplacer.java @@ -44,6 +44,7 @@ import org.graalvm.nativeimage.hosted.Feature.BeforeHeapLayoutAccess; import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException; +import com.oracle.graal.pointsto.heap.ImageHeapConstant; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisType; @@ -195,6 +196,9 @@ public Object apply(Object source) { dest = createType((ResolvedJavaType) source); } else if (source instanceof FieldLocationIdentity && !(source instanceof SubstrateFieldLocationIdentity)) { dest = createFieldLocationIdentity((FieldLocationIdentity) source); + } else if (source instanceof ImageHeapConstant heapConstant) { + dest = heapConstant.getHostedObject(); + assert dest != null; } assert dest != null; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 27b8860661cb..a8928f7f8f45 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -203,7 +203,6 @@ import com.oracle.svm.core.graal.meta.SubstrateForeignCallsProvider; import com.oracle.svm.core.graal.meta.SubstrateLoweringProvider; import com.oracle.svm.core.graal.meta.SubstrateReplacements; -import com.oracle.svm.core.graal.meta.SubstrateSnippetReflectionProvider; import com.oracle.svm.core.graal.meta.SubstrateStampProvider; import com.oracle.svm.core.graal.phases.CollectDeoptimizationSourcePositionsPhase; import com.oracle.svm.core.graal.phases.DeadStoreRemovalPhase; @@ -284,6 +283,7 @@ import com.oracle.svm.hosted.image.NativeImageCodeCacheFactory; import com.oracle.svm.hosted.image.NativeImageHeap; import com.oracle.svm.hosted.jdk.localization.LocalizationFeature; +import com.oracle.svm.hosted.meta.AnalysisSnippetReflectionProvider; import com.oracle.svm.hosted.meta.HostedConstantReflectionProvider; import com.oracle.svm.hosted.meta.HostedField; import com.oracle.svm.hosted.meta.HostedInterface; @@ -614,8 +614,8 @@ protected void doRun(Map entryPoints, BuildPhaseProvider.markHostedUniverseBuilt(); ClassInitializationSupport classInitializationSupport = bb.getHostVM().getClassInitializationSupport(); SubstratePlatformConfigurationProvider platformConfig = getPlatformConfig(hMetaAccess); - runtimeConfiguration = new HostedRuntimeConfigurationBuilder(options, bb.getHostVM(), hUniverse, hMetaAccess, bb.getProviders(MultiMethod.ORIGINAL_METHOD), classInitializationSupport, - GraalAccess.getOriginalProviders().getLoopsDataProvider(), platformConfig).build(); + runtimeConfiguration = new HostedRuntimeConfigurationBuilder(options, aUniverse.getHeapScanner(), bb.getHostVM(), hUniverse, hMetaAccess, bb.getProviders(MultiMethod.ORIGINAL_METHOD), + classInitializationSupport, GraalAccess.getOriginalProviders().getLoopsDataProvider(), platformConfig).build(); registerGraphBuilderPlugins(featureHandler, runtimeConfiguration, (HostedProviders) runtimeConfiguration.getProviders(), bb.getMetaAccess(), aUniverse, hMetaAccess, hUniverse, @@ -937,6 +937,7 @@ protected void setupNativeImage(OptionValues options, Map feature.registerGraphBuilderPlugins(providers, plugins, reason)); - HostedSnippetReflectionProvider hostedSnippetReflection = new HostedSnippetReflectionProvider(new SubstrateWordTypes(aMetaAccess, FrameAccess.getWordKind())); - NodeIntrinsificationProvider nodeIntrinsificationProvider; if (SubstrateUtil.isBuildingLibgraal()) { HotSpotGraalCompiler compiler = (HotSpotGraalCompiler) HotSpotJVMCIRuntime.runtime().getCompiler(); @@ -1382,7 +1383,7 @@ public T getInjectedArgument(Class type) { } final boolean useExactMathPlugins = SubstrateOptions.useLIRBackend(); - registerInvocationPlugins(providers.getSnippetReflection(), plugins.getInvocationPlugins(), replacements, + registerInvocationPlugins(hostedSnippetReflection, plugins.getInvocationPlugins(), replacements, useExactMathPlugins, true, supportsStubBasedPlugins, providers.getLowerer()); Architecture architecture = ConfigurationValues.getTarget().arch; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java index bc9188cfb1e6..7f4e2fd08d66 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java @@ -34,6 +34,7 @@ import org.graalvm.nativeimage.Platforms; import org.graalvm.word.WordBase; +import com.oracle.graal.pointsto.ObjectScanner; import com.oracle.graal.pointsto.heap.ImageHeapArray; import com.oracle.graal.pointsto.heap.ImageHeapConstant; import com.oracle.graal.pointsto.heap.ImageHeapInstance; @@ -366,6 +367,24 @@ public JavaConstant asJavaClass(ResolvedJavaType type) { return SubstrateObjectConstant.forObject(getHostVM().dynamicHub(type)); } + @Override + public JavaConstant forString(String value) { + if (value == null) { + return JavaConstant.NULL_POINTER; + } + return universe.getHeapScanner().createImageHeapConstant(super.forString(value), ObjectScanner.OtherReason.UNKNOWN); + } + + @Override + public JavaConstant forObject(Object object) { + if (object instanceof ImageHeapConstant heapConstant) { + /* This could be a simulated constant. */ + return heapConstant; + } + /* Redirect constant lookup through the shadow heap. */ + return universe.getHeapScanner().createImageHeapConstant(super.forObject(object), ObjectScanner.OtherReason.UNKNOWN); + } + private SVMHost getHostVM() { return (SVMHost) universe.hostVM(); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CGlobalDataFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CGlobalDataFeature.java index 17cc37f006a3..f6ca7ac35065 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CGlobalDataFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/c/CGlobalDataFeature.java @@ -80,8 +80,8 @@ import com.oracle.svm.core.graal.code.CGlobalDataInfo; import com.oracle.svm.core.graal.nodes.CGlobalDataLoadAddressNode; import com.oracle.svm.core.util.VMError; -import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl; import com.oracle.svm.hosted.image.RelocatableBuffer; +import com.oracle.svm.hosted.meta.HostedSnippetReflectionProvider; import com.oracle.svm.util.ReflectionUtil; import jdk.vm.ci.meta.JavaConstant; @@ -96,7 +96,6 @@ public class CGlobalDataFeature implements InternalFeature { private final Field isSymbolReferenceField = ReflectionUtil.lookupField(CGlobalDataInfo.class, "isSymbolReference"); private final CGlobalDataNonConstantRegistry nonConstantRegistry = new CGlobalDataNonConstantRegistry(); - private JavaConstant nonConstantRegistryJavaConstant; private final Map, CGlobalDataInfo> map = new ConcurrentHashMap<>(); private CGlobalDataInfo cGlobalDataBaseAddress; @@ -112,10 +111,8 @@ private boolean isLayouted() { @Override public void duringSetup(DuringSetupAccess a) { - DuringSetupAccessImpl access = (DuringSetupAccessImpl) a; a.registerObjectReplacer(this::replaceObject); cGlobalDataBaseAddress = registerAsAccessedOrGet(CGlobalDataInfo.CGLOBALDATA_RUNTIME_BASE_ADDRESS); - nonConstantRegistryJavaConstant = access.getMetaAccess().getUniverse().getSnippetReflection().forObject(nonConstantRegistry); } @Override @@ -129,6 +126,8 @@ public void registerInvocationPlugins(Providers providers, SnippetReflectionProv r.register(new RequiredInvocationPlugin("get", Receiver.class) { @Override public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver receiver) { + assert snippetReflection instanceof HostedSnippetReflectionProvider; + JavaConstant nonConstantRegistryJavaConstant = snippetReflection.forObject(nonConstantRegistry); ValueNode cGlobalDataNode = receiver.get(); if (cGlobalDataNode.isConstant()) { CGlobalDataImpl data = providers.getSnippetReflection().asObject(CGlobalDataImpl.class, cGlobalDataNode.asJavaConstant()); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java index 023d779faef9..ab8c85d4c6a4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedRuntimeConfigurationBuilder.java @@ -39,6 +39,7 @@ import org.graalvm.compiler.phases.util.Providers; import org.graalvm.compiler.word.WordTypes; +import com.oracle.graal.pointsto.heap.ImageHeapScanner; import com.oracle.graal.pointsto.meta.HostedProviders; import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.graal.code.SubstrateBackendFactory; @@ -61,13 +62,15 @@ public class HostedRuntimeConfigurationBuilder extends SharedRuntimeConfiguratio private final HostedUniverse universe; private final HostedProviders analysisProviders; + private final ImageHeapScanner heapScanner; - public HostedRuntimeConfigurationBuilder(OptionValues options, SVMHost hostVM, HostedUniverse universe, HostedMetaAccess metaAccess, HostedProviders analysisProviders, - ClassInitializationSupport classInitializationSupport, LoopsDataProvider originalLoopsDataProvider, + public HostedRuntimeConfigurationBuilder(OptionValues options, ImageHeapScanner heapScanner, SVMHost hostVM, HostedUniverse universe, HostedMetaAccess metaAccess, + HostedProviders analysisProviders, ClassInitializationSupport classInitializationSupport, LoopsDataProvider originalLoopsDataProvider, SubstratePlatformConfigurationProvider platformConfig) { super(options, hostVM, metaAccess, SubstrateBackendFactory.get()::newBackend, classInitializationSupport, originalLoopsDataProvider, platformConfig); this.universe = universe; this.analysisProviders = analysisProviders; + this.heapScanner = heapScanner; } @Override @@ -95,7 +98,7 @@ protected LoweringProvider createLoweringProvider(ForeignCallsProvider foreignCa @Override protected SnippetReflectionProvider createSnippetReflectionProvider(WordTypes wordTypes) { - return new HostedSnippetReflectionProvider(wordTypes); + return new HostedSnippetReflectionProvider(heapScanner, wordTypes); } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoProvider.java index e85a04c7ceda..eb564533f932 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageDebugInfoProvider.java @@ -42,23 +42,14 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import com.oracle.svm.hosted.c.NativeLibraries; -import com.oracle.svm.hosted.c.info.AccessorInfo; -import com.oracle.svm.hosted.c.info.ElementInfo; -import com.oracle.svm.hosted.c.info.PointerToInfo; -import com.oracle.svm.hosted.c.info.PropertyInfo; -import com.oracle.svm.hosted.c.info.RawStructureInfo; -import com.oracle.svm.hosted.c.info.SizableInfo; -import com.oracle.svm.hosted.c.info.SizableInfo.ElementKind; -import com.oracle.svm.hosted.c.info.StructFieldInfo; -import com.oracle.svm.hosted.c.info.StructInfo; -import com.oracle.svm.util.ClassUtil; import org.graalvm.collections.EconomicMap; import org.graalvm.compiler.code.CompilationResult; import org.graalvm.compiler.debug.DebugContext; import org.graalvm.compiler.graph.NodeSourcePosition; import org.graalvm.compiler.java.StableMethodNameFormatter; import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.c.struct.CPointerTo; +import org.graalvm.nativeimage.c.struct.RawPointerTo; import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider; import com.oracle.graal.pointsto.infrastructure.WrappedJavaMethod; @@ -75,6 +66,16 @@ import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.graal.code.SubstrateBackend.SubstrateMarkId; import com.oracle.svm.core.image.ImageHeapPartition; +import com.oracle.svm.hosted.c.NativeLibraries; +import com.oracle.svm.hosted.c.info.AccessorInfo; +import com.oracle.svm.hosted.c.info.ElementInfo; +import com.oracle.svm.hosted.c.info.PointerToInfo; +import com.oracle.svm.hosted.c.info.PropertyInfo; +import com.oracle.svm.hosted.c.info.RawStructureInfo; +import com.oracle.svm.hosted.c.info.SizableInfo; +import com.oracle.svm.hosted.c.info.SizableInfo.ElementKind; +import com.oracle.svm.hosted.c.info.StructFieldInfo; +import com.oracle.svm.hosted.c.info.StructInfo; import com.oracle.svm.hosted.image.NativeImageHeap.ObjectInfo; import com.oracle.svm.hosted.image.sources.SourceManager; import com.oracle.svm.hosted.meta.HostedArrayClass; @@ -88,6 +89,7 @@ import com.oracle.svm.hosted.meta.HostedType; import com.oracle.svm.hosted.substitute.SubstitutionField; import com.oracle.svm.hosted.substitute.SubstitutionMethod; +import com.oracle.svm.util.ClassUtil; import jdk.vm.ci.aarch64.AArch64; import jdk.vm.ci.amd64.AMD64; @@ -109,8 +111,6 @@ import jdk.vm.ci.meta.ResolvedJavaType; import jdk.vm.ci.meta.Signature; import jdk.vm.ci.meta.Value; -import org.graalvm.nativeimage.c.struct.CPointerTo; -import org.graalvm.nativeimage.c.struct.RawPointerTo; /** * Implementation of the DebugInfoProvider API interface that allows type, code and heap data info @@ -266,9 +266,15 @@ public String typeName() { @Override public long classOffset() { - ObjectInfo objectInfo = heap.getObjectInfo(hostedType.getHub()); - if (objectInfo != null) { - return objectInfo.getOffset(); + /* + * Only query the heap for reachable types. These are guaranteed to have been seen by + * the analysis and to exist in the shadow heap. + */ + if (hostedType.getWrapped().isReachable()) { + ObjectInfo objectInfo = heap.getObjectInfo(hostedType.getHub()); + if (objectInfo != null) { + return objectInfo.getOffset(); + } } return -1; } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java index ba2ae42db12d..4428bafee1fe 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java @@ -161,7 +161,9 @@ public int getObjectCount() { } public ObjectInfo getObjectInfo(Object obj) { - return objects.get(hUniverse.getSnippetReflection().forObject(obj)); + JavaConstant constant = hUniverse.getSnippetReflection().forObject(obj); + /* Must unwrap since objects use the SubstrateObjectConstant hosted objects as keys. */ + return objects.get(maybeUnwrap(constant)); } public ObjectInfo getConstantInfo(JavaConstant constant) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/AnalysisSnippetReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/AnalysisSnippetReflectionProvider.java new file mode 100644 index 000000000000..f39df6306028 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/AnalysisSnippetReflectionProvider.java @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.hosted.meta; + +import org.graalvm.compiler.word.WordTypes; + +import com.oracle.graal.pointsto.heap.ImageHeapConstant; +import com.oracle.svm.core.graal.meta.SubstrateSnippetReflectionProvider; +import com.oracle.svm.core.util.VMError; + +import jdk.vm.ci.meta.JavaConstant; + +public class AnalysisSnippetReflectionProvider extends SubstrateSnippetReflectionProvider { + + public AnalysisSnippetReflectionProvider(WordTypes wordTypes) { + super(wordTypes); + } + + @Override + public JavaConstant forObject(Object object) { + VMError.guarantee(!(object instanceof ImageHeapConstant)); + return super.forObject(object); + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantReflectionProvider.java index 7774fd048b9c..f47cf783274a 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantReflectionProvider.java @@ -111,6 +111,16 @@ public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receive return hUniverse.lookup(aConstantReflection.readValue(hMetaAccess, hField.getWrapped(), receiver, true)); } + @Override + public JavaConstant forString(String value) { + return aConstantReflection.forString(value); + } + + @Override + protected JavaConstant forObject(Object object) { + return aConstantReflection.forObject(object); + } + private boolean checkHub(JavaConstant constant) { if (hMetaAccess.isInstanceOf(constant, Class.class)) { Object classObject = hUniverse.getSnippetReflection().asObject(Object.class, constant); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedSnippetReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedSnippetReflectionProvider.java index efe821101390..20d7d80c19ae 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedSnippetReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedSnippetReflectionProvider.java @@ -28,7 +28,9 @@ import org.graalvm.nativeimage.c.function.RelocatedPointer; import org.graalvm.word.WordBase; +import com.oracle.graal.pointsto.ObjectScanner.OtherReason; import com.oracle.graal.pointsto.heap.ImageHeapConstant; +import com.oracle.graal.pointsto.heap.ImageHeapScanner; import com.oracle.svm.core.FrameAccess; import com.oracle.svm.core.graal.meta.SubstrateSnippetReflectionProvider; import com.oracle.svm.core.hub.DynamicHub; @@ -37,9 +39,15 @@ import jdk.vm.ci.meta.JavaConstant; public class HostedSnippetReflectionProvider extends SubstrateSnippetReflectionProvider { + private ImageHeapScanner heapScanner; - public HostedSnippetReflectionProvider(WordTypes wordTypes) { + public HostedSnippetReflectionProvider(ImageHeapScanner heapScanner, WordTypes wordTypes) { super(wordTypes); + this.heapScanner = heapScanner; + } + + public void setHeapScanner(ImageHeapScanner heapScanner) { + this.heapScanner = heapScanner; } @Override @@ -48,7 +56,20 @@ public JavaConstant forObject(Object object) { /* Relocated pointers are subject to relocation, so we don't know their value yet. */ return JavaConstant.forIntegerKind(FrameAccess.getWordKind(), word.rawValue()); } - return super.forObject(object); + if (object instanceof ImageHeapConstant heapConstant) { + /* This could be a simulated constant. */ + return heapConstant; + } + /* Redirect constant lookup through the shadow heap. */ + return heapScanner.createImageHeapConstant(super.forObject(object), OtherReason.UNKNOWN); + } + + @Override + public JavaConstant unwrapConstant(JavaConstant constant) { + if (constant instanceof ImageHeapConstant heapConstant && heapConstant.getHostedObject() != null) { + return heapConstant.getHostedObject(); + } + return constant; } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedUniverse.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedUniverse.java index e940c2b73cf0..f1a3d8e8b1a5 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedUniverse.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedUniverse.java @@ -45,6 +45,7 @@ import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.PointsToAnalysis; import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException; +import com.oracle.graal.pointsto.heap.ImageHeapConstant; import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider; import com.oracle.graal.pointsto.infrastructure.OriginalFieldProvider; import com.oracle.graal.pointsto.infrastructure.OriginalMethodProvider; @@ -441,6 +442,15 @@ public JavaConstant lookup(JavaConstant constant) { return constant; } + @Override + public JavaConstant shadowHeapLookup(JavaConstant constant) { + if (constant == null || constant.isNull() || constant.getJavaKind().isPrimitive()) { + return constant; + } + VMError.guarantee(constant instanceof ImageHeapConstant); + return constant; + } + public Collection getTypes() { return orderedTypes; } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java index dd9abef15a8c..366015f23f7b 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java @@ -124,6 +124,7 @@ import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.meta.HostedMethod; +import com.oracle.svm.hosted.meta.HostedSnippetReflectionProvider; import com.oracle.svm.hosted.meta.HostedType; import com.oracle.svm.hosted.meta.HostedUniverse; import com.oracle.svm.hosted.snippets.IntrinsificationPluginRegistry; @@ -201,6 +202,7 @@ public static class IntrinsificationRegistry extends IntrinsificationPluginRegis private final HostedProviders universeProviders; private final AnalysisUniverse aUniverse; private final HostedUniverse hUniverse; + private final HostedSnippetReflectionProvider hostedSnippetReflection; private final ClassInitializationPlugin classInitializationPlugin; @@ -209,11 +211,13 @@ public static class IntrinsificationRegistry extends IntrinsificationPluginRegis private final ResolvedJavaType methodHandleType; private final ResolvedJavaType varHandleType; - public IntrinsifyMethodHandlesInvocationPlugin(ParsingReason reason, HostedProviders providers, AnalysisUniverse aUniverse, HostedUniverse hUniverse) { + public IntrinsifyMethodHandlesInvocationPlugin(ParsingReason reason, HostedSnippetReflectionProvider hostedSnippetReflection, HostedProviders providers, AnalysisUniverse aUniverse, + HostedUniverse hUniverse) { this.reason = reason; this.aUniverse = aUniverse; this.hUniverse = hUniverse; this.universeProviders = providers; + this.hostedSnippetReflection = hostedSnippetReflection; Providers originalProviders = GraalAccess.getOriginalProviders(); this.parsingProviders = new Providers(originalProviders).copyWith(new MethodHandlesMetaAccessExtensionProvider()); @@ -337,7 +341,7 @@ private boolean isVarHandleMethod(ResolvedJavaMethod method, ValueNode[] args) { * initialization has happened. We force initialization by invoking the method * VarHandle.vform.getMethodType_V(0). */ - VarHandle varHandle = aUniverse.getSnippetReflection().asObject(VarHandle.class, args[0].asJavaConstant()); + VarHandle varHandle = hostedSnippetReflection.asObject(VarHandle.class, args[0].asJavaConstant()); Object varForm = varHandleVFormField.get(varHandle); varFormInitMethod.invoke(varForm, 0); @@ -980,18 +984,6 @@ private JavaConstant constant(Constant oConstant) throws AbortTransplantExceptio } else { throw bailout(); } - - if (tConstant.getJavaKind() == JavaKind.Object) { - /* - * The object replacer are not invoked when parsing in the HotSpot universe, so we - * also need to do call the replacer here. - */ - Object oldObject = aUniverse.getSnippetReflection().asObject(Object.class, tConstant); - Object newObject = aUniverse.replaceObject(oldObject); - if (newObject != oldObject) { - return aUniverse.getSnippetReflection().forObject(newObject); - } - } return tConstant; } @@ -1058,11 +1050,18 @@ private ResolvedJavaType optionalLookup(ResolvedJavaType type) { } private JavaConstant lookup(JavaConstant constant) { - return aUniverse.lookup(constant); + /* Redirect constant lookup through the shadow heap. */ + return aUniverse.shadowHeapLookup(constant); } private JavaConstant toOriginal(JavaConstant constant) { - return aUniverse.toHosted(constant); + if (constant == null) { + return null; + } else if (constant.getJavaKind().isObject() && !constant.isNull()) { + return GraalAccess.getOriginalSnippetReflection().forObject(hostedSnippetReflection.asObject(Object.class, constant)); + } else { + return constant; + } } private static ResolvedJavaMethod toOriginal(ResolvedJavaMethod method) { From 7863bb3b12ea067494ddf28c111c4a333abfa24f Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Tue, 12 Sep 2023 22:08:46 +0200 Subject: [PATCH 2/8] Unwrap ImageHeapInstance for debug info and reflection metadata. --- .../aarch64/SubstrateAArch64Backend.java | 2 +- .../graal/amd64/SubstrateAMD64Backend.java | 2 +- .../svm/core/graal/llvm/LLVMGenerator.java | 3 +-- .../svm/core/graal/llvm/NodeLLVMBuilder.java | 2 +- .../graal/code/SubstrateDebugInfoBuilder.java | 16 ++++++++++++- .../AnnotationExceptionProxyValue.java | 2 +- .../ReflectionMetadataEncoderImpl.java | 24 ++++++++++++------- 7 files changed, 35 insertions(+), 16 deletions(-) diff --git a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java index b83e518330da..a0231502f65d 100755 --- a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java +++ b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java @@ -693,7 +693,7 @@ public void visitBreakpointNode(BreakpointNode node) { @Override protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeValueMap nodeValueMap) { - return new SubstrateDebugInfoBuilder(graph, gen.getProviders().getMetaAccessExtensionProvider(), nodeValueMap); + return new SubstrateDebugInfoBuilder(graph, getProviders().getSnippetReflection(), gen.getProviders().getMetaAccessExtensionProvider(), nodeValueMap); } private boolean getDestroysCallerSavedRegisters(ResolvedJavaMethod targetMethod) { diff --git a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java index 81874c919158..d2f94b3b13cd 100644 --- a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java +++ b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java @@ -828,7 +828,7 @@ public void visitBreakpointNode(BreakpointNode node) { @Override protected DebugInfoBuilder createDebugInfoBuilder(StructuredGraph graph, NodeValueMap nodeValueMap) { - return new SubstrateDebugInfoBuilder(graph, gen.getProviders().getMetaAccessExtensionProvider(), nodeValueMap); + return new SubstrateDebugInfoBuilder(graph, getProviders().getSnippetReflection(), gen.getProviders().getMetaAccessExtensionProvider(), nodeValueMap); } @Override diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java index ff0c19e25117..eb12bb86a91c 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/LLVMGenerator.java @@ -56,7 +56,6 @@ import org.graalvm.compiler.core.common.memory.BarrierType; import org.graalvm.compiler.core.common.memory.MemoryExtendKind; import org.graalvm.compiler.core.common.memory.MemoryOrderMode; -import org.graalvm.compiler.core.common.spi.CodeGenProviders; import org.graalvm.compiler.core.common.spi.ForeignCallLinkage; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.spi.LIRKindTool; @@ -204,7 +203,7 @@ public BarrierSetLIRGeneratorTool getBarrierSet() { } @Override - public CodeGenProviders getProviders() { + public Providers getProviders() { return providers; } diff --git a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java index 45773b01764c..50779f8117e4 100644 --- a/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java +++ b/substratevm/src/com.oracle.svm.core.graal.llvm/src/com/oracle/svm/core/graal/llvm/NodeLLVMBuilder.java @@ -149,7 +149,7 @@ public class NodeLLVMBuilder implements NodeLIRBuilderTool, SubstrateNodeLIRBuil protected NodeLLVMBuilder(StructuredGraph graph, LLVMGenerator gen) { this.gen = gen; this.builder = gen.getBuilder(); - this.debugInfoBuilder = new SubstrateDebugInfoBuilder(graph, gen.getProviders().getMetaAccessExtensionProvider(), this); + this.debugInfoBuilder = new SubstrateDebugInfoBuilder(graph, gen.getProviders().getSnippetReflection(), gen.getProviders().getMetaAccessExtensionProvider(), this); setCompilationResultMethod(gen.getCompilationResult(), graph); for (HIRBlock block : graph.getLastSchedule().getCFG().getBlocks()) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateDebugInfoBuilder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateDebugInfoBuilder.java index ae706b3c7d98..4207f8050f34 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateDebugInfoBuilder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/code/SubstrateDebugInfoBuilder.java @@ -24,10 +24,12 @@ */ package com.oracle.svm.core.graal.code; +import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.spi.MetaAccessExtensionProvider; import org.graalvm.compiler.core.gen.DebugInfoBuilder; import org.graalvm.compiler.nodes.FrameState; import org.graalvm.compiler.nodes.StructuredGraph; +import org.graalvm.compiler.nodes.ValueNode; import org.graalvm.compiler.nodes.spi.NodeValueMap; import com.oracle.svm.core.meta.SharedMethod; @@ -36,6 +38,7 @@ import jdk.vm.ci.code.StackLockValue; import jdk.vm.ci.code.VirtualObject; +import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.JavaValue; @@ -44,10 +47,12 @@ public final class SubstrateDebugInfoBuilder extends DebugInfoBuilder { private final SharedMethod method; + private final SnippetReflectionProvider snippetReflection; - public SubstrateDebugInfoBuilder(StructuredGraph graph, MetaAccessExtensionProvider metaAccessExtensionProvider, NodeValueMap nodeValueMap) { + public SubstrateDebugInfoBuilder(StructuredGraph graph, SnippetReflectionProvider snippetReflection, MetaAccessExtensionProvider metaAccessExtensionProvider, NodeValueMap nodeValueMap) { super(nodeValueMap, metaAccessExtensionProvider, graph.getDebug()); this.method = (SharedMethod) graph.method(); + this.snippetReflection = snippetReflection; } @Override @@ -55,6 +60,15 @@ protected JavaKind storageKind(JavaType type) { return ((SharedType) type).getStorageKind(); } + @Override + protected JavaValue toJavaValue(ValueNode valueNode) { + JavaValue value = super.toJavaValue(valueNode); + if (value instanceof JavaConstant constant) { + return snippetReflection.unwrapConstant(constant); + } + return value; + } + @Override protected JavaValue computeLockValue(FrameState state, int lockIndex) { JavaValue object = toJavaValue(state.lockAt(lockIndex)); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationExceptionProxyValue.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationExceptionProxyValue.java index 841fd6a5dbec..50c55eb03449 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationExceptionProxyValue.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/annotation/AnnotationExceptionProxyValue.java @@ -63,7 +63,7 @@ public List> getTypes() { @Override public List getExceptionProxies(SnippetReflectionProvider snippetReflection) { if (objectConstant == null) { - objectConstant = snippetReflection.forObject(exceptionProxy); + objectConstant = snippetReflection.unwrapConstant(snippetReflection.forObject(exceptionProxy)); } return Collections.singletonList(objectConstant); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionMetadataEncoderImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionMetadataEncoderImpl.java index c5c24ba5e152..50ef8fc81045 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionMetadataEncoderImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/reflect/ReflectionMetadataEncoderImpl.java @@ -73,6 +73,7 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.impl.RuntimeReflectionSupport; +import com.oracle.graal.pointsto.heap.ImageHeapConstant; import com.oracle.graal.pointsto.infrastructure.WrappedElement; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMethod; @@ -281,8 +282,8 @@ public void addClassMetadata(MetaAccessProvider metaAccess, HostedType type, Cla if (signers != null) { signerConstants = new JavaConstant[signers.length]; for (int i = 0; i < signers.length; ++i) { - signerConstants[i] = snippetReflection.forObject(signers[i]); - encoders.objectConstants.addObject(signerConstants[i]); + signerConstants[i] = snippetReflection.unwrapConstant(snippetReflection.forObject(signers[i])); + addConstantObject(signerConstants[i]); } } AnalysisType analysisType = type.getWrapped(); @@ -292,8 +293,13 @@ public void addClassMetadata(MetaAccessProvider metaAccess, HostedType type, Cla registerClass(type, new ClassMetadata(innerTypes, enclosingMethodInfo, recordComponents, permittedSubtypes, nestMemberTypes, signerConstants, flags, annotations, typeAnnotations)); } + private void addConstantObject(JavaConstant constant) { + assert !(constant instanceof ImageHeapConstant); + encoders.objectConstants.addObject(constant); + } + private void registerError(Throwable error) { - encoders.objectConstants.addObject(snippetReflection.forObject(error)); + addConstantObject(snippetReflection.unwrapConstant(snippetReflection.forObject(error))); } private static final Method getEnclosingMethod0 = ReflectionUtil.lookupMethod(Class.class, "getEnclosingMethod0"); @@ -416,8 +422,8 @@ public void addReflectionExecutableMetadata(MetaAccessProvider metaAccess, Hoste ReflectParameterMetadata[] reflectParameters = registerReflectParameters(reflectMethod); JavaConstant accessorConstant = null; if (accessor != null) { - accessorConstant = snippetReflection.forObject(accessor); - encoders.objectConstants.addObject(accessorConstant); + accessorConstant = snippetReflection.unwrapConstant(snippetReflection.forObject(accessor)); + addConstantObject(accessorConstant); } if (isMethod) { @@ -452,8 +458,8 @@ public void addHeapAccessibleObjectMetadata(MetaAccessProvider metaAccess, Wrapp AnnotationMemberValue annotationDefault = isMethod ? registerAnnotationDefaultValues((AnalysisMethod) analysisObject) : null; ReflectParameterMetadata[] reflectParameters = isExecutable ? registerReflectParameters((Executable) object) : null; AccessibleObject holder = ReflectionMetadataEncoder.getHolder(object); - JavaConstant heapObjectConstant = snippetReflection.forObject(holder); - encoders.objectConstants.addObject(heapObjectConstant); + JavaConstant heapObjectConstant = snippetReflection.unwrapConstant(snippetReflection.forObject(holder)); + addConstantObject(heapObjectConstant); AccessibleObjectMetadata metadata; if (isMethod) { @@ -528,7 +534,7 @@ private void registerValues(AnnotationMemberValue annotationValue) { encoders.sourceMethodNames.addObject(string); } for (JavaConstant proxy : annotationValue.getExceptionProxies(snippetReflection)) { - encoders.objectConstants.addObject(proxy); + addConstantObject(snippetReflection.unwrapConstant(proxy)); } } @@ -737,7 +743,7 @@ public void encodeAllAndInstall() { } private int encodeErrorIndex(Throwable error) { - int index = encoders.objectConstants.getIndex(snippetReflection.forObject(error)); + int index = encoders.objectConstants.getIndex(snippetReflection.unwrapConstant(snippetReflection.forObject(error))); int encodedIndex = FIRST_ERROR_INDEX - index; VMError.guarantee(ReflectionMetadataDecoderImpl.isErrorIndex(encodedIndex)); return encodedIndex; From 590890d47425737da46c390f971b01a13e29f7d3 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Tue, 12 Sep 2023 21:53:20 +0200 Subject: [PATCH 3/8] Allow re-scanning after analysis. --- .../graal/pointsto/heap/HeapSnapshotVerifier.java | 7 +++++++ .../graal/pointsto/heap/ImageHeapScanner.java | 14 -------------- .../oracle/graal/pointsto/meta/AnalysisType.java | 6 +++--- .../pointsto/meta/PointsToAnalysisMethod.java | 6 +++++- .../oracle/svm/hosted/NativeImageGenerator.java | 7 +++++++ .../svm/hosted/heap/SVMImageHeapScanner.java | 6 ------ 6 files changed, 22 insertions(+), 24 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/HeapSnapshotVerifier.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/HeapSnapshotVerifier.java index fd8cf133f2dd..c74f230a6047 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/HeapSnapshotVerifier.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/HeapSnapshotVerifier.java @@ -27,6 +27,7 @@ import static com.oracle.graal.pointsto.ObjectScanner.ScanReason; import java.util.Objects; +import java.util.concurrent.ForkJoinPool; import java.util.function.Consumer; import org.graalvm.compiler.options.Option; @@ -73,6 +74,12 @@ public HeapSnapshotVerifier(BigBang bb, ImageHeap imageHeap, ImageHeapScanner sc verbosity = Options.HeapVerifierVerbosity.getValue(bb.getOptions()); } + public boolean checkHeapSnapshot(UniverseMetaAccess metaAccess, ForkJoinPool threadPool, String stage) { + CompletionExecutor executor = new CompletionExecutor(bb, threadPool, bb.getHeartbeatCallback()); + executor.init(); + return checkHeapSnapshot(metaAccess, executor, stage, false); + } + /** * Heap verification does a complete scan from roots (static fields and embedded constant) and * compares the object graph against the shadow heap. If any new reachable objects or primitive diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java index ac9bc05140cb..2563b869df99 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java @@ -522,15 +522,7 @@ public JavaConstant readFieldValue(AnalysisField field, JavaConstant receiver) { return constantReflection.readFieldValue(field, receiver); } - protected boolean skipScanning() { - return false; - } - public void rescanRoot(Field reflectionField) { - if (skipScanning()) { - return; - } - maybeRunInExecutor(unused -> { AnalysisType type = metaAccess.lookupJavaType(reflectionField.getDeclaringClass()); if (type.isReachable()) { @@ -546,9 +538,6 @@ public void rescanRoot(Field reflectionField) { } public void rescanField(Object receiver, Field reflectionField) { - if (skipScanning()) { - return; - } maybeRunInExecutor(unused -> { AnalysisType type = metaAccess.lookupJavaType(reflectionField.getDeclaringClass()); if (type.isReachable()) { @@ -618,9 +607,6 @@ public void rescanObject(Object object) { * Add the object to the image heap. */ public void rescanObject(Object object, ScanReason reason) { - if (skipScanning()) { - return; - } if (object == null) { return; } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java index ee7d6eddebdb..52b686201aee 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java @@ -186,9 +186,10 @@ public enum UsageKind { private final AnalysisFuture initializeMetaDataTask; /** - * Additional information that is only available for types that are marked as reachable. + * Additional information that is only available for types that are marked as reachable. It is + * preserved after analysis. */ - private AnalysisFuture typeData; + private final AnalysisFuture typeData; /** * Contains reachability handlers that are notified when any of the subtypes are marked as @@ -347,7 +348,6 @@ public void cleanupAfterAnalysis() { constantObjectsCache = null; uniqueConstant = null; unsafeAccessedFields = null; - typeData = null; scheduledTypeReachableNotifications = null; } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/PointsToAnalysisMethod.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/PointsToAnalysisMethod.java index 659320cae413..fa00c4de2720 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/PointsToAnalysisMethod.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/PointsToAnalysisMethod.java @@ -49,6 +49,8 @@ public final class PointsToAnalysisMethod extends AnalysisMethod { private MethodTypeFlow typeFlow; + /** The parsing context in which given method was parsed, preserved after analysis. */ + private final Object parsingReason; private Set invokedBy; private Set implementationInvokedBy; @@ -69,11 +71,13 @@ public final class PointsToAnalysisMethod extends AnalysisMethod { public PointsToAnalysisMethod(AnalysisUniverse universe, ResolvedJavaMethod wrapped) { super(universe, wrapped, MultiMethod.ORIGINAL_METHOD, null); typeFlow = declaringClass.universe.analysisPolicy().createMethodTypeFlow(this); + parsingReason = typeFlow.getParsingReason(); } private PointsToAnalysisMethod(AnalysisMethod original, MultiMethodKey multiMethodKey) { super(original, multiMethodKey); typeFlow = declaringClass.universe.analysisPolicy().createMethodTypeFlow(this); + parsingReason = typeFlow.getParsingReason(); } @Override @@ -149,7 +153,7 @@ public Iterable getInvokes() { @Override public Object getParsingReason() { - return typeFlow.getParsingReason(); + return parsingReason; } public InvokeTypeFlow initAndGetContextInsensitiveInvoke(PointsToAnalysis bb, BytecodePosition originalLocation, boolean isSpecial, MultiMethodKey callerMultiMethodKey) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index a8928f7f8f45..24c3f4475159 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -688,6 +688,10 @@ protected void doRun(Map entryPoints, featureHandler.forEachFeature(feature -> feature.afterCompilation(config)); BuildPhaseProvider.markCompilationFinished(); } + + /* Re-run shadow heap verification after compilation. */ + aUniverse.getHeapVerifier().checkHeapSnapshot(hMetaAccess, compilationExecutor, "after compilation"); + CodeCacheProvider codeCacheProvider = runtimeConfiguration.getBackendForNormalMethod().getProviders().getCodeCache(); reporter.printCreationStart(); try (Indent indent = debug.logAndIndent("create native image")) { @@ -704,6 +708,9 @@ protected void doRun(Map entryPoints, AfterHeapLayoutAccessImpl config = new AfterHeapLayoutAccessImpl(featureHandler, loader, heap, hMetaAccess, debug); featureHandler.forEachFeature(feature -> feature.afterHeapLayout(config)); + /* Re-run shadow heap verification after heap layout. */ + aUniverse.getHeapVerifier().checkHeapSnapshot(hMetaAccess, compilationExecutor, "after heap layout"); + createAbstractImage(k, hostedEntryPoints, heap, hMetaAccess, codeCache); if (ImageSingletons.contains(DynamicMethodAddressResolutionHostedSupport.class)) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/SVMImageHeapScanner.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/SVMImageHeapScanner.java index ad29e779b0fc..a6536dddbdcf 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/SVMImageHeapScanner.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/SVMImageHeapScanner.java @@ -46,7 +46,6 @@ import com.oracle.graal.pointsto.heap.value.ValueSupplier; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; -import com.oracle.svm.core.BuildPhaseProvider; import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.jdk.VarHandleFeature; import com.oracle.svm.core.util.VMError; @@ -135,11 +134,6 @@ protected JavaConstant transformFieldValue(AnalysisField field, JavaConstant rec return ((AnalysisConstantReflectionProvider) constantReflection).interceptValue(metaAccess, field, originalValueConstant); } - @Override - protected boolean skipScanning() { - return BuildPhaseProvider.isAnalysisFinished(); - } - @Override protected void rescanEconomicMap(EconomicMap map) { super.rescanEconomicMap(map); From b2fe7475fb10656deb0cfa161168cf9c5c3c8aba Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Thu, 14 Sep 2023 23:08:40 +0200 Subject: [PATCH 4/8] Use the HostedSnippetReflectionProvider for array scanning. --- .../src/com/oracle/graal/pointsto/ObjectScanner.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java index 137038c3e15c..e598d44e043a 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java @@ -245,10 +245,10 @@ protected final void scanArray(JavaConstant array, ScanReason prevReason) { scanningObserver.forNullArrayElement(array, arrayType, idx, reason); } else { try { - JavaConstant element = bb.getSnippetReflectionProvider().forObject(bb.getUniverse().replaceObject(e)); + JavaConstant element = bb.getUniverse().getSnippetReflection().forObject(bb.getUniverse().replaceObject(e)); scanArrayElement(array, arrayType, reason, idx, element); } catch (UnsupportedFeatureException ex) { /* Object replacement can throw. */ - unsupportedFeatureDuringConstantScan(bb, bb.getSnippetReflectionProvider().forObject(e), ex, reason); + unsupportedFeatureDuringConstantScan(bb, bb.getUniverse().getSnippetReflection().forObject(e), ex, reason); } } } From def72dd033f719eb62e8e473706d91d31459b110 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Sat, 16 Sep 2023 23:37:53 +0200 Subject: [PATCH 5/8] Guarantee that ImageHeapConstant is not double wrapped. Unwrap ImgaeHeapConstant before encoding graphs for run time compilation. --- .../graal/pointsto/heap/ImageHeapScanner.java | 5 +-- .../graal/meta/SubstrateReplacements.java | 5 +-- .../hosted/GraalGraphObjectReplacer.java | 2 +- .../LegacyRuntimeCompilationFeature.java | 3 ++ .../ParseOnceRuntimeCompilationFeature.java | 2 ++ .../hosted/RuntimeCompilationFeature.java | 18 ++++++++++ .../SubstrateRuntimeConfigurationBuilder.java | 34 ++++++++++++++++++- .../svm/hosted/NativeImageGenerator.java | 4 +-- .../AnalysisConstantReflectionProvider.java | 16 ++++++--- .../svm/hosted/code/SubstrateGraphMaker.java | 2 +- .../code/SubstrateGraphMakerFactory.java | 5 +-- ...ostedLookupSnippetReflectionProvider.java} | 9 +++-- .../meta/HostedSnippetReflectionProvider.java | 6 ++-- 13 files changed, 85 insertions(+), 26 deletions(-) rename substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/{AnalysisSnippetReflectionProvider.java => HostedLookupSnippetReflectionProvider.java} (82%) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java index 2563b869df99..1ab245f8d116 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java @@ -664,10 +664,7 @@ protected Object asObject(JavaConstant constant) { return snippetReflection.asObject(Object.class, constant); } - public JavaConstant asConstant(Object object) { - if (object instanceof ImageHeapConstant constant) { - return constant; - } + private JavaConstant asConstant(Object object) { return universe.getSnippetReflection().forObject(object); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java index 343308e79e9a..ac5bfbe4fb8c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/meta/SubstrateReplacements.java @@ -93,6 +93,7 @@ import jdk.vm.ci.code.TargetDescription; import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; @@ -105,7 +106,7 @@ public class SubstrateReplacements extends ReplacementsImpl { @Platforms(Platform.HOSTED_ONLY.class) public interface GraphMakerFactory { - GraphMaker create(ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod); + GraphMaker create(MetaAccessProvider metaAccess, ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod); } @Platforms(Platform.HOSTED_ONLY.class) @@ -376,7 +377,7 @@ public StructuredGraph getIntrinsicGraph(ResolvedJavaMethod method, CompilationI @Platforms(Platform.HOSTED_ONLY.class) @Override protected final GraphMaker createGraphMaker(ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod) { - return builder.graphMakerFactory.create(this, substitute, substitutedMethod); + return builder.graphMakerFactory.create(providers.getMetaAccess(), this, substitute, substitutedMethod); } private static Object[] prepareConstantArguments(Object receiver) { diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalGraphObjectReplacer.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalGraphObjectReplacer.java index 8a340276fcbb..f870b282ee95 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalGraphObjectReplacer.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalGraphObjectReplacer.java @@ -197,8 +197,8 @@ public Object apply(Object source) { } else if (source instanceof FieldLocationIdentity && !(source instanceof SubstrateFieldLocationIdentity)) { dest = createFieldLocationIdentity((FieldLocationIdentity) source); } else if (source instanceof ImageHeapConstant heapConstant) { + VMError.guarantee(heapConstant.isBackedByHostedObject(), "Expected to find a heap object backed by a hosted object, found %s", heapConstant); dest = heapConstant.getHostedObject(); - assert dest != null; } assert dest != null; diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/LegacyRuntimeCompilationFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/LegacyRuntimeCompilationFeature.java index b54009e25aa4..7628f96332ff 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/LegacyRuntimeCompilationFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/LegacyRuntimeCompilationFeature.java @@ -300,6 +300,7 @@ private void processMethod(CallTreeNode node, Deque worklist, BigB new DeoptimizeOnExceptionPhase(deoptimizeOnExceptionPredicate).apply(graph); } new ConvertDeoptimizeToGuardPhase(canonicalizer).apply(graph, hostedProviders); + unwrapImageHeapConstants(graph, hostedProviders.getMetaAccess()); graphEncoder.prepare(graph); node.graph = graph; @@ -467,6 +468,8 @@ public void beforeCompilation(BeforeCompilationAccess c) { */ convertDeoptimizeToGuard.apply(graph, hostedProviders); + unwrapImageHeapConstants(graph, hostedProviders.getMetaAccess()); + graphEncoder.prepare(graph); assert RuntimeCompilationFeature.verifyNodes(graph); } catch (Throwable ex) { diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/ParseOnceRuntimeCompilationFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/ParseOnceRuntimeCompilationFeature.java index b957b6e185e6..b4e740a82ccf 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/ParseOnceRuntimeCompilationFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/ParseOnceRuntimeCompilationFeature.java @@ -603,6 +603,7 @@ private void compileRuntimeCompiledMethod(DebugContext debug, HostedMethod metho VMError.guarantee(deoptMethod != null, "New deopt target method seen: %s", deoptEntryMethod); return deoptMethod; })); + unwrapImageHeapConstants(graph, hostedProviders.getMetaAccess()); assert RuntimeCompilationFeature.verifyNodes(graph); var previous = runtimeGraphs.put(method, graph); @@ -915,6 +916,7 @@ public boolean validateGraph(PointsToAnalysis bb, StructuredGraph graph) { assert MultiMethod.isDeoptTarget(method); ((PointsToAnalysisMethod) method).getTypeFlow().updateFlowsGraph(bb, MethodFlowsGraph.GraphKind.FULL, null, true); } + unwrapImageHeapConstants(graph, hostedProviders.getMetaAccess()); // Note that this will be made thread-safe in the future synchronized (this) { diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/RuntimeCompilationFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/RuntimeCompilationFeature.java index 84d065b8f155..6c05737b0210 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/RuntimeCompilationFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/RuntimeCompilationFeature.java @@ -44,8 +44,10 @@ import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.core.common.spi.MetaAccessExtensionProvider; import org.graalvm.compiler.debug.DebugContext; +import org.graalvm.compiler.graph.Node; import org.graalvm.compiler.graph.NodeClass; import org.graalvm.compiler.lir.phases.LIRSuites; +import org.graalvm.compiler.nodes.ConstantNode; import org.graalvm.compiler.nodes.GraphEncoder; import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.extended.BytecodeExceptionNode; @@ -68,6 +70,7 @@ import org.graalvm.nativeimage.hosted.RuntimeReflection; import com.oracle.graal.pointsto.BigBang; +import com.oracle.graal.pointsto.heap.ImageHeapConstant; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; import com.oracle.graal.pointsto.meta.AnalysisMethod; @@ -119,6 +122,7 @@ import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; +import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; @@ -675,6 +679,20 @@ protected final void afterHeapLayoutHelper(AfterHeapLayoutAccess a) { objectReplacer.updateSubstrateDataAfterHeapLayout(hUniverse); } + /** + * Unwrap the hosted constant from an {@link ImageHeapConstant} before encoding the graph for + * run time compilation. {@link ImageHeapConstant} is a hosted only constant representation. + */ + public static void unwrapImageHeapConstants(StructuredGraph graph, MetaAccessProvider metaAccess) { + for (Node n : graph.getNodes()) { + if (n instanceof ConstantNode constantNode) { + if (constantNode.getValue() instanceof ImageHeapConstant heapConstant) { + VMError.guarantee(heapConstant.isBackedByHostedObject(), "Expected to find a heap object backed by a hosted object, found %s", heapConstant); + constantNode.replace(graph, ConstantNode.forConstant(heapConstant.getHostedObject(), metaAccess, graph)); + } + } + } + } } /** diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateRuntimeConfigurationBuilder.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateRuntimeConfigurationBuilder.java index f8ada706724f..ccaceb1d75f6 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateRuntimeConfigurationBuilder.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateRuntimeConfigurationBuilder.java @@ -32,6 +32,7 @@ import org.graalvm.compiler.core.common.spi.ConstantFieldProvider; import org.graalvm.compiler.core.common.spi.ForeignCallsProvider; import org.graalvm.compiler.core.common.spi.MetaAccessExtensionProvider; +import org.graalvm.compiler.nodes.StructuredGraph; import org.graalvm.compiler.nodes.spi.LoopsDataProvider; import org.graalvm.compiler.nodes.spi.LoweringProvider; import org.graalvm.compiler.nodes.spi.PlatformConfigurationProvider; @@ -39,6 +40,7 @@ import org.graalvm.compiler.nodes.spi.StampProvider; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.util.Providers; +import org.graalvm.compiler.replacements.ReplacementsImpl; import org.graalvm.compiler.word.WordTypes; import com.oracle.graal.pointsto.infrastructure.UniverseMetaAccess; @@ -51,17 +53,21 @@ import com.oracle.svm.core.graal.meta.SubstrateLoweringProvider; import com.oracle.svm.core.graal.meta.SubstrateReplacements; import com.oracle.svm.core.graal.meta.SubstrateSnippetReflectionProvider; +import com.oracle.svm.graal.hosted.RuntimeCompilationFeature; import com.oracle.svm.graal.isolated.IsolateAwareCodeCacheProvider; import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.ameta.AnalysisConstantFieldProvider; import com.oracle.svm.hosted.ameta.AnalysisConstantReflectionProvider; import com.oracle.svm.hosted.classinitialization.ClassInitializationSupport; import com.oracle.svm.hosted.code.SharedRuntimeConfigurationBuilder; +import com.oracle.svm.hosted.code.SubstrateGraphMaker; import com.oracle.svm.hosted.code.SubstrateGraphMakerFactory; import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.code.RegisterConfig; import jdk.vm.ci.meta.ConstantReflectionProvider; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaMethod; public class SubstrateRuntimeConfigurationBuilder extends SharedRuntimeConfigurationBuilder { @@ -106,7 +112,7 @@ protected LoweringProvider createLoweringProvider(ForeignCallsProvider foreignCa protected Replacements createReplacements(Providers p, SnippetReflectionProvider snippetReflection) { BytecodeProvider bytecodeProvider = new ResolvedJavaMethodBytecodeProvider(); WordTypes wordTypes = p.getWordTypes(); - return new SubstrateReplacements(p, snippetReflection, bytecodeProvider, ConfigurationValues.getTarget(), wordTypes, new SubstrateGraphMakerFactory(wordTypes)); + return new SubstrateReplacements(p, snippetReflection, bytecodeProvider, ConfigurationValues.getTarget(), wordTypes, new SubstrateRuntimeGraphMakerFactory(wordTypes)); } @Override @@ -117,4 +123,30 @@ protected SharedCodeCacheProvider createCodeCacheProvider(RegisterConfig registe return new SubstrateCodeCacheProvider(ConfigurationValues.getTarget(), registerConfig); } + static class SubstrateRuntimeGraphMakerFactory extends SubstrateGraphMakerFactory { + + SubstrateRuntimeGraphMakerFactory(WordTypes wordTypes) { + super(wordTypes); + } + + @Override + public ReplacementsImpl.GraphMaker create(MetaAccessProvider metaAccess, ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod) { + return new SubstrateRuntimeGraphMaker(metaAccess, replacements, substitute, substitutedMethod, wordTypes); + } + } + + static class SubstrateRuntimeGraphMaker extends SubstrateGraphMaker { + private final MetaAccessProvider metaAccess; + + SubstrateRuntimeGraphMaker(MetaAccessProvider metaAccess, ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod, WordTypes wordTypes) { + super(replacements, substitute, substitutedMethod, wordTypes); + this.metaAccess = metaAccess; + } + + @Override + protected void finalizeGraph(StructuredGraph graph) { + RuntimeCompilationFeature.unwrapImageHeapConstants(graph, metaAccess); + super.finalizeGraph(graph); + } + } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index 24c3f4475159..5596e042f2e4 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -283,10 +283,10 @@ import com.oracle.svm.hosted.image.NativeImageCodeCacheFactory; import com.oracle.svm.hosted.image.NativeImageHeap; import com.oracle.svm.hosted.jdk.localization.LocalizationFeature; -import com.oracle.svm.hosted.meta.AnalysisSnippetReflectionProvider; import com.oracle.svm.hosted.meta.HostedConstantReflectionProvider; import com.oracle.svm.hosted.meta.HostedField; import com.oracle.svm.hosted.meta.HostedInterface; +import com.oracle.svm.hosted.meta.HostedLookupSnippetReflectionProvider; import com.oracle.svm.hosted.meta.HostedMetaAccess; import com.oracle.svm.hosted.meta.HostedMethod; import com.oracle.svm.hosted.meta.HostedSnippetReflectionProvider; @@ -1032,7 +1032,7 @@ public static AnalysisUniverse createAnalysisUniverse(OptionValues options, Targ analysisFactory = new PointsToAnalysisFactory(); } SubstrateAnnotationExtractor annotationExtractor = (SubstrateAnnotationExtractor) loader.classLoaderSupport.annotationExtractor; - AnalysisSnippetReflectionProvider snippetReflection = new AnalysisSnippetReflectionProvider(new SubstrateWordTypes(originalMetaAccess, FrameAccess.getWordKind())); + HostedLookupSnippetReflectionProvider snippetReflection = new HostedLookupSnippetReflectionProvider(new SubstrateWordTypes(originalMetaAccess, FrameAccess.getWordKind())); return new AnalysisUniverse(hostVM, target.wordJavaKind, analysisPolicy, aSubstitutions, originalMetaAccess, snippetReflection, analysisFactory, annotationExtractor); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java index 7f4e2fd08d66..a40ead335085 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java @@ -377,14 +377,22 @@ public JavaConstant forString(String value) { @Override public JavaConstant forObject(Object object) { - if (object instanceof ImageHeapConstant heapConstant) { - /* This could be a simulated constant. */ - return heapConstant; - } + validateRawObjectConstant(object); /* Redirect constant lookup through the shadow heap. */ return universe.getHeapScanner().createImageHeapConstant(super.forObject(object), ObjectScanner.OtherReason.UNKNOWN); } + /** + * The raw object may never be an {@link ImageHeapConstant}. However, it can be a + * {@link SubstrateObjectConstant} coming from graphs prepared for run time compilation. In that + * case we'll get a double wrapping: the {@link SubstrateObjectConstant} parameter value will be + * wrapped in another {@link SubstrateObjectConstant} which will then be stored in a + * {@link ImageHeapConstant} in the shadow heap. + */ + public static void validateRawObjectConstant(Object object) { + AnalysisError.guarantee(!(object instanceof ImageHeapConstant), "Unexpected ImageHeapConstant %s", object); + } + private SVMHost getHostVM() { return (SVMHost) universe.hostVM(); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SubstrateGraphMaker.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SubstrateGraphMaker.java index 68c4f039029d..593e3ef4530e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SubstrateGraphMaker.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SubstrateGraphMaker.java @@ -47,7 +47,7 @@ public class SubstrateGraphMaker extends GraphMaker { private final WordTypes wordTypes; - protected SubstrateGraphMaker(ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod, WordTypes wordTypes) { + public SubstrateGraphMaker(ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod, WordTypes wordTypes) { super(replacements, substitute, substitutedMethod); this.wordTypes = wordTypes; } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SubstrateGraphMakerFactory.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SubstrateGraphMakerFactory.java index ea68cf9966e5..aace232d48ce 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SubstrateGraphMakerFactory.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SubstrateGraphMakerFactory.java @@ -24,6 +24,7 @@ */ package com.oracle.svm.hosted.code; +import jdk.vm.ci.meta.MetaAccessProvider; import org.graalvm.compiler.replacements.ReplacementsImpl; import org.graalvm.compiler.replacements.ReplacementsImpl.GraphMaker; import org.graalvm.compiler.word.WordTypes; @@ -34,14 +35,14 @@ public class SubstrateGraphMakerFactory implements SubstrateReplacements.GraphMakerFactory { - private final WordTypes wordTypes; + protected final WordTypes wordTypes; public SubstrateGraphMakerFactory(WordTypes wordTypes) { this.wordTypes = wordTypes; } @Override - public GraphMaker create(ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod) { + public GraphMaker create(MetaAccessProvider metaAccess, ReplacementsImpl replacements, ResolvedJavaMethod substitute, ResolvedJavaMethod substitutedMethod) { return new SubstrateGraphMaker(replacements, substitute, substitutedMethod, wordTypes); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/AnalysisSnippetReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedLookupSnippetReflectionProvider.java similarity index 82% rename from substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/AnalysisSnippetReflectionProvider.java rename to substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedLookupSnippetReflectionProvider.java index f39df6306028..b16589f2408e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/AnalysisSnippetReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedLookupSnippetReflectionProvider.java @@ -24,23 +24,22 @@ */ package com.oracle.svm.hosted.meta; +import com.oracle.svm.hosted.ameta.AnalysisConstantReflectionProvider; import org.graalvm.compiler.word.WordTypes; -import com.oracle.graal.pointsto.heap.ImageHeapConstant; import com.oracle.svm.core.graal.meta.SubstrateSnippetReflectionProvider; -import com.oracle.svm.core.util.VMError; import jdk.vm.ci.meta.JavaConstant; -public class AnalysisSnippetReflectionProvider extends SubstrateSnippetReflectionProvider { +public class HostedLookupSnippetReflectionProvider extends SubstrateSnippetReflectionProvider { - public AnalysisSnippetReflectionProvider(WordTypes wordTypes) { + public HostedLookupSnippetReflectionProvider(WordTypes wordTypes) { super(wordTypes); } @Override public JavaConstant forObject(Object object) { - VMError.guarantee(!(object instanceof ImageHeapConstant)); + AnalysisConstantReflectionProvider.validateRawObjectConstant(object); return super.forObject(object); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedSnippetReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedSnippetReflectionProvider.java index 20d7d80c19ae..2394fcebae25 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedSnippetReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedSnippetReflectionProvider.java @@ -35,6 +35,7 @@ import com.oracle.svm.core.graal.meta.SubstrateSnippetReflectionProvider; import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.meta.SubstrateObjectConstant; +import com.oracle.svm.hosted.ameta.AnalysisConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; @@ -56,10 +57,7 @@ public JavaConstant forObject(Object object) { /* Relocated pointers are subject to relocation, so we don't know their value yet. */ return JavaConstant.forIntegerKind(FrameAccess.getWordKind(), word.rawValue()); } - if (object instanceof ImageHeapConstant heapConstant) { - /* This could be a simulated constant. */ - return heapConstant; - } + AnalysisConstantReflectionProvider.validateRawObjectConstant(object); /* Redirect constant lookup through the shadow heap. */ return heapScanner.createImageHeapConstant(super.forObject(object), OtherReason.UNKNOWN); } From dc2855424fcfc629d5a0daa7ae22a6bf528c7361 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Sat, 16 Sep 2023 23:18:23 +0200 Subject: [PATCH 6/8] Update documentation. --- .../api/replacements/SnippetReflectionProvider.java | 4 +++- .../com/oracle/graal/pointsto/heap/ImageHeapScanner.java | 6 ++++++ .../svm/hosted/meta/HostedSnippetReflectionProvider.java | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java b/compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java index cdd4b4023b90..55621c632244 100644 --- a/compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java +++ b/compiler/src/jdk.internal.vm.compiler/src/org/graalvm/compiler/api/replacements/SnippetReflectionProvider.java @@ -65,7 +65,9 @@ public interface SnippetReflectionProvider { T asObject(Class type, JavaConstant constant); /** - * Get the wrapped constant object, if any. + * Get the wrapped constant object, if any. This is a temporary workaround required in Native + * Image to expand the use of ImageHeapConstant. It will be removed when all hosted phases + * support ImageHeapConstant by default and no unwrapping is necessary. (GR-48682) */ default JavaConstant unwrapConstant(JavaConstant constant) { return constant; diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java index 1ab245f8d116..bfb68599403b 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java @@ -434,6 +434,12 @@ private boolean isNonNullObjectConstant(JavaConstant constant) { } public boolean isWordType(JavaConstant rawElementValue) { + /* + * UniverseMetaAccess.isInstanceOf cannot be used here because the object replacers may have + * not yet been applied to the object. This can lead to + * "Type is not available in this platform" issues when accessing the object type. A proper + * fix will add a JavaConstant implementation class for relocatable word values.(GR-48681). + */ Object obj = snippetReflection.asObject(Object.class, rawElementValue); return obj instanceof WordBase; } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedSnippetReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedSnippetReflectionProvider.java index 2394fcebae25..38985da7ca2c 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedSnippetReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedSnippetReflectionProvider.java @@ -53,6 +53,7 @@ public void setHeapScanner(ImageHeapScanner heapScanner) { @Override public JavaConstant forObject(Object object) { + /* RelocatedPointer values will be represented as a RelocatableConstant by GR-48681. */ if (object instanceof WordBase word && !(object instanceof RelocatedPointer)) { /* Relocated pointers are subject to relocation, so we don't know their value yet. */ return JavaConstant.forIntegerKind(FrameAccess.getWordKind(), word.rawValue()); From c3a6e3c89f5c5e482c25370e45523ef150dbcc3d Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Sat, 16 Sep 2023 23:20:19 +0200 Subject: [PATCH 7/8] Refactor AnalysisUniverse.lookup(JavaConstant). --- .../StandaloneConstantReflectionProvider.java | 2 +- .../graal/pointsto/heap/ImageHeapScanner.java | 2 +- .../pointsto/infrastructure/Universe.java | 10 ++++++--- .../infrastructure/WrappedConstantPool.java | 2 +- .../graal/pointsto/meta/AnalysisField.java | 2 +- .../graal/pointsto/meta/AnalysisUniverse.java | 21 ++++++++++++------- .../AnalysisConstantReflectionProvider.java | 2 +- .../svm/hosted/meta/HostedUniverse.java | 15 +++---------- ...trinsifyMethodHandlesInvocationPlugin.java | 2 +- 9 files changed, 29 insertions(+), 29 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/meta/StandaloneConstantReflectionProvider.java b/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/meta/StandaloneConstantReflectionProvider.java index dc6ad698955a..86c11564e77c 100644 --- a/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/meta/StandaloneConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/meta/StandaloneConstantReflectionProvider.java @@ -50,7 +50,7 @@ public StandaloneConstantReflectionProvider(AnalysisUniverse universe, HotSpotJV @Override public final JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver) { ResolvedJavaField wrappedField = ((AnalysisField) field).getWrapped(); - JavaConstant ret = universe.lookup(super.readFieldValue(wrappedField, universe.toHosted(receiver))); + JavaConstant ret = universe.fromHosted(super.readFieldValue(wrappedField, universe.toHosted(receiver))); if (ret == null) { ret = wrappedField.getConstantValue(); if (ret == null) { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java index bfb68599403b..cb63d8b27bca 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java @@ -520,7 +520,7 @@ protected String formatReason(String message, ScanReason reason) { protected ValueSupplier readHostedFieldValue(AnalysisField field, JavaConstant receiver) { // Wrap the hosted constant into a substrate constant - JavaConstant value = universe.lookup(hostedConstantReflection.readFieldValue(field.wrapped, receiver)); + JavaConstant value = universe.fromHosted(hostedConstantReflection.readFieldValue(field.wrapped, receiver)); return ValueSupplier.eagerValue(value); } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/Universe.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/Universe.java index 4658bbd91fef..678f05ce573a 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/Universe.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/Universe.java @@ -27,6 +27,8 @@ import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import com.oracle.graal.pointsto.api.HostVM; +import com.oracle.graal.pointsto.heap.ImageHeap; +import com.oracle.graal.pointsto.heap.ImageHeapConstant; import jdk.vm.ci.meta.ConstantPool; import jdk.vm.ci.meta.JavaConstant; @@ -60,11 +62,13 @@ public interface Universe { WrappedConstantPool lookup(ConstantPool constantPool, ResolvedJavaType defaultAccessingClass); + /** + * Lookup a constant originating from the underlying VM, via JVMCI, in the analysis universe. + * This method will unpack hosted object constants and repack the raw constant object into an + * {@link ImageHeapConstant} cached in the {@link ImageHeap}. + */ JavaConstant lookup(JavaConstant constant); - /** Redirect constant lookup through the shadow heap. */ - JavaConstant shadowHeapLookup(JavaConstant constant); - ResolvedJavaMethod resolveSubstitution(ResolvedJavaMethod method); ResolvedJavaType objectType(); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedConstantPool.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedConstantPool.java index d7005e3c7af5..adf1fc0f85ad 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedConstantPool.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/infrastructure/WrappedConstantPool.java @@ -64,7 +64,7 @@ public int length() { } private JavaConstant lookupConstant(JavaConstant constant) { - return universe.shadowHeapLookup(constant); + return universe.lookup(constant); } /** diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisField.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisField.java index 5227392105bc..6d0e783cfea8 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisField.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisField.java @@ -537,7 +537,7 @@ public Field getJavaField() { @Override public JavaConstant getConstantValue() { - return getUniverse().shadowHeapLookup(getWrapped().getConstantValue()); + return getUniverse().lookup(getWrapped().getConstantValue()); } public void addAnalysisFieldObserver(AnalysisFieldObserver observer) { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java index 18e4a91a51e8..441171fcc316 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisUniverse.java @@ -497,6 +497,16 @@ public WrappedConstantPool lookup(ConstantPool constantPool, ResolvedJavaType de @Override public JavaConstant lookup(JavaConstant constant) { + if (constant == null || constant.isNull() || constant.getJavaKind().isPrimitive()) { + return constant; + } + return heapScanner.createImageHeapConstant(fromHosted(constant), ObjectScanner.OtherReason.UNKNOWN); + } + + /** + * Convert a hosted HotSpotObjectConstant into a SubstrateObjectConstant. + */ + public JavaConstant fromHosted(JavaConstant constant) { if (constant == null) { return null; } else if (constant.getJavaKind().isObject() && !constant.isNull()) { @@ -517,14 +527,9 @@ public JavaConstant lookup(JavaConstant constant) { } } - @Override - public JavaConstant shadowHeapLookup(JavaConstant constant) { - if (constant == null || constant.isNull() || constant.getJavaKind().isPrimitive()) { - return constant; - } - return heapScanner.createImageHeapConstant(lookup(constant), ObjectScanner.OtherReason.UNKNOWN); - } - + /** + * Convert a hosted SubstrateObjectConstant into a HotSpotObjectConstant. + */ public JavaConstant toHosted(JavaConstant constant) { if (constant == null) { return null; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java index a40ead335085..9fd27f2e1b55 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java @@ -237,7 +237,7 @@ public ValueSupplier readHostedFieldValue(AnalysisField field, Hos } private JavaConstant doReadValue(AnalysisField field, JavaConstant receiver, UniverseMetaAccess access) { - return universe.lookup(ReadableJavaField.readFieldValue(access, classInitializationSupport, field.wrapped, receiver)); + return universe.fromHosted(ReadableJavaField.readFieldValue(access, classInitializationSupport, field.wrapped, receiver)); } /** diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedUniverse.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedUniverse.java index f1a3d8e8b1a5..5387b862d2d9 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedUniverse.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedUniverse.java @@ -437,18 +437,9 @@ public WrappedConstantPool lookup(ConstantPool constantPool, ResolvedJavaType de } @Override - public JavaConstant lookup(JavaConstant constant) { - // There should not be any conversion necessary for constants. - return constant; - } - - @Override - public JavaConstant shadowHeapLookup(JavaConstant constant) { - if (constant == null || constant.isNull() || constant.getJavaKind().isPrimitive()) { - return constant; - } - VMError.guarantee(constant instanceof ImageHeapConstant); - return constant; + public JavaConstant lookup(JavaConstant c) { + VMError.guarantee(c == null || c.isNull() || c.getJavaKind().isPrimitive() || c instanceof ImageHeapConstant); + return c; } public Collection getTypes() { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java index 366015f23f7b..bab8b30cf0fd 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/phases/IntrinsifyMethodHandlesInvocationPlugin.java @@ -1051,7 +1051,7 @@ private ResolvedJavaType optionalLookup(ResolvedJavaType type) { private JavaConstant lookup(JavaConstant constant) { /* Redirect constant lookup through the shadow heap. */ - return aUniverse.shadowHeapLookup(constant); + return aUniverse.lookup(constant); } private JavaConstant toOriginal(JavaConstant constant) { From 26872f66512ec453b6d7fd21ca56590c45cd0517 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Fri, 15 Sep 2023 18:32:53 +0200 Subject: [PATCH 8/8] Remove unnecessary old HostedUniverse.lookup(). This would now be HostedUniverse.fromHosted(), but with the same empty implementation. --- .../svm/hosted/meta/HostedConstantReflectionProvider.java | 2 +- .../src/com/oracle/svm/hosted/meta/HostedType.java | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantReflectionProvider.java index f47cf783274a..2358f8cf4eec 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantReflectionProvider.java @@ -108,7 +108,7 @@ public void forEachArrayElement(JavaConstant array, ObjIntConsumer public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver) { var hField = (HostedField) field; assert checkHub(receiver) : "Receiver " + receiver + " of field " + hField + " read should not be java.lang.Class. Expecting to see DynamicHub here."; - return hUniverse.lookup(aConstantReflection.readValue(hMetaAccess, hField.getWrapped(), receiver, true)); + return aConstantReflection.readValue(hMetaAccess, hField.getWrapped(), receiver, true); } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedType.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedType.java index 8febc3022eba..0ea3d9b28aa9 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedType.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedType.java @@ -353,7 +353,6 @@ public final int getModifiers() { @Override public final boolean isInstance(JavaConstant obj) { - assert universe.lookup(obj) == obj : "constant should not have analysis-universe dependent value"; return wrapped.isInstance(obj); }