Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -542,11 +542,7 @@ public String toString(BigBang bb) {
}

public static class OtherReason extends ScanReason {
public static final ScanReason LATE_SCAN = new OtherReason("late scan, after sealing heap");
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 Expand Up @@ -608,8 +604,7 @@ public AnalysisField getField() {

public String location() {
Object readBy = field.getReadBy();
if (readBy instanceof BytecodePosition) {
BytecodePosition position = (BytecodePosition) readBy;
if (readBy instanceof BytecodePosition position) {
return position.getMethod().asStackTraceElement(position.getBCI()).toString();
} else if (readBy instanceof AnalysisMethod) {
return ((AnalysisMethod) readBy).asStackTraceElement(0).toString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,9 @@ public abstract class ImageHeapScanner {

private boolean sealed;

/** Reserved for constants that are only known late, e.g., like interned strings array. */
public static final ScanReason LATE_SCAN = new OtherReason("Constant scanned manually after sealing the heap.");

public ImageHeapScanner(BigBang bb, ImageHeap heap, AnalysisMetaAccess aMetaAccess, SnippetReflectionProvider aSnippetReflection,
ConstantReflectionProvider aConstantReflection, ObjectScanningObserver aScanningObserver, HostedValuesProvider aHostedValuesProvider) {
this.bb = bb;
Expand Down Expand Up @@ -299,7 +302,7 @@ private void ensureFieldPositionsComputed(ImageHeapConstant baseLayerConstant, S
}

private void checkSealed(ScanReason reason, String format, Object... args) {
if (sealed && reason != OtherReason.LATE_SCAN) {
if (sealed && reason != LATE_SCAN) {
throw AnalysisError.sealedHeapError(HeapSnapshotVerifier.formatReason(bb, reason, format, args));
}
}
Expand Down Expand Up @@ -678,25 +681,37 @@ protected ValueSupplier<JavaConstant> readHostedFieldValue(AnalysisField field,
return hostedValuesProvider.readFieldValue(field, receiver);
}

public void rescanRoot(Field reflectionField) {
/**
* Trigger rescanning of a root field. If the value was not scanned before it will first be
* scanned and added to the shadow heap, then it will be linked to the field. If the value is
* already in the shadow heap it will not be rescanned, i.e., it's fields will not be followed,
* with an exception: if the value is a known collection type ({@code Object[]},
* {{@link Collection}, {@link Map} or {@link EconomicMap}} then its elements will be rescanned
* too.
*/
public void rescanRoot(Field reflectionField, ScanReason rescanReason) {
maybeRunInExecutor(unused -> {
AnalysisType type = metaAccess.lookupJavaType(reflectionField.getDeclaringClass());
if (type.isReachable()) {
AnalysisField field = metaAccess.lookupJavaField(reflectionField);
JavaConstant fieldValue = readHostedFieldValue(field, null).get();
TypeData typeData = field.getDeclaringClass().getOrComputeData();
AnalysisFuture<JavaConstant> fieldTask = patchStaticField(typeData, field, fieldValue, OtherReason.RESCAN, null);
AnalysisFuture<JavaConstant> fieldTask = patchStaticField(typeData, field, fieldValue, rescanReason, null);
if (field.isRead() || field.isFolded()) {
rescanCollectionElements(fieldTask.ensureDone());
rescanCollectionElements(fieldTask.ensureDone(), new FieldScan(field, null, rescanReason));
}
}
});
}

public void rescanField(Object receiver, Field reflectionField) {
rescanField(receiver, reflectionField, OtherReason.RESCAN);
}

/**
* Trigger rescanning of an instance field. If the receiver value or field value were not
* scanned before they will first be scanned and added to the shadow heap, then the value will
* be linked to the field. If the value is already in the shadow heap it will not be rescanned,
* i.e., it's fields will not be followed, with an exception: if the value is a known collection
* type ({@code Object[]}, {{@link Collection}, {@link Map} or {@link EconomicMap}} then its
* elements will be rescanned too.
*/
public void rescanField(Object receiver, Field reflectionField, ScanReason reason) {
maybeRunInExecutor(unused -> {
AnalysisType type = metaAccess.lookupJavaType(reflectionField.getDeclaringClass());
Expand Down Expand Up @@ -736,7 +751,7 @@ public void rescanField(Object receiver, Field reflectionField, ScanReason reaso
if (field.isRead() || field.isFolded()) {
JavaConstant constant = fieldTask.ensureDone();
ensureReaderInstalled(constant);
rescanCollectionElements(constant);
rescanCollectionElements(constant, reason);
}
} else {
ScanningObserver.patchPrimitiveArrayValue(bb, fieldSnapshot, fieldValue);
Expand Down Expand Up @@ -808,63 +823,49 @@ public boolean isObjectReachable(Object object) {
/**
* Add the object to the image heap and, if the object is a collection, rescan its elements.
*/
public void rescanObject(Object object) {
rescanObject(object, OtherReason.RESCAN);
}

/**
* Add the object to the image heap.
*/
public void rescanObject(Object object, ScanReason reason) {
if (object == null) {
return;
}

maybeRunInExecutor(unused -> {
doScan(asConstant(object), reason);
rescanCollectionElements(object);
rescanCollectionElements(object, reason);
});
}

private void rescanCollectionElements(JavaConstant constant) {
private void rescanCollectionElements(JavaConstant constant, ScanReason reason) {
if (isNonNullObjectConstant(constant)) {
rescanCollectionElements(snippetReflection.asObject(Object.class, constant));
rescanCollectionElements(snippetReflection.asObject(Object.class, constant), reason);
}
}

private void rescanCollectionElements(Object object) {
if (object instanceof Object[]) {
Object[] array = (Object[]) object;
private void rescanCollectionElements(Object object, ScanReason reason) {
if (object instanceof Object[] array) {
for (Object element : array) {
doScan(asConstant(element));
doScan(asConstant(element), reason);
}
} else if (object instanceof Collection) {
Collection<?> collection = (Collection<?>) object;
collection.forEach(e -> doScan(asConstant(e)));
} else if (object instanceof Map) {
Map<?, ?> map = (Map<?, ?>) object;
} else if (object instanceof Collection<?> collection) {
collection.forEach(e -> doScan(asConstant(e), reason));
} else if (object instanceof Map<?, ?> map) {
map.forEach((k, v) -> {
doScan(asConstant(k));
doScan(asConstant(v));
doScan(asConstant(k), reason);
doScan(asConstant(v), reason);
});
} else if (object instanceof EconomicMap) {
rescanEconomicMap((EconomicMap<?, ?>) object);
rescanEconomicMap((EconomicMap<?, ?>) object, reason);
}
}

protected void rescanEconomicMap(EconomicMap<?, ?> object) {
protected void rescanEconomicMap(EconomicMap<?, ?> object, ScanReason reason) {
MapCursor<?, ?> cursor = object.getEntries();
while (cursor.advance()) {
doScan(asConstant(cursor.getKey()));
doScan(asConstant(cursor.getValue()));
doScan(asConstant(cursor.getKey()), reason);
doScan(asConstant(cursor.getValue()), reason);
}
}

public void doScan(JavaConstant constant) {
doScan(constant, OtherReason.RESCAN);
}

void doScan(JavaConstant constant, ScanReason reason) {
public void doScan(JavaConstant constant, ScanReason reason) {
JavaConstant value = createImageHeapConstant(constant, reason);
markReachable(value, reason, null);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,8 @@
import org.graalvm.nativeimage.hosted.Feature.BeforeHeapLayoutAccess;
import org.graalvm.nativeimage.hosted.Feature.FeatureAccess;

import com.oracle.graal.pointsto.ObjectScanner.OtherReason;
import com.oracle.graal.pointsto.ObjectScanner.ScanReason;
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
import com.oracle.svm.core.BuildPhaseProvider.AfterAnalysis;
import com.oracle.svm.core.config.ConfigurationValues;
Expand Down Expand Up @@ -80,6 +82,8 @@
*/
public class TruffleRuntimeCompilationSupport {

private static final ScanReason scanReason = new OtherReason("Manual rescan of Graal objects triggered from " + TruffleRuntimeCompilationSupport.class);

private RuntimeConfiguration runtimeConfig;

private Suites fullOptimizationSuites;
Expand Down Expand Up @@ -237,7 +241,7 @@ private static void rescan(FeatureAccess a, Object object) {
* and patches the shadow heap.
*/
public static void rescan(AnalysisUniverse universe, Object object) {
universe.getHeapScanner().rescanObject(object);
universe.getHeapScanner().rescanObject(object, scanReason);
}

@Platforms(Platform.HOSTED_ONLY.class)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function;

import com.oracle.graal.pointsto.ObjectScanner.OtherReason;
import com.oracle.graal.pointsto.ObjectScanner.ScanReason;
import com.oracle.graal.pointsto.heap.ImageHeapConstant;
import com.oracle.svm.core.BuildPhaseProvider;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
Expand Down Expand Up @@ -167,7 +169,8 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
* We need to scan this because the final package info cannot be installed until after
* analysis has completed.
*/
config.rescanObject(HostedClassLoaderPackageManagement.singleton().getPriorAppClassLoaderPackages());
ScanReason reason = new OtherReason("Manual rescan triggered from " + ClassLoaderFeature.class);
config.rescanObject(HostedClassLoaderPackageManagement.singleton().getPriorAppClassLoaderPackages(), reason);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import com.oracle.graal.pointsto.ObjectScanner.OtherReason;
import com.oracle.graal.pointsto.ObjectScanner.ScanReason;
import com.oracle.graal.pointsto.meta.AnalysisType;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
Expand Down Expand Up @@ -114,7 +116,8 @@ public void duringAnalysis(DuringAnalysisAccess access) {
}

int numTypes = impl.getUniverse().getTypes().size();
mapsToRescan.forEach(impl::rescanObject);
ScanReason reason = new OtherReason("Manual rescan triggered from " + ClassValueFeature.class);
mapsToRescan.forEach(obj -> impl.rescanObject(obj, reason));
if (numTypes != impl.getUniverse().getTypes().size()) {
access.requireAnalysisIteration();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
*/
package com.oracle.svm.hosted;

import static com.oracle.graal.pointsto.ObjectScanner.OtherReason;
import static com.oracle.graal.pointsto.ObjectScanner.ScanReason;

import org.graalvm.nativeimage.ImageSingletons;

import com.oracle.graal.pointsto.heap.ImageHeapConstant;
Expand Down Expand Up @@ -60,7 +63,8 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
@Override
public void beforeCompilation(BeforeCompilationAccess access) {
BeforeCompilationAccessImpl a = (BeforeCompilationAccessImpl) access;
a.getHeapScanner().rescanField(DynamicHubSupport.currentLayer(), ReflectionUtil.lookupField(DynamicHubSupport.class, "referenceMapEncoding"));
ScanReason reason = new OtherReason("Manual rescan triggered before compilation from " + DynamicHubSupport.class);
a.getHeapScanner().rescanField(DynamicHubSupport.currentLayer(), ReflectionUtil.lookupField(DynamicHubSupport.class, "referenceMapEncoding"), reason);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
import org.graalvm.nativeimage.hosted.RuntimeReflection;

import com.oracle.graal.pointsto.BigBang;
import com.oracle.graal.pointsto.ObjectScanner;
import com.oracle.graal.pointsto.ObjectScanner.ScanReason;
import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException;
import com.oracle.graal.pointsto.heap.ImageHeapConstant;
import com.oracle.graal.pointsto.heap.ImageHeapScanner;
Expand Down Expand Up @@ -263,16 +263,16 @@ Set<AnalysisMethod> reachableMethodOverrides(AnalysisMethod baseMethod) {
return baseMethod.collectMethodImplementations(true);
}

public void rescanObject(Object obj) {
getUniverse().getHeapScanner().rescanObject(obj);
public void rescanObject(Object obj, ScanReason reason) {
getUniverse().getHeapScanner().rescanObject(obj, reason);
}

public void rescanField(Object receiver, Field field) {
getUniverse().getHeapScanner().rescanField(receiver, field);
public void rescanField(Object receiver, Field field, ScanReason reason) {
getUniverse().getHeapScanner().rescanField(receiver, field, reason);
}

public void rescanRoot(Field field) {
getUniverse().getHeapScanner().rescanRoot(field);
public void rescanRoot(Field field, ScanReason reason) {
getUniverse().getHeapScanner().rescanRoot(field, reason);
}

public Field findField(String declaringClassName, String fieldName) {
Expand Down Expand Up @@ -465,7 +465,7 @@ public void registerAsRoot(AnalysisMethod aMethod, boolean invokeSpecial, String
bb.addRootMethod(aMethod, invokeSpecial, reason, otherRoots);
}

public void registerAsRoot(AnalysisMethod aMethod, boolean invokeSpecial, ObjectScanner.ScanReason reason, MultiMethod.MultiMethodKey... otherRoots) {
public void registerAsRoot(AnalysisMethod aMethod, boolean invokeSpecial, ScanReason reason, MultiMethod.MultiMethodKey... otherRoots) {
bb.addRootMethod(aMethod, invokeSpecial, reason, otherRoots);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@

import org.graalvm.nativeimage.hosted.RuntimeReflection;

import com.oracle.graal.pointsto.ObjectScanner.OtherReason;
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.option.HostedOptionKey;
Expand Down Expand Up @@ -99,7 +100,7 @@ public void beforeAnalysis(BeforeAnalysisAccess access) {
public void duringAnalysis(DuringAnalysisAccess a) {
DuringAnalysisAccessImpl access = (DuringAnalysisAccessImpl) a;

access.rescanRoot(loggersField);
access.rescanRoot(loggersField, new OtherReason("Manual rescan triggered during analysis from " + LoggingFeature.class));
}

private void registerForReflection(Class<?> clazz) {
Expand Down
Loading