Bug 758278 - Sweep crossCompartmentWrappers of all compartments, not only GCed ones. r=billm

This commit is contained in:
Till Schneidereit 2012-05-24 19:04:44 +02:00
parent eaca72e8fd
commit f21b878154
3 changed files with 29 additions and 25 deletions

View File

@ -372,18 +372,6 @@ JSCompartment::markCrossCompartmentWrappers(JSTracer *trc)
MarkValueRoot(trc, &call, "cross-compartment wrapper");
JS_ASSERT(call == GetProxyCall(wrapper));
}
} else {
/*
* Strings don't have a private pointer to mark, so we use the
* wrapper map key. (This does not work for wrappers because, in the
* case of Location objects, the wrapper map key is not the same as
* the proxy private slot. If we only marked the wrapper map key, we
* would miss same-compartment wrappers for Location objects.)
*/
JS_ASSERT(v.isString());
Value v = e.front().key;
MarkValueRoot(trc, &v, "cross-compartment wrapper");
JS_ASSERT(v == e.front().key);
}
}
}
@ -463,17 +451,7 @@ JSCompartment::discardJitCode(FreeOp *fop)
void
JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
{
/* Remove dead wrappers from the table. */
for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) {
Value key = e.front().key;
bool keyMarked = IsValueMarked(&key);
bool valMarked = IsValueMarked(e.front().value.unsafeGet());
JS_ASSERT_IF(!keyMarked && valMarked, key.isString());
if (!keyMarked || !valMarked)
e.removeFront();
else if (key != e.front().key)
e.rekeyFront(key);
}
sweepCrossCompartmentWrappers();
/* Remove dead references held weakly by the compartment. */
@ -551,6 +529,27 @@ JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
active = false;
}
/*
* Remove dead wrappers from the table. We must sweep all compartments, since
* string entries in the crossCompartmentWrappers table are not marked during
* markCrossCompartmentWrappers.
*/
void
JSCompartment::sweepCrossCompartmentWrappers()
{
/* Remove dead wrappers from the table. */
for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront()) {
Value key = e.front().key;
bool keyMarked = IsValueMarked(&key);
bool valMarked = IsValueMarked(e.front().value.unsafeGet());
JS_ASSERT_IF(!keyMarked && valMarked, key.isString());
if (!keyMarked || !valMarked)
e.removeFront();
else if (key != e.front().key)
e.rekeyFront(key);
}
}
void
JSCompartment::purge()
{

View File

@ -262,6 +262,7 @@ struct JSCompartment
void markTypes(JSTracer *trc);
void discardJitCode(js::FreeOp *fop);
void sweep(js::FreeOp *fop, bool releaseTypes);
void sweepCrossCompartmentWrappers();
void purge();
void setGCLastBytes(size_t lastBytes, size_t lastMallocBytes, js::JSGCInvocationKind gckind);

View File

@ -3255,8 +3255,12 @@ SweepPhase(JSRuntime *rt, JSGCInvocationKind gckind, bool *startBackgroundSweep)
gcstats::AutoPhase ap(rt->gcStats, gcstats::PHASE_SWEEP_COMPARTMENTS);
bool releaseTypes = ReleaseObservedTypes(rt);
for (GCCompartmentsIter c(rt); !c.done(); c.next())
c->sweep(&fop, releaseTypes);
for (CompartmentsIter c(rt); !c.done(); c.next()) {
if (c->isCollecting())
c->sweep(&fop, releaseTypes);
else
c->sweepCrossCompartmentWrappers();
}
}
{