diff --git a/js/src/jit/BaselineCompiler.cpp b/js/src/jit/BaselineCompiler.cpp index 96c76a80d086..371de9d5feed 100644 --- a/js/src/jit/BaselineCompiler.cpp +++ b/js/src/jit/BaselineCompiler.cpp @@ -408,7 +408,8 @@ BaselineCompiler::emitEpilogue() #ifdef JSGC_GENERATIONAL // On input: // R2.scratchReg() contains object being written to. -// Otherwise, baseline stack will be synced, so all other registers are usable as scratch. +// Called with the baseline stack synced, except for R0 which is preserved. +// All other registers are usable as scratch. // This calls: // void PostWriteBarrier(JSRuntime *rt, JSObject *obj); bool @@ -418,6 +419,7 @@ BaselineCompiler::emitOutOfLinePostBarrierSlot() Register objReg = R2.scratchReg(); GeneralRegisterSet regs(GeneralRegisterSet::All()); + regs.take(R0); regs.take(objReg); regs.take(BaselineFrameReg); Register scratch = regs.takeAny(); @@ -428,6 +430,7 @@ BaselineCompiler::emitOutOfLinePostBarrierSlot() #elif defined(JS_CODEGEN_MIPS) masm.push(ra); #endif + masm.pushValue(R0); masm.setupUnalignedABICall(2, scratch); masm.movePtr(ImmPtr(cx->runtime()), scratch); @@ -435,6 +438,7 @@ BaselineCompiler::emitOutOfLinePostBarrierSlot() masm.passABIArg(objReg); masm.callWithABI(JS_FUNC_TO_DATA_PTR(void *, PostWriteBarrier)); + masm.popValue(R0); masm.ret(); return true; } @@ -2096,16 +2100,15 @@ BaselineCompiler::emit_JSOP_SETALIASEDVAR() frame.push(R0); #ifdef JSGC_GENERATIONAL - // Fully sync the stack if post-barrier is needed. + // Only R0 is live at this point. // Scope coordinate object is already in R2.scratchReg(). - frame.syncStack(0); Register temp = R1.scratchReg(); Label skipBarrier; - masm.branchTestObject(Assembler::NotEqual, R0, &skipBarrier); - masm.branchPtrInNurseryRange(objReg, temp, &skipBarrier); + masm.branchPtrInNurseryRange(Assembler::Equal, objReg, temp, &skipBarrier); + masm.branchValueIsNurseryObject(Assembler::NotEqual, R0, temp, &skipBarrier); - masm.call(&postBarrierSlot_); + masm.call(&postBarrierSlot_); // Won't clobber R0 masm.bind(&skipBarrier); #endif @@ -2461,11 +2464,12 @@ BaselineCompiler::emitFormalArgAccess(uint32_t arg, bool get) frame.push(R0); } else { masm.patchableCallPreBarrier(argAddr, MIRType_Value); - storeValue(frame.peek(-1), argAddr, R0); + masm.loadValue(frame.addressOfStackValue(frame.peek(-1)), R0); + masm.storeValue(R0, argAddr); #ifdef JSGC_GENERATIONAL - // Fully sync the stack if post-barrier is needed. - frame.syncStack(0); + MOZ_ASSERT(frame.numUnsyncedSlots() == 0); + Register temp = R1.scratchReg(); // Reload the arguments object @@ -2473,7 +2477,9 @@ BaselineCompiler::emitFormalArgAccess(uint32_t arg, bool get) masm.loadPtr(Address(BaselineFrameReg, BaselineFrame::reverseOffsetOfArgsObj()), reg); Label skipBarrier; - masm.branchPtrInNurseryRange(reg, temp, &skipBarrier); + + masm.branchPtrInNurseryRange(Assembler::Equal, reg, temp, &skipBarrier); + masm.branchValueIsNurseryObject(Assembler::NotEqual, R0, temp, &skipBarrier); masm.call(&postBarrierSlot_); diff --git a/js/src/jit/BaselineIC.cpp b/js/src/jit/BaselineIC.cpp index cf32d70c6e51..9c4b0aa681ac 100644 --- a/js/src/jit/BaselineIC.cpp +++ b/js/src/jit/BaselineIC.cpp @@ -734,16 +734,9 @@ inline bool ICStubCompiler::emitPostWriteBarrierSlot(MacroAssembler &masm, Register obj, ValueOperand val, Register scratch, GeneralRegisterSet saveRegs) { - Nursery &nursery = cx->runtime()->gc.nursery; - Label skipBarrier; - masm.branchTestObject(Assembler::NotEqual, val, &skipBarrier); - - masm.branchPtrInNurseryRange(obj, scratch, &skipBarrier); - - Register valReg = masm.extractObject(val, scratch); - masm.branchPtr(Assembler::Below, valReg, ImmWord(nursery.start()), &skipBarrier); - masm.branchPtr(Assembler::AboveOrEqual, valReg, ImmWord(nursery.heapEnd()), &skipBarrier); + masm.branchPtrInNurseryRange(Assembler::Equal, obj, scratch, &skipBarrier); + masm.branchValueIsNurseryObject(Assembler::NotEqual, val, scratch, &skipBarrier); // void PostWriteBarrier(JSRuntime *rt, JSObject *obj); #if defined(JS_CODEGEN_ARM) || defined(JS_CODEGEN_MIPS) diff --git a/js/src/jit/CodeGenerator.cpp b/js/src/jit/CodeGenerator.cpp index 11d95547c48b..e2dc2dc36df8 100644 --- a/js/src/jit/CodeGenerator.cpp +++ b/js/src/jit/CodeGenerator.cpp @@ -1875,10 +1875,11 @@ CodeGenerator::visitPostWriteBarrierO(LPostWriteBarrierO *lir) JS_ASSERT(!nursery.isInside(&lir->object()->toConstant()->toObject())); #endif } else { - masm.branchPtrInNurseryRange(ToRegister(lir->object()), temp, ool->rejoin()); + masm.branchPtrInNurseryRange(Assembler::Equal, ToRegister(lir->object()), temp, + ool->rejoin()); } - masm.branchPtrInNurseryRange(ToRegister(lir->value()), temp, ool->entry()); + masm.branchPtrInNurseryRange(Assembler::Equal, ToRegister(lir->value()), temp, ool->entry()); masm.bind(ool->rejoin()); #endif @@ -1901,11 +1902,12 @@ CodeGenerator::visitPostWriteBarrierV(LPostWriteBarrierV *lir) JS_ASSERT(!nursery.isInside(&lir->object()->toConstant()->toObject())); #endif } else { - masm.branchPtrInNurseryRange(ToRegister(lir->object()), temp, ool->rejoin()); + masm.branchPtrInNurseryRange(Assembler::Equal, ToRegister(lir->object()), temp, + ool->rejoin()); } ValueOperand value = ToValue(lir, LPostWriteBarrierV::Input); - masm.branchValueIsNurseryObject(value, temp, ool->entry()); + masm.branchValueIsNurseryObject(Assembler::Equal, value, temp, ool->entry()); masm.bind(ool->rejoin()); #endif diff --git a/js/src/jit/arm/MacroAssembler-arm.cpp b/js/src/jit/arm/MacroAssembler-arm.cpp index 53456433e7d3..4d5c881c4915 100644 --- a/js/src/jit/arm/MacroAssembler-arm.cpp +++ b/js/src/jit/arm/MacroAssembler-arm.cpp @@ -4350,8 +4350,10 @@ MacroAssemblerARMCompat::jumpWithPatch(RepatchLabel *label, Condition cond) #ifdef JSGC_GENERATIONAL void -MacroAssemblerARMCompat::branchPtrInNurseryRange(Register ptr, Register temp, Label *label) +MacroAssemblerARMCompat::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, + Label *label) { + JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual); JS_ASSERT(ptr != temp); JS_ASSERT(ptr != secondScratchReg_); @@ -4360,16 +4362,20 @@ MacroAssemblerARMCompat::branchPtrInNurseryRange(Register ptr, Register temp, La ma_mov(Imm32(startChunk), secondScratchReg_); as_rsb(secondScratchReg_, secondScratchReg_, lsr(ptr, Nursery::ChunkShift)); - branch32(Assembler::Below, secondScratchReg_, Imm32(Nursery::NumNurseryChunks), label); + branch32(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual, + secondScratchReg_, Imm32(Nursery::NumNurseryChunks), label); } void -MacroAssemblerARMCompat::branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label) +MacroAssemblerARMCompat::branchValueIsNurseryObject(Condition cond, ValueOperand value, + Register temp, Label *label) { + JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual); + Label done; - branchTestObject(Assembler::NotEqual, value, &done); - branchPtrInNurseryRange(value.payloadReg(), temp, label); + branchTestObject(Assembler::NotEqual, value, cond == Assembler::Equal ? &done : label); + branchPtrInNurseryRange(cond, value.payloadReg(), temp, label); bind(&done); } diff --git a/js/src/jit/arm/MacroAssembler-arm.h b/js/src/jit/arm/MacroAssembler-arm.h index 6e26f1971dba..fb924993fa7f 100644 --- a/js/src/jit/arm/MacroAssembler-arm.h +++ b/js/src/jit/arm/MacroAssembler-arm.h @@ -1599,8 +1599,8 @@ class MacroAssemblerARMCompat : public MacroAssemblerARM } #ifdef JSGC_GENERATIONAL - void branchPtrInNurseryRange(Register ptr, Register temp, Label *label); - void branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label); + void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label *label); + void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, Label *label); #endif }; diff --git a/js/src/jit/x64/MacroAssembler-x64.cpp b/js/src/jit/x64/MacroAssembler-x64.cpp index 9a9f995b7c3a..838a26853f14 100644 --- a/js/src/jit/x64/MacroAssembler-x64.cpp +++ b/js/src/jit/x64/MacroAssembler-x64.cpp @@ -370,27 +370,33 @@ MacroAssemblerX64::handleFailureWithHandlerTail() #ifdef JSGC_GENERATIONAL void -MacroAssemblerX64::branchPtrInNurseryRange(Register ptr, Register temp, Label *label) +MacroAssemblerX64::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label *label) { + JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual); JS_ASSERT(ptr != temp); JS_ASSERT(ptr != ScratchReg); const Nursery &nursery = GetIonContext()->runtime->gcNursery(); movePtr(ImmWord(-ptrdiff_t(nursery.start())), ScratchReg); addPtr(ptr, ScratchReg); - branchPtr(Assembler::Below, ScratchReg, Imm32(Nursery::NurserySize), label); + branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual, + ScratchReg, Imm32(Nursery::NurserySize), label); } void -MacroAssemblerX64::branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label) +MacroAssemblerX64::branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, + Label *label) { + JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual); + // 'Value' representing the start of the nursery tagged as a JSObject const Nursery &nursery = GetIonContext()->runtime->gcNursery(); Value start = ObjectValue(*reinterpret_cast(nursery.start())); movePtr(ImmWord(-ptrdiff_t(start.asRawBits())), ScratchReg); addPtr(value.valueReg(), ScratchReg); - branchPtr(Assembler::Below, ScratchReg, Imm32(Nursery::NurserySize), label); + branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual, + ScratchReg, Imm32(Nursery::NurserySize), label); } #endif diff --git a/js/src/jit/x64/MacroAssembler-x64.h b/js/src/jit/x64/MacroAssembler-x64.h index e8145ba31afc..6c21b932a113 100644 --- a/js/src/jit/x64/MacroAssembler-x64.h +++ b/js/src/jit/x64/MacroAssembler-x64.h @@ -1334,8 +1334,8 @@ class MacroAssemblerX64 : public MacroAssemblerX86Shared } #ifdef JSGC_GENERATIONAL - void branchPtrInNurseryRange(Register ptr, Register temp, Label *label); - void branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label); + void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label *label); + void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, Label *label); #endif }; diff --git a/js/src/jit/x86/MacroAssembler-x86.cpp b/js/src/jit/x86/MacroAssembler-x86.cpp index d36f4d32c5c2..f42f9506af8e 100644 --- a/js/src/jit/x86/MacroAssembler-x86.cpp +++ b/js/src/jit/x86/MacroAssembler-x86.cpp @@ -390,24 +390,30 @@ MacroAssemblerX86::branchTestValue(Condition cond, const ValueOperand &value, co #ifdef JSGC_GENERATIONAL void -MacroAssemblerX86::branchPtrInNurseryRange(Register ptr, Register temp, Label *label) +MacroAssemblerX86::branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, + Label *label) { + JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual); JS_ASSERT(ptr != temp); JS_ASSERT(temp != InvalidReg); // A temp register is required for x86. const Nursery &nursery = GetIonContext()->runtime->gcNursery(); movePtr(ImmWord(-ptrdiff_t(nursery.start())), temp); addPtr(ptr, temp); - branchPtr(Assembler::Below, temp, Imm32(Nursery::NurserySize), label); + branchPtr(cond == Assembler::Equal ? Assembler::Below : Assembler::AboveOrEqual, + temp, Imm32(Nursery::NurserySize), label); } void -MacroAssemblerX86::branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label) +MacroAssemblerX86::branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, + Label *label) { + JS_ASSERT(cond == Assembler::Equal || cond == Assembler::NotEqual); + Label done; - branchTestObject(Assembler::NotEqual, value, &done); - branchPtrInNurseryRange(value.payloadReg(), temp, label); + branchTestObject(Assembler::NotEqual, value, cond == Assembler::Equal ? &done : label); + branchPtrInNurseryRange(cond, value.payloadReg(), temp, label); bind(&done); } diff --git a/js/src/jit/x86/MacroAssembler-x86.h b/js/src/jit/x86/MacroAssembler-x86.h index 90f82aff3499..b300f6a8bf25 100644 --- a/js/src/jit/x86/MacroAssembler-x86.h +++ b/js/src/jit/x86/MacroAssembler-x86.h @@ -1124,8 +1124,8 @@ class MacroAssemblerX86 : public MacroAssemblerX86Shared } #ifdef JSGC_GENERATIONAL - void branchPtrInNurseryRange(Register ptr, Register temp, Label *label); - void branchValueIsNurseryObject(ValueOperand value, Register temp, Label *label); + void branchPtrInNurseryRange(Condition cond, Register ptr, Register temp, Label *label); + void branchValueIsNurseryObject(Condition cond, ValueOperand value, Register temp, Label *label); #endif };