diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java index 0f2f29c0c634..15a64e5e3166 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/HotSpotBackendFactory.java @@ -28,6 +28,7 @@ import static jdk.vm.ci.services.Services.IS_BUILDING_NATIVE_IMAGE; import static jdk.vm.ci.services.Services.IS_IN_NATIVE_IMAGE; +import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; import jdk.graal.compiler.bytecode.BytecodeProvider; import jdk.graal.compiler.core.common.spi.ConstantFieldProvider; import jdk.graal.compiler.debug.Assertions; @@ -56,6 +57,7 @@ import jdk.graal.compiler.nodes.java.AbstractNewObjectNode; import jdk.graal.compiler.nodes.loop.LoopsDataProviderImpl; import jdk.graal.compiler.nodes.memory.FixedAccessNode; +import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; import jdk.graal.compiler.nodes.spi.LoopsDataProvider; import jdk.graal.compiler.nodes.spi.Replacements; import jdk.graal.compiler.options.OptionValues; @@ -188,9 +190,12 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti try (InitTimer rt = timer("create Bytecode provider")) { bytecodeProvider = createBytecodeProvider(metaAccess, snippetReflection); } - + IdentityHashCodeProvider identityHashCodeProvider; + try (InitTimer rt = timer("create IdentityHashCode provider")) { + identityHashCodeProvider = createIdentityHashCodeProvider(snippetReflection); + } providers = new HotSpotProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, null, registers, - snippetReflection, wordTypes, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, loopsDataProvider, config); + snippetReflection, wordTypes, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, loopsDataProvider, config, identityHashCodeProvider); HotSpotReplacementsImpl replacements; try (InitTimer rt = timer("create Replacements provider")) { replacements = createReplacements(target, providers, bytecodeProvider); @@ -217,6 +222,10 @@ public final HotSpotBackend createBackend(HotSpotGraalRuntimeProvider graalRunti } } + protected IdentityHashCodeProvider createIdentityHashCodeProvider(SnippetReflectionProvider snippetReflection) { + return new IdentityHashCodeProvider(snippetReflection); + } + protected abstract HotSpotBackend createBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider graalRuntime, HotSpotProviders providers); protected abstract Value[] createNativeABICallerSaveRegisters(GraalHotSpotVMConfig config, RegisterConfig registerConfig); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java index a402fe7a7a68..baa6beeb6e86 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/SymbolicSnippetEncoder.java @@ -365,7 +365,8 @@ private boolean verifySnippetEncodeDecode(DebugContext debug, ResolvedJavaMethod HotSpotProviders newProviders = new HotSpotProviders(originalProvider.getMetaAccess(), originalProvider.getCodeCache(), constantReflection, originalProvider.getConstantFieldProvider(), originalProvider.getForeignCalls(), originalProvider.getLowerer(), null, originalProvider.getSuites(), originalProvider.getRegisters(), originalProvider.getSnippetReflection(), originalProvider.getWordTypes(), originalProvider.getStampProvider(), - originalProvider.getPlatformConfigurationProvider(), originalProvider.getMetaAccessExtensionProvider(), originalProvider.getLoopsDataProvider(), originalProvider.getConfig()); + originalProvider.getPlatformConfigurationProvider(), originalProvider.getMetaAccessExtensionProvider(), originalProvider.getLoopsDataProvider(), originalProvider.getConfig(), + originalProvider.getIdentityHashCodeProvider()); HotSpotSnippetReplacementsImpl filteringReplacements = new HotSpotSnippetReplacementsImpl(newProviders, originalProvider.getReplacements().getDefaultReplacementBytecodeProvider(), originalProvider.getCodeCache().getTarget()); filteringReplacements.setGraphBuilderPlugins(originalProvider.getReplacements().getGraphBuilderPlugins()); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotProviders.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotProviders.java index 1de93b76088b..dff5d5f9c340 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotProviders.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/meta/HotSpotProviders.java @@ -30,6 +30,7 @@ import jdk.graal.compiler.hotspot.GraalHotSpotVMConfig; import jdk.graal.compiler.hotspot.word.HotSpotWordTypes; import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins; +import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; import jdk.graal.compiler.nodes.spi.LoopsDataProvider; import jdk.graal.compiler.nodes.spi.LoweringProvider; import jdk.graal.compiler.nodes.spi.PlatformConfigurationProvider; @@ -37,7 +38,6 @@ import jdk.graal.compiler.nodes.spi.StampProvider; import jdk.graal.compiler.phases.tiers.SuitesProvider; import jdk.graal.compiler.phases.util.Providers; - import jdk.vm.ci.hotspot.HotSpotCodeCacheProvider; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.MetaAccessProvider; @@ -67,9 +67,10 @@ public HotSpotProviders(MetaAccessProvider metaAccess, PlatformConfigurationProvider platformConfigurationProvider, MetaAccessExtensionProvider metaAccessExtensionProvider, LoopsDataProvider loopsDataProvider, - GraalHotSpotVMConfig config) { + GraalHotSpotVMConfig config, + IdentityHashCodeProvider identityHashCodeProvider) { super(metaAccess, codeCache, constantReflection, constantField, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, - snippetReflection, wordTypes, loopsDataProvider); + snippetReflection, wordTypes, loopsDataProvider, identityHashCodeProvider); this.suites = suites; this.registers = registers; this.config = config; @@ -116,7 +117,7 @@ public HotSpotProviders copyWith(ConstantReflectionProvider substitution) { return new HotSpotProviders(getMetaAccess(), getCodeCache(), substitution, getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider(), - config); + config, getIdentityHashCodeProvider()); } @Override @@ -125,7 +126,7 @@ public HotSpotProviders copyWith(ConstantFieldProvider substitution) { getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider(), - config); + config, getIdentityHashCodeProvider()); } @Override @@ -133,14 +134,14 @@ public HotSpotProviders copyWith(Replacements substitution) { return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), substitution, getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), - getLoopsDataProvider(), config); + getLoopsDataProvider(), config, getIdentityHashCodeProvider()); } public HotSpotProviders copyWith() { return new HotSpotProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getSuites(), getRegisters(), getSnippetReflection(), getWordTypes(), getStampProvider(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider(), - config); + config, getIdentityHashCodeProvider()); } public void setSuites(HotSpotSuitesProvider suites) { diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/CoreProviders.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/CoreProviders.java index b89c51d875f1..4062052a179d 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/CoreProviders.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/CoreProviders.java @@ -60,4 +60,6 @@ public interface CoreProviders { CodeCacheProvider getCodeCache(); SnippetReflectionProvider getSnippetReflection(); + + IdentityHashCodeProvider getIdentityHashCodeProvider(); } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/CoreProvidersDelegate.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/CoreProvidersDelegate.java index 63ae24f909a8..4ad0c029d44d 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/CoreProvidersDelegate.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/CoreProvidersDelegate.java @@ -109,4 +109,9 @@ public WordTypes getWordTypes() { public SnippetReflectionProvider getSnippetReflection() { return providers.getSnippetReflection(); } + + @Override + public IdentityHashCodeProvider getIdentityHashCodeProvider() { + return providers.getIdentityHashCodeProvider(); + } } diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/IdentityHashCodeProvider.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/IdentityHashCodeProvider.java new file mode 100644 index 000000000000..3fc7a8eabe73 --- /dev/null +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/nodes/spi/IdentityHashCodeProvider.java @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2024, 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 jdk.graal.compiler.nodes.spi; + +import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; +import jdk.vm.ci.meta.JavaConstant; + +public class IdentityHashCodeProvider { + + protected final SnippetReflectionProvider snippetReflection; + + public IdentityHashCodeProvider(SnippetReflectionProvider snippetReflection) { + this.snippetReflection = snippetReflection; + } + + public int identityHashCode(JavaConstant constant) { + return System.identityHashCode(snippetReflection.asObject(Object.class, constant)); + } +} diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/FixReadsPhase.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/FixReadsPhase.java index 7e4915893158..790d166e374c 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/FixReadsPhase.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/common/FixReadsPhase.java @@ -239,7 +239,7 @@ public RawConditionalEliminationVisitor(StructuredGraph graph, ScheduleResult sc this.debug = graph.getDebug(); this.schedule = schedule; this.metaAccess = metaAccess; - this.rawCanonicalizerTool = new RawCanonicalizerTool(new Providers(metaAccess, null, null, null, null, null, null, null, null, null, null, null, null)); + this.rawCanonicalizerTool = new RawCanonicalizerTool(new Providers(metaAccess, null, null, null, null, null, null, null, null, null, null, null, null, null)); blockActionStart = new BlockMap<>(schedule.getCFG()); endMaps = EconomicMap.create(Equivalence.IDENTITY); stampMap = graph.createNodeMap(); diff --git a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/util/Providers.java b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/util/Providers.java index 9f04d4c35718..5699d7b64016 100644 --- a/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/util/Providers.java +++ b/compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/phases/util/Providers.java @@ -29,6 +29,7 @@ import jdk.graal.compiler.core.common.spi.ForeignCallsProvider; import jdk.graal.compiler.core.common.spi.MetaAccessExtensionProvider; import jdk.graal.compiler.nodes.spi.CoreProviders; +import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; import jdk.graal.compiler.nodes.spi.LoopsDataProvider; import jdk.graal.compiler.nodes.spi.LoweringProvider; import jdk.graal.compiler.nodes.spi.PlatformConfigurationProvider; @@ -57,10 +58,12 @@ public class Providers implements CoreProviders { protected final CodeCacheProvider codeCache; protected final SnippetReflectionProvider snippetReflection; protected final WordTypes wordTypes; + protected final IdentityHashCodeProvider identityHashCodeProvider; public Providers(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, ForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, PlatformConfigurationProvider platformConfigurationProvider, - MetaAccessExtensionProvider metaAccessExtensionProvider, SnippetReflectionProvider snippetReflection, WordTypes wordTypes, LoopsDataProvider loopsDataProvider) { + MetaAccessExtensionProvider metaAccessExtensionProvider, SnippetReflectionProvider snippetReflection, WordTypes wordTypes, LoopsDataProvider loopsDataProvider, + IdentityHashCodeProvider identityHashCodeProvider) { this.metaAccess = metaAccess; this.constantReflection = constantReflection; this.constantFieldProvider = constantFieldProvider; @@ -74,12 +77,13 @@ public Providers(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, Con this.codeCache = codeCache; this.snippetReflection = snippetReflection; this.wordTypes = wordTypes; + this.identityHashCodeProvider = identityHashCodeProvider; } public Providers(Providers copyFrom) { this(copyFrom.getMetaAccess(), copyFrom.getCodeCache(), copyFrom.getConstantReflection(), copyFrom.getConstantFieldProvider(), copyFrom.getForeignCalls(), copyFrom.getLowerer(), copyFrom.getReplacements(), copyFrom.getStampProvider(), copyFrom.getPlatformConfigurationProvider(), copyFrom.getMetaAccessExtensionProvider(), - copyFrom.getSnippetReflection(), copyFrom.getWordTypes(), copyFrom.getLoopsDataProvider()); + copyFrom.getSnippetReflection(), copyFrom.getWordTypes(), copyFrom.getLoopsDataProvider(), copyFrom.getIdentityHashCodeProvider()); } @Override @@ -142,6 +146,11 @@ public SnippetReflectionProvider getSnippetReflection() { return snippetReflection; } + @Override + public IdentityHashCodeProvider getIdentityHashCodeProvider() { + return identityHashCodeProvider; + } + @Override public WordTypes getWordTypes() { return wordTypes; @@ -150,24 +159,24 @@ public WordTypes getWordTypes() { public Providers copyWith(ConstantReflectionProvider substitution) { assert this.getClass() == Providers.class : "must override"; return new Providers(metaAccess, codeCache, substitution, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, - snippetReflection, wordTypes, loopsDataProvider); + snippetReflection, wordTypes, loopsDataProvider, identityHashCodeProvider); } public Providers copyWith(ConstantFieldProvider substitution) { assert this.getClass() == Providers.class : "must override"; return new Providers(metaAccess, codeCache, constantReflection, substitution, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, - snippetReflection, wordTypes, loopsDataProvider); + snippetReflection, wordTypes, loopsDataProvider, identityHashCodeProvider); } public Providers copyWith(Replacements substitution) { assert this.getClass() == Providers.class : "must override in " + getClass(); return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, substitution, stampProvider, platformConfigurationProvider, - metaAccessExtensionProvider, snippetReflection, wordTypes, loopsDataProvider); + metaAccessExtensionProvider, snippetReflection, wordTypes, loopsDataProvider, identityHashCodeProvider); } public Providers copyWith(MetaAccessExtensionProvider substitution) { assert this.getClass() == Providers.class : getClass() + " must override"; return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, substitution, - snippetReflection, wordTypes, loopsDataProvider); + snippetReflection, wordTypes, loopsDataProvider, identityHashCodeProvider); } } diff --git a/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/PointsToAnalyzer.java b/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/PointsToAnalyzer.java index 4d4f2eabc187..6a69f606f955 100644 --- a/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/PointsToAnalyzer.java +++ b/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/PointsToAnalyzer.java @@ -77,6 +77,7 @@ import jdk.graal.compiler.debug.Indent; import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; import jdk.graal.compiler.nodes.graphbuilderconf.InvocationPlugins; +import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; import jdk.graal.compiler.options.OptionValues; import jdk.graal.compiler.phases.util.Providers; import jdk.graal.compiler.printer.GraalDebugHandlersFactory; @@ -147,10 +148,11 @@ private PointsToAnalyzer(String mainEntryClass, OptionValues options) { StandaloneConstantReflectionProvider aConstantReflection = new StandaloneConstantReflectionProvider(aUniverse, HotSpotJVMCIRuntime.runtime()); StandaloneConstantFieldProvider aConstantFieldProvider = new StandaloneConstantFieldProvider(aMetaAccess); AnalysisMetaAccessExtensionProvider aMetaAccessExtensionProvider = new AnalysisMetaAccessExtensionProvider(); + IdentityHashCodeProvider identityHashCodeProvider = originalProviders.getIdentityHashCodeProvider(); HostedProviders aProviders = new HostedProviders(aMetaAccess, null, aConstantReflection, aConstantFieldProvider, originalProviders.getForeignCalls(), originalProviders.getLowerer(), originalProviders.getReplacements(), originalProviders.getStampProvider(), snippetReflection, new WordTypes(aMetaAccess, wordKind), - originalProviders.getPlatformConfigurationProvider(), aMetaAccessExtensionProvider, originalProviders.getLoopsDataProvider()); + originalProviders.getPlatformConfigurationProvider(), aMetaAccessExtensionProvider, originalProviders.getLoopsDataProvider(), identityHashCodeProvider); standaloneHost.initializeProviders(aProviders); analysisName = getAnalysisName(mainEntryClass); ClassInclusionPolicy classInclusionPolicy = new ClassInclusionPolicy.DefaultAllInclusionPolicy("Included in the base image"); @@ -160,7 +162,7 @@ private PointsToAnalyzer(String mainEntryClass, OptionValues options) { aUniverse.setBigBang(bigbang); ImageHeap heap = new ImageHeap(); StandaloneImageHeapScanner heapScanner = new StandaloneImageHeapScanner(bigbang, heap, aMetaAccess, - snippetReflection, aConstantReflection, new AnalysisObjectScanningObserver(bigbang), analysisClassLoader, new HostedValuesProvider(aUniverse)); + snippetReflection, aConstantReflection, new AnalysisObjectScanningObserver(bigbang), analysisClassLoader, new HostedValuesProvider(aUniverse), identityHashCodeProvider); aUniverse.setHeapScanner(heapScanner); HeapSnapshotVerifier heapVerifier = new StandaloneHeapSnapshotVerifier(bigbang, heap, heapScanner); aUniverse.setHeapVerifier(heapVerifier); diff --git a/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/heap/StandaloneImageHeapScanner.java b/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/heap/StandaloneImageHeapScanner.java index 4e1674a84469..86275096f782 100644 --- a/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/heap/StandaloneImageHeapScanner.java +++ b/substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/heap/StandaloneImageHeapScanner.java @@ -39,6 +39,7 @@ import com.oracle.graal.pointsto.util.AnalysisError; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; +import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; import jdk.vm.ci.code.BytecodePosition; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; @@ -50,8 +51,8 @@ public class StandaloneImageHeapScanner extends ImageHeapScanner { private Predicate shouldScanField; public StandaloneImageHeapScanner(BigBang bb, ImageHeap heap, AnalysisMetaAccess aMetaAccess, SnippetReflectionProvider aSnippetReflection, ConstantReflectionProvider aConstantReflection, - ObjectScanningObserver aScanningObserver, ClassLoader classLoader, HostedValuesProvider hostedValuesProvider) { - super(bb, heap, aMetaAccess, aSnippetReflection, aConstantReflection, aScanningObserver, hostedValuesProvider); + ObjectScanningObserver aScanningObserver, ClassLoader classLoader, HostedValuesProvider hostedValuesProvider, IdentityHashCodeProvider identityHashCodeProvider) { + super(bb, heap, aMetaAccess, aSnippetReflection, aConstantReflection, aScanningObserver, hostedValuesProvider, identityHashCodeProvider); this.classLoader = classLoader; shouldScanConstant = constant -> isClassLoaderAllowed(metaAccess.lookupJavaType(constant).getJavaClass().getClassLoader()); shouldScanField = field -> isClassLoaderAllowed(field.getDeclaringClass().getJavaClass().getClassLoader()); 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 86c11564e77c..7f888bcaaf49 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.fromHosted(super.readFieldValue(wrappedField, universe.toHosted(receiver))); + JavaConstant ret = universe.getHostedValuesProvider().interceptHosted(super.readFieldValue(wrappedField, 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/HostedValuesProvider.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/HostedValuesProvider.java index 84af4ab56eff..524298a30c81 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/HostedValuesProvider.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/HostedValuesProvider.java @@ -48,19 +48,16 @@ public JavaConstant readFieldValueWithReplacement(AnalysisField field, JavaConst } private JavaConstant doReadValue(AnalysisField field, JavaConstant receiver) { - /* Wrap the hosted constant into a substrate constant */ field.beforeFieldValueAccess(); - JavaConstant hostedReceiver = universe.toHosted(receiver); - JavaConstant hostedValue = GraalAccess.getOriginalProviders().getConstantReflection().readFieldValue(field.wrapped, hostedReceiver); - return universe.fromHosted(hostedValue); + return interceptHosted(GraalAccess.getOriginalProviders().getConstantReflection().readFieldValue(field.wrapped, receiver)); } public Integer readArrayLength(JavaConstant array) { - return GraalAccess.getOriginalProviders().getConstantReflection().readArrayLength(universe.toHosted(array)); + return GraalAccess.getOriginalProviders().getConstantReflection().readArrayLength(array); } public JavaConstant readArrayElement(JavaConstant array, int index) { - return GraalAccess.getOriginalProviders().getConstantReflection().readArrayElement(universe.toHosted(array), index); + return GraalAccess.getOriginalProviders().getConstantReflection().readArrayElement(array, index); } /** @@ -90,11 +87,15 @@ public JavaConstant validateReplacedConstant(JavaConstant value) { } public JavaConstant forObject(Object object) { - return GraalAccess.getOriginalProviders().getSnippetReflection().forObject(object); + return GraalAccess.getOriginalSnippetReflection().forObject(object); } public T asObject(Class type, JavaConstant constant) { - return GraalAccess.getOriginalProviders().getSnippetReflection().asObject(type, constant); + return GraalAccess.getOriginalSnippetReflection().asObject(type, constant); } + /** Hook to allow subclasses to intercept hosted constants. */ + public JavaConstant interceptHosted(JavaConstant constant) { + return constant; + } } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapArray.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapArray.java index 0bc8f603b24a..e7ace74dbe17 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapArray.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapArray.java @@ -30,9 +30,9 @@ public abstract class ImageHeapArray extends ImageHeapConstant { - public static ImageHeapArray create(AnalysisType type, int length) { + public static ImageHeapArray create(AnalysisType type, int length, int identityHashCode) { assert type.isArray() : type; - return type.getComponentType().getStorageKind().isPrimitive() ? new ImageHeapPrimitiveArray(type, length) : new ImageHeapObjectArray(type, length); + return type.getComponentType().getStorageKind().isPrimitive() ? new ImageHeapPrimitiveArray(type, length, identityHashCode) : new ImageHeapObjectArray(type, length, identityHashCode); } protected ImageHeapArray(ConstantData constantData, boolean compressed) { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapConstant.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapConstant.java index d90ea95495e1..e5a5cda93b66 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapConstant.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapConstant.java @@ -39,6 +39,7 @@ import jdk.graal.compiler.core.common.type.CompressibleConstant; import jdk.graal.compiler.core.common.type.TypedConstant; +import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MetaAccessProvider; @@ -66,7 +67,17 @@ public abstract static class ConstantData { */ private final JavaConstant hostedObject; /** - * See {@link #createIdentityHashCode(JavaConstant)}. + * The identity hash code for the heap object. This can be the same as the identity hash + * code of the referenced hosted object or not. The value is provided via a + * {@link IdentityHashCodeProvider} which can decide to use a previously computed identity + * hash code, e.g., to accommodate for replaced constants. + *

+ * For objects without a backing object in the heap of the image builder VM we create a + * "virtual" identity hash code that has the same properties as the image builder VM by + * using the identity hash code of a new and otherwise unused object in the image builder + * VM. + *

+ * The value is guaranteed to be positive. */ private final int identityHashCode; /** @@ -86,6 +97,11 @@ public abstract static class ConstantData { Objects.requireNonNull(type); this.type = type; this.hostedObject = CompressibleConstant.uncompress(object); + /* + * The Java HotSpot VM only returns positive numbers for the identity hash code, so we + * want to have the same restriction on Substrate VM in order to not surprise users. + */ + AnalysisError.guarantee(identityHashCode > 0, "The provided identity hashcode value must be a positive number to be on par with the Java HotSpot VM."); this.identityHashCode = identityHashCode; } @@ -139,41 +155,9 @@ public Object getReachableReason() { return constantData.isReachable; } - static int createIdentityHashCode(JavaConstant object) { - if (object == null) { - /* - * No backing object in the heap of the image builder VM. We want a "virtual" identity - * hash code that has the same properties as the image builder VM, so we use the - * identity hash code of a new and otherwise unused object in the image builder VM. - */ - return System.identityHashCode(new Object()); - } else { - /* Lazily looked up from the hostedObject when requested. */ - return -1; - } - } - @Override public int getIdentityHashCode() { - if (constantData.hostedObject != null) { - if (constantData.hostedObject.isNull()) { - /* - * According to the JavaDoc of System.identityHashCode, the identity hash code of - * null is 0. - */ - return 0; - } else { - return ((TypedConstant) constantData.hostedObject).getIdentityHashCode(); - } - } else { - /* - * No backing object in the heap of the image builder VM. We want a "virtual" identity - * hash code that has the same properties as the image builder VM, so we use the - * identity hash code of a new and otherwise unused object in the image builder VM. - */ - assert constantData.identityHashCode > 0 : "The Java HotSpot VM only returns positive numbers for the identity hash code, so we want to have the same restriction on Substrate VM in order to not surprise users"; - return constantData.identityHashCode; - } + return constantData.identityHashCode; } public JavaConstant getHostedObject() { @@ -248,7 +232,9 @@ public boolean isCompressed() { @Override public String toValueString() { if (constantData.type.getJavaClass() == String.class && constantData.hostedObject != null) { - return constantData.hostedObject.toValueString(); + String valueString = constantData.hostedObject.toValueString(); + /* HotSpotObjectConstantImpl.toValueString() puts the string between quotes. */ + return valueString.substring(1, valueString.length() - 1); } return constantData.type.getName(); } @@ -256,8 +242,11 @@ public String toValueString() { /** * Returns a new image heap instance, as if {@link Object#clone} was called on the original * object. If the type is not cloneable, then null is returned. + *

+ * The new constant is never backed by a hosted object, regardless of the input object. The + * caller must provide a unique identity hash code. */ - public abstract ImageHeapConstant forObjectClone(); + public abstract ImageHeapConstant forObjectClone(int identityHashCode); @Override public boolean equals(Object o) { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapInstance.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapInstance.java index f9844938095c..c16d15f429fd 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapInstance.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapInstance.java @@ -80,16 +80,16 @@ public static class InstanceData extends ConstantData { } } - ImageHeapInstance(AnalysisType type, JavaConstant object) { - super(new InstanceData(type, object, createIdentityHashCode(object)), false); + ImageHeapInstance(AnalysisType type, JavaConstant object, int identityHashCode) { + super(new InstanceData(type, object, identityHashCode), false); } - public ImageHeapInstance(AnalysisType type) { - this(type, null, type.getInstanceFields(true).length); + public ImageHeapInstance(AnalysisType type, int identityHashCode) { + this(type, null, type.getInstanceFields(true).length, identityHashCode); } - private ImageHeapInstance(AnalysisType type, JavaConstant object, int length) { - this(type, object, createIdentityHashCode(object), new Object[length], false); + private ImageHeapInstance(AnalysisType type, JavaConstant object, int length, int identityHashCode) { + this(type, object, identityHashCode, new Object[length], false); } private ImageHeapInstance(AnalysisType type, JavaConstant object, int identityHashCode, Object[] fieldValues, boolean compressed) { @@ -172,7 +172,7 @@ public JavaConstant uncompress() { } @Override - public ImageHeapConstant forObjectClone() { + public ImageHeapConstant forObjectClone(int identityHashCode) { if (!constantData.type.isCloneableWithAllocation()) { return null; } @@ -181,7 +181,6 @@ public ImageHeapConstant forObjectClone() { Objects.requireNonNull(fieldValues, "Cannot clone an instance before the field values are set."); Object[] newFieldValues = Arrays.copyOf(fieldValues, fieldValues.length); /* The new constant is never backed by a hosted object, regardless of the input object. */ - JavaConstant newObject = null; - return new ImageHeapInstance(constantData.type, newObject, createIdentityHashCode(newObject), newFieldValues, compressed); + return new ImageHeapInstance(constantData.type, null, identityHashCode, newFieldValues, compressed); } } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapObjectArray.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapObjectArray.java index a222b3fd3ee8..d4d5c007edba 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapObjectArray.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapObjectArray.java @@ -71,16 +71,12 @@ public ArrayData(AnalysisType type, JavaConstant object, int identityHashCode, O } } - ImageHeapObjectArray(AnalysisType type, JavaConstant object, int length) { - super(new ArrayData(type, object, createIdentityHashCode(object), length), false); + ImageHeapObjectArray(AnalysisType type, JavaConstant object, int length, int identityHashCode) { + super(new ArrayData(type, object, identityHashCode, length), false); } - ImageHeapObjectArray(AnalysisType type, int length) { - this(type, null, new Object[length], length); - } - - ImageHeapObjectArray(AnalysisType type, JavaConstant object, Object[] arrayElementValues, int length) { - this(type, object, createIdentityHashCode(object), arrayElementValues, length, false); + ImageHeapObjectArray(AnalysisType type, int length, int identityHashCode) { + this(type, null, identityHashCode, new Object[length], length, false); } private ImageHeapObjectArray(AnalysisType type, JavaConstant object, int identityHashCode, Object[] arrayElementValues, int length, boolean compressed) { @@ -161,14 +157,13 @@ public JavaConstant uncompress() { } @Override - public ImageHeapConstant forObjectClone() { + public ImageHeapConstant forObjectClone(int identityHashCode) { assert constantData.type.isCloneableWithAllocation() : "all arrays implement Cloneable"; Object[] arrayElements = getElementValues(); Objects.requireNonNull(arrayElements, "Cannot clone an array before the element values are set."); Object[] newArrayElementValues = Arrays.copyOf(arrayElements, arrayElements.length); /* The new constant is never backed by a hosted object, regardless of the input object. */ - JavaConstant newObject = null; - return new ImageHeapObjectArray(constantData.type, newObject, createIdentityHashCode(newObject), newArrayElementValues, arrayElements.length, compressed); + return new ImageHeapObjectArray(constantData.type, null, identityHashCode, newArrayElementValues, arrayElements.length, compressed); } } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapPrimitiveArray.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapPrimitiveArray.java index 931cdd2b26d0..fc76265aa058 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapPrimitiveArray.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapPrimitiveArray.java @@ -52,18 +52,18 @@ public PrimitiveArrayData(AnalysisType type, JavaConstant object, int identityHa } } - ImageHeapPrimitiveArray(AnalysisType type, int length) { + ImageHeapPrimitiveArray(AnalysisType type, int length, int identityHashCode) { this(type, null, /* Without a hosted object, we need to create a backing primitive array. */ Array.newInstance(type.getComponentType().getStorageKind().toJavaClass(), length), - createIdentityHashCode(null), false, length); + identityHashCode, false, length); } - ImageHeapPrimitiveArray(AnalysisType type, JavaConstant hostedObject, Object array, int length) { + ImageHeapPrimitiveArray(AnalysisType type, JavaConstant hostedObject, Object array, int length, int identityHashCode) { this(type, hostedObject, /* We need a clone of the hosted array so that we have a stable snapshot. */ getClone(type.getComponentType().getJavaKind(), array), - createIdentityHashCode(hostedObject), false, length); + identityHashCode, false, length); } private ImageHeapPrimitiveArray(AnalysisType type, JavaConstant hostedObject, Object array, int identityHashCode, boolean compressed, int length) { @@ -134,13 +134,12 @@ public JavaConstant uncompress() { } @Override - public ImageHeapConstant forObjectClone() { + public ImageHeapConstant forObjectClone(int identityHashCode) { assert constantData.type.isCloneableWithAllocation() : "all arrays implement Cloneable"; PrimitiveArrayData data = getConstantData(); Object newArray = getClone(data.type.getComponentType().getJavaKind(), data.array); /* The new constant is never backed by a hosted object, regardless of the input object. */ - JavaConstant newHostedObject = null; - return new ImageHeapPrimitiveArray(data.type, newHostedObject, newArray, createIdentityHashCode(newHostedObject), compressed, data.length); + return new ImageHeapPrimitiveArray(data.type, null, newArray, identityHashCode, compressed, data.length); } } 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 ae22be1b838b..80cd53da6235 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 @@ -60,6 +60,7 @@ import jdk.graal.compiler.core.common.SuppressFBWarnings; import jdk.graal.compiler.core.common.type.TypedConstant; import jdk.graal.compiler.debug.GraalError; +import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; import jdk.vm.ci.code.BytecodePosition; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; @@ -89,13 +90,15 @@ public abstract class ImageHeapScanner { protected final HostedValuesProvider hostedValuesProvider; protected final ConstantReflectionProvider hostedConstantReflection; protected final SnippetReflectionProvider hostedSnippetReflection; + private final IdentityHashCodeProvider identityHashCodeProvider; protected ObjectScanningObserver scanningObserver; private boolean sealed; public ImageHeapScanner(BigBang bb, ImageHeap heap, AnalysisMetaAccess aMetaAccess, SnippetReflectionProvider aSnippetReflection, - ConstantReflectionProvider aConstantReflection, ObjectScanningObserver aScanningObserver, HostedValuesProvider aHostedValuesProvider) { + ConstantReflectionProvider aConstantReflection, ObjectScanningObserver aScanningObserver, HostedValuesProvider aHostedValuesProvider, + IdentityHashCodeProvider identityHashCodeProvider) { this.bb = bb; imageHeap = heap; metaAccess = aMetaAccess; @@ -105,6 +108,7 @@ public ImageHeapScanner(BigBang bb, ImageHeap heap, AnalysisMetaAccess aMetaAcce constantReflection = aConstantReflection; hostedValuesProvider = aHostedValuesProvider; scanningObserver = aScanningObserver; + this.identityHashCodeProvider = identityHashCodeProvider; hostedConstantReflection = GraalAccess.getOriginalProviders().getConstantReflection(); hostedSnippetReflection = GraalAccess.getOriginalProviders().getSnippetReflection(); } @@ -195,6 +199,21 @@ public JavaConstant getImageHeapConstant(JavaConstant constant) { return constant; } + /** Create an {@link ImageHeapConstant} from a raw hosted object. */ + public JavaConstant createImageHeapConstant(Object object, ScanReason reason) { + /* + * First, get the hosted constant representation and pre-process the object if necessary, + * e.g., transform RelocatedPointer into RelocatableConstant and WordBase into Integer. + */ + JavaConstant hostedConstant = hostedValuesProvider.forObject(object); + /* Then create an {@link ImageHeapConstant} from a hosted constant. */ + return createImageHeapConstant(hostedConstant, reason); + } + + /** + * Create an {@link ImageHeapConstant} from a hosted constant, if that constant represents an + * object, otherwise return the input content. + */ public JavaConstant createImageHeapConstant(JavaConstant constant, ScanReason reason) { if (isNonNullObjectConstant(constant)) { return getOrCreateImageHeapConstant(constant, reason); @@ -259,7 +278,7 @@ protected ImageHeapConstant createImageHeapObject(JavaConstant constant, ScanRea if (type.isArray()) { Integer length = hostedValuesProvider.readArrayLength(constant); if (type.getComponentType().isPrimitive()) { - return new ImageHeapPrimitiveArray(type, constant, snippetReflection.asObject(Object.class, constant), length); + return new ImageHeapPrimitiveArray(type, constant, snippetReflection.asObject(Object.class, constant), length, getIdentityHashCode(constant, identityHashCodeProvider)); } else { return createImageHeapObjectArray(constant, type, length, reason); } @@ -269,7 +288,7 @@ protected ImageHeapConstant createImageHeapObject(JavaConstant constant, ScanRea } private ImageHeapArray createImageHeapObjectArray(JavaConstant constant, AnalysisType type, int length, ScanReason reason) { - ImageHeapObjectArray array = new ImageHeapObjectArray(type, constant, length); + ImageHeapObjectArray array = new ImageHeapObjectArray(type, constant, length, getIdentityHashCode(constant, identityHashCodeProvider)); /* Read hosted array element values only when the array is initialized. */ array.constantData.hostedValuesReader = new AnalysisFuture<>(() -> { checkSealed(reason, "Trying to materialize an ImageHeapObjectArray for %s after the ImageHeapScanner is sealed.", constant); @@ -291,7 +310,7 @@ private ImageHeapArray createImageHeapObjectArray(JavaConstant constant, Analysi } private ImageHeapInstance createImageHeapInstance(JavaConstant constant, AnalysisType type, ScanReason reason) { - ImageHeapInstance instance = new ImageHeapInstance(type, constant); + ImageHeapInstance instance = new ImageHeapInstance(type, constant, getIdentityHashCode(constant, identityHashCodeProvider)); /* Read hosted field values only when the receiver is initialized. */ instance.constantData.hostedValuesReader = new AnalysisFuture<>(() -> { checkSealed(reason, "Trying to materialize an ImageHeapInstance for %s after the ImageHeapScanner is sealed.", constant); @@ -753,6 +772,19 @@ protected AnalysisField lookupJavaField(String className, String fieldName) { return metaAccess.lookupJavaField(ReflectionUtil.lookupField(getClass(className), fieldName)); } + public static int getIdentityHashCode(JavaConstant constant, IdentityHashCodeProvider identityHashCodeProvider) { + if (constant != null) { + return identityHashCodeProvider.identityHashCode(constant); + } else { + /* + * No backing object in the heap of the image builder VM. We want a "virtual" identity + * hash code that has the same properties as the image builder VM, so we use the + * identity hash code of a new and otherwise unused object in the image builder VM. + */ + return identityHashCodeProvider.identityHashCode(GraalAccess.getOriginalSnippetReflection().forObject(new Object())); + } + } + /** * When a re-scanning is triggered while the analysis is running in parallel, it is necessary to * do the re-scanning in a separate executor task to avoid deadlocks. For example, 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 aaac01db0757..a57b5530d159 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 @@ -1008,7 +1008,7 @@ public boolean isAssignableFrom(ResolvedJavaType other) { @Override public boolean isInstance(JavaConstant obj) { - return wrapped.isInstance(universe.toHosted(obj)); + return wrapped.isInstance(obj); } @Override 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 0abc9ab1c7aa..6430e888bfa2 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 @@ -48,7 +48,6 @@ import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException; import com.oracle.graal.pointsto.heap.HeapSnapshotVerifier; import com.oracle.graal.pointsto.heap.HostedValuesProvider; -import com.oracle.graal.pointsto.heap.ImageHeapConstant; import com.oracle.graal.pointsto.heap.ImageHeapScanner; import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider; import com.oracle.graal.pointsto.infrastructure.ResolvedSignature; @@ -58,7 +57,6 @@ import com.oracle.graal.pointsto.infrastructure.WrappedJavaType; import com.oracle.graal.pointsto.meta.AnalysisType.UsageKind; import com.oracle.graal.pointsto.util.AnalysisError; -import com.oracle.graal.pointsto.util.GraalAccess; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; import jdk.graal.compiler.core.common.SuppressFBWarnings; @@ -483,44 +481,7 @@ 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()) { - Object original = GraalAccess.getOriginalSnippetReflection().asObject(Object.class, constant); - if (original instanceof ImageHeapConstant) { - /* - * The value is an ImageHeapObject, i.e., it already has a build time - * representation, so there is no need to re-wrap it. The value likely comes from - * reading a field of a normal object that is referencing a simulated object. The - * originalConstantReflection provider is not aware of simulated constants, and it - * always wraps them into a HotSpotObjectConstant when reading fields. - */ - return (JavaConstant) original; - } - return getHostedValuesProvider().forObject(original); - } else { - return constant; - } - } - - /** - * Convert a hosted SubstrateObjectConstant into a HotSpotObjectConstant. - */ - public JavaConstant toHosted(JavaConstant constant) { - if (constant == null) { - return null; - } else if (constant.getJavaKind().isObject() && !constant.isNull()) { - return GraalAccess.getOriginalSnippetReflection().forObject(getHostedValuesProvider().asObject(Object.class, constant)); - } else { - return constant; - } + return heapScanner.createImageHeapConstant(getHostedValuesProvider().interceptHosted(constant), ObjectScanner.OtherReason.UNKNOWN); } public List getTypes() { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/HostedProviders.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/HostedProviders.java index 6c85fa051ed4..b40dc17324fa 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/HostedProviders.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/HostedProviders.java @@ -29,6 +29,7 @@ import jdk.graal.compiler.core.common.spi.ForeignCallsProvider; import jdk.graal.compiler.core.common.spi.MetaAccessExtensionProvider; import jdk.graal.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration; +import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; import jdk.graal.compiler.nodes.spi.LoopsDataProvider; import jdk.graal.compiler.nodes.spi.LoweringProvider; import jdk.graal.compiler.nodes.spi.PlatformConfigurationProvider; @@ -36,7 +37,6 @@ import jdk.graal.compiler.nodes.spi.StampProvider; import jdk.graal.compiler.phases.util.Providers; import jdk.graal.compiler.word.WordTypes; - import jdk.vm.ci.code.CodeCacheProvider; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.MetaAccessProvider; @@ -47,9 +47,10 @@ public class HostedProviders extends Providers { public HostedProviders(MetaAccessProvider metaAccess, CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, ForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, SnippetReflectionProvider snippetReflection, - WordTypes wordTypes, PlatformConfigurationProvider platformConfigurationProvider, MetaAccessExtensionProvider metaAccessExtensionProvider, LoopsDataProvider loopsDataProvider) { + WordTypes wordTypes, PlatformConfigurationProvider platformConfigurationProvider, MetaAccessExtensionProvider metaAccessExtensionProvider, LoopsDataProvider loopsDataProvider, + IdentityHashCodeProvider identityHashCodeProvider) { super(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, metaAccessExtensionProvider, - snippetReflection, wordTypes, loopsDataProvider); + snippetReflection, wordTypes, loopsDataProvider, identityHashCodeProvider); } public GraphBuilderConfiguration.Plugins getGraphBuilderPlugins() { @@ -64,20 +65,20 @@ public void setGraphBuilderPlugins(GraphBuilderConfiguration.Plugins graphBuilde public HostedProviders copyWith(ConstantReflectionProvider substitution) { assert this.getClass() == HostedProviders.class : "must override in " + getClass(); return new HostedProviders(getMetaAccess(), getCodeCache(), substitution, getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getStampProvider(), - getSnippetReflection(), getWordTypes(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider()); + getSnippetReflection(), getWordTypes(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider(), getIdentityHashCodeProvider()); } @Override public HostedProviders copyWith(ConstantFieldProvider substitution) { assert this.getClass() == HostedProviders.class : "must override in " + getClass(); return new HostedProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), substitution, getForeignCalls(), getLowerer(), getReplacements(), getStampProvider(), - getSnippetReflection(), getWordTypes(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider()); + getSnippetReflection(), getWordTypes(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider(), getIdentityHashCodeProvider()); } @Override public HostedProviders copyWith(Replacements substitution) { assert this.getClass() == HostedProviders.class : "must override in " + getClass(); return new HostedProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), substitution, getStampProvider(), - getSnippetReflection(), getWordTypes(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider()); + getSnippetReflection(), getWordTypes(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider(), getIdentityHashCodeProvider()); } } 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 33fe95470967..c38c28ab0b74 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 @@ -175,10 +175,10 @@ private static boolean isImmutable(Object o) { } @Platforms(Platform.HOSTED_ONLY.class) - public Collection getSnippetGraphs(boolean trackNodeSourcePosition, OptionValues options) { + public Collection getSnippetGraphs(boolean trackNodeSourcePosition, OptionValues options, Function objectTransformer) { List result = new ArrayList<>(snippetStartOffsets.size()); for (ResolvedJavaMethod method : snippetStartOffsets.keySet()) { - result.add(getSnippet(method, null, null, null, trackNodeSourcePosition, null, options)); + result.add(getSnippet(method, null, trackNodeSourcePosition, options, objectTransformer)); } return result; } @@ -206,6 +206,10 @@ public void setGraphBuilderPlugins(Plugins plugins) { @Override public StructuredGraph getSnippet(ResolvedJavaMethod method, ResolvedJavaMethod recursiveEntry, Object[] args, BitSet nonNullParameters, boolean trackNodeSourcePosition, NodeSourcePosition replaceePosition, OptionValues options) { + return getSnippet(method, args, trackNodeSourcePosition, options, Function.identity()); + } + + public StructuredGraph getSnippet(ResolvedJavaMethod method, Object[] args, boolean trackNodeSourcePosition, OptionValues options, Function objectTransformer) { Integer startOffset = snippetStartOffsets.get(method); if (startOffset == null) { throw VMError.shouldNotReachHere("snippet not found: " + method.format("%H.%n(%p)")); @@ -246,6 +250,11 @@ protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod lookupMethod, Bytec public IntrinsicContext getIntrinsic() { return intrinsic; } + + @Override + protected Object readObject(MethodScope methodScope) { + return objectTransformer.apply(super.readObject(methodScope)); + } }; graphDecoder.decode(method); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/DirectSubstrateObjectConstant.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/DirectSubstrateObjectConstant.java index 8faf816ec642..0e2353201cc7 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/DirectSubstrateObjectConstant.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/DirectSubstrateObjectConstant.java @@ -26,7 +26,9 @@ import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.Uninterruptible; +import com.oracle.svm.core.util.VMError; +import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; import jdk.vm.ci.meta.MetaAccessProvider; import jdk.vm.ci.meta.ResolvedJavaType; @@ -35,10 +37,18 @@ public final class DirectSubstrateObjectConstant extends SubstrateObjectConstant /** The raw object wrapped by this constant. */ private final Object object; + /** + * The identity hash code for this constant. It may or may not be the same as of the identity + * hashcode of the object. When the constant is used during image build the value is provided + * via {@link IdentityHashCodeProvider}. When used for run time JIT compilation the initial + * value is 0, and it is computed lazily. + */ + private int identityHashCode; - DirectSubstrateObjectConstant(Object object, boolean compressed) { + DirectSubstrateObjectConstant(Object object, boolean compressed, int identityHashCode) { super(compressed); this.object = object; + this.identityHashCode = identityHashCode; assert object != null; if (SubstrateUtil.isInLibgraal()) { throw new InternalError(); @@ -58,18 +68,22 @@ public ResolvedJavaType getType(MetaAccessProvider provider) { @Override public SubstrateObjectConstant compress() { assert !compressed; - return new DirectSubstrateObjectConstant(object, true); + return new DirectSubstrateObjectConstant(object, true, identityHashCode); } @Override public SubstrateObjectConstant uncompress() { assert compressed; - return new DirectSubstrateObjectConstant(object, false); + return new DirectSubstrateObjectConstant(object, false, identityHashCode); } @Override public int getIdentityHashCode() { - return computeIdentityHashCode(object); + if (identityHashCode == 0) { + VMError.guarantee(!SubstrateUtil.HOSTED); + identityHashCode = computeIdentityHashCode(object); + } + return identityHashCode; } @Override diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstant.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstant.java index df1841f343ad..faacdafe295c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstant.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/meta/SubstrateObjectConstant.java @@ -24,13 +24,10 @@ */ package com.oracle.svm.core.meta; -import jdk.graal.compiler.core.common.type.CompressibleConstant; -import jdk.graal.compiler.core.common.type.TypedConstant; - -import com.oracle.svm.core.SubstrateUtil; -import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.util.ClassUtil; +import jdk.graal.compiler.core.common.type.CompressibleConstant; +import jdk.graal.compiler.core.common.type.TypedConstant; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; @@ -39,14 +36,22 @@ public abstract class SubstrateObjectConstant implements JavaConstant, TypedConstant, CompressibleConstant, VMConstant { public static JavaConstant forObject(Object object) { - return forObject(object, false); + return forObject(object, false, 0); + } + + public static JavaConstant forObject(Object object, int identityHashCode) { + return forObject(object, false, identityHashCode); } public static JavaConstant forObject(Object object, boolean compressed) { + return forObject(object, compressed, 0); + } + + public static JavaConstant forObject(Object object, boolean compressed, int identityHashCode) { if (object == null) { return compressed ? CompressedNullConstant.COMPRESSED_NULL : JavaConstant.NULL_POINTER; } - return new DirectSubstrateObjectConstant(object, compressed); + return new DirectSubstrateObjectConstant(object, compressed, identityHashCode); } public static JavaConstant forBoxedValue(JavaKind kind, Object value) { @@ -157,17 +162,8 @@ public final int hashCode() { return getIdentityHashCode(); } - public static int computeIdentityHashCode(Object object) { - if (SubstrateUtil.HOSTED && object instanceof DynamicHub) { - /* - * We need to use the identity hash code of the original java.lang.Class object and not - * of the DynamicHub, so that hash maps that are filled during image generation and use - * Class keys still work at run time. - */ - return System.identityHashCode(((DynamicHub) object).getHostedJavaClass()); - } else { - return System.identityHashCode(object); - } + protected static int computeIdentityHashCode(Object object) { + return System.identityHashCode(object); } @Override diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/SubstrateGraalUtils.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/SubstrateGraalUtils.java index a51146d9b748..6dd4756a429e 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/SubstrateGraalUtils.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/SubstrateGraalUtils.java @@ -34,6 +34,8 @@ import org.graalvm.nativeimage.ImageSingletons; import com.oracle.graal.pointsto.heap.ImageHeapConstant; +import com.oracle.graal.pointsto.heap.ImageHeapScanner; +import com.oracle.graal.pointsto.util.GraalAccess; import com.oracle.svm.core.CPUFeatureAccess; import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.graal.code.SubstrateCompilationIdentifier; @@ -63,6 +65,7 @@ import jdk.graal.compiler.phases.OptimisticOptimizations; import jdk.graal.compiler.phases.tiers.Suites; import jdk.vm.ci.code.Architecture; +import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.JavaConstant; public class SubstrateGraalUtils { @@ -194,23 +197,37 @@ private static CompilationResult compileGraph(RuntimeConfiguration runtimeConfig } /** Prepares a hosted {@link JavaConstant} for runtime compilation. */ - public static JavaConstant forRuntimeCompilation(JavaConstant constant) { + public static JavaConstant hostedToRuntime(JavaConstant constant) { if (constant instanceof ImageHeapConstant heapConstant) { - return forRuntimeCompilation(heapConstant); + return hostedToRuntime(heapConstant); } return constant; } /** - * Prepares a hosted {@link ImageHeapConstant} for runtime compilation. For now this simply - * returns the hosted object which already is a {@link SubstrateObjectConstant}. When the - * {@link ImageHeapConstant} will reference a HotSpot constant directly (GR-50240), this code - * will have to do its own wrapping. + * Prepares a hosted {@link ImageHeapConstant} for runtime compilation: it unwraps the + * {@link HotSpotObjectConstant} and wraps the hosted object into a + * {@link SubstrateObjectConstant}. We reuse the identity hash code of the heap constant. */ - public static JavaConstant forRuntimeCompilation(ImageHeapConstant heapConstant) { - JavaConstant hostedObject = heapConstant.getHostedObject(); - VMError.guarantee(hostedObject instanceof SubstrateObjectConstant, "Expected to find SubstrateObjectConstant, found %s", heapConstant); - return hostedObject; + public static JavaConstant hostedToRuntime(ImageHeapConstant heapConstant) { + JavaConstant hostedConstant = heapConstant.getHostedObject(); + VMError.guarantee(hostedConstant instanceof HotSpotObjectConstant, "Expected to find HotSpotObjectConstant, found %s", hostedConstant); + Object hostedObject = GraalAccess.getOriginalSnippetReflection().asObject(Object.class, hostedConstant); + return SubstrateObjectConstant.forObject(hostedObject, heapConstant.getIdentityHashCode()); + } + + /** + * Transforms a {@link SubstrateObjectConstant} from an encoded graph into an + * {@link ImageHeapConstant} for hosted processing: it unwraps the hosted object from the + * {@link SubstrateObjectConstant}, wraps it into an {@link HotSpotObjectConstant}, then + * redirects the lookup through the {@link ImageHeapScanner}. + */ + public static JavaConstant runtimeToHosted(JavaConstant constant, ImageHeapScanner scanner) { + if (constant instanceof SubstrateObjectConstant) { + JavaConstant hostedConstant = GraalAccess.getOriginalSnippetReflection().forObject(SubstrateObjectConstant.asObject(constant)); + return scanner.getImageHeapConstant(hostedConstant); + } + return constant; } } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/GraalGraphObjectReplacer.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/GraalGraphObjectReplacer.java index 54001ea2e1c4..b3ba0d9ab363 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/GraalGraphObjectReplacer.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/GraalGraphObjectReplacer.java @@ -203,7 +203,7 @@ public Object apply(Object source) { } else if (source instanceof FieldLocationIdentity && !(source instanceof SubstrateFieldLocationIdentity)) { dest = createFieldLocationIdentity((FieldLocationIdentity) source); } else if (source instanceof ImageHeapConstant heapConstant) { - dest = SubstrateGraalUtils.forRuntimeCompilation(heapConstant); + dest = SubstrateGraalUtils.hostedToRuntime(heapConstant); } assert dest != null; @@ -458,7 +458,7 @@ public void updateSubstrateDataAfterCompilation(HostedUniverse hUniverse, Provid JavaConstant constantValue = hField.isStatic() && ((HostedConstantFieldProvider) providers.getConstantFieldProvider()).isFinalField(hField, null) ? providers.getConstantReflection().readFieldValue(hField, null) : null; - constantValue = SubstrateGraalUtils.forRuntimeCompilation(constantValue); + constantValue = SubstrateGraalUtils.hostedToRuntime(constantValue); sField.setSubstrateData(hField.getLocation(), hField.isAccessed(), hField.isWritten() || !hField.isValueAvailable(), constantValue); } } diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationFeature.java index 41c78163bf82..9be4c2d93382 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompilationFeature.java @@ -87,6 +87,7 @@ import com.oracle.svm.core.util.VMError; import com.oracle.svm.graal.GraalSupport; import com.oracle.svm.graal.SubstrateGraalRuntime; +import com.oracle.svm.graal.SubstrateGraalUtils; import com.oracle.svm.graal.TruffleRuntimeCompilationSupport; import com.oracle.svm.graal.hosted.DeoptimizationFeature; import com.oracle.svm.graal.hosted.FieldsOffsetsFeature; @@ -144,6 +145,7 @@ import jdk.graal.compiler.phases.tiers.Suites; import jdk.graal.compiler.phases.util.Providers; import jdk.graal.compiler.truffle.phases.DeoptimizeOnExceptionPhase; +import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.JavaType; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -386,7 +388,7 @@ private void installRuntimeConfig(BeforeAnalysisAccessImpl config) { runtimeProviders.getForeignCalls(), runtimeProviders.getLowerer(), runtimeProviders.getReplacements(), runtimeProviders.getStampProvider(), runtimeConfig.getProviders().getSnippetReflection(), runtimeProviders.getWordTypes(), runtimeProviders.getPlatformConfigurationProvider(), new GraphPrepareMetaAccessExtensionProvider(), - runtimeProviders.getLoopsDataProvider()); + runtimeProviders.getLoopsDataProvider(), runtimeProviders.getIdentityHashCodeProvider()); FeatureHandler featureHandler = config.getFeatureHandler(); final boolean supportsStubBasedPlugins = !SubstrateOptions.useLLVMBackend(); @@ -432,10 +434,22 @@ public void beforeAnalysis(BeforeAnalysisAccess c) { for (NodeClass nodeClass : replacements.getSnippetNodeClasses()) { config.getMetaAccess().lookupJavaType(nodeClass.getClazz()).registerAsAllocated("All " + NodeClass.class.getName() + " classes are marked as instantiated eagerly."); } + + /* + * The snippet graphs are prepared for runtime compilation by the + * RuntimeCompilationGraphEncoder, so constants are represented as SubstrateObjectConstant. + * Get back the ImageHeapConstant. + */ + Function objectTransformer = (object) -> { + if (object instanceof JavaConstant constant) { + return SubstrateGraalUtils.runtimeToHosted(constant, config.getUniverse().getHeapScanner()); + } + return object; + }; /* * Ensure runtime snippet graphs are analyzed. */ - NativeImageGenerator.performSnippetGraphAnalysis(config.getBigBang(), replacements, config.getBigBang().getOptions()); + NativeImageGenerator.performSnippetGraphAnalysis(config.getBigBang(), replacements, config.getBigBang().getOptions(), objectTransformer); /* * Ensure that all snippet methods have their SubstrateMethod object created by the object diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompiledMethodSupport.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompiledMethodSupport.java index 471a576d55b0..646b17f02440 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompiledMethodSupport.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/runtimecompilation/RuntimeCompiledMethodSupport.java @@ -373,12 +373,12 @@ public RuntimeCompilationGraphEncoder(Architecture architecture, ImageHeapScanne @Override protected void addObject(Object object) { - super.addObject(forRuntimeCompilation(object)); + super.addObject(hostedToRuntime(object)); } @Override protected void writeObjectId(Object object) { - super.writeObjectId(forRuntimeCompilation(object)); + super.writeObjectId(hostedToRuntime(object)); } @Override @@ -386,11 +386,11 @@ protected GraphDecoder graphDecoderForVerification(StructuredGraph decodedGraph) return new RuntimeCompilationGraphDecoder(architecture, decodedGraph, heapScanner); } - private Object forRuntimeCompilation(Object object) { + private Object hostedToRuntime(Object object) { if (object instanceof ImageHeapConstant heapConstant) { - return SubstrateGraalUtils.forRuntimeCompilation(heapConstant); + return SubstrateGraalUtils.hostedToRuntime(heapConstant); } else if (object instanceof ObjectLocationIdentity oli && oli.getObject() instanceof ImageHeapConstant heapConstant) { - return locationIdentityCache.computeIfAbsent(heapConstant, (hc) -> ObjectLocationIdentity.create(SubstrateGraalUtils.forRuntimeCompilation(hc))); + return locationIdentityCache.computeIfAbsent(heapConstant, (hc) -> ObjectLocationIdentity.create(SubstrateGraalUtils.hostedToRuntime(hc))); } return object; } @@ -415,9 +415,9 @@ static class RuntimeCompilationGraphDecoder extends GraphDecoder { protected Object readObject(MethodScope methodScope) { Object object = super.readObject(methodScope); if (object instanceof JavaConstant constant) { - return heapScanner.getImageHeapConstant(constant); + return SubstrateGraalUtils.runtimeToHosted(constant, heapScanner); } else if (object instanceof ObjectLocationIdentity oli) { - return locationIdentityCache.computeIfAbsent(oli.getObject(), (obj) -> ObjectLocationIdentity.create(heapScanner.getImageHeapConstant(obj))); + return locationIdentityCache.computeIfAbsent(oli.getObject(), (constant) -> ObjectLocationIdentity.create(SubstrateGraalUtils.runtimeToHosted(constant, heapScanner))); } return object; } 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 c6a0b344f6a5..6843a98c64a6 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 @@ -49,6 +49,7 @@ import jdk.graal.compiler.core.common.spi.ConstantFieldProvider; import jdk.graal.compiler.core.common.spi.ForeignCallsProvider; import jdk.graal.compiler.core.common.spi.MetaAccessExtensionProvider; +import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; import jdk.graal.compiler.nodes.spi.LoopsDataProvider; import jdk.graal.compiler.nodes.spi.LoweringProvider; import jdk.graal.compiler.nodes.spi.PlatformConfigurationProvider; @@ -75,9 +76,10 @@ public SubstrateRuntimeConfigurationBuilder(OptionValues options, SVMHost hostVM @Override protected Providers createProviders(CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, ForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, SnippetReflectionProvider reflectionProvider, - PlatformConfigurationProvider platformConfigurationProvider, MetaAccessExtensionProvider metaAccessExtensionProvider, WordTypes wordTypes, LoopsDataProvider loopsDataProvider) { + PlatformConfigurationProvider platformConfigurationProvider, MetaAccessExtensionProvider metaAccessExtensionProvider, WordTypes wordTypes, LoopsDataProvider loopsDataProvider, + IdentityHashCodeProvider identityHashCodeProvider) { return new Providers(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, platformConfigurationProvider, - metaAccessExtensionProvider, reflectionProvider, wordTypes, loopsDataProvider); + metaAccessExtensionProvider, reflectionProvider, wordTypes, loopsDataProvider, identityHashCodeProvider); } @Override @@ -108,4 +110,9 @@ protected SharedCodeCacheProvider createCodeCacheProvider(RegisterConfig registe } return new SubstrateCodeCacheProvider(ConfigurationValues.getTarget(), registerConfig); } + + @Override + protected IdentityHashCodeProvider createIdentityHashCodeProvider() { + return new IdentityHashCodeProvider(snippetReflection); + } } 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 3e21525e0ae1..debcdb7e1784 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 @@ -55,6 +55,7 @@ import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.function.BooleanSupplier; +import java.util.function.Function; import org.graalvm.collections.EconomicMap; import org.graalvm.collections.EconomicSet; @@ -219,6 +220,7 @@ import com.oracle.svm.hosted.code.CFunctionSubstitutionProcessor; import com.oracle.svm.hosted.code.CompileQueue; import com.oracle.svm.hosted.code.DynamicMethodAddressResolutionHostedSupport; +import com.oracle.svm.hosted.code.HostedIdentityHashCodeProvider; import com.oracle.svm.hosted.code.HostedRuntimeConfigurationBuilder; import com.oracle.svm.hosted.code.NativeMethodSubstitutionProcessor; import com.oracle.svm.hosted.code.RestrictHeapAccessCalleesImpl; @@ -948,7 +950,7 @@ protected void setupNativeImage(OptionValues options, Map snippetGraphs = replacements.getSnippetGraphs(GraalOptions.TrackNodeSourcePosition.getValue(options), options); + public static void performSnippetGraphAnalysis(BigBang bb, SubstrateReplacements replacements, OptionValues options, Function objectTransformer) { + Collection snippetGraphs = replacements.getSnippetGraphs(GraalOptions.TrackNodeSourcePosition.getValue(options), options, objectTransformer); if (bb instanceof NativeImagePointsToAnalysis pointsToAnalysis) { for (StructuredGraph graph : snippetGraphs) { MethodTypeFlowBuilder.registerUsedElements(pointsToAnalysis, graph); @@ -1184,7 +1186,8 @@ private static HostedProviders createHostedProviders(TargetDescription target, A StampProvider aStampProvider = new SubstrateStampProvider(aMetaAccess); HostedProviders aProviders = new HostedProviders(aMetaAccess, null, aConstantReflection, aConstantFieldProvider, aForeignCalls, aLoweringProvider, null, aStampProvider, aSnippetReflection, - aWordTypes, platformConfig, aMetaAccessExtensionProvider, originalProviders.getLoopsDataProvider()); + aWordTypes, platformConfig, aMetaAccessExtensionProvider, originalProviders.getLoopsDataProvider(), + new HostedIdentityHashCodeProvider(originalProviders.getSnippetReflection())); BytecodeProvider bytecodeProvider = new ResolvedJavaMethodBytecodeProvider(); SubstrateReplacements aReplacements = new SubstrateReplacements(aProviders, bytecodeProvider, target, new SubstrateGraphMakerFactory()); 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 c07898a99d3b..f2620d27d2b2 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 @@ -43,7 +43,6 @@ import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.util.AnalysisError; import com.oracle.svm.core.hub.DynamicHub; -import com.oracle.svm.core.meta.SubstrateObjectConstant; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.classinitialization.SimulateClassInitializerSupport; @@ -93,7 +92,7 @@ public MemoryAccessProvider getMemoryAccessProvider() { @Override public JavaConstant unboxPrimitive(JavaConstant source) { - if (!source.getJavaKind().isObject()) { + if (!source.getJavaKind().isObject() || source.isNull()) { return null; } ImageHeapConstant imageHeapConstant = (ImageHeapConstant) source; @@ -260,7 +259,7 @@ public ResolvedJavaType asJavaType(Constant constant) { @Override public JavaConstant asJavaClass(ResolvedJavaType type) { - return universe.getHeapScanner().createImageHeapConstant(asConstant(getHostVM().dynamicHub(type)), ObjectScanner.OtherReason.UNKNOWN); + return universe.getHeapScanner().createImageHeapConstant(getHostVM().dynamicHub(type), ObjectScanner.OtherReason.UNKNOWN); } @Override @@ -277,11 +276,7 @@ public JavaConstant forString(String value) { if (value == null) { return JavaConstant.NULL_POINTER; } - return universe.getHeapScanner().createImageHeapConstant(asConstant(value), ObjectScanner.OtherReason.UNKNOWN); - } - - private static JavaConstant asConstant(Object object) { - return SubstrateObjectConstant.forObject(object); + return universe.getHeapScanner().createImageHeapConstant(value, ObjectScanner.OtherReason.UNKNOWN); } private SVMHost getHostVM() { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/SVMHostedValueProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/SVMHostedValueProvider.java index 86a68f179a8f..faa6403e896e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/SVMHostedValueProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/SVMHostedValueProvider.java @@ -24,24 +24,26 @@ */ package com.oracle.svm.hosted.ameta; -import java.lang.reflect.Array; +import java.util.Optional; import org.graalvm.nativeimage.c.function.RelocatedPointer; import org.graalvm.word.WordBase; import com.oracle.graal.pointsto.heap.HostedValuesProvider; +import com.oracle.graal.pointsto.heap.ImageHeapConstant; import com.oracle.graal.pointsto.heap.value.ValueSupplier; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisUniverse; +import com.oracle.graal.pointsto.util.AnalysisError; import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.meta.SubstrateObjectConstant; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.classinitialization.SimulateClassInitializerSupport; -import com.oracle.svm.hosted.meta.HostedSnippetReflectionProvider; import com.oracle.svm.hosted.meta.RelocatableConstant; +import jdk.vm.ci.hotspot.HotSpotObjectConstant; +import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; -import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.PrimitiveConstant; public class SVMHostedValueProvider extends HostedValuesProvider { @@ -84,8 +86,8 @@ public JavaConstant readFieldValueWithReplacement(AnalysisField field, JavaConst } private JavaConstant doReadValue(AnalysisField field, JavaConstant receiver) { - JavaConstant hostedReceiver = universe.toHosted(receiver); - return universe.fromHosted(fieldValueInterceptionSupport.readFieldValue(field, hostedReceiver)); + VMError.guarantee(!(receiver instanceof SubstrateObjectConstant)); + return interceptHosted(fieldValueInterceptionSupport.readFieldValue(field, receiver)); } /** @@ -94,33 +96,8 @@ private JavaConstant doReadValue(AnalysisField field, JavaConstant receiver) { */ @Override public JavaConstant readArrayElement(JavaConstant array, int index) { - if (array.getJavaKind() != JavaKind.Object || array.isNull()) { - return null; - } - Object a = SubstrateObjectConstant.asObject(array); - - if (!a.getClass().isArray() || index < 0 || index >= Array.getLength(a)) { - return null; - } - - if (a instanceof Object[]) { - Object element = ((Object[]) a)[index]; - return forObject(element); - } else { - return JavaConstant.forBoxedPrimitive(Array.get(a, index)); - } - } - - @Override - public Integer readArrayLength(JavaConstant array) { - if (array.getJavaKind() != JavaKind.Object || array.isNull()) { - return null; - } - Object a = SubstrateObjectConstant.asObject(array); - if (!a.getClass().isArray()) { - return null; - } - return java.lang.reflect.Array.getLength(a); + JavaConstant element = super.readArrayElement(array, index); + return interceptWordType(super.asObject(Object.class, element)).orElse(element); } /** @@ -136,13 +113,9 @@ public JavaConstant validateReplacedConstant(JavaConstant value) { @Override public JavaConstant forObject(Object object) { - if (object instanceof RelocatedPointer pointer) { - return new RelocatableConstant(pointer); - } else if (object instanceof WordBase word) { - return JavaConstant.forIntegerKind(ConfigurationValues.getWordKind(), word.rawValue()); - } - HostedSnippetReflectionProvider.validateRawObjectConstant(object); - return SubstrateObjectConstant.forObject(object); + /* The raw object may never be an ImageHeapConstant. */ + AnalysisError.guarantee(!(object instanceof ImageHeapConstant), "Unexpected ImageHeapConstant %s", object); + return interceptWordType(object).orElse(super.forObject(object)); } @Override @@ -150,7 +123,55 @@ public T asObject(Class type, JavaConstant constant) { if (constant instanceof RelocatableConstant relocatable) { return type.cast(relocatable.getPointer()); } - return SubstrateObjectConstant.asObject(type, constant); + return super.asObject(type, constant); + } + + /** + * Intercept hosted objects that need special treatment. + *

    + *
  • First, we allow hosted objects to reference {@link ImageHeapConstant} directly. This is + * useful for example when encoding heap partition limits. Instead of referencing the raw hosted + * object from ImageHeapInfo we reference a {@link ImageHeapConstant} which allows using + * simulated constant as partition limits. However, since the original + * {@link ConstantReflectionProvider} is not aware of {@link ImageHeapConstant} it always treats + * them as hosted objects and wraps them into a {@link HotSpotObjectConstant}. Therefore, we + * need intercept the {@link HotSpotObjectConstant} and if it wraps an {@link ImageHeapConstant} + * unwrap it and return the original constant.
  • + *
  • Second, intercept {@link WordBase} constants. See {@link #interceptWordType(Object)} for + * details.
  • + *
+ * This method will return null if the input constant is null. + */ + @Override + public JavaConstant interceptHosted(JavaConstant constant) { + if (constant != null && constant.getJavaKind().isObject() && !constant.isNull()) { + Object original = super.asObject(Object.class, constant); + if (original instanceof ImageHeapConstant heapConstant) { + return heapConstant; + } + /* Intercept WordBase and RelocatedPointer objects, otherwise return input constant. */ + return interceptWordType(original).orElse(constant); + } + return constant; + } + + /** + * Intercept {@link WordBase} constants and: + *
    + *
  • replace {@link RelocatedPointer} constants with {@link RelocatableConstant} to easily and + * reliably distinguish them from other {@link WordBase} values during image build.
  • + *
  • replace regular {@link WordBase} values with corresponding integer kind + * {@link PrimitiveConstant}.
  • + *
+ */ + private static Optional interceptWordType(Object object) { + if (object instanceof RelocatedPointer pointer) { + return Optional.of(new RelocatableConstant(pointer)); + } + if (object instanceof WordBase word) { + return Optional.of(JavaConstant.forIntegerKind(ConfigurationValues.getWordKind(), word.rawValue())); + } + return Optional.empty(); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializerGraphBuilderPhase.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializerGraphBuilderPhase.java index e70ac9ea2eac..ca8b7c800107 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializerGraphBuilderPhase.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/ClassInitializerGraphBuilderPhase.java @@ -61,7 +61,8 @@ private static Providers clearWordTypes(CoreProviders providers) { providers.getMetaAccessExtensionProvider(), providers.getSnippetReflection(), wordTypes, - providers.getLoopsDataProvider()); + providers.getLoopsDataProvider(), + providers.getIdentityHashCodeProvider()); } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/SimulateClassInitializerGraphDecoder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/SimulateClassInitializerGraphDecoder.java index bc5a2dc3e32f..0cd5fada944d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/SimulateClassInitializerGraphDecoder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/classinitialization/SimulateClassInitializerGraphDecoder.java @@ -58,6 +58,7 @@ import com.oracle.graal.pointsto.heap.ImageHeapArray; import com.oracle.graal.pointsto.heap.ImageHeapConstant; import com.oracle.graal.pointsto.heap.ImageHeapInstance; +import com.oracle.graal.pointsto.heap.ImageHeapScanner; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisType; import com.oracle.graal.pointsto.phases.InlineBeforeAnalysisGraphDecoder; @@ -441,7 +442,7 @@ private Node handleAllocatedObjectNode(AllocatedObjectNode node) { private ValueNode handleNewInstanceNode(SimulateClassInitializerInlineScope countersScope, NewInstanceNode node) { var type = (AnalysisType) node.instanceClass(); if (accumulateNewInstanceSize(countersScope, type, node)) { - var instance = new ImageHeapInstance(type); + var instance = new ImageHeapInstance(type, getIdentityHashCode()); for (var field : type.getInstanceFields(true)) { var aField = (AnalysisField) field; instance.setFieldValue(aField, JavaConstant.defaultForKind(aField.getStorageKind())); @@ -463,7 +464,7 @@ private ValueNode handleNewArrayNode(SimulateClassInitializerInlineScope counter } protected ImageHeapArray createNewArray(AnalysisType arrayType, int length) { - var array = ImageHeapArray.create(arrayType, length); + var array = ImageHeapArray.create(arrayType, length, getIdentityHashCode()); var defaultValue = JavaConstant.defaultForKind(arrayType.getComponentType().getStorageKind()); for (int i = 0; i < length; i++) { array.setElement(i, defaultValue); @@ -503,7 +504,7 @@ private ImageHeapArray createNewMultiArray(AnalysisType curArrayType, int curDim } var nextArrayType = curArrayType.getComponentType(); - var array = ImageHeapArray.create(curArrayType, dimensions[curDimension]); + var array = ImageHeapArray.create(curArrayType, dimensions[curDimension], getIdentityHashCode()); for (int i = 0; i < curLength; i++) { array.setElement(i, createNewMultiArray(nextArrayType, nextDimension, dimensions)); } @@ -541,7 +542,7 @@ private ValueNode handleObjectClone(SimulateClassInitializerInlineScope counters var type = originalImageHeapConstant.getType(); if ((originalImageHeapConstant instanceof ImageHeapArray originalArray && accumulateNewArraySize(countersScope, type, originalArray.getLength(), node.asNode())) || (type.isCloneableWithAllocation() && accumulateNewInstanceSize(countersScope, type, node.asNode()))) { - var cloned = originalImageHeapConstant.forObjectClone(); + var cloned = originalImageHeapConstant.forObjectClone(getIdentityHashCode()); currentActiveObjects.add(cloned); return ConstantNode.forConstant(cloned, metaAccess); } @@ -556,7 +557,7 @@ private ValueNode handleObjectClone(SimulateClassInitializerInlineScope counters var arrayType = (AnalysisType) metaAccess.lookupJavaType(original); Integer length = providers.getConstantReflection().readArrayLength(original); if (length != null && accumulateNewArraySize(countersScope, arrayType, length, node.asNode())) { - var array = ImageHeapArray.create(arrayType, length); + var array = ImageHeapArray.create(arrayType, length, getIdentityHashCode()); for (int i = 0; i < length; i++) { array.setElement(i, adaptForImageHeap(providers.getConstantReflection().readArrayElement(original, i), arrayType.getComponentType().getStorageKind())); } @@ -618,7 +619,7 @@ private boolean handleVirtualInstance(SimulateClassInitializerInlineScope counte if (!accumulateNewInstanceSize(countersScope, type, reason)) { return false; } - var instance = new ImageHeapInstance(type); + var instance = new ImageHeapInstance(type, getIdentityHashCode()); for (int j = 0; j < virtualInstance.entryCount(); j++) { var entry = lookupConstantEntry(j, entries); if (entry == null) { @@ -642,7 +643,7 @@ private boolean handleVirtualArray(SimulateClassInitializerInlineScope countersS if (!accumulateNewArraySize(countersScope, arrayType, length, reason)) { return false; } - var array = ImageHeapArray.create(arrayType, length); + var array = ImageHeapArray.create(arrayType, length, getIdentityHashCode()); for (int j = 0; j < length; j++) { var entry = lookupConstantEntry(j, entries); if (entry == null) { @@ -659,6 +660,10 @@ private boolean handleVirtualArray(SimulateClassInitializerInlineScope countersS return true; } + private int getIdentityHashCode() { + return ImageHeapScanner.getIdentityHashCode(null, providers.getIdentityHashCodeProvider()); + } + private JavaConstant lookupConstantEntry(int index, List entries) { var entry = entries.get(index); if (entry instanceof VirtualObjectNode virtualObjectNode) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedIdentityHashCodeProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedIdentityHashCodeProvider.java new file mode 100644 index 000000000000..e3af54c5162c --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/HostedIdentityHashCodeProvider.java @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2024, 2024, 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.code; + +import com.oracle.svm.core.SubstrateUtil; +import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.util.VMError; + +import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; +import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; +import jdk.vm.ci.meta.JavaConstant; + +public class HostedIdentityHashCodeProvider extends IdentityHashCodeProvider { + + public HostedIdentityHashCodeProvider(SnippetReflectionProvider snippetReflection) { + super(snippetReflection); + } + + @Override + public int identityHashCode(JavaConstant constant) { + VMError.guarantee(SubstrateUtil.HOSTED); + Object object = snippetReflection.asObject(Object.class, constant); + if (object instanceof DynamicHub) { + /* + * We need to use the identity hash code of the original java.lang.Class object and not + * of the DynamicHub, so that hash maps that are filled during image generation and use + * Class keys still work at run time. + */ + return System.identityHashCode(((DynamicHub) object).getHostedJavaClass()); + } + return super.identityHashCode(constant); + } +} 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 ba90bd1cb4ea..077c70cf6777 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 @@ -42,6 +42,7 @@ import jdk.graal.compiler.core.common.spi.ConstantFieldProvider; import jdk.graal.compiler.core.common.spi.ForeignCallsProvider; import jdk.graal.compiler.core.common.spi.MetaAccessExtensionProvider; +import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; import jdk.graal.compiler.nodes.spi.LoopsDataProvider; import jdk.graal.compiler.nodes.spi.LoweringProvider; import jdk.graal.compiler.nodes.spi.PlatformConfigurationProvider; @@ -70,9 +71,10 @@ public HostedRuntimeConfigurationBuilder(OptionValues options, SVMHost hostVM, H @Override protected Providers createProviders(CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, ForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, SnippetReflectionProvider reflectionProvider, - PlatformConfigurationProvider platformConfigurationProvider, MetaAccessExtensionProvider metaAccessExtensionProvider, WordTypes wordTypes, LoopsDataProvider loopsDataProvider) { + PlatformConfigurationProvider platformConfigurationProvider, MetaAccessExtensionProvider metaAccessExtensionProvider, WordTypes wordTypes, LoopsDataProvider loopsDataProvider, + IdentityHashCodeProvider identityHashCodeProvider) { return new HostedProviders(metaAccess, codeCache, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, reflectionProvider, - wordTypes, platformConfigurationProvider, metaAccessExtensionProvider, loopsDataProvider); + wordTypes, platformConfigurationProvider, metaAccessExtensionProvider, loopsDataProvider, identityHashCodeProvider); } @Override @@ -100,4 +102,9 @@ protected Replacements createReplacements(Providers p) { protected CodeCacheProvider createCodeCacheProvider(RegisterConfig registerConfig) { return new HostedCodeCacheProvider(ConfigurationValues.getTarget(), registerConfig); } + + @Override + protected IdentityHashCodeProvider createIdentityHashCodeProvider() { + return analysisProviders.getIdentityHashCodeProvider(); + } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java index a902028ea059..bfaf6b5c12bf 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/SharedRuntimeConfigurationBuilder.java @@ -52,6 +52,7 @@ import jdk.graal.compiler.core.common.spi.ForeignCallsProvider; import jdk.graal.compiler.core.common.spi.MetaAccessExtensionProvider; import jdk.graal.compiler.debug.DebugHandlersFactory; +import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; import jdk.graal.compiler.nodes.spi.LoopsDataProvider; import jdk.graal.compiler.nodes.spi.LoweringProvider; import jdk.graal.compiler.nodes.spi.PlatformConfigurationProvider; @@ -118,8 +119,10 @@ public final RuntimeConfiguration build() { LoopsDataProvider loopsDataProvider = originalLoopsDataProvider; + IdentityHashCodeProvider identityHashCodeProvider = createIdentityHashCodeProvider(); + Providers p = createProviders(null, constantReflection, constantFieldProvider, foreignCalls, lowerer, null, stampProvider, snippetReflection, platformConfig, metaAccessExtensionProvider, - wordTypes, loopsDataProvider); + wordTypes, loopsDataProvider, identityHashCodeProvider); /* * Use the snippet reflection provider during image building replacement. It will be @@ -133,7 +136,7 @@ public final RuntimeConfiguration build() { CodeCacheProvider codeCacheProvider = createCodeCacheProvider(registerConfigs.get(config)); Providers newProviders = createProviders(codeCacheProvider, constantReflection, constantFieldProvider, foreignCalls, lowerer, replacements, stampProvider, - snippetReflection, platformConfig, metaAccessExtensionProvider, wordTypes, loopsDataProvider); + snippetReflection, platformConfig, metaAccessExtensionProvider, wordTypes, loopsDataProvider, identityHashCodeProvider); backends.put(config, GraalConfiguration.runtimeInstance().createBackend(newProviders)); } @@ -152,7 +155,8 @@ public final RuntimeConfiguration build() { protected abstract Providers createProviders(CodeCacheProvider codeCache, ConstantReflectionProvider constantReflection, ConstantFieldProvider constantFieldProvider, ForeignCallsProvider foreignCalls, LoweringProvider lowerer, Replacements replacements, StampProvider stampProvider, SnippetReflectionProvider reflectionProvider, - PlatformConfigurationProvider platformConfigurationProvider, MetaAccessExtensionProvider metaAccessExtensionProvider, WordTypes wordTypes, LoopsDataProvider loopsDataProvider); + PlatformConfigurationProvider platformConfigurationProvider, MetaAccessExtensionProvider metaAccessExtensionProvider, WordTypes wordTypes, LoopsDataProvider loopsDataProvider, + IdentityHashCodeProvider identityHashCodeProvider); protected abstract ConstantReflectionProvider createConstantReflectionProvider(); @@ -171,4 +175,6 @@ private StampProvider createStampProvider() { protected abstract Replacements createReplacements(Providers p); protected abstract CodeCacheProvider createCodeCacheProvider(RegisterConfig registerConfig); + + protected abstract IdentityHashCodeProvider createIdentityHashCodeProvider(); } 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 98cae252d6c9..629be3c93733 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 @@ -36,7 +36,6 @@ import org.graalvm.nativeimage.ImageSingletons; import com.oracle.graal.pointsto.BigBang; -import com.oracle.graal.pointsto.ObjectScanner; import com.oracle.graal.pointsto.ObjectScanner.ScanReason; import com.oracle.graal.pointsto.ObjectScanningObserver; import com.oracle.graal.pointsto.heap.HostedValuesProvider; @@ -47,18 +46,15 @@ import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.jdk.VarHandleFeature; -import com.oracle.svm.core.meta.DirectSubstrateObjectConstant; -import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.ImageClassLoader; import com.oracle.svm.hosted.ameta.AnalysisConstantReflectionProvider; import com.oracle.svm.hosted.ameta.FieldValueInterceptionSupport; -import com.oracle.svm.hosted.classinitialization.SimulateClassInitializerSupport; import com.oracle.svm.hosted.methodhandles.MethodHandleFeature; import com.oracle.svm.hosted.reflect.ReflectionHostedSupport; import com.oracle.svm.util.ReflectionUtil; import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; -import jdk.graal.compiler.core.common.type.TypedConstant; +import jdk.graal.compiler.nodes.spi.IdentityHashCodeProvider; import jdk.vm.ci.meta.ConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; @@ -79,8 +75,9 @@ public class SVMImageHeapScanner extends ImageHeapScanner { @SuppressWarnings("this-escape") public SVMImageHeapScanner(BigBang bb, ImageHeap imageHeap, ImageClassLoader loader, AnalysisMetaAccess metaAccess, SnippetReflectionProvider snippetReflection, - ConstantReflectionProvider aConstantReflection, ObjectScanningObserver aScanningObserver, HostedValuesProvider hostedValuesProvider) { - super(bb, imageHeap, metaAccess, snippetReflection, aConstantReflection, aScanningObserver, hostedValuesProvider); + ConstantReflectionProvider aConstantReflection, ObjectScanningObserver aScanningObserver, HostedValuesProvider hostedValuesProvider, + IdentityHashCodeProvider identityHashCodeProvider) { + super(bb, imageHeap, metaAccess, snippetReflection, aConstantReflection, aScanningObserver, hostedValuesProvider, identityHashCodeProvider); this.loader = loader; economicMapImpl = getClass("org.graalvm.collections.EconomicMapImpl"); economicMapImplEntriesField = ReflectionUtil.lookupField(economicMapImpl, "entries"); @@ -107,7 +104,6 @@ protected Class getClass(String className) { @Override protected ImageHeapConstant getOrCreateImageHeapConstant(JavaConstant javaConstant, ScanReason reason) { - VMError.guarantee(javaConstant instanceof TypedConstant, "Not a substrate constant: %s", javaConstant); return super.getOrCreateImageHeapConstant(javaConstant, reason); } @@ -124,18 +120,7 @@ public boolean isValueAvailable(AnalysisField field) { @Override public JavaConstant readStaticFieldValue(AnalysisField field) { AnalysisConstantReflectionProvider aConstantReflection = (AnalysisConstantReflectionProvider) this.constantReflection; - JavaConstant constant = aConstantReflection.readValue(field, null, true); - if (constant instanceof DirectSubstrateObjectConstant) { - /* - * The "late initialization" doesn't work with heap snapshots because the wrong value - * will be snapshot for classes proven late, so we only read via the shadow heap if - * simulation of class initializers is enabled. This branch will be removed when the old - * initialization strategy is removed. - */ - VMError.guarantee(!SimulateClassInitializerSupport.singleton().isEnabled()); - return toImageHeapObject(constant, ObjectScanner.OtherReason.UNKNOWN); - } - return constant; + return aConstantReflection.readValue(field, null, true); } @Override 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 ddeab25409e7..f8bbda9c98f9 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 @@ -578,12 +578,8 @@ private void addObjectToImageHeap(final JavaConstant constant, boolean immutable try { recursiveAddObject(hub, false, info); if (hMetaAccess.isInstanceOf(constant, Object[].class)) { - if (constant instanceof ImageHeapConstant) { - relocatable = addConstantArrayElements(constant, length, false, info); - } else { - Object object = hUniverse.getSnippetReflection().asObject(Object.class, constant); - relocatable = addArrayElements((Object[]) object, false, info); - } + VMError.guarantee(constant instanceof ImageHeapConstant, "Expected an ImageHeapConstant, found %s", constant); + relocatable = addConstantArrayElements(constant, length, false, info); references = true; } written = true; /* How to know if any of the array elements are written? */ diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeapWriter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeapWriter.java index ec61e19a3ac5..138d230d22c2 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeapWriter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeapWriter.java @@ -52,7 +52,7 @@ import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.image.ImageHeapLayoutInfo; import com.oracle.svm.core.meta.MethodPointer; -import com.oracle.svm.core.meta.SubstrateObjectConstant; +import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.code.CEntryPointLiteralFeature; import com.oracle.svm.hosted.config.DynamicHubLayout; import com.oracle.svm.hosted.config.HybridLayout; @@ -70,6 +70,7 @@ import jdk.graal.compiler.debug.DebugContext; import jdk.graal.compiler.debug.Indent; import jdk.internal.misc.Unsafe; +import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; @@ -96,7 +97,7 @@ public NativeImageHeapWriter(NativeImageHeap heap, ImageHeapLayoutInfo heapLayou public long writeHeap(DebugContext debug, RelocatableBuffer buffer) { try (Indent perHeapIndent = debug.logAndIndent("NativeImageHeap.writeHeap:")) { for (ObjectInfo info : heap.getObjects()) { - assert !(info.getConstant() instanceof SubstrateObjectConstant) || !heap.isBlacklisted(info.getObject()); + assert !(info.getConstant() instanceof HotSpotObjectConstant) || !heap.isBlacklisted(info.getObject()); writeObject(info, buffer); } @@ -424,30 +425,15 @@ private void writeObject(ObjectInfo info, RelocatableBuffer buffer) { bufferBytes.putInt(getIndexInBuffer(info, objectLayout.getArrayLengthOffset()), length); bufferBytes.putInt(getIndexInBuffer(info, objectLayout.getArrayIdentityHashOffset(kind, length)), info.getIdentityHashCode()); - if (constant instanceof ImageHeapConstant) { - if (clazz.getComponentType().isPrimitive()) { - ImageHeapPrimitiveArray imageHeapArray = (ImageHeapPrimitiveArray) constant; - writePrimitiveArray(info, buffer, objectLayout, kind, imageHeapArray.getArray(), length); - } else { - heap.hConstantReflection.forEachArrayElement(constant, (element, index) -> { - final int elementIndex = getIndexInBuffer(info, objectLayout.getArrayElementOffset(kind, index)); - writeConstant(buffer, elementIndex, kind, element, info); - }); - } + VMError.guarantee(constant instanceof ImageHeapConstant, "Expected an ImageHeapConstant, found %s", constant); + if (clazz.getComponentType().isPrimitive()) { + ImageHeapPrimitiveArray imageHeapArray = (ImageHeapPrimitiveArray) constant; + writePrimitiveArray(info, buffer, objectLayout, kind, imageHeapArray.getArray(), length); } else { - Object array = info.getObject(); - if (array instanceof Object[]) { - Object[] oarray = (Object[]) array; - assert oarray.length == length; - for (int i = 0; i < length; i++) { - final int elementIndex = getIndexInBuffer(info, objectLayout.getArrayElementOffset(kind, i)); - Object element = maybeReplace(oarray[i], info); - assert (oarray[i] instanceof RelocatedPointer) == (element instanceof RelocatedPointer); - writeConstant(buffer, elementIndex, kind, element, info); - } - } else { - writePrimitiveArray(info, buffer, objectLayout, kind, array, length); - } + heap.hConstantReflection.forEachArrayElement(constant, (element, index) -> { + final int elementIndex = getIndexInBuffer(info, objectLayout.getArrayElementOffset(kind, index)); + writeConstant(buffer, elementIndex, kind, element, info); + }); } } else { throw shouldNotReachHereUnexpectedInput(clazz); // ExcludeFromJacocoGeneratedReport diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/RelocatableBuffer.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/RelocatableBuffer.java index cb4491ca1bf5..9f5d1e80cf46 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/RelocatableBuffer.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/RelocatableBuffer.java @@ -33,14 +33,13 @@ import java.util.SortedMap; import java.util.TreeMap; -import jdk.graal.compiler.core.common.NumUtil; import org.graalvm.nativeimage.c.function.RelocatedPointer; import com.oracle.graal.pointsto.heap.ImageHeapConstant; import com.oracle.objectfile.ObjectFile; import com.oracle.svm.core.meta.MethodPointer; -import com.oracle.svm.core.meta.SubstrateObjectConstant; +import jdk.graal.compiler.core.common.NumUtil; import jdk.vm.ci.code.site.Reference; /** @@ -97,8 +96,7 @@ public static final class Info { this.targetObject = targetObject; /* Sanity check for allowed groups of target objects. */ - assert targetObject instanceof Reference || targetObject instanceof MethodPointer || - targetObject instanceof SubstrateObjectConstant || targetObject instanceof ImageHeapConstant : targetObject; + assert targetObject instanceof Reference || targetObject instanceof MethodPointer || targetObject instanceof ImageHeapConstant : targetObject; } public int getRelocationSize() { 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 6a15f8ddadb5..67b5a08da7e1 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 @@ -24,28 +24,32 @@ */ package com.oracle.svm.hosted.meta; -import org.graalvm.nativeimage.c.function.RelocatedPointer; -import org.graalvm.word.WordBase; +import java.lang.reflect.Executable; +import java.lang.reflect.Field; import com.oracle.graal.pointsto.ObjectScanner.OtherReason; import com.oracle.graal.pointsto.heap.ImageHeapConstant; import com.oracle.graal.pointsto.heap.ImageHeapScanner; -import com.oracle.graal.pointsto.util.AnalysisError; -import com.oracle.svm.core.config.ConfigurationValues; -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.core.util.VMError; +import jdk.graal.compiler.api.replacements.SnippetReflectionProvider; import jdk.graal.compiler.word.WordTypes; +import jdk.vm.ci.hotspot.HotSpotObjectConstant; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.ResolvedJavaField; +import jdk.vm.ci.meta.ResolvedJavaMethod; +import jdk.vm.ci.meta.ResolvedJavaType; -public class HostedSnippetReflectionProvider extends SubstrateSnippetReflectionProvider { +public class HostedSnippetReflectionProvider implements SnippetReflectionProvider { private ImageHeapScanner heapScanner; + private final WordTypes wordTypes; public HostedSnippetReflectionProvider(ImageHeapScanner heapScanner, WordTypes wordTypes) { - super(wordTypes); this.heapScanner = heapScanner; + this.wordTypes = wordTypes; } public void setHeapScanner(ImageHeapScanner heapScanner) { @@ -54,26 +58,8 @@ public void setHeapScanner(ImageHeapScanner heapScanner) { @Override public JavaConstant forObject(Object object) { - if (object instanceof RelocatedPointer pointer) { - /* Relocated pointers are subject to relocation, so we don't know their value yet. */ - return new RelocatableConstant(pointer); - } else if (object instanceof WordBase word) { - return JavaConstant.forIntegerKind(ConfigurationValues.getWordKind(), word.rawValue()); - } - validateRawObjectConstant(object); - /* Redirect constant lookup through the shadow heap. */ - return heapScanner.createImageHeapConstant(super.forObject(object), 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); + /* Redirect object lookup through the shadow heap. */ + return heapScanner.createImageHeapConstant(object, OtherReason.UNKNOWN); } @Override @@ -87,9 +73,6 @@ public JavaConstant forBoxed(JavaKind kind, Object value) { @Override public T asObject(Class type, JavaConstant c) { JavaConstant constant = c; - if (constant instanceof RelocatableConstant relocatable) { - return type.cast(relocatable.getPointer()); - } if (constant instanceof ImageHeapConstant imageHeapConstant) { constant = imageHeapConstant.getHostedObject(); if (constant == null) { @@ -98,12 +81,37 @@ public T asObject(Class type, JavaConstant c) { } } - if (type == Class.class && constant instanceof SubstrateObjectConstant) { + if (type == Class.class && constant instanceof HotSpotObjectConstant) { /* Only unwrap the DynamicHub if a Class object is required explicitly. */ - if (SubstrateObjectConstant.asObject(constant) instanceof DynamicHub hub) { + if (heapScanner.getHostedValuesProvider().asObject(Object.class, constant) instanceof DynamicHub hub) { return type.cast(hub.getHostedJavaClass()); } } - return super.asObject(type, constant); + VMError.guarantee(!(constant instanceof SubstrateObjectConstant)); + return heapScanner.getHostedValuesProvider().asObject(type, constant); + } + + @Override + public T getInjectedNodeIntrinsicParameter(Class type) { + if (type.isAssignableFrom(WordTypes.class)) { + return type.cast(wordTypes); + } else { + return null; + } + } + + @Override + public Class originalClass(ResolvedJavaType type) { + throw VMError.intentionallyUnimplemented(); // ExcludeFromJacocoGeneratedReport + } + + @Override + public Executable originalMethod(ResolvedJavaMethod method) { + throw VMError.intentionallyUnimplemented(); // ExcludeFromJacocoGeneratedReport + } + + @Override + public Field originalField(ResolvedJavaField field) { + throw VMError.intentionallyUnimplemented(); // ExcludeFromJacocoGeneratedReport } } diff --git a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleFeature.java b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleFeature.java index ab7bae47d52e..58363f56b749 100644 --- a/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleFeature.java +++ b/substratevm/src/com.oracle.svm.truffle/src/com/oracle/svm/truffle/TruffleFeature.java @@ -383,7 +383,8 @@ public void beforeAnalysis(BeforeAnalysisAccess access) { runtimeCompilationFeature.getHostedProviders().getWordTypes(), runtimeCompilationFeature.getHostedProviders().getPlatformConfigurationProvider(), runtimeCompilationFeature.getHostedProviders().getMetaAccessExtensionProvider(), - runtimeCompilationFeature.getHostedProviders().getLoopsDataProvider()); + runtimeCompilationFeature.getHostedProviders().getLoopsDataProvider(), + runtimeCompilationFeature.getHostedProviders().getIdentityHashCodeProvider()); newHostedProviders.setGraphBuilderPlugins(graphBuilderConfig.getPlugins()); runtimeCompilationFeature.initializeRuntimeCompilationConfiguration(newHostedProviders, graphBuilderConfig, this::allowRuntimeCompilation, this::deoptimizeOnException, this::checkBlockList);