Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(284)

Side by Side Diff: src/compiler/arm/code-generator-arm.cc

Issue 2026313002: Emit unwinding information for TurboFan code. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@eh-frame
Patch Set: Clarify assumptions on frame ction/dtion routines in arm/arm64. Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698