зеркало из https://github.com/mozilla/gecko-dev.git
When idle the GC holds on to unused chunks indefinitely (bug 631733, r=brendan, a=blocker). (relanding in a CLOSED TREE)
This commit is contained in:
Родитель
04bbcc7b36
Коммит
a2f58bb615
|
@ -3480,6 +3480,12 @@ DOMGCCallback(JSContext *cx, JSGCStatus status)
|
|||
nsJSContext::PokeCC();
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't end up scheduling a GC, and there are unused
|
||||
// chunks waiting to expire, make sure we will GC again soon.
|
||||
if (!sGCTimer && JS_GetGCParameter(cx->runtime, JSGC_UNUSED_CHUNKS) > 0) {
|
||||
nsJSContext::PokeGC();
|
||||
}
|
||||
}
|
||||
|
||||
JSBool result = gOldJSGCCallback ? gOldJSGCCallback(cx, status) : JS_TRUE;
|
||||
|
|
|
@ -2644,6 +2644,8 @@ JS_GetGCParameter(JSRuntime *rt, JSGCParamKey key)
|
|||
return rt->gcBytes;
|
||||
case JSGC_MODE:
|
||||
return uint32(rt->gcMode);
|
||||
case JSGC_UNUSED_CHUNKS:
|
||||
return uint32(rt->gcChunksWaitingToExpire);
|
||||
default:
|
||||
JS_ASSERT(key == JSGC_NUMBER);
|
||||
return rt->gcNumber;
|
||||
|
|
|
@ -1785,7 +1785,10 @@ typedef enum JSGCParamKey {
|
|||
JSGC_MAX_CODE_CACHE_BYTES = 6,
|
||||
|
||||
/* Select GC mode. */
|
||||
JSGC_MODE = 7
|
||||
JSGC_MODE = 7,
|
||||
|
||||
/* Number of GC chunks waiting to expire. */
|
||||
JSGC_UNUSED_CHUNKS = 8
|
||||
} JSGCParamKey;
|
||||
|
||||
typedef enum JSGCMode {
|
||||
|
|
|
@ -1047,6 +1047,7 @@ struct JSRuntime {
|
|||
size_t gcLastBytes;
|
||||
size_t gcMaxBytes;
|
||||
size_t gcMaxMallocBytes;
|
||||
size_t gcChunksWaitingToExpire;
|
||||
uint32 gcEmptyArenaPoolLifespan;
|
||||
uint32 gcNumber;
|
||||
js::GCMarker *gcMarkingTracer;
|
||||
|
|
|
@ -360,14 +360,6 @@ Chunk::releaseArena(Arena<T> *arena)
|
|||
info.age = 0;
|
||||
}
|
||||
|
||||
bool
|
||||
Chunk::expire()
|
||||
{
|
||||
if (!unused())
|
||||
return false;
|
||||
return info.age++ > MaxAge;
|
||||
}
|
||||
|
||||
JSRuntime *
|
||||
Chunk::getRuntime()
|
||||
{
|
||||
|
@ -456,16 +448,22 @@ PickChunk(JSRuntime *rt)
|
|||
static void
|
||||
ExpireGCChunks(JSRuntime *rt)
|
||||
{
|
||||
static const size_t MaxAge = 3;
|
||||
|
||||
/* Remove unused chunks. */
|
||||
AutoLockGC lock(rt);
|
||||
|
||||
rt->gcChunksWaitingToExpire = 0;
|
||||
for (GCChunkSet::Enum e(rt->gcChunkSet); !e.empty(); e.popFront()) {
|
||||
Chunk *chunk = e.front();
|
||||
JS_ASSERT(chunk->info.runtime == rt);
|
||||
if (chunk->expire()) {
|
||||
e.removeFront();
|
||||
ReleaseGCChunk(rt, chunk);
|
||||
continue;
|
||||
if (chunk->unused()) {
|
||||
if (chunk->info.age++ > MaxAge) {
|
||||
e.removeFront();
|
||||
ReleaseGCChunk(rt, chunk);
|
||||
continue;
|
||||
}
|
||||
rt->gcChunksWaitingToExpire++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -340,7 +340,6 @@ struct Chunk {
|
|||
sizeof(MarkingDelay);
|
||||
|
||||
static const size_t ArenasPerChunk = (GC_CHUNK_SIZE - sizeof(ChunkInfo)) / BytesPerArena;
|
||||
static const size_t MaxAge = 3;
|
||||
|
||||
Arena<FreeCell> arenas[ArenasPerChunk];
|
||||
ArenaBitmap bitmaps[ArenasPerChunk];
|
||||
|
@ -362,7 +361,6 @@ struct Chunk {
|
|||
void releaseArena(Arena<T> *a);
|
||||
|
||||
JSRuntime *getRuntime();
|
||||
bool expire();
|
||||
};
|
||||
JS_STATIC_ASSERT(sizeof(Chunk) <= GC_CHUNK_SIZE);
|
||||
JS_STATIC_ASSERT(sizeof(Chunk) + Chunk::BytesPerArena > GC_CHUNK_SIZE);
|
||||
|
|
Загрузка…
Ссылка в новой задаче