mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1056411 - Part 1: Remove DebugFromC and clean up compartment debug mode logic. (r=jimb)
This commit is contained in:
parent
3b9122894c
commit
9ca5cfff0a
@ -540,7 +540,6 @@ struct CompartmentStats
|
||||
macro(Other, NotLiveGCThing, compartmentTables) \
|
||||
macro(Other, NotLiveGCThing, crossCompartmentWrappersTable) \
|
||||
macro(Other, NotLiveGCThing, regexpCompartment) \
|
||||
macro(Other, NotLiveGCThing, debuggeesSet) \
|
||||
macro(Other, NotLiveGCThing, savedStacksSet)
|
||||
|
||||
CompartmentStats()
|
||||
|
@ -58,7 +58,7 @@ JSCompartment::JSCompartment(Zone *zone, const JS::CompartmentOptions &options =
|
||||
selfHostingScriptSource(nullptr),
|
||||
gcIncomingGrayPointers(nullptr),
|
||||
gcWeakMapList(nullptr),
|
||||
debugModeBits(runtime_->debugMode ? DebugFromC : 0),
|
||||
debugModeBits(0),
|
||||
rngState(0),
|
||||
watchpointMap(nullptr),
|
||||
scriptCountsMap(nullptr),
|
||||
@ -113,7 +113,7 @@ JSCompartment::init(JSContext *cx)
|
||||
if (!savedStacks_.init())
|
||||
return false;
|
||||
|
||||
return debuggees.init(0);
|
||||
return true;
|
||||
}
|
||||
|
||||
jit::JitRuntime *
|
||||
@ -594,8 +594,11 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
|
||||
sweepCallsiteClones();
|
||||
savedStacks_.sweep(rt);
|
||||
|
||||
if (global_ && IsObjectAboutToBeFinalized(global_.unsafeGet()))
|
||||
if (global_ && IsObjectAboutToBeFinalized(global_.unsafeGet())) {
|
||||
if (debugMode())
|
||||
Debugger::detachAllDebuggersFromGlobal(fop, global_);
|
||||
global_.set(nullptr);
|
||||
}
|
||||
|
||||
if (selfHostingScriptSource &&
|
||||
IsObjectAboutToBeFinalized((JSObject **) selfHostingScriptSource.unsafeGet()))
|
||||
@ -628,17 +631,6 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
|
||||
ni->unlink();
|
||||
ni = next;
|
||||
}
|
||||
|
||||
/* For each debuggee being GC'd, detach it from all its debuggers. */
|
||||
for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) {
|
||||
GlobalObject *global = e.front();
|
||||
if (IsObjectAboutToBeFinalized(&global)) {
|
||||
// See infallibility note above.
|
||||
Debugger::detachAllDebuggersFromGlobal(fop, global, &e);
|
||||
} else if (global != e.front()) {
|
||||
e.rekeyFront(global);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -847,41 +839,6 @@ JSCompartment::ensureDelazifyScriptsForDebugMode(JSContext *cx)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSCompartment::setDebugModeFromC(JSContext *cx, bool b, AutoDebugModeInvalidation &invalidate)
|
||||
{
|
||||
bool enabledBefore = debugMode();
|
||||
bool enabledAfter = (debugModeBits & DebugModeFromMask & ~DebugFromC) || b;
|
||||
|
||||
// Enabling debug mode from C (vs of from JS) can only be done when no
|
||||
// scripts from the target compartment are on the stack.
|
||||
//
|
||||
// We do allow disabling debug mode while scripts are on the stack. In
|
||||
// that case the debug-mode code for those scripts remains, so subsequently
|
||||
// hooks may be called erroneously, even though debug mode is supposedly
|
||||
// off, and we have to live with it.
|
||||
bool onStack = false;
|
||||
if (enabledBefore != enabledAfter) {
|
||||
onStack = hasScriptsOnStack();
|
||||
if (b && onStack) {
|
||||
JS_ReportErrorNumber(cx, js_GetErrorMessage, nullptr, JSMSG_DEBUG_NOT_IDLE);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
debugModeBits = (debugModeBits & ~DebugFromC) | (b ? DebugFromC : 0);
|
||||
JS_ASSERT(debugMode() == enabledAfter);
|
||||
if (enabledBefore != enabledAfter) {
|
||||
// Pass in a nullptr cx to not bother recompiling for JSD1, since
|
||||
// we're still enforcing the idle-stack invariant here.
|
||||
if (!updateJITForDebugMode(nullptr, invalidate))
|
||||
return false;
|
||||
if (!enabledAfter)
|
||||
DebugScopes::onCompartmentLeaveDebugMode(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSCompartment::updateJITForDebugMode(JSContext *maybecx, AutoDebugModeInvalidation &invalidate)
|
||||
{
|
||||
@ -893,76 +850,47 @@ JSCompartment::updateJITForDebugMode(JSContext *maybecx, AutoDebugModeInvalidati
|
||||
}
|
||||
|
||||
bool
|
||||
JSCompartment::addDebuggee(JSContext *cx, JS::Handle<js::GlobalObject *> global)
|
||||
JSCompartment::enterDebugMode(JSContext *cx)
|
||||
{
|
||||
AutoDebugModeInvalidation invalidate(this);
|
||||
return addDebuggee(cx, global, invalidate);
|
||||
return enterDebugMode(cx, invalidate);
|
||||
}
|
||||
|
||||
bool
|
||||
JSCompartment::addDebuggee(JSContext *cx,
|
||||
JS::Handle<GlobalObject *> global,
|
||||
AutoDebugModeInvalidation &invalidate)
|
||||
JSCompartment::enterDebugMode(JSContext *cx, AutoDebugModeInvalidation &invalidate)
|
||||
{
|
||||
bool wasEnabled = debugMode();
|
||||
if (!debuggees.put(global)) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
if (!debugMode()) {
|
||||
debugModeBits |= DebugMode;
|
||||
if (!updateJITForDebugMode(cx, invalidate))
|
||||
return false;
|
||||
}
|
||||
debugModeBits |= DebugFromJS;
|
||||
if (!wasEnabled && !updateJITForDebugMode(cx, invalidate))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
JSCompartment::removeDebuggee(JSContext *cx,
|
||||
js::GlobalObject *global,
|
||||
js::GlobalObjectSet::Enum *debuggeesEnum)
|
||||
JSCompartment::leaveDebugMode(JSContext *cx)
|
||||
{
|
||||
AutoDebugModeInvalidation invalidate(this);
|
||||
return removeDebuggee(cx, global, invalidate, debuggeesEnum);
|
||||
return leaveDebugMode(cx, invalidate);
|
||||
}
|
||||
|
||||
bool
|
||||
JSCompartment::removeDebuggee(JSContext *cx,
|
||||
js::GlobalObject *global,
|
||||
AutoDebugModeInvalidation &invalidate,
|
||||
js::GlobalObjectSet::Enum *debuggeesEnum)
|
||||
JSCompartment::leaveDebugMode(JSContext *cx, AutoDebugModeInvalidation &invalidate)
|
||||
{
|
||||
bool wasEnabled = debugMode();
|
||||
removeDebuggeeUnderGC(cx->runtime()->defaultFreeOp(), global, invalidate, debuggeesEnum);
|
||||
if (wasEnabled && !debugMode() && !updateJITForDebugMode(cx, invalidate))
|
||||
return false;
|
||||
if (debugMode()) {
|
||||
leaveDebugModeUnderGC();
|
||||
if (!updateJITForDebugMode(cx, invalidate))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::removeDebuggeeUnderGC(FreeOp *fop,
|
||||
js::GlobalObject *global,
|
||||
js::GlobalObjectSet::Enum *debuggeesEnum)
|
||||
JSCompartment::leaveDebugModeUnderGC()
|
||||
{
|
||||
AutoDebugModeInvalidation invalidate(this);
|
||||
removeDebuggeeUnderGC(fop, global, invalidate, debuggeesEnum);
|
||||
}
|
||||
|
||||
void
|
||||
JSCompartment::removeDebuggeeUnderGC(FreeOp *fop,
|
||||
js::GlobalObject *global,
|
||||
AutoDebugModeInvalidation &invalidate,
|
||||
js::GlobalObjectSet::Enum *debuggeesEnum)
|
||||
{
|
||||
bool wasEnabled = debugMode();
|
||||
JS_ASSERT(debuggees.has(global));
|
||||
if (debuggeesEnum)
|
||||
debuggeesEnum->removeFront();
|
||||
else
|
||||
debuggees.remove(global);
|
||||
|
||||
if (debuggees.empty()) {
|
||||
debugModeBits &= ~DebugFromJS;
|
||||
if (wasEnabled && !debugMode())
|
||||
DebugScopes::onCompartmentLeaveDebugMode(this);
|
||||
if (debugMode()) {
|
||||
debugModeBits &= ~DebugMode;
|
||||
DebugScopes::onCompartmentLeaveDebugMode(this);
|
||||
}
|
||||
}
|
||||
|
||||
@ -985,7 +913,6 @@ JSCompartment::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
|
||||
size_t *compartmentTables,
|
||||
size_t *crossCompartmentWrappersArg,
|
||||
size_t *regexpCompartment,
|
||||
size_t *debuggeesSet,
|
||||
size_t *savedStacksSet)
|
||||
{
|
||||
*compartmentObject += mallocSizeOf(this);
|
||||
@ -997,7 +924,6 @@ JSCompartment::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf,
|
||||
+ lazyTypeObjects.sizeOfExcludingThis(mallocSizeOf);
|
||||
*crossCompartmentWrappersArg += crossCompartmentWrappers.sizeOfExcludingThis(mallocSizeOf);
|
||||
*regexpCompartment += regExps.sizeOfExcludingThis(mallocSizeOf);
|
||||
*debuggeesSet += debuggees.sizeOfExcludingThis(mallocSizeOf);
|
||||
*savedStacksSet += savedStacks_.sizeOfExcludingThis(mallocSizeOf);
|
||||
}
|
||||
|
||||
|
@ -234,7 +234,6 @@ struct JSCompartment
|
||||
size_t *compartmentTables,
|
||||
size_t *crossCompartmentWrappers,
|
||||
size_t *regexpCompartment,
|
||||
size_t *debuggeesSet,
|
||||
size_t *savedStacksSet);
|
||||
|
||||
/*
|
||||
@ -295,14 +294,11 @@ struct JSCompartment
|
||||
|
||||
private:
|
||||
enum {
|
||||
DebugFromC = 1 << 0,
|
||||
DebugFromJS = 1 << 1,
|
||||
DebugNeedDelazification = 1 << 2
|
||||
DebugMode = 1 << 0,
|
||||
DebugNeedDelazification = 1 << 1
|
||||
};
|
||||
|
||||
static const unsigned DebugModeFromMask = DebugFromC | DebugFromJS;
|
||||
|
||||
unsigned debugModeBits; // see debugMode() below
|
||||
unsigned debugModeBits;
|
||||
|
||||
public:
|
||||
JSCompartment(JS::Zone *zone, const JS::CompartmentOptions &options);
|
||||
@ -381,32 +377,25 @@ struct JSCompartment
|
||||
/* Random number generator state, used by jsmath.cpp. */
|
||||
uint64_t rngState;
|
||||
|
||||
private:
|
||||
/*
|
||||
* Weak reference to each global in this compartment that is a debuggee.
|
||||
* Each global has its own list of debuggers.
|
||||
*/
|
||||
js::GlobalObjectSet debuggees;
|
||||
|
||||
private:
|
||||
JSCompartment *thisForCtor() { return this; }
|
||||
|
||||
// Only called from {enter,leave}DebugMode.
|
||||
bool updateJITForDebugMode(JSContext *maybecx, js::AutoDebugModeInvalidation &invalidate);
|
||||
|
||||
public:
|
||||
/*
|
||||
* There are dueling APIs for debug mode. It can be enabled or disabled via
|
||||
* JS_SetDebugModeForCompartment. It is automatically enabled and disabled
|
||||
* by Debugger objects. Therefore debugModeBits has the DebugFromC bit set
|
||||
* if the C API wants debug mode and the DebugFromJS bit set if debuggees
|
||||
* is non-empty.
|
||||
*
|
||||
* When toggling on, DebugNeedDelazification is set to signal that
|
||||
* Debugger methods which depend on seeing all scripts (like findScripts)
|
||||
* need to delazify the scripts in the compartment first.
|
||||
*/
|
||||
// True if this compartment's global is a debuggee of some Debugger
|
||||
// object.
|
||||
bool debugMode() const {
|
||||
return !!(debugModeBits & DebugModeFromMask);
|
||||
return !!(debugModeBits & DebugMode);
|
||||
}
|
||||
|
||||
bool enterDebugMode(JSContext *cx);
|
||||
bool enterDebugMode(JSContext *cx, js::AutoDebugModeInvalidation &invalidate);
|
||||
bool leaveDebugMode(JSContext *cx);
|
||||
bool leaveDebugMode(JSContext *cx, js::AutoDebugModeInvalidation &invalidate);
|
||||
void leaveDebugModeUnderGC();
|
||||
|
||||
/* True if any scripts from this compartment are on the JS stack. */
|
||||
bool hasScriptsOnStack();
|
||||
|
||||
@ -424,29 +413,6 @@ struct JSCompartment
|
||||
*/
|
||||
bool ensureDelazifyScriptsForDebugMode(JSContext *cx);
|
||||
|
||||
private:
|
||||
|
||||
/* This is called only when debugMode() has just toggled. */
|
||||
bool updateJITForDebugMode(JSContext *maybecx, js::AutoDebugModeInvalidation &invalidate);
|
||||
|
||||
public:
|
||||
js::GlobalObjectSet &getDebuggees() { return debuggees; }
|
||||
bool addDebuggee(JSContext *cx, JS::Handle<js::GlobalObject *> global);
|
||||
bool addDebuggee(JSContext *cx, JS::Handle<js::GlobalObject *> global,
|
||||
js::AutoDebugModeInvalidation &invalidate);
|
||||
bool removeDebuggee(JSContext *cx, js::GlobalObject *global,
|
||||
js::GlobalObjectSet::Enum *debuggeesEnum = nullptr);
|
||||
bool removeDebuggee(JSContext *cx, js::GlobalObject *global,
|
||||
js::AutoDebugModeInvalidation &invalidate,
|
||||
js::GlobalObjectSet::Enum *debuggeesEnum = nullptr);
|
||||
void removeDebuggeeUnderGC(js::FreeOp *fop, js::GlobalObject *global,
|
||||
js::GlobalObjectSet::Enum *debuggeesEnum = nullptr);
|
||||
void removeDebuggeeUnderGC(js::FreeOp *fop, js::GlobalObject *global,
|
||||
js::AutoDebugModeInvalidation &invalidate,
|
||||
js::GlobalObjectSet::Enum *debuggeesEnum = nullptr);
|
||||
bool setDebugModeFromC(JSContext *cx, bool b,
|
||||
js::AutoDebugModeInvalidation &invalidate);
|
||||
|
||||
void clearBreakpointsIn(js::FreeOp *fop, js::Debugger *dbg, JS::HandleObject handler);
|
||||
|
||||
private:
|
||||
|
@ -17,7 +17,7 @@ js::Debugger::onLeaveFrame(JSContext *cx, AbstractFramePtr frame, bool ok)
|
||||
/* Traps must be cleared from eval frames, see slowPathOnLeaveFrame. */
|
||||
bool evalTraps = frame.isEvalFrame() &&
|
||||
frame.script()->hasAnyBreakpointsOrStepMode();
|
||||
if (!cx->compartment()->getDebuggees().empty() || evalTraps)
|
||||
if (cx->compartment()->debugMode() || evalTraps)
|
||||
ok = slowPathOnLeaveFrame(cx, frame, ok);
|
||||
return ok;
|
||||
}
|
||||
|
@ -1177,23 +1177,21 @@ Debugger::slowPathOnNewScript(JSContext *cx, HandleScript script, GlobalObject *
|
||||
JS_ASSERT(script->compileAndGo() == !!compileAndGoGlobal);
|
||||
|
||||
/*
|
||||
* Build the list of recipients. For compile-and-go scripts, this is the
|
||||
* same as the generic Debugger::dispatchHook code, but non-compile-and-go
|
||||
* scripts are not tied to particular globals. We deliver them to every
|
||||
* debugger observing any global in the script's compartment.
|
||||
* Build the list of recipients based on the debuggers observing the
|
||||
* script's compartment.
|
||||
*
|
||||
* TODO bug 1064079 will simplify this logic. The meaning of
|
||||
* compile-and-go has changed over the years and is no longer relevant to
|
||||
* Debugger.
|
||||
*/
|
||||
AutoValueVector triggered(cx);
|
||||
if (script->compileAndGo()) {
|
||||
if (GlobalObject::DebuggerVector *debuggers = compileAndGoGlobal->getDebuggers()) {
|
||||
if (!AddNewScriptRecipients(debuggers, script, &triggered))
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
GlobalObjectSet &debuggees = script->compartment()->getDebuggees();
|
||||
for (GlobalObjectSet::Range r = debuggees.all(); !r.empty(); r.popFront()) {
|
||||
if (!AddNewScriptRecipients(r.front()->getDebuggers(), script, &triggered))
|
||||
return;
|
||||
}
|
||||
GlobalObject::DebuggerVector *debuggers =
|
||||
(script->compileAndGo()
|
||||
? compileAndGoGlobal->getDebuggers()
|
||||
: script->compartment()->maybeGlobal()->getDebuggers());
|
||||
if (debuggers) {
|
||||
if (!AddNewScriptRecipients(debuggers, script, &triggered))
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1593,13 +1591,10 @@ Debugger::markAllIteratively(GCMarker *trc)
|
||||
*/
|
||||
JSRuntime *rt = trc->runtime();
|
||||
for (CompartmentsIter c(rt, SkipAtoms); !c.done(); c.next()) {
|
||||
GlobalObjectSet &debuggees = c->getDebuggees();
|
||||
for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) {
|
||||
GlobalObject *global = e.front();
|
||||
if (c->debugMode()) {
|
||||
GlobalObject *global = c->maybeGlobal();
|
||||
if (!IsObjectMarked(&global))
|
||||
continue;
|
||||
else if (global != e.front())
|
||||
e.rekeyFront(global);
|
||||
|
||||
/*
|
||||
* Every debuggee has at least one debugger, so in this case
|
||||
@ -1750,20 +1745,19 @@ Debugger::sweepAll(FreeOp *fop)
|
||||
// We can't recompile on-stack scripts here, and we
|
||||
// can only toggle debug mode to off, so we use an
|
||||
// infallible variant of removeDebuggeeGlobal.
|
||||
dbg->removeDebuggeeGlobalUnderGC(fop, e.front(), nullptr, &e);
|
||||
dbg->removeDebuggeeGlobalUnderGC(fop, e.front(), &e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Debugger::detachAllDebuggersFromGlobal(FreeOp *fop, GlobalObject *global,
|
||||
GlobalObjectSet::Enum *compartmentEnum)
|
||||
Debugger::detachAllDebuggersFromGlobal(FreeOp *fop, GlobalObject *global)
|
||||
{
|
||||
const GlobalObject::DebuggerVector *debuggers = global->getDebuggers();
|
||||
JS_ASSERT(!debuggers->empty());
|
||||
while (!debuggers->empty())
|
||||
debuggers->back()->removeDebuggeeGlobalUnderGC(fop, global, compartmentEnum, nullptr);
|
||||
debuggers->back()->removeDebuggeeGlobalUnderGC(fop, global, nullptr);
|
||||
}
|
||||
|
||||
/* static */ void
|
||||
@ -2144,7 +2138,7 @@ Debugger::removeDebuggee(JSContext *cx, unsigned argc, Value *vp)
|
||||
if (!global)
|
||||
return false;
|
||||
if (dbg->debuggees.has(global)) {
|
||||
if (!dbg->removeDebuggeeGlobal(cx, global, nullptr, nullptr))
|
||||
if (!dbg->removeDebuggeeGlobal(cx, global, nullptr))
|
||||
return false;
|
||||
}
|
||||
args.rval().setUndefined();
|
||||
@ -2158,7 +2152,7 @@ Debugger::removeAllDebuggees(JSContext *cx, unsigned argc, Value *vp)
|
||||
|
||||
for (GlobalObjectSet::Enum e(dbg->debuggees); !e.empty(); e.popFront()) {
|
||||
Rooted<GlobalObject *> global(cx, e.front());
|
||||
if (!dbg->removeDebuggeeGlobal(cx, global, nullptr, &e))
|
||||
if (!dbg->removeDebuggeeGlobal(cx, global, &e))
|
||||
return false;
|
||||
}
|
||||
|
||||
@ -2332,11 +2326,11 @@ Debugger::addDebuggeeGlobal(JSContext *cx,
|
||||
}
|
||||
|
||||
/*
|
||||
* Find all compartments containing debuggers debugging global objects
|
||||
* in c. Add those compartments to visited.
|
||||
* Find all compartments containing debuggers debugging c's global
|
||||
* object. Add those compartments to visited.
|
||||
*/
|
||||
for (GlobalObjectSet::Range r = c->getDebuggees().all(); !r.empty(); r.popFront()) {
|
||||
GlobalObject::DebuggerVector *v = r.front()->getDebuggers();
|
||||
if (c->debugMode()) {
|
||||
GlobalObject::DebuggerVector *v = c->maybeGlobal()->getDebuggers();
|
||||
for (Debugger **p = v->begin(); p != v->end(); p++) {
|
||||
JSCompartment *next = (*p)->object->compartment();
|
||||
if (Find(visited, next) == visited.end() && !visited.append(next))
|
||||
@ -2375,7 +2369,7 @@ Debugger::addDebuggeeGlobal(JSContext *cx,
|
||||
} else {
|
||||
if (global->getDebuggers()->length() > 1)
|
||||
return true;
|
||||
if (debuggeeCompartment->addDebuggee(cx, global, invalidate))
|
||||
if (debuggeeCompartment->enterDebugMode(cx, invalidate))
|
||||
return true;
|
||||
|
||||
/* Maintain consistency on error. */
|
||||
@ -2394,18 +2388,13 @@ Debugger::addDebuggeeGlobal(JSContext *cx,
|
||||
|
||||
void
|
||||
Debugger::cleanupDebuggeeGlobalBeforeRemoval(FreeOp *fop, GlobalObject *global,
|
||||
AutoDebugModeInvalidation &invalidate,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnum)
|
||||
{
|
||||
/*
|
||||
* Each debuggee is in two HashSets: one for its compartment and one for
|
||||
* its debugger (this). The caller might be enumerating either set; if so,
|
||||
* use HashSet::Enum::removeFront rather than HashSet::remove below, to
|
||||
* avoid invalidating the live enumerator.
|
||||
* The caller might have found global by enumerating this->debuggees; if
|
||||
* so, use HashSet::Enum::removeFront rather than HashSet::remove below,
|
||||
* to avoid invalidating the live enumerator.
|
||||
*/
|
||||
JS_ASSERT(global->compartment()->getDebuggees().has(global));
|
||||
JS_ASSERT_IF(compartmentEnum, compartmentEnum->front() == global);
|
||||
JS_ASSERT(debuggees.has(global));
|
||||
JS_ASSERT_IF(debugEnum, debugEnum->front() == global);
|
||||
|
||||
@ -2465,45 +2454,31 @@ Debugger::cleanupDebuggeeGlobalBeforeRemoval(FreeOp *fop, GlobalObject *global,
|
||||
|
||||
bool
|
||||
Debugger::removeDebuggeeGlobal(JSContext *cx, Handle<GlobalObject *> global,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnum)
|
||||
{
|
||||
AutoDebugModeInvalidation invalidate(global->compartment());
|
||||
return removeDebuggeeGlobal(cx, global, invalidate, compartmentEnum, debugEnum);
|
||||
return removeDebuggeeGlobal(cx, global, invalidate, debugEnum);
|
||||
}
|
||||
|
||||
bool
|
||||
Debugger::removeDebuggeeGlobal(JSContext *cx, Handle<GlobalObject *> global,
|
||||
AutoDebugModeInvalidation &invalidate,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnum)
|
||||
{
|
||||
cleanupDebuggeeGlobalBeforeRemoval(cx->runtime()->defaultFreeOp(), global,
|
||||
invalidate, compartmentEnum, debugEnum);
|
||||
cleanupDebuggeeGlobalBeforeRemoval(cx->runtime()->defaultFreeOp(), global, debugEnum);
|
||||
|
||||
// The debuggee needs to be removed from the compartment last to save a root.
|
||||
if (global->getDebuggers()->empty())
|
||||
return global->compartment()->removeDebuggee(cx, global, invalidate, compartmentEnum);
|
||||
return global->compartment()->leaveDebugMode(cx, invalidate);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
Debugger::removeDebuggeeGlobalUnderGC(FreeOp *fop, GlobalObject *global,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnum)
|
||||
{
|
||||
AutoDebugModeInvalidation invalidate(global->compartment());
|
||||
removeDebuggeeGlobalUnderGC(fop, global, invalidate, compartmentEnum, debugEnum);
|
||||
}
|
||||
|
||||
void
|
||||
Debugger::removeDebuggeeGlobalUnderGC(FreeOp *fop, GlobalObject *global,
|
||||
AutoDebugModeInvalidation &invalidate,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnum)
|
||||
{
|
||||
cleanupDebuggeeGlobalBeforeRemoval(fop, global, invalidate, compartmentEnum, debugEnum);
|
||||
cleanupDebuggeeGlobalBeforeRemoval(fop, global, debugEnum);
|
||||
|
||||
/*
|
||||
* The debuggee needs to be removed from the compartment last, as this can
|
||||
@ -2511,7 +2486,7 @@ Debugger::removeDebuggeeGlobalUnderGC(FreeOp *fop, GlobalObject *global,
|
||||
* global cannot be rooted on the stack without a cx.
|
||||
*/
|
||||
if (global->getDebuggers()->empty())
|
||||
global->compartment()->removeDebuggeeUnderGC(fop, global, invalidate, compartmentEnum);
|
||||
global->compartment()->leaveDebugModeUnderGC();
|
||||
}
|
||||
|
||||
static inline ScriptSourceObject *GetSourceReferent(JSObject *obj);
|
||||
|
@ -265,22 +265,13 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||
bool addDebuggeeGlobal(JSContext *cx, Handle<GlobalObject*> obj,
|
||||
AutoDebugModeInvalidation &invalidate);
|
||||
void cleanupDebuggeeGlobalBeforeRemoval(FreeOp *fop, GlobalObject *global,
|
||||
AutoDebugModeInvalidation &invalidate,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnu);
|
||||
GlobalObjectSet::Enum *debugEnum);
|
||||
bool removeDebuggeeGlobal(JSContext *cx, Handle<GlobalObject *> global,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnum);
|
||||
bool removeDebuggeeGlobal(JSContext *cx, Handle<GlobalObject *> global,
|
||||
AutoDebugModeInvalidation &invalidate,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnum);
|
||||
void removeDebuggeeGlobalUnderGC(FreeOp *fop, GlobalObject *global,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnum);
|
||||
void removeDebuggeeGlobalUnderGC(FreeOp *fop, GlobalObject *global,
|
||||
AutoDebugModeInvalidation &invalidate,
|
||||
GlobalObjectSet::Enum *compartmentEnum,
|
||||
GlobalObjectSet::Enum *debugEnum);
|
||||
|
||||
/*
|
||||
@ -457,8 +448,7 @@ class Debugger : private mozilla::LinkedListElement<Debugger>
|
||||
static bool markAllIteratively(GCMarker *trc);
|
||||
static void markAll(JSTracer *trc);
|
||||
static void sweepAll(FreeOp *fop);
|
||||
static void detachAllDebuggersFromGlobal(FreeOp *fop, GlobalObject *global,
|
||||
GlobalObjectSet::Enum *compartmentEnum);
|
||||
static void detachAllDebuggersFromGlobal(FreeOp *fop, GlobalObject *global);
|
||||
static void findCompartmentEdges(JS::Zone *v, gc::ComponentFinder<JS::Zone> &finder);
|
||||
|
||||
static inline JSTrapStatus onEnterFrame(JSContext *cx, AbstractFramePtr frame,
|
||||
@ -740,7 +730,7 @@ Debugger::observesGlobal(GlobalObject *global) const
|
||||
JSTrapStatus
|
||||
Debugger::onEnterFrame(JSContext *cx, AbstractFramePtr frame, MutableHandleValue vp)
|
||||
{
|
||||
if (cx->compartment()->getDebuggees().empty())
|
||||
if (!cx->compartment()->debugMode())
|
||||
return JSTRAP_CONTINUE;
|
||||
return slowPathOnEnterFrame(cx, frame, vp);
|
||||
}
|
||||
@ -748,17 +738,17 @@ Debugger::onEnterFrame(JSContext *cx, AbstractFramePtr frame, MutableHandleValue
|
||||
JSTrapStatus
|
||||
Debugger::onDebuggerStatement(JSContext *cx, MutableHandleValue vp)
|
||||
{
|
||||
return cx->compartment()->getDebuggees().empty()
|
||||
? JSTRAP_CONTINUE
|
||||
: dispatchHook(cx, vp, OnDebuggerStatement);
|
||||
return cx->compartment()->debugMode()
|
||||
? dispatchHook(cx, vp, OnDebuggerStatement)
|
||||
: JSTRAP_CONTINUE;
|
||||
}
|
||||
|
||||
JSTrapStatus
|
||||
Debugger::onExceptionUnwind(JSContext *cx, MutableHandleValue vp)
|
||||
{
|
||||
return cx->compartment()->getDebuggees().empty()
|
||||
? JSTRAP_CONTINUE
|
||||
: dispatchHook(cx, vp, OnExceptionUnwind);
|
||||
return cx->compartment()->debugMode()
|
||||
? dispatchHook(cx, vp, OnExceptionUnwind)
|
||||
: JSTRAP_CONTINUE;
|
||||
}
|
||||
|
||||
void
|
||||
@ -772,7 +762,7 @@ Debugger::onNewScript(JSContext *cx, HandleScript script, GlobalObject *compileA
|
||||
!script->selfHosted(),
|
||||
script->compartment()->firedOnNewGlobalObject);
|
||||
JS_ASSERT_IF(!script->compileAndGo(), !compileAndGoGlobal);
|
||||
if (!script->compartment()->getDebuggees().empty())
|
||||
if (script->compartment()->debugMode())
|
||||
slowPathOnNewScript(cx, script, compileAndGoGlobal);
|
||||
}
|
||||
|
||||
|
@ -338,7 +338,6 @@ StatsCompartmentCallback(JSRuntime *rt, void *data, JSCompartment *compartment)
|
||||
&cStats.compartmentTables,
|
||||
&cStats.crossCompartmentWrappersTable,
|
||||
&cStats.regexpCompartment,
|
||||
&cStats.debuggeesSet,
|
||||
&cStats.savedStacksSet);
|
||||
}
|
||||
|
||||
|
@ -98,9 +98,6 @@ js::DebugExceptionUnwind(JSContext *cx, AbstractFramePtr frame, jsbytecode *pc)
|
||||
{
|
||||
JS_ASSERT(cx->compartment()->debugMode());
|
||||
|
||||
if (cx->compartment()->getDebuggees().empty())
|
||||
return JSTRAP_CONTINUE;
|
||||
|
||||
/* Call debugger throw hook if set. */
|
||||
RootedValue rval(cx);
|
||||
JSTrapStatus status = Debugger::onExceptionUnwind(cx, &rval);
|
||||
|
@ -175,7 +175,6 @@ JSRuntime::JSRuntime(JSRuntime *parentRuntime)
|
||||
#ifdef NIGHTLY_BUILD
|
||||
assertOnScriptEntryHook_(nullptr),
|
||||
#endif
|
||||
debugMode(false),
|
||||
spsProfiler(thisFromCtor()),
|
||||
profilingScripts(false),
|
||||
suppressProfilerSampling(false),
|
||||
|
@ -1014,9 +1014,6 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||
js::AssertOnScriptEntryHook assertOnScriptEntryHook_;
|
||||
#endif
|
||||
|
||||
/* If true, new compartments are initially in debug mode. */
|
||||
bool debugMode;
|
||||
|
||||
/* SPS profiling metadata */
|
||||
js::SPSProfiler spsProfiler;
|
||||
|
||||
|
@ -2212,10 +2212,6 @@ ReportCompartmentStats(const JS::CompartmentStats &cStats,
|
||||
cStats.regexpCompartment,
|
||||
"The regexp compartment and regexp data.");
|
||||
|
||||
ZCREPORT_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("debuggees-set"),
|
||||
cStats.debuggeesSet,
|
||||
"The debuggees set.");
|
||||
|
||||
if (sundriesGCHeap > 0) {
|
||||
// We deliberately don't use ZCREPORT_GC_BYTES here.
|
||||
REPORT_GC_BYTES(cJSPathPrefix + NS_LITERAL_CSTRING("sundries/gc-heap"),
|
||||
|
Loading…
Reference in New Issue
Block a user