зеркало из https://github.com/mozilla/gecko-dev.git
Bug 999158 - Keep a spare chunk around to mitigate GGC OOM crashes on tenuring r=terrence
This commit is contained in:
Родитель
b59461402a
Коммит
81b32d0f45
|
@ -55,9 +55,6 @@ class ChunkPool
|
||||||
/* Must be called either during the GC or with the GC lock taken. */
|
/* Must be called either during the GC or with the GC lock taken. */
|
||||||
inline void put(Chunk *chunk);
|
inline void put(Chunk *chunk);
|
||||||
|
|
||||||
/* Must be called with the GC lock taken. */
|
|
||||||
void expireAndFree(JSRuntime *rt, bool releaseAll);
|
|
||||||
|
|
||||||
class Enum {
|
class Enum {
|
||||||
public:
|
public:
|
||||||
Enum(ChunkPool &pool) : pool(pool), chunkp(&pool.emptyChunkListHead) {}
|
Enum(ChunkPool &pool) : pool(pool), chunkp(&pool.emptyChunkListHead) {}
|
||||||
|
@ -358,7 +355,7 @@ class GCRuntime
|
||||||
* Return the list of chunks that can be released outside the GC lock.
|
* Return the list of chunks that can be released outside the GC lock.
|
||||||
* Must be called either during the GC or with the GC lock taken.
|
* Must be called either during the GC or with the GC lock taken.
|
||||||
*/
|
*/
|
||||||
Chunk *expireChunkPool(bool releaseAll);
|
Chunk *expireChunkPool(bool shrinkBuffers, bool releaseAll);
|
||||||
void expireAndFreeChunkPool(bool releaseAll);
|
void expireAndFreeChunkPool(bool releaseAll);
|
||||||
void freeChunkList(Chunk *chunkListHead);
|
void freeChunkList(Chunk *chunkListHead);
|
||||||
void prepareToFreeChunk(ChunkInfo &info);
|
void prepareToFreeChunk(ChunkInfo &info);
|
||||||
|
|
|
@ -239,10 +239,16 @@ static const uint64_t GC_IDLE_FULL_SPAN = 20 * 1000 * 1000;
|
||||||
/* Increase the IGC marking slice time if we are in highFrequencyGC mode. */
|
/* Increase the IGC marking slice time if we are in highFrequencyGC mode. */
|
||||||
static const int IGC_MARK_SLICE_MULTIPLIER = 2;
|
static const int IGC_MARK_SLICE_MULTIPLIER = 2;
|
||||||
|
|
||||||
#if defined(ANDROID) || defined(MOZ_B2G)
|
#ifdef JSGC_GENERATIONAL
|
||||||
static const int MAX_EMPTY_CHUNK_COUNT = 2;
|
static const unsigned MIN_EMPTY_CHUNK_COUNT = 1;
|
||||||
#else
|
#else
|
||||||
static const int MAX_EMPTY_CHUNK_COUNT = 30;
|
static const unsigned MIN_EMPTY_CHUNK_COUNT = 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if defined(ANDROID) || defined(MOZ_B2G)
|
||||||
|
static const unsigned MAX_EMPTY_CHUNK_COUNT = 2;
|
||||||
|
#else
|
||||||
|
static const unsigned MAX_EMPTY_CHUNK_COUNT = 30;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
const AllocKind gc::slotsToThingKind[] = {
|
const AllocKind gc::slotsToThingKind[] = {
|
||||||
|
@ -712,7 +718,7 @@ ChunkPool::Enum::removeAndPopFront()
|
||||||
|
|
||||||
/* Must be called either during the GC or with the GC lock taken. */
|
/* Must be called either during the GC or with the GC lock taken. */
|
||||||
Chunk *
|
Chunk *
|
||||||
GCRuntime::expireChunkPool(bool releaseAll)
|
GCRuntime::expireChunkPool(bool shrinkBuffers, bool releaseAll)
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
* Return old empty chunks to the system while preserving the order of
|
* Return old empty chunks to the system while preserving the order of
|
||||||
|
@ -721,14 +727,14 @@ GCRuntime::expireChunkPool(bool releaseAll)
|
||||||
* and are more likely to reach the max age.
|
* and are more likely to reach the max age.
|
||||||
*/
|
*/
|
||||||
Chunk *freeList = nullptr;
|
Chunk *freeList = nullptr;
|
||||||
int freeChunkCount = 0;
|
unsigned freeChunkCount = 0;
|
||||||
for (ChunkPool::Enum e(chunkPool); !e.empty(); ) {
|
for (ChunkPool::Enum e(chunkPool); !e.empty(); ) {
|
||||||
Chunk *chunk = e.front();
|
Chunk *chunk = e.front();
|
||||||
JS_ASSERT(chunk->unused());
|
JS_ASSERT(chunk->unused());
|
||||||
JS_ASSERT(!chunkSet.has(chunk));
|
JS_ASSERT(!chunkSet.has(chunk));
|
||||||
JS_ASSERT(chunk->info.age <= MAX_EMPTY_CHUNK_AGE);
|
if (releaseAll || freeChunkCount >= MAX_EMPTY_CHUNK_COUNT ||
|
||||||
if (releaseAll || chunk->info.age == MAX_EMPTY_CHUNK_AGE ||
|
(freeChunkCount >= MIN_EMPTY_CHUNK_COUNT &&
|
||||||
freeChunkCount++ > MAX_EMPTY_CHUNK_COUNT)
|
(shrinkBuffers || chunk->info.age == MAX_EMPTY_CHUNK_AGE)))
|
||||||
{
|
{
|
||||||
e.removeAndPopFront();
|
e.removeAndPopFront();
|
||||||
prepareToFreeChunk(chunk->info);
|
prepareToFreeChunk(chunk->info);
|
||||||
|
@ -736,10 +742,12 @@ GCRuntime::expireChunkPool(bool releaseAll)
|
||||||
freeList = chunk;
|
freeList = chunk;
|
||||||
} else {
|
} else {
|
||||||
/* Keep the chunk but increase its age. */
|
/* Keep the chunk but increase its age. */
|
||||||
|
++freeChunkCount;
|
||||||
++chunk->info.age;
|
++chunk->info.age;
|
||||||
e.popFront();
|
e.popFront();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
JS_ASSERT_IF(shrinkBuffers, chunkPool.getEmptyCount() <= MIN_EMPTY_CHUNK_COUNT);
|
||||||
JS_ASSERT_IF(releaseAll, chunkPool.getEmptyCount() == 0);
|
JS_ASSERT_IF(releaseAll, chunkPool.getEmptyCount() == 0);
|
||||||
return freeList;
|
return freeList;
|
||||||
}
|
}
|
||||||
|
@ -757,7 +765,7 @@ GCRuntime::freeChunkList(Chunk *chunkListHead)
|
||||||
void
|
void
|
||||||
GCRuntime::expireAndFreeChunkPool(bool releaseAll)
|
GCRuntime::expireAndFreeChunkPool(bool releaseAll)
|
||||||
{
|
{
|
||||||
freeChunkList(expireChunkPool(releaseAll));
|
freeChunkList(expireChunkPool(true, releaseAll));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ Chunk *
|
/* static */ Chunk *
|
||||||
|
@ -1056,7 +1064,7 @@ GCRuntime::wantBackgroundAllocation() const
|
||||||
* of them.
|
* of them.
|
||||||
*/
|
*/
|
||||||
return helperState.canBackgroundAllocate() &&
|
return helperState.canBackgroundAllocate() &&
|
||||||
chunkPool.getEmptyCount() == 0 &&
|
chunkPool.getEmptyCount() < MIN_EMPTY_CHUNK_COUNT &&
|
||||||
chunkSet.count() >= 4;
|
chunkSet.count() >= 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2609,7 +2617,7 @@ GCRuntime::expireChunksAndArenas(bool shouldShrink)
|
||||||
rt->threadPool.pruneChunkCache();
|
rt->threadPool.pruneChunkCache();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (Chunk *toFree = expireChunkPool(shouldShrink)) {
|
if (Chunk *toFree = expireChunkPool(shouldShrink, false)) {
|
||||||
AutoUnlockGC unlock(rt);
|
AutoUnlockGC unlock(rt);
|
||||||
freeChunkList(toFree);
|
freeChunkList(toFree);
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче