From 1ed2a58a20f03bf5f00287386c8d405c90ae267f Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Sat, 16 Sep 2023 23:15:56 +0200 Subject: [PATCH] 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) {