From 8f74ecd8cf227ba7b98091a11f8ea5116a7f3f3b Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Tue, 19 Sep 2023 17:38:56 +0200 Subject: [PATCH 1/4] Represent relocatable pointers as RelocatableConstant. --- .../graal/pointsto/heap/ImageHeapScanner.java | 19 +--- .../src/com/oracle/svm/hosted/SVMHost.java | 4 +- .../AnalysisConstantReflectionProvider.java | 29 +++-- .../svm/hosted/image/NativeImageHeap.java | 5 +- .../hosted/image/NativeImageHeapWriter.java | 9 +- ...HostedLookupSnippetReflectionProvider.java | 22 +++- .../meta/HostedSnippetReflectionProvider.java | 7 +- .../svm/hosted/meta/RelocatableConstant.java | 102 ++++++++++++++++++ 8 files changed, 157 insertions(+), 40 deletions(-) create mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/RelocatableConstant.java 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 cb63d8b27bca..1738229cc660 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 @@ -35,8 +35,8 @@ import org.graalvm.collections.MapCursor; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.SuppressFBWarnings; +import org.graalvm.compiler.core.common.type.TypedConstant; import org.graalvm.compiler.debug.GraalError; -import org.graalvm.word.WordBase; import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.ObjectScanner; @@ -397,6 +397,8 @@ private void notifyAnalysis(AnalysisField field, ImageHeapInstance receiver, Jav private boolean doNotifyAnalysis(AnalysisField field, JavaConstant receiver, JavaConstant fieldValue, ScanReason reason) { boolean analysisModified = false; if (fieldValue.getJavaKind() == JavaKind.Object && hostVM.isRelocatedPointer(metaAccess, fieldValue)) { + /* Ensure the relocatable pointer type is analysed. */ + ((AnalysisType) ((TypedConstant) fieldValue).getType(metaAccess)).registerAsReachable(reason); analysisModified = scanningObserver.forRelocatedPointerFieldValue(receiver, field, fieldValue, reason); } else if (fieldValue.isNull()) { analysisModified = scanningObserver.forNullFieldValue(receiver, field, reason); @@ -430,18 +432,7 @@ private void notifyAnalysis(ImageHeapArray array, AnalysisType arrayType, int el } private boolean isNonNullObjectConstant(JavaConstant constant) { - return constant.getJavaKind() == JavaKind.Object && constant.isNonNull() && !isWordType(constant); - } - - public boolean isWordType(JavaConstant rawElementValue) { - /* - * UniverseMetaAccess.isInstanceOf cannot be used here because the object replacers may have - * not yet been applied to the object. This can lead to - * "Type is not available in this platform" issues when accessing the object type. A proper - * fix will add a JavaConstant implementation class for relocatable word values.(GR-48681). - */ - Object obj = snippetReflection.asObject(Object.class, rawElementValue); - return obj instanceof WordBase; + return constant.getJavaKind() == JavaKind.Object && constant.isNonNull() && !universe.hostVM().isRelocatedPointer(metaAccess, constant); } private boolean notifyAnalysis(JavaConstant array, AnalysisType arrayType, JavaConstant elementValue, int elementIndex, ScanReason reason) { @@ -449,7 +440,7 @@ private boolean notifyAnalysis(JavaConstant array, AnalysisType arrayType, JavaC if (elementValue.isNull()) { analysisModified = scanningObserver.forNullArrayElement(array, arrayType, elementIndex, reason); } else { - if (isWordType(elementValue)) { + if (universe.hostVM().isRelocatedPointer(metaAccess, elementValue)) { return false; } AnalysisType elementType = metaAccess.lookupJavaType(elementValue); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java index cea86e5a2f9c..da80417a38b5 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java @@ -76,7 +76,6 @@ import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; -import org.graalvm.nativeimage.c.function.RelocatedPointer; import com.oracle.graal.pointsto.BigBang; import com.oracle.graal.pointsto.PointsToAnalysis; @@ -134,6 +133,7 @@ import com.oracle.svm.hosted.meta.HostedField; import com.oracle.svm.hosted.meta.HostedType; import com.oracle.svm.hosted.meta.HostedUniverse; +import com.oracle.svm.hosted.meta.RelocatableConstant; import com.oracle.svm.hosted.phases.AnalysisGraphBuilderPhase; import com.oracle.svm.hosted.phases.ImplicitAssertionsPhase; import com.oracle.svm.hosted.phases.InlineBeforeAnalysisGraphDecoderImpl; @@ -272,7 +272,7 @@ public String getImageName() { @Override public boolean isRelocatedPointer(UniverseMetaAccess metaAccess, JavaConstant constant) { - return metaAccess.isInstanceOf(constant, RelocatedPointer.class); + return constant instanceof RelocatableConstant; } @Override 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 9fd27f2e1b55..c33a261f43ed 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 @@ -54,13 +54,16 @@ import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.classinitialization.ClassInitializationSupport; import com.oracle.svm.hosted.classinitialization.SimulateClassInitializerSupport; +import com.oracle.svm.hosted.meta.HostedLookupSnippetReflectionProvider; import com.oracle.svm.hosted.meta.HostedMetaAccess; +import com.oracle.svm.hosted.meta.RelocatableConstant; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.MemoryAccessProvider; import jdk.vm.ci.meta.MethodHandleAccessProvider; +import jdk.vm.ci.meta.PrimitiveConstant; import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaType; @@ -265,7 +268,7 @@ public JavaConstant interceptValue(UniverseMetaAccess suppliedMetaAccess, Analys result = filterInjectedAccessor(field, result); result = replaceObject(result); result = interceptAssertionStatus(field, result); - result = interceptWordType(suppliedMetaAccess, field, result); + result = interceptWordField(suppliedMetaAccess, field, result); } return result; } @@ -321,23 +324,17 @@ private static JavaConstant interceptAssertionStatus(AnalysisField field, JavaCo } /** - * Intercept {@link Word} types. They are boxed objects in the hosted world, but primitive - * values in the runtime world. + * Intercept {@link Word} fields. {@link Word} values are boxed objects in the hosted world, but + * primitive values in the runtime world, so the default value of {@link Word} fields is 0. + * + * {@link HostedLookupSnippetReflectionProvider} replaces relocatable pointers with + * {@link RelocatableConstant} and regular {@link WordBase} values with + * {@link PrimitiveConstant}. No other {@link WordBase} values can be reachable at this point. */ - private JavaConstant interceptWordType(UniverseMetaAccess suppliedMetaAccess, AnalysisField field, JavaConstant value) { + private JavaConstant interceptWordField(UniverseMetaAccess suppliedMetaAccess, AnalysisField field, JavaConstant value) { if (value.getJavaKind() == JavaKind.Object) { - if (universe.hostVM().isRelocatedPointer(suppliedMetaAccess, value)) { - /* - * Such pointers are subject to relocation therefore we don't know their values yet. - * Therefore there should not be a relocated pointer constant in a function which is - * compiled. RelocatedPointers are only allowed in non-constant fields. The caller - * of readValue is responsible of handling the returned value correctly. - */ - return value; - } else if (suppliedMetaAccess.isInstanceOf(value, WordBase.class)) { - Object originalObject = universe.getSnippetReflection().asObject(Object.class, value); - return JavaConstant.forIntegerKind(universe.getWordKind(), ((WordBase) originalObject).rawValue()); - } else if (value.isNull() && field.getType().isWordType()) { + VMError.guarantee(value instanceof RelocatableConstant || !suppliedMetaAccess.isInstanceOf(value, WordBase.class)); + if (value.isNull() && field.getType().isWordType()) { return JavaConstant.forIntegerKind(universe.getWordKind(), 0); } } 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 4428bafee1fe..8fec58df18a4 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 @@ -83,6 +83,7 @@ import com.oracle.svm.hosted.meta.HostedType; import com.oracle.svm.hosted.meta.HostedUniverse; import com.oracle.svm.hosted.meta.MaterializedConstantFields; +import com.oracle.svm.hosted.meta.RelocatableConstant; import com.oracle.svm.hosted.meta.UniverseBuilder; import jdk.vm.ci.meta.JavaConstant; @@ -544,7 +545,7 @@ private void addObjectToImageHeap(final JavaConstant constant, boolean immutable JavaConstant fieldValueConstant = hConstantReflection.readFieldValue(field, constant); if (fieldValueConstant.getJavaKind() == JavaKind.Object) { if (spawnIsolates()) { - fieldRelocatable = hMetaAccess.isInstanceOf(fieldValueConstant, RelocatedPointer.class); + fieldRelocatable = fieldValueConstant instanceof RelocatableConstant; } recursiveAddConstant(fieldValueConstant, fieldsAreImmutable, info); references = true; @@ -708,7 +709,7 @@ private boolean addConstantArrayElements(JavaConstant array, int length, boolean JavaConstant value = hConstantReflection.readArrayElement(array, idx); /* Object replacement is done as part as constant refection. */ if (spawnIsolates()) { - relocatable = relocatable || hMetaAccess.isInstanceOf(value, RelocatedPointer.class); + relocatable = relocatable || value instanceof RelocatableConstant; } recursiveAddConstant(value, false, reason); } 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 ab80403ad89b..acc0bbbc7cef 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 @@ -31,8 +31,6 @@ import java.lang.reflect.Modifier; import java.nio.ByteBuffer; -import com.oracle.svm.core.meta.SubstrateMethodPointerConstant; -import jdk.vm.ci.meta.Constant; import org.graalvm.compiler.api.replacements.SnippetReflectionProvider; import org.graalvm.compiler.core.common.CompressEncoding; import org.graalvm.compiler.core.common.NumUtil; @@ -57,6 +55,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.SubstrateMethodPointerConstant; import com.oracle.svm.core.meta.SubstrateObjectConstant; import com.oracle.svm.hosted.config.HybridLayout; import com.oracle.svm.hosted.image.NativeImageHeap.ObjectInfo; @@ -64,8 +63,10 @@ import com.oracle.svm.hosted.meta.HostedField; import com.oracle.svm.hosted.meta.HostedInstanceClass; import com.oracle.svm.hosted.meta.MaterializedConstantFields; +import com.oracle.svm.hosted.meta.RelocatableConstant; import jdk.internal.misc.Unsafe; +import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; @@ -150,7 +151,7 @@ private void writeField(RelocatableBuffer buffer, ObjectInfo fields, HostedField throw NativeImageHeap.reportIllegalType(ex.getType(), info); } - if (value.getJavaKind() == JavaKind.Object && heap.hMetaAccess.isInstanceOf(value, RelocatedPointer.class)) { + if (value instanceof RelocatableConstant) { addNonDataRelocation(buffer, index, snippetReflection().asObject(RelocatedPointer.class, value)); } else { write(buffer, index, value, info != null ? info : field); @@ -193,7 +194,7 @@ void writeReference(RelocatableBuffer buffer, int index, Constant constant, Obje } private void writeConstant(RelocatableBuffer buffer, int index, JavaKind kind, JavaConstant constant, ObjectInfo info) { - if (heap.hMetaAccess.isInstanceOf(constant, RelocatedPointer.class)) { + if (constant instanceof RelocatableConstant) { addNonDataRelocation(buffer, index, snippetReflection().asObject(RelocatedPointer.class, constant)); return; } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedLookupSnippetReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedLookupSnippetReflectionProvider.java index b16589f2408e..90bb88b54a74 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedLookupSnippetReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedLookupSnippetReflectionProvider.java @@ -24,13 +24,20 @@ */ package com.oracle.svm.hosted.meta; -import com.oracle.svm.hosted.ameta.AnalysisConstantReflectionProvider; import org.graalvm.compiler.word.WordTypes; +import org.graalvm.nativeimage.c.function.RelocatedPointer; +import org.graalvm.word.WordBase; +import com.oracle.svm.core.FrameAccess; import com.oracle.svm.core.graal.meta.SubstrateSnippetReflectionProvider; +import com.oracle.svm.hosted.ameta.AnalysisConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; +/** + * The snippet reflection provider that acts as the interface between the Native Image builder and + * the hosting VM. + */ public class HostedLookupSnippetReflectionProvider extends SubstrateSnippetReflectionProvider { public HostedLookupSnippetReflectionProvider(WordTypes wordTypes) { @@ -39,7 +46,20 @@ public HostedLookupSnippetReflectionProvider(WordTypes wordTypes) { @Override public JavaConstant forObject(Object object) { + if (object instanceof RelocatedPointer pointer) { + return new RelocatableConstant(pointer); + } else if (object instanceof WordBase word) { + return JavaConstant.forIntegerKind(FrameAccess.getWordKind(), word.rawValue()); + } AnalysisConstantReflectionProvider.validateRawObjectConstant(object); return super.forObject(object); } + + @Override + public T asObject(Class type, JavaConstant constant) { + if (constant instanceof RelocatableConstant relocatable) { + return type.cast(relocatable.getPointer()); + } + return super.asObject(type, constant); + } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedSnippetReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedSnippetReflectionProvider.java index 38985da7ca2c..1ced5db218c9 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 @@ -54,7 +54,9 @@ public void setHeapScanner(ImageHeapScanner heapScanner) { @Override public JavaConstant forObject(Object object) { /* RelocatedPointer values will be represented as a RelocatableConstant by GR-48681. */ - if (object instanceof WordBase word && !(object instanceof RelocatedPointer)) { + if (object instanceof RelocatedPointer pointer) { + return new RelocatableConstant(pointer); + } else if (object instanceof WordBase word) { /* Relocated pointers are subject to relocation, so we don't know their value yet. */ return JavaConstant.forIntegerKind(FrameAccess.getWordKind(), word.rawValue()); } @@ -74,6 +76,9 @@ public JavaConstant unwrapConstant(JavaConstant constant) { @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) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/RelocatableConstant.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/RelocatableConstant.java new file mode 100644 index 000000000000..87f1bd74ad85 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/RelocatableConstant.java @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2023, 2023, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.hosted.meta; + +import org.graalvm.compiler.core.common.type.TypedConstant; +import org.graalvm.nativeimage.c.function.RelocatedPointer; + +import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaType; + +/** Wraps pointers that are subject to relocation, so their value is not known during analysis. */ +public class RelocatableConstant implements JavaConstant, TypedConstant { + + private final RelocatedPointer pointer; + + public RelocatableConstant(RelocatedPointer pointer) { + this.pointer = pointer; + } + + public RelocatedPointer getPointer() { + return pointer; + } + + @Override + public JavaKind getJavaKind() { + return JavaKind.Object; + } + + @Override + public boolean isNull() { + return false; + } + + @Override + public boolean isDefaultForKind() { + throw new IllegalArgumentException(); + } + + @Override + public Object asBoxedPrimitive() { + throw new IllegalArgumentException(); + } + + @Override + public int asInt() { + throw new IllegalArgumentException(); + } + + @Override + public boolean asBoolean() { + throw new IllegalArgumentException(); + } + + @Override + public long asLong() { + throw new IllegalArgumentException(); + } + + @Override + public float asFloat() { + throw new IllegalArgumentException(); + } + + @Override + public double asDouble() { + throw new IllegalArgumentException(); + } + + @Override + public ResolvedJavaType getType(MetaAccessProvider provider) { + return provider.lookupJavaType(pointer.getClass()); + } + + @Override + public int getIdentityHashCode() { + return 0; + } +} From 57fdbf020dcb9a2e470a6813c5e9ae27ff9c7fcb Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Tue, 19 Sep 2023 16:40:27 +0200 Subject: [PATCH 2/4] Clean up use of ImageHeapConstant. --- .../graal/pointsto/heap/HeapSnapshotVerifier.java | 15 +++++---------- .../graal/pointsto/heap/ImageHeapScanner.java | 4 ---- .../graal/pointsto/results/StrengthenGraphs.java | 10 ---------- .../ameta/AnalysisConstantReflectionProvider.java | 2 +- .../hosted/analysis/DynamicHubInitializer.java | 2 +- .../svm/hosted/heap/SVMImageHeapScanner.java | 6 ------ .../meta/HostedConstantReflectionProvider.java | 3 +-- 7 files changed, 8 insertions(+), 34 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/HeapSnapshotVerifier.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/HeapSnapshotVerifier.java index c74f230a6047..5c43650f19ad 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/HeapSnapshotVerifier.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/HeapSnapshotVerifier.java @@ -343,11 +343,7 @@ public void forScannedConstant(JavaConstant value, ScanReason reason) { } private void ensureTypeScanned(JavaConstant typeConstant, AnalysisType type, ScanReason reason) { - if (typeConstant instanceof ImageHeapConstant imageHeapConstant) { - ensureTypeScanned(null, imageHeapConstant.getHostedObject(), type, reason); - } else { - ensureTypeScanned(null, typeConstant, type, reason); - } + ensureTypeScanned(null, typeConstant, type, reason); } @SuppressWarnings({"unchecked", "rawtypes"}) @@ -361,14 +357,13 @@ private void ensureTypeScanned(JavaConstant value, JavaConstant typeConstant, An onNoTaskForClassConstant(type, reason); scanner.toImageHeapObject(typeConstant, reason); heapPatched = true; - } else if (task instanceof ImageHeapConstant) { - JavaConstant snapshot = ((ImageHeapConstant) task).getHostedObject(); - verifyTypeConstant(snapshot, typeConstant, reason); + } else if (task instanceof ImageHeapConstant snapshot) { + verifyTypeConstant(maybeUnwrapSnapshot(snapshot, typeConstant instanceof ImageHeapConstant), typeConstant, reason); } else { assert task instanceof AnalysisFuture; AnalysisFuture future = ((AnalysisFuture) task); if (future.isDone()) { - JavaConstant snapshot = future.guardedGet().getHostedObject(); + JavaConstant snapshot = maybeUnwrapSnapshot(future.guardedGet(), typeConstant instanceof ImageHeapConstant); verifyTypeConstant(snapshot, typeConstant, reason); } else { onTaskForClassConstantNotDone(value, type, reason); @@ -379,7 +374,7 @@ private void ensureTypeScanned(JavaConstant value, JavaConstant typeConstant, An private void verifyTypeConstant(JavaConstant snapshot, JavaConstant typeConstant, ScanReason reason) { if (!Objects.equals(snapshot, typeConstant)) { - throw error(reason, "Value mismatch for class constant snapshot: %s %n new value: %s %n", snapshot, typeConstant); + throw error(reason, "Value mismatch for class constant%n snapshot: %s %n new value: %s %n", snapshot, typeConstant); } } 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 1738229cc660..773bd3e6dc30 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 @@ -515,10 +515,6 @@ protected ValueSupplier readHostedFieldValue(AnalysisField field, return ValueSupplier.eagerValue(value); } - public JavaConstant readFieldValue(AnalysisField field, JavaConstant receiver) { - return constantReflection.readFieldValue(field, receiver); - } - public void rescanRoot(Field reflectionField) { maybeRunInExecutor(unused -> { AnalysisType type = metaAccess.lookupJavaType(reflectionField.getDeclaringClass()); diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java index 3d9ac4810bc3..ed02a7473d25 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java @@ -94,7 +94,6 @@ import com.oracle.graal.pointsto.flow.MethodFlowsGraph; import com.oracle.graal.pointsto.flow.MethodTypeFlow; import com.oracle.graal.pointsto.flow.TypeFlow; -import com.oracle.graal.pointsto.heap.ImageHeapConstant; import com.oracle.graal.pointsto.infrastructure.Universe; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMethod; @@ -728,15 +727,6 @@ private Object strengthenStampFromTypeFlow(ValueNode node, TypeFlow nodeFlow, if (hasUsages && allowConstantFolding && !nodeTypeState.canBeNull()) { JavaConstant constantValue = nodeTypeState.asConstant(); - if (constantValue instanceof ImageHeapConstant) { - /* - * GR-42996: until the AOT compilation can properly constant fold also - * ImageHeapConstant, we unwrap the ImageHeapConstant to the hosted object. This - * also means we do not constant fold yet when the constant does not wrap a - * hosted object. - */ - constantValue = ((ImageHeapConstant) constantValue).getHostedObject(); - } if (constantValue != null) { return constantValue; } 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 c33a261f43ed..f02ab1371c25 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 @@ -361,7 +361,7 @@ public AnalysisType asJavaType(Constant constant) { @Override public JavaConstant asJavaClass(ResolvedJavaType type) { - return SubstrateObjectConstant.forObject(getHostVM().dynamicHub(type)); + return universe.getHeapScanner().createImageHeapConstant(super.forObject(getHostVM().dynamicHub(type)), ObjectScanner.OtherReason.UNKNOWN); } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java index c46203663f0b..84dd3ba35efc 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/DynamicHubInitializer.java @@ -181,7 +181,7 @@ private Enum[] retrieveEnumConstantArray(AnalysisType type, Class javaClas */ enumConstants = (Enum[]) javaClass.getEnumConstants(); } else { - enumConstants = metaAccess.getUniverse().getSnippetReflection().asObject(Enum[].class, constantReflection.readFieldValue(found, null)); + enumConstants = bb.getSnippetReflectionProvider().asObject(Enum[].class, constantReflection.readFieldValue(found, null)); assert enumConstants != null; } return enumConstants; 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 a6536dddbdcf..6129fd09cccf 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 @@ -123,12 +123,6 @@ protected ValueSupplier readHostedFieldValue(AnalysisField field, return aConstantReflection.readHostedFieldValue(field, hostedMetaAccess, receiver, true); } - @Override - public JavaConstant readFieldValue(AnalysisField field, JavaConstant receiver) { - AnalysisConstantReflectionProvider aConstantReflection = (AnalysisConstantReflectionProvider) this.constantReflection; - return aConstantReflection.readValue(metaAccess, field, receiver, true); - } - @Override protected JavaConstant transformFieldValue(AnalysisField field, JavaConstant receiverConstant, JavaConstant originalValueConstant) { return ((AnalysisConstantReflectionProvider) constantReflection).interceptValue(metaAccess, field, originalValueConstant); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantReflectionProvider.java index 2358f8cf4eec..d750349b7d57 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantReflectionProvider.java @@ -31,7 +31,6 @@ import com.oracle.svm.core.graal.meta.SharedConstantReflectionProvider; import com.oracle.svm.core.hub.DynamicHub; -import com.oracle.svm.core.meta.SubstrateObjectConstant; import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.ameta.AnalysisConstantReflectionProvider; @@ -83,7 +82,7 @@ public ResolvedJavaType asJavaType(Constant constant) { @Override public JavaConstant asJavaClass(ResolvedJavaType type) { - return SubstrateObjectConstant.forObject(hostVM.dynamicHub(((HostedType) type).wrapped)); + return aConstantReflection.asJavaClass(((HostedType) type).wrapped); } @Override From 65177e73ace5b531dd545828718f1912b96e6387 Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Tue, 19 Sep 2023 21:33:52 +0200 Subject: [PATCH 3/4] Fix lazy value computation. --- .../svm/hosted/NativeImageGenerator.java | 2 +- .../AnalysisConstantReflectionProvider.java | 21 +++++++++++++++++-- .../svm/hosted/heap/SVMImageHeapScanner.java | 8 +------ 3 files changed, 21 insertions(+), 10 deletions(-) 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 589884821e5b..d6c9780bd128 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 @@ -603,7 +603,7 @@ protected void doRun(Map entryPoints, hUniverse = new HostedUniverse(bb); hMetaAccess = new HostedMetaAccess(hUniverse, bb.getMetaAccess()); - ((SVMImageHeapScanner) aUniverse.getHeapScanner()).setHostedMetaAccess(hMetaAccess); + ((AnalysisConstantReflectionProvider) bb.getConstantReflectionProvider()).setHostedMetaAccess(hMetaAccess); BeforeUniverseBuildingAccessImpl beforeUniverseBuildingConfig = new BeforeUniverseBuildingAccessImpl(featureHandler, loader, debug, hMetaAccess); featureHandler.forEachFeature(feature -> feature.beforeUniverseBuilding(beforeUniverseBuildingConfig)); 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 f02ab1371c25..1234901733ec 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 @@ -46,6 +46,7 @@ import com.oracle.graal.pointsto.util.AnalysisError; import com.oracle.svm.core.RuntimeAssertionsSupport; import com.oracle.svm.core.annotate.InjectAccessors; +import com.oracle.svm.core.annotate.RecomputeFieldValue; import com.oracle.svm.core.graal.meta.SharedConstantReflectionProvider; import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.meta.ObjectConstantEquality; @@ -54,6 +55,7 @@ import com.oracle.svm.hosted.SVMHost; import com.oracle.svm.hosted.classinitialization.ClassInitializationSupport; import com.oracle.svm.hosted.classinitialization.SimulateClassInitializerSupport; +import com.oracle.svm.hosted.meta.HostedField; import com.oracle.svm.hosted.meta.HostedLookupSnippetReflectionProvider; import com.oracle.svm.hosted.meta.HostedMetaAccess; import com.oracle.svm.hosted.meta.RelocatableConstant; @@ -71,6 +73,7 @@ public class AnalysisConstantReflectionProvider extends SharedConstantReflectionProvider { private final AnalysisUniverse universe; private final UniverseMetaAccess metaAccess; + private HostedMetaAccess hMetaAccess; private final ClassInitializationSupport classInitializationSupport; private final AnalysisMethodHandleAccessProvider methodHandleAccess; private SimulateClassInitializerSupport simulateClassInitializerSupport; @@ -82,6 +85,10 @@ public AnalysisConstantReflectionProvider(AnalysisUniverse universe, UniverseMet this.methodHandleAccess = new AnalysisMethodHandleAccessProvider(universe); } + public void setHostedMetaAccess(HostedMetaAccess hMetaAccess) { + this.hMetaAccess = hMetaAccess; + } + @Override public Boolean constantEquals(Constant x, Constant y) { if (x == y) { @@ -215,7 +222,7 @@ public JavaConstant readValue(UniverseMetaAccess suppliedMetaAccess, AnalysisFie } /** Read the field value and wrap it in a value supplier without performing any replacements. */ - public ValueSupplier readHostedFieldValue(AnalysisField field, HostedMetaAccess hMetaAccess, JavaConstant receiver, boolean returnSimulatedValues) { + public ValueSupplier readHostedFieldValue(AnalysisField field, JavaConstant receiver, boolean returnSimulatedValues) { if (returnSimulatedValues) { var simulatedValue = readSimulatedValue(field); if (simulatedValue != null) { @@ -236,7 +243,17 @@ public ValueSupplier readHostedFieldValue(AnalysisField field, Hos * during analysis or in a later phase. Attempts to materialize the value before it becomes * available will result in an error. */ - return ValueSupplier.lazyValue(() -> doReadValue(field, receiver, hMetaAccess), () -> ReadableJavaField.isValueAvailable(field)); + return ValueSupplier.lazyValue(() -> doReadValue(field, receiver), () -> ReadableJavaField.isValueAvailable(field)); + } + + /** + * The {@link HostedMetaAccess} is used to access the {@link HostedField} in the re-computation + * of {@link RecomputeFieldValue.Kind#AtomicFieldUpdaterOffset} and + * {@link RecomputeFieldValue.Kind#TranslateFieldOffset} annotated fields . + */ + private JavaConstant doReadValue(AnalysisField field, JavaConstant receiver) { + Objects.requireNonNull(hMetaAccess); + return doReadValue(field, receiver, hMetaAccess); } private JavaConstant doReadValue(AnalysisField field, JavaConstant receiver, UniverseMetaAccess access) { 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 6129fd09cccf..3b47aec8a657 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 @@ -52,7 +52,6 @@ import com.oracle.svm.hosted.ImageClassLoader; import com.oracle.svm.hosted.ameta.AnalysisConstantReflectionProvider; import com.oracle.svm.hosted.ameta.ReadableJavaField; -import com.oracle.svm.hosted.meta.HostedMetaAccess; import com.oracle.svm.hosted.methodhandles.MethodHandleFeature; import com.oracle.svm.hosted.reflect.ReflectionHostedSupport; import com.oracle.svm.util.ReflectionUtil; @@ -63,7 +62,6 @@ public class SVMImageHeapScanner extends ImageHeapScanner { private final ImageClassLoader loader; - protected HostedMetaAccess hostedMetaAccess; private final Class economicMapImpl; private final Field economicMapImplEntriesField; private final Field economicMapImplHashArrayField; @@ -97,10 +95,6 @@ public static ImageHeapScanner instance() { return ImageSingletons.lookup(ImageHeapScanner.class); } - public void setHostedMetaAccess(HostedMetaAccess hostedMetaAccess) { - this.hostedMetaAccess = hostedMetaAccess; - } - @Override protected Class getClass(String className) { return loader.findClassOrFail(className); @@ -120,7 +114,7 @@ public boolean isValueAvailable(AnalysisField field) { @Override protected ValueSupplier readHostedFieldValue(AnalysisField field, JavaConstant receiver) { AnalysisConstantReflectionProvider aConstantReflection = (AnalysisConstantReflectionProvider) this.constantReflection; - return aConstantReflection.readHostedFieldValue(field, hostedMetaAccess, receiver, true); + return aConstantReflection.readHostedFieldValue(field, receiver, true); } @Override From 5d0ed0122bd9257299372a35e9b465e79671120d Mon Sep 17 00:00:00 2001 From: Codrut Stancu Date: Tue, 19 Sep 2023 23:41:59 +0200 Subject: [PATCH 4/4] Redirect HostedSnippetReflectionProvider.forBoxed through the shadow heap. --- .../oracle/svm/hosted/NativeImageGenerator.java | 15 +++++++++++++++ .../meta/HostedSnippetReflectionProvider.java | 9 +++++++++ 2 files changed, 24 insertions(+) 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 d6c9780bd128..c85cb81f67ce 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 @@ -1126,6 +1126,21 @@ public static void initializeBigBang(Inflation bb, OptionValues options, Feature bb.getMetaAccess().lookupJavaType(JavaKind.Void.toJavaClass()).registerAsReachable("root class"); bb.getMetaAccess().lookupJavaType(com.oracle.svm.core.util.Counter.class).registerAsReachable("root class"); bb.getMetaAccess().lookupJavaType(com.oracle.svm.core.allocationprofile.AllocationCounter.class).registerAsReachable("root class"); + /* + * SubstrateAllocationProfilingData is not actually present in the image since it is + * only allocated at build time, is passed to snippets as a @ConstantParameter, and it + * only contains final fields that are constant-folded. However, since the profiling + * object is only allocated during lowering it is processed by the shadow heap after + * analysis, so its type needs to be already marked reachable at this point. + */ + bb.getMetaAccess().lookupJavaType(com.oracle.svm.core.graal.snippets.SubstrateAllocationSnippets.SubstrateAllocationProfilingData.class).registerAsReachable("root class"); + /* + * Similarly to above, StackSlotIdentity only gets reachable during lowering, through + * build time allocated constants. It doesn't actually end up in the image heap since + * all its fields are final and are constant-folded, but the type becomes reachable, + * through the shadow heap processing, after analysis. + */ + bb.getMetaAccess().lookupJavaType(com.oracle.svm.core.graal.stackvalue.StackValueNode.StackSlotIdentity.class).registerAsReachable("root class"); NativeImageGenerator.registerGraphBuilderPlugins(featureHandler, null, aProviders, aMetaAccess, aUniverse, null, null, nativeLibraries, loader, ParsingReason.PointsToAnalysis, bb.getAnnotationSubstitutionProcessor(), classInitializationPlugin, ConfigurationValues.getTarget(), supportsStubBasedPlugins); 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 1ced5db218c9..04d91eb95c83 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 @@ -38,6 +38,7 @@ import com.oracle.svm.hosted.ameta.AnalysisConstantReflectionProvider; import jdk.vm.ci.meta.JavaConstant; +import jdk.vm.ci.meta.JavaKind; public class HostedSnippetReflectionProvider extends SubstrateSnippetReflectionProvider { private ImageHeapScanner heapScanner; @@ -65,6 +66,14 @@ public JavaConstant forObject(Object object) { return heapScanner.createImageHeapConstant(super.forObject(object), OtherReason.UNKNOWN); } + @Override + public JavaConstant forBoxed(JavaKind kind, Object value) { + if (kind == JavaKind.Object) { + return forObject(value); + } + return JavaConstant.forBoxedPrimitive(value); + } + @Override public JavaConstant unwrapConstant(JavaConstant constant) { if (constant instanceof ImageHeapConstant heapConstant && heapConstant.getHostedObject() != null) {