📄 prmsgc.c
字号:
/******************************************************************************/typedef void (*WalkObject_t)(FILE *out, GCType* tp, PRWord *obj, size_t bytes, PRBool detailed);typedef void (*WalkUnknown_t)(FILE *out, GCType* tp, PRWord tix, PRWord *p, size_t bytes, PRBool detailed);typedef void (*WalkFree_t)(FILE *out, PRWord *p, size_t size, PRBool detailed);typedef void (*WalkSegment_t)(FILE *out, GCSeg* sp, PRBool detailed);static voidpr_WalkSegment(FILE* out, GCSeg* sp, PRBool detailed, char* enterMsg, char* exitMsg, WalkObject_t walkObject, WalkUnknown_t walkUnknown, WalkFree_t walkFree){ PRWord *p, *limit; p = (PRWord *) sp->base; limit = (PRWord *) sp->limit; if (enterMsg) fprintf(out, enterMsg, p); while (p < limit) { if (IS_HBIT(sp, p)) /* Is this an object header? */ { PRWord h = p[0]; PRWord tix = GET_TYPEIX(h); size_t bytes = OBJ_BYTES(h); PRWord* np = (PRWord*) ((char*)p + bytes); GCType* tp = &_pr_collectorTypes[tix].gctype; if ((0 != tp) && walkObject) walkObject(out, tp, p, bytes, detailed); else if (walkUnknown) walkUnknown(out, tp, tix, p, bytes, detailed); p = np; } else { /* Must be a freelist item */ size_t size = ((GCFreeChunk*)p)->chunkSize; if (walkFree) walkFree(out, p, size, detailed); p = (PRWord*)((char*)p + size); } } if (p != limit) fprintf(out, "SEGMENT OVERRUN (end should be at 0x%p)\n", limit); if (exitMsg) fprintf(out, exitMsg, p);}static voidpr_WalkSegments(FILE *out, WalkSegment_t walkSegment, PRBool detailed){ GCSeg *sp = segs; GCSeg *esp; LOCK_GC(); esp = sp + nsegs; while (sp < esp) { walkSegment(out, sp, detailed); sp++; } fprintf(out, "End of heap\n"); UNLOCK_GC();}/******************************************************************************* * Heap Dumper ******************************************************************************/PR_IMPLEMENT(void)PR_DumpIndent(FILE *out, int indent){ while (--indent >= 0) fprintf(out, " ");}static voidPR_DumpHexWords(FILE *out, PRWord *p, int nWords, int indent, int nWordsPerLine){ while (nWords > 0) { int i; PR_DumpIndent(out, indent); i = nWordsPerLine; if (i > nWords) i = nWords; nWords -= i; while (i--) { fprintf(out, "0x%.8lX", (long) *p++); if (i) fputc(' ', out); } fputc('\n', out); }}static void PR_CALLBACKpr_DumpObject(FILE *out, GCType* tp, PRWord *p, size_t bytes, PRBool detailed){ char kindChar = tp->kindChar; fprintf(out, "0x%p: 0x%.6lX %c ", p, (long) bytes, kindChar ? kindChar : '?'); if (tp->dump) (*tp->dump)(out, (void*) (p + 1), detailed, 0); if (detailed) PR_DumpHexWords(out, p, bytes>>2, 22, 4);} static void PR_CALLBACKpr_DumpUnknown(FILE *out, GCType* tp, PRWord tix, PRWord *p, size_t bytes, PRBool detailed){ char kindChar = tp->kindChar; fprintf(out, "0x%p: 0x%.6lX %c ", p, (long) bytes, kindChar ? kindChar : '?'); fprintf(out, "UNKNOWN KIND %ld\n", (long) tix); if (detailed) PR_DumpHexWords(out, p, bytes>>2, 22, 4);}static void PR_CALLBACKpr_DumpFree(FILE *out, PRWord *p, size_t size, PRBool detailed){#if defined(XP_MAC) && XP_MAC# pragma unused( detailed )#endif fprintf(out, "0x%p: 0x%.6lX - FREE\n", p, (long) size);}static void PR_CALLBACKpr_DumpSegment(FILE* out, GCSeg* sp, PRBool detailed){ pr_WalkSegment(out, sp, detailed, "\n Address: Length\n0x%p: Beginning of segment\n", "0x%p: End of segment\n\n", pr_DumpObject, pr_DumpUnknown, pr_DumpFree);}static void pr_DumpRoots(FILE *out);/*** Dump out the GC heap.*/PR_IMPLEMENT(void)PR_DumpGCHeap(FILE *out, PRBool detailed){ fprintf(out, "\n" "The kinds are:\n" " U unscanned block\n" " W weak link block\n" " S scanned block\n" " F scanned and final block\n" " C class record\n" " X context record\n" " - free list item\n" " ? other\n"); LOCK_GC(); pr_WalkSegments(out, pr_DumpSegment, detailed); if (detailed) pr_DumpRoots(out); UNLOCK_GC();}PR_IMPLEMENT(void)PR_DumpMemory(PRBool detailed){ PR_DumpToFile("memory.out", "Dumping memory", PR_DumpGCHeap, detailed);}/******************************************************************************/static PRInt32 PR_CALLBACKpr_DumpRootPointer(PRWord* p, void* data){#ifdef XP_MAC#pragma unused(data)#endif PRWord h = p[0]; PRWord tix = GET_TYPEIX(h); size_t bytes = OBJ_BYTES(h); GCType* tp = &_pr_collectorTypes[tix].gctype; if (0 != tp) pr_DumpObject(_pr_gcData.dumpOutput, tp, p, bytes, PR_FALSE); else pr_DumpUnknown(_pr_gcData.dumpOutput, tp, tix, p, bytes, PR_FALSE); return 0;}static void PR_CALLBACKpr_ConservativeDumpRootPointer(void* ptr){ (void)pr_ConservativeWalkPointer(ptr, (PRWalkFun) pr_DumpRootPointer, NULL);}static void PR_CALLBACKpr_ConservativeDumpRootBlock(void **base, PRInt32 count){ (void)pr_ConservativeWalkBlock(base, count, (PRWalkFun) pr_DumpRootPointer, NULL);}extern intDumpThreadRoots(PRThread *t, int i, void *notused);static voidpr_DumpRoots(FILE *out){ RootFinder *rf; void (*liveBlock)(void **base, PRInt32 count); void (*livePointer)(void *ptr); void (*processRootBlock)(void **base, PRInt32 count); void (*processRootPointer)(void *ptr); LOCK_GC(); liveBlock = _pr_gcData.liveBlock; livePointer = _pr_gcData.livePointer; processRootBlock = _pr_gcData.processRootBlock; processRootPointer = _pr_gcData.processRootPointer; _pr_gcData.liveBlock = pr_ConservativeDumpRootBlock; _pr_gcData.livePointer = pr_ConservativeDumpRootPointer; _pr_gcData.processRootBlock = pr_ConservativeDumpRootBlock; _pr_gcData.processRootPointer = pr_ConservativeDumpRootPointer; _pr_gcData.dumpOutput = out; rf = _pr_rootFinders; while (rf) { fprintf(out, "\n===== Roots for %s\n", rf->name); (*rf->func)(rf->arg); rf = rf->next; } _pr_gcData.liveBlock = liveBlock; _pr_gcData.livePointer = livePointer; _pr_gcData.processRootBlock = processRootBlock; _pr_gcData.processRootPointer = processRootPointer; _pr_gcData.dumpOutput = NULL; UNLOCK_GC();}/******************************************************************************* * Heap Summary Dumper ******************************************************************************/PRSummaryPrinter summaryPrinter = NULL;void* summaryPrinterClosure = NULL;PR_IMPLEMENT(void) PR_RegisterSummaryPrinter(PRSummaryPrinter fun, void* closure){ summaryPrinter = fun; summaryPrinterClosure = closure;}static void PR_CALLBACKpr_SummarizeObject(FILE *out, GCType* tp, PRWord *p, size_t bytes, PRBool detailed){#if defined(XP_MAC) && XP_MAC# pragma unused( out, detailed )#endif if (tp->summarize) (*tp->summarize)((void GCPTR*)(p + 1), bytes);}static void PR_CALLBACKpr_DumpSummary(FILE* out, GCSeg* sp, PRBool detailed){ pr_WalkSegment(out, sp, detailed, NULL, NULL, pr_SummarizeObject, NULL, NULL);}PR_IMPLEMENT(void)PR_DumpGCSummary(FILE *out, PRBool detailed){ if (summaryPrinter) { pr_WalkSegments(out, pr_DumpSummary, detailed); summaryPrinter(out, summaryPrinterClosure); }#if 0 fprintf(out, "\nFinalizable objects:\n"); { PRCList *qp; qp = _pr_pendingFinalQueue.next; while (qp != &_pr_pendingFinalQueue) { GCFinal* fp = FinalPtr(qp); PRWord h = fp->object[0]; /* Grab header word */ PRWord tix = GET_TYPEIX(h); GCType* tp = _pr_gcTypes[tix]; size_t bytes = OBJ_BYTES(h); pr_DumpObject(out, tp, fp->object, bytes, PR_FALSE); qp = qp->next; } }#endif}PR_IMPLEMENT(void)PR_DumpMemorySummary(void){ PR_DumpToFile("memory.out", "Memory Summary", PR_DumpGCSummary, PR_FALSE);}/******************************************************************************* * End Of Heap Walker ******************************************************************************/#ifdef GC_TRACEROOTSPRInt32 pr_traceGen = 0;static PRBoolpr_IsMarked(PRWord* p){ GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd)); PR_ASSERT(end->check == PR_BLOCK_END); return end->traceGeneration == pr_traceGen;}static voidpr_Mark(PRWord* p){ GCBlockEnd* end = (GCBlockEnd*)((char*)p + OBJ_BYTES(p[0]) - sizeof(GCBlockEnd)); PR_ASSERT(end->check == PR_BLOCK_END); end->traceGeneration = pr_traceGen;}PRWord* pr_traceObj; /* set this in the debugger, then execute PR_TraceRoot() */static PRInt32 PR_CALLBACKpr_TraceRootObject(void* obj, void* data);static PRInt32 PR_CALLBACKpr_TraceRootPointer(PRWord *p, void* data){ PRInt32 printTrace = 0; PRWord h = p[0]; PRWord tix = GET_TYPEIX(h); GCType* tp = &_pr_collectorTypes[tix].gctype; FILE* out = _pr_gcData.dumpOutput; PR_ASSERT(tp); if (pr_IsMarked(p)) return printTrace; pr_Mark(p); if (p == pr_traceObj) { fprintf(out, "\n### Found path to:\n"); printTrace = 1; } else { if (PR_StackSpaceLeft(PR_CurrentThread()) < 512) { fprintf(out, "\n### Path too deep (giving up):\n"); printTrace = 1; } else if (tp->walk) { printTrace = tp->walk((void*)(p + 1), pr_TraceRootObject, data); } /* else there's no way to walk this object, so we haven't found what we're looking for */ } if (printTrace == 1) { PR_ASSERT(tp->dump); fprintf(out, "0x%p: ", p); tp->dump(out, (void*)(p + 1), PR_FALSE, 1); } return printTrace;}static PRInt32 PR_CALLBACKpr_TraceRootObject(void* obj, void* data){ /* This version of pr_TraceRootPointer takes object pointers, instead of gc header pointers. */ return pr_TraceRootPointer((PRWord*)obj - 1, data);}static void PR_CALLBACKpr_ConservativeTraceRootPointer(PRWord *p){ PRInt32 status; ++pr_traceGen; status = pr_ConservativeWalkPointer(p, pr_TraceRootPointer, NULL); if (status) { FILE* out = _pr_gcData.dumpOutput; fprintf(out, "### from root at 0x%p\n\n", p); }}static void PR_CALLBACKpr_ConservativeTraceRootBlock(void **base, PRInt32 count){ PRInt32 status; ++pr_traceGen; status = pr_ConservativeWalkBlock(base, count, pr_TraceRootPointer, NULL); if (status) { FILE* out = _pr_gcData.dumpOutput; fprintf(out, "### from root in range 0x%p + 0x%lx\n\n", base, (long) count); }}static voidPR_TraceRoot1(FILE* out, PRBool detailed){ RootFinder *rf; void (*liveBlock)(void **base, PRInt32 count); void (*livePointer)(void *ptr); void (*processRootBlock)(void **base, PRInt32 count); void (*processRootPointer)(void *ptr); LOCK_GC(); liveBlock = _pr_gcData.liveBlock; livePointer = _pr_gcData.livePointer; processRootBlock = _pr_gcData.processRootBlock; processRootPointer = _pr_gcData.processRootPointer; _pr_gcData.liveBlock = pr_ConservativeTraceRootBlock; _pr_gcData.livePointer = pr_ConservativeTraceRootPointer; _pr_gcData.processRootBlock = pr_ConservativeTraceRootBlock; _pr_gcData.processRootPointer = pr_ConservativeTraceRootPointer; _pr_gcData.dumpOutput = out; fprintf(out, "### Looking for paths to 0x%p\n\n", pr_traceObj); rf = _pr_rootFinders; while (rf) { fprintf(out, "\n===== Roots for %s\n", rf->name); (*rf->func)(rf->arg); rf = rf->next; } _pr_gcData.liveBlock = liveBlock; _pr_gcData.livePointer = livePointer; _pr_gcData.processRootBlock = processRootBlock; _pr_gcData.processRootPointer = processRootPointer; _pr_gcData.dumpOutput = NULL; UNLOCK_GC();}PR_PUBLIC_API(void)PR_TraceRoot(){ /* ** How this works: ** Once you find the object you want to trace the roots of, set the ** global variable pr_traceObj to point to it (the header, not the ** java handle), and then call this routine (on Windows, you can set ** a breakpoint at the end of a function that returns void (e.g. dogc) ** and then do a "set next statement" to point to this routine and go. ** This will dump a list of the paths from the roots to the object in ** question to your memory.out file. */ PR_DumpToFile("memory.out", "Tracing Roots", PR_TraceRoot1, PR_FALSE);}#endif /* GC_TRACEROOTS *//******************************************************************************/#if defined(DEBUG) && defined(WIN32)static void DumpApplicationHeap(FILE *out, HA
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -