зеркало из https://github.com/mozilla/gecko-dev.git
Bug 541140 - TM: don't return GCChunks immediately
This commit is contained in:
Родитель
46b939366c
Коммит
1b351d8da0
|
@ -721,6 +721,8 @@ struct JSClassProtoCache {
|
|||
#endif
|
||||
};
|
||||
|
||||
typedef js::Vector<JSGCChunkInfo*, 0, js::SystemAllocPolicy> GCEmptyChunks;
|
||||
|
||||
struct JSRuntime {
|
||||
/* Runtime state, synchronized by the stateChange/gcLock condvar/lock. */
|
||||
JSRuntimeState state;
|
||||
|
@ -744,6 +746,7 @@ struct JSRuntime {
|
|||
|
||||
/* Garbage collector state, used by jsgc.c. */
|
||||
JSGCChunkInfo *gcChunkList;
|
||||
GCEmptyChunks gcEmptyChunks;
|
||||
JSGCArenaList gcArenaList[FINALIZE_LIMIT];
|
||||
JSGCDoubleArenaList gcDoubleArenaList;
|
||||
JSDHashTable gcRootsHash;
|
||||
|
|
|
@ -240,6 +240,8 @@ static const jsuword GC_ARENA_SHIFT = 12;
|
|||
static const jsuword GC_ARENA_MASK = JS_BITMASK(GC_ARENA_SHIFT);
|
||||
static const jsuword GC_ARENA_SIZE = JS_BIT(GC_ARENA_SHIFT);
|
||||
|
||||
static const jsuword GC_MAX_CHUNK_AGE = 3;
|
||||
|
||||
const size_t GC_CELL_SHIFT = 3;
|
||||
const size_t GC_CELL_SIZE = size_t(1) << GC_CELL_SHIFT;
|
||||
const size_t GC_CELL_MASK = GC_CELL_SIZE - 1;
|
||||
|
@ -327,6 +329,7 @@ struct JSGCChunkInfo {
|
|||
JSGCChunkInfo **prevp;
|
||||
JSGCChunkInfo *next;
|
||||
size_t numFreeArenas;
|
||||
size_t gcChunkAge;
|
||||
|
||||
inline void init(JSRuntime *rt);
|
||||
|
||||
|
@ -641,7 +644,7 @@ GetGCChunk(JSRuntime *rt)
|
|||
}
|
||||
|
||||
inline void
|
||||
PutGCChunk(JSRuntime *rt, void *p)
|
||||
ReleaseGCChunk(JSRuntime *rt, void *p)
|
||||
{
|
||||
JS_ASSERT(p);
|
||||
#ifdef MOZ_GCTIMER
|
||||
|
@ -652,16 +655,6 @@ PutGCChunk(JSRuntime *rt, void *p)
|
|||
FreeGCChunk(p);
|
||||
}
|
||||
|
||||
static void
|
||||
PutGCChunks(JSRuntime *rt, JSGCChunkInfo *list)
|
||||
{
|
||||
while (list) {
|
||||
jsuword chunk = list->getChunk();
|
||||
list = list->next;
|
||||
PutGCChunk(rt, reinterpret_cast<void *>(chunk));
|
||||
}
|
||||
}
|
||||
|
||||
static JSGCArena *
|
||||
NewGCArena(JSContext *cx)
|
||||
{
|
||||
|
@ -680,11 +673,20 @@ NewGCArena(JSContext *cx)
|
|||
JSGCChunkInfo *ci = rt->gcChunkList;
|
||||
jsuword chunk;
|
||||
if (!ci) {
|
||||
void *chunkptr = GetGCChunk(rt);
|
||||
if (!chunkptr)
|
||||
return NULL;
|
||||
chunk = reinterpret_cast<jsuword>(chunkptr);
|
||||
ci = JSGCChunkInfo::fromChunk(chunk);
|
||||
GCEmptyChunks *chunks = &rt->gcEmptyChunks;
|
||||
if (!chunks->empty()) {
|
||||
ci = chunks->back();
|
||||
chunks->popBack();
|
||||
JS_ASSERT(ci);
|
||||
chunk = ci->getChunk();
|
||||
} else {
|
||||
void *chunkptr = GetGCChunk(rt);
|
||||
if (!chunkptr)
|
||||
return NULL;
|
||||
chunk = reinterpret_cast<jsuword>(chunkptr);
|
||||
ci = JSGCChunkInfo::fromChunk(chunk);
|
||||
}
|
||||
ci->gcChunkAge = 0;
|
||||
ci->init(rt);
|
||||
} else {
|
||||
chunk = ci->getChunk();
|
||||
|
@ -719,13 +721,11 @@ NewGCArena(JSContext *cx)
|
|||
namespace js {
|
||||
|
||||
struct GCArenaReleaser {
|
||||
JSGCChunkInfo *emptyChunkList;
|
||||
#ifdef DEBUG
|
||||
JSGCArena *emptyArenaList;
|
||||
#endif
|
||||
|
||||
GCArenaReleaser()
|
||||
: emptyChunkList(NULL)
|
||||
{
|
||||
#ifdef DEBUG
|
||||
emptyArenaList = NULL;
|
||||
|
@ -756,8 +756,11 @@ struct GCArenaReleaser {
|
|||
ci->numFreeArenas++;
|
||||
if (ci->numFreeArenas == GC_ARENAS_PER_CHUNK) {
|
||||
ci->removeFromList(rt);
|
||||
ci->next = emptyChunkList;
|
||||
emptyChunkList = ci;
|
||||
ci->gcChunkAge = 0;
|
||||
if (!rt->gcEmptyChunks.append(ci)) {
|
||||
jsuword chunk = ci->getChunk();
|
||||
ReleaseGCChunk(rt, (void *)chunk);
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef DEBUG
|
||||
|
@ -785,8 +788,6 @@ struct GCArenaReleaser {
|
|||
emptyArenaList = next;
|
||||
}
|
||||
#endif
|
||||
PutGCChunks(rt, emptyChunkList);
|
||||
emptyChunkList = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -889,10 +890,8 @@ FinishGCArenaLists(JSRuntime *rt)
|
|||
rt->gcDoubleArenaList.cursor = NULL;
|
||||
|
||||
arenaReleaser.freeArenas(rt);
|
||||
JS_ASSERT(rt->gcChunkList == NULL);
|
||||
rt->gcBytes = 0;
|
||||
|
||||
PutGCChunks(rt, rt->gcChunkList);
|
||||
rt->gcChunkList = NULL;
|
||||
}
|
||||
|
||||
intN
|
||||
|
@ -1188,6 +1187,27 @@ static void
|
|||
CheckLeakedRoots(JSRuntime *rt);
|
||||
#endif
|
||||
|
||||
void DestroyEmptyGCChunks(JSRuntime *rt, bool releaseAll)
|
||||
{
|
||||
size_t newLength = 0;
|
||||
GCEmptyChunks *chunks = &rt->gcEmptyChunks;
|
||||
JSGCChunkInfo **array = chunks->begin();
|
||||
|
||||
for (JSGCChunkInfo **i = chunks->begin(); i != chunks->end(); ++i) {
|
||||
JSGCChunkInfo *ci = *i;
|
||||
JS_ASSERT(ci->numFreeArenas == GC_ARENAS_PER_CHUNK);
|
||||
if (releaseAll || ci->gcChunkAge > GC_MAX_CHUNK_AGE) {
|
||||
jsuword chunk = ci->getChunk();
|
||||
ReleaseGCChunk(rt, (void *)chunk);
|
||||
} else {
|
||||
ci->gcChunkAge++;
|
||||
array[newLength++] = ci;
|
||||
}
|
||||
}
|
||||
|
||||
rt->gcEmptyChunks.resize(newLength);
|
||||
}
|
||||
|
||||
void
|
||||
js_FinishGC(JSRuntime *rt)
|
||||
{
|
||||
|
@ -1200,7 +1220,9 @@ js_FinishGC(JSRuntime *rt)
|
|||
#endif
|
||||
|
||||
FinishGCArenaLists(rt);
|
||||
|
||||
DestroyEmptyGCChunks(rt, true);
|
||||
JS_ASSERT(rt->gcEmptyChunks.length() == 0);
|
||||
|
||||
if (rt->gcRootsHash.ops) {
|
||||
#ifdef DEBUG
|
||||
CheckLeakedRoots(rt);
|
||||
|
@ -3098,6 +3120,7 @@ GC(JSContext *cx, JSGCInvocationKind gckind GCTIMER_PARAM)
|
|||
* use js_IsAboutToBeFinalized().
|
||||
*/
|
||||
arenaReleaser.freeArenas(rt);
|
||||
DestroyEmptyGCChunks(rt, false);
|
||||
TIMESTAMP(gcTimer.sweepDestroyEnd);
|
||||
|
||||
#ifdef JS_THREADSAFE
|
||||
|
|
Загрузка…
Ссылка в новой задаче