From 97ba04bf95606b409b1b3035504a41c274ecffe2 Mon Sep 17 00:00:00 2001 From: Shu-yu Guo Date: Mon, 26 Jan 2015 18:26:25 -0800 Subject: [PATCH] Bug 1119579 - Don't GC while iterating compartments in findAllGlobals. r=sfink, a=abillings --- js/src/vm/Debugger.cpp | 56 ++++++++++++++++++++++++++++++-------------------- 1 file changed, 34 insertions(+), 22 deletions(-) diff --git a/js/src/vm/Debugger.cpp b/js/src/vm/Debugger.cpp index 27e993d..a8decef 100644 --- a/js/src/vm/Debugger.cpp +++ b/js/src/vm/Debugger.cpp @@ -2825,37 +2825,49 @@ Debugger::findAllGlobals(JSContext *cx, unsigned argc, Value *vp) { THIS_DEBUGGER(cx, argc, vp, "findAllGlobals", args, dbg); - RootedObject result(cx, NewDenseEmptyArray(cx)); - if (!result) - return false; + AutoObjectVector globals(cx); - for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next()) { - if (c->options().invisibleToDebugger()) - continue; + { + // Accumulate the list of globals before wrapping them, because + // wrapping can GC and collect compartments from under us, while + // iterating. - c->zone()->scheduledForDestruction = false; + for (CompartmentsIter c(cx->runtime(), SkipAtoms); !c.done(); c.next()) { + if (c->options().invisibleToDebugger()) + continue; - GlobalObject *global = c->maybeGlobal(); + c->zone()->scheduledForDestruction = false; - if (cx->runtime()->isSelfHostingGlobal(global)) - continue; + GlobalObject *global = c->maybeGlobal(); - if (global) { - /* - * We pulled |global| out of nowhere, so it's possible that it was - * marked gray by XPConnect. Since we're now exposing it to JS code, - * we need to mark it black. - */ - JS::ExposeGCThingToActiveJS(global, JSTRACE_OBJECT); + if (cx->runtime()->isSelfHostingGlobal(global)) + continue; - RootedValue globalValue(cx, ObjectValue(*global)); - if (!dbg->wrapDebuggeeValue(cx, &globalValue)) - return false; - if (!NewbornArrayPush(cx, result, globalValue)) - return false; + if (global) { + /* + * We pulled |global| out of nowhere, so it's possible that it was + * marked gray by XPConnect. Since we're now exposing it to JS code, + * we need to mark it black. + */ + JS::ExposeGCThingToActiveJS(global, JSTRACE_OBJECT); + if (!globals.append(global)) + return false; + } } } + RootedObject result(cx, NewDenseEmptyArray(cx)); + if (!result) + return false; + + for (size_t i = 0; i < globals.length(); i++) { + RootedValue globalValue(cx, ObjectValue(*globals[i])); + if (!dbg->wrapDebuggeeValue(cx, &globalValue)) + return false; + if (!NewbornArrayPush(cx, result, globalValue)) + return false; + } + args.rval().setObject(*result); return true; } -- 2.2.1