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

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

Issue 1843273002: PPC: [turbofan] Frame elision for code stubs. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Add AssembleBlock Created 4 years, 8 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
« no previous file with comments | « src/compiler/code-generator.cc ('k') | src/ppc/macro-assembler-ppc.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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/ast/scopes.h" 7 #include "src/ast/scopes.h"
8 #include "src/compiler/code-generator-impl.h" 8 #include "src/compiler/code-generator-impl.h"
9 #include "src/compiler/gap-resolver.h" 9 #include "src/compiler/gap-resolver.h"
10 #include "src/compiler/node-matchers.h" 10 #include "src/compiler/node-matchers.h"
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t offset, 180 OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t offset,
181 Register value, Register scratch0, Register scratch1, 181 Register value, Register scratch0, Register scratch1,
182 RecordWriteMode mode) 182 RecordWriteMode mode)
183 : OutOfLineCode(gen), 183 : OutOfLineCode(gen),
184 object_(object), 184 object_(object),
185 offset_(no_reg), 185 offset_(no_reg),
186 offset_immediate_(offset), 186 offset_immediate_(offset),
187 value_(value), 187 value_(value),
188 scratch0_(scratch0), 188 scratch0_(scratch0),
189 scratch1_(scratch1), 189 scratch1_(scratch1),
190 mode_(mode) {} 190 mode_(mode),
191 must_save_lr_(!gen->frame_access_state()->has_frame()) {}
191 192
192 void Generate() final { 193 void Generate() final {
193 if (mode_ > RecordWriteMode::kValueIsPointer) { 194 if (mode_ > RecordWriteMode::kValueIsPointer) {
194 __ JumpIfSmi(value_, exit()); 195 __ JumpIfSmi(value_, exit());
195 } 196 }
196 __ CheckPageFlag(value_, scratch0_, 197 __ CheckPageFlag(value_, scratch0_,
197 MemoryChunk::kPointersToHereAreInterestingMask, eq, 198 MemoryChunk::kPointersToHereAreInterestingMask, eq,
198 exit()); 199 exit());
199 RememberedSetAction const remembered_set_action = 200 RememberedSetAction const remembered_set_action =
200 mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET 201 mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
201 : OMIT_REMEMBERED_SET; 202 : OMIT_REMEMBERED_SET;
202 SaveFPRegsMode const save_fp_mode = 203 SaveFPRegsMode const save_fp_mode =
203 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; 204 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
204 if (!frame()->needs_frame()) { 205 if (must_save_lr_) {
205 // We need to save and restore lr if the frame was elided. 206 // We need to save and restore lr if the frame was elided.
206 __ mflr(scratch1_); 207 __ mflr(scratch1_);
207 __ Push(scratch1_); 208 __ Push(scratch1_);
208 } 209 }
209 RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_, 210 RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_,
210 remembered_set_action, save_fp_mode); 211 remembered_set_action, save_fp_mode);
211 if (offset_.is(no_reg)) { 212 if (offset_.is(no_reg)) {
212 __ addi(scratch1_, object_, Operand(offset_immediate_)); 213 __ addi(scratch1_, object_, Operand(offset_immediate_));
213 } else { 214 } else {
214 DCHECK_EQ(0, offset_immediate_); 215 DCHECK_EQ(0, offset_immediate_);
215 __ add(scratch1_, object_, offset_); 216 __ add(scratch1_, object_, offset_);
216 } 217 }
217 __ CallStub(&stub); 218 __ CallStub(&stub);
218 if (!frame()->needs_frame()) { 219 if (must_save_lr_) {
219 // We need to save and restore lr if the frame was elided. 220 // We need to save and restore lr if the frame was elided.
220 __ Pop(scratch1_); 221 __ Pop(scratch1_);
221 __ mtlr(scratch1_); 222 __ mtlr(scratch1_);
222 } 223 }
223 } 224 }
224 225
225 private: 226 private:
226 Register const object_; 227 Register const object_;
227 Register const offset_; 228 Register const offset_;
228 int32_t const offset_immediate_; // Valid if offset_.is(no_reg). 229 int32_t const offset_immediate_; // Valid if offset_.is(no_reg).
229 Register const value_; 230 Register const value_;
230 Register const scratch0_; 231 Register const scratch0_;
231 Register const scratch1_; 232 Register const scratch1_;
232 RecordWriteMode const mode_; 233 RecordWriteMode const mode_;
234 bool must_save_lr_;
233 }; 235 };
234 236
235 237
236 Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) { 238 Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
237 switch (condition) { 239 switch (condition) {
238 case kEqual: 240 case kEqual:
239 return eq; 241 return eq;
240 case kNotEqual: 242 case kNotEqual:
241 return ne; 243 return ne;
242 case kSignedLessThan: 244 case kSignedLessThan:
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 Register value = i.InputRegister(3); \ 665 Register value = i.InputRegister(3); \
664 if (mode == kMode_MRI) { \ 666 if (mode == kMode_MRI) { \
665 __ asm_instr(value, operand); \ 667 __ asm_instr(value, operand); \
666 } else { \ 668 } else { \
667 __ asm_instrx(value, operand); \ 669 __ asm_instrx(value, operand); \
668 } \ 670 } \
669 __ bind(&done); \ 671 __ bind(&done); \
670 DCHECK_EQ(LeaveRC, i.OutputRCBit()); \ 672 DCHECK_EQ(LeaveRC, i.OutputRCBit()); \
671 } while (0) 673 } while (0)
672 674
675 void CodeGenerator::AssembleDeconstructFrame() {
676 __ LeaveFrame(StackFrame::MANUAL);
677 }
678
679 void CodeGenerator::AssembleSetupStackPointer() {}
673 680
674 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { 681 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
675 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); 682 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
676 if (sp_slot_delta > 0) { 683 if (sp_slot_delta > 0) {
677 __ Add(sp, sp, sp_slot_delta * kPointerSize, r0); 684 __ Add(sp, sp, sp_slot_delta * kPointerSize, r0);
678 } 685 }
679 frame_access_state()->SetFrameAccessToDefault(); 686 frame_access_state()->SetFrameAccessToDefault();
680 } 687 }
681 688
682 689
683 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { 690 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
684 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); 691 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
685 if (sp_slot_delta < 0) { 692 if (sp_slot_delta < 0) {
686 __ Add(sp, sp, sp_slot_delta * kPointerSize, r0); 693 __ Add(sp, sp, sp_slot_delta * kPointerSize, r0);
687 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); 694 frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
688 } 695 }
689 if (frame()->needs_frame()) { 696 if (frame_access_state()->has_frame()) {
690 __ RestoreFrameStateForTailCall(); 697 __ RestoreFrameStateForTailCall();
691 } 698 }
692 frame_access_state()->SetFrameAccessToSP(); 699 frame_access_state()->SetFrameAccessToSP();
693 } 700 }
694 701
695 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, 702 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg,
696 Register scratch1, 703 Register scratch1,
697 Register scratch2, 704 Register scratch2,
698 Register scratch3) { 705 Register scratch3) {
699 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); 706 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
(...skipping 160 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 break; 867 break;
861 case kArchStackPointer: 868 case kArchStackPointer:
862 __ mr(i.OutputRegister(), sp); 869 __ mr(i.OutputRegister(), sp);
863 DCHECK_EQ(LeaveRC, i.OutputRCBit()); 870 DCHECK_EQ(LeaveRC, i.OutputRCBit());
864 break; 871 break;
865 case kArchFramePointer: 872 case kArchFramePointer:
866 __ mr(i.OutputRegister(), fp); 873 __ mr(i.OutputRegister(), fp);
867 DCHECK_EQ(LeaveRC, i.OutputRCBit()); 874 DCHECK_EQ(LeaveRC, i.OutputRCBit());
868 break; 875 break;
869 case kArchParentFramePointer: 876 case kArchParentFramePointer:
870 if (frame_access_state()->frame()->needs_frame()) { 877 if (frame_access_state()->has_frame()) {
871 __ LoadP(i.OutputRegister(), MemOperand(fp, 0)); 878 __ LoadP(i.OutputRegister(), MemOperand(fp, 0));
872 } else { 879 } else {
873 __ mr(i.OutputRegister(), fp); 880 __ mr(i.OutputRegister(), fp);
874 } 881 }
875 break; 882 break;
876 case kArchTruncateDoubleToI: 883 case kArchTruncateDoubleToI:
877 // TODO(mbrandy): move slow call to stub out of line. 884 // TODO(mbrandy): move slow call to stub out of line.
878 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); 885 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
879 DCHECK_EQ(LeaveRC, i.OutputRCBit()); 886 DCHECK_EQ(LeaveRC, i.OutputRCBit());
880 break; 887 break;
(...skipping 807 matching lines...) Expand 10 before | Expand all | Expand 10 after
1688 isolate(), deoptimization_id, bailout_type); 1695 isolate(), deoptimization_id, bailout_type);
1689 // TODO(turbofan): We should be able to generate better code by sharing the 1696 // TODO(turbofan): We should be able to generate better code by sharing the
1690 // actual final call site and just bl'ing to it here, similar to what we do 1697 // actual final call site and just bl'ing to it here, similar to what we do
1691 // in the lithium backend. 1698 // in the lithium backend.
1692 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); 1699 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
1693 } 1700 }
1694 1701
1695 1702
1696 void CodeGenerator::AssemblePrologue() { 1703 void CodeGenerator::AssemblePrologue() {
1697 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); 1704 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
1698 if (frame()->needs_frame()) { 1705 if (frame_access_state()->has_frame()) {
1699 if (descriptor->IsCFunctionCall()) { 1706 if (descriptor->IsCFunctionCall()) {
1700 __ function_descriptor(); 1707 __ function_descriptor();
1701 __ mflr(r0); 1708 __ mflr(r0);
1702 if (FLAG_enable_embedded_constant_pool) { 1709 if (FLAG_enable_embedded_constant_pool) {
1703 __ Push(r0, fp, kConstantPoolRegister); 1710 __ Push(r0, fp, kConstantPoolRegister);
1704 // Adjust FP to point to saved FP. 1711 // Adjust FP to point to saved FP.
1705 __ subi(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset)); 1712 __ subi(fp, sp, Operand(StandardFrameConstants::kConstantPoolOffset));
1706 } else { 1713 } else {
1707 __ Push(r0, fp); 1714 __ Push(r0, fp);
1708 __ mr(fp, sp); 1715 __ mr(fp, sp);
1709 } 1716 }
1710 } else if (descriptor->IsJSFunctionCall()) { 1717 } else if (descriptor->IsJSFunctionCall()) {
1711 __ Prologue(this->info()->GeneratePreagedPrologue(), ip); 1718 __ Prologue(this->info()->GeneratePreagedPrologue(), ip);
1712 } else { 1719 } else {
1713 StackFrame::Type type = info()->GetOutputStackFrameType(); 1720 StackFrame::Type type = info()->GetOutputStackFrameType();
1714 if (!ABI_CALL_VIA_IP && 1721 // TODO(mbrandy): Detect cases where ip is the entrypoint (for
1715 info()->output_code_kind() == Code::WASM_FUNCTION) { 1722 // efficient intialization of the constant pool pointer register).
1716 // TODO(mbrandy): Restrict only to the wasm wrapper case. 1723 __ StubPrologue(type);
1717 __ StubPrologue(type);
1718 } else {
1719 __ StubPrologue(type, ip);
1720 }
1721 } 1724 }
1722 } else {
1723 frame()->SetElidedFrameSizeInSlots(0);
1724 } 1725 }
1725 frame_access_state()->SetFrameAccessToDefault();
1726 1726
1727 int stack_shrink_slots = frame()->GetSpillSlotCount(); 1727 int stack_shrink_slots = frame()->GetSpillSlotCount();
1728 if (info()->is_osr()) { 1728 if (info()->is_osr()) {
1729 // TurboFan OSR-compiled functions cannot be entered directly. 1729 // TurboFan OSR-compiled functions cannot be entered directly.
1730 __ Abort(kShouldNotDirectlyEnterOsrFunction); 1730 __ Abort(kShouldNotDirectlyEnterOsrFunction);
1731 1731
1732 // Unoptimized code jumps directly to this entrypoint while the unoptimized 1732 // Unoptimized code jumps directly to this entrypoint while the unoptimized
1733 // frame is still on the stack. Optimized code uses OSR values directly from 1733 // frame is still on the stack. Optimized code uses OSR values directly from
1734 // the unoptimized frame. Thus, all that needs to be done is to allocate the 1734 // the unoptimized frame. Thus, all that needs to be done is to allocate the
1735 // remaining stack slots. 1735 // remaining stack slots.
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
1784 __ MultiPop(saves); 1784 __ MultiPop(saves);
1785 } 1785 }
1786 1786
1787 // Restore double registers. 1787 // Restore double registers.
1788 const RegList double_saves = descriptor->CalleeSavedFPRegisters(); 1788 const RegList double_saves = descriptor->CalleeSavedFPRegisters();
1789 if (double_saves != 0) { 1789 if (double_saves != 0) {
1790 __ MultiPopDoubles(double_saves); 1790 __ MultiPopDoubles(double_saves);
1791 } 1791 }
1792 1792
1793 if (descriptor->IsCFunctionCall()) { 1793 if (descriptor->IsCFunctionCall()) {
1794 __ LeaveFrame(StackFrame::MANUAL, pop_count * kPointerSize); 1794 AssembleDeconstructFrame();
1795 } else if (frame()->needs_frame()) { 1795 } else if (frame_access_state()->has_frame()) {
1796 // Canonicalize JSFunction return sites for now. 1796 // Canonicalize JSFunction return sites for now.
1797 if (return_label_.is_bound()) { 1797 if (return_label_.is_bound()) {
1798 __ b(&return_label_); 1798 __ b(&return_label_);
1799 return; 1799 return;
1800 } else { 1800 } else {
1801 __ bind(&return_label_); 1801 __ bind(&return_label_);
1802 __ LeaveFrame(StackFrame::MANUAL, pop_count * kPointerSize); 1802 AssembleDeconstructFrame();
1803 } 1803 }
1804 } else {
1805 __ Drop(pop_count);
1806 } 1804 }
1807 __ Ret(); 1805 __ Ret(pop_count);
1808 } 1806 }
1809 1807
1810 1808
1811 void CodeGenerator::AssembleMove(InstructionOperand* source, 1809 void CodeGenerator::AssembleMove(InstructionOperand* source,
1812 InstructionOperand* destination) { 1810 InstructionOperand* destination) {
1813 PPCOperandConverter g(this, nullptr); 1811 PPCOperandConverter g(this, nullptr);
1814 // Dispatch on the source and destination operand kinds. Not all 1812 // Dispatch on the source and destination operand kinds. Not all
1815 // combinations are possible. 1813 // combinations are possible.
1816 if (source->IsRegister()) { 1814 if (source->IsRegister()) {
1817 DCHECK(destination->IsRegister() || destination->IsStackSlot()); 1815 DCHECK(destination->IsRegister() || destination->IsStackSlot());
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
2011 padding_size -= v8::internal::Assembler::kInstrSize; 2009 padding_size -= v8::internal::Assembler::kInstrSize;
2012 } 2010 }
2013 } 2011 }
2014 } 2012 }
2015 2013
2016 #undef __ 2014 #undef __
2017 2015
2018 } // namespace compiler 2016 } // namespace compiler
2019 } // namespace internal 2017 } // namespace internal
2020 } // namespace v8 2018 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/code-generator.cc ('k') | src/ppc/macro-assembler-ppc.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698