зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset c245807aad3a for bug 714066
This commit is contained in:
Родитель
d279636f61
Коммит
5c0d522df5
|
@ -104,6 +104,7 @@ ThreadData::ThreadData(JSRuntime *rt)
|
|||
#ifdef JS_THREADSAFE
|
||||
requestDepth(0),
|
||||
#endif
|
||||
waiveGCQuota(false),
|
||||
tempLifoAlloc(TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE),
|
||||
execAlloc(NULL),
|
||||
bumpAlloc(NULL),
|
||||
|
@ -1269,9 +1270,34 @@ js_InvokeOperationCallback(JSContext *cx)
|
|||
#endif
|
||||
JS_UNLOCK_GC(rt);
|
||||
|
||||
if (rt->gcIsNeeded)
|
||||
if (rt->gcIsNeeded) {
|
||||
js_GC(cx, rt->gcTriggerCompartment, GC_NORMAL, rt->gcTriggerReason);
|
||||
|
||||
/*
|
||||
* On trace we can exceed the GC quota, see comments in NewGCArena. So
|
||||
* we check the quota and report OOM here when we are off trace.
|
||||
*/
|
||||
if (checkOutOfMemory(rt)) {
|
||||
#ifdef JS_THREADSAFE
|
||||
/*
|
||||
* We have to wait until the background thread is done in order
|
||||
* to get a correct answer.
|
||||
*/
|
||||
{
|
||||
AutoLockGC lock(rt);
|
||||
rt->gcHelperThread.waitBackgroundSweepEnd();
|
||||
}
|
||||
if (checkOutOfMemory(rt)) {
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
js_ReportOutOfMemory(cx);
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
/*
|
||||
* We automatically yield the current context every time the operation
|
||||
|
@ -1572,7 +1598,7 @@ JSRuntime::onOutOfMemory(void *p, size_t nbytes, JSContext *cx)
|
|||
AutoLockGC lock(this);
|
||||
gcHelperThread.waitBackgroundSweepOrAllocEnd();
|
||||
#endif
|
||||
gcChunkPool.expireAndFree(this, true);
|
||||
gcChunkPool.expire(this, true);
|
||||
}
|
||||
if (!p)
|
||||
p = OffTheBooks::malloc_(nbytes);
|
||||
|
|
|
@ -140,6 +140,12 @@ struct ThreadData {
|
|||
/* Keeper of the contiguous stack used by all contexts in this thread. */
|
||||
StackSpace stackSpace;
|
||||
|
||||
/*
|
||||
* Flag indicating that we are waiving any soft limits on the GC heap
|
||||
* because we want allocations to be infallible (except when we hit OOM).
|
||||
*/
|
||||
bool waiveGCQuota;
|
||||
|
||||
/* Temporary arena pool used while compiling and decompiling. */
|
||||
static const size_t TEMP_LIFO_ALLOC_PRIMARY_CHUNK_SIZE = 1 << 12;
|
||||
LifoAlloc tempLifoAlloc;
|
||||
|
|
|
@ -517,22 +517,6 @@ ChunkPool::expire(JSRuntime *rt, bool releaseAll)
|
|||
return freeList;
|
||||
}
|
||||
|
||||
static void
|
||||
FreeChunkList(Chunk *chunkListHead)
|
||||
{
|
||||
while (Chunk *chunk = chunkListHead) {
|
||||
JS_ASSERT(!chunk->info.numArenasFreeCommitted);
|
||||
chunkListHead = chunk->info.next;
|
||||
FreeChunk(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ChunkPool::expireAndFree(JSRuntime *rt, bool releaseAll)
|
||||
{
|
||||
FreeChunkList(expire(rt, releaseAll));
|
||||
}
|
||||
|
||||
JS_FRIEND_API(int64_t)
|
||||
ChunkPool::countCleanDecommittedArenas(JSRuntime *rt)
|
||||
{
|
||||
|
@ -569,6 +553,16 @@ Chunk::release(JSRuntime *rt, Chunk *chunk)
|
|||
FreeChunk(chunk);
|
||||
}
|
||||
|
||||
static void
|
||||
FreeChunkList(Chunk *chunkListHead)
|
||||
{
|
||||
while (Chunk *chunk = chunkListHead) {
|
||||
JS_ASSERT(!chunk->info.numArenasFreeCommitted);
|
||||
chunkListHead = chunk->info.next;
|
||||
FreeChunk(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
inline void
|
||||
Chunk::prepareToBeFreed(JSRuntime *rt)
|
||||
{
|
||||
|
@ -1188,7 +1182,7 @@ js_FinishGC(JSRuntime *rt)
|
|||
* Finish the pool after the background thread stops in case it was doing
|
||||
* the background sweeping.
|
||||
*/
|
||||
rt->gcChunkPool.expireAndFree(rt, true);
|
||||
FreeChunkList(rt->gcChunkPool.expire(rt, true));
|
||||
|
||||
#ifdef DEBUG
|
||||
if (!rt->gcRootsHash.empty())
|
||||
|
@ -1647,6 +1641,12 @@ RunLastDitchGC(JSContext *cx)
|
|||
#endif
|
||||
}
|
||||
|
||||
inline bool
|
||||
IsGCAllowed(JSContext *cx)
|
||||
{
|
||||
return !JS_THREAD_DATA(cx)->waiveGCQuota;
|
||||
}
|
||||
|
||||
/* static */ void *
|
||||
ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
|
||||
{
|
||||
|
@ -1658,7 +1658,7 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
|
|||
|
||||
bool runGC = !!rt->gcIsNeeded;
|
||||
for (;;) {
|
||||
if (JS_UNLIKELY(runGC)) {
|
||||
if (JS_UNLIKELY(runGC) && IsGCAllowed(cx)) {
|
||||
RunLastDitchGC(cx);
|
||||
|
||||
/* Report OOM of the GC failed to free enough memory. */
|
||||
|
@ -1679,11 +1679,14 @@ ArenaLists::refillFreeList(JSContext *cx, AllocKind thingKind)
|
|||
return thing;
|
||||
|
||||
/*
|
||||
* We failed to allocate. Run the GC if we haven't done it already.
|
||||
* Otherwise report OOM.
|
||||
* We failed to allocate. Run the GC if we can unless we have done it
|
||||
* already. Otherwise report OOM but first schedule a new GC soon.
|
||||
*/
|
||||
if (runGC)
|
||||
if (runGC || !IsGCAllowed(cx)) {
|
||||
AutoLockGC lock(rt);
|
||||
TriggerGC(rt, gcstats::REFILL);
|
||||
break;
|
||||
}
|
||||
runGC = true;
|
||||
}
|
||||
|
||||
|
@ -2990,10 +2993,12 @@ GCCycle(JSContext *cx, JSCompartment *comp, JSGCInvocationKind gckind)
|
|||
js_PurgeThreads_PostGlobalSweep(cx);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
if (cx->gcBackgroundFree) {
|
||||
if (gckind != GC_LAST_CONTEXT && rt->state != JSRTS_LANDING) {
|
||||
JS_ASSERT(cx->gcBackgroundFree == &rt->gcHelperThread);
|
||||
cx->gcBackgroundFree = NULL;
|
||||
rt->gcHelperThread.startBackgroundSweep(gckind == GC_SHRINK);
|
||||
} else {
|
||||
JS_ASSERT(!cx->gcBackgroundFree);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -3274,6 +3279,7 @@ void
|
|||
RunDebugGC(JSContext *cx)
|
||||
{
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (IsGCAllowed(cx)) {
|
||||
JSRuntime *rt = cx->runtime;
|
||||
|
||||
/*
|
||||
|
@ -3285,6 +3291,7 @@ RunDebugGC(JSContext *cx)
|
|||
rt->gcTriggerCompartment = NULL;
|
||||
|
||||
RunLastDitchGC(cx);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -808,9 +808,6 @@ class ChunkPool {
|
|||
*/
|
||||
Chunk *expire(JSRuntime *rt, bool releaseAll);
|
||||
|
||||
/* Must be called with the GC lock taken. */
|
||||
void expireAndFree(JSRuntime *rt, bool releaseAll);
|
||||
|
||||
/* Must be called either during the GC or with the GC lock taken. */
|
||||
JS_FRIEND_API(int64_t) countCleanDecommittedArenas(JSRuntime *rt);
|
||||
};
|
||||
|
|
Загрузка…
Ссылка в новой задаче