mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-10-14 13:55:43 +00:00
Bug 919536 - Post barrier array write in SetElementIC r=bhackett
This commit is contained in:
parent
7361d2de35
commit
34e3df263e
17
js/src/jit-test/tests/gc/bug-919536.js
Normal file
17
js/src/jit-test/tests/gc/bug-919536.js
Normal 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();
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
@ -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 ®);
|
||||
|
Loading…
Reference in New Issue
Block a user