From e16cc0acaf19e0d1bfd484a6b1d9632210f9113a Mon Sep 17 00:00:00 2001 From: "bmeurer@chromium.org" Date: Tue, 4 Mar 2014 12:45:00 +0000 Subject: [PATCH] Push safepoint registers in deferred number-to-i/u only on-demand. R=svenpanne@chromium.org Review URL: https://codereview.chromium.org/181053005 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@19649 ce2b1a6d-e550-0410-aec6-3dcde31c8c00 --- src/arm/lithium-arm.cc | 8 +++- src/arm/lithium-arm.h | 16 +++++-- src/arm/lithium-codegen-arm.cc | 75 +++++++++++++++++--------------- src/arm/lithium-codegen-arm.h | 8 ++-- src/ia32/lithium-codegen-ia32.cc | 60 +++++++++++++------------ src/ia32/lithium-codegen-ia32.h | 8 ++-- src/ia32/lithium-ia32.cc | 10 +++-- src/ia32/lithium-ia32.h | 16 ++++--- src/x64/lithium-codegen-x64.cc | 44 +++++++++---------- src/x64/lithium-x64.cc | 5 ++- src/x64/lithium-x64.h | 10 +++-- 11 files changed, 146 insertions(+), 114 deletions(-) diff --git a/src/arm/lithium-arm.cc b/src/arm/lithium-arm.cc index 3242b19ac..7db97feef 100644 --- a/src/arm/lithium-arm.cc +++ b/src/arm/lithium-arm.cc @@ -1843,12 +1843,16 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { HValue* val = instr->value(); LOperand* value = UseRegisterAtStart(val); if (val->CheckFlag(HInstruction::kUint32)) { - LNumberTagU* result = new(zone()) LNumberTagU(value); + LOperand* temp1 = TempRegister(); + LOperand* temp2 = TempRegister(); + LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2); return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); } else if (val->HasRange() && val->range()->IsInSmiRange()) { return DefineAsRegister(new(zone()) LSmiTag(value)); } else { - LNumberTagI* result = new(zone()) LNumberTagI(value); + LOperand* temp1 = TempRegister(); + LOperand* temp2 = TempRegister(); + LNumberTagI* result = new(zone()) LNumberTagI(value, temp1, temp2); return AssignEnvironment(AssignPointerMap(DefineAsRegister(result))); } } else if (to.IsSmi()) { diff --git a/src/arm/lithium-arm.h b/src/arm/lithium-arm.h index fbe52644a..b83ca134d 100644 --- a/src/arm/lithium-arm.h +++ b/src/arm/lithium-arm.h @@ -1936,25 +1936,33 @@ class LUint32ToSmi V8_FINAL : public LTemplateInstruction<1, 1, 0> { }; -class LNumberTagI V8_FINAL : public LTemplateInstruction<1, 1, 0> { +class LNumberTagI V8_FINAL : public LTemplateInstruction<1, 1, 2> { public: - explicit LNumberTagI(LOperand* value) { + LNumberTagI(LOperand* value, LOperand* temp1, LOperand* temp2) { inputs_[0] = value; + temps_[0] = temp1; + temps_[1] = temp2; } LOperand* value() { return inputs_[0]; } + LOperand* temp1() { return temps_[0]; } + LOperand* temp2() { return temps_[1]; } DECLARE_CONCRETE_INSTRUCTION(NumberTagI, "number-tag-i") }; -class LNumberTagU V8_FINAL : public LTemplateInstruction<1, 1, 0> { +class LNumberTagU V8_FINAL : public LTemplateInstruction<1, 1, 2> { public: - explicit LNumberTagU(LOperand* value) { + LNumberTagU(LOperand* value, LOperand* temp1, LOperand* temp2) { inputs_[0] = value; + temps_[0] = temp1; + temps_[1] = temp2; } LOperand* value() { return inputs_[0]; } + LOperand* temp1() { return temps_[0]; } + LOperand* temp2() { return temps_[1]; } DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u") }; diff --git a/src/arm/lithium-codegen-arm.cc b/src/arm/lithium-codegen-arm.cc index 7f5900df0..8acddbdd9 100644 --- a/src/arm/lithium-codegen-arm.cc +++ b/src/arm/lithium-codegen-arm.cc @@ -4606,9 +4606,11 @@ void LCodeGen::DoNumberTagI(LNumberTagI* instr) { DeferredNumberTagI(LCodeGen* codegen, LNumberTagI* instr) : LDeferredCode(codegen), instr_(instr) { } virtual void Generate() V8_OVERRIDE { - codegen()->DoDeferredNumberTagI(instr_, - instr_->value(), - SIGNED_INT32); + codegen()->DoDeferredNumberTagIU(instr_, + instr_->value(), + instr_->temp1(), + instr_->temp2(), + SIGNED_INT32); } virtual LInstruction* instr() V8_OVERRIDE { return instr_; } private: @@ -4631,9 +4633,11 @@ void LCodeGen::DoNumberTagU(LNumberTagU* instr) { DeferredNumberTagU(LCodeGen* codegen, LNumberTagU* instr) : LDeferredCode(codegen), instr_(instr) { } virtual void Generate() V8_OVERRIDE { - codegen()->DoDeferredNumberTagI(instr_, - instr_->value(), - UNSIGNED_INT32); + codegen()->DoDeferredNumberTagIU(instr_, + instr_->value(), + instr_->temp1(), + instr_->temp2(), + UNSIGNED_INT32); } virtual LInstruction* instr() V8_OVERRIDE { return instr_; } private: @@ -4651,18 +4655,19 @@ void LCodeGen::DoNumberTagU(LNumberTagU* instr) { } -void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, - LOperand* value, - IntegerSignedness signedness) { - Label slow; +void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, + LOperand* value, + LOperand* temp1, + LOperand* temp2, + IntegerSignedness signedness) { + Label done, slow; Register src = ToRegister(value); Register dst = ToRegister(instr->result()); + Register tmp1 = scratch0(); + Register tmp2 = ToRegister(temp1); + Register tmp3 = ToRegister(temp2); LowDwVfpRegister dbl_scratch = double_scratch0(); - // Preserve the value of all registers. - PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); - - Label done; if (signedness == SIGNED_INT32) { // There was overflow, so bits 30 and 31 of the original integer // disagree. Try to allocate a heap number in new space and store @@ -4679,38 +4684,40 @@ void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, } if (FLAG_inline_new) { - __ LoadRoot(scratch0(), Heap::kHeapNumberMapRootIndex); - __ AllocateHeapNumber(r5, r3, r4, scratch0(), &slow, DONT_TAG_RESULT); - __ Move(dst, r5); + __ LoadRoot(tmp3, Heap::kHeapNumberMapRootIndex); + __ AllocateHeapNumber(dst, tmp1, tmp2, tmp3, &slow, DONT_TAG_RESULT); __ b(&done); } // Slow case: Call the runtime system to do the number allocation. __ bind(&slow); + { + // TODO(3095996): Put a valid pointer value in the stack slot where the + // result register is stored, as this register is in the pointer map, but + // contains an integer value. + __ mov(dst, Operand::Zero()); - // TODO(3095996): Put a valid pointer value in the stack slot where the result - // register is stored, as this register is in the pointer map, but contains an - // integer value. - __ mov(ip, Operand::Zero()); - __ StoreToSafepointRegisterSlot(ip, dst); - // NumberTagI and NumberTagD use the context from the frame, rather than - // the environment's HContext or HInlinedContext value. - // They only call Runtime::kAllocateHeapNumber. - // The corresponding HChange instructions are added in a phase that does - // not have easy access to the local context. - __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); - __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); - RecordSafepointWithRegisters( - instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); - __ Move(dst, r0); - __ sub(dst, dst, Operand(kHeapObjectTag)); + // Preserve the value of all registers. + PushSafepointRegistersScope scope(this, Safepoint::kWithRegisters); + + // NumberTagI and NumberTagD use the context from the frame, rather than + // the environment's HContext or HInlinedContext value. + // They only call Runtime::kAllocateHeapNumber. + // The corresponding HChange instructions are added in a phase that does + // not have easy access to the local context. + __ ldr(cp, MemOperand(fp, StandardFrameConstants::kContextOffset)); + __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); + RecordSafepointWithRegisters( + instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); + __ sub(r0, r0, Operand(kHeapObjectTag)); + __ StoreToSafepointRegisterSlot(r0, dst); + } // Done. Put the value in dbl_scratch into the value of the allocated heap // number. __ bind(&done); __ vstr(dbl_scratch, dst, HeapNumber::kValueOffset); __ add(dst, dst, Operand(kHeapObjectTag)); - __ StoreToSafepointRegisterSlot(dst, dst); } diff --git a/src/arm/lithium-codegen-arm.h b/src/arm/lithium-codegen-arm.h index 5251b85fa..1638ee9ae 100644 --- a/src/arm/lithium-codegen-arm.h +++ b/src/arm/lithium-codegen-arm.h @@ -126,9 +126,11 @@ class LCodeGen: public LCodeGenBase { void DoDeferredNumberTagD(LNumberTagD* instr); enum IntegerSignedness { SIGNED_INT32, UNSIGNED_INT32 }; - void DoDeferredNumberTagI(LInstruction* instr, - LOperand* value, - IntegerSignedness signedness); + void DoDeferredNumberTagIU(LInstruction* instr, + LOperand* value, + LOperand* temp1, + LOperand* temp2, + IntegerSignedness signedness); void DoDeferredTaggedToI(LTaggedToI* instr); void DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr); diff --git a/src/ia32/lithium-codegen-ia32.cc b/src/ia32/lithium-codegen-ia32.cc index 5f03146d5..14d1ab3f7 100644 --- a/src/ia32/lithium-codegen-ia32.cc +++ b/src/ia32/lithium-codegen-ia32.cc @@ -4904,7 +4904,8 @@ void LCodeGen::DoNumberTagI(LNumberTagI* instr) { const X87Stack& x87_stack) : LDeferredCode(codegen, x87_stack), instr_(instr) { } virtual void Generate() V8_OVERRIDE { - codegen()->DoDeferredNumberTagI(instr_, instr_->value(), SIGNED_INT32); + codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp(), + NULL, SIGNED_INT32); } virtual LInstruction* instr() V8_OVERRIDE { return instr_; } private: @@ -4931,7 +4932,8 @@ void LCodeGen::DoNumberTagU(LNumberTagU* instr) { const X87Stack& x87_stack) : LDeferredCode(codegen, x87_stack), instr_(instr) { } virtual void Generate() V8_OVERRIDE { - codegen()->DoDeferredNumberTagI(instr_, instr_->value(), UNSIGNED_INT32); + codegen()->DoDeferredNumberTagIU(instr_, instr_->value(), instr_->temp1(), + instr_->temp2(), UNSIGNED_INT32); } virtual LInstruction* instr() V8_OVERRIDE { return instr_; } private: @@ -4951,19 +4953,16 @@ void LCodeGen::DoNumberTagU(LNumberTagU* instr) { } -void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, - LOperand* value, - IntegerSignedness signedness) { - Label slow; +void LCodeGen::DoDeferredNumberTagIU(LInstruction* instr, + LOperand* value, + LOperand* temp1, + LOperand* temp2, + IntegerSignedness signedness) { + Label done, slow; Register reg = ToRegister(value); - Register tmp = reg.is(eax) ? ecx : eax; + Register tmp = ToRegister(temp1); XMMRegister xmm_scratch = double_scratch0(); - // Preserve the value of all registers. - PushSafepointRegistersScope scope(this); - - Label done; - if (signedness == SIGNED_INT32) { // There was overflow, so bits 30 and 31 of the original integer // disagree. Try to allocate a heap number in new space and store @@ -4981,8 +4980,7 @@ void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, } else { if (CpuFeatures::IsSupported(SSE2)) { CpuFeatureScope feature_scope(masm(), SSE2); - __ LoadUint32(xmm_scratch, reg, - ToDoubleRegister(LNumberTagU::cast(instr)->temp())); + __ LoadUint32(xmm_scratch, reg, ToDoubleRegister(temp2)); } else { // There's no fild variant for unsigned values, so zero-extend to a 64-bit // int manually. @@ -5001,21 +4999,26 @@ void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, // Slow case: Call the runtime system to do the number allocation. __ bind(&slow); + { + // TODO(3095996): Put a valid pointer value in the stack slot where the + // result register is stored, as this register is in the pointer map, but + // contains an integer value. + __ Set(reg, Immediate(0)); - // TODO(3095996): Put a valid pointer value in the stack slot where the result - // register is stored, as this register is in the pointer map, but contains an - // integer value. - __ StoreToSafepointRegisterSlot(reg, Immediate(0)); - // NumberTagI and NumberTagD use the context from the frame, rather than - // the environment's HContext or HInlinedContext value. - // They only call Runtime::kAllocateHeapNumber. - // The corresponding HChange instructions are added in a phase that does - // not have easy access to the local context. - __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); - __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); - RecordSafepointWithRegisters( - instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); - if (!reg.is(eax)) __ mov(reg, eax); + // Preserve the value of all registers. + PushSafepointRegistersScope scope(this); + + // NumberTagI and NumberTagD use the context from the frame, rather than + // the environment's HContext or HInlinedContext value. + // They only call Runtime::kAllocateHeapNumber. + // The corresponding HChange instructions are added in a phase that does + // not have easy access to the local context. + __ mov(esi, Operand(ebp, StandardFrameConstants::kContextOffset)); + __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); + RecordSafepointWithRegisters( + instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); + __ StoreToSafepointRegisterSlot(reg, eax); + } // Done. Put the value in xmm_scratch into the value of the allocated heap // number. @@ -5026,7 +5029,6 @@ void LCodeGen::DoDeferredNumberTagI(LInstruction* instr, } else { __ fstp_d(FieldOperand(reg, HeapNumber::kValueOffset)); } - __ StoreToSafepointRegisterSlot(reg, reg); } diff --git a/src/ia32/lithium-codegen-ia32.h b/src/ia32/lithium-codegen-ia32.h index fa5e88b03..c5e253bef 100644 --- a/src/ia32/lithium-codegen-ia32.h +++ b/src/ia32/lithium-codegen-ia32.h @@ -148,9 +148,11 @@ class LCodeGen: public LCodeGenBase { void DoDeferredNumberTagD(LNumberTagD* instr); enum IntegerSignedness { SIGNED_INT32, UNSIGNED_INT32 }; - void DoDeferredNumberTagI(LInstruction* instr, - LOperand* value, - IntegerSignedness signedness); + void DoDeferredNumberTagIU(LInstruction* instr, + LOperand* value, + LOperand* temp1, + LOperand* temp2, + IntegerSignedness signedness); void DoDeferredTaggedToI(LTaggedToI* instr, Label* done); void DoDeferredMathAbsTaggedHeapNumber(LMathAbs* instr); diff --git a/src/ia32/lithium-ia32.cc b/src/ia32/lithium-ia32.cc index 6b4db67ae..f815784e1 100644 --- a/src/ia32/lithium-ia32.cc +++ b/src/ia32/lithium-ia32.cc @@ -1862,12 +1862,14 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { if (val->HasRange() && val->range()->IsInSmiRange()) { return DefineSameAsFirst(new(zone()) LSmiTag(value)); } else if (val->CheckFlag(HInstruction::kUint32)) { - LOperand* temp = CpuFeatures::IsSupported(SSE2) ? FixedTemp(xmm1) - : NULL; - LNumberTagU* result = new(zone()) LNumberTagU(value, temp); + LOperand* temp1 = TempRegister(); + LOperand* temp2 = CpuFeatures::IsSupported(SSE2) ? FixedTemp(xmm1) + : NULL; + LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2); return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); } else { - LNumberTagI* result = new(zone()) LNumberTagI(value); + LOperand* temp = TempRegister(); + LNumberTagI* result = new(zone()) LNumberTagI(value, temp); return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); } } else if (to.IsSmi()) { diff --git a/src/ia32/lithium-ia32.h b/src/ia32/lithium-ia32.h index 073bcdd6d..caf4a18f3 100644 --- a/src/ia32/lithium-ia32.h +++ b/src/ia32/lithium-ia32.h @@ -1937,27 +1937,31 @@ class LUint32ToSmi V8_FINAL : public LTemplateInstruction<1, 1, 0> { }; -class LNumberTagI V8_FINAL : public LTemplateInstruction<1, 1, 0> { +class LNumberTagI V8_FINAL : public LTemplateInstruction<1, 1, 1> { public: - explicit LNumberTagI(LOperand* value) { + LNumberTagI(LOperand* value, LOperand* temp) { inputs_[0] = value; + temps_[0] = temp; } LOperand* value() { return inputs_[0]; } + LOperand* temp() { return temps_[0]; } DECLARE_CONCRETE_INSTRUCTION(NumberTagI, "number-tag-i") }; -class LNumberTagU V8_FINAL : public LTemplateInstruction<1, 1, 1> { +class LNumberTagU V8_FINAL : public LTemplateInstruction<1, 1, 2> { public: - LNumberTagU(LOperand* value, LOperand* temp) { + LNumberTagU(LOperand* value, LOperand* temp1, LOperand* temp2) { inputs_[0] = value; - temps_[0] = temp; + temps_[0] = temp1; + temps_[1] = temp2; } LOperand* value() { return inputs_[0]; } - LOperand* temp() { return temps_[0]; } + LOperand* temp1() { return temps_[0]; } + LOperand* temp2() { return temps_[1]; } DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u") }; diff --git a/src/x64/lithium-codegen-x64.cc b/src/x64/lithium-codegen-x64.cc index 64366e2db..bf91f8ba4 100644 --- a/src/x64/lithium-codegen-x64.cc +++ b/src/x64/lithium-codegen-x64.cc @@ -4545,15 +4545,11 @@ void LCodeGen::DoNumberTagU(LNumberTagU* instr) { void LCodeGen::DoDeferredNumberTagU(LNumberTagU* instr) { - Label slow; + Label done, slow; Register reg = ToRegister(instr->value()); - Register tmp = reg.is(rax) ? rcx : rax; - XMMRegister temp_xmm = ToDoubleRegister(instr->temp()); + Register tmp = ToRegister(instr->temp1()); + XMMRegister temp_xmm = ToDoubleRegister(instr->temp2()); - // Preserve the value of all registers. - PushSafepointRegistersScope scope(this); - - Label done; // Load value into temp_xmm which will be preserved across potential call to // runtime (MacroAssembler::EnterExitFrameEpilogue preserves only allocatable // XMM registers on x64). @@ -4567,29 +4563,31 @@ void LCodeGen::DoDeferredNumberTagU(LNumberTagU* instr) { // Slow case: Call the runtime system to do the number allocation. __ bind(&slow); + { + // Put a valid pointer value in the stack slot where the result + // register is stored, as this register is in the pointer map, but contains + // an integer value. + __ Set(reg, 0); - // Put a valid pointer value in the stack slot where the result - // register is stored, as this register is in the pointer map, but contains an - // integer value. - __ StoreToSafepointRegisterSlot(reg, Immediate(0)); - - // NumberTagU uses the context from the frame, rather than - // the environment's HContext or HInlinedContext value. - // They only call Runtime::kAllocateHeapNumber. - // The corresponding HChange instructions are added in a phase that does - // not have easy access to the local context. - __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); - __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); - RecordSafepointWithRegisters( - instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); + // Preserve the value of all registers. + PushSafepointRegistersScope scope(this); - if (!reg.is(rax)) __ movp(reg, rax); + // NumberTagU uses the context from the frame, rather than + // the environment's HContext or HInlinedContext value. + // They only call Runtime::kAllocateHeapNumber. + // The corresponding HChange instructions are added in a phase that does + // not have easy access to the local context. + __ movp(rsi, Operand(rbp, StandardFrameConstants::kContextOffset)); + __ CallRuntimeSaveDoubles(Runtime::kAllocateHeapNumber); + RecordSafepointWithRegisters( + instr->pointer_map(), 0, Safepoint::kNoLazyDeopt); + __ StoreToSafepointRegisterSlot(reg, rax); + } // Done. Put the value in temp_xmm into the value of the allocated heap // number. __ bind(&done); __ movsd(FieldOperand(reg, HeapNumber::kValueOffset), temp_xmm); - __ StoreToSafepointRegisterSlot(reg, reg); } diff --git a/src/x64/lithium-x64.cc b/src/x64/lithium-x64.cc index d42d3824e..792d05fda 100644 --- a/src/x64/lithium-x64.cc +++ b/src/x64/lithium-x64.cc @@ -1745,8 +1745,9 @@ LInstruction* LChunkBuilder::DoChange(HChange* instr) { HValue* val = instr->value(); LOperand* value = UseRegister(val); if (val->CheckFlag(HInstruction::kUint32)) { - LOperand* temp = FixedTemp(xmm1); - LNumberTagU* result = new(zone()) LNumberTagU(value, temp); + LOperand* temp1 = TempRegister(); + LOperand* temp2 = FixedTemp(xmm1); + LNumberTagU* result = new(zone()) LNumberTagU(value, temp1, temp2); return AssignEnvironment(AssignPointerMap(DefineSameAsFirst(result))); } else if (val->HasRange() && val->range()->IsInSmiRange()) { return DefineSameAsFirst(new(zone()) LSmiTag(value)); diff --git a/src/x64/lithium-x64.h b/src/x64/lithium-x64.h index a58208c81..3724cff8d 100644 --- a/src/x64/lithium-x64.h +++ b/src/x64/lithium-x64.h @@ -1892,15 +1892,17 @@ class LNumberTagI V8_FINAL : public LTemplateInstruction<1, 1, 0> { }; -class LNumberTagU V8_FINAL : public LTemplateInstruction<1, 1, 1> { +class LNumberTagU V8_FINAL : public LTemplateInstruction<1, 1, 2> { public: - explicit LNumberTagU(LOperand* value, LOperand* temp) { + LNumberTagU(LOperand* value, LOperand* temp1, LOperand* temp2) { inputs_[0] = value; - temps_[0] = temp; + temps_[0] = temp1; + temps_[1] = temp2; } LOperand* value() { return inputs_[0]; } - LOperand* temp() { return temps_[0]; } + LOperand* temp1() { return temps_[0]; } + LOperand* temp2() { return temps_[1]; } DECLARE_CONCRETE_INSTRUCTION(NumberTagU, "number-tag-u") }; -- 2.34.1