зеркало из https://github.com/mozilla/gecko-dev.git
Bug 957723 - Decommit unused portions of the nursery; r=jonco
This commit is contained in:
Родитель
af909242bc
Коммит
0988607fd4
|
@ -181,7 +181,8 @@ struct GCSizes
|
|||
{
|
||||
#define FOR_EACH_SIZE(macro) \
|
||||
macro(_, _, marker) \
|
||||
macro(_, _, nursery) \
|
||||
macro(_, _, nurseryCommitted) \
|
||||
macro(_, _, nurseryDecommitted) \
|
||||
macro(_, _, storeBufferVals) \
|
||||
macro(_, _, storeBufferCells) \
|
||||
macro(_, _, storeBufferSlots) \
|
||||
|
|
|
@ -70,14 +70,14 @@ js::Nursery::init()
|
|||
|
||||
JSRuntime *rt = runtime();
|
||||
rt->gcNurseryStart_ = uintptr_t(heap);
|
||||
currentStart_ = start();
|
||||
rt->gcNurseryEnd_ = chunk(LastNurseryChunk).end();
|
||||
numActiveChunks_ = 1;
|
||||
setCurrentChunk(0);
|
||||
#ifdef JS_GC_ZEAL
|
||||
JS_POISON(heap, FreshNursery, NurserySize);
|
||||
#endif
|
||||
for (int i = 0; i < NumNurseryChunks; ++i)
|
||||
chunk(i).trailer.runtime = rt;
|
||||
setCurrentChunk(0);
|
||||
updateDecommittedRegion();
|
||||
|
||||
#ifdef PROFILE_NURSERY
|
||||
char *env = getenv("JS_MINORGC_TIME");
|
||||
|
@ -103,6 +103,7 @@ js::Nursery::enable()
|
|||
return;
|
||||
numActiveChunks_ = 1;
|
||||
setCurrentChunk(0);
|
||||
currentStart_ = position();
|
||||
#ifdef JS_GC_ZEAL
|
||||
if (runtime()->gcZeal_ == ZealGenerationalGCValue)
|
||||
enterZealMode();
|
||||
|
@ -112,11 +113,12 @@ js::Nursery::enable()
|
|||
void
|
||||
js::Nursery::disable()
|
||||
{
|
||||
JS_ASSERT(isEmpty());
|
||||
if (!isEnabled())
|
||||
return;
|
||||
JS_ASSERT(isEmpty());
|
||||
numActiveChunks_ = 0;
|
||||
currentEnd_ = 0;
|
||||
updateDecommittedRegion();
|
||||
}
|
||||
|
||||
bool
|
||||
|
@ -168,6 +170,7 @@ js::Nursery::allocate(size_t size)
|
|||
{
|
||||
JS_ASSERT(isEnabled());
|
||||
JS_ASSERT(!runtime()->isHeapBusy());
|
||||
JS_ASSERT(position() >= currentStart_);
|
||||
|
||||
if (position() + size > currentEnd()) {
|
||||
if (currentChunk_ + 1 == numActiveChunks_)
|
||||
|
@ -862,33 +865,35 @@ js::Nursery::sweep(JSRuntime *rt)
|
|||
chunk(i).trailer.runtime = runtime();
|
||||
|
||||
if (rt->gcZeal_ == ZealGenerationalGCValue) {
|
||||
/* Undo any grow or shrink the collection may have done. */
|
||||
numActiveChunks_ = NumNurseryChunks;
|
||||
MOZ_ASSERT(numActiveChunks_ == NumNurseryChunks);
|
||||
|
||||
/* Only reset the alloc point when we are close to the end. */
|
||||
if (currentChunk_ + 1 == NumNurseryChunks)
|
||||
setCurrentChunk(0);
|
||||
|
||||
/* Set current start position for isEmpty checks. */
|
||||
currentStart_ = position();
|
||||
|
||||
return;
|
||||
}
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
setCurrentChunk(0);
|
||||
}
|
||||
|
||||
setCurrentChunk(0);
|
||||
/* Set current start position for isEmpty checks. */
|
||||
currentStart_ = position();
|
||||
}
|
||||
|
||||
void
|
||||
js::Nursery::growAllocableSpace()
|
||||
{
|
||||
MOZ_ASSERT_IF(runtime()->gcZeal_ == ZealGenerationalGCValue, numActiveChunks_ == NumNurseryChunks);
|
||||
numActiveChunks_ = Min(numActiveChunks_ * 2, NumNurseryChunks);
|
||||
}
|
||||
|
||||
void
|
||||
js::Nursery::shrinkAllocableSpace()
|
||||
{
|
||||
if (runtime()->gcZeal_ == ZealGenerationalGCValue)
|
||||
return;
|
||||
numActiveChunks_ = Max(numActiveChunks_ - 1, 1);
|
||||
updateDecommittedRegion();
|
||||
}
|
||||
|
||||
#endif /* JSGC_GENERATIONAL */
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
#include "ds/BitArray.h"
|
||||
#include "gc/Heap.h"
|
||||
#include "gc/Memory.h"
|
||||
#include "js/GCAPI.h"
|
||||
#include "js/HashTable.h"
|
||||
#include "js/HeapAPI.h"
|
||||
|
@ -29,6 +30,7 @@ namespace js {
|
|||
|
||||
class ObjectElements;
|
||||
class HeapSlot;
|
||||
void SetGCZeal(JSRuntime *, uint8_t, uint32_t);
|
||||
|
||||
namespace gc {
|
||||
class Cell;
|
||||
|
@ -123,27 +125,8 @@ class Nursery
|
|||
/* Forward a slots/elements pointer stored in an Ion frame. */
|
||||
void forwardBufferPointer(HeapSlot **pSlotsElems);
|
||||
|
||||
size_t sizeOfHeap() { return start() ? NurserySize : 0; }
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
/*
|
||||
* In debug and zeal builds, these bytes indicate the state of an unused
|
||||
* segment of nursery-allocated memory.
|
||||
*/
|
||||
static const uint8_t FreshNursery = 0x2a;
|
||||
static const uint8_t SweptNursery = 0x2b;
|
||||
static const uint8_t AllocatedThing = 0x2c;
|
||||
void enterZealMode() {
|
||||
if (isEnabled())
|
||||
numActiveChunks_ = NumNurseryChunks;
|
||||
}
|
||||
void leaveZealMode() {
|
||||
if (isEnabled()) {
|
||||
JS_ASSERT(isEmpty());
|
||||
setCurrentChunk(0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
size_t sizeOfHeapCommitted() { return numActiveChunks_ * gc::ChunkSize; }
|
||||
size_t sizeOfHeapDecommitted() { return (NumNurseryChunks - numActiveChunks_) * gc::ChunkSize; }
|
||||
|
||||
private:
|
||||
/*
|
||||
|
@ -156,7 +139,7 @@ class Nursery
|
|||
/* Pointer to the first unallocated byte in the nursery. */
|
||||
uintptr_t position_;
|
||||
|
||||
/* Pointer to the logic start of the Nursery. */
|
||||
/* Pointer to the logical start of the Nursery. */
|
||||
uintptr_t currentStart_;
|
||||
|
||||
/* Pointer to the last byte of space in the current chunk. */
|
||||
|
@ -211,8 +194,18 @@ class Nursery
|
|||
JS_ASSERT(chunkno < numActiveChunks_);
|
||||
currentChunk_ = chunkno;
|
||||
position_ = chunk(chunkno).start();
|
||||
currentStart_ = chunk(0).start();
|
||||
currentEnd_ = chunk(chunkno).end();
|
||||
chunk(chunkno).trailer.runtime = runtime();
|
||||
}
|
||||
|
||||
void updateDecommittedRegion() {
|
||||
#ifndef JS_GC_ZEAL
|
||||
if (numActiveChunks_ < NumNurseryChunks) {
|
||||
uintptr_t decommitStart = chunk(numActiveChunks_).start();
|
||||
JS_ASSERT(decommitStart == AlignBytes(decommitStart, 1 << 20));
|
||||
gc::MarkPagesUnused(runtime(), (void *)decommitStart, heapEnd() - decommitStart);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE uintptr_t allocationEnd() const {
|
||||
|
@ -284,11 +277,36 @@ class Nursery
|
|||
|
||||
static void MinorGCCallback(JSTracer *trc, void **thingp, JSGCTraceKind kind);
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
/*
|
||||
* In debug and zeal builds, these bytes indicate the state of an unused
|
||||
* segment of nursery-allocated memory.
|
||||
*/
|
||||
static const uint8_t FreshNursery = 0x2a;
|
||||
static const uint8_t SweptNursery = 0x2b;
|
||||
static const uint8_t AllocatedThing = 0x2c;
|
||||
void enterZealMode() {
|
||||
if (isEnabled())
|
||||
numActiveChunks_ = NumNurseryChunks;
|
||||
}
|
||||
void leaveZealMode() {
|
||||
if (isEnabled()) {
|
||||
JS_ASSERT(isEmpty());
|
||||
setCurrentChunk(0);
|
||||
currentStart_ = start();
|
||||
}
|
||||
}
|
||||
#else
|
||||
void enterZealMode() {}
|
||||
void leaveZealMode() {}
|
||||
#endif
|
||||
|
||||
friend class gc::MinorCollectionTracer;
|
||||
friend class jit::CodeGenerator;
|
||||
friend class jit::MacroAssembler;
|
||||
friend class jit::ICStubCompiler;
|
||||
friend class jit::BaselineCompiler;
|
||||
friend void SetGCZeal(JSRuntime *, uint8_t, uint32_t);
|
||||
};
|
||||
|
||||
} /* namespace js */
|
||||
|
|
|
@ -628,7 +628,8 @@ JSRuntime::addSizeOfIncludingThis(mozilla::MallocSizeOf mallocSizeOf, JS::Runtim
|
|||
|
||||
rtSizes->gc.marker += gcMarker.sizeOfExcludingThis(mallocSizeOf);
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
rtSizes->gc.nursery += gcNursery.sizeOfHeap();
|
||||
rtSizes->gc.nurseryCommitted += gcNursery.sizeOfHeapCommitted();
|
||||
rtSizes->gc.nurseryDecommitted += gcNursery.sizeOfHeapDecommitted();
|
||||
gcStoreBuffer.addSizeOfExcludingThis(mallocSizeOf, &rtSizes->gc);
|
||||
#endif
|
||||
}
|
||||
|
|
|
@ -2347,9 +2347,9 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats,
|
|||
KIND_HEAP, rtStats.runtime.gc.marker,
|
||||
"The GC mark stack and gray roots.");
|
||||
|
||||
RREPORT_BYTES(rtPath + NS_LITERAL_CSTRING("runtime/gc/nursery"),
|
||||
KIND_NONHEAP, rtStats.runtime.gc.nursery,
|
||||
"The GC nursery.");
|
||||
RREPORT_BYTES(rtPath + NS_LITERAL_CSTRING("runtime/gc/nursery-committed"),
|
||||
KIND_NONHEAP, rtStats.runtime.gc.nurseryCommitted,
|
||||
"Memory being used by the GC's nursery.");
|
||||
|
||||
RREPORT_BYTES(rtPath + NS_LITERAL_CSTRING("runtime/gc/store-buffer/vals"),
|
||||
KIND_HEAP, rtStats.runtime.gc.storeBufferVals,
|
||||
|
@ -2393,6 +2393,11 @@ ReportJSRuntimeExplicitTreeStats(const JS::RuntimeStats &rtStats,
|
|||
"GC arenas in non-empty chunks that is decommitted, i.e. it takes up "
|
||||
"address space but no physical memory or swap space.");
|
||||
|
||||
REPORT_GC_BYTES(rtPath2 + NS_LITERAL_CSTRING("runtime/gc/nursery-decommitted"),
|
||||
rtStats.runtime.gc.nurseryDecommitted,
|
||||
"Memory allocated to the GC's nursery this is decommitted, i.e. it takes up "
|
||||
"address space but no physical memory or swap space.");
|
||||
|
||||
REPORT_GC_BYTES(rtPath + NS_LITERAL_CSTRING("gc-heap/unused-chunks"),
|
||||
rtStats.gcHeapUnusedChunks,
|
||||
"Empty GC chunks which will soon be released unless claimed for new "
|
||||
|
|
Загрузка…
Ссылка в новой задаче