Bug 988950 - Add a macro assembler instruction to check if a pointer is in the nursery r=jandem

This commit is contained in:
Jon Coppeard 2014-04-23 13:48:35 +01:00
parent 0d8a56a9e2
commit 7192a5c411
5 changed files with 54 additions and 36 deletions

View File

@ -416,7 +416,6 @@ BaselineCompiler::emitEpilogue()
#ifdef JSGC_GENERATIONAL
// On input:
// R2.scratchReg() contains object being written to.
// R1.scratchReg() contains slot index being written to.
// Otherwise, baseline stack will be synced, so all other registers are usable as scratch.
// This calls:
// void PostWriteBarrier(JSRuntime *rt, JSObject *obj);
@ -2101,15 +2100,13 @@ BaselineCompiler::emit_JSOP_SETALIASEDVAR()
// Fully sync the stack if post-barrier is needed.
// Scope coordinate object is already in R2.scratchReg().
frame.syncStack(0);
Register temp = R1.scratchReg();
Nursery &nursery = cx->runtime()->gcNursery;
Label skipBarrier;
Label isTenured;
masm.branchTestObject(Assembler::NotEqual, R0, &skipBarrier);
masm.branchPtr(Assembler::Below, objReg, ImmWord(nursery.start()), &isTenured);
masm.branchPtr(Assembler::Below, objReg, ImmWord(nursery.heapEnd()), &skipBarrier);
masm.branchPtrInNurseryRange(objReg, temp, &skipBarrier);
masm.bind(&isTenured);
masm.call(&postBarrierSlot_);
masm.bind(&skipBarrier);
@ -2419,6 +2416,7 @@ BaselineCompiler::emitFormalArgAccess(uint32_t arg, bool get)
#ifdef JSGC_GENERATIONAL
// Fully sync the stack if post-barrier is needed.
frame.syncStack(0);
Register temp = R1.scratchReg();
// Reload the arguments object
Register reg = R2.scratchReg();
@ -2426,11 +2424,8 @@ BaselineCompiler::emitFormalArgAccess(uint32_t arg, bool get)
Nursery &nursery = cx->runtime()->gcNursery;
Label skipBarrier;
Label isTenured;
masm.branchPtr(Assembler::Below, reg, ImmWord(nursery.start()), &isTenured);
masm.branchPtr(Assembler::Below, reg, ImmWord(nursery.heapEnd()), &skipBarrier);
masm.branchPtrInNurseryRange(reg, temp, &skipBarrier);
masm.bind(&isTenured);
masm.call(&postBarrierSlot_);
masm.bind(&skipBarrier);

View File

@ -738,10 +738,7 @@ ICStubCompiler::emitPostWriteBarrierSlot(MacroAssembler &masm, Register obj, Val
Label skipBarrier;
masm.branchTestObject(Assembler::NotEqual, val, &skipBarrier);
Label isTenured;
masm.branchPtr(Assembler::Below, obj, ImmWord(nursery.start()), &isTenured);
masm.branchPtr(Assembler::Below, obj, ImmWord(nursery.heapEnd()), &skipBarrier);
masm.bind(&isTenured);
masm.branchPtrInNurseryRange(obj, scratch, &skipBarrier);
Register valReg = masm.extractObject(val, scratch);
masm.branchPtr(Assembler::Below, valReg, ImmWord(nursery.start()), &skipBarrier);

View File

@ -1831,22 +1831,16 @@ CodeGenerator::visitPostWriteBarrierO(LPostWriteBarrierO *lir)
if (!addOutOfLineCode(ool))
return false;
const Nursery &nursery = GetIonContext()->runtime->gcNursery();
Register temp = ToRegister(lir->temp());
if (lir->object()->isConstant()) {
const Nursery &nursery = GetIonContext()->runtime->gcNursery();
JS_ASSERT(!nursery.isInside(&lir->object()->toConstant()->toObject()));
} else {
Register objreg = ToRegister(lir->object());
masm.movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
masm.addPtr(objreg, temp);
masm.branchPtr(Assembler::Below, temp, Imm32(Nursery::NurserySize), ool->rejoin());
masm.branchPtrInNurseryRange(ToRegister(lir->object()), temp, ool->rejoin());
}
Register valuereg = ToRegister(lir->value());
masm.movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
masm.addPtr(valuereg, temp);
masm.branchPtr(Assembler::Below, temp, Imm32(Nursery::NurserySize), ool->entry());
masm.branchPtrInNurseryRange(ToRegister(lir->value()), temp, ool->entry());
masm.bind(ool->rejoin());
#endif
@ -1861,27 +1855,17 @@ CodeGenerator::visitPostWriteBarrierV(LPostWriteBarrierV *lir)
if (!addOutOfLineCode(ool))
return false;
const Nursery &nursery = GetIonContext()->runtime->gcNursery();
Register temp = ToRegister(lir->temp());
if (lir->object()->isConstant()) {
const Nursery &nursery = GetIonContext()->runtime->gcNursery();
JS_ASSERT(!nursery.isInside(&lir->object()->toConstant()->toObject()));
} else {
Register temp = ToRegister(lir->temp());
Register objreg = ToRegister(lir->object());
masm.movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
masm.addPtr(objreg, temp);
masm.branchPtr(Assembler::Below, temp, Imm32(Nursery::NurserySize), ool->rejoin());
masm.branchPtrInNurseryRange(ToRegister(lir->object()), temp, ool->rejoin());
}
ValueOperand value = ToValue(lir, LPostWriteBarrierV::Input);
masm.branchTestObject(Assembler::NotEqual, value, ool->rejoin());
// This section is a little different because we mustn't trash the temp
// register before we use its contents.
Register temp = ToRegister(lir->temp());
masm.unboxObject(value, temp);
masm.addPtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
masm.branchPtr(Assembler::Below, temp, Imm32(Nursery::NurserySize), ool->entry());
masm.branchValueIsNurseryObject(value, temp, ool->entry());
masm.bind(ool->rejoin());
#endif

View File

@ -1786,3 +1786,40 @@ MacroAssembler::spsUnmarkJit(SPSProfiler *p, Register temp)
bind(&spsNotEnabled);
}
#ifdef JSGC_GENERATIONAL
void
MacroAssembler::branchPtrInNurseryRange(Register ptr, Register temp, Label *label)
{
JS_ASSERT(ptr != temp);
JS_ASSERT(temp != InvalidReg);
const Nursery &nursery = GetIonContext()->runtime->gcNursery();
movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp);
addPtr(ptr, temp);
branchPtr(Assembler::Below, temp, Imm32(Nursery::NurserySize), label);
}
void
MacroAssembler::branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label)
{
Label done;
branchTestObject(Assembler::NotEqual, value, &done);
Register obj = extractObject(value, temp);
// valobj and temp may be the same register, in which case we mustn't trash it
// before we use its contents.
if (obj == temp) {
const Nursery &nursery = GetIonContext()->runtime->gcNursery();
addPtr(ImmWord(-ptrdiff_t(nursery.start())), obj);
branchPtr(Assembler::Below, obj, Imm32(Nursery::NurserySize), label);
} else {
branchPtrInNurseryRange(obj, temp, label);
}
bind(&done);
}
#endif

View File

@ -1352,6 +1352,11 @@ class MacroAssembler : public MacroAssemblerSpecific
convertTypedOrValueToInt(src, temp, output, fail, IntConversion_ClampToUint8);
}
#ifdef JSGC_GENERATIONAL
void branchPtrInNurseryRange(Register ptr, Register temp, Label *label);
void branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label);
#endif
public:
class AfterICSaveLive {
friend class MacroAssembler;