Bug 919536 - Post barrier array write in SetElementIC r=bhackett

This commit is contained in:
Jon Coppeard 2013-09-26 16:02:16 +01:00
parent 7361d2de35
commit 34e3df263e
4 changed files with 77 additions and 0 deletions

View File

@ -0,0 +1,17 @@
if ("gczeal" in this) {
gczeal(2, 1000);
var a = new Array(10 * 1000);
var i = a.length;
while (i-- != 0) {
switch (i % 3) {
case 0:
a[i] = { };
break;
}
}
gc();
}

View File

@ -3341,6 +3341,11 @@ SetElementIC::attachDenseElement(JSContext *cx, IonScript *ion, JSObject *obj, c
masm.callPreBarrier(target, MIRType_Value);
}
// Call post barrier if necessary, and recalculate elements pointer if it got cobbered.
Register postBarrierScratch = elements;
if (masm.maybeCallPostBarrier(object(), value(), postBarrierScratch))
masm.loadPtr(Address(object(), JSObject::offsetOfElements()), elements);
// Store the value.
masm.bind(&storeElem);
masm.storeConstantOrRegister(value(), target);

View File

@ -338,6 +338,53 @@ MacroAssembler::PopRegsInMaskIgnore(RegisterSet set, RegisterSet ignore)
JS_ASSERT(diffG == 0);
}
bool MacroAssembler::maybeCallPostBarrier(Register object, ConstantOrRegister value,
Register maybeScratch) {
bool usedMaybeScratch = false;
#ifdef JSGC_GENERATIONAL
JSRuntime *runtime = GetIonContext()->runtime;
if (value.constant()) {
JS_ASSERT_IF(value.value().isGCThing(),
!gc::IsInsideNursery(runtime, value.value().toGCThing()));
return false;
}
TypedOrValueRegister valReg = value.reg();
if (valReg.hasTyped() && valReg.type() != MIRType_Object)
return false;
Label done;
Label tenured;
branchPtr(Assembler::Below, object, ImmWord(runtime->gcNurseryStart_), &tenured);
branchPtr(Assembler::Below, object, ImmWord(runtime->gcNurseryEnd_), &done);
bind(&tenured);
if (valReg.hasValue()) {
branchTestObject(Assembler::NotEqual, valReg.valueReg(), &done);
extractObject(valReg, maybeScratch);
usedMaybeScratch = true;
}
Register valObj = valReg.hasValue() ? maybeScratch : valReg.typedReg().gpr();
branchPtr(Assembler::Below, valObj, ImmWord(runtime->gcNurseryStart_), &done);
branchPtr(Assembler::AboveOrEqual, valObj, ImmWord(runtime->gcNurseryEnd_), &done);
GeneralRegisterSet saveRegs = GeneralRegisterSet::Volatile();
PushRegsInMask(saveRegs);
Register callScratch = saveRegs.getAny();
setupUnalignedABICall(2, callScratch);
movePtr(ImmPtr(runtime), callScratch);
passABIArg(callScratch);
passABIArg(object);
callWithABI(JS_FUNC_TO_DATA_PTR(void *, PostWriteBarrier));
PopRegsInMask(saveRegs);
bind(&done);
#endif
return usedMaybeScratch;
}
void
MacroAssembler::branchNurseryPtr(Condition cond, const Address &ptr1, const ImmMaybeNurseryPtr &ptr2,
Label *label)

View File

@ -662,6 +662,14 @@ class MacroAssembler : public MacroAssemblerSpecific
bind(&done);
}
/*
* Call the post barrier if necessary when writing value to a slot or
* element of object.
*
* Returns whether the maybeScratch register was used.
*/
bool maybeCallPostBarrier(Register object, ConstantOrRegister value, Register maybeScratch);
void branchNurseryPtr(Condition cond, const Address &ptr1, const ImmMaybeNurseryPtr &ptr2,
Label *label);
void moveNurseryPtr(const ImmMaybeNurseryPtr &ptr, const Register &reg);