mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1034621 - Make it possible to configure nursery size r=terrence
--HG-- extra : rebase_source : 7bdf2b2b15712a31baa34501ef4adcfe0ef8bf7d
This commit is contained in:
parent
e339908a91
commit
acf7c3159c
@ -88,6 +88,9 @@ AssertGCThingHasType(js::gc::Cell *cell, JSGCTraceKind kind) {}
|
||||
namespace JS {
|
||||
struct Zone;
|
||||
|
||||
/* Default size for the generational nursery in bytes. */
|
||||
const uint32_t DefaultNurseryBytes = 16 * 1024 * 1024;
|
||||
|
||||
/*
|
||||
* We cannot expose the class hierarchy: the implementation is hidden. Instead
|
||||
* we provide cast functions with strong debug-mode assertions.
|
||||
|
@ -131,7 +131,7 @@ class GCRuntime
|
||||
{
|
||||
public:
|
||||
explicit GCRuntime(JSRuntime *rt);
|
||||
bool init(uint32_t maxbytes);
|
||||
bool init(uint32_t maxbytes, uint32_t maxNurseryBytes);
|
||||
void finish();
|
||||
|
||||
inline int zeal();
|
||||
|
@ -49,20 +49,27 @@ static int64_t GCReportThreshold = INT64_MAX;
|
||||
#endif
|
||||
|
||||
bool
|
||||
js::Nursery::init()
|
||||
js::Nursery::init(uint32_t maxNurseryBytes)
|
||||
{
|
||||
/* maxNurseryBytes parameter is rounded down to a multiple of chunk size. */
|
||||
numNurseryChunks_ = maxNurseryBytes >> ChunkShift;
|
||||
|
||||
/* If no chunks are specified then the nursery is permenantly disabled. */
|
||||
if (numNurseryChunks_ == 0)
|
||||
return true;
|
||||
|
||||
if (!hugeSlots.init())
|
||||
return false;
|
||||
|
||||
void *heap = runtime()->gc.pageAllocator.mapAlignedPages(NurserySize, Alignment);
|
||||
void *heap = runtime()->gc.pageAllocator.mapAlignedPages(nurserySize(), Alignment);
|
||||
if (!heap)
|
||||
return false;
|
||||
|
||||
heapStart_ = uintptr_t(heap);
|
||||
heapEnd_ = heapStart_ + NurserySize;
|
||||
heapEnd_ = heapStart_ + nurserySize();
|
||||
currentStart_ = start();
|
||||
numActiveChunks_ = 1;
|
||||
JS_POISON(heap, JS_FRESH_NURSERY_PATTERN, NurserySize);
|
||||
JS_POISON(heap, JS_FRESH_NURSERY_PATTERN, nurserySize());
|
||||
setCurrentChunk(0);
|
||||
updateDecommittedRegion();
|
||||
|
||||
@ -79,14 +86,14 @@ js::Nursery::init()
|
||||
js::Nursery::~Nursery()
|
||||
{
|
||||
if (start())
|
||||
runtime()->gc.pageAllocator.unmapPages((void *)start(), NurserySize);
|
||||
runtime()->gc.pageAllocator.unmapPages((void *)start(), nurserySize());
|
||||
}
|
||||
|
||||
void
|
||||
js::Nursery::updateDecommittedRegion()
|
||||
{
|
||||
#ifndef JS_GC_ZEAL
|
||||
if (numActiveChunks_ < NumNurseryChunks) {
|
||||
if (numActiveChunks_ < numNurseryChunks_) {
|
||||
// Bug 994054: madvise on MacOS is too slow to make this
|
||||
// optimization worthwhile.
|
||||
# ifndef XP_MACOSX
|
||||
@ -140,7 +147,7 @@ js::Nursery::isEmpty() const
|
||||
void
|
||||
js::Nursery::enterZealMode() {
|
||||
if (isEnabled())
|
||||
numActiveChunks_ = NumNurseryChunks;
|
||||
numActiveChunks_ = numNurseryChunks_;
|
||||
}
|
||||
|
||||
void
|
||||
@ -951,15 +958,15 @@ js::Nursery::sweep()
|
||||
{
|
||||
#ifdef JS_GC_ZEAL
|
||||
/* Poison the nursery contents so touching a freed object will crash. */
|
||||
JS_POISON((void *)start(), JS_SWEPT_NURSERY_PATTERN, NurserySize);
|
||||
for (int i = 0; i < NumNurseryChunks; ++i)
|
||||
JS_POISON((void *)start(), JS_SWEPT_NURSERY_PATTERN, nurserySize());
|
||||
for (int i = 0; i < numNurseryChunks_; ++i)
|
||||
initChunk(i);
|
||||
|
||||
if (runtime()->gcZeal() == ZealGenerationalGCValue) {
|
||||
MOZ_ASSERT(numActiveChunks_ == NumNurseryChunks);
|
||||
MOZ_ASSERT(numActiveChunks_ == numNurseryChunks_);
|
||||
|
||||
/* Only reset the alloc point when we are close to the end. */
|
||||
if (currentChunk_ + 1 == NumNurseryChunks)
|
||||
if (currentChunk_ + 1 == numNurseryChunks_)
|
||||
setCurrentChunk(0);
|
||||
} else
|
||||
#endif
|
||||
@ -981,9 +988,9 @@ js::Nursery::growAllocableSpace()
|
||||
{
|
||||
#ifdef JS_GC_ZEAL
|
||||
MOZ_ASSERT_IF(runtime()->gcZeal() == ZealGenerationalGCValue,
|
||||
numActiveChunks_ == NumNurseryChunks);
|
||||
numActiveChunks_ == numNurseryChunks_);
|
||||
#endif
|
||||
numActiveChunks_ = Min(numActiveChunks_ * 2, NumNurseryChunks);
|
||||
numActiveChunks_ = Min(numActiveChunks_ * 2, numNurseryChunks_);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -86,25 +86,27 @@ class RelocationOverlay
|
||||
class Nursery
|
||||
{
|
||||
public:
|
||||
static const int NumNurseryChunks = 16;
|
||||
static const int LastNurseryChunk = NumNurseryChunks - 1;
|
||||
static const size_t Alignment = gc::ChunkSize;
|
||||
static const size_t ChunkShift = gc::ChunkShift;
|
||||
static const size_t NurserySize = gc::ChunkSize * NumNurseryChunks;
|
||||
|
||||
explicit Nursery(JSRuntime *rt)
|
||||
: runtime_(rt),
|
||||
position_(0),
|
||||
heapStart_(0),
|
||||
heapEnd_(0),
|
||||
currentStart_(0),
|
||||
currentEnd_(0),
|
||||
heapStart_(0),
|
||||
heapEnd_(0),
|
||||
currentChunk_(0),
|
||||
numActiveChunks_(0)
|
||||
numActiveChunks_(0),
|
||||
numNurseryChunks_(0)
|
||||
{}
|
||||
~Nursery();
|
||||
|
||||
bool init();
|
||||
bool init(uint32_t numNurseryChunks);
|
||||
|
||||
bool exists() const { return numNurseryChunks_ != 0; }
|
||||
size_t numChunks() const { return numNurseryChunks_; }
|
||||
size_t nurserySize() const { return numNurseryChunks_ << ChunkShift; }
|
||||
|
||||
void enable();
|
||||
void disable();
|
||||
@ -170,7 +172,7 @@ class Nursery
|
||||
return numActiveChunks_ * gc::ChunkSize;
|
||||
}
|
||||
size_t sizeOfHeapDecommitted() const {
|
||||
return (NumNurseryChunks - numActiveChunks_) * gc::ChunkSize;
|
||||
return (numNurseryChunks_ - numActiveChunks_) * gc::ChunkSize;
|
||||
}
|
||||
size_t sizeOfHugeSlots(mozilla::MallocSizeOf mallocSizeOf) const {
|
||||
size_t total = 0;
|
||||
@ -204,22 +206,25 @@ class Nursery
|
||||
/* Pointer to the first unallocated byte in the nursery. */
|
||||
uintptr_t position_;
|
||||
|
||||
/* Pointer to first and last address of the total nursery allocation. */
|
||||
uintptr_t heapStart_;
|
||||
uintptr_t heapEnd_;
|
||||
|
||||
/* Pointer to the logical start of the Nursery. */
|
||||
uintptr_t currentStart_;
|
||||
|
||||
/* Pointer to the last byte of space in the current chunk. */
|
||||
uintptr_t currentEnd_;
|
||||
|
||||
/* Pointer to first and last address of the total nursery allocation. */
|
||||
uintptr_t heapStart_;
|
||||
uintptr_t heapEnd_;
|
||||
|
||||
/* The index of the chunk that is currently being allocated from. */
|
||||
int currentChunk_;
|
||||
|
||||
/* The index after the last chunk that we will allocate from. */
|
||||
int numActiveChunks_;
|
||||
|
||||
/* Number of chunks allocated for the nursery. */
|
||||
int numNurseryChunks_;
|
||||
|
||||
/*
|
||||
* The set of externally malloced slots potentially kept live by objects
|
||||
* stored in the nursery. Any external slots that do not belong to a
|
||||
@ -243,7 +248,7 @@ class Nursery
|
||||
static_assert(sizeof(NurseryChunkLayout) == gc::ChunkSize,
|
||||
"Nursery chunk size must match gc::Chunk size.");
|
||||
NurseryChunkLayout &chunk(int index) const {
|
||||
JS_ASSERT(index < NumNurseryChunks);
|
||||
JS_ASSERT(index < numNurseryChunks_);
|
||||
JS_ASSERT(start());
|
||||
return reinterpret_cast<NurseryChunkLayout *>(start())[index];
|
||||
}
|
||||
@ -256,7 +261,7 @@ class Nursery
|
||||
}
|
||||
|
||||
MOZ_ALWAYS_INLINE void setCurrentChunk(int chunkno) {
|
||||
JS_ASSERT(chunkno < NumNurseryChunks);
|
||||
JS_ASSERT(chunkno < numNurseryChunks_);
|
||||
JS_ASSERT(chunkno < numActiveChunks_);
|
||||
currentChunk_ = chunkno;
|
||||
position_ = chunk(chunkno).start();
|
||||
|
@ -5285,7 +5285,7 @@ ICSetElem_Dense::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
masm.storeValue(tmpVal, element);
|
||||
regs.add(key);
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
{
|
||||
if (cx->runtime()->gc.nursery.exists()) {
|
||||
Register r = regs.takeAny();
|
||||
GeneralRegisterSet saveRegs;
|
||||
emitPostWriteBarrierSlot(masm, obj, tmpVal, r, saveRegs);
|
||||
@ -5468,7 +5468,7 @@ ICSetElemDenseAddCompiler::generateStubCode(MacroAssembler &masm)
|
||||
masm.storeValue(tmpVal, element);
|
||||
regs.add(key);
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
{
|
||||
if (cx->runtime()->gc.nursery.exists()) {
|
||||
Register r = regs.takeAny();
|
||||
GeneralRegisterSet saveRegs;
|
||||
emitPostWriteBarrierSlot(masm, obj, tmpVal, r, saveRegs);
|
||||
@ -7691,7 +7691,7 @@ ICSetProp_Native::Compiler::generateStubCode(MacroAssembler &masm)
|
||||
if (holderReg != objReg)
|
||||
regs.add(holderReg);
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
{
|
||||
if (cx->runtime()->gc.nursery.exists()) {
|
||||
Register scr = regs.takeAny();
|
||||
GeneralRegisterSet saveRegs;
|
||||
saveRegs.add(R1);
|
||||
@ -7813,7 +7813,7 @@ ICSetPropNativeAddCompiler::generateStubCode(MacroAssembler &masm)
|
||||
regs.add(holderReg);
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
{
|
||||
if (cx->runtime()->gc.nursery.exists()) {
|
||||
Register scr = regs.takeAny();
|
||||
GeneralRegisterSet saveRegs;
|
||||
saveRegs.add(R1);
|
||||
|
@ -6543,6 +6543,10 @@ jit::TypeSetIncludes(types::TypeSet *types, MIRType input, types::TypeSet *input
|
||||
bool
|
||||
jit::NeedsPostBarrier(CompileInfo &info, MDefinition *value)
|
||||
{
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (!GetIonContext()->runtime->gcNursery().exists())
|
||||
return false;
|
||||
#endif
|
||||
return info.executionMode() != ParallelExecution && value->mightBeType(MIRType_Object);
|
||||
}
|
||||
|
||||
|
@ -4573,7 +4573,7 @@ MacroAssemblerARMCompat::branchPtrInNurseryRange(Condition cond, Register ptr, R
|
||||
ma_mov(Imm32(startChunk), secondScratchReg_);
|
||||
as_rsb(secondScratchReg_, secondScratchReg_, lsr(ptr, Nursery::ChunkShift));
|
||||
branch32(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
|
||||
secondScratchReg_, Imm32(Nursery::NumNurseryChunks), label);
|
||||
secondScratchReg_, Imm32(nursery.numChunks()), label);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -3516,7 +3516,7 @@ MacroAssemblerMIPSCompat::branchPtrInNurseryRange(Condition cond, Register ptr,
|
||||
movePtr(ImmWord(-ptrdiff_t(nursery.start())), SecondScratchReg);
|
||||
addPtr(ptr, SecondScratchReg);
|
||||
branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
|
||||
SecondScratchReg, Imm32(Nursery::NurserySize), label);
|
||||
SecondScratchReg, Imm32(nursery.nurserySize()), label);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -419,7 +419,7 @@ MacroAssemblerX64::branchPtrInNurseryRange(Condition cond, Register ptr, Registe
|
||||
movePtr(ImmWord(-ptrdiff_t(nursery.start())), ScratchReg);
|
||||
addPtr(ptr, ScratchReg);
|
||||
branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
|
||||
ScratchReg, Imm32(Nursery::NurserySize), label);
|
||||
ScratchReg, Imm32(nursery.nurserySize()), label);
|
||||
}
|
||||
|
||||
void
|
||||
@ -435,7 +435,7 @@ MacroAssemblerX64::branchValueIsNurseryObject(Condition cond, ValueOperand value
|
||||
movePtr(ImmWord(-ptrdiff_t(start.asRawBits())), ScratchReg);
|
||||
addPtr(value.valueReg(), ScratchReg);
|
||||
branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
|
||||
ScratchReg, Imm32(Nursery::NurserySize), label);
|
||||
ScratchReg, Imm32(nursery.nurserySize()), label);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -430,7 +430,7 @@ MacroAssemblerX86::branchPtrInNurseryRange(Condition cond, Register ptr, Registe
|
||||
movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
|
||||
addPtr(ptr, temp);
|
||||
branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
|
||||
temp, Imm32(Nursery::NurserySize), label);
|
||||
temp, Imm32(nursery.nurserySize()), label);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -636,7 +636,7 @@ JS_FRIEND_API(bool) JS::isGCEnabled() { return true; }
|
||||
#endif
|
||||
|
||||
JS_PUBLIC_API(JSRuntime *)
|
||||
JS_NewRuntime(uint32_t maxbytes, JSRuntime *parentRuntime)
|
||||
JS_NewRuntime(uint32_t maxbytes, uint32_t maxNurseryBytes, JSRuntime *parentRuntime)
|
||||
{
|
||||
MOZ_ASSERT(jsInitState == Running,
|
||||
"must call JS_Init prior to creating any JSRuntimes");
|
||||
@ -651,7 +651,7 @@ JS_NewRuntime(uint32_t maxbytes, JSRuntime *parentRuntime)
|
||||
if (!rt)
|
||||
return nullptr;
|
||||
|
||||
if (!rt->init(maxbytes)) {
|
||||
if (!rt->init(maxbytes, maxNurseryBytes)) {
|
||||
JS_DestroyRuntime(rt);
|
||||
return nullptr;
|
||||
}
|
||||
|
@ -1264,7 +1264,9 @@ extern JS_PUBLIC_API(void)
|
||||
JS_ShutDown(void);
|
||||
|
||||
extern JS_PUBLIC_API(JSRuntime *)
|
||||
JS_NewRuntime(uint32_t maxbytes, JSRuntime *parentRuntime = nullptr);
|
||||
JS_NewRuntime(uint32_t maxbytes,
|
||||
uint32_t maxNurseryBytes = JS::DefaultNurseryBytes,
|
||||
JSRuntime *parentRuntime = nullptr);
|
||||
|
||||
extern JS_PUBLIC_API(void)
|
||||
JS_DestroyRuntime(JSRuntime *rt);
|
||||
|
@ -1266,7 +1266,7 @@ GCRuntime::initZeal()
|
||||
static const int64_t JIT_SCRIPT_RELEASE_TYPES_INTERVAL = 60 * 1000 * 1000;
|
||||
|
||||
bool
|
||||
GCRuntime::init(uint32_t maxbytes)
|
||||
GCRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
lock = PR_NewLock();
|
||||
@ -1295,11 +1295,17 @@ GCRuntime::init(uint32_t maxbytes)
|
||||
#endif
|
||||
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
if (!nursery.init())
|
||||
if (!nursery.init(maxNurseryBytes))
|
||||
return false;
|
||||
|
||||
if (!storeBuffer.enable())
|
||||
return false;
|
||||
if (!nursery.isEnabled()) {
|
||||
JS_ASSERT(nursery.nurserySize() == 0);
|
||||
++rt->gc.generationalDisabled;
|
||||
} else {
|
||||
JS_ASSERT(nursery.nurserySize() > 0);
|
||||
if (!storeBuffer.enable())
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef JS_GC_ZEAL
|
||||
|
@ -2893,7 +2893,7 @@ WorkerMain(void *arg)
|
||||
{
|
||||
WorkerInput *input = (WorkerInput *) arg;
|
||||
|
||||
JSRuntime *rt = JS_NewRuntime(8L * 1024L * 1024L, input->runtime);
|
||||
JSRuntime *rt = JS_NewRuntime(8L * 1024L * 1024L, 2L * 1024L * 1024L, input->runtime);
|
||||
if (!rt) {
|
||||
js_delete(input);
|
||||
return;
|
||||
@ -6343,6 +6343,9 @@ main(int argc, char **argv, char **envp)
|
||||
"simulator.")
|
||||
|| !op.addIntOption('\0', "mips-sim-stop-at", "NUMBER", "Stop the MIPS simulator after the given "
|
||||
"NUMBER of instructions.", -1)
|
||||
#endif
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
|| !op.addIntOption('\0', "nursery-size", "SIZE-MB", "Set the maximum nursery size in MB", 16)
|
||||
#endif
|
||||
)
|
||||
{
|
||||
@ -6409,8 +6412,13 @@ main(int argc, char **argv, char **envp)
|
||||
if (!JS_Init())
|
||||
return 1;
|
||||
|
||||
size_t nurseryBytes = JS::DefaultNurseryBytes;
|
||||
#ifdef JSGC_GENERATIONAL
|
||||
nurseryBytes = op.getIntOption("nursery-size") * 1024L * 1024L;
|
||||
#endif
|
||||
|
||||
/* Use the same parameters as the browser in xpcjsruntime.cpp. */
|
||||
rt = JS_NewRuntime(32L * 1024L * 1024L);
|
||||
rt = JS_NewRuntime(32L * 1024L * 1024L, nurseryBytes);
|
||||
if (!rt)
|
||||
return 1;
|
||||
|
||||
|
@ -257,7 +257,7 @@ JitSupportsFloatingPoint()
|
||||
}
|
||||
|
||||
bool
|
||||
JSRuntime::init(uint32_t maxbytes)
|
||||
JSRuntime::init(uint32_t maxbytes, uint32_t maxNurseryBytes)
|
||||
{
|
||||
#ifdef JS_THREADSAFE
|
||||
ownerThread_ = PR_GetCurrentThread();
|
||||
@ -279,7 +279,7 @@ JSRuntime::init(uint32_t maxbytes)
|
||||
if (!threadPool.init())
|
||||
return false;
|
||||
|
||||
if (!gc.init(maxbytes))
|
||||
if (!gc.init(maxbytes, maxNurseryBytes))
|
||||
return false;
|
||||
|
||||
const char *size = getenv("JSGC_MARK_STACK_LIMIT");
|
||||
|
@ -1283,7 +1283,7 @@ struct JSRuntime : public JS::shadow::Runtime,
|
||||
JSRuntime(JSRuntime *parentRuntime);
|
||||
~JSRuntime();
|
||||
|
||||
bool init(uint32_t maxbytes);
|
||||
bool init(uint32_t maxbytes, uint32_t maxNurseryBytes);
|
||||
|
||||
JSRuntime *thisFromCtor() { return this; }
|
||||
|
||||
|
@ -476,7 +476,7 @@ CycleCollectedJSRuntime::CycleCollectedJSRuntime(JSRuntime* aParentRuntime,
|
||||
{
|
||||
mozilla::dom::InitScriptSettings();
|
||||
|
||||
mJSRuntime = JS_NewRuntime(aMaxbytes, aParentRuntime);
|
||||
mJSRuntime = JS_NewRuntime(aMaxbytes, JS::DefaultNurseryBytes, aParentRuntime);
|
||||
if (!mJSRuntime) {
|
||||
MOZ_CRASH();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user