mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Sweep compartments when no objects live in them (bug 639270, r=gregor).
This commit is contained in:
parent
d21d12b55b
commit
e787b97701
@ -1333,7 +1333,7 @@ JS_TransplantObject(JSContext *cx, JSObject *origobj, JSObject *target)
|
|||||||
// types of security wrappers based on whether the new compartment
|
// types of security wrappers based on whether the new compartment
|
||||||
// is same origin with them.
|
// is same origin with them.
|
||||||
Value targetv = ObjectValue(*obj);
|
Value targetv = ObjectValue(*obj);
|
||||||
WrapperVector &vector = cx->runtime->compartments;
|
CompartmentVector &vector = cx->runtime->compartments;
|
||||||
AutoValueVector toTransplant(cx);
|
AutoValueVector toTransplant(cx);
|
||||||
if (!toTransplant.reserve(vector.length()))
|
if (!toTransplant.reserve(vector.length()))
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -1427,7 +1427,7 @@ js_TransplantObjectWithWrapper(JSContext *cx,
|
|||||||
// and not |origwrapper|. They need to be updated to point at the new
|
// and not |origwrapper|. They need to be updated to point at the new
|
||||||
// location object.
|
// location object.
|
||||||
Value targetv = ObjectValue(*targetobj);
|
Value targetv = ObjectValue(*targetobj);
|
||||||
WrapperVector &vector = cx->runtime->compartments;
|
CompartmentVector &vector = cx->runtime->compartments;
|
||||||
AutoValueVector toTransplant(cx);
|
AutoValueVector toTransplant(cx);
|
||||||
if (!toTransplant.reserve(vector.length()))
|
if (!toTransplant.reserve(vector.length()))
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -3081,6 +3081,23 @@ JS_NewGlobalObject(JSContext *cx, JSClass *clasp)
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AutoHoldCompartment {
|
||||||
|
public:
|
||||||
|
explicit AutoHoldCompartment(JSCompartment *compartment JS_GUARD_OBJECT_NOTIFIER_PARAM)
|
||||||
|
: holdp(&compartment->hold)
|
||||||
|
{
|
||||||
|
JS_GUARD_OBJECT_NOTIFIER_INIT;
|
||||||
|
*holdp = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
~AutoHoldCompartment() {
|
||||||
|
*holdp = false;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
bool *holdp;
|
||||||
|
JS_DECL_USE_GUARD_OBJECT_NOTIFIER
|
||||||
|
};
|
||||||
|
|
||||||
JS_PUBLIC_API(JSObject *)
|
JS_PUBLIC_API(JSObject *)
|
||||||
JS_NewCompartmentAndGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals)
|
JS_NewCompartmentAndGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *principals)
|
||||||
{
|
{
|
||||||
@ -3089,6 +3106,8 @@ JS_NewCompartmentAndGlobalObject(JSContext *cx, JSClass *clasp, JSPrincipals *pr
|
|||||||
if (!compartment)
|
if (!compartment)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
|
AutoHoldCompartment hold(compartment);
|
||||||
|
|
||||||
JSCompartment *saved = cx->compartment;
|
JSCompartment *saved = cx->compartment;
|
||||||
cx->compartment = compartment;
|
cx->compartment = compartment;
|
||||||
JSObject *obj = JS_NewGlobalObject(cx, clasp);
|
JSObject *obj = JS_NewGlobalObject(cx, clasp);
|
||||||
|
@ -988,7 +988,7 @@ typedef void
|
|||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
typedef js::Vector<JSCompartment *, 0, js::SystemAllocPolicy> WrapperVector;
|
typedef js::Vector<JSCompartment *, 0, js::SystemAllocPolicy> CompartmentVector;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1000,7 +1000,7 @@ struct JSRuntime {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* List of compartments (protected by the GC lock). */
|
/* List of compartments (protected by the GC lock). */
|
||||||
js::WrapperVector compartments;
|
js::CompartmentVector compartments;
|
||||||
|
|
||||||
/* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */
|
/* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */
|
||||||
JSRuntimeState state;
|
JSRuntimeState state;
|
||||||
|
@ -66,6 +66,7 @@ JSCompartment::JSCompartment(JSRuntime *rt)
|
|||||||
gcBytes(0),
|
gcBytes(0),
|
||||||
gcTriggerBytes(0),
|
gcTriggerBytes(0),
|
||||||
gcLastBytes(0),
|
gcLastBytes(0),
|
||||||
|
hold(false),
|
||||||
data(NULL),
|
data(NULL),
|
||||||
active(false),
|
active(false),
|
||||||
#ifdef JS_METHODJIT
|
#ifdef JS_METHODJIT
|
||||||
@ -82,8 +83,7 @@ JSCompartment::JSCompartment(JSRuntime *rt)
|
|||||||
#if ENABLE_YARR_JIT
|
#if ENABLE_YARR_JIT
|
||||||
regExpAllocator(NULL),
|
regExpAllocator(NULL),
|
||||||
#endif
|
#endif
|
||||||
mathCache(NULL),
|
mathCache(NULL)
|
||||||
marked(false)
|
|
||||||
{
|
{
|
||||||
JS_INIT_CLIST(&scripts);
|
JS_INIT_CLIST(&scripts);
|
||||||
|
|
||||||
@ -447,35 +447,23 @@ ScriptPoolDestroyed(JSContext *cx, mjit::JITScript *jit,
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* This method marks pointers that cross compartment boundaries. It should be
|
* This method marks pointers that cross compartment boundaries. It should be
|
||||||
* called only by per-compartment GCs, since full GCs naturally follow pointers
|
* called only for per-compartment GCs, since full GCs naturally follow pointers
|
||||||
* across compartments.
|
* across compartments.
|
||||||
*/
|
*/
|
||||||
void
|
void
|
||||||
JSCompartment::markCrossCompartment(JSTracer *trc)
|
JSCompartment::markCrossCompartmentWrappers(JSTracer *trc)
|
||||||
{
|
{
|
||||||
|
JS_ASSERT(trc->context->runtime->gcCurrentCompartment);
|
||||||
|
|
||||||
for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront())
|
for (WrapperMap::Enum e(crossCompartmentWrappers); !e.empty(); e.popFront())
|
||||||
MarkValue(trc, e.front().key, "cross-compartment wrapper");
|
MarkValue(trc, e.front().key, "cross-compartment wrapper");
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
JSCompartment::mark(JSTracer *trc)
|
|
||||||
{
|
|
||||||
if (IS_GC_MARKING_TRACER(trc)) {
|
|
||||||
JSRuntime *rt = trc->context->runtime;
|
|
||||||
|
|
||||||
if (rt->gcCurrentCompartment && rt->gcCurrentCompartment != this)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (marked)
|
|
||||||
return;
|
|
||||||
marked = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
|
JSCompartment::sweep(JSContext *cx, uint32 releaseInterval)
|
||||||
{
|
{
|
||||||
chunk = NULL;
|
chunk = NULL;
|
||||||
|
|
||||||
/* 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()) {
|
||||||
JS_ASSERT_IF(IsAboutToBeFinalized(cx, e.front().key.toGCThing()) &&
|
JS_ASSERT_IF(IsAboutToBeFinalized(cx, e.front().key.toGCThing()) &&
|
||||||
|
@ -381,6 +381,8 @@ struct JS_FRIEND_API(JSCompartment) {
|
|||||||
size_t gcTriggerBytes;
|
size_t gcTriggerBytes;
|
||||||
size_t gcLastBytes;
|
size_t gcLastBytes;
|
||||||
|
|
||||||
|
bool hold;
|
||||||
|
|
||||||
#ifdef JS_GCMETER
|
#ifdef JS_GCMETER
|
||||||
js::gc::JSGCArenaStats compartmentStats[js::gc::FINALIZE_LIMIT];
|
js::gc::JSGCArenaStats compartmentStats[js::gc::FINALIZE_LIMIT];
|
||||||
#endif
|
#endif
|
||||||
@ -451,10 +453,7 @@ struct JS_FRIEND_API(JSCompartment) {
|
|||||||
bool init();
|
bool init();
|
||||||
|
|
||||||
/* Mark cross-compartment wrappers. */
|
/* Mark cross-compartment wrappers. */
|
||||||
void markCrossCompartment(JSTracer *trc);
|
void markCrossCompartmentWrappers(JSTracer *trc);
|
||||||
|
|
||||||
/* Mark this compartment's local roots. */
|
|
||||||
void mark(JSTracer *trc);
|
|
||||||
|
|
||||||
bool wrap(JSContext *cx, js::Value *vp);
|
bool wrap(JSContext *cx, js::Value *vp);
|
||||||
bool wrap(JSContext *cx, JSString **strp);
|
bool wrap(JSContext *cx, JSString **strp);
|
||||||
@ -481,8 +480,6 @@ struct JS_FRIEND_API(JSCompartment) {
|
|||||||
|
|
||||||
js::MathCache *allocMathCache(JSContext *cx);
|
js::MathCache *allocMathCache(JSContext *cx);
|
||||||
|
|
||||||
bool marked;
|
|
||||||
|
|
||||||
typedef js::HashMap<jsbytecode*,
|
typedef js::HashMap<jsbytecode*,
|
||||||
size_t,
|
size_t,
|
||||||
js::DefaultHasher<jsbytecode*>,
|
js::DefaultHasher<jsbytecode*>,
|
||||||
@ -496,9 +493,6 @@ struct JS_FRIEND_API(JSCompartment) {
|
|||||||
return mathCache ? mathCache : allocMathCache(cx);
|
return mathCache ? mathCache : allocMathCache(cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool isMarked() { return marked; }
|
|
||||||
void clearMark() { marked = false; }
|
|
||||||
|
|
||||||
size_t backEdgeCount(jsbytecode *pc) const;
|
size_t backEdgeCount(jsbytecode *pc) const;
|
||||||
size_t incBackEdgeCount(jsbytecode *pc);
|
size_t incBackEdgeCount(jsbytecode *pc);
|
||||||
};
|
};
|
||||||
|
@ -1633,9 +1633,6 @@ MarkContext(JSTracer *trc, JSContext *acx)
|
|||||||
js_TraceSharpMap(trc, &acx->sharpObjectMap);
|
js_TraceSharpMap(trc, &acx->sharpObjectMap);
|
||||||
|
|
||||||
MarkValue(trc, acx->iterValue, "iterValue");
|
MarkValue(trc, acx->iterValue, "iterValue");
|
||||||
|
|
||||||
if (acx->compartment)
|
|
||||||
acx->compartment->mark(trc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_REQUIRES_STACK void
|
JS_REQUIRES_STACK void
|
||||||
@ -1724,8 +1721,6 @@ MarkRuntime(JSTracer *trc)
|
|||||||
while (JSContext *acx = js_ContextIterator(rt, JS_TRUE, &iter))
|
while (JSContext *acx = js_ContextIterator(rt, JS_TRUE, &iter))
|
||||||
MarkContext(trc, acx);
|
MarkContext(trc, acx);
|
||||||
|
|
||||||
rt->atomsCompartment->mark(trc);
|
|
||||||
|
|
||||||
#ifdef JS_TRACER
|
#ifdef JS_TRACER
|
||||||
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
|
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
|
||||||
(*c)->traceMonitor.mark(trc);
|
(*c)->traceMonitor.mark(trc);
|
||||||
@ -2187,13 +2182,8 @@ SweepCompartments(JSContext *cx, JSGCInvocationKind gckind)
|
|||||||
while (read < end) {
|
while (read < end) {
|
||||||
JSCompartment *compartment = *read++;
|
JSCompartment *compartment = *read++;
|
||||||
|
|
||||||
/*
|
if (!compartment->hold &&
|
||||||
* Unmarked compartments containing marked objects don't get deleted,
|
(compartment->arenaListsAreEmpty() || gckind == GC_LAST_CONTEXT)) {
|
||||||
* except when LAST_CONTEXT GC is performed.
|
|
||||||
*/
|
|
||||||
if ((!compartment->isMarked() && compartment->arenaListsAreEmpty()) ||
|
|
||||||
gckind == GC_LAST_CONTEXT)
|
|
||||||
{
|
|
||||||
JS_ASSERT(compartment->freeLists.isEmpty());
|
JS_ASSERT(compartment->freeLists.isEmpty());
|
||||||
if (callback)
|
if (callback)
|
||||||
(void) callback(cx, compartment, JSCOMPARTMENT_DESTROY);
|
(void) callback(cx, compartment, JSCOMPARTMENT_DESTROY);
|
||||||
@ -2268,7 +2258,6 @@ MarkAndSweepCompartment(JSContext *cx, JSCompartment *comp, JSGCInvocationKind g
|
|||||||
JS_ASSERT(!rt->gcRegenShapes);
|
JS_ASSERT(!rt->gcRegenShapes);
|
||||||
JS_ASSERT(gckind != GC_LAST_CONTEXT);
|
JS_ASSERT(gckind != GC_LAST_CONTEXT);
|
||||||
JS_ASSERT(comp != rt->atomsCompartment);
|
JS_ASSERT(comp != rt->atomsCompartment);
|
||||||
JS_ASSERT(!comp->isMarked());
|
|
||||||
JS_ASSERT(comp->rt->gcMode == JSGC_MODE_COMPARTMENT);
|
JS_ASSERT(comp->rt->gcMode == JSGC_MODE_COMPARTMENT);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2284,9 +2273,7 @@ MarkAndSweepCompartment(JSContext *cx, JSCompartment *comp, JSGCInvocationKind g
|
|||||||
r.front()->clearMarkBitmap();
|
r.front()->clearMarkBitmap();
|
||||||
|
|
||||||
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
|
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
|
||||||
(*c)->markCrossCompartment(&gcmarker);
|
(*c)->markCrossCompartmentWrappers(&gcmarker);
|
||||||
|
|
||||||
comp->mark(&gcmarker);
|
|
||||||
|
|
||||||
MarkRuntime(&gcmarker);
|
MarkRuntime(&gcmarker);
|
||||||
|
|
||||||
@ -2384,8 +2371,6 @@ MarkAndSweepCompartment(JSContext *cx, JSCompartment *comp, JSGCInvocationKind g
|
|||||||
ExpireGCChunks(rt);
|
ExpireGCChunks(rt);
|
||||||
TIMESTAMP(sweepDestroyEnd);
|
TIMESTAMP(sweepDestroyEnd);
|
||||||
|
|
||||||
comp->clearMark();
|
|
||||||
|
|
||||||
if (rt->gcCallback)
|
if (rt->gcCallback)
|
||||||
(void) rt->gcCallback(cx, JSGC_FINALIZE_END);
|
(void) rt->gcCallback(cx, JSGC_FINALIZE_END);
|
||||||
}
|
}
|
||||||
@ -2523,9 +2508,6 @@ MarkAndSweep(JSContext *cx, JSGCInvocationKind gckind GCTIMER_PARAM)
|
|||||||
ExpireGCChunks(rt);
|
ExpireGCChunks(rt);
|
||||||
TIMESTAMP(sweepDestroyEnd);
|
TIMESTAMP(sweepDestroyEnd);
|
||||||
|
|
||||||
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
|
|
||||||
(*c)->clearMark();
|
|
||||||
|
|
||||||
if (rt->gcCallback)
|
if (rt->gcCallback)
|
||||||
(void) rt->gcCallback(cx, JSGC_FINALIZE_END);
|
(void) rt->gcCallback(cx, JSGC_FINALIZE_END);
|
||||||
#ifdef DEBUG_srcnotesize
|
#ifdef DEBUG_srcnotesize
|
||||||
@ -2736,9 +2718,6 @@ GCUntilDone(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind GCTIM
|
|||||||
|
|
||||||
AutoGCSession gcsession(cx);
|
AutoGCSession gcsession(cx);
|
||||||
|
|
||||||
for (JSCompartment **c = rt->compartments.begin(); c != rt->compartments.end(); ++c)
|
|
||||||
JS_ASSERT(!(*c)->isMarked());
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* We should not be depending on cx->compartment in the GC, so set it to
|
* We should not be depending on cx->compartment in the GC, so set it to
|
||||||
* NULL to look for violations.
|
* NULL to look for violations.
|
||||||
|
@ -6509,11 +6509,6 @@ js_TraceObject(JSTracer *trc, JSObject *obj)
|
|||||||
|
|
||||||
obj->trace(trc);
|
obj->trace(trc);
|
||||||
|
|
||||||
if (obj->getClass()->flags & JSCLASS_IS_GLOBAL) {
|
|
||||||
JSCompartment *compartment = obj->getCompartment();
|
|
||||||
compartment->mark(trc);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NB: clasp->mark could mutate something (which would be a bug, but we are
|
* NB: clasp->mark could mutate something (which would be a bug, but we are
|
||||||
* defensive), so don't hoist this above calling clasp->mark.
|
* defensive), so don't hoist this above calling clasp->mark.
|
||||||
|
@ -2561,7 +2561,7 @@ nsXPConnect::CheckForDebugMode(JSRuntime *rt) {
|
|||||||
} adc(cx);
|
} adc(cx);
|
||||||
JSAutoRequest ar(cx);
|
JSAutoRequest ar(cx);
|
||||||
|
|
||||||
js::WrapperVector &vector = rt->compartments;
|
js::CompartmentVector &vector = rt->compartments;
|
||||||
for (JSCompartment **p = vector.begin(); p != vector.end(); ++p) {
|
for (JSCompartment **p = vector.begin(); p != vector.end(); ++p) {
|
||||||
JSCompartment *comp = *p;
|
JSCompartment *comp = *p;
|
||||||
if (!comp->principals) {
|
if (!comp->principals) {
|
||||||
|
Loading…
Reference in New Issue
Block a user