--- a/js/src/jsgc.cpp 2012-12-15 17:19:27.919779697 +0100 +++ b/js/src/jsgc.cpp 2012-12-15 17:22:09.267787141 +0100 @@ -92,16 +92,18 @@ #include "vm/Debugger.h" #include "vm/String.h" #include "jsobjinlines.h" #include "vm/CallObject-inl.h" #include "vm/String-inl.h" +#include "yarr/PageBlock.h" /* for pageSize() */ + #ifdef MOZ_VALGRIND # define JS_VALGRIND #endif #ifdef JS_VALGRIND # include #endif using namespace mozilla; @@ -2380,16 +2382,23 @@ ReleaseObservedTypes(JSContext *cx) } return releaseTypes; } static void DecommitFreePages(JSContext *cx) { + /* + * If the ArenaSize is smaller than a memory page, we don't attempt to + * decommit anything because DecommitMemory() would always fail. + */ + if (ArenaSize < pageSize()) + return; + JSRuntime *rt = cx->runtime; for (GCChunkSet::Range r(rt->gcChunkSet.all()); !r.empty(); r.popFront()) { Chunk *chunk = r.front(); while (chunk) { ArenaHeader *aheader = static_cast(chunk->info.freeArenasHead); /* @@ -2402,24 +2411,23 @@ DecommitFreePages(JSContext *cx) while (aheader) { /* Store aside everything we will need after decommit. */ ArenaHeader *next = aheader->next; bool success = DecommitMemory(aheader, ArenaSize); if (!success) { aheader->next = chunk->info.freeArenasHead; chunk->info.freeArenasHead = aheader; - continue; + } else { + size_t arenaOffset = Chunk::arenaIndex(reinterpret_cast(aheader)); + chunk->decommittedArenas.set(arenaOffset); + --chunk->info.numArenasFreeCommitted; + --rt->gcNumFreeArenas; } - size_t arenaOffset = Chunk::arenaIndex(reinterpret_cast(aheader)); - chunk->decommittedArenas.set(arenaOffset); - --chunk->info.numArenasFreeCommitted; - --rt->gcNumFreeArenas; - aheader = next; } chunk = chunk->info.next; } } } Signed-off-by: Stephan Schreiber