mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
bug 713916 - JS API to shrink GC buffers. r=wmccloskey
This commit is contained in:
parent
d75b0d6c5e
commit
ac8ad79e00
@ -1592,13 +1592,13 @@ JSRuntime::onOutOfMemory(void *p, size_t nbytes, JSContext *cx)
|
|||||||
* Retry when we are done with the background sweeping and have stopped
|
* Retry when we are done with the background sweeping and have stopped
|
||||||
* all the allocations and released the empty GC chunks.
|
* all the allocations and released the empty GC chunks.
|
||||||
*/
|
*/
|
||||||
{
|
ShrinkGCBuffers(this);
|
||||||
#ifdef JS_THREADSAFE
|
#ifdef JS_THREADSAFE
|
||||||
|
{
|
||||||
AutoLockGC lock(this);
|
AutoLockGC lock(this);
|
||||||
gcHelperThread.waitBackgroundSweepOrAllocEnd();
|
gcHelperThread.waitBackgroundSweepOrAllocEnd();
|
||||||
#endif
|
|
||||||
gcChunkPool.expireAndFree(this, true);
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
if (!p)
|
if (!p)
|
||||||
p = OffTheBooks::malloc_(nbytes);
|
p = OffTheBooks::malloc_(nbytes);
|
||||||
else if (p == reinterpret_cast<void *>(1))
|
else if (p == reinterpret_cast<void *>(1))
|
||||||
|
@ -125,12 +125,18 @@ JS_NewObjectWithUniqueType(JSContext *cx, JSClass *clasp, JSObject *proto, JSObj
|
|||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
|
|
||||||
JS_PUBLIC_API(void)
|
JS_FRIEND_API(void)
|
||||||
JS_ShrinkingGC(JSContext *cx)
|
JS_ShrinkingGC(JSContext *cx)
|
||||||
{
|
{
|
||||||
js_GC(cx, NULL, GC_SHRINK, gcstats::PUBLIC_API);
|
js_GC(cx, NULL, GC_SHRINK, gcstats::PUBLIC_API);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
JS_FRIEND_API(void)
|
||||||
|
JS_ShrinkGCBuffers(JSRuntime *rt)
|
||||||
|
{
|
||||||
|
ShrinkGCBuffers(rt);
|
||||||
|
}
|
||||||
|
|
||||||
JS_FRIEND_API(JSPrincipals *)
|
JS_FRIEND_API(JSPrincipals *)
|
||||||
JS_GetCompartmentPrincipals(JSCompartment *compartment)
|
JS_GetCompartmentPrincipals(JSCompartment *compartment)
|
||||||
{
|
{
|
||||||
|
@ -73,6 +73,9 @@ JS_ObjectCountDynamicSlots(JSObject *obj);
|
|||||||
extern JS_FRIEND_API(void)
|
extern JS_FRIEND_API(void)
|
||||||
JS_ShrinkingGC(JSContext *cx);
|
JS_ShrinkingGC(JSContext *cx);
|
||||||
|
|
||||||
|
extern JS_FRIEND_API(void)
|
||||||
|
JS_ShrinkGCBuffers(JSRuntime *rt);
|
||||||
|
|
||||||
extern JS_FRIEND_API(size_t)
|
extern JS_FRIEND_API(size_t)
|
||||||
JS_GetE4XObjectsCreated(JSContext *cx);
|
JS_GetE4XObjectsCreated(JSContext *cx);
|
||||||
|
|
||||||
|
@ -2423,28 +2423,53 @@ GCHelperThread::threadLoop()
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool
|
bool
|
||||||
GCHelperThread::prepareForBackgroundSweep(JSContext *cx)
|
GCHelperThread::prepareForBackgroundSweep()
|
||||||
{
|
{
|
||||||
JS_ASSERT(cx->runtime == rt);
|
|
||||||
JS_ASSERT(state == IDLE);
|
JS_ASSERT(state == IDLE);
|
||||||
size_t maxArenaLists = MAX_BACKGROUND_FINALIZE_KINDS * rt->compartments.length();
|
size_t maxArenaLists = MAX_BACKGROUND_FINALIZE_KINDS * rt->compartments.length();
|
||||||
if (!finalizeVector.reserve(maxArenaLists))
|
return finalizeVector.reserve(maxArenaLists);
|
||||||
return false;
|
|
||||||
context = cx;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Must be called with the GC lock taken. */
|
/* Must be called with the GC lock taken. */
|
||||||
inline void
|
void
|
||||||
GCHelperThread::startBackgroundSweep(bool shouldShrink)
|
GCHelperThread::startBackgroundSweep(JSContext *cx, bool shouldShrink)
|
||||||
{
|
{
|
||||||
/* The caller takes the GC lock. */
|
/* The caller takes the GC lock. */
|
||||||
JS_ASSERT(state == IDLE);
|
JS_ASSERT(state == IDLE);
|
||||||
|
JS_ASSERT(cx);
|
||||||
|
JS_ASSERT(!finalizationContext);
|
||||||
|
finalizationContext = cx;
|
||||||
shrinkFlag = shouldShrink;
|
shrinkFlag = shouldShrink;
|
||||||
state = SWEEPING;
|
state = SWEEPING;
|
||||||
PR_NotifyCondVar(wakeup);
|
PR_NotifyCondVar(wakeup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Must be called with the GC lock taken. */
|
||||||
|
void
|
||||||
|
GCHelperThread::startBackgroundShrink()
|
||||||
|
{
|
||||||
|
switch (state) {
|
||||||
|
case IDLE:
|
||||||
|
JS_ASSERT(!finalizationContext);
|
||||||
|
shrinkFlag = true;
|
||||||
|
state = SWEEPING;
|
||||||
|
PR_NotifyCondVar(wakeup);
|
||||||
|
break;
|
||||||
|
case SWEEPING:
|
||||||
|
shrinkFlag = true;
|
||||||
|
break;
|
||||||
|
case ALLOCATING:
|
||||||
|
case CANCEL_ALLOCATION:
|
||||||
|
/*
|
||||||
|
* If we have started background allocation there is nothing to
|
||||||
|
* shrink.
|
||||||
|
*/
|
||||||
|
break;
|
||||||
|
case SHUTDOWN:
|
||||||
|
JS_NOT_REACHED("No shrink on shutdown");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Must be called with the GC lock taken. */
|
/* Must be called with the GC lock taken. */
|
||||||
void
|
void
|
||||||
GCHelperThread::waitBackgroundSweepEnd()
|
GCHelperThread::waitBackgroundSweepEnd()
|
||||||
@ -2496,9 +2521,8 @@ GCHelperThread::replenishAndFreeLater(void *ptr)
|
|||||||
void
|
void
|
||||||
GCHelperThread::doSweep()
|
GCHelperThread::doSweep()
|
||||||
{
|
{
|
||||||
JS_ASSERT(context);
|
if (JSContext *cx = finalizationContext) {
|
||||||
|
finalizationContext = NULL;
|
||||||
{
|
|
||||||
AutoUnlockGC unlock(rt);
|
AutoUnlockGC unlock(rt);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -2506,11 +2530,9 @@ GCHelperThread::doSweep()
|
|||||||
* finalizeObjects.
|
* finalizeObjects.
|
||||||
*/
|
*/
|
||||||
for (ArenaHeader **i = finalizeVector.begin(); i != finalizeVector.end(); ++i)
|
for (ArenaHeader **i = finalizeVector.begin(); i != finalizeVector.end(); ++i)
|
||||||
ArenaLists::backgroundFinalize(context, *i);
|
ArenaLists::backgroundFinalize(cx, *i);
|
||||||
finalizeVector.resize(0);
|
finalizeVector.resize(0);
|
||||||
|
|
||||||
context = NULL;
|
|
||||||
|
|
||||||
if (freeCursor) {
|
if (freeCursor) {
|
||||||
void **array = freeCursorEnd - FREE_ARRAY_LENGTH;
|
void **array = freeCursorEnd - FREE_ARRAY_LENGTH;
|
||||||
freeElementsAndArray(array, freeCursor);
|
freeElementsAndArray(array, freeCursor);
|
||||||
@ -2525,7 +2547,18 @@ GCHelperThread::doSweep()
|
|||||||
freeVector.resize(0);
|
freeVector.resize(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
ExpireChunksAndArenas(rt, shouldShrink());
|
bool shrinking = shrinkFlag;
|
||||||
|
ExpireChunksAndArenas(rt, shrinking);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The main thread may have called ShrinkGCBuffers while
|
||||||
|
* ExpireChunksAndArenas(rt, false) was running, so we recheck the flag
|
||||||
|
* afterwards.
|
||||||
|
*/
|
||||||
|
if (!shrinking && shrinkFlag) {
|
||||||
|
shrinkFlag = false;
|
||||||
|
ExpireChunksAndArenas(rt, true);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif /* JS_THREADSAFE */
|
#endif /* JS_THREADSAFE */
|
||||||
@ -3008,7 +3041,7 @@ GCCycle(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
|
|||||||
JS_ASSERT(!cx->gcBackgroundFree);
|
JS_ASSERT(!cx->gcBackgroundFree);
|
||||||
rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
|
rt->gcHelperThread.waitBackgroundSweepOrAllocEnd();
|
||||||
if (gckind != GC_LAST_CONTEXT && rt->state != JSRTS_LANDING) {
|
if (gckind != GC_LAST_CONTEXT && rt->state != JSRTS_LANDING) {
|
||||||
if (rt->gcHelperThread.prepareForBackgroundSweep(cx))
|
if (rt->gcHelperThread.prepareForBackgroundSweep())
|
||||||
cx->gcBackgroundFree = &rt->gcHelperThread;
|
cx->gcBackgroundFree = &rt->gcHelperThread;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -3022,7 +3055,7 @@ GCCycle(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
|
|||||||
if (cx->gcBackgroundFree) {
|
if (cx->gcBackgroundFree) {
|
||||||
JS_ASSERT(cx->gcBackgroundFree == &rt->gcHelperThread);
|
JS_ASSERT(cx->gcBackgroundFree == &rt->gcHelperThread);
|
||||||
cx->gcBackgroundFree = NULL;
|
cx->gcBackgroundFree = NULL;
|
||||||
rt->gcHelperThread.startBackgroundSweep(gckind == GC_SHRINK);
|
rt->gcHelperThread.startBackgroundSweep(cx, gckind == GC_SHRINK);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -3100,6 +3133,18 @@ js_GC(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind, gcstats::Re
|
|||||||
|
|
||||||
namespace js {
|
namespace js {
|
||||||
|
|
||||||
|
void
|
||||||
|
ShrinkGCBuffers(JSRuntime *rt)
|
||||||
|
{
|
||||||
|
AutoLockGC lock(rt);
|
||||||
|
JS_ASSERT(!rt->gcRunning);
|
||||||
|
#ifndef JS_THREADSAFE
|
||||||
|
ExpireChunksAndArenas(rt, true);
|
||||||
|
#else
|
||||||
|
rt->gcHelperThread.startBackgroundShrink();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
class AutoCopyFreeListToArenas {
|
class AutoCopyFreeListToArenas {
|
||||||
JSRuntime *rt;
|
JSRuntime *rt;
|
||||||
|
|
||||||
@ -3312,7 +3357,7 @@ RunDebugGC(JSContext *cx)
|
|||||||
rt->gcTriggerCompartment = rt->gcDebugCompartmentGC ? cx->compartment : NULL;
|
rt->gcTriggerCompartment = rt->gcDebugCompartmentGC ? cx->compartment : NULL;
|
||||||
if (rt->gcTriggerCompartment == rt->atomsCompartment)
|
if (rt->gcTriggerCompartment == rt->atomsCompartment)
|
||||||
rt->gcTriggerCompartment = NULL;
|
rt->gcTriggerCompartment = NULL;
|
||||||
|
|
||||||
RunLastDitchGC(cx);
|
RunLastDitchGC(cx);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -1388,6 +1388,9 @@ TriggerCompartmentGC(JSCompartment *comp, js::gcstats::Reason reason);
|
|||||||
extern void
|
extern void
|
||||||
MaybeGC(JSContext *cx);
|
MaybeGC(JSContext *cx);
|
||||||
|
|
||||||
|
extern void
|
||||||
|
ShrinkGCBuffers(JSRuntime *rt);
|
||||||
|
|
||||||
} /* namespace js */
|
} /* namespace js */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -1459,7 +1462,7 @@ class GCHelperThread {
|
|||||||
PRCondVar *done;
|
PRCondVar *done;
|
||||||
volatile State state;
|
volatile State state;
|
||||||
|
|
||||||
JSContext *context;
|
JSContext *finalizationContext;
|
||||||
bool shrinkFlag;
|
bool shrinkFlag;
|
||||||
|
|
||||||
Vector<void **, 16, js::SystemAllocPolicy> freeVector;
|
Vector<void **, 16, js::SystemAllocPolicy> freeVector;
|
||||||
@ -1495,6 +1498,8 @@ class GCHelperThread {
|
|||||||
wakeup(NULL),
|
wakeup(NULL),
|
||||||
done(NULL),
|
done(NULL),
|
||||||
state(IDLE),
|
state(IDLE),
|
||||||
|
finalizationContext(NULL),
|
||||||
|
shrinkFlag(false),
|
||||||
freeCursor(NULL),
|
freeCursor(NULL),
|
||||||
freeCursorEnd(NULL),
|
freeCursorEnd(NULL),
|
||||||
backgroundAllocation(true)
|
backgroundAllocation(true)
|
||||||
@ -1504,7 +1509,10 @@ class GCHelperThread {
|
|||||||
void finish();
|
void finish();
|
||||||
|
|
||||||
/* Must be called with the GC lock taken. */
|
/* Must be called with the GC lock taken. */
|
||||||
inline void startBackgroundSweep(bool shouldShrink);
|
void startBackgroundSweep(JSContext *cx, bool shouldShrink);
|
||||||
|
|
||||||
|
/* Must be called with the GC lock taken. */
|
||||||
|
void startBackgroundShrink();
|
||||||
|
|
||||||
/* Must be called with the GC lock taken. */
|
/* Must be called with the GC lock taken. */
|
||||||
void waitBackgroundSweepEnd();
|
void waitBackgroundSweepEnd();
|
||||||
@ -1549,7 +1557,7 @@ class GCHelperThread {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Must be called with the GC lock taken. */
|
/* Must be called with the GC lock taken. */
|
||||||
bool prepareForBackgroundSweep(JSContext *cx);
|
bool prepareForBackgroundSweep();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* JS_THREADSAFE */
|
#endif /* JS_THREADSAFE */
|
||||||
|
Loading…
Reference in New Issue
Block a user