@@ -77,6 +77,7 @@ public boolean requireAnalysisIteration(CompletionExecutor executor) throws Inte
7777 info ("Verifying the heap snapshot..." );
7878 analysisModified = false ;
7979 heapPatched = false ;
80+ int reachableTypesBefore = bb .getUniverse ().getReachableTypes ();
8081 iterations ++;
8182 scannedObjects .reset ();
8283 ObjectScanner objectScanner = new ObjectScanner (bb , executor , scannedObjects , new ScanningObserver ());
@@ -85,32 +86,29 @@ public boolean requireAnalysisIteration(CompletionExecutor executor) throws Inte
8586 objectScanner .scanBootImageHeapRoots ();
8687 executor .complete ();
8788 executor .shutdown ();
89+ int verificationReachableTypes = bb .getUniverse ().getReachableTypes () - reachableTypesBefore ;
8890 if (heapPatched ) {
8991 info ("Heap verification patched the heap snapshot." );
9092 } else {
9193 info ("Heap verification didn't find any heap snapshot modifications." );
9294 }
95+ if (verificationReachableTypes > 0 ) {
96+ info ("Heap verification made " + verificationReachableTypes + " new types reachable." );
97+ } else {
98+ info ("Heap verification didn't make any new types reachable." );
99+ }
93100 if (analysisModified ) {
94101 info ("Heap verification modified the analysis state. Executing an additional analysis iteration." );
95102 } else {
96103 info ("Heap verification didn't modify the analysis state. Heap state stabilized after " + iterations + " iterations." );
97104 info ("Exiting analysis." );
98105 }
99- return analysisModified ;
106+ return analysisModified || verificationReachableTypes > 0 ;
100107 }
101108
102109 protected void scanTypes (@ SuppressWarnings ("unused" ) ObjectScanner objectScanner ) {
103110 }
104111
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-
114112 public void cleanupAfterAnalysis () {
115113 scannedObjects = null ;
116114 }
@@ -224,80 +222,62 @@ public void forScannedConstant(JavaConstant value, ScanReason reason) {
224222 Object object = constantAsObject (bb , value );
225223 Class <?> objectClass = object .getClass ();
226224 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- */
225+ /* Ensure that java.lang.Class constants are scanned. */
234226 AnalysisType type = bb .getMetaAccess ().lookupJavaType ((Class <?>) object );
235- if (!initializationInfoComputed (type )) {
236- onNoInitInfoForClassConstant (type , reason );
237- } else {
238- ensureTypeScanned (value , type , reason );
239- }
227+ ensureTypeScanned (value , type , reason );
240228 } else {
241229 /*
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.
230+ * Ensure that the Class of any other constants are also scanned. An object replacer
231+ * can introduce new types which otherwise could be missed by the verifier. For
232+ * example com.oracle.svm.hosted.annotation.AnnotationObjectReplacer creates
233+ * annotation proxy types on the fly for constant annotation objects.
247234 */
248235 AnalysisType type = bb .getMetaAccess ().lookupJavaType (objectClass );
249- if (!initializationInfoComputed (type )) {
250- onNoInitInfoForObjectType (value , type , reason );
251- } else {
252- ensureTypeScanned (bb .getConstantReflectionProvider ().asJavaClass (type ), type , reason );
253- }
236+ ensureTypeScanned (value , bb .getConstantReflectionProvider ().asJavaClass (type ), type , reason );
254237 }
255238 }
256239
257- private void ensureTypeScanned (JavaConstant value , AnalysisType type , ScanReason reason ) {
240+ private void ensureTypeScanned (JavaConstant typeConstant , AnalysisType type , ScanReason reason ) {
241+ ensureTypeScanned (null , typeConstant , type , reason );
242+ }
243+
244+ private void ensureTypeScanned (JavaConstant object , JavaConstant typeConstant , AnalysisType type , ScanReason reason ) {
258245 AnalysisError .guarantee (type .isReachable (), "The heap snapshot verifier discovered a type not marked as reachable " + type .toJavaName ());
259- AnalysisFuture <ImageHeapObject > task = imageHeap .getTask (value );
246+ AnalysisFuture <ImageHeapObject > task = imageHeap .getTask (typeConstant );
260247 /* Make sure the DynamicHub value is scanned. */
261248 if (task == null ) {
262- onNoTaskForClassConstant (value , reason );
263- scanner .toImageHeapObject (value , reason , null );
249+ onNoTaskForClassConstant (type , reason );
250+ scanner .toImageHeapObject (typeConstant , reason , null );
264251 heapPatched = true ;
265252 } else {
266253 if (task .isDone ()) {
267254 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 );
255+ if (!Objects .equals (snapshot , typeConstant )) {
256+ throw error (reason , "Value mismatch for class constant snapshot: %s %n new value: %s %n" , snapshot , typeConstant );
270257 }
271258 } 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 );
259+ onTaskForClassConstantNotDone ( object , type , reason );
260+ task . ensureDone ( );
274261 }
275262 }
276263 }
277264 }
278265
279- protected boolean initializationInfoComputed (@ SuppressWarnings ("unused" ) AnalysisType type ) {
280- return true ;
281- }
282-
283- private void onNoInitInfoForClassConstant (AnalysisType type , ScanReason reason ) {
266+ private void onNoTaskForClassConstant (AnalysisType type , ScanReason reason ) {
284267 analysisModified = true ;
285268 if (printAll ()) {
286- warning (reason , "No initialization info computed for class constant %s %n" , type .toJavaName ());
269+ warning (reason , "No snapshot task found for class constant %s %n" , type .toJavaName ());
287270 }
288271 }
289272
290- private void onNoInitInfoForObjectType (JavaConstant object , AnalysisType type , ScanReason reason ) {
273+ private void onTaskForClassConstantNotDone (JavaConstant object , AnalysisType type , ScanReason reason ) {
291274 analysisModified = true ;
292275 if (printAll ()) {
293- warning (reason , "No initialization info computed for class %s of object %s %n" , type .toJavaName (), object );
294- }
295- }
296-
297- private void onNoTaskForClassConstant (JavaConstant value , ScanReason reason ) {
298- analysisModified = true ;
299- if (printAll ()) {
300- warning (reason , "No snapshot task found for class constant %s %n" , value );
276+ if (object != null ) {
277+ warning (reason , "Snapshot not yet computed for class %s of object %s %n" , type .toJavaName (), object );
278+ } else {
279+ warning (reason , "Snapshot not yet computed for class constant %n new value: %s %n" , type .toJavaName ());
280+ }
301281 }
302282 }
303283
0 commit comments