Bug 913224 - Fix js::DumpHeapComplete() to work with GGC r=billm r=mccr8

This commit is contained in:
Jon Coppeard 2013-09-30 11:20:08 +01:00
Родитель efbbb0848b
Коммит 41f1b86482
5 изменённых файлов: 60 добавлений и 21 удалений

Просмотреть файл

@ -827,32 +827,52 @@ FinalizeCount(JSContext *cx, unsigned argc, jsval *vp)
static bool static bool
DumpHeapComplete(JSContext *cx, unsigned argc, jsval *vp) DumpHeapComplete(JSContext *cx, unsigned argc, jsval *vp)
{ {
const char *fileName = nullptr; CallArgs args = CallArgsFromVp(argc, vp);
JSAutoByteString fileNameBytes;
if (argc > 0) { DumpHeapNurseryBehaviour nurseryBehaviour = js::IgnoreNurseryObjects;
Value v = JS_ARGV(cx, vp)[0]; FILE *dumpFile = NULL;
unsigned i = 0;
if (argc > i) {
Value v = args[i];
if (v.isString()) { if (v.isString()) {
JSString *str = v.toString(); JSString *str = v.toString();
bool same = false;
if (!JS_StringEqualsAscii(cx, str, "collectNurseryBeforeDump", &same))
return false;
if (same) {
nurseryBehaviour = js::CollectNurseryBeforeDump;
++i;
}
}
}
if (argc > i) {
Value v = args[i];
if (v.isString()) {
JSString *str = v.toString();
JSAutoByteString fileNameBytes;
if (!fileNameBytes.encodeLatin1(cx, str)) if (!fileNameBytes.encodeLatin1(cx, str))
return false; return false;
fileName = fileNameBytes.ptr(); const char *fileName = fileNameBytes.ptr();
dumpFile = fopen(fileName, "w");
if (!dumpFile) {
JS_ReportError(cx, "can't open %s", fileName);
return false;
}
++i;
} }
} }
FILE *dumpFile; if (i != argc) {
if (!fileName) { JS_ReportError(cx, "bad arguments passed to dumpHeapComplete");
dumpFile = stdout; return false;
} else {
dumpFile = fopen(fileName, "w");
if (!dumpFile) {
JS_ReportError(cx, "can't open %s", fileName);
return false;
}
} }
js::DumpHeapComplete(JS_GetRuntime(cx), dumpFile); js::DumpHeapComplete(JS_GetRuntime(cx), dumpFile ? dumpFile : stdout, nurseryBehaviour);
fclose(dumpFile); if (dumpFile)
fclose(dumpFile);
JS_SET_RVAL(cx, vp, JSVAL_VOID); JS_SET_RVAL(cx, vp, JSVAL_VOID);
return true; return true;
@ -1184,8 +1204,10 @@ static const JSFunctionSpecWithHelp TestingFunctions[] = {
" If true, obj is a proxy of some sort"), " If true, obj is a proxy of some sort"),
JS_FN_HELP("dumpHeapComplete", DumpHeapComplete, 1, 0, JS_FN_HELP("dumpHeapComplete", DumpHeapComplete, 1, 0,
"dumpHeapComplete([filename])", "dumpHeapComplete(['collectNurseryBeforeDump'], [filename])",
" Dump reachable and unreachable objects to a file."), " Dump reachable and unreachable objects to the named file, or to stdout. If\n"
" 'collectNurseryBeforeDump' is specified, a minor GC is performed first,\n"
" otherwise objects in the nursery are ignored."),
JS_FN_HELP("terminate", Terminate, 0, 0, JS_FN_HELP("terminate", Terminate, 0, 0,
"terminate()", "terminate()",

Просмотреть файл

@ -0,0 +1 @@
dumpHeapComplete();

Просмотреть файл

@ -753,6 +753,9 @@ DumpHeapVisitCell(JSRuntime *rt, void *data, void *thing,
static void static void
DumpHeapVisitChild(JSTracer *trc, void **thingp, JSGCTraceKind kind) DumpHeapVisitChild(JSTracer *trc, void **thingp, JSGCTraceKind kind)
{ {
if (gc::IsInsideNursery(trc->runtime, *thingp))
return;
JSDumpHeapTracer *dtrc = static_cast<JSDumpHeapTracer *>(trc); JSDumpHeapTracer *dtrc = static_cast<JSDumpHeapTracer *>(trc);
char buffer[1024]; char buffer[1024];
fprintf(dtrc->output, "> %p %c %s\n", *thingp, MarkDescriptor(*thingp), fprintf(dtrc->output, "> %p %c %s\n", *thingp, MarkDescriptor(*thingp),
@ -762,6 +765,9 @@ DumpHeapVisitChild(JSTracer *trc, void **thingp, JSGCTraceKind kind)
static void static void
DumpHeapVisitRoot(JSTracer *trc, void **thingp, JSGCTraceKind kind) DumpHeapVisitRoot(JSTracer *trc, void **thingp, JSGCTraceKind kind)
{ {
if (gc::IsInsideNursery(trc->runtime, *thingp))
return;
JSDumpHeapTracer *dtrc = static_cast<JSDumpHeapTracer *>(trc); JSDumpHeapTracer *dtrc = static_cast<JSDumpHeapTracer *>(trc);
char buffer[1024]; char buffer[1024];
fprintf(dtrc->output, "%p %c %s\n", *thingp, MarkDescriptor(*thingp), fprintf(dtrc->output, "%p %c %s\n", *thingp, MarkDescriptor(*thingp),
@ -769,10 +775,15 @@ DumpHeapVisitRoot(JSTracer *trc, void **thingp, JSGCTraceKind kind)
} }
void void
js::DumpHeapComplete(JSRuntime *rt, FILE *fp) js::DumpHeapComplete(JSRuntime *rt, FILE *fp, js::DumpHeapNurseryBehaviour nurseryBehaviour)
{ {
JSDumpHeapTracer dtrc(fp); JSDumpHeapTracer dtrc(fp);
#ifdef JSGC_GENERATIONAL
if (nurseryBehaviour == js::CollectNurseryBeforeDump)
MinorGC(rt, JS::gcreason::API);
#endif
JS_TracerInit(&dtrc, rt, DumpHeapVisitRoot); JS_TracerInit(&dtrc, rt, DumpHeapVisitRoot);
dtrc.eagerlyTraceWeakMaps = TraceWeakMapKeysValues; dtrc.eagerlyTraceWeakMaps = TraceWeakMapKeysValues;
TraceRuntime(&dtrc); TraceRuntime(&dtrc);

Просмотреть файл

@ -255,12 +255,17 @@ GetCompartmentZone(JSCompartment *comp);
typedef bool typedef bool
(* PreserveWrapperCallback)(JSContext *cx, JSObject *obj); (* PreserveWrapperCallback)(JSContext *cx, JSObject *obj);
typedef enum {
CollectNurseryBeforeDump,
IgnoreNurseryObjects
} DumpHeapNurseryBehaviour;
/* /*
* Dump the complete object graph of heap-allocated things. * Dump the complete object graph of heap-allocated things.
* fp is the file for the dump output. * fp is the file for the dump output.
*/ */
extern JS_FRIEND_API(void) extern JS_FRIEND_API(void)
DumpHeapComplete(JSRuntime *rt, FILE *fp); DumpHeapComplete(JSRuntime *rt, FILE *fp, DumpHeapNurseryBehaviour nurseryBehaviour);
#ifdef JS_OLD_GETTER_SETTER_METHODS #ifdef JS_OLD_GETTER_SETTER_METHODS
JS_FRIEND_API(bool) obj_defineGetter(JSContext *cx, unsigned argc, JS::Value *vp); JS_FRIEND_API(bool) obj_defineGetter(JSContext *cx, unsigned argc, JS::Value *vp);

Просмотреть файл

@ -968,7 +968,7 @@ CycleCollectedJSRuntime::DeferredFinalize(nsISupports* aSupports)
void void
CycleCollectedJSRuntime::DumpJSHeap(FILE* file) CycleCollectedJSRuntime::DumpJSHeap(FILE* file)
{ {
js::DumpHeapComplete(Runtime(), file); js::DumpHeapComplete(Runtime(), file, js::CollectNurseryBeforeDump);
} }