Bug 708303 - Use pinReg/unpinReg more in write barriers (r=dmandelin)

This commit is contained in:
Bill McCloskey 2012-01-16 13:52:57 -08:00
parent f8066a7f28
commit 0603b2c7d2
4 changed files with 27 additions and 13 deletions

View File

@ -5030,7 +5030,7 @@ mjit::Compiler::jsop_setprop(PropertyName *name, bool popGuaranteed)
ScriptAnalysis::NameAccess access =
analysis->resolveNameAccess(cx, ATOM_TO_JSID(name), true);
if (access.nesting) {
/* Use a SavedReg so it isn't clobbered by the stub call. */
/* Use a SavedReg so it isn't clobbered by sync or the stub call. */
RegisterID nameReg = frame.allocReg(Registers::SavedRegs).reg();
Address address = frame.loadNameAddress(access, nameReg);
@ -5077,9 +5077,9 @@ mjit::Compiler::jsop_setprop(PropertyName *name, bool popGuaranteed)
if (!isObject)
notObject = frame.testObject(Assembler::NotEqual, lhs);
#ifdef JSGC_INCREMENTAL_MJ
frame.pinReg(reg);
if (cx->compartment->needsBarrier() && propertyTypes->needsBarrier(cx)) {
/* Write barrier. */
frame.pinReg(reg);
Jump j = masm.testGCThing(Address(reg, JSObject::getFixedSlotOffset(slot)));
stubcc.linkExit(j, Uses(0));
stubcc.leave();
@ -5087,8 +5087,8 @@ mjit::Compiler::jsop_setprop(PropertyName *name, bool popGuaranteed)
reg, Registers::ArgReg1);
OOL_STUBCALL(stubs::GCThingWriteBarrier, REJOIN_NONE);
stubcc.rejoin(Changes(0));
frame.unpinReg(reg);
}
frame.unpinReg(reg);
#endif
if (!isObject) {
stubcc.linkExit(notObject.get(), Uses(2));

View File

@ -1171,17 +1171,26 @@ mjit::Compiler::jsop_setelem_dense()
/*
* The sync call below can potentially clobber key.reg() and slotsReg.
* So we save and restore them. Additionally, the WriteBarrier stub can
* clobber both registers. The rejoin call will restore key.reg() but
* not slotsReg. So we restore it again after the stub call.
* We pin key.reg() to avoid it being clobbered. If |hoisted| is true,
* we can also pin slotsReg. If not, then slotsReg is owned by the
* compiler and we save in manually to VMFrame::scratch.
*
* Additionally, the WriteBarrier stub can clobber both registers. The
* rejoin call will restore key.reg() but not slotsReg. So we save
* slotsReg in the frame and restore it after the stub call.
*/
stubcc.masm.storePtr(slotsReg, FrameAddress(offsetof(VMFrame, scratch)));
if (hoisted)
frame.pinReg(slotsReg);
if (!key.isConstant())
stubcc.masm.push(key.reg());
frame.pinReg(key.reg());
frame.sync(stubcc.masm, Uses(3));
if (!key.isConstant())
stubcc.masm.pop(key.reg());
stubcc.masm.loadPtr(FrameAddress(offsetof(VMFrame, scratch)), slotsReg);
frame.unpinReg(key.reg());
if (hoisted)
frame.unpinReg(slotsReg);
else
stubcc.masm.loadPtr(FrameAddress(offsetof(VMFrame, scratch)), slotsReg);
if (key.isConstant())
stubcc.masm.lea(Address(slotsReg, key.index() * sizeof(Value)), Registers::ArgReg1);

View File

@ -48,7 +48,7 @@ using namespace js;
using namespace js::mjit;
ImmutableSync::ImmutableSync()
: cx(NULL), entries(NULL), frame(NULL), avail(Registers::AvailRegs), generation(0)
: cx(NULL), entries(NULL), frame(NULL), avail(Registers::TempRegs), generation(0)
{
}
@ -71,7 +71,7 @@ ImmutableSync::init(JSContext *cx, const FrameState &frame, uint32_t nentries)
void
ImmutableSync::reset(Assembler *masm, Registers avail, FrameEntry *top, FrameEntry *bottom)
{
this->avail = avail;
this->avail = avail & Registers::TempRegs;
this->masm = masm;
this->top = top;
this->bottom = bottom;
@ -91,7 +91,7 @@ ImmutableSync::doAllocReg()
/* Find something to evict. */
for (uint32_t i = 0; i < Registers::TotalRegisters; i++) {
RegisterID reg = RegisterID(i);
if (!(Registers::maskReg(reg) & Registers::AvailRegs))
if (!(Registers::maskReg(reg) & Registers::TempRegs))
continue;
if (frame->regstate(reg).isPinned())
@ -151,13 +151,14 @@ ImmutableSync::allocReg()
{
RegisterID reg = doAllocReg();
JS_ASSERT(!frame->regstate(reg).isPinned());
JS_ASSERT(!Registers::isSaved(reg));
return reg;
}
void
ImmutableSync::freeReg(JSC::MacroAssembler::RegisterID reg)
{
if (!frame->regstate(reg).isPinned())
if (!frame->regstate(reg).isPinned() && !Registers::isSaved(reg))
avail.putReg(reg);
}

View File

@ -573,6 +573,10 @@ struct Registers {
return freeMask == other.freeMask;
}
Registers operator &(const Registers &other) {
return Registers(freeMask & other.freeMask);
}
uint32_t freeMask;
};