Skip to content

Commit d62e574

Browse files
committed
[GR-42996] Refactor shadow heap.
PullRequest: graal/15141
2 parents 10bcd49 + a9ec779 commit d62e574

File tree

17 files changed

+134
-106
lines changed

17 files changed

+134
-106
lines changed

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageHeapScanner.java

Lines changed: 24 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -118,27 +118,27 @@ public void scanEmbeddedRoot(JavaConstant root, BytecodePosition position) {
118118
public void onFieldRead(AnalysisField field) {
119119
assert field.isRead();
120120
/* Check if the value is available before accessing it. */
121-
if (isValueAvailable(field)) {
122-
FieldScan reason = new FieldScan(field);
123-
AnalysisType declaringClass = field.getDeclaringClass();
124-
if (field.isStatic()) {
121+
FieldScan reason = new FieldScan(field);
122+
AnalysisType declaringClass = field.getDeclaringClass();
123+
if (field.isStatic()) {
124+
if (isValueAvailable(field)) {
125125
JavaConstant fieldValue = declaringClass.getOrComputeData().readFieldValue(field);
126126
markReachable(fieldValue, reason);
127127
notifyAnalysis(field, null, fieldValue, reason);
128-
} else {
129-
/* Trigger field scanning for the already processed objects. */
130-
postTask(() -> onInstanceFieldRead(field, declaringClass, reason));
128+
} else if (field.canBeNull()) {
129+
notifyAnalysis(field, null, JavaConstant.NULL_POINTER, reason);
131130
}
131+
} else {
132+
/* Trigger field scanning for the already processed objects. */
133+
postTask(() -> onInstanceFieldRead(field, declaringClass, reason));
132134
}
133135
}
134136

135137
private void onInstanceFieldRead(AnalysisField field, AnalysisType type, FieldScan reason) {
136138
for (AnalysisType subtype : type.getSubTypes()) {
137139
for (ImageHeapConstant imageHeapConstant : imageHeap.getReachableObjects(subtype)) {
138140
ImageHeapInstance imageHeapInstance = (ImageHeapInstance) imageHeapConstant;
139-
JavaConstant fieldValue = imageHeapInstance.readFieldValue(field);
140-
markReachable(fieldValue, reason);
141-
notifyAnalysis(field, imageHeapInstance, fieldValue, reason);
141+
updateInstanceField(field, imageHeapInstance, reason, null);
142142
}
143143
/* Subtypes include this type itself. */
144144
if (!subtype.equals(type)) {
@@ -468,17 +468,25 @@ protected void onObjectReachable(ImageHeapConstant imageHeapConstant, ScanReason
468468
} else if (imageHeapConstant instanceof ImageHeapInstance imageHeapInstance) {
469469
for (ResolvedJavaField javaField : objectType.getInstanceFields(true)) {
470470
AnalysisField field = (AnalysisField) javaField;
471-
if (field.isRead() && isValueAvailable(field)) {
472-
JavaConstant fieldValue = imageHeapInstance.readFieldValue(field);
473-
markReachable(fieldValue, reason, onAnalysisModified);
474-
notifyAnalysis(field, imageHeapInstance, fieldValue, reason, onAnalysisModified);
471+
if (field.isRead()) {
472+
updateInstanceField(field, imageHeapInstance, reason, onAnalysisModified);
475473
}
476474
}
477475
}
478476
}
479477

480-
public boolean isValueAvailable(@SuppressWarnings("unused") AnalysisField field) {
481-
return true;
478+
private void updateInstanceField(AnalysisField field, ImageHeapInstance imageHeapInstance, ScanReason reason, Consumer<ScanReason> onAnalysisModified) {
479+
if (isValueAvailable(field)) {
480+
JavaConstant fieldValue = imageHeapInstance.readFieldValue(field);
481+
markReachable(fieldValue, reason, onAnalysisModified);
482+
notifyAnalysis(field, imageHeapInstance, fieldValue, reason, onAnalysisModified);
483+
} else if (field.canBeNull()) {
484+
notifyAnalysis(field, imageHeapInstance, JavaConstant.NULL_POINTER, reason, onAnalysisModified);
485+
}
486+
}
487+
488+
public boolean isValueAvailable(AnalysisField field) {
489+
return field.isValueAvailable();
482490
}
483491

484492
protected String formatReason(String message, ScanReason reason) {

substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ImageHeapInfo.java

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -47,29 +47,29 @@ public final class ImageHeapInfo {
4747
/** Indicates no chunk with {@link #initialize} chunk offset parameters. */
4848
public static final long NO_CHUNK = -1;
4949

50-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object firstReadOnlyPrimitiveObject;
51-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object lastReadOnlyPrimitiveObject;
50+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object firstReadOnlyPrimitiveObject;
51+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object lastReadOnlyPrimitiveObject;
5252

53-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object firstReadOnlyReferenceObject;
54-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object lastReadOnlyReferenceObject;
53+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object firstReadOnlyReferenceObject;
54+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object lastReadOnlyReferenceObject;
5555

56-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object firstReadOnlyRelocatableObject;
57-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object lastReadOnlyRelocatableObject;
56+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object firstReadOnlyRelocatableObject;
57+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object lastReadOnlyRelocatableObject;
5858

59-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object firstWritablePrimitiveObject;
60-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object lastWritablePrimitiveObject;
59+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object firstWritablePrimitiveObject;
60+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object lastWritablePrimitiveObject;
6161

62-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object firstWritableReferenceObject;
63-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object lastWritableReferenceObject;
62+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object firstWritableReferenceObject;
63+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object lastWritableReferenceObject;
6464

65-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object firstWritableHugeObject;
66-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object lastWritableHugeObject;
65+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object firstWritableHugeObject;
66+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object lastWritableHugeObject;
6767

68-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object firstReadOnlyHugeObject;
69-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object lastReadOnlyHugeObject;
68+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object firstReadOnlyHugeObject;
69+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object lastReadOnlyHugeObject;
7070

71-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object firstObject;
72-
@UnknownObjectField(availability = AfterHeapLayout.class) public Object lastObject;
71+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object firstObject;
72+
@UnknownObjectField(availability = AfterHeapLayout.class, canBeNull = true) public Object lastObject;
7373

7474
// All offsets are relative to the heap base.
7575
@UnknownPrimitiveField(availability = AfterHeapLayout.class) public long offsetOfFirstWritableAlignedChunk;

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heapdump/HeapDumpUtils.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import org.graalvm.word.UnsignedWord;
3838
import org.graalvm.word.WordFactory;
3939

40+
import com.oracle.svm.core.BuildPhaseProvider.AfterCompilation;
4041
import com.oracle.svm.core.NeverInline;
4142
import com.oracle.svm.core.SubstrateOptions;
4243
import com.oracle.svm.core.code.CodeInfo;
@@ -64,7 +65,7 @@
6465
*/
6566
public class HeapDumpUtils {
6667

67-
@UnknownObjectField private byte[] fieldsMap;
68+
@UnknownObjectField(availability = AfterCompilation.class) private byte[] fieldsMap;
6869

6970
/** Extra methods for testing. */
7071
private final TestingBackDoor testingBackDoor;

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,7 @@ public final class DynamicHub implements AnnotatedElement, java.lang.reflect.Typ
314314
* Back link to the SubstrateType used by the substrate meta access. Only used for the subset of
315315
* types for which a SubstrateType exists.
316316
*/
317+
@UnknownObjectField(fullyQualifiedTypes = "com.oracle.svm.graal.meta.SubstrateType")//
317318
private SharedType metaType;
318319

319320
/**

substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/GraalSupport.java

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
import static org.graalvm.word.LocationIdentity.ANY_LOCATION;
2828

2929
import java.io.PrintStream;
30-
import java.lang.reflect.Field;
3130
import java.lang.reflect.Modifier;
3231
import java.util.ArrayList;
3332
import java.util.Arrays;
@@ -73,6 +72,7 @@
7372
import org.graalvm.word.Pointer;
7473
import org.graalvm.word.WordFactory;
7574

75+
import com.oracle.graal.pointsto.meta.AnalysisUniverse;
7676
import com.oracle.svm.core.c.CGlobalData;
7777
import com.oracle.svm.core.c.CGlobalDataFactory;
7878
import com.oracle.svm.core.config.ConfigurationValues;
@@ -86,7 +86,6 @@
8686
import com.oracle.svm.core.util.ImageHeapMap;
8787
import com.oracle.svm.graal.meta.SubstrateMethod;
8888
import com.oracle.svm.hosted.FeatureImpl.DuringAnalysisAccessImpl;
89-
import com.oracle.svm.util.ReflectionUtil;
9089

9190
/**
9291
* Holds data that is pre-computed during native image generation and accessed at run time during a
@@ -129,11 +128,6 @@ public class GraalSupport {
129128
protected final DiagnosticsOutputDirectory outputDirectory = new DiagnosticsOutputDirectory(RuntimeOptionValues.singleton());
130129
protected final Map<ExceptionAction, Integer> compilationProblemsPerAction = new EnumMap<>(ExceptionAction.class);
131130

132-
private static final Field graphEncodingField = ReflectionUtil.lookupField(GraalSupport.class, "graphEncoding");
133-
private static final Field graphObjectsField = ReflectionUtil.lookupField(GraalSupport.class, "graphObjects");
134-
private static final Field graphNodeTypesField = ReflectionUtil.lookupField(GraalSupport.class, "graphNodeTypes");
135-
private static final Field methodsToCompileField = ReflectionUtil.lookupField(GraalSupport.class, "methodsToCompile");
136-
137131
private static final CGlobalData<Pointer> nextIsolateId = CGlobalDataFactory.createWord((Pointer) WordFactory.unsigned(1L));
138132

139133
private volatile long isolateId = 0;
@@ -234,7 +228,7 @@ public static boolean setMethodsToCompile(DuringAnalysisAccessImpl config, Subst
234228
GraalSupport support = get();
235229
if (!Arrays.equals(support.methodsToCompile, methodsToCompile)) {
236230
support.methodsToCompile = methodsToCompile;
237-
GraalSupport.rescan(config, support, methodsToCompileField);
231+
GraalSupport.rescan(config, methodsToCompile);
238232
result = true;
239233
}
240234
return result;
@@ -274,28 +268,38 @@ public static boolean setGraphEncoding(FeatureAccess a, byte[] graphEncoding, Ob
274268
boolean result = false;
275269
if (!Arrays.equals(support.graphEncoding, graphEncoding)) {
276270
support.graphEncoding = graphEncoding;
277-
GraalSupport.rescan(a, support, graphEncodingField);
278271
result = true;
279272
}
280273
if (!Arrays.deepEquals(support.graphObjects, graphObjects)) {
281274
support.graphObjects = graphObjects;
282-
GraalSupport.rescan(a, support, graphObjectsField);
275+
GraalSupport.rescan(a, graphObjects);
283276
result = true;
284277
}
285278
if (!Arrays.equals(support.graphNodeTypes, graphNodeTypes)) {
286279
support.graphNodeTypes = graphNodeTypes;
287-
GraalSupport.rescan(a, support, graphNodeTypesField);
280+
GraalSupport.rescan(a, graphNodeTypes);
288281
result = true;
289282
}
290283
return result;
291284
}
292285

293-
private static void rescan(FeatureAccess a, GraalSupport support, Field field) {
294-
if (a instanceof DuringAnalysisAccessImpl) {
295-
((DuringAnalysisAccessImpl) a).rescanField(support, field);
286+
private static void rescan(FeatureAccess a, Object object) {
287+
if (a instanceof DuringAnalysisAccessImpl access) {
288+
rescan(access.getUniverse(), object);
296289
}
297290
}
298291

292+
/**
293+
* Rescan Graal objects during analysis. The fields that point to these objects are annotated
294+
* with {@link UnknownObjectField} so their value is not processed during analysis, only their
295+
* declared type is injected in the type flow graphs. Their eventual value becomes available
296+
* after analysis. Later when the field is read the lazy value supplier scans the final value
297+
* and patches the shadow heap.
298+
*/
299+
public static void rescan(AnalysisUniverse universe, Object object) {
300+
universe.getHeapScanner().rescanObject(object);
301+
}
302+
299303
@Platforms(Platform.HOSTED_ONLY.class)
300304
public static void registerImmutableObjects(CompilationAccess access) {
301305
access.registerAsImmutable(get().graphEncoding);

substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/GraalGraphObjectReplacer.java

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424
*/
2525
package com.oracle.svm.graal.hosted;
2626

27-
import java.lang.reflect.Field;
2827
import java.util.Map;
2928
import java.util.concurrent.ConcurrentHashMap;
3029
import java.util.concurrent.ConcurrentMap;
@@ -56,6 +55,7 @@
5655
import com.oracle.svm.core.util.HostedStringDeduplication;
5756
import com.oracle.svm.core.util.ObservableImageHeapMapProvider;
5857
import com.oracle.svm.core.util.VMError;
58+
import com.oracle.svm.graal.GraalSupport;
5959
import com.oracle.svm.graal.SubstrateGraalRuntime;
6060
import com.oracle.svm.graal.meta.SubstrateField;
6161
import com.oracle.svm.graal.meta.SubstrateMethod;
@@ -107,11 +107,6 @@ public class GraalGraphObjectReplacer implements Function<Object, Object> {
107107

108108
private final HostedStringDeduplication stringTable;
109109

110-
private final Field substrateFieldTypeField;
111-
private final Field substrateFieldDeclaringClassField;
112-
private final Field dynamicHubMetaTypeField;
113-
private final Field substrateTypeRawAllInstanceFieldsField;
114-
115110
private final Class<?> jvmciCleanerClass = ReflectionUtil.lookupClass(false, "jdk.vm.ci.hotspot.Cleaner");
116111

117112
/**
@@ -125,10 +120,6 @@ public GraalGraphObjectReplacer(AnalysisUniverse aUniverse, SubstrateProviders s
125120
this.sProviders = sProviders;
126121
this.universeFactory = universeFactory;
127122
this.stringTable = HostedStringDeduplication.singleton();
128-
substrateFieldTypeField = ReflectionUtil.lookupField(SubstrateField.class, "type");
129-
substrateFieldDeclaringClassField = ReflectionUtil.lookupField(SubstrateField.class, "declaringClass");
130-
dynamicHubMetaTypeField = ReflectionUtil.lookupField(DynamicHub.class, "metaType");
131-
substrateTypeRawAllInstanceFieldsField = ReflectionUtil.lookupField(SubstrateType.class, "rawAllInstanceFields");
132123
}
133124

134125
public void setGraalRuntime(SubstrateGraalRuntime sGraalRuntime) {
@@ -289,8 +280,8 @@ public synchronized SubstrateField createField(ResolvedJavaField original) {
289280
sField = newField;
290281

291282
sField.setLinks(createType(aField.getType()), createType(aField.getDeclaringClass()));
292-
aUniverse.getHeapScanner().rescanField(sField, substrateFieldTypeField);
293-
aUniverse.getHeapScanner().rescanField(sField, substrateFieldDeclaringClassField);
283+
GraalSupport.rescan(aUniverse, sField.getType());
284+
GraalSupport.rescan(aUniverse, sField.getDeclaringClass());
294285
}
295286
}
296287
return sField;
@@ -338,10 +329,10 @@ public synchronized SubstrateType createType(JavaType original) {
338329
if (sType == null) {
339330
sType = newType;
340331
hub.setMetaType(sType);
341-
aUniverse.getHeapScanner().rescanField(hub, dynamicHubMetaTypeField);
332+
GraalSupport.rescan(aUniverse, hub.getMetaType());
342333

343334
sType.setRawAllInstanceFields(createAllInstanceFields(aType));
344-
aUniverse.getHeapScanner().rescanField(sType, substrateTypeRawAllInstanceFieldsField);
335+
GraalSupport.rescan(aUniverse, sType.getRawAllInstanceFields());
345336
createType(aType.getSuperclass());
346337
createType(aType.getComponentType());
347338
for (AnalysisType aInterface : aType.getInterfaces()) {

substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/meta/SubstrateField.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,8 +50,8 @@ public class SubstrateField implements SharedField {
5050

5151
protected static final SubstrateField[] EMPTY_ARRAY = new SubstrateField[0];
5252

53-
SubstrateType type;
54-
SubstrateType declaringClass;
53+
@UnknownObjectField SubstrateType type;
54+
@UnknownObjectField SubstrateType declaringClass;
5555
private final String name;
5656
private final int modifiers;
5757
private int hashCode;

0 commit comments

Comments
 (0)