3737import org .graalvm .word .WordBase ;
3838
3939import com .oracle .graal .pointsto .constraints .UnsupportedFeatureException ;
40+ import com .oracle .graal .pointsto .heap .HeapSnapshotVerifier ;
4041import com .oracle .graal .pointsto .heap .ImageHeapArray ;
4142import com .oracle .graal .pointsto .heap .ImageHeapConstant ;
43+ import com .oracle .graal .pointsto .heap .ImageHeapScanner ;
4244import com .oracle .graal .pointsto .meta .AnalysisField ;
4345import com .oracle .graal .pointsto .meta .AnalysisMethod ;
4446import com .oracle .graal .pointsto .meta .AnalysisType ;
47+ import com .oracle .graal .pointsto .reports .ReportUtils ;
4548import com .oracle .graal .pointsto .util .AnalysisError ;
4649import com .oracle .graal .pointsto .util .CompletionExecutor ;
4750
4851import jdk .vm .ci .code .BytecodePosition ;
4952import jdk .vm .ci .meta .JavaConstant ;
5053import jdk .vm .ci .meta .JavaKind ;
54+ import jdk .vm .ci .meta .ResolvedJavaMethod ;
5155
5256/**
5357 * Provides functionality for scanning constant objects.
@@ -267,7 +271,7 @@ public final void scanConstant(JavaConstant value, ScanReason reason) {
267271 * message if the constant is reachable from multiple places.
268272 */
269273 public static void unsupportedFeatureDuringConstantScan (BigBang bb , JavaConstant constant , UnsupportedFeatureException e , ScanReason reason ) {
270- unsupportedFeature (bb , String .valueOf (constant . hashCode ( )), e .getMessage (), reason );
274+ unsupportedFeature (bb , String .valueOf (receiverHashCode ( constant )), e .getMessage (), reason );
271275 }
272276
273277 /**
@@ -276,7 +280,27 @@ public static void unsupportedFeatureDuringConstantScan(BigBang bb, JavaConstant
276280 * heap scanning and the heap verification would scan a field that contains an illegal value.
277281 */
278282 public static void unsupportedFeatureDuringFieldScan (BigBang bb , AnalysisField field , JavaConstant receiver , UnsupportedFeatureException e , ScanReason reason ) {
279- unsupportedFeature (bb , (receiver != null ? receiver .hashCode () + "_" : "" ) + field .format ("%H.%n" ), e .getMessage (), reason );
283+ unsupportedFeature (bb , (receiver != null ? receiverHashCode (receiver ) + "_" : "" ) + field .format ("%H.%n" ), e .getMessage (), reason );
284+ }
285+
286+ public static void unsupportedFeatureDuringFieldFolding (BigBang bb , AnalysisField field , JavaConstant receiver , UnsupportedFeatureException e , AnalysisMethod parsedMethod , int bci ) {
287+ ScanReason reason = new FieldConstantFold (field , parsedMethod , bci , receiver , new MethodParsing (parsedMethod ));
288+ unsupportedFeature (bb , (receiver != null ? receiverHashCode (receiver ) + "_" : "" ) + field .format ("%H.%n" ), e .getMessage (), reason );
289+ }
290+
291+ /**
292+ * The {@link ImageHeapScanner} may find issue when scanning the {@link ImageHeapConstant}
293+ * whereas the {@link HeapSnapshotVerifier} may find issues when scanning the original hosted
294+ * objects. Use a consistent hash code as a key to map them to the same error message.
295+ */
296+ private static int receiverHashCode (JavaConstant receiver ) {
297+ if (receiver instanceof ImageHeapConstant ) {
298+ JavaConstant hostedObject = ((ImageHeapConstant ) receiver ).getHostedObject ();
299+ if (hostedObject != null ) {
300+ return hostedObject .hashCode ();
301+ }
302+ }
303+ return receiver .hashCode ();
280304 }
281305
282306 public static void unsupportedFeature (BigBang bb , String key , String message , ScanReason reason ) {
@@ -311,13 +335,28 @@ public static AnalysisMethod buildObjectBacktrace(BigBang bb, ScanReason reason,
311335 }
312336
313337 static String asString (BigBang bb , ScanReason reason ) {
314- if (reason instanceof FieldScan ) {
338+ if (reason instanceof MethodParsing ) {
339+ MethodParsing mp = (MethodParsing ) reason ;
340+ String str = String .format ("parsing method %s reachable via the parsing context" , mp .getMethod ().asStackTraceElement (0 ));
341+ str += ReportUtils .parsingContext (mp .getMethod (), indent + indent );
342+ return str ;
343+ } else if (reason instanceof FieldConstantFold ) {
344+ FieldConstantFold fieldFold = (FieldConstantFold ) reason ;
345+ StackTraceElement location = fieldFold .parsedMethod .asStackTraceElement (fieldFold .bci );
346+ if (fieldFold .field .isStatic ()) {
347+ return "trying to constant fold static field " + reason + "\n at " + location ;
348+ } else {
349+ /* Instance field scans must have a receiver, hence the 'of'. */
350+ return "trying to constant fold field " + reason + " of constant \n " + asString (bb , reason .constant ) + "\n at " + location ;
351+ }
352+ } else if (reason instanceof FieldScan ) {
315353 FieldScan fieldScan = (FieldScan ) reason ;
316354 if (fieldScan .field .isStatic ()) {
317- return "reading static field " + reason ;
355+ return "reading static field " + reason + " \n at " + fieldScan . location () ;
318356 } else {
319357 /* Instance field scans must have a receiver, hence the 'of'. */
320358 return "reading field " + reason + " of constant \n " + asString (bb , reason .constant );
359+ // + "\n at " + location;
321360 }
322361 } else if (reason instanceof EmbeddedRootScan ) {
323362 return "scanning root " + asString (bb , reason .constant ) + " embedded in \n " + reason ;
@@ -472,25 +511,93 @@ public String toString() {
472511 public static class FieldScan extends ScanReason {
473512 final AnalysisField field ;
474513
514+ private static ScanReason previous (AnalysisField field ) {
515+ assert field .isStatic () && field .isRead ();
516+ Object readBy = field .getReadBy ();
517+ if (readBy instanceof BytecodePosition ) {
518+ ResolvedJavaMethod readingMethod = ((BytecodePosition ) readBy ).getMethod ();
519+ return new MethodParsing ((AnalysisMethod ) readingMethod );
520+ } else if (readBy instanceof AnalysisMethod ) {
521+ return new MethodParsing ((AnalysisMethod ) readBy );
522+ } else {
523+ return new OtherReason ("registered as read because: " + readBy );
524+ }
525+ }
526+
475527 public FieldScan (AnalysisField field ) {
476- this (field , null , null );
528+ this (field , null , previous ( field ) );
477529 }
478530
479531 public FieldScan (AnalysisField field , JavaConstant receiver , ScanReason previous ) {
480532 super (previous , receiver );
481533 this .field = field ;
534+ assert field .isRead ();
482535 }
483536
484537 public AnalysisField getField () {
485538 return field ;
486539 }
487540
541+ public String location () {
542+ Object readBy = field .getReadBy ();
543+ if (readBy instanceof BytecodePosition ) {
544+ BytecodePosition position = (BytecodePosition ) readBy ;
545+ return position .getMethod ().asStackTraceElement (position .getBCI ()).toString ();
546+ } else if (readBy instanceof AnalysisMethod ) {
547+ return ((AnalysisMethod ) readBy ).asStackTraceElement (0 ).toString ();
548+ } else {
549+ return "<unknown-location>" ;
550+ }
551+ }
552+
553+ @ Override
554+ public String toString () {
555+ return field .format ("%H.%n" );
556+ }
557+ }
558+
559+ public static class FieldConstantFold extends ScanReason {
560+ final AnalysisField field ;
561+ private final AnalysisMethod parsedMethod ;
562+ private final int bci ;
563+
564+ public FieldConstantFold (AnalysisField field , AnalysisMethod parsedMethod , int bci , JavaConstant receiver , ScanReason previous ) {
565+ super (previous , receiver );
566+ this .field = field ;
567+ this .parsedMethod = parsedMethod ;
568+ this .bci = bci ;
569+ }
570+
488571 @ Override
489572 public String toString () {
490573 return field .format ("%H.%n" );
491574 }
492575 }
493576
577+ public static class MethodParsing extends ScanReason {
578+ final AnalysisMethod method ;
579+
580+ public MethodParsing (AnalysisMethod method ) {
581+ this (method , null );
582+ }
583+
584+ public MethodParsing (AnalysisMethod method , ScanReason previous ) {
585+ super (previous , null );
586+ this .method = method ;
587+ }
588+
589+ public AnalysisMethod getMethod () {
590+ return method ;
591+ }
592+
593+ @ Override
594+ public String toString () {
595+ String str = String .format ("Parsing method %s %n" , method .asStackTraceElement (0 ));
596+ str += "Parsing context:" + ReportUtils .parsingContext (method );
597+ return str ;
598+ }
599+ }
600+
494601 public static class ArrayScan extends ScanReason {
495602 final AnalysisType arrayType ;
496603
@@ -509,7 +616,7 @@ public static class EmbeddedRootScan extends ScanReason {
509616 final BytecodePosition position ;
510617
511618 public EmbeddedRootScan (BytecodePosition nodeSourcePosition , JavaConstant root ) {
512- this (nodeSourcePosition , root , null );
619+ this (nodeSourcePosition , root , new MethodParsing (( AnalysisMethod ) nodeSourcePosition . getMethod ()) );
513620 }
514621
515622 public EmbeddedRootScan (BytecodePosition nodeSourcePosition , JavaConstant root , ScanReason previous ) {
0 commit comments