зеркало из https://github.com/mozilla/gecko-dev.git
Bug 790338 - Add Is*AboutToBeFinalized functions r=billm
--HG-- extra : rebase_source : 629c81772d673eb4f4c7ce45db57f6111468689c
This commit is contained in:
Родитель
1159281622
Коммит
d881fbff05
|
@ -221,6 +221,17 @@ IsMarked(T **thingp)
|
||||||
return (*thingp)->isMarked();
|
return (*thingp)->isMarked();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
static bool
|
||||||
|
IsAboutToBeFinalized(T **thingp)
|
||||||
|
{
|
||||||
|
JS_ASSERT(thingp);
|
||||||
|
JS_ASSERT(*thingp);
|
||||||
|
if (!(*thingp)->compartment()->isGCSweeping())
|
||||||
|
return false;
|
||||||
|
return !(*thingp)->isMarked();
|
||||||
|
}
|
||||||
|
|
||||||
#define DeclMarkerImpl(base, type) \
|
#define DeclMarkerImpl(base, type) \
|
||||||
void \
|
void \
|
||||||
Mark##base(JSTracer *trc, EncapsulatedPtr<type> *thing, const char *name) \
|
Mark##base(JSTracer *trc, EncapsulatedPtr<type> *thing, const char *name) \
|
||||||
|
@ -262,6 +273,16 @@ bool
|
||||||
Is##base##Marked(EncapsulatedPtr<type> *thingp) \
|
Is##base##Marked(EncapsulatedPtr<type> *thingp) \
|
||||||
{ \
|
{ \
|
||||||
return IsMarked<type>(thingp->unsafeGet()); \
|
return IsMarked<type>(thingp->unsafeGet()); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
bool Is##base##AboutToBeFinalized(type **thingp) \
|
||||||
|
{ \
|
||||||
|
return IsAboutToBeFinalized<type>(thingp); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
bool Is##base##AboutToBeFinalized(EncapsulatedPtr<type> *thingp) \
|
||||||
|
{ \
|
||||||
|
return IsAboutToBeFinalized<type>(thingp->unsafeGet()); \
|
||||||
}
|
}
|
||||||
|
|
||||||
DeclMarkerImpl(BaseShape, BaseShape)
|
DeclMarkerImpl(BaseShape, BaseShape)
|
||||||
|
@ -498,6 +519,23 @@ gc::IsValueMarked(Value *v)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
gc::IsValueAboutToBeFinalized(Value *v)
|
||||||
|
{
|
||||||
|
JS_ASSERT(v->isMarkable());
|
||||||
|
bool rv;
|
||||||
|
if (v->isString()) {
|
||||||
|
JSString *str = (JSString *)v->toGCThing();
|
||||||
|
rv = IsAboutToBeFinalized<JSString>(&str);
|
||||||
|
v->setString(str);
|
||||||
|
} else {
|
||||||
|
JSObject *obj = (JSObject *)v->toGCThing();
|
||||||
|
rv = IsAboutToBeFinalized<JSObject>(&obj);
|
||||||
|
v->setObject(*obj);
|
||||||
|
}
|
||||||
|
return rv;
|
||||||
|
}
|
||||||
|
|
||||||
/*** Slot Marking ***/
|
/*** Slot Marking ***/
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -578,6 +616,12 @@ gc::IsCellMarked(Cell **thingp)
|
||||||
return IsMarked<Cell>(thingp);
|
return IsMarked<Cell>(thingp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
gc::IsCellAboutToBeFinalized(Cell **thingp)
|
||||||
|
{
|
||||||
|
return IsAboutToBeFinalized<Cell>(thingp);
|
||||||
|
}
|
||||||
|
|
||||||
/*** Push Mark Stack ***/
|
/*** Push Mark Stack ***/
|
||||||
|
|
||||||
#define JS_COMPARTMENT_ASSERT(rt, thing) \
|
#define JS_COMPARTMENT_ASSERT(rt, thing) \
|
||||||
|
|
|
@ -63,6 +63,20 @@ namespace gc {
|
||||||
*
|
*
|
||||||
* Additionally, the functions MarkObjectRange and MarkObjectRootRange are
|
* Additionally, the functions MarkObjectRange and MarkObjectRootRange are
|
||||||
* defined for marking arrays of object pointers.
|
* defined for marking arrays of object pointers.
|
||||||
|
*
|
||||||
|
* The following functions are provided to test whether a GC thing is marked
|
||||||
|
* under different circumstances:
|
||||||
|
*
|
||||||
|
* IsObjectAboutToBeFinalized(JSObject **thing);
|
||||||
|
* This function is indended to be used in code used to sweep GC things. It
|
||||||
|
* indicates whether the object will will be finialized in the current group
|
||||||
|
* of compartments being swept. Note that this will return false for any
|
||||||
|
* object not in the group of compartments currently being swept, as even if
|
||||||
|
* it is unmarked it may still become marked before it is swept.
|
||||||
|
*
|
||||||
|
* IsObjectMarked(JSObject **thing);
|
||||||
|
* This function is indended to be used in rare cases in code used to mark
|
||||||
|
* GC things. It indicates whether the object is currently marked.
|
||||||
*/
|
*/
|
||||||
#define DeclMarker(base, type) \
|
#define DeclMarker(base, type) \
|
||||||
void Mark##base(JSTracer *trc, EncapsulatedPtr<type> *thing, const char *name); \
|
void Mark##base(JSTracer *trc, EncapsulatedPtr<type> *thing, const char *name); \
|
||||||
|
@ -71,7 +85,9 @@ void Mark##base##Unbarriered(JSTracer *trc, type **thingp, const char *name);
|
||||||
void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr<type> *thing, const char *name); \
|
void Mark##base##Range(JSTracer *trc, size_t len, HeapPtr<type> *thing, const char *name); \
|
||||||
void Mark##base##RootRange(JSTracer *trc, size_t len, type **thing, const char *name); \
|
void Mark##base##RootRange(JSTracer *trc, size_t len, type **thing, const char *name); \
|
||||||
bool Is##base##Marked(type **thingp); \
|
bool Is##base##Marked(type **thingp); \
|
||||||
bool Is##base##Marked(EncapsulatedPtr<type> *thingp);
|
bool Is##base##Marked(EncapsulatedPtr<type> *thingp); \
|
||||||
|
bool Is##base##AboutToBeFinalized(type **thingp); \
|
||||||
|
bool Is##base##AboutToBeFinalized(EncapsulatedPtr<type> *thingp);
|
||||||
|
|
||||||
DeclMarker(BaseShape, BaseShape)
|
DeclMarker(BaseShape, BaseShape)
|
||||||
DeclMarker(BaseShape, UnownedBaseShape)
|
DeclMarker(BaseShape, UnownedBaseShape)
|
||||||
|
@ -164,6 +180,9 @@ MarkTypeRoot(JSTracer *trc, types::Type *v, const char *name);
|
||||||
bool
|
bool
|
||||||
IsValueMarked(Value *v);
|
IsValueMarked(Value *v);
|
||||||
|
|
||||||
|
bool
|
||||||
|
IsValueAboutToBeFinalized(Value *v);
|
||||||
|
|
||||||
/*** Slot Marking ***/
|
/*** Slot Marking ***/
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -262,6 +281,9 @@ Mark(JSTracer *trc, HeapPtr<ion::IonCode> *code, const char *name)
|
||||||
bool
|
bool
|
||||||
IsCellMarked(Cell **thingp);
|
IsCellMarked(Cell **thingp);
|
||||||
|
|
||||||
|
bool
|
||||||
|
IsCellAboutToBeFinalized(Cell **thing);
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
IsMarked(EncapsulatedValue *v)
|
IsMarked(EncapsulatedValue *v)
|
||||||
{
|
{
|
||||||
|
@ -282,11 +304,31 @@ IsMarked(EncapsulatedPtrScript *scriptp)
|
||||||
return IsScriptMarked(scriptp);
|
return IsScriptMarked(scriptp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
IsAboutToBeFinalized(EncapsulatedValue *v)
|
||||||
|
{
|
||||||
|
if (!v->isMarkable())
|
||||||
|
return false;
|
||||||
|
return IsValueAboutToBeFinalized(v->unsafeGet());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
IsAboutToBeFinalized(EncapsulatedPtrObject *objp)
|
||||||
|
{
|
||||||
|
return IsObjectAboutToBeFinalized(objp);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool
|
||||||
|
IsAboutToBeFinalized(EncapsulatedPtrScript *scriptp)
|
||||||
|
{
|
||||||
|
return IsScriptAboutToBeFinalized(scriptp);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef JS_ION
|
#ifdef JS_ION
|
||||||
/* Nonsense to get WeakCache to work with new Marking semantics. */
|
/* Nonsense to get WeakCache to work with new Marking semantics. */
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
IsMarked(const js::ion::VMFunction **vmfunc)
|
IsAboutToBeFinalized(const js::ion::VMFunction **vmfunc)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Preserves entries in the WeakCache<VMFunction, IonCode>
|
* Preserves entries in the WeakCache<VMFunction, IonCode>
|
||||||
|
@ -296,7 +338,7 @@ IsMarked(const js::ion::VMFunction **vmfunc)
|
||||||
}
|
}
|
||||||
|
|
||||||
inline bool
|
inline bool
|
||||||
IsMarked(ReadBarriered<js::ion::IonCode> code)
|
IsAboutToBeFinalized(ReadBarriered<js::ion::IonCode> code)
|
||||||
{
|
{
|
||||||
return IsIonCodeMarked(code.unsafeGet());
|
return IsIonCodeMarked(code.unsafeGet());
|
||||||
}
|
}
|
||||||
|
|
|
@ -2949,9 +2949,9 @@ JS_PUBLIC_API(JSBool)
|
||||||
JS_IsAboutToBeFinalized(void *thing)
|
JS_IsAboutToBeFinalized(void *thing)
|
||||||
{
|
{
|
||||||
gc::Cell *t = static_cast<gc::Cell *>(thing);
|
gc::Cell *t = static_cast<gc::Cell *>(thing);
|
||||||
bool isMarked = IsCellMarked(&t);
|
bool isDying = IsCellAboutToBeFinalized(&t);
|
||||||
JS_ASSERT(t == thing);
|
JS_ASSERT(t == thing);
|
||||||
return !isMarked;
|
return isDying;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
JS_PUBLIC_API(void)
|
||||||
|
|
|
@ -598,10 +598,9 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
|
||||||
sweepInitialShapeTable();
|
sweepInitialShapeTable();
|
||||||
sweepNewTypeObjectTable(newTypeObjects);
|
sweepNewTypeObjectTable(newTypeObjects);
|
||||||
sweepNewTypeObjectTable(lazyTypeObjects);
|
sweepNewTypeObjectTable(lazyTypeObjects);
|
||||||
|
|
||||||
sweepBreakpoints(fop);
|
sweepBreakpoints(fop);
|
||||||
|
|
||||||
if (global_ && !IsObjectMarked(&global_))
|
if (global_ && IsObjectAboutToBeFinalized(&global_))
|
||||||
global_ = NULL;
|
global_ = NULL;
|
||||||
|
|
||||||
#ifdef JS_ION
|
#ifdef JS_ION
|
||||||
|
@ -693,11 +692,11 @@ JSCompartment::sweepCrossCompartmentWrappers()
|
||||||
/* Remove dead wrappers from the table. */
|
/* Remove dead wrappers from the table. */
|
||||||
for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) {
|
for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) {
|
||||||
CrossCompartmentKey key = e.front().key;
|
CrossCompartmentKey key = e.front().key;
|
||||||
bool keyMarked = IsCellMarked(&key.wrapped);
|
bool keyDying = IsCellAboutToBeFinalized(&key.wrapped);
|
||||||
bool valMarked = IsValueMarked(e.front().value.unsafeGet());
|
bool valDying = IsValueAboutToBeFinalized(e.front().value.unsafeGet());
|
||||||
bool dbgMarked = !key.debugger || IsObjectMarked(&key.debugger);
|
bool dbgDying = key.debugger && IsObjectAboutToBeFinalized(&key.debugger);
|
||||||
JS_ASSERT_IF(!keyMarked && valMarked, key.kind == CrossCompartmentKey::StringWrapper);
|
JS_ASSERT_IF(keyDying && !valDying, key.kind == CrossCompartmentKey::StringWrapper);
|
||||||
if (!keyMarked || !valMarked || !dbgMarked)
|
if (keyDying || valDying || dbgDying)
|
||||||
e.removeFront();
|
e.removeFront();
|
||||||
else if (key.wrapped != e.front().key.wrapped || key.debugger != e.front().key.debugger)
|
else if (key.wrapped != e.front().key.wrapped || key.debugger != e.front().key.debugger)
|
||||||
e.rekeyFront(key);
|
e.rekeyFront(key);
|
||||||
|
@ -895,7 +894,7 @@ JSCompartment::sweepBreakpoints(FreeOp *fop)
|
||||||
JSScript *script = i.get<JSScript>();
|
JSScript *script = i.get<JSScript>();
|
||||||
if (!script->hasAnyBreakpointsOrStepMode())
|
if (!script->hasAnyBreakpointsOrStepMode())
|
||||||
continue;
|
continue;
|
||||||
bool scriptGone = !IsScriptMarked(&script);
|
bool scriptGone = IsScriptAboutToBeFinalized(&script);
|
||||||
JS_ASSERT(script == i.get<JSScript>());
|
JS_ASSERT(script == i.get<JSScript>());
|
||||||
for (unsigned i = 0; i < script->length; i++) {
|
for (unsigned i = 0; i < script->length; i++) {
|
||||||
BreakpointSite *site = script->getBreakpointSite(script->code + i);
|
BreakpointSite *site = script->getBreakpointSite(script->code + i);
|
||||||
|
@ -906,7 +905,7 @@ JSCompartment::sweepBreakpoints(FreeOp *fop)
|
||||||
Breakpoint *nextbp;
|
Breakpoint *nextbp;
|
||||||
for (Breakpoint *bp = site->firstBreakpoint(); bp; bp = nextbp) {
|
for (Breakpoint *bp = site->firstBreakpoint(); bp; bp = nextbp) {
|
||||||
nextbp = bp->nextInSite();
|
nextbp = bp->nextInSite();
|
||||||
if (scriptGone || !IsObjectMarked(&bp->debugger->toJSObjectRef()))
|
if (scriptGone || IsObjectAboutToBeFinalized(&bp->debugger->toJSObjectRef()))
|
||||||
bp->destroy(fop);
|
bp->destroy(fop);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -452,7 +452,7 @@ struct JSCompartment
|
||||||
js::ScriptCountsMap *scriptCountsMap;
|
js::ScriptCountsMap *scriptCountsMap;
|
||||||
|
|
||||||
js::DebugScriptMap *debugScriptMap;
|
js::DebugScriptMap *debugScriptMap;
|
||||||
|
|
||||||
#ifdef JS_ION
|
#ifdef JS_ION
|
||||||
private:
|
private:
|
||||||
js::ion::IonCompartment *ionCompartment_;
|
js::ion::IonCompartment *ionCompartment_;
|
||||||
|
|
|
@ -1149,7 +1149,7 @@ JSCompartment::sweepBaseShapeTable()
|
||||||
if (baseShapes.initialized()) {
|
if (baseShapes.initialized()) {
|
||||||
for (BaseShapeSet::Enum e(baseShapes); !e.empty(); e.popFront()) {
|
for (BaseShapeSet::Enum e(baseShapes); !e.empty(); e.popFront()) {
|
||||||
UnownedBaseShape *base = e.front();
|
UnownedBaseShape *base = e.front();
|
||||||
if (!base->isMarked())
|
if (IsBaseShapeAboutToBeFinalized(&base))
|
||||||
e.removeFront();
|
e.removeFront();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1306,12 +1306,12 @@ JSCompartment::sweepInitialShapeTable()
|
||||||
const InitialShapeEntry &entry = e.front();
|
const InitialShapeEntry &entry = e.front();
|
||||||
Shape *shape = entry.shape;
|
Shape *shape = entry.shape;
|
||||||
JSObject *proto = entry.proto.raw();
|
JSObject *proto = entry.proto.raw();
|
||||||
if (!IsShapeMarked(&shape) || (entry.proto.isObject() && !IsObjectMarked(&proto))) {
|
if (IsShapeAboutToBeFinalized(&shape) || (entry.proto.isObject() && IsObjectAboutToBeFinalized(&proto))) {
|
||||||
e.removeFront();
|
e.removeFront();
|
||||||
} else {
|
} else {
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
DebugOnly<JSObject *> parent = shape->getObjectParent();
|
DebugOnly<JSObject *> parent = shape->getObjectParent();
|
||||||
JS_ASSERT(!parent || IsObjectMarked(&parent));
|
JS_ASSERT(!parent || !IsObjectAboutToBeFinalized(&parent));
|
||||||
JS_ASSERT(parent == shape->getObjectParent());
|
JS_ASSERT(parent == shape->getObjectParent());
|
||||||
#endif
|
#endif
|
||||||
if (shape != entry.shape || proto != entry.proto.raw()) {
|
if (shape != entry.shape || proto != entry.proto.raw()) {
|
||||||
|
|
|
@ -220,7 +220,7 @@ WatchpointMap::sweep()
|
||||||
for (Map::Enum e(map); !e.empty(); e.popFront()) {
|
for (Map::Enum e(map); !e.empty(); e.popFront()) {
|
||||||
Map::Entry &entry = e.front();
|
Map::Entry &entry = e.front();
|
||||||
RelocatablePtrObject obj(entry.key.object);
|
RelocatablePtrObject obj(entry.key.object);
|
||||||
if (!IsObjectMarked(&obj)) {
|
if (IsObjectAboutToBeFinalized(&obj)) {
|
||||||
JS_ASSERT(!entry.value.held);
|
JS_ASSERT(!entry.value.held);
|
||||||
e.removeFront();
|
e.removeFront();
|
||||||
} else if (obj != entry.key.object) {
|
} else if (obj != entry.key.object) {
|
||||||
|
|
|
@ -42,9 +42,9 @@ class WeakCache : public HashMap<Key, Value, HashPolicy, AllocPolicy> {
|
||||||
// Checking IsMarked() may update the location of the Key (or Value).
|
// Checking IsMarked() may update the location of the Key (or Value).
|
||||||
// Pass in a stack local, then manually update the backing heap store.
|
// Pass in a stack local, then manually update the backing heap store.
|
||||||
Key k(e.front().key);
|
Key k(e.front().key);
|
||||||
bool isKeyMarked = gc::IsMarked(&k);
|
bool isKeyDying = gc::IsAboutToBeFinalized(&k);
|
||||||
|
|
||||||
if (!isKeyMarked || !gc::IsMarked(e.front().value)) {
|
if (isKeyDying || gc::IsAboutToBeFinalized(e.front().value)) {
|
||||||
e.removeFront();
|
e.removeFront();
|
||||||
} else {
|
} else {
|
||||||
// Potentially update the location of the Key.
|
// Potentially update the location of the Key.
|
||||||
|
@ -60,8 +60,8 @@ class WeakCache : public HashMap<Key, Value, HashPolicy, AllocPolicy> {
|
||||||
for (Range r = Base::all(); !r.empty(); r.popFront()) {
|
for (Range r = Base::all(); !r.empty(); r.popFront()) {
|
||||||
Key k(r.front().key);
|
Key k(r.front().key);
|
||||||
|
|
||||||
JS_ASSERT(gc::IsMarked(&k));
|
JS_ASSERT(!gc::IsAboutToBeFinalized(&k));
|
||||||
JS_ASSERT(gc::IsMarked(r.front().value));
|
JS_ASSERT(!gc::IsAboutToBeFinalized(r.front().value));
|
||||||
|
|
||||||
// Assert that IsMarked() did not perform relocation.
|
// Assert that IsMarked() did not perform relocation.
|
||||||
JS_ASSERT(k == r.front().key);
|
JS_ASSERT(k == r.front().key);
|
||||||
|
|
|
@ -180,7 +180,7 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>, publ
|
||||||
/* Remove all entries whose keys remain unmarked. */
|
/* Remove all entries whose keys remain unmarked. */
|
||||||
for (Enum e(*this); !e.empty(); e.popFront()) {
|
for (Enum e(*this); !e.empty(); e.popFront()) {
|
||||||
Key k(e.front().key);
|
Key k(e.front().key);
|
||||||
if (!gc::IsMarked(&k))
|
if (gc::IsAboutToBeFinalized(&k))
|
||||||
e.removeFront();
|
e.removeFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -192,8 +192,8 @@ class WeakMap : public HashMap<Key, Value, HashPolicy, RuntimeAllocPolicy>, publ
|
||||||
for (Range r = Base::all(); !r.empty(); r.popFront()) {
|
for (Range r = Base::all(); !r.empty(); r.popFront()) {
|
||||||
Key k(r.front().key);
|
Key k(r.front().key);
|
||||||
Value v(r.front().value);
|
Value v(r.front().value);
|
||||||
JS_ASSERT(gc::IsMarked(&k));
|
JS_ASSERT(!gc::IsAboutToBeFinalized(&k));
|
||||||
JS_ASSERT(gc::IsMarked(&v));
|
JS_ASSERT(!gc::IsAboutToBeFinalized(&v));
|
||||||
JS_ASSERT(k == r.front().key);
|
JS_ASSERT(k == r.front().key);
|
||||||
JS_ASSERT(v == r.front().value);
|
JS_ASSERT(v == r.front().value);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1528,7 +1528,7 @@ Debugger::sweepAll(FreeOp *fop)
|
||||||
for (JSCList *p = &rt->debuggerList; (p = JS_NEXT_LINK(p)) != &rt->debuggerList;) {
|
for (JSCList *p = &rt->debuggerList; (p = JS_NEXT_LINK(p)) != &rt->debuggerList;) {
|
||||||
Debugger *dbg = Debugger::fromLinks(p);
|
Debugger *dbg = Debugger::fromLinks(p);
|
||||||
|
|
||||||
if (!IsObjectMarked(&dbg->object)) {
|
if (IsObjectAboutToBeFinalized(&dbg->object)) {
|
||||||
/*
|
/*
|
||||||
* dbg is being GC'd. Detach it from its debuggees. The debuggee
|
* dbg is being GC'd. Detach it from its debuggees. The debuggee
|
||||||
* might be GC'd too. Since detaching requires access to both
|
* might be GC'd too. Since detaching requires access to both
|
||||||
|
@ -1544,7 +1544,7 @@ Debugger::sweepAll(FreeOp *fop)
|
||||||
GlobalObjectSet &debuggees = (*c)->getDebuggees();
|
GlobalObjectSet &debuggees = (*c)->getDebuggees();
|
||||||
for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) {
|
for (GlobalObjectSet::Enum e(debuggees); !e.empty(); e.popFront()) {
|
||||||
GlobalObject *global = e.front();
|
GlobalObject *global = e.front();
|
||||||
if (!IsObjectMarked(&global))
|
if (IsObjectAboutToBeFinalized(&global))
|
||||||
detachAllDebuggersFromGlobal(fop, global, &e);
|
detachAllDebuggersFromGlobal(fop, global, &e);
|
||||||
else if (global != e.front())
|
else if (global != e.front())
|
||||||
e.rekeyFront(global);
|
e.rekeyFront(global);
|
||||||
|
|
|
@ -1559,7 +1559,7 @@ DebugScopes::sweep()
|
||||||
* creating an uncollectable cycle with suspended generator frames.
|
* creating an uncollectable cycle with suspended generator frames.
|
||||||
*/
|
*/
|
||||||
for (MissingScopeMap::Enum e(missingScopes); !e.empty(); e.popFront()) {
|
for (MissingScopeMap::Enum e(missingScopes); !e.empty(); e.popFront()) {
|
||||||
if (!IsObjectMarked(e.front().value.unsafeGet()))
|
if (IsObjectAboutToBeFinalized(e.front().value.unsafeGet()))
|
||||||
e.removeFront();
|
e.removeFront();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1571,7 +1571,7 @@ DebugScopes::sweep()
|
||||||
* Scopes can be finalized when a debugger-synthesized ScopeObject is
|
* Scopes can be finalized when a debugger-synthesized ScopeObject is
|
||||||
* no longer reachable via its DebugScopeObject.
|
* no longer reachable via its DebugScopeObject.
|
||||||
*/
|
*/
|
||||||
if (!IsObjectMarked(&scope)) {
|
if (IsObjectAboutToBeFinalized(&scope)) {
|
||||||
e.removeFront();
|
e.removeFront();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -1583,7 +1583,7 @@ DebugScopes::sweep()
|
||||||
*/
|
*/
|
||||||
if (JSGenerator *gen = fp->maybeSuspendedGenerator(rt)) {
|
if (JSGenerator *gen = fp->maybeSuspendedGenerator(rt)) {
|
||||||
JS_ASSERT(gen->state == JSGEN_NEWBORN || gen->state == JSGEN_OPEN);
|
JS_ASSERT(gen->state == JSGEN_NEWBORN || gen->state == JSGEN_OPEN);
|
||||||
if (!IsObjectMarked(&gen->obj)) {
|
if (IsObjectAboutToBeFinalized(&gen->obj)) {
|
||||||
e.removeFront();
|
e.removeFront();
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче