Bug 1000100 - Baseline postbarrier tidyup r=jandem

This commit is contained in:
Jon Coppeard 2014-05-01 11:34:48 +01:00
Родитель a580d15ad3
Коммит 1ca46994a4
9 изменённых файлов: 62 добавлений и 43 удалений

Просмотреть файл

@ -408,7 +408,8 @@ BaselineCompiler::emitEpilogue()
#ifdef JSGC_GENERATIONAL
// On input:
// R2.scratchReg() contains object being written to.
// Otherwise, baseline stack will be synced, so all other registers are usable as scratch.
// Called with the baseline stack synced, except for R0 which is preserved.
// All other registers are usable as scratch.
// This calls:
// void PostWriteBarrier(JSRuntime *rt, JSObject *obj);
bool
@ -418,6 +419,7 @@ BaselineCompiler::emitOutOfLinePostBarrierSlot()
Register objReg = R2.scratchReg();
GeneralRegisterSet regs(GeneralRegisterSet::All());
regs.take(R0);
regs.take(objReg);
regs.take(BaselineFrameReg);
Register scratch = regs.takeAny();
@ -428,6 +430,7 @@ BaselineCompiler::emitOutOfLinePostBarrierSlot()
#elif defined(JS_CODEGEN_MIPS)
masm.push(ra);
#endif
masm.pushValue(R0);
masm.setupUnalignedABICall(2, scratch);
masm.movePtr(ImmPtr(cx->runtime()), scratch);
@ -435,6 +438,7 @@ BaselineCompiler::emitOutOfLinePostBarrierSlot()
masm.passABIArg(objReg);
masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, PostWriteBarrier));
masm.popValue(R0);
masm.ret();
return true;
}
@ -2096,16 +2100,15 @@ BaselineCompiler::emit_JSOP_SETALIASEDVAR()
frame.push(R0);
#ifdef JSGC_GENERATIONAL
// Fully sync the stack if post-barrier is needed.
// Only R0 is live at this point.
// Scope coordinate object is already in R2.scratchReg().
frame.syncStack(0);
Register temp = R1.scratchReg();
Label skipBarrier;
masm.branchTestObject(Assembler::NotEqual, R0, &skipBarrier);
masm.branchPtrInNurseryRange(objReg, temp, &skipBarrier);
masm.branchPtrInNurseryRange(Assembler::Equal, objReg, temp, &skipBarrier);
masm.branchValueIsNurseryObject(Assembler::NotEqual, R0, temp, &skipBarrier);
masm.call(&postBarrierSlot_);
masm.call(&postBarrierSlot_); // Won't clobber R0
masm.bind(&skipBarrier);
#endif
@ -2461,11 +2464,12 @@ BaselineCompiler::emitFormalArgAccess(uint32_t arg, bool get)
frame.push(R0);
} else {
masm.patchableCallPreBarrier(argAddr, MIRType_Value);
storeValue(frame.peek(-1), argAddr, R0);
masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0);
masm.storeValue(R0, argAddr);
#ifdef JSGC_GENERATIONAL
// Fully sync the stack if post-barrier is needed.
frame.syncStack(0);
MOZ_ASSERT(frame.numUnsyncedSlots() == 0);
Register temp = R1.scratchReg();
// Reload the arguments object
@ -2473,7 +2477,9 @@ BaselineCompiler::emitFormalArgAccess(uint32_t arg, bool get)
masm.loadPtr(Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfArgsObj()), reg);
Label skipBarrier;
masm.branchPtrInNurseryRange(reg, temp, &skipBarrier);
masm.branchPtrInNurseryRange(Assembler::Equal, reg, temp, &skipBarrier);
masm.branchValueIsNurseryObject(Assembler::NotEqual, R0, temp, &skipBarrier);
masm.call(&postBarrierSlot_);

Просмотреть файл

@ -734,16 +734,9 @@ inline bool
ICStubCompiler::emitPostWriteBarrierSlot(MacroAssembler &masm, Register obj, ValueOperand val,
Register scratch, GeneralRegisterSet saveRegs)
{
Nursery &nursery = cx->runtime()->gc.nursery;
Label skipBarrier;
masm.branchTestObject(Assembler::NotEqual, val, &skipBarrier);
masm.branchPtrInNurseryRange(obj, scratch, &skipBarrier);
Register valReg = masm.extractObject(val, scratch);
masm.branchPtr(Assembler::Below, valReg, ImmWord(nursery.start()), &skipBarrier);
masm.branchPtr(Assembler::AboveOrEqual, valReg, ImmWord(nursery.heapEnd()), &skipBarrier);
masm.branchPtrInNurseryRange(Assembler::Equal, obj, scratch, &skipBarrier);
masm.branchValueIsNurseryObject(Assembler::NotEqual, val, scratch, &skipBarrier);
// void PostWriteBarrier(JSRuntime *rt, JSObject *obj);
#if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS)

Просмотреть файл

@ -1875,10 +1875,11 @@ CodeGenerator::visitPostWriteBarrierO(LPostWriteBarrierO *lir)
JS_ASSERT(!nursery.isInside(&lir->object()->toConstant()->toObject()));
#endif
} else {
masm.branchPtrInNurseryRange(ToRegister(lir->object()), temp, ool->rejoin());
masm.branchPtrInNurseryRange(Assembler::Equal, ToRegister(lir->object()), temp,
ool->rejoin());
}
masm.branchPtrInNurseryRange(ToRegister(lir->value()), temp, ool->entry());
masm.branchPtrInNurseryRange(Assembler::Equal, ToRegister(lir->value()), temp, ool->entry());
masm.bind(ool->rejoin());
#endif
@ -1901,11 +1902,12 @@ CodeGenerator::visitPostWriteBarrierV(LPostWriteBarrierV *lir)
JS_ASSERT(!nursery.isInside(&lir->object()->toConstant()->toObject()));
#endif
} else {
masm.branchPtrInNurseryRange(ToRegister(lir->object()), temp, ool->rejoin());
masm.branchPtrInNurseryRange(Assembler::Equal, ToRegister(lir->object()), temp,
ool->rejoin());
}
ValueOperand value = ToValue(lir, LPostWriteBarrierV::Input);
masm.branchValueIsNurseryObject(value, temp, ool->entry());
masm.branchValueIsNurseryObject(Assembler::Equal, value, temp, ool->entry());
masm.bind(ool->rejoin());
#endif

Просмотреть файл

@ -4350,8 +4350,10 @@ MacroAssemblerARMCompat::jumpWithPatch(RepatchLabel *label, Condition cond)
#ifdef JSGC_GENERATIONAL
void
MacroAssemblerARMCompat::branchPtrInNurseryRange(Register ptr, Register temp, Label *label)
MacroAssemblerARMCompat::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp,
Label *label)
{
JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
JS_ASSERT(ptr != temp);
JS_ASSERT(ptr != secondScratchReg_);
@ -4360,16 +4362,20 @@ MacroAssemblerARMCompat::branchPtrInNurseryRange(Register ptr, Register temp, La
ma_mov(Imm32(startChunk), secondScratchReg_);
as_rsb(secondScratchReg_, secondScratchReg_, lsr(ptr, Nursery::ChunkShift));
branch32(Assembler::Below, secondScratchReg_, Imm32(Nursery::NumNurseryChunks), label);
branch32(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
secondScratchReg_, Imm32(Nursery::NumNurseryChunks), label);
}
void
MacroAssemblerARMCompat::branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label)
MacroAssemblerARMCompat::branchValueIsNurseryObject(Condition cond, ValueOperand value,
Register temp, Label *label)
{
JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
Label done;
branchTestObject(Assembler::NotEqual, value, &done);
branchPtrInNurseryRange(value.payloadReg(), temp, label);
branchTestObject(Assembler::NotEqual, value, cond == Assembler::Equal ? &done : label);
branchPtrInNurseryRange(cond, value.payloadReg(), temp, label);
bind(&done);
}

Просмотреть файл

@ -1599,8 +1599,8 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM
}
#ifdef JSGC_GENERATIONAL
void branchPtrInNurseryRange(Register ptr, Register temp, Label *label);
void branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label);
void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label *label);
void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, Label *label);
#endif
};

Просмотреть файл

@ -370,27 +370,33 @@ MacroAssemblerX64::handleFailureWithHandlerTail()
#ifdef JSGC_GENERATIONAL
void
MacroAssemblerX64::branchPtrInNurseryRange(Register ptr, Register temp, Label *label)
MacroAssemblerX64::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label *label)
{
JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
JS_ASSERT(ptr != temp);
JS_ASSERT(ptr != ScratchReg);
const Nursery &nursery = GetIonContext()->runtime->gcNursery();
movePtr(ImmWord(-ptrdiff_t(nursery.start())), ScratchReg);
addPtr(ptr, ScratchReg);
branchPtr(Assembler::Below, ScratchReg, Imm32(Nursery::NurserySize), label);
branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
ScratchReg, Imm32(Nursery::NurserySize), label);
}
void
MacroAssemblerX64::branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label)
MacroAssemblerX64::branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp,
Label *label)
{
JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
// 'Value' representing the start of the nursery tagged as a JSObject
const Nursery &nursery = GetIonContext()->runtime->gcNursery();
Value start = ObjectValue(*reinterpret_cast<JSObject *>(nursery.start()));
movePtr(ImmWord(-ptrdiff_t(start.asRawBits())), ScratchReg);
addPtr(value.valueReg(), ScratchReg);
branchPtr(Assembler::Below, ScratchReg, Imm32(Nursery::NurserySize), label);
branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
ScratchReg, Imm32(Nursery::NurserySize), label);
}
#endif

Просмотреть файл

@ -1334,8 +1334,8 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared
}
#ifdef JSGC_GENERATIONAL
void branchPtrInNurseryRange(Register ptr, Register temp, Label *label);
void branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label);
void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label *label);
void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, Label *label);
#endif
};

Просмотреть файл

@ -390,24 +390,30 @@ MacroAssemblerX86::branchTestValue(Condition cond, const ValueOperand &value, co
#ifdef JSGC_GENERATIONAL
void
MacroAssemblerX86::branchPtrInNurseryRange(Register ptr, Register temp, Label *label)
MacroAssemblerX86::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp,
Label *label)
{
JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
JS_ASSERT(ptr != temp);
JS_ASSERT(temp != InvalidReg); // A temp register is required for x86.
const Nursery &nursery = GetIonContext()->runtime->gcNursery();
movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
addPtr(ptr, temp);
branchPtr(Assembler::Below, temp, Imm32(Nursery::NurserySize), label);
branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual,
temp, Imm32(Nursery::NurserySize), label);
}
void
MacroAssemblerX86::branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label)
MacroAssemblerX86::branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp,
Label *label)
{
JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual);
Label done;
branchTestObject(Assembler::NotEqual, value, &done);
branchPtrInNurseryRange(value.payloadReg(), temp, label);
branchTestObject(Assembler::NotEqual, value, cond == Assembler::Equal ? &done : label);
branchPtrInNurseryRange(cond, value.payloadReg(), temp, label);
bind(&done);
}

Просмотреть файл

@ -1124,8 +1124,8 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared
}
#ifdef JSGC_GENERATIONAL
void branchPtrInNurseryRange(Register ptr, Register temp, Label *label);
void branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label);
void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label *label);
void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, Label *label);
#endif
};