@@ -63,6 +63,7 @@ static class Options {
63
63
private boolean analysisModified ;
64
64
65
65
private final int verbosity ;
66
+ private int iterations ;
66
67
67
68
public HeapSnapshotVerifier (BigBang bb , ImageHeap imageHeap , ImageHeapScanner scanner ) {
68
69
this .bb = bb ;
@@ -76,6 +77,7 @@ public boolean requireAnalysisIteration(CompletionExecutor executor) throws Inte
76
77
info ("Verifying the heap snapshot..." );
77
78
analysisModified = false ;
78
79
heapPatched = false ;
80
+ iterations ++;
79
81
scannedObjects .reset ();
80
82
ObjectScanner objectScanner = new ObjectScanner (bb , executor , scannedObjects , new ScanningObserver ());
81
83
executor .start ();
@@ -91,14 +93,24 @@ public boolean requireAnalysisIteration(CompletionExecutor executor) throws Inte
91
93
if (analysisModified ) {
92
94
info ("Heap verification modified the analysis state. Executing an additional analysis iteration." );
93
95
} else {
94
- info ("Heap verification didn't modify the analysis state. Exiting analysis." );
96
+ info ("Heap verification didn't modify the analysis state. Heap state stabilized after " + iterations + " iterations." );
97
+ info ("Exiting analysis." );
95
98
}
96
99
return analysisModified ;
97
100
}
98
101
99
102
protected void scanTypes (@ SuppressWarnings ("unused" ) ObjectScanner objectScanner ) {
100
103
}
101
104
105
+ public boolean checkTypes () {
106
+ for (AnalysisType t : bb .getUniverse ().getTypes ()) {
107
+ if (t .isReachable () && !initializationInfoComputed (t )) {
108
+ throw AnalysisError .shouldNotReachHere ("Type is not initialized " + t .getName ());
109
+ }
110
+ }
111
+ return true ;
112
+ }
113
+
102
114
public void cleanupAfterAnalysis () {
103
115
scannedObjects = null ;
104
116
}
@@ -209,34 +221,56 @@ public void forEmbeddedRoot(JavaConstant root, ScanReason reason) {
209
221
210
222
@ Override
211
223
public void forScannedConstant (JavaConstant value , ScanReason reason ) {
212
- AnalysisFuture <ImageHeapObject > task = imageHeap .getTask (value );
213
224
Object object = constantAsObject (bb , value );
214
- if (object .getClass ().equals (Class .class )) {
225
+ Class <?> objectClass = object .getClass ();
226
+ if (objectClass .equals (Class .class )) {
227
+ /*
228
+ * Ensure that java.lang.Class constants are fully initialized and scanned. If a
229
+ * type is marked as reachable during the verification then it's class
230
+ * initialization info will be missing since
231
+ * ClassInitializationFeature.buildClassInitializationInfo() hasn't processed it
232
+ * yet.
233
+ */
215
234
AnalysisType type = bb .getMetaAccess ().lookupJavaType ((Class <?>) object );
216
- if (type .isReachable () && !initializationInfoComputed (type )) {
217
- /*
218
- * This means that the type has been marked as reachable during the verification
219
- * and ClassInitializationFeature.buildClassInitializationInfo() hasn't
220
- * processed it yet. Allow ClassInitializationFeature to build the
221
- * DynamicHub.classInitializationInfo.
222
- */
223
- onNoInitInfoForHub (value , reason );
235
+ if (!initializationInfoComputed (type )) {
236
+ onNoInitInfoForClassConstant (type , reason );
237
+ } else {
238
+ ensureTypeScanned (value , type , reason );
224
239
}
225
- /* Make sure the DynamicHub value is scanned. */
226
- if (task == null ) {
227
- onNoTaskForHub (value , reason );
228
- scanner .toImageHeapObject (value , reason , null );
229
- heapPatched = true ;
240
+ } else {
241
+ /*
242
+ * Ensure that the Class of any other constants are also fully initialized and
243
+ * scanned. An object replacer can introduce new types which otherwise could be
244
+ * missed by the verifier. For example
245
+ * com.oracle.svm.hosted.annotation.AnnotationObjectReplacer creates annotation
246
+ * proxy types on the fly for constant annotation objects.
247
+ */
248
+ AnalysisType type = bb .getMetaAccess ().lookupJavaType (objectClass );
249
+ if (!initializationInfoComputed (type )) {
250
+ onNoInitInfoForObjectType (value , type , reason );
230
251
} else {
231
- if (task .isDone ()) {
232
- JavaConstant snapshot = task .guardedGet ().getObject ();
233
- if (!Objects .equals (snapshot , value )) {
234
- throw error (reason , "Value mismatch for hub snapshot: %s %n new value: %s %n" , snapshot , value );
235
- }
236
- } else {
237
- /* If there is a task for the hub it should have been triggered. */
238
- throw error (reason , "Snapshot not yet computed for hub %n new value: %s %n" , value );
252
+ ensureTypeScanned (bb .getConstantReflectionProvider ().asJavaClass (type ), type , reason );
253
+ }
254
+ }
255
+ }
256
+
257
+ private void ensureTypeScanned (JavaConstant value , AnalysisType type , ScanReason reason ) {
258
+ AnalysisError .guarantee (type .isReachable (), "The heap snapshot verifier discovered a type not marked as reachable " + type .toJavaName ());
259
+ AnalysisFuture <ImageHeapObject > task = imageHeap .getTask (value );
260
+ /* Make sure the DynamicHub value is scanned. */
261
+ if (task == null ) {
262
+ onNoTaskForClassConstant (value , reason );
263
+ scanner .toImageHeapObject (value , reason , null );
264
+ heapPatched = true ;
265
+ } else {
266
+ if (task .isDone ()) {
267
+ JavaConstant snapshot = task .guardedGet ().getObject ();
268
+ if (!Objects .equals (snapshot , value )) {
269
+ throw error (reason , "Value mismatch for class constant snapshot: %s %n new value: %s %n" , snapshot , value );
239
270
}
271
+ } else {
272
+ /* If there is a task for the hub it should have been triggered. */
273
+ throw error (reason , "Snapshot not yet computed for class constant %n new value: %s %n" , value );
240
274
}
241
275
}
242
276
}
@@ -246,17 +280,24 @@ protected boolean initializationInfoComputed(@SuppressWarnings("unused") Analysi
246
280
return true ;
247
281
}
248
282
249
- private void onNoInitInfoForHub (JavaConstant value , ScanReason reason ) {
283
+ private void onNoInitInfoForClassConstant (AnalysisType type , ScanReason reason ) {
284
+ analysisModified = true ;
285
+ if (printAll ()) {
286
+ warning (reason , "No initialization info computed for class constant %s %n" , type .toJavaName ());
287
+ }
288
+ }
289
+
290
+ private void onNoInitInfoForObjectType (JavaConstant object , AnalysisType type , ScanReason reason ) {
250
291
analysisModified = true ;
251
292
if (printAll ()) {
252
- warning (reason , "No initialization info computed for hub %s % n" , value );
293
+ warning (reason , "No initialization info computed for class %s of object %s % n" , type . toJavaName (), object );
253
294
}
254
295
}
255
296
256
- private void onNoTaskForHub (JavaConstant value , ScanReason reason ) {
297
+ private void onNoTaskForClassConstant (JavaConstant value , ScanReason reason ) {
257
298
analysisModified = true ;
258
299
if (printAll ()) {
259
- warning (reason , "No snapshot task found for hub %s %n" , value );
300
+ warning (reason , "No snapshot task found for class constant %s %n" , value );
260
301
}
261
302
}
262
303
0 commit comments