Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 the V8 project authors. All rights reserved. | 1 // Copyright 2014 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/code-generator.h" | 5 #include "src/compiler/code-generator.h" |
| 6 | 6 |
| 7 #include "src/arm/macro-assembler-arm.h" | 7 #include "src/arm/macro-assembler-arm.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/compiler/code-generator-impl.h" | 9 #include "src/compiler/code-generator-impl.h" |
| 10 #include "src/compiler/gap-resolver.h" | 10 #include "src/compiler/gap-resolver.h" |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 181 | 181 |
| 182 private: | 182 private: |
| 183 Register const result_; | 183 Register const result_; |
| 184 }; | 184 }; |
| 185 | 185 |
| 186 | 186 |
| 187 class OutOfLineRecordWrite final : public OutOfLineCode { | 187 class OutOfLineRecordWrite final : public OutOfLineCode { |
| 188 public: | 188 public: |
| 189 OutOfLineRecordWrite(CodeGenerator* gen, Register object, Register index, | 189 OutOfLineRecordWrite(CodeGenerator* gen, Register object, Register index, |
| 190 Register value, Register scratch0, Register scratch1, | 190 Register value, Register scratch0, Register scratch1, |
| 191 RecordWriteMode mode) | 191 RecordWriteMode mode, |
| 192 UnwindingInfoWriter* unwinding_info_writer) | |
| 192 : OutOfLineCode(gen), | 193 : OutOfLineCode(gen), |
| 193 object_(object), | 194 object_(object), |
| 194 index_(index), | 195 index_(index), |
| 195 index_immediate_(0), | 196 index_immediate_(0), |
| 196 value_(value), | 197 value_(value), |
| 197 scratch0_(scratch0), | 198 scratch0_(scratch0), |
| 198 scratch1_(scratch1), | 199 scratch1_(scratch1), |
| 199 mode_(mode), | 200 mode_(mode), |
| 200 must_save_lr_(!gen->frame_access_state()->has_frame()) {} | 201 must_save_lr_(!gen->frame_access_state()->has_frame()), |
| 202 unwinding_info_writer_(unwinding_info_writer) {} | |
| 201 | 203 |
| 202 OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t index, | 204 OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t index, |
| 203 Register value, Register scratch0, Register scratch1, | 205 Register value, Register scratch0, Register scratch1, |
| 204 RecordWriteMode mode) | 206 RecordWriteMode mode, |
| 207 UnwindingInfoWriter* unwinding_info_writer) | |
| 205 : OutOfLineCode(gen), | 208 : OutOfLineCode(gen), |
| 206 object_(object), | 209 object_(object), |
| 207 index_(no_reg), | 210 index_(no_reg), |
| 208 index_immediate_(index), | 211 index_immediate_(index), |
| 209 value_(value), | 212 value_(value), |
| 210 scratch0_(scratch0), | 213 scratch0_(scratch0), |
| 211 scratch1_(scratch1), | 214 scratch1_(scratch1), |
| 212 mode_(mode), | 215 mode_(mode), |
| 213 must_save_lr_(!gen->frame_access_state()->has_frame()) {} | 216 must_save_lr_(!gen->frame_access_state()->has_frame()), |
| 217 unwinding_info_writer_(unwinding_info_writer) {} | |
| 214 | 218 |
| 215 void Generate() final { | 219 void Generate() final { |
| 216 if (mode_ > RecordWriteMode::kValueIsPointer) { | 220 if (mode_ > RecordWriteMode::kValueIsPointer) { |
| 217 __ JumpIfSmi(value_, exit()); | 221 __ JumpIfSmi(value_, exit()); |
| 218 } | 222 } |
| 219 __ CheckPageFlag(value_, scratch0_, | 223 __ CheckPageFlag(value_, scratch0_, |
| 220 MemoryChunk::kPointersToHereAreInterestingMask, eq, | 224 MemoryChunk::kPointersToHereAreInterestingMask, eq, |
| 221 exit()); | 225 exit()); |
| 222 RememberedSetAction const remembered_set_action = | 226 RememberedSetAction const remembered_set_action = |
| 223 mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET | 227 mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET |
| 224 : OMIT_REMEMBERED_SET; | 228 : OMIT_REMEMBERED_SET; |
| 225 SaveFPRegsMode const save_fp_mode = | 229 SaveFPRegsMode const save_fp_mode = |
| 226 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; | 230 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; |
| 227 if (must_save_lr_) { | 231 if (must_save_lr_) { |
| 228 // We need to save and restore lr if the frame was elided. | 232 // We need to save and restore lr if the frame was elided. |
| 229 __ Push(lr); | 233 __ Push(lr); |
| 234 if (unwinding_info_writer_) { | |
| 235 unwinding_info_writer_->MarkLinkRegisterOnTopOfStack(__ pc_offset()); | |
| 236 } | |
| 230 } | 237 } |
| 231 RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_, | 238 RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_, |
| 232 remembered_set_action, save_fp_mode); | 239 remembered_set_action, save_fp_mode); |
| 233 if (index_.is(no_reg)) { | 240 if (index_.is(no_reg)) { |
| 234 __ add(scratch1_, object_, Operand(index_immediate_)); | 241 __ add(scratch1_, object_, Operand(index_immediate_)); |
| 235 } else { | 242 } else { |
| 236 DCHECK_EQ(0, index_immediate_); | 243 DCHECK_EQ(0, index_immediate_); |
| 237 __ add(scratch1_, object_, Operand(index_)); | 244 __ add(scratch1_, object_, Operand(index_)); |
| 238 } | 245 } |
| 239 __ CallStub(&stub); | 246 __ CallStub(&stub); |
| 240 if (must_save_lr_) { | 247 if (must_save_lr_) { |
| 241 __ Pop(lr); | 248 __ Pop(lr); |
| 249 if (unwinding_info_writer_) { | |
| 250 unwinding_info_writer_->MarkPopLinkRegisterFromTopOfStack( | |
| 251 __ pc_offset()); | |
| 252 } | |
| 242 } | 253 } |
| 243 } | 254 } |
| 244 | 255 |
| 245 private: | 256 private: |
| 246 Register const object_; | 257 Register const object_; |
| 247 Register const index_; | 258 Register const index_; |
| 248 int32_t const index_immediate_; // Valid if index_.is(no_reg). | 259 int32_t const index_immediate_; // Valid if index_.is(no_reg). |
| 249 Register const value_; | 260 Register const value_; |
| 250 Register const scratch0_; | 261 Register const scratch0_; |
| 251 Register const scratch1_; | 262 Register const scratch1_; |
| 252 RecordWriteMode const mode_; | 263 RecordWriteMode const mode_; |
| 253 bool must_save_lr_; | 264 bool must_save_lr_; |
| 265 UnwindingInfoWriter* const unwinding_info_writer_; | |
| 254 }; | 266 }; |
| 255 | 267 |
| 256 | 268 |
| 257 Condition FlagsConditionToCondition(FlagsCondition condition) { | 269 Condition FlagsConditionToCondition(FlagsCondition condition) { |
| 258 switch (condition) { | 270 switch (condition) { |
| 259 case kEqual: | 271 case kEqual: |
| 260 return eq; | 272 return eq; |
| 261 case kNotEqual: | 273 case kNotEqual: |
| 262 return ne; | 274 return ne; |
| 263 case kSignedLessThan: | 275 case kSignedLessThan: |
| (...skipping 142 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 406 __ MovToFloatParameter(i.InputDoubleRegister(0)); \ | 418 __ MovToFloatParameter(i.InputDoubleRegister(0)); \ |
| 407 __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \ | 419 __ CallCFunction(ExternalReference::ieee754_##name##_function(isolate()), \ |
| 408 0, 1); \ | 420 0, 1); \ |
| 409 /* Move the result in the double result register. */ \ | 421 /* Move the result in the double result register. */ \ |
| 410 __ MovFromFloatResult(i.OutputDoubleRegister()); \ | 422 __ MovFromFloatResult(i.OutputDoubleRegister()); \ |
| 411 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ | 423 DCHECK_EQ(LeaveCC, i.OutputSBit()); \ |
| 412 } while (0) | 424 } while (0) |
| 413 | 425 |
| 414 void CodeGenerator::AssembleDeconstructFrame() { | 426 void CodeGenerator::AssembleDeconstructFrame() { |
| 415 __ LeaveFrame(StackFrame::MANUAL); | 427 __ LeaveFrame(StackFrame::MANUAL); |
| 428 | |
| 429 if (!unwinding_info_writer_.is_empty()) { | |
|
Jarin
2016/07/06 07:09:42
I am wondering whether you do not want to fold thi
rmcilroy
2016/07/07 09:55:17
+1, I think this would make things clearer in the
| |
| 430 unwinding_info_writer_->MarkFrameDeconstructed(__ pc_offset()); | |
| 431 } | |
| 416 } | 432 } |
| 417 | 433 |
| 418 void CodeGenerator::AssemblePrepareTailCall() { | 434 void CodeGenerator::AssemblePrepareTailCall() { |
| 419 if (frame_access_state()->has_frame()) { | 435 if (frame_access_state()->has_frame()) { |
| 420 if (FLAG_enable_embedded_constant_pool) { | 436 if (FLAG_enable_embedded_constant_pool) { |
| 421 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset)); | 437 __ ldr(cp, MemOperand(fp, StandardFrameConstants::kConstantPoolOffset)); |
| 422 } | 438 } |
| 423 __ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); | 439 __ ldr(lr, MemOperand(fp, StandardFrameConstants::kCallerPCOffset)); |
| 424 __ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); | 440 __ ldr(fp, MemOperand(fp, StandardFrameConstants::kCallerFPOffset)); |
| 425 } | 441 } |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 593 } | 609 } |
| 594 if (instr->InputAt(0)->IsImmediate()) { | 610 if (instr->InputAt(0)->IsImmediate()) { |
| 595 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), | 611 __ Jump(Handle<Code>::cast(i.InputHeapObject(0)), |
| 596 RelocInfo::CODE_TARGET); | 612 RelocInfo::CODE_TARGET); |
| 597 } else { | 613 } else { |
| 598 __ add(ip, i.InputRegister(0), | 614 __ add(ip, i.InputRegister(0), |
| 599 Operand(Code::kHeaderSize - kHeapObjectTag)); | 615 Operand(Code::kHeaderSize - kHeapObjectTag)); |
| 600 __ Jump(ip); | 616 __ Jump(ip); |
| 601 } | 617 } |
| 602 DCHECK_EQ(LeaveCC, i.OutputSBit()); | 618 DCHECK_EQ(LeaveCC, i.OutputSBit()); |
| 619 if (!unwinding_info_writer_.is_empty()) { | |
| 620 unwinding_info_writer_->MarkBlockWillExit(); | |
| 621 } | |
| 603 frame_access_state()->ClearSPDelta(); | 622 frame_access_state()->ClearSPDelta(); |
| 604 frame_access_state()->SetFrameAccessToDefault(); | 623 frame_access_state()->SetFrameAccessToDefault(); |
| 605 break; | 624 break; |
| 606 } | 625 } |
| 607 case kArchTailCallAddress: { | 626 case kArchTailCallAddress: { |
| 608 CHECK(!instr->InputAt(0)->IsImmediate()); | 627 CHECK(!instr->InputAt(0)->IsImmediate()); |
| 609 __ Jump(i.InputRegister(0)); | 628 __ Jump(i.InputRegister(0)); |
| 629 if (!unwinding_info_writer_.is_empty()) { | |
| 630 unwinding_info_writer_->MarkBlockWillExit(); | |
| 631 } | |
| 610 frame_access_state()->ClearSPDelta(); | 632 frame_access_state()->ClearSPDelta(); |
| 611 frame_access_state()->SetFrameAccessToDefault(); | 633 frame_access_state()->SetFrameAccessToDefault(); |
| 612 break; | 634 break; |
| 613 } | 635 } |
| 614 case kArchCallJSFunction: { | 636 case kArchCallJSFunction: { |
| 615 EnsureSpaceForLazyDeopt(); | 637 EnsureSpaceForLazyDeopt(); |
| 616 Register func = i.InputRegister(0); | 638 Register func = i.InputRegister(0); |
| 617 if (FLAG_debug_code) { | 639 if (FLAG_debug_code) { |
| 618 // Check the function's context matches the context argument. | 640 // Check the function's context matches the context argument. |
| 619 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); | 641 __ ldr(kScratchReg, FieldMemOperand(func, JSFunction::kContextOffset)); |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 735 Register object = i.InputRegister(0); | 757 Register object = i.InputRegister(0); |
| 736 Register value = i.InputRegister(2); | 758 Register value = i.InputRegister(2); |
| 737 Register scratch0 = i.TempRegister(0); | 759 Register scratch0 = i.TempRegister(0); |
| 738 Register scratch1 = i.TempRegister(1); | 760 Register scratch1 = i.TempRegister(1); |
| 739 OutOfLineRecordWrite* ool; | 761 OutOfLineRecordWrite* ool; |
| 740 | 762 |
| 741 AddressingMode addressing_mode = | 763 AddressingMode addressing_mode = |
| 742 AddressingModeField::decode(instr->opcode()); | 764 AddressingModeField::decode(instr->opcode()); |
| 743 if (addressing_mode == kMode_Offset_RI) { | 765 if (addressing_mode == kMode_Offset_RI) { |
| 744 int32_t index = i.InputInt32(1); | 766 int32_t index = i.InputInt32(1); |
| 745 ool = new (zone()) OutOfLineRecordWrite(this, object, index, value, | 767 ool = new (zone()) |
| 746 scratch0, scratch1, mode); | 768 OutOfLineRecordWrite(this, object, index, value, scratch0, scratch1, |
| 769 mode, unwinding_info_writer_.get()); | |
| 747 __ str(value, MemOperand(object, index)); | 770 __ str(value, MemOperand(object, index)); |
| 748 } else { | 771 } else { |
| 749 DCHECK_EQ(kMode_Offset_RR, addressing_mode); | 772 DCHECK_EQ(kMode_Offset_RR, addressing_mode); |
| 750 Register index(i.InputRegister(1)); | 773 Register index(i.InputRegister(1)); |
| 751 ool = new (zone()) OutOfLineRecordWrite(this, object, index, value, | 774 ool = new (zone()) |
| 752 scratch0, scratch1, mode); | 775 OutOfLineRecordWrite(this, object, index, value, scratch0, scratch1, |
| 776 mode, unwinding_info_writer_.get()); | |
| 753 __ str(value, MemOperand(object, index)); | 777 __ str(value, MemOperand(object, index)); |
| 754 } | 778 } |
| 755 __ CheckPageFlag(object, scratch0, | 779 __ CheckPageFlag(object, scratch0, |
| 756 MemoryChunk::kPointersFromHereAreInterestingMask, ne, | 780 MemoryChunk::kPointersFromHereAreInterestingMask, ne, |
| 757 ool->entry()); | 781 ool->entry()); |
| 758 __ bind(ool->exit()); | 782 __ bind(ool->exit()); |
| 759 break; | 783 break; |
| 760 } | 784 } |
| 761 case kArchStackSlot: { | 785 case kArchStackSlot: { |
| 762 FrameOffset offset = | 786 FrameOffset offset = |
| (...skipping 830 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1593 __ Push(lr, fp); | 1617 __ Push(lr, fp); |
| 1594 __ mov(fp, sp); | 1618 __ mov(fp, sp); |
| 1595 } | 1619 } |
| 1596 } else if (descriptor->IsJSFunctionCall()) { | 1620 } else if (descriptor->IsJSFunctionCall()) { |
| 1597 __ Prologue(this->info()->GeneratePreagedPrologue()); | 1621 __ Prologue(this->info()->GeneratePreagedPrologue()); |
| 1598 } else { | 1622 } else { |
| 1599 __ StubPrologue(info()->GetOutputStackFrameType()); | 1623 __ StubPrologue(info()->GetOutputStackFrameType()); |
| 1600 } | 1624 } |
| 1601 } | 1625 } |
| 1602 | 1626 |
| 1627 if (!unwinding_info_writer_.is_empty() && | |
| 1628 !info()->GeneratePreagedPrologue()) { | |
| 1629 unwinding_info_writer_->MarkFrameConstructed(__ pc_offset()); | |
| 1630 } | |
| 1631 | |
| 1603 int shrink_slots = frame()->GetSpillSlotCount(); | 1632 int shrink_slots = frame()->GetSpillSlotCount(); |
| 1604 | 1633 |
| 1605 if (info()->is_osr()) { | 1634 if (info()->is_osr()) { |
| 1606 // TurboFan OSR-compiled functions cannot be entered directly. | 1635 // TurboFan OSR-compiled functions cannot be entered directly. |
| 1607 __ Abort(kShouldNotDirectlyEnterOsrFunction); | 1636 __ Abort(kShouldNotDirectlyEnterOsrFunction); |
| 1608 | 1637 |
| 1609 // Unoptimized code jumps directly to this entrypoint while the unoptimized | 1638 // Unoptimized code jumps directly to this entrypoint while the unoptimized |
| 1610 // frame is still on the stack. Optimized code uses OSR values directly from | 1639 // frame is still on the stack. Optimized code uses OSR values directly from |
| 1611 // the unoptimized frame. Thus, all that needs to be done is to allocate the | 1640 // the unoptimized frame. Thus, all that needs to be done is to allocate the |
| 1612 // remaining stack slots. | 1641 // remaining stack slots. |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1654 // Restore FP registers. | 1683 // Restore FP registers. |
| 1655 const RegList saves_fp = descriptor->CalleeSavedFPRegisters(); | 1684 const RegList saves_fp = descriptor->CalleeSavedFPRegisters(); |
| 1656 if (saves_fp != 0) { | 1685 if (saves_fp != 0) { |
| 1657 STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32); | 1686 STATIC_ASSERT(DwVfpRegister::kMaxNumRegisters == 32); |
| 1658 uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1; | 1687 uint32_t last = base::bits::CountLeadingZeros32(saves_fp) - 1; |
| 1659 uint32_t first = base::bits::CountTrailingZeros32(saves_fp); | 1688 uint32_t first = base::bits::CountTrailingZeros32(saves_fp); |
| 1660 __ vldm(ia_w, sp, DwVfpRegister::from_code(first), | 1689 __ vldm(ia_w, sp, DwVfpRegister::from_code(first), |
| 1661 DwVfpRegister::from_code(last)); | 1690 DwVfpRegister::from_code(last)); |
| 1662 } | 1691 } |
| 1663 | 1692 |
| 1693 if (!unwinding_info_writer_.is_empty()) { | |
| 1694 unwinding_info_writer_->MarkBlockWillExit(); | |
| 1695 } | |
| 1696 | |
| 1664 if (descriptor->IsCFunctionCall()) { | 1697 if (descriptor->IsCFunctionCall()) { |
| 1665 AssembleDeconstructFrame(); | 1698 AssembleDeconstructFrame(); |
| 1666 } else if (frame_access_state()->has_frame()) { | 1699 } else if (frame_access_state()->has_frame()) { |
| 1667 // Canonicalize JSFunction return sites for now. | 1700 // Canonicalize JSFunction return sites for now. |
| 1668 if (return_label_.is_bound()) { | 1701 if (return_label_.is_bound()) { |
| 1669 __ b(&return_label_); | 1702 __ b(&return_label_); |
| 1670 return; | 1703 return; |
| 1671 } else { | 1704 } else { |
| 1672 __ bind(&return_label_); | 1705 __ bind(&return_label_); |
| 1673 AssembleDeconstructFrame(); | 1706 AssembleDeconstructFrame(); |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1937 padding_size -= v8::internal::Assembler::kInstrSize; | 1970 padding_size -= v8::internal::Assembler::kInstrSize; |
| 1938 } | 1971 } |
| 1939 } | 1972 } |
| 1940 } | 1973 } |
| 1941 | 1974 |
| 1942 #undef __ | 1975 #undef __ |
| 1943 | 1976 |
| 1944 } // namespace compiler | 1977 } // namespace compiler |
| 1945 } // namespace internal | 1978 } // namespace internal |
| 1946 } // namespace v8 | 1979 } // namespace v8 |
| OLD | NEW |