Bug 1140737. Fix Ion setter cache to reserve the register the value being set lives in as needed, so other things don't stomp on that register. r=jandem

This commit is contained in:
Boris Zbarsky 2015-03-11 16:53:29 -04:00
parent 3d44a57364
commit f5d543e29c

View File

@ -2384,9 +2384,11 @@ GenerateCallSetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs); MacroAssembler::AfterICSaveLive aic = masm.icSaveLive(liveRegs);
// Remaining registers should basically be free, but we need to use |object| still // Remaining registers should basically be free, but we need to use |object| still
// so leave it alone. // so leave it alone. And of course we need our value, if it's not a constant.
RegisterSet regSet(RegisterSet::All()); RegisterSet regSet(RegisterSet::All());
regSet.take(AnyRegister(object)); regSet.take(AnyRegister(object));
if (!value.constant())
regSet.takeUnchecked(value.reg());
// This is a slower stub path, and we're going to be doing a call anyway. Don't need // This is a slower stub path, and we're going to be doing a call anyway. Don't need
// to try so hard to not use the stack. Scratch regs are just taken from the register // to try so hard to not use the stack. Scratch regs are just taken from the register
@ -2446,11 +2448,11 @@ GenerateCallSetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
// masm.leaveExitFrame & pop locals. // masm.leaveExitFrame & pop locals.
masm.adjustStack(IonOOLNativeExitFrameLayout::Size(1)); masm.adjustStack(IonOOLNativeExitFrameLayout::Size(1));
} else if (IsCacheableSetPropCallPropertyOp(obj, holder, shape)) { } else if (IsCacheableSetPropCallPropertyOp(obj, holder, shape)) {
Register argJSContextReg = regSet.takeGeneral(); // We can't take all our registers up front, because on x86 we need 2
Register argVpReg = regSet.takeGeneral(); // for the value, one for scratch, 5 for the arguments, which makes 8,
Register argObjReg = regSet.takeGeneral(); // but we only have 7 to work with. So only grab the ones we need
Register argIdReg = regSet.takeGeneral(); // before we push value and release its reg back into the set.
Register argResultReg = regSet.takeGeneral(); Register argResultReg = regSet.takeGeneral();
SetterOp target = shape->setterOp(); SetterOp target = shape->setterOp();
MOZ_ASSERT(target); MOZ_ASSERT(target);
@ -2466,10 +2468,20 @@ GenerateCallSetter(JSContext *cx, IonScript *ion, MacroAssembler &masm,
attacher.pushStubCodePointer(masm); attacher.pushStubCodePointer(masm);
// Push args on stack so we can take pointers to make handles. // Push args on stack so we can take pointers to make handles.
if (value.constant()) if (value.constant()) {
masm.Push(value.value()); masm.Push(value.value());
else } else {
masm.Push(value.reg()); masm.Push(value.reg());
regSet.add(value.reg());
}
// OK, now we can grab our remaining registers and grab the pointer to
// what we just pushed into one of them.
Register argJSContextReg = regSet.takeGeneral();
Register argVpReg = regSet.takeGeneral();
// We can just reuse the "object" register for argObjReg
Register argObjReg = object;
Register argIdReg = regSet.takeGeneral();
masm.movePtr(StackPointer, argVpReg); masm.movePtr(StackPointer, argVpReg);
// push canonical jsid from shape instead of propertyname. // push canonical jsid from shape instead of propertyname.