Bug 1245485 - Only decommit newly unused Nursery Chunks; r=sfink

This commit is contained in:
Terrence Cole 2016-02-09 15:19:37 -08:00
parent 25ee4eb1d3
commit 2d082fa30b
2 changed files with 32 additions and 29 deletions

View File

@ -82,10 +82,10 @@ js::Nursery::init(uint32_t maxNurseryBytes)
heapStart_ = uintptr_t(heap);
heapEnd_ = heapStart_ + nurserySize();
currentStart_ = start();
numActiveChunks_ = 1;
numActiveChunks_ = numNurseryChunks_;
JS_POISON(heap, JS_FRESH_NURSERY_PATTERN, nurserySize());
updateNumActiveChunks(1);
setCurrentChunk(0);
updateDecommittedRegion();
char* env = getenv("JS_GC_PROFILE_NURSERY");
if (env) {
@ -110,24 +110,6 @@ js::Nursery::~Nursery()
js_delete(freeMallocedBuffersTask);
}
void
js::Nursery::updateDecommittedRegion()
{
#ifndef JS_GC_ZEAL
if (numActiveChunks_ < numNurseryChunks_) {
// Bug 994054: madvise on MacOS is too slow to make this
// optimization worthwhile.
# ifndef XP_DARWIN
uintptr_t decommitStart = chunk(numActiveChunks_).start();
uintptr_t decommitSize = heapEnd() - decommitStart;
MOZ_ASSERT(decommitStart == AlignBytes(decommitStart, Alignment));
MOZ_ASSERT(decommitSize == AlignBytes(decommitStart, Alignment));
MarkPagesUnused((void*)decommitStart, decommitSize);
# endif
}
#endif
}
void
js::Nursery::enable()
{
@ -135,7 +117,7 @@ js::Nursery::enable()
MOZ_ASSERT(!runtime()->gc.isVerifyPreBarriersEnabled());
if (isEnabled())
return;
numActiveChunks_ = 1;
updateNumActiveChunks(1);
setCurrentChunk(0);
currentStart_ = position();
#ifdef JS_GC_ZEAL
@ -150,9 +132,8 @@ js::Nursery::disable()
MOZ_ASSERT(isEmpty());
if (!isEnabled())
return;
numActiveChunks_ = 0;
updateNumActiveChunks(0);
currentEnd_ = 0;
updateDecommittedRegion();
}
bool
@ -707,7 +688,7 @@ js::Nursery::growAllocableSpace()
MOZ_ASSERT_IF(runtime()->hasZealMode(ZealMode::GenerationalGC),
numActiveChunks_ == numNurseryChunks_);
#endif
numActiveChunks_ = Min(numActiveChunks_ * 2, numNurseryChunks_);
updateNumActiveChunks(Min(numActiveChunks_ * 2, numNurseryChunks_));
}
void
@ -717,6 +698,28 @@ js::Nursery::shrinkAllocableSpace()
if (runtime()->hasZealMode(ZealMode::GenerationalGC))
return;
#endif
numActiveChunks_ = Max(numActiveChunks_ - 1, 1);
updateDecommittedRegion();
updateNumActiveChunks(Max(numActiveChunks_ - 1, 1));
}
void
js::Nursery::updateNumActiveChunks(int newCount)
{
#ifndef JS_GC_ZEAL
int priorChunks = numActiveChunks_;
#endif
numActiveChunks_ = newCount;
// In zeal mode, we want to keep the unused memory poisoned so that we
// will crash sooner. Avoid decommit in that case to avoid having the
// system zero the pages.
#ifndef JS_GC_ZEAL
if (numActiveChunks_ < priorChunks) {
uintptr_t decommitStart = chunk(numActiveChunks_).start();
uintptr_t decommitSize = chunk(priorChunks - 1).start() + ChunkSize - decommitStart;
MOZ_ASSERT(decommitSize != 0);
MOZ_ASSERT(decommitStart == AlignBytes(decommitStart, Alignment));
MOZ_ASSERT(decommitSize == AlignBytes(decommitSize, Alignment));
MarkPagesUnused((void*)decommitStart, decommitSize);
}
#endif // !defined(JS_GC_ZEAL)
}

View File

@ -303,8 +303,8 @@ class Nursery
struct NurseryChunkLayout {
char data[NurseryChunkUsableSize];
gc::ChunkTrailer trailer;
uintptr_t start() { return uintptr_t(&data); }
uintptr_t end() { return uintptr_t(&trailer); }
uintptr_t start() const { return uintptr_t(&data); }
uintptr_t end() const { return uintptr_t(&trailer); }
};
static_assert(sizeof(NurseryChunkLayout) == gc::ChunkSize,
"Nursery chunk size must match gc::Chunk size.");
@ -328,7 +328,7 @@ class Nursery
initChunk(chunkno);
}
void updateDecommittedRegion();
void updateNumActiveChunks(int newCount);
MOZ_ALWAYS_INLINE uintptr_t allocationEnd() const {
MOZ_ASSERT(numActiveChunks_ > 0);