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 |