Skip to content

Commit 28a4718

Browse files
committed
[GR-42996] Refactor shadow heap verification and fix lazy scanned values.
PullRequest: graal/15503
2 parents 365052a + 59751ac commit 28a4718

File tree

13 files changed

+293
-202
lines changed

13 files changed

+293
-202
lines changed

substratevm/src/com.oracle.graal.pointsto.standalone/src/com/oracle/graal/pointsto/standalone/heap/StandaloneHeapSnapshotVerifier.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
import com.oracle.graal.pointsto.heap.HeapSnapshotVerifier;
3232
import com.oracle.graal.pointsto.heap.ImageHeap;
3333
import com.oracle.graal.pointsto.heap.ImageHeapScanner;
34+
import com.oracle.graal.pointsto.infrastructure.UniverseMetaAccess;
3435
import com.oracle.graal.pointsto.standalone.StandaloneObjectScanner;
3536
import com.oracle.graal.pointsto.util.CompletionExecutor;
3637

@@ -40,7 +41,7 @@ public StandaloneHeapSnapshotVerifier(BigBang bb, ImageHeap imageHeap, ImageHeap
4041
}
4142

4243
@Override
43-
protected ObjectScanner installObjectScanner(CompletionExecutor executor) {
44+
protected ObjectScanner installObjectScanner(UniverseMetaAccess metaAccess, CompletionExecutor executor) {
4445
StandaloneImageHeapScanner standaloneImageHeapScanner = (StandaloneImageHeapScanner) this.scanner;
4546
return new StandaloneObjectScanner(bb, executor, scannedObjects, new ScanningObserver(), standaloneImageHeapScanner.getShouldScanConstant(),
4647
standaloneImageHeapScanner.getShouldScanField());

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/AbstractAnalysisEngine.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,10 +204,10 @@ public void runAnalysis(DebugContext debugContext, Function<AnalysisUniverse, Bo
204204
protected abstract CompletionExecutor.Timing getTiming();
205205

206206
@SuppressWarnings("try")
207-
private boolean analysisModified() throws InterruptedException {
207+
private boolean analysisModified() {
208208
boolean analysisModified;
209209
try (Timer.StopTimer ignored = verifyHeapTimer.start()) {
210-
analysisModified = universe.getHeapVerifier().requireAnalysisIteration(executor);
210+
analysisModified = universe.getHeapVerifier().checkHeapSnapshot(metaAccess, executor, "after analysis", true);
211211
}
212212
/* Initialize for the next iteration. */
213213
executor.init(getTiming());

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanner.java

Lines changed: 58 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ public void scanBootImageHeapRoots(Comparator<AnalysisField> fieldComparator, Co
9898
fields = fieldsList;
9999
}
100100
for (AnalysisField field : fields) {
101-
if (Modifier.isStatic(field.getModifiers()) && field.getJavaKind() == JavaKind.Object && field.isRead()) {
101+
if (Modifier.isStatic(field.getModifiers()) && field.isRead()) {
102102
execute(() -> scanRootField(field));
103103
}
104104
}
@@ -157,7 +157,9 @@ protected void scanField(AnalysisField field, JavaConstant receiver, ScanReason
157157
/* The value is not available yet. */
158158
return;
159159
}
160-
JavaConstant fieldValue = bb.getUniverse().getHeapScanner().readFieldValue(field, receiver);
160+
assert isUnwrapped(receiver);
161+
162+
JavaConstant fieldValue = readFieldValue(field, receiver);
161163
if (fieldValue == null) {
162164
StringBuilder backtrace = new StringBuilder();
163165
buildObjectBacktrace(bb, reason, backtrace);
@@ -179,20 +181,47 @@ protected void scanField(AnalysisField field, JavaConstant receiver, ScanReason
179181
* referenced elements are being scanned.
180182
*/
181183
scanConstant(fieldValue, reason);
184+
} else if (fieldValue.getJavaKind().isNumericInteger()) {
185+
scanningObserver.forPrimitiveFieldValue(receiver, field, fieldValue, reason);
182186
}
183187

184188
} catch (UnsupportedFeatureException ex) {
185189
unsupportedFeatureDuringFieldScan(bb, field, receiver, ex, reason);
186190
}
187191
}
188192

193+
protected JavaConstant readFieldValue(AnalysisField field, JavaConstant receiver) {
194+
return bb.getConstantReflectionProvider().readFieldValue(field, receiver);
195+
}
196+
197+
/**
198+
* Must unwrap the receiver if it is an ImageHeapConstant to scan the hosted value, if any, for
199+
* verification, otherwise the verification just compares shadow heap with shadow heap for
200+
* embedded roots, which is completely useless.
201+
*/
202+
private static JavaConstant maybeUnwrap(JavaConstant receiver) {
203+
if (receiver instanceof ImageHeapConstant heapConstant && heapConstant.getHostedObject() != null) {
204+
return heapConstant.getHostedObject();
205+
}
206+
return receiver;
207+
}
208+
209+
private static boolean isUnwrapped(JavaConstant receiver) {
210+
if (receiver instanceof ImageHeapConstant heapConstant) {
211+
// Non hosted backed ImageHeapConstant is considered unwrapped
212+
return heapConstant.getHostedObject() == null;
213+
}
214+
return true;
215+
}
216+
189217
/**
190218
* Scans constant arrays, one element at the time.
191219
*
192220
* @param array the array to be scanned
193221
*/
194222
protected final void scanArray(JavaConstant array, ScanReason prevReason) {
195223

224+
assert isUnwrapped(array);
196225
AnalysisType arrayType = bb.getMetaAccess().lookupJavaType(array);
197226
ScanReason reason = new ArrayScan(arrayType, array, prevReason);
198227

@@ -246,13 +275,14 @@ public void scanConstant(JavaConstant value, ScanReason reason) {
246275
bb.registerTypeAsInHeap(bb.getMetaAccess().lookupJavaType(value), reason);
247276
return;
248277
}
249-
Object valueObj = (value instanceof ImageHeapConstant) ? value : constantAsObject(bb, value);
278+
JavaConstant unwrappedValue = maybeUnwrap(value);
279+
Object valueObj = unwrappedValue instanceof ImageHeapConstant ? unwrappedValue : constantAsObject(bb, unwrappedValue);
250280
if (scannedObjects.putAndAcquire(valueObj) == null) {
251281
try {
252-
scanningObserver.forScannedConstant(value, reason);
282+
scanningObserver.forScannedConstant(unwrappedValue, reason);
253283
} finally {
254284
scannedObjects.release(valueObj);
255-
WorklistEntry worklistEntry = new WorklistEntry(value, reason);
285+
WorklistEntry worklistEntry = new WorklistEntry(unwrappedValue, reason);
256286
if (executor != null) {
257287
executor.execute(debug -> doScan(worklistEntry));
258288
} else {
@@ -339,12 +369,22 @@ public static String asString(BigBang bb, JavaConstant constant, boolean appendT
339369
return "null";
340370
}
341371
AnalysisType type = bb.getMetaAccess().lookupJavaType(constant);
342-
if (constant instanceof ImageHeapConstant) {
343-
// Checkstyle: allow Class.getSimpleName
344-
return constant.getClass().getSimpleName() + "<" + type.toJavaName() + ">";
345-
// Checkstyle: disallow Class.getSimpleName
372+
JavaConstant hosted = constant;
373+
if (constant instanceof ImageHeapConstant heapConstant) {
374+
JavaConstant hostedObject = heapConstant.getHostedObject();
375+
if (hostedObject == null) {
376+
// Checkstyle: allow Class.getSimpleName
377+
return constant.getClass().getSimpleName() + "<" + type.toJavaName() + ">";
378+
// Checkstyle: disallow Class.getSimpleName
379+
}
380+
hosted = hostedObject;
381+
}
382+
383+
if (hosted.getJavaKind().isPrimitive()) {
384+
return hosted.toValueString();
346385
}
347-
Object obj = constantAsObject(bb, constant);
386+
387+
Object obj = constantAsObject(bb, hosted);
348388
String str = type.toJavaName() + '@' + Integer.toHexString(System.identityHashCode(obj));
349389
if (appendToString) {
350390
try {
@@ -381,7 +421,7 @@ private void doScan(WorklistEntry entry) {
381421
/* Scan constant's instance fields. */
382422
for (ResolvedJavaField javaField : type.getInstanceFields(true)) {
383423
AnalysisField field = (AnalysisField) javaField;
384-
if (field.getJavaKind() == JavaKind.Object && field.isRead()) {
424+
if (field.isRead()) {
385425
assert !Modifier.isStatic(field.getModifiers());
386426
scanField(field, entry.constant, entry.reason);
387427
}
@@ -589,15 +629,21 @@ public String toString() {
589629

590630
public static class ArrayScan extends ScanReason {
591631
final AnalysisType arrayType;
632+
final int idx;
592633

593634
public ArrayScan(AnalysisType arrayType, JavaConstant array, ScanReason previous) {
635+
this(arrayType, array, previous, -1);
636+
}
637+
638+
public ArrayScan(AnalysisType arrayType, JavaConstant array, ScanReason previous, int idx) {
594639
super(previous, array);
595640
this.arrayType = arrayType;
641+
this.idx = idx;
596642
}
597643

598644
@Override
599645
public String toString(BigBang bb) {
600-
return "indexing into array " + asString(bb, constant);
646+
return "indexing into array " + asString(bb, constant) + (idx != -1 ? " at index " + idx : "");
601647
}
602648

603649
@Override

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/ObjectScanningObserver.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,13 @@ default boolean forRelocatedPointerFieldValue(JavaConstant receiver, AnalysisFie
5151
return false;
5252
}
5353

54+
/**
55+
* Hook for scanned value of primitive field.
56+
*/
57+
default boolean forPrimitiveFieldValue(JavaConstant receiver, AnalysisField field, JavaConstant fieldValue, ScanReason reason) {
58+
return false;
59+
}
60+
5461
/**
5562
* Hook for scanned null field value.
5663
*/

0 commit comments

Comments
 (0)