Bug 1017141 - Make empty chunk count constants GC params r=terrence

This commit is contained in:
Jon Coppeard 2014-07-16 10:01:19 +01:00
Родитель bf7bbdfd29
Коммит 1aa9dc0f8f
5 изменённых файлов: 62 добавлений и 18 удалений

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

@ -291,7 +291,9 @@ static const struct ParamPair {
{"gcBytes", JSGC_BYTES},
{"gcNumber", JSGC_NUMBER},
{"sliceTimeBudget", JSGC_SLICE_TIME_BUDGET},
{"markStackLimit", JSGC_MARK_STACK_LIMIT}
{"markStackLimit", JSGC_MARK_STACK_LIMIT},
{"minEmptyChunkCount", JSGC_MIN_EMPTY_CHUNK_COUNT},
{"maxEmptyChunkCount", JSGC_MAX_EMPTY_CHUNK_COUNT}
};
// Keep this in sync with above params.

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

@ -480,6 +480,8 @@ class GCRuntime
bool dynamicHeapGrowth;
bool dynamicMarkSlice;
uint64_t decommitThreshold;
unsigned minEmptyChunkCount;
unsigned maxEmptyChunkCount;
/* During shutdown, the GC needs to clean up every possible object. */
bool cleanUpEverything;

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

@ -0,0 +1,25 @@
var min = gcparam('minEmptyChunkCount');
var max = gcparam('maxEmptyChunkCount');
gcparam('minEmptyChunkCount', 10);
gcparam('maxEmptyChunkCount', 20);
assertEq(gcparam('minEmptyChunkCount'), 10);
assertEq(gcparam('maxEmptyChunkCount'), 20);
gc();
/* We maintain the invariant that maxEmptyChunkCount >= minEmptyChunkCount. */
gcparam('minEmptyChunkCount', 30);
assertEq(gcparam('minEmptyChunkCount'), 30);
assertEq(gcparam('maxEmptyChunkCount'), 30);
gc();
gcparam('maxEmptyChunkCount', 5);
assertEq(gcparam('minEmptyChunkCount'), 5);
assertEq(gcparam('maxEmptyChunkCount'), 5);
gc();
gcparam('minEmptyChunkCount', min);
gcparam('maxEmptyChunkCount', max);
assertEq(gcparam('minEmptyChunkCount'), min);
assertEq(gcparam('maxEmptyChunkCount'), max);
gc();

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

@ -2145,7 +2145,16 @@ typedef enum JSGCParamKey {
* available to be decommitted, then JS_MaybeGC will trigger a shrinking GC
* to decommit it.
*/
JSGC_DECOMMIT_THRESHOLD = 20
JSGC_DECOMMIT_THRESHOLD = 20,
/*
* We try to keep at least this many unused chunks in the free chunk pool at
* all times, even after a shrinking GC.
*/
JSGC_MIN_EMPTY_CHUNK_COUNT = 21,
/* We never keep more than this many unused chunks in the free chunk pool. */
JSGC_MAX_EMPTY_CHUNK_COUNT = 22
} JSGCParamKey;
extern JS_PUBLIC_API(void)

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

@ -238,18 +238,6 @@ static const uint64_t GC_IDLE_FULL_SPAN = 20 * 1000 * 1000;
/* Increase the IGC marking slice time if we are in highFrequencyGC mode. */
static const int IGC_MARK_SLICE_MULTIPLIER = 2;
#ifdef JSGC_GENERATIONAL
static const unsigned MIN_EMPTY_CHUNK_COUNT = 1;
#else
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
const AllocKind gc::slotsToThingKind[] = {
/* 0 */ FINALIZE_OBJECT0, FINALIZE_OBJECT2, FINALIZE_OBJECT2, FINALIZE_OBJECT4,
/* 4 */ FINALIZE_OBJECT4, FINALIZE_OBJECT8, FINALIZE_OBJECT8, FINALIZE_OBJECT8,
@ -695,14 +683,15 @@ GCRuntime::expireChunkPool(bool shrinkBuffers, bool releaseAll)
* without emptying the list, the older chunks will stay at the tail
* and are more likely to reach the max age.
*/
JS_ASSERT(maxEmptyChunkCount >= minEmptyChunkCount);
Chunk *freeList = nullptr;
unsigned freeChunkCount = 0;
for (ChunkPool::Enum e(chunkPool); !e.empty(); ) {
Chunk *chunk = e.front();
JS_ASSERT(chunk->unused());
JS_ASSERT(!chunkSet.has(chunk));
if (releaseAll || freeChunkCount >= MAX_EMPTY_CHUNK_COUNT ||
(freeChunkCount >= MIN_EMPTY_CHUNK_COUNT &&
if (releaseAll || freeChunkCount >= maxEmptyChunkCount ||
(freeChunkCount >= minEmptyChunkCount &&
(shrinkBuffers || chunk->info.age == MAX_EMPTY_CHUNK_AGE)))
{
e.removeAndPopFront();
@ -716,7 +705,8 @@ GCRuntime::expireChunkPool(bool shrinkBuffers, bool releaseAll)
e.popFront();
}
}
JS_ASSERT_IF(shrinkBuffers, chunkPool.getEmptyCount() <= MIN_EMPTY_CHUNK_COUNT);
JS_ASSERT(chunkPool.getEmptyCount() <= maxEmptyChunkCount);
JS_ASSERT_IF(shrinkBuffers, chunkPool.getEmptyCount() <= minEmptyChunkCount);
JS_ASSERT_IF(releaseAll, chunkPool.getEmptyCount() == 0);
return freeList;
}
@ -1032,7 +1022,7 @@ GCRuntime::wantBackgroundAllocation() const
* of them.
*/
return helperState.canBackgroundAllocate() &&
chunkPool.getEmptyCount() < MIN_EMPTY_CHUNK_COUNT &&
chunkPool.getEmptyCount() < minEmptyChunkCount &&
chunkSet.count() >= 4;
}
@ -1137,6 +1127,8 @@ GCRuntime::GCRuntime(JSRuntime *rt) :
dynamicHeapGrowth(false),
dynamicMarkSlice(false),
decommitThreshold(32 * 1024 * 1024),
minEmptyChunkCount(1),
maxEmptyChunkCount(30),
cleanUpEverything(false),
grayBitsValid(false),
isNeeded(0),
@ -1456,6 +1448,16 @@ GCRuntime::setParameter(JSGCParamKey key, uint32_t value)
case JSGC_DECOMMIT_THRESHOLD:
decommitThreshold = value * 1024 * 1024;
break;
case JSGC_MIN_EMPTY_CHUNK_COUNT:
minEmptyChunkCount = value;
if (minEmptyChunkCount > maxEmptyChunkCount)
maxEmptyChunkCount = minEmptyChunkCount;
break;
case JSGC_MAX_EMPTY_CHUNK_COUNT:
maxEmptyChunkCount = value;
if (minEmptyChunkCount > maxEmptyChunkCount)
minEmptyChunkCount = maxEmptyChunkCount;
break;
default:
JS_ASSERT(key == JSGC_MODE);
mode = JSGCMode(value);
@ -1504,6 +1506,10 @@ GCRuntime::getParameter(JSGCParamKey key)
return dynamicMarkSlice;
case JSGC_ALLOCATION_THRESHOLD:
return allocThreshold / 1024 / 1024;
case JSGC_MIN_EMPTY_CHUNK_COUNT:
return minEmptyChunkCount;
case JSGC_MAX_EMPTY_CHUNK_COUNT:
return maxEmptyChunkCount;
default:
JS_ASSERT(key == JSGC_NUMBER);
return uint32_t(number);