Bug 1093307 - Part 2: Make OOM flushing paths more straightforward; r=jonco

--HG--
extra : rebase_source : 4634215f64ea96c2057f4ff609119b2a6cad008f
This commit is contained in:
Terrence Cole 2014-11-06 14:03:05 -08:00
Родитель d6d15a2f78
Коммит b0ef029ce6
2 изменённых файлов: 38 добавлений и 6 удалений

Просмотреть файл

@ -498,7 +498,7 @@ class GCRuntime
* Must be called either during the GC or with the GC lock taken.
*/
Chunk *expireEmptyChunkPool(bool shrinkBuffers, const AutoLockGC &lock);
void freeEmptyChunks(JSRuntime *rt);
void freeEmptyChunks(JSRuntime *rt, const AutoLockGC &lock);
void freeChunkList(Chunk *chunkListHead);
void prepareToFreeChunk(ChunkInfo &info);
void releaseChunk(Chunk *chunk);
@ -543,6 +543,7 @@ class GCRuntime
bool sweepPhase(SliceBudget &sliceBudget);
void endSweepPhase(bool lastGC);
void sweepZones(FreeOp *fop, bool lastGC);
void decommitAllWithoutUnlocking(const AutoLockGC &lock);
void decommitArenasFromAvailableList(Chunk **availableListHeadp);
void decommitArenas();
void expireChunksAndArenas(bool shouldShrink, const AutoLockGC &lock);

Просмотреть файл

@ -744,15 +744,22 @@ GCRuntime::expireEmptyChunkPool(bool shrinkBuffers, const AutoLockGC &lock)
return freeList;
}
void
GCRuntime::freeEmptyChunks(JSRuntime *rt)
static void
FreeChunkPool(JSRuntime *rt, ChunkPool &pool)
{
for (ChunkPool::Enum e(emptyChunks_); !e.empty();) {
for (ChunkPool::Enum e(pool); !e.empty();) {
Chunk *chunk = e.front();
e.removeAndPopFront();
MOZ_ASSERT(!chunk->info.numArenasFreeCommitted);
FreeChunk(rt, chunk);
}
MOZ_ASSERT(pool.count() == 0);
}
void
GCRuntime::freeEmptyChunks(JSRuntime *rt, const AutoLockGC &lock)
{
FreeChunkPool(rt, emptyChunks(lock));
}
void
@ -1422,7 +1429,7 @@ GCRuntime::finish()
chunkSet.clear();
}
freeEmptyChunks(rt);
FreeChunkPool(rt, emptyChunks_);
if (rootsHash.initialized())
rootsHash.clear();
@ -3122,6 +3129,25 @@ GCRuntime::maybePeriodicFullGC()
#endif
}
// Do all possible decommit immediately from the current thread without
// releasing the GC lock or allocating any memory.
void
GCRuntime::decommitAllWithoutUnlocking(const AutoLockGC &lock)
{
MOZ_ASSERT(emptyChunks(lock).count() == 0);
for (Chunk *chunk = *getAvailableChunkList(); chunk; chunk = chunk->info.next) {
for (size_t i = 0; i < ArenasPerChunk; ++i) {
if (chunk->decommittedArenas.get(i) || chunk->arenas[i].aheader.allocated())
continue;
if (MarkPagesUnused(&chunk->arenas[i], ArenaSize)) {
chunk->info.numArenasFreeCommitted--;
chunk->decommittedArenas.set(i);
}
}
}
}
void
GCRuntime::decommitArenasFromAvailableList(Chunk **availableListHeadp)
{
@ -6216,7 +6242,12 @@ GCRuntime::onOutOfMallocMemory()
// Throw away any excess chunks we have lying around.
AutoLockGC lock(rt);
expireChunksAndArenas(true, lock);
freeEmptyChunks(rt, lock);
// Immediately decommit as many arenas as possible in the hopes that this
// might let the OS scrape together enough pages to satisfy the failing
// malloc request.
decommitAllWithoutUnlocking(lock);
}
void