Skip to content

Commit

Permalink
[GR-60551] [GR-60503] Mark all persisted constants as reachable
Browse files Browse the repository at this point in the history
PullRequest: graal/19744
  • Loading branch information
Zeavee committed Jan 17, 2025
2 parents 7cc02b1 + 6719253 commit 07d4cfd
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 70 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,22 @@ public EncodedGraph(byte[] encoding, int startOffset, Object[] objects, NodeClas
sourceGraph.trackNodeSourcePosition());
}

public EncodedGraph(EncodedGraph original) {
this(original.encoding,
original.startOffset,
original.objects,
original.types,
original.assumptions,
original.inlinedMethods,
original.hasUnsafeAccess,
original.trackNodeSourcePosition);
/*
* The nodeStartOffsets is only used as a cache for decoding, so it is not copied to ensure
* not having inconsistent caching information in the new EncodedGraph.
*/
this.nodeStartOffsets = null;
}

public EncodedGraph(byte[] encoding, int startOffset, Object[] objects, NodeClass<?>[] types, Assumptions assumptions, List<ResolvedJavaMethod> inlinedMethods,
boolean hasUnsafeAccess, boolean trackNodeSourcePosition) {
this.encoding = encoding;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,7 @@ public static class OtherReason extends ScanReason {
public static final ScanReason UNKNOWN = new OtherReason("manually created constant");
public static final ScanReason RESCAN = new OtherReason("manually triggered rescan");
public static final ScanReason HUB = new OtherReason("scanning a class constant");
public static final ScanReason PERSISTED = new OtherReason("persisted");

final String reason;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
*/
package com.oracle.graal.pointsto.api;

import com.oracle.graal.pointsto.flow.AnalysisParsedGraph;
import com.oracle.graal.pointsto.meta.AnalysisMethod;
import com.oracle.graal.pointsto.util.AnalysisError;

Expand All @@ -33,4 +34,9 @@ public class ImageLayerWriter {
public void onTrackedAcrossLayer(AnalysisMethod method, Object reason) {
throw AnalysisError.shouldNotReachHere("This method should not be called");
}

@SuppressWarnings("unused")
public void persistAnalysisParsedGraph(AnalysisMethod method, AnalysisParsedGraph analysisParsedGraph) {
throw AnalysisError.shouldNotReachHere("This method should not be called");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -497,7 +497,7 @@ private void notifyAnalysis(AnalysisField field, ImageHeapInstance receiver, Jav
}

private void notifyAnalysis(AnalysisField field, ImageHeapInstance receiver, JavaConstant fieldValue, ScanReason reason, Consumer<ScanReason> onAnalysisModified) {
if (scanningObserver != null) {
if (!universe.sealed()) {
/* Notify the points-to analysis of the scan. */
boolean analysisModified = doNotifyAnalysis(field, receiver, fieldValue, reason);
if (analysisModified && onAnalysisModified != null) {
Expand Down Expand Up @@ -563,7 +563,7 @@ private boolean notifyAnalysis(JavaConstant array, AnalysisType arrayType, JavaC
return analysisModified;
}

protected JavaConstant markReachable(JavaConstant constant, ScanReason reason) {
public JavaConstant markReachable(JavaConstant constant, ScanReason reason) {
return markReachable(constant, reason, null);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceFieldUpdater;
import java.util.concurrent.locks.ReentrantLock;
Expand All @@ -50,6 +51,7 @@

import com.oracle.graal.pointsto.BigBang;
import com.oracle.graal.pointsto.api.ImageLayerLoader;
import com.oracle.graal.pointsto.api.ImageLayerWriter;
import com.oracle.graal.pointsto.api.PointstoOptions;
import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException;
import com.oracle.graal.pointsto.flow.AnalysisParsedGraph;
Expand Down Expand Up @@ -174,6 +176,7 @@ public record Signature(String name, AnalysisType[] parameterTypes) {
private final boolean enableReachableInCurrentLayer;

private final AtomicReference<GraphCacheEntry> parsedGraphCacheState = new AtomicReference<>(GraphCacheEntry.UNPARSED);
private final AtomicBoolean trackedGraphPersisted = new AtomicBoolean(false);

private EncodedGraph analyzedGraph;

Expand Down Expand Up @@ -547,6 +550,13 @@ protected void notifyImplementationInvokedCallbacks() {
ConcurrentLightHashSet.removeElementIf(this, implementationInvokedNotificationsUpdater, ElementNotification::isNotified);
}

private void persistTrackedGraph(AnalysisParsedGraph graph) {
if (isTrackedAcrossLayers() && trackedGraphPersisted.compareAndSet(false, true)) {
ImageLayerWriter imageLayerWriter = getUniverse().getImageLayerWriter();
imageLayerWriter.persistAnalysisParsedGraph(this, graph);
}
}

/** Get the set of all callers for this method, as inferred by the static analysis. */
public Set<AnalysisMethod> getCallers() {
return getInvokeLocations().stream().map(location -> (AnalysisMethod) location.getMethod()).collect(Collectors.toSet());
Expand Down Expand Up @@ -684,6 +694,10 @@ protected void onTrackedAcrossLayers(Object reason) {
parameter.registerAsTrackedAcrossLayers(reason);
}
signature.getReturnType().registerAsTrackedAcrossLayers(reason);

if (getParsedGraphCacheStateObject() instanceof AnalysisParsedGraph analysisParsedGraph) {
persistTrackedGraph(analysisParsedGraph);
}
}

public void registerOverrideReachabilityNotification(MethodOverrideReachableNotification notification) {
Expand Down Expand Up @@ -1233,7 +1247,13 @@ private AnalysisParsedGraph setGraph(BigBang bb, Stage stage, GraphCacheEntry ex
boolean result = parsedGraphCacheState.compareAndSet(lockState, newEntry);
AnalysisError.guarantee(result, "State transition failed");

return (AnalysisParsedGraph) newEntry.get(stage);
AnalysisParsedGraph analysisParsedGraph = (AnalysisParsedGraph) newEntry.get(stage);

if (stage == Stage.finalStage()) {
persistTrackedGraph(analysisParsedGraph);
}

return analysisParsedGraph;

} catch (Throwable ex) {
parsedGraphCacheState.set(GraphCacheEntry.createParsingError(stage, expectedValue, ex));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,10 @@ protected ImageLayerBuildingSupport(boolean buildingImageLayer, boolean building
*/
public static void openModules() {
ModuleSupport.accessPackagesToClass(ModuleSupport.Access.OPEN, ObjectCopier.class, false, "java.base", "java.lang");
ModuleSupport.accessPackagesToClass(ModuleSupport.Access.OPEN, ObjectCopier.class, false, "java.base", "java.lang.reflect");
ModuleSupport.accessPackagesToClass(ModuleSupport.Access.OPEN, ObjectCopier.class, false, "java.base", "java.util");
ModuleSupport.accessPackagesToClass(ModuleSupport.Access.OPEN, ObjectCopier.class, false, "java.base", "java.util.concurrent");
ModuleSupport.accessPackagesToClass(ModuleSupport.Access.OPEN, ObjectCopier.class, false, "java.base", "sun.reflect.annotation");
}

private static ImageLayerBuildingSupport singleton() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -572,11 +572,6 @@ protected void doRun(Map<Method, CEntryPointData> entryPoints, JavaMainSupport j
return;
}

if (ImageLayerBuildingSupport.buildingSharedLayer()) {
HostedImageLayerBuildingSupport.singleton().getWriter().initializeExternalValues();
HostedImageLayerBuildingSupport.singleton().getWriter().persistAnalysisParsedGraphs();
}

NativeImageHeap heap;
HostedMetaAccess hMetaAccess;
RuntimeConfiguration runtimeConfiguration;
Expand Down Expand Up @@ -811,6 +806,9 @@ protected boolean runPointsToAnalysis(String imageName, OptionValues options, De
if (ImageLayerBuildingSupport.buildingImageLayer()) {
ImageSingletons.lookup(LoadImageSingletonFeature.class).processRegisteredSingletons(aUniverse);
}
if (ImageLayerBuildingSupport.buildingSharedLayer()) {
HostedImageLayerBuildingSupport.singleton().getWriter().initializeExternalValues();
}
}

try (ReporterClosable c = ProgressReporter.singleton().printAnalysis(bb.getUniverse(), nativeLibraries.getLibraries())) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -823,7 +823,9 @@ private PersistedAnalysisMethod.Reader getMethodData(AnalysisMethod analysisMeth
}

/**
* See {@link SVMImageLayerWriter#persistAnalysisParsedGraphs()} for implementation.
* See
* {@link SVMImageLayerWriter#persistAnalysisParsedGraph(AnalysisMethod, AnalysisParsedGraph)}
* for implementation.
*/
@Override
public boolean hasAnalysisParsedGraph(AnalysisMethod analysisMethod) {
Expand Down Expand Up @@ -1248,11 +1250,11 @@ private Object[] getReferencedValues(ImageHeapConstant parentConstant, StructLis
if (delegateProcessing(constantData, values, position)) {
continue;
}
int finalPosition = position;
values[position] = switch (constantData.which()) {
case OBJECT_CONSTANT -> {
int constantId = constantData.getObjectConstant().getConstantId();
boolean relink = positionsToRelink.contains(position);
int finalPosition = position;
yield new AnalysisFuture<>(() -> {
ensureHubInitialized(parentConstant);

Expand All @@ -1279,7 +1281,14 @@ private Object[] getReferencedValues(ImageHeapConstant parentConstant, StructLis
* in the base image.
*/
new AnalysisFuture<>(() -> {
throw AnalysisError.shouldNotReachHere("This constant was not materialized in the base image.");
String errorMessage = "Reading the value of a base layer constant which was not materialized in the base image, ";
if (parentConstant instanceof ImageHeapInstance instance) {
AnalysisField field = getFieldFromIndex(instance, finalPosition);
errorMessage += "reachable by reading field " + field + " of parent object constant: " + parentConstant;
} else {
errorMessage += "reachable by indexing at position " + finalPosition + " into parent array constant: " + parentConstant;
}
throw AnalysisError.shouldNotReachHere(errorMessage);
});
case PRIMITIVE_VALUE -> {
PrimitiveValue.Reader pv = constantData.getPrimitiveValue();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

import org.graalvm.nativeimage.ImageSingletons;

import com.oracle.graal.pointsto.ObjectScanner;
import com.oracle.graal.pointsto.heap.ImageHeapConstant;
import com.oracle.graal.pointsto.heap.ImageHeapInstance;
import com.oracle.graal.pointsto.heap.ImageHeapObjectArray;
Expand All @@ -51,6 +52,7 @@
import com.oracle.graal.pointsto.meta.AnalysisMetaAccess;
import com.oracle.graal.pointsto.meta.AnalysisMethod;
import com.oracle.graal.pointsto.meta.AnalysisType;
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
import com.oracle.graal.pointsto.meta.PointsToAnalysisField;
import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod;
import com.oracle.graal.pointsto.meta.PointsToAnalysisType;
Expand Down Expand Up @@ -84,6 +86,7 @@
import jdk.graal.compiler.util.ObjectCopierInputStream;
import jdk.graal.compiler.util.ObjectCopierOutputStream;
import jdk.vm.ci.hotspot.HotSpotResolvedJavaMethod;
import jdk.vm.ci.meta.ConstantReflectionProvider;

public class SVMImageLayerSnapshotUtil {
public static final String FILE_NAME_PREFIX = "layer-snapshot-";
Expand Down Expand Up @@ -115,6 +118,8 @@ public class SVMImageLayerSnapshotUtil {
protected static final Set<Field> dynamicHubRelinkedFields = Set.of(companion, name, componentType);
protected static final Set<Field> dynamicHubCompanionRelinkedFields = Set.of(classInitializationInfo, superHub, arrayHub);

private static final Class<?> sourceRoots = ReflectionUtil.lookupClass("com.oracle.svm.hosted.image.sources.SourceCache$SourceRoots");

/**
* This map stores the field indexes that should be relinked using the hosted value of a
* constant from the key type.
Expand Down Expand Up @@ -151,6 +156,10 @@ private void addSVMExternalValueFields() {
continue;
}

if (!shouldScanClass(clazz)) {
continue;
}

/* The ObjectCopier needs to access the static fields by reflection */
Module module = clazz.getModule();
ModuleSupport.accessPackagesToClass(ModuleSupport.Access.OPEN, ObjectCopier.class, false, module.getName(), packageName);
Expand Down Expand Up @@ -182,6 +191,11 @@ protected boolean shouldScanPackage(String packageName) {
return true;
}

private static boolean shouldScanClass(Class<?> clazz) {
/* This class should not be scanned because it needs to be initialized after the analysis */
return !clazz.equals(sourceRoots);
}

/**
* Get all the field indexes that should be relinked using the hosted value of a constant from
* the given type.
Expand All @@ -207,8 +221,8 @@ private static Set<Integer> getRelinkedFields(AnalysisType type, Set<Field> type
return typeRelinkedFieldsSet.stream().map(metaAccess::lookupJavaField).map(AnalysisField::getPosition).collect(Collectors.toSet());
}

public SVMGraphEncoder getGraphEncoder(SVMImageLayerWriter imageLayerWriter) {
return new SVMGraphEncoder(externalValues, imageLayerWriter);
public SVMGraphEncoder getGraphEncoder() {
return new SVMGraphEncoder(externalValues);
}

public AbstractSVMGraphDecoder getGraphHostedToAnalysisElementsDecoder(SVMImageLayerLoader imageLayerLoader, AnalysisMethod analysisMethod, SnippetReflectionProvider snippetReflectionProvider) {
Expand Down Expand Up @@ -309,9 +323,9 @@ private static String getQualifiedName(AnalysisMethod method) {

public static class SVMGraphEncoder extends ObjectCopier.Encoder {
@SuppressWarnings("this-escape")
public SVMGraphEncoder(Map<Object, Field> externalValues, SVMImageLayerWriter imageLayerWriter) {
public SVMGraphEncoder(Map<Object, Field> externalValues) {
super(externalValues);
addBuiltin(new ImageHeapConstantBuiltIn(imageLayerWriter, null));
addBuiltin(new ImageHeapConstantBuiltIn(null));
addBuiltin(new AnalysisTypeBuiltIn(null));
addBuiltin(new AnalysisMethodBuiltIn(null, null));
addBuiltin(new AnalysisFieldBuiltIn(null));
Expand All @@ -333,7 +347,7 @@ public abstract static class AbstractSVMGraphDecoder extends ObjectCopier.Decode
public AbstractSVMGraphDecoder(ClassLoader classLoader, SVMImageLayerLoader imageLayerLoader, AnalysisMethod analysisMethod, SnippetReflectionProvider snippetReflectionProvider) {
super(classLoader);
this.imageLayerBuildingSupport = imageLayerLoader.getImageLayerBuildingSupport();
addBuiltin(new ImageHeapConstantBuiltIn(null, imageLayerLoader));
addBuiltin(new ImageHeapConstantBuiltIn(imageLayerLoader));
addBuiltin(new AnalysisTypeBuiltIn(imageLayerLoader));
addBuiltin(new AnalysisMethodBuiltIn(imageLayerLoader, analysisMethod));
addBuiltin(new AnalysisFieldBuiltIn(imageLayerLoader));
Expand Down Expand Up @@ -371,19 +385,28 @@ public SVMGraphDecoder(ClassLoader classLoader, SVMImageLayerLoader svmImageLaye
}

public static class ImageHeapConstantBuiltIn extends ObjectCopier.Builtin {
private final SVMImageLayerWriter imageLayerWriter;
private final SVMImageLayerLoader imageLayerLoader;

protected ImageHeapConstantBuiltIn(SVMImageLayerWriter imageLayerWriter, SVMImageLayerLoader imageLayerLoader) {
protected ImageHeapConstantBuiltIn(SVMImageLayerLoader imageLayerLoader) {
super(ImageHeapConstant.class, ImageHeapInstance.class, ImageHeapObjectArray.class, ImageHeapPrimitiveArray.class);
this.imageLayerWriter = imageLayerWriter;
this.imageLayerLoader = imageLayerLoader;
}

@Override
public void encode(ObjectCopier.Encoder encoder, ObjectCopierOutputStream stream, Object obj) throws IOException {
ImageHeapConstant imageHeapConstant = (ImageHeapConstant) obj;
imageLayerWriter.ensureConstantPersisted(imageHeapConstant);

AnalysisUniverse universe = imageHeapConstant.getType().getUniverse();
universe.getHeapScanner().markReachable(imageHeapConstant, ObjectScanner.OtherReason.PERSISTED);

imageHeapConstant.getType().registerAsTrackedAcrossLayers(imageHeapConstant);
/* If this is a Class constant persist the corresponding type. */
ConstantReflectionProvider constantReflection = universe.getBigbang().getConstantReflectionProvider();
AnalysisType typeFromClassConstant = (AnalysisType) constantReflection.asJavaType(imageHeapConstant);
if (typeFromClassConstant != null) {
typeFromClassConstant.registerAsTrackedAcrossLayers(imageHeapConstant);
}

stream.writePackedUnsignedInt(ImageHeapConstant.getConstantID(imageHeapConstant));
}

Expand Down
Loading

0 comments on commit 07d4cfd

Please sign in to comment.