2 Time-stamp: <Sun Mar 18 2001 19:32:56 Stardate: [-30]6349.07 hwloidl>
4 Various debugging routines for GranSim and GUM
7 #if defined(DEBUG) && (defined(GRAN) || defined(PAR)) /* whole file */
9 //@node Debugging routines for GranSim and GUM, , ,
10 //@section Debugging routines for GranSim and GUM
14 //* Constants and Variables::
21 //* Printing info type::
22 //* Printing Pack:et Contents::
27 //@node Includes, Prototypes, Debugging routines for GranSim and GUM, Debugging routines for GranSim and GUM
28 //@subsection Includes
32 #include "GranSimRts.h"
33 #include "ParallelRts.h"
34 #include "StgMiscClosures.h"
39 # include "ParallelDebug.h"
42 //@node Prototypes, Constants and Variables, Includes, Debugging routines for GranSim and GUM
43 //@subsection Prototypes
45 rtsBool isOffset(globalAddr *ga);
46 rtsBool isFixed(globalAddr *ga);
48 //@node Constants and Variables, Closures, Prototypes, Debugging routines for GranSim and GUM
49 //@subsection Constants and Variables
51 static HashTable *tmpClosureTable; // used in GraphFingerPrint and PrintGraph
54 static char finger_print_char[] = {
55 '/', /* INVALID_OBJECT 0 */
57 'C', /* CONSTR_1_0 2 */
58 'C', /* CONSTR_0_1 3 */
59 'C', /* CONSTR_2_0 4 */
60 'C', /* CONSTR_1_1 5 */
61 'C', /* CONSTR_0_2 6 */
62 'I', /* CONSTR_INTLIKE 7 */
63 'I', /* CONSTR_CHARLIKE 8 */
64 'S', /* CONSTR_STATIC 9 */
65 'S', /* CONSTR_NOCAF_STATIC 10 */
72 'S', /* FUN_STATIC 17 */
74 'T', /* THUNK_1_0 19 */
75 'T', /* THUNK_0_1 20 */
76 'T', /* THUNK_2_0 21 */
77 'T', /* THUNK_1_1 22 */
78 'T', /* THUNK_0_2 23 */
79 'S', /* THUNK_STATIC 24 */
80 'E', /* THUNK_SELECTOR 25 */
85 '_', /* IND_OLDGEN 30 */
86 '_', /* IND_PERM 31 */
87 '_', /* IND_OLDGEN_PERM 32 */
88 '_', /* IND_STATIC 33 */
89 '?', /* ***unused*** 34 */
90 '?', /* ***unused*** 35 */
92 '^', /* RET_SMALL 37 */
93 '^', /* RET_VEC_SMALL 38 */
95 '^', /* RET_VEC_BIG 40 */
97 '~', /* UPDATE_FRAME 42 */
98 '~', /* CATCH_FRAME 43 */
99 '~', /* STOP_FRAME 44 */
100 '~', /* SEQ_FRAME 45 */
101 'o', /* CAF_BLACKHOLE 46 */
102 'o', /* BLACKHOLE 47 */
103 'o', /* BLACKHOLE_BQ 48 */
104 'o', /* SE_BLACKHOLE 49 */
105 'o', /* SE_CAF_BLACKHOLE 50 */
107 'a', /* ARR_WORDS 52 */
108 'a', /* MUT_ARR_PTRS 53 */
109 'a', /* MUT_ARR_PTRS_FROZEN 54 */
110 'q', /* MUT_VAR 55 */
112 'f', /* FOREIGN 57 */
113 's', /* STABLE_NAME 58 */
115 '#', /* BLOCKED_FETCH 60 */
116 '>', /* FETCH_ME 61 */
117 '>', /* FETCH_ME_BQ 62 */
119 'v', /* EVACUATED 64 */
120 '>' /* REMOTE_REF 65 */
121 /* ASSERT(there are N_CLOSURE_TYPES (==66) in this arrary) */
125 #if defined(GRAN) && defined(GRAN_CHECK)
126 //@node Closures, Threads, Constants and Variables, Debugging routines for GranSim and GUM
127 //@subsection Closures
133 StgInfoTable *info_ptr;
135 nat size = 0, ptrs = 0, nonptrs = 0, i, vhs = 0;
136 char info_hdr_ty[80], info_ty[80];
139 fprintf(stderr,"NULL\n");
141 } else if (node==END_TSO_QUEUE) {
142 fprintf(stderr,"END_TSO_QUEUE\n");
145 /* size_and_ptrs(node,&size,&ptrs); */
146 info_ptr = get_closure_info(node, &size, &ptrs, &nonptrs, &vhs, info_hdr_ty);
148 /* vhs = var_hdr_size(node); */
149 display_info_type(info_ptr,info_ty);
151 fprintf(stderr,"Node: 0x%lx", node);
154 fprintf(stderr," [GA: 0x%lx]",GA(node));
157 #if defined(USE_COST_CENTRES)
158 fprintf(stderr," [CC: 0x%lx]",CC_HDR(node));
162 fprintf(stderr," [Bitmask: 0%lo]",PROCS(node));
165 if (info_ptr->type==TSO)
166 fprintf(stderr," TSO: 0x%lx (%x) IP: 0x%lx (%s), type %s \n ",
167 (StgTSO*)node, ((StgTSO*)node)->id, info_ptr, info_hdr_ty, info_ty);
169 fprintf(stderr," IP: 0x%lx (%s), type %s \n VHS: %d, size: %ld, ptrs:%ld, nonptrs: %ld\n ",
170 info_ptr,info_hdr_ty,info_ty,vhs,size,ptrs,nonptrs);
172 /* For now, we ignore the variable header */
174 fprintf(stderr," Ptrs: ");
175 for(i=0; i < ptrs; ++i)
178 fprintf(stderr,"\n ");
179 fprintf(stderr," 0x%lx[P]",node->payload[i]);
182 fprintf(stderr," Data: ");
183 for(i=0; i < nonptrs; ++i)
186 fprintf(stderr,"\n ");
187 fprintf(stderr," %lu[D]",node->payload[ptrs+i]);
189 fprintf(stderr, "\n");
192 switch (info_ptr->type)
195 fprintf(stderr,"\n TSO_LINK: %#lx",
196 ((StgTSO*)node)->link);
201 bqe = ((StgBlockingQueue*)node)->blocking_queue;
202 fprintf(stderr," BQ of %#lx: ", node);
207 printf("Panic: found FETCH_ME or FETCH_ME_BQ Infotable in GrAnSim system.\n");
215 G_PPN(node) /* Extracted from PrintPacket in Pack.lc */
219 nat size = 0, ptrs = 0, nonptrs = 0, i, vhs = 0, locn = 0;
222 /* size_and_ptrs(node,&size,&ptrs); */
223 info = get_closure_info(node, &size, &ptrs, &nonptrs, &vhs, info_type);
225 if (info->type == FETCH_ME || info->type == FETCH_ME_BQ ||
226 info->type == BLACKHOLE || info->type == RBH )
227 size = ptrs = nonptrs = vhs = 0;
229 if (closure_THUNK(node)) {
230 if (!closure_UNPOINTED(node))
231 fputs("SHARED ", stderr);
233 fputs("UNSHARED ", stderr);
235 if (info->type==BLACKHOLE) {
236 fputs("BLACK HOLE\n", stderr);
239 fprintf(stderr, "(%s) FH [%#lx", info_type, node[locn++]);
240 for (i = 1; i < _HS; i++)
241 fprintf(stderr, " %#lx", node[locn++]);
243 /* Variable header */
245 fprintf(stderr, "] VH [%#lx", node->payload[0]);
247 for (i = 1; i < vhs; i++)
248 fprintf(stderr, " %#lx", node->payload[i]);
251 fprintf(stderr, "] PTRS %u", ptrs);
255 fprintf(stderr, " NPTRS [%#lx", node->payload[ptrs]);
257 for (i = 1; i < nonptrs; i++)
258 fprintf(stderr, " %#lx", node->payload[ptrs+i]);
268 // ToDo: fix this!! -- HWL
273 StgInfoTable *info_ptr;
274 nat size = 0, ptrs = 0, nonptrs = 0, vhs = 0;
275 char info_type[80], hdr_type[80];
277 info_hdr_type(info_ptr, hdr_type);
280 info_ptr = get_closure_info(node, &size, &ptrs, &nonptrs, &vhs, info_type);
281 fprintf(stderr,"%s Info Ptr @0x%lx; Entry: 0x%lx; Size: %lu; Ptrs: %lu\n\n",
282 info_type,info_ptr,(W_) ENTRY_CODE(info_ptr),
284 // INFO_SIZE(info_ptr),INFO_NoPTRS(info_ptr));
286 if (closure_THUNK(node) && !closure_UNPOINTED(node) ) {
287 fprintf(stderr," RBH InfoPtr: %#lx\n",
288 RBH_INFOPTR(info_ptr));
292 fprintf(stderr,"Enter Flush Entry: 0x%lx;\tExit Flush Entry: 0x%lx\n",INFO_FLUSHENT(info_ptr),INFO_FLUSH(info_ptr));
295 #if defined(USE_COST_CENTRES)
296 fprintf(stderr,"Cost Centre (?): 0x%lx\n",INFO_CAT(info_ptr));
299 #if defined(_INFO_COPYING)
300 fprintf(stderr,"Evacuate Entry: 0x%lx;\tScavenge Entry: 0x%lx\n",
301 INFO_EVAC_2S(info_ptr),INFO_SCAV_2S(info_ptr));
304 #if defined(_INFO_COMPACTING)
305 fprintf(stderr,"Scan Link: 0x%lx;\tScan Move: 0x%lx\n",
306 (W_) INFO_SCAN_LINK_1S(info_ptr), (W_) INFO_SCAN_MOVE_1S(info_ptr));
307 fprintf(stderr,"Mark: 0x%lx;\tMarked: 0x%lx;\t",
308 (W_) INFO_MARK_1S(info_ptr), (W_) INFO_MARKED_1S(info_ptr));
309 #if 0 /* avoid INFO_TYPE */
310 if(BASE_INFO_TYPE(info_ptr)==INFO_SPEC_TYPE)
311 fprintf(stderr,"plus specialised code\n");
313 fprintf(stderr,"Marking: 0x%lx\n",(W_) INFO_MARKING_1S(info_ptr));
315 #endif /* _INFO_COMPACTING */
326 char str[80], str0[80];
328 fprintf(stderr,"\n[PE %d] @ %lu BQ: ",
329 CurrentProc,CurrentTime[CurrentProc]);
330 if ( node == (StgClosure*)NULL ) {
331 fprintf(stderr," NULL.\n");
334 if ( node == END_TSO_QUEUE ) {
335 fprintf(stderr," _|_\n");
338 tso = ((StgBlockingQueue*)node)->blocking_queue;
339 while (node != END_TSO_QUEUE) {
342 /* Find where the tso lives */
343 proc = where_is(node);
344 info = get_itbl(node);
346 switch (info->type) {
351 strcpy(str0,"BLOCKED_FETCH");
358 if(proc == CurrentProc)
359 fprintf(stderr," %#lx (%x) L %s,",
360 node, ((StgBlockingQueue*)node)->blocking_queue, str0);
362 fprintf(stderr," %#lx (%x) G (PE %d) %s,",
363 node, ((StgBlockingQueue*)node)->blocking_queue, proc, str0);
368 if ( tso == END_TSO_QUEUE )
369 fprintf(stderr," _|_\n");
372 //@node Threads, Events, Closures, Debugging routines for GranSim and GUM
373 //@subsection Threads
376 G_CURR_THREADQ(verbose)
379 fprintf(stderr,"Thread Queue on proc %d: ", CurrentProc);
380 G_THREADQ(run_queue_hd, verbose);
384 G_THREADQ(closure, verbose)
390 fprintf(stderr,"Thread Queue: ");
391 for (x=closure; x!=END_TSO_QUEUE; x=x->link)
395 fprintf(stderr," %#lx",x);
397 if (closure==END_TSO_QUEUE)
398 fprintf(stderr,"NIL\n");
400 fprintf(stderr,"\n");
404 G_TSO(closure,verbose)
409 if (closure==END_TSO_QUEUE) {
410 fprintf(stderr,"TSO at %#lx is END_TSO_QUEUE!\n");
414 if ( verbose & 0x08 ) { /* short info */
415 fprintf(stderr,"[TSO @ %#lx, PE %d]: Id: %#lx, Link: %#lx\n",
416 closure,where_is(closure),
417 closure->id,closure->link);
421 fprintf(stderr,"TSO at %#lx has the following contents:\n",
424 fprintf(stderr,"> Id: \t%#lx",closure->id);
425 // fprintf(stderr,"\tstate: \t%#lx",closure->state);
426 fprintf(stderr,"\twhat_next: \t%#lx",closure->what_next);
427 fprintf(stderr,"\tlink: \t%#lx\n",closure->link);
428 fprintf(stderr,"\twhy_blocked: \t%d", closure->why_blocked);
429 fprintf(stderr,"\tblock_info: \t%p\n", closure->block_info);
430 // fprintf(stderr,"\tType: \t%s\n",type_name[TSO_TYPE(closure)]);
431 fprintf(stderr,">PRI: \t%#lx", closure->gran.pri);
432 fprintf(stderr,"\tMAGIC: \t%#lx %s\n", closure->gran.magic,
433 (closure->gran.magic==TSO_MAGIC ? "it IS a TSO" : "THIS IS NO TSO!!"));
434 if ( verbose & 0x04 ) {
435 fprintf(stderr, "Stack: stack @ %#lx (stack_size: %u; max_stack_size: %u)\n",
436 closure->stack, closure->stack_size, closure->max_stack_size);
437 fprintf(stderr, " sp: %#lx, su: %#lx, splim: %#lx\n",
438 closure->sp, closure->su, closure->splim);
440 // fprintf(stderr,"\n");
441 if (verbose & 0x01) {
442 // fprintf(stderr,"} LOCKED: \t%#lx",closure->locked);
443 fprintf(stderr,"} SPARKNAME: \t%#lx\n", closure->gran.sparkname);
444 fprintf(stderr,"} STARTEDAT: \t%#lx", closure->gran.startedat);
445 fprintf(stderr,"\tEXPORTED: \t%#lx\n", closure->gran.exported);
446 fprintf(stderr,"} BASICBLOCKS: \t%#lx", closure->gran.basicblocks);
447 fprintf(stderr,"\tALLOCS: \t%#lx\n", closure->gran.allocs);
448 fprintf(stderr,"} EXECTIME: \t%#lx", closure->gran.exectime);
449 fprintf(stderr,"\tFETCHTIME: \t%#lx\n", closure->gran.fetchtime);
450 fprintf(stderr,"} FETCHCOUNT: \t%#lx", closure->gran.fetchcount);
451 fprintf(stderr,"\tBLOCKTIME: \t%#lx\n", closure->gran.blocktime);
452 fprintf(stderr,"} BLOCKCOUNT: \t%#lx", closure->gran.blockcount);
453 fprintf(stderr,"\tBLOCKEDAT: \t%#lx\n", closure->gran.blockedat);
454 fprintf(stderr,"} GLOBALSPARKS:\t%#lx", closure->gran.globalsparks);
455 fprintf(stderr,"\tLOCALSPARKS:\t%#lx\n", closure->gran.localsparks);
457 if ( verbose & 0x02 ) {
458 fprintf(stderr,"BQ that starts with this TSO: ");
463 //@node Events, Sparks, Threads, Debugging routines for GranSim and GUM
467 G_EVENT(event, verbose)
474 fprintf(stderr," %#lx",event);
482 extern rtsEventQ EventHd;
485 fprintf(stderr,"RtsEventQ (hd @%#lx):\n",EventHd);
486 for (x=EventHd; x!=NULL; x=x->next) {
490 fprintf(stderr,"NIL\n");
492 fprintf(stderr,"\n");
500 extern rtsEventQ EventHd;
503 fprintf(stderr,"RtsEventQ (hd @%#lx):\n",EventHd);
504 for (x=EventHd; x!=NULL; x=x->next) {
509 fprintf(stderr,"NIL\n");
511 fprintf(stderr,"\n");
514 //@node Sparks, Processors, Events, Debugging routines for GranSim and GUM
518 G_SPARK(spark, verbose)
522 if (spark==(rtsSpark*)NULL) {
523 belch("G_SPARK: NULL spark; aborting");
529 fprintf(stderr," %#lx",spark);
533 G_SPARKQ(spark,verbose)
539 if (spark==(rtsSpark*)NULL) {
540 belch("G_SPARKQ: NULL spark; aborting");
544 fprintf(stderr,"RtsSparkQ (hd @%#lx):\n",spark);
545 for (x=spark; x!=NULL; x=x->next) {
549 fprintf(stderr,"NIL\n");
551 fprintf(stderr,"\n");
555 G_CURR_SPARKQ(verbose)
558 G_SPARKQ(pending_sparks_hd,verbose);
561 //@node Processors, Shortcuts, Sparks, Debugging routines for GranSim and GUM
562 //@subsection Processors
569 extern rtsEventQ EventHd;
570 extern char *proc_status_names[];
572 fprintf(stderr,"Status of proc %d at time %d (%#lx): %s (%s)\n",
573 proc,CurrentTime[proc],CurrentTime[proc],
574 (CurrentProc==proc)?"ACTIVE":"INACTIVE",
575 proc_status_names[procStatus[proc]]);
576 G_THREADQ(run_queue_hds[proc],verbose & 0x2);
577 if ( (CurrentProc==proc) )
581 fprintf(stderr,"Next event (%s) is on proc %d\n",
582 event_names[EventHd->evttype],EventHd->proc);
585 fprintf(stderr,"\nREQUIRED sparks: ");
586 G_SPARKQ(pending_sparks_hds[proc],1);
587 fprintf(stderr,"\nADVISORY_sparks: ");
588 G_SPARKQ(pending_sparks_hds[proc],1);
592 //@node Shortcuts, Printing info type, Processors, Debugging routines for GranSim and GUM
593 //@subsection Shortcuts
595 /* Debug Processor */
602 /* Debug Current Processor */
604 GCP(){ G_PROC(CurrentProc,2); }
612 /* Debug CurrentTSO */
615 fprintf(stderr,"Current Proc: %d\n",CurrentProc);
619 /* Shorthand for debugging event queue */
621 GEQ() { G_EVENTQ(1); }
623 /* Shorthand for debugging thread queue of a processor */
625 GTQ(PEs p) { G_THREADQ(run_queue_hds[p],1); }
627 /* Shorthand for debugging thread queue of current processor */
629 GCTQ() { G_THREADQ(run_queue_hds[CurrentProc],1); }
631 /* Shorthand for debugging spark queue of a processor */
633 GSQ(PEs p) { G_SPARKQ(pending_sparks_hds[p],1); }
635 /* Shorthand for debugging spark queue of current processor */
637 GCSQ() { G_CURR_SPARKQ(1); }
639 /* Shorthand for printing a node */
641 GN(StgPtr node) { G_PRINT_NODE(node); }
643 /* Shorthand for printing info table */
647 GIT(StgPtr node) { G_INFO_TABLE(node); }
651 printThreadQPtrs(void)
654 for (p=0; p<RtsFlags.GranFlags.proc; p++) {
655 fprintf(stderr,", PE %d: (hd=%p,tl=%p)",
656 run_queue_hds[p], run_queue_tls[p]);
661 printThreadQ(StgTSO *tso) { G_THREADQ(tso, 0); };
664 printSparkQ(rtsSpark *spark) { G_SPARKQ(spark, 0); };
667 printThreadQ_verbose(StgTSO *tso) { G_THREADQ(tso, 1); };
670 printSparkQ_verbose(rtsSpark *spark) { G_SPARKQ(spark, 1); };
672 /* Shorthand for some of ADRs debugging functions */
674 #endif /* GRAN && GRAN_CHECK*/
678 DEBUG_PRINT_NODE(node)
681 W_ info_ptr = INFO_PTR(node);
682 StgInt size = 0, ptrs = 0, i, vhs = 0;
685 info_hdr_type(info_ptr, info_type);
687 size_and_ptrs(node,&size,&ptrs);
688 vhs = var_hdr_size(node);
690 fprintf(stderr,"Node: 0x%lx", (W_) node);
693 fprintf(stderr," [GA: 0x%lx]",GA(node));
696 #if defined(PROFILING)
697 fprintf(stderr," [CC: 0x%lx]",CC_HDR(node));
701 fprintf(stderr," [Bitmask: 0%lo]",PROCS(node));
704 fprintf(stderr," IP: 0x%lx (%s), size %ld, %ld ptrs\n",
705 info_ptr,info_type,size,ptrs);
707 /* For now, we ignore the variable header */
709 for(i=0; i < size; ++i)
712 fprintf(stderr,"Data: ");
715 fprintf(stderr,"\n ");
718 fprintf(stderr," 0x%lx[P]",*(node+_HS+vhs+i));
720 fprintf(stderr," %lu[D]",*(node+_HS+vhs+i));
722 fprintf(stderr, "\n");
726 #define INFO_MASK 0x80000000
732 W_ size = 0, ptrs = 0, i, vhs = 0;
734 /* Don't print cycles */
735 if((INFO_PTR(node) & INFO_MASK) != 0)
738 size_and_ptrs(node,&size,&ptrs);
739 vhs = var_hdr_size(node);
741 DEBUG_PRINT_NODE(node);
742 fprintf(stderr, "\n");
744 /* Mark the node -- may be dangerous */
745 INFO_PTR(node) |= INFO_MASK;
747 for(i = 0; i < ptrs; ++i)
748 DEBUG_TREE((StgPtr)node[i+vhs+_HS]);
750 /* Unmark the node */
751 INFO_PTR(node) &= ~INFO_MASK;
756 DEBUG_INFO_TABLE(node)
759 W_ info_ptr = INFO_PTR(node);
760 char *iStgPtrtype = info_hdr_type(info_ptr);
762 fprintf(stderr,"%s Info Ptr @0x%lx; Entry: 0x%lx; Size: %lu; Ptrs: %lu\n\n",
763 iStgPtrtype,info_ptr,(W_) ENTRY_CODE(info_ptr),INFO_SIZE(info_ptr),INFO_NoPTRS(info_ptr));
765 fprintf(stderr,"Enter Flush Entry: 0x%lx;\tExit Flush Entry: 0x%lx\n",INFO_FLUSHENT(info_ptr),INFO_FLUSH(info_ptr));
768 #if defined(PROFILING)
769 fprintf(stderr,"Cost Centre (?): 0x%lx\n",INFO_CAT(info_ptr));
772 #if defined(_INFO_COPYING)
773 fprintf(stderr,"Evacuate Entry: 0x%lx;\tScavenge Entry: 0x%lx\n",
774 INFO_EVAC_2S(info_ptr),INFO_SCAV_2S(info_ptr));
777 #if defined(_INFO_COMPACTING)
778 fprintf(stderr,"Scan Link: 0x%lx;\tScan Move: 0x%lx\n",
779 (W_) INFO_SCAN_LINK_1S(info_ptr), (W_) INFO_SCAN_MOVE_1S(info_ptr));
780 fprintf(stderr,"Mark: 0x%lx;\tMarked: 0x%lx;\t",
781 (W_) INFO_MARK_1S(info_ptr), (W_) INFO_MARKED_1S(info_ptr));
782 #if 0 /* avoid INFO_TYPE */
783 if(BASE_INFO_TYPE(info_ptr)==INFO_SPEC_TYPE)
784 fprintf(stderr,"plus specialised code\n");
786 fprintf(stderr,"Marking: 0x%lx\n",(W_) INFO_MARKING_1S(info_ptr));
788 #endif /* _INFO_COMPACTING */
792 //@node Printing info type, Printing Packet Contents, Shortcuts, Debugging routines for GranSim and GUM
793 //@subsection Printing info type
796 display_info_type(closure, str)
801 if ( closure_HNF(closure) )
802 strcat(str,"|_HNF ");
803 else if ( closure_BITMAP(closure) )
805 else if ( !closure_SHOULD_SPARK(closure) )
807 else if ( closure_STATIC(closure) )
809 else if ( closure_THUNK(closure) )
811 else if ( closure_MUTABLE(closure) )
813 else if ( closure_UNPOINTED(closure) )
815 else if ( closure_SRT(closure) )
822 PrintPacket is in Pack.c because it makes use of closure queues
825 #if defined(GRAN) || defined(PAR)
828 Print graph rooted at q. The structure of this recursive printing routine
829 should be the same as in the graph traversals when packing a graph in
830 GUM. Thus, it demonstrates the structure of such a generic graph
831 traversal, and in particular, how to extract pointer and non-pointer info
832 from the multitude of different heap objects available.
834 {evacuate}Daq ngoqvam nIHlu'pu'!!
838 PrintGraph(StgClosure *p, int indent_level)
840 void PrintGraph_(StgClosure *p, int indent_level);
842 ASSERT(tmpClosureTable==NULL);
844 /* init hash table */
845 tmpClosureTable = allocHashTable();
847 /* now do the real work */
848 PrintGraph_(p, indent_level);
850 /* nuke hash table */
851 freeHashTable(tmpClosureTable, NULL);
852 tmpClosureTable = NULL;
856 This is the actual worker functions.
857 All recursive calls should be made to this function.
860 PrintGraph_(StgClosure *p, int indent_level)
863 rtsBool printed = rtsFalse;
865 const StgInfoTable *info;
867 /* check whether we have met this node already to break cycles */
868 if (lookupHashTable(tmpClosureTable, (StgWord)p)) { // ie. already touched
870 for (j=0; j<indent_level; j++)
873 fprintf(stderr, "#### cylce to %p", p);
877 /* record that we are processing this closure */
878 insertHashTable(tmpClosureTable, (StgWord) p, (void *)rtsTrue/*non-NULL*/);
880 q = p; /* save ptr to object */
883 for (j=0; j<indent_level; j++)
886 ASSERT(p!=(StgClosure*)NULL);
887 ASSERT(LOOKS_LIKE_STATIC(p) ||
888 LOOKS_LIKE_GHC_INFO(GET_INFO((StgClosure *)p)) ||
889 IS_HUGS_CONSTR_INFO(GET_INFO((StgClosure *)p)));
891 printClosure(p); // prints contents of this one closure
894 for (j=0; j<indent_level; j++)
897 info = get_itbl((StgClosure *)p);
898 /* the rest of this fct recursively traverses the graph */
899 switch (info -> type) {
903 StgBCO* bco = stgCast(StgBCO*,p);
905 fprintf(stderr, "BCO (%p)\n", p);
907 for (i = 0; i < bco->n_ptrs; i++) {
908 // bcoConstCPtr(bco,i) =
909 PrintGraph_(bcoConstCPtr(bco,i), indent_level+1);
912 // p += bco_sizeW(bco);
917 /* treat MVars specially, because we don't want to PrintGraph the
918 * mut_link field in the middle of the closure.
921 StgMVar *mvar = ((StgMVar *)p);
923 fprintf(stderr, "MVAR (%p) with 3 pointers (head, tail, value)\n", p);
924 // (StgClosure *)mvar->head =
925 PrintGraph_((StgClosure *)mvar->head, indent_level+1);
926 // (StgClosure *)mvar->tail =
927 PrintGraph_((StgClosure *)mvar->tail, indent_level+1);
928 //(StgClosure *)mvar->value =
929 PrintGraph_((StgClosure *)mvar->value, indent_level+1);
930 // p += sizeofW(StgMVar);
931 // evac_gen = saved_evac_gen;
937 fprintf(stderr, "THUNK_2_0 (%p) with 2 pointers\n", p);
942 fprintf(stderr, "FUN_2_0 (%p) with 2 pointers\n", p);
945 // scavenge_srt(info);
948 fprintf(stderr, "CONSTR_2_0 (%p) with 2 pointers\n", p);
951 // ((StgClosure *)p)->payload[0] =
952 PrintGraph_(((StgClosure *)p)->payload[0],
954 // ((StgClosure *)p)->payload[1] =
955 PrintGraph_(((StgClosure *)p)->payload[1],
957 // p += sizeofW(StgHeader) + 2;
961 // scavenge_srt(info);
962 fprintf(stderr, "THUNK_1_0 (%p) with 1 pointer\n", p);
963 // ((StgClosure *)p)->payload[0] =
964 PrintGraph_(((StgClosure *)p)->payload[0],
966 // p += sizeofW(StgHeader) + 2; /* MIN_UPD_SIZE */
971 fprintf(stderr, "FUN_1_0 (%p) with 1 pointer\n", p);
974 // scavenge_srt(info);
977 fprintf(stderr, "CONSTR_2_0 (%p) with 2 pointers\n", p);
980 // ((StgClosure *)p)->payload[0] =
981 PrintGraph_(((StgClosure *)p)->payload[0],
983 // p += sizeofW(StgHeader) + 1;
987 fprintf(stderr, "THUNK_0_1 (%p) with 0 pointers\n", p);
988 // scavenge_srt(info);
989 // p += sizeofW(StgHeader) + 2; /* MIN_UPD_SIZE */
993 fprintf(stderr, "FUN_0_1 (%p) with 0 pointers\n", p);
994 //scavenge_srt(info);
996 fprintf(stderr, "CONSTR_0_1 (%p) with 0 pointers\n", p);
997 //p += sizeofW(StgHeader) + 1;
1002 fprintf(stderr, "THUNK_0_2 (%p) with 0 pointers\n", p);
1007 fprintf(stderr, "FUN_0_2 (%p) with 0 pointers\n", p);
1010 // scavenge_srt(info);
1013 fprintf(stderr, "CONSTR_0_2 (%p) with 0 pointers\n", p);
1016 // p += sizeofW(StgHeader) + 2;
1021 fprintf(stderr, "THUNK_1_1 (%p) with 1 pointer\n", p);
1026 fprintf(stderr, "FUN_1_1 (%p) with 1 pointer\n", p);
1029 // scavenge_srt(info);
1032 fprintf(stderr, "CONSTR_1_1 (%p) with 1 pointer\n", p);
1035 // ((StgClosure *)p)->payload[0] =
1036 PrintGraph_(((StgClosure *)p)->payload[0],
1038 // p += sizeofW(StgHeader) + 2;
1043 fprintf(stderr, "FUN (%p) with %d pointers\n", p, info->layout.payload.ptrs);
1050 fprintf(stderr, "THUNK (%p) with %d pointers\n", p, info->layout.payload.ptrs);
1053 // scavenge_srt(info);
1058 fprintf(stderr, "CONSTR (%p) with %d pointers\n", p, info->layout.payload.ptrs);
1061 /* basically same as loop in STABLE_NAME case */
1062 for (i=0; i<info->layout.payload.ptrs; i++)
1063 PrintGraph_(((StgClosure *)p)->payload[i],
1066 /* NOT fall through */
1070 fprintf(stderr, "WEAK (%p) with %d pointers\n", p, info->layout.payload.ptrs);
1077 fprintf(stderr, "FOREIGN (%p) with %d pointers\n", p, info->layout.payload.ptrs);
1087 fprintf(stderr, "STABLE_NAME (%p) with %d pointers (not followed!)\n",
1088 p, info->layout.payload.ptrs);
1091 end = (StgPtr)((StgClosure *)p)->payload + info->layout.payload.ptrs;
1092 for (p = (StgPtr)((StgClosure *)p)->payload; p < end; p++) {
1093 // (StgClosure *)*p =
1094 //PrintGraph_((StgClosure *)*p, indent_level+1);
1095 fprintf(stderr, ", %p", *p);
1097 //fputs("\n", stderr);
1098 // p += info->layout.payload.nptrs;
1103 //if (step->gen->no != 0) {
1104 // SET_INFO(((StgClosure *)p), &IND_OLDGEN_PERM_info);
1107 fprintf(stderr, "IND_PERM (%p) with indirection to\n",
1108 p, ((StgIndOldGen *)p)->indirectee);
1113 case IND_OLDGEN_PERM:
1115 fprintf(stderr, "IND_OLDGEN_PERM (%p) with indirection to %p\n",
1116 p, ((StgIndOldGen *)p)->indirectee);
1119 // ((StgIndOldGen *)p)->indirectee =
1120 PrintGraph_(((StgIndOldGen *)p)->indirectee,
1122 //if (failed_to_evac) {
1123 // failed_to_evac = rtsFalse;
1124 // recordOldToNewPtrs((StgMutClosure *)p);
1126 // p += sizeofW(StgIndOldGen);
1130 /* ignore MUT_CONSs */
1131 fprintf(stderr, "MUT_VAR (%p) pointing to %p\n", p, ((StgMutVar *)p)->var);
1132 if (((StgMutVar *)p)->header.info != &stg_MUT_CONS_info) {
1134 PrintGraph_(((StgMutVar *)p)->var, indent_level+1);
1135 //evac_gen = saved_evac_gen;
1137 //p += sizeofW(StgMutVar);
1142 fprintf(stderr, "CAF_BLACKHOLE (%p) with 0 pointers\n", p);
1145 case SE_CAF_BLACKHOLE:
1147 fprintf(stderr, "SE_CAF_BLACKHOLE (%p) with 0 pointers\n", p);
1152 fprintf(stderr, "SE_BLACKHOLE (%p) with 0 pointers\n", p);
1157 fprintf(stderr, "BLACKHOLE (%p) with 0 pointers\n", p);
1160 //p += BLACKHOLE_sizeW();
1165 StgBlockingQueue *bh = (StgBlockingQueue *)p;
1166 // (StgClosure *)bh->blocking_queue =
1167 fprintf(stderr, "BLACKHOLE_BQ (%p) pointing to %p\n",
1168 p, (StgClosure *)bh->blocking_queue);
1169 PrintGraph_((StgClosure *)bh->blocking_queue, indent_level+1);
1170 //if (failed_to_evac) {
1171 // failed_to_evac = rtsFalse;
1172 // recordMutable((StgMutClosure *)bh);
1174 // p += BLACKHOLE_sizeW();
1178 case THUNK_SELECTOR:
1180 StgSelector *s = (StgSelector *)p;
1181 fprintf(stderr, "THUNK_SELECTOR (%p) pointing to %p\n",
1183 PrintGraph_(s->selectee, indent_level+1);
1184 // p += THUNK_SELECTOR_sizeW();
1189 fprintf(stderr, "IND (%p) pointing to %p\n", p, ((StgInd*)p)->indirectee);
1190 PrintGraph_(((StgInd*)p)->indirectee, indent_level+1);
1194 fprintf(stderr, "IND_OLDGEN (%p) pointing to %p\n",
1195 p, ((StgIndOldGen*)p)->indirectee);
1196 PrintGraph_(((StgIndOldGen*)p)->indirectee, indent_level+1);
1199 case CONSTR_INTLIKE:
1200 fprintf(stderr, "CONSTR_INTLIKE (%p) with 0 pointers\n", p);
1202 case CONSTR_CHARLIKE:
1203 fprintf(stderr, "CONSTR_CHARLIKE (%p) with 0 pointers\n", p);
1206 fprintf(stderr, "CONSTR_STATIC (%p) with 0 pointers\n", p);
1208 case CONSTR_NOCAF_STATIC:
1209 fprintf(stderr, "CONSTR_NOCAF_STATIC (%p) with 0 pointers\n", p);
1212 fprintf(stderr, "THUNK_STATIC (%p) with 0 pointers\n", p);
1215 fprintf(stderr, "FUN_STATIC (%p) with 0 pointers\n", p);
1218 fprintf(stderr, "IND_STATIC (%p) with 0 pointers\n", p);
1222 fprintf(stderr, "RET_BCO (%p) with 0 pointers\n", p);
1225 fprintf(stderr, "RET_SMALL (%p) with 0 pointers\n", p);
1228 fprintf(stderr, "RET_VEC_SMALL (%p) with 0 pointers\n", p);
1231 fprintf(stderr, "RET_BIG (%p) with 0 pointers\n", p);
1234 fprintf(stderr, "RET_VEC_BIG (%p) with 0 pointers\n", p);
1237 fprintf(stderr, "RET_DYN (%p) with 0 pointers\n", p);
1240 fprintf(stderr, "UPDATE_FRAME (%p) with 0 pointers\n", p);
1243 fprintf(stderr, "STOP_FRAME (%p) with 0 pointers\n", p);
1246 fprintf(stderr, "CATCH_FRAME (%p) with 0 pointers\n", p);
1249 fprintf(stderr, "SEQ_FRAME (%p) with 0 pointers\n", p);
1252 case AP_UPD: /* same as PAPs */
1253 fprintf(stderr, "AP_UPD (%p) with 0 pointers\n", p);
1255 /* Treat a PAP just like a section of stack, not forgetting to
1256 * PrintGraph_ the function pointer too...
1259 StgPAP* pap = stgCast(StgPAP*,p);
1261 fprintf(stderr, "PAP (%p) pointing to %p\n", p, pap->fun);
1263 //PrintGraph_(pap->fun, indent_level+1);
1264 //scavenge_stack((P_)pap->payload, (P_)pap->payload + pap->n_args);
1265 //p += pap_sizeW(pap);
1270 /* an array of (non-mutable) words */
1271 fprintf(stderr, "ARR_WORDS (%p) of %d non-ptrs (maybe a string?)\n",
1272 p, ((StgArrWords *)q)->words);
1276 /* follow everything */
1280 fprintf(stderr, "MUT_ARR_PTRS (%p) with %d pointers (not followed)\n",
1281 p, mut_arr_ptrs_sizeW((StgMutArrPtrs*)p));
1282 // evac_gen = 0; /* repeatedly mutable */
1283 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1284 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
1285 // (StgClosure *)*p =
1286 // PrintGraph_((StgClosure *)*p, indent_level+1);
1287 fprintf(stderr, ", %p", *p);
1289 fputs("\n", stderr);
1290 //evac_gen = saved_evac_gen;
1294 case MUT_ARR_PTRS_FROZEN:
1295 /* follow everything */
1297 StgPtr start = p, next;
1299 fprintf(stderr, "MUT_ARR_PTRS (%p) with %d pointers (not followed)",
1300 p, mut_arr_ptrs_sizeW((StgMutArrPtrs*)p));
1301 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1302 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
1303 // (StgClosure *)*p =
1304 // PrintGraph_((StgClosure *)*p, indent_level+1);
1305 fprintf(stderr, ", %p", *p);
1307 fputs("\n", stderr);
1308 //if (failed_to_evac) {
1309 /* we can do this easier... */
1310 // recordMutable((StgMutClosure *)start);
1311 // failed_to_evac = rtsFalse;
1321 fprintf(stderr, "TSO (%p) with link field %p\n", p, (StgClosure *)tso->link);
1323 /* chase the link field for any TSOs on the same queue */
1324 // (StgClosure *)tso->link =
1325 PrintGraph_((StgClosure *)tso->link, indent_level+1);
1326 //if (tso->blocked_on) {
1327 // tso->blocked_on = PrintGraph_(tso->blocked_on);
1329 /* scavenge this thread's stack */
1330 //scavenge_stack(tso->sp, &(tso->stack[tso->stack_size]));
1331 //evac_gen = saved_evac_gen;
1332 //p += tso_sizeW(tso);
1336 #if defined(GRAN) || defined(PAR)
1339 StgInfoTable *rip = REVERT_INFOPTR(get_itbl(p));
1340 //if (LOOKS_LIKE_GHC_INFO(rip))
1341 // fprintf(stderr, "RBH (%p) with 0 pointers (reverted type=%s)\n",
1342 // p, info_type_by_ip(rip));
1344 fprintf(stderr, "RBH (%p) with 0 pointers (reverted IP=%x)\n",
1351 fprintf(stderr, "BLOCKED_FETCH (%p) with 0 pointers (link=%p)\n",
1352 p, ((StgBlockedFetch *)p)->link);
1355 fprintf(stderr, "FETCH_ME (%p) with 0 pointers\n", p);
1358 fprintf(stderr, "FETCH_ME_BQ (%p) with 0 pointers (blocking_queue=%p)\n",
1359 p, ((StgFetchMeBlockingQueue *)p)->blocking_queue);
1365 fprintf(stderr, "REMOTE_REF (%p) with 0 pointers\n", p);
1370 fprintf(stderr, "EVACUATED (%p) with 0 pointers (evacuee=%p)\n",
1371 p, ((StgEvacuated *)p)->evacuee);
1375 barf("PrintGraph_: unknown closure %d (%s)",
1376 info -> type, info_type(info));
1379 /* If we didn't manage to promote all the objects pointed to by
1380 * the current object, then we have to designate this object as
1381 * mutable (because it contains old-to-new generation pointers).
1383 //if (failed_to_evac) {
1384 // mkMutCons((StgClosure *)q, &generations[evac_gen]);
1385 // failed_to_evac = rtsFalse;
1391 Generate a finger-print for a graph.
1392 A finger-print is a string, with each char representing one node;
1393 depth-first traversal
1397 GraphFingerPrint(StgClosure *p, char *finger_print)
1399 void GraphFingerPrint_(StgClosure *p, char *finger_print);
1401 ASSERT(tmpClosureTable==NULL);
1402 ASSERT(strlen(finger_print)==0);
1404 /* init hash table */
1405 tmpClosureTable = allocHashTable();
1407 /* now do the real work */
1408 GraphFingerPrint_(p, finger_print);
1410 /* nuke hash table */
1411 freeHashTable(tmpClosureTable, NULL);
1412 tmpClosureTable = NULL;
1416 This is the actual worker functions.
1417 All recursive calls should be made to this function.
1420 GraphFingerPrint_(StgClosure *p, char *finger_print)
1423 rtsBool printed = rtsFalse;
1425 const StgInfoTable *info;
1427 q = p; /* save ptr to object */
1428 len = strlen(finger_print);
1429 ASSERT(len<=MAX_FINGER_PRINT_LEN);
1430 /* at most 7 chars for this node (I think) */
1431 if (len+7>=MAX_FINGER_PRINT_LEN)
1434 /* check whether we have met this node already to break cycles */
1435 if (lookupHashTable(tmpClosureTable, (StgWord)p)) { // ie. already touched
1436 strcat(finger_print, "#");
1440 /* record that we are processing this closure */
1441 insertHashTable(tmpClosureTable, (StgWord) p, (void *)rtsTrue/*non-NULL*/);
1443 ASSERT(p!=(StgClosure*)NULL);
1444 ASSERT(LOOKS_LIKE_STATIC(p) ||
1445 LOOKS_LIKE_GHC_INFO(GET_INFO((StgClosure *)p)) ||
1446 IS_HUGS_CONSTR_INFO(GET_INFO((StgClosure *)p)));
1448 info = get_itbl((StgClosure *)p);
1449 // append char for this node
1450 finger_print[len] = finger_print_char[info->type]; finger_print[len+1] = '\0';
1451 /* the rest of this fct recursively traverses the graph */
1452 switch (info -> type) {
1456 StgBCO* bco = stgCast(StgBCO*,p);
1458 //%% fprintf(stderr, "BCO (%p) with %d pointers\n", p, bco->n_ptrs);
1460 for (i = 0; i < bco->n_ptrs; i++) {
1461 // bcoConstCPtr(bco,i) =
1462 GraphFingerPrint_(bcoConstCPtr(bco,i), finger_print);
1465 // p += bco_sizeW(bco);
1475 // append char for this node
1476 strcat(finger_print, "22(");
1477 GraphFingerPrint_(((StgClosure *)p)->payload[0], finger_print);
1478 GraphFingerPrint_(((StgClosure *)p)->payload[1], finger_print);
1479 if (strlen(finger_print)+2<MAX_FINGER_PRINT_LEN)
1480 strcat(finger_print, ")");
1486 // append char for this node
1487 strcat(finger_print, "12(");
1488 GraphFingerPrint_(((StgClosure *)p)->payload[0], finger_print);
1489 if (strlen(finger_print)+2<MAX_FINGER_PRINT_LEN)
1490 strcat(finger_print, ")");
1496 // append char for this node
1497 strcat(finger_print, "01");
1503 // append char for this node
1504 strcat(finger_print, "02");
1510 // append char for this node
1511 strcat(finger_print, "11(");
1512 GraphFingerPrint_(((StgClosure *)p)->payload[0], finger_print);
1513 if (strlen(finger_print)+2<MAX_FINGER_PRINT_LEN)
1514 strcat(finger_print, ")");
1520 /* basically same as loop in STABLE_NAME case */
1523 sprintf(str,"%d?(",info->layout.payload.ptrs);
1524 strcat(finger_print,str);
1525 for (i=0; i<info->layout.payload.ptrs; i++)
1526 GraphFingerPrint_(((StgClosure *)p)->payload[i], finger_print);
1527 if (strlen(finger_print)+2<MAX_FINGER_PRINT_LEN)
1528 strcat(finger_print, ")");
1538 sprintf(str,"%d?", info->layout.payload.ptrs);
1539 strcat(finger_print,str);
1541 //end = (StgPtr)((StgClosure *)p)->payload + info->layout.payload.ptrs;
1542 //for (p = (StgPtr)((StgClosure *)p)->payload; p < end; p++) {
1543 // GraphFingerPrint_((StgClosure *)*p, finger_print);
1549 case IND_OLDGEN_PERM:
1550 GraphFingerPrint_(((StgIndOldGen *)p)->indirectee, finger_print);
1554 /* ignore MUT_CONSs */
1555 if (((StgMutVar *)p)->header.info != &stg_MUT_CONS_info) {
1556 GraphFingerPrint_(((StgMutVar *)p)->var, finger_print);
1561 case SE_CAF_BLACKHOLE:
1568 StgBlockingQueue *bh = (StgBlockingQueue *)p;
1569 // GraphFingerPrint_((StgClosure *)bh->blocking_queue, finger_print);
1573 case THUNK_SELECTOR:
1575 StgSelector *s = (StgSelector *)p;
1576 GraphFingerPrint_(s->selectee, finger_print);
1581 GraphFingerPrint_(((StgInd*)p)->indirectee, finger_print);
1585 GraphFingerPrint_(((StgIndOldGen*)p)->indirectee, finger_print);
1589 GraphFingerPrint_(((StgIndOldGen*)p)->indirectee, finger_print);
1592 case CONSTR_INTLIKE:
1593 case CONSTR_CHARLIKE:
1595 case CONSTR_NOCAF_STATIC:
1612 case AP_UPD: /* same as PAPs */
1614 /* Treat a PAP just like a section of stack, not forgetting to
1615 * GraphFingerPrint_ the function pointer too...
1618 StgPAP* pap = stgCast(StgPAP*,p);
1620 sprintf(str,"%d",pap->n_args);
1621 strcat(finger_print,str);
1622 //GraphFingerPrint_(pap->fun, finger_print); // ??
1629 sprintf(str,"%d",((StgArrWords*)p)->words);
1630 strcat(finger_print,str);
1635 /* follow everything */
1638 sprintf(str,"%d",((StgMutArrPtrs*)p)->ptrs);
1639 strcat(finger_print,str);
1643 //next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1644 //for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
1645 // GraphFingerPrint_((StgClosure *)*p, finger_print);
1650 case MUT_ARR_PTRS_FROZEN:
1651 /* follow everything */
1654 sprintf(str,"%d",((StgMutArrPtrs*)p)->ptrs);
1655 strcat(finger_print,str);
1658 StgPtr start = p, next;
1659 //next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1660 //for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
1661 // GraphFingerPrint_((StgClosure *)*p, finger_print);
1668 StgTSO *tso = (StgTSO *)p;
1670 sprintf(str,"%d",tso->id);
1671 strcat(finger_print,str);
1673 //GraphFingerPrint_((StgClosure *)tso->link, indent_level+1);
1676 #if defined(GRAN) || defined(PAR)
1680 // StgInfoTable *rip = REVERT_INFOPTR(get_itbl(p));
1700 barf("GraphFingerPrint_: unknown closure %d (%s)",
1701 info -> type, info_type(info));
1708 Do a sanity check on the whole graph, down to a recursion level of level.
1709 Same structure as PrintGraph (nona).
1712 checkGraph(StgClosure *p, int rec_level)
1716 const StgInfoTable *info;
1721 q = p; /* save ptr to object */
1723 /* First, the obvious generic checks */
1724 ASSERT(p!=(StgClosure*)NULL);
1725 checkClosure(p); /* see Sanity.c for what's actually checked */
1727 info = get_itbl((StgClosure *)p);
1728 /* the rest of this fct recursively traverses the graph */
1729 switch (info -> type) {
1733 StgBCO* bco = stgCast(StgBCO*,p);
1736 for (i = 0; i < bco->n_ptrs; i++) {
1737 checkGraph(bcoConstCPtr(bco,i), rec_level-1);
1744 /* treat MVars specially, because we don't want to PrintGraph the
1745 * mut_link field in the middle of the closure.
1748 StgMVar *mvar = ((StgMVar *)p);
1749 checkGraph((StgClosure *)mvar->head, rec_level-1);
1750 checkGraph((StgClosure *)mvar->tail, rec_level-1);
1751 checkGraph((StgClosure *)mvar->value, rec_level-1);
1758 checkGraph(((StgClosure *)p)->payload[0], rec_level-1);
1759 checkGraph(((StgClosure *)p)->payload[1], rec_level-1);
1763 checkGraph(((StgClosure *)p)->payload[0], rec_level-1);
1768 checkGraph(((StgClosure *)p)->payload[0], rec_level-1);
1786 checkGraph(((StgClosure *)p)->payload[0], rec_level-1);
1792 for (i=0; i<info->layout.payload.ptrs; i++)
1793 checkGraph(((StgClosure *)p)->payload[i], rec_level-1);
1802 end = (StgPtr)((StgClosure *)p)->payload + info->layout.payload.ptrs;
1803 for (p = (StgPtr)((StgClosure *)p)->payload; p < end; p++) {
1804 checkGraph(*(StgClosure **)p, rec_level-1);
1810 case IND_OLDGEN_PERM:
1811 checkGraph(((StgIndOldGen *)p)->indirectee, rec_level-1);
1815 /* ignore MUT_CONSs */
1816 if (((StgMutVar *)p)->header.info != &stg_MUT_CONS_info) {
1817 checkGraph(((StgMutVar *)p)->var, rec_level-1);
1822 case SE_CAF_BLACKHOLE:
1830 case THUNK_SELECTOR:
1832 StgSelector *s = (StgSelector *)p;
1833 checkGraph(s->selectee, rec_level-1);
1838 checkGraph(((StgInd*)p)->indirectee, rec_level-1);
1842 checkGraph(((StgIndOldGen*)p)->indirectee, rec_level-1);
1845 case CONSTR_INTLIKE:
1847 case CONSTR_CHARLIKE:
1851 case CONSTR_NOCAF_STATIC:
1881 case AP_UPD: /* same as PAPs */
1883 /* Treat a PAP just like a section of stack, not forgetting to
1884 * checkGraph the function pointer too...
1887 StgPAP* pap = stgCast(StgPAP*,p);
1889 checkGraph(pap->fun, rec_level-1);
1897 /* follow everything */
1901 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1902 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
1903 checkGraph(*(StgClosure **)p, rec_level-1);
1908 case MUT_ARR_PTRS_FROZEN:
1909 /* follow everything */
1911 StgPtr start = p, next;
1913 next = p + mut_arr_ptrs_sizeW((StgMutArrPtrs*)p);
1914 for (p = (P_)((StgMutArrPtrs *)p)->payload; p < next; p++) {
1915 checkGraph(*(StgClosure **)p, rec_level-1);
1925 checkGraph((StgClosure *)tso->link, rec_level-1);
1929 #if defined(GRAN) || defined(PAR)
1942 barf("checkGraph: found EVACUATED closure %p (%s)",
1952 #endif /* GRAN || PAR */
1954 //@node End of File, , Printing Packet Contents, Debugging routines for GranSim and GUM
1955 //@subsection End of File