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

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

Issue 1848623003: S390: [turbofan] Frame elision for code stubs. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: 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 | « no previous file | src/s390/macro-assembler-s390.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 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
160 OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t offset, 160 OutOfLineRecordWrite(CodeGenerator* gen, Register object, int32_t offset,
161 Register value, Register scratch0, Register scratch1, 161 Register value, Register scratch0, Register scratch1,
162 RecordWriteMode mode) 162 RecordWriteMode mode)
163 : OutOfLineCode(gen), 163 : OutOfLineCode(gen),
164 object_(object), 164 object_(object),
165 offset_(no_reg), 165 offset_(no_reg),
166 offset_immediate_(offset), 166 offset_immediate_(offset),
167 value_(value), 167 value_(value),
168 scratch0_(scratch0), 168 scratch0_(scratch0),
169 scratch1_(scratch1), 169 scratch1_(scratch1),
170 mode_(mode) {} 170 mode_(mode),
171 must_save_lr_(!gen->frame_access_state()->has_frame()) {}
171 172
172 void Generate() final { 173 void Generate() final {
173 if (mode_ > RecordWriteMode::kValueIsPointer) { 174 if (mode_ > RecordWriteMode::kValueIsPointer) {
174 __ JumpIfSmi(value_, exit()); 175 __ JumpIfSmi(value_, exit());
175 } 176 }
176 __ CheckPageFlag(value_, scratch0_, 177 __ CheckPageFlag(value_, scratch0_,
177 MemoryChunk::kPointersToHereAreInterestingMask, eq, 178 MemoryChunk::kPointersToHereAreInterestingMask, eq,
178 exit()); 179 exit());
179 RememberedSetAction const remembered_set_action = 180 RememberedSetAction const remembered_set_action =
180 mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET 181 mode_ > RecordWriteMode::kValueIsMap ? EMIT_REMEMBERED_SET
181 : OMIT_REMEMBERED_SET; 182 : OMIT_REMEMBERED_SET;
182 SaveFPRegsMode const save_fp_mode = 183 SaveFPRegsMode const save_fp_mode =
183 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs; 184 frame()->DidAllocateDoubleRegisters() ? kSaveFPRegs : kDontSaveFPRegs;
184 if (!frame()->needs_frame()) { 185 if (must_save_lr_) {
185 // We need to save and restore r14 if the frame was elided. 186 // We need to save and restore r14 if the frame was elided.
186 __ Push(r14); 187 __ Push(r14);
187 } 188 }
188 RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_, 189 RecordWriteStub stub(isolate(), object_, scratch0_, scratch1_,
189 remembered_set_action, save_fp_mode); 190 remembered_set_action, save_fp_mode);
190 if (offset_.is(no_reg)) { 191 if (offset_.is(no_reg)) {
191 __ AddP(scratch1_, object_, Operand(offset_immediate_)); 192 __ AddP(scratch1_, object_, Operand(offset_immediate_));
192 } else { 193 } else {
193 DCHECK_EQ(0, offset_immediate_); 194 DCHECK_EQ(0, offset_immediate_);
194 __ AddP(scratch1_, object_, offset_); 195 __ AddP(scratch1_, object_, offset_);
195 } 196 }
196 __ CallStub(&stub); 197 __ CallStub(&stub);
197 if (!frame()->needs_frame()) { 198 if (must_save_lr_) {
198 // We need to save and restore r14 if the frame was elided. 199 // We need to save and restore r14 if the frame was elided.
199 __ Pop(r14); 200 __ Pop(r14);
200 } 201 }
201 } 202 }
202 203
203 private: 204 private:
204 Register const object_; 205 Register const object_;
205 Register const offset_; 206 Register const offset_;
206 int32_t const offset_immediate_; // Valid if offset_.is(no_reg). 207 int32_t const offset_immediate_; // Valid if offset_.is(no_reg).
207 Register const value_; 208 Register const value_;
208 Register const scratch0_; 209 Register const scratch0_;
209 Register const scratch1_; 210 Register const scratch1_;
210 RecordWriteMode const mode_; 211 RecordWriteMode const mode_;
212 bool must_save_lr_;
211 }; 213 };
212 214
213 Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) { 215 Condition FlagsConditionToCondition(FlagsCondition condition, ArchOpcode op) {
214 switch (condition) { 216 switch (condition) {
215 case kEqual: 217 case kEqual:
216 return eq; 218 return eq;
217 case kNotEqual: 219 case kNotEqual:
218 return ne; 220 return ne;
219 case kSignedLessThan: 221 case kSignedLessThan:
220 case kUnsignedLessThan: 222 case kUnsignedLessThan:
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
553 __ CmpLogical32(offset, i.InputRegister(2)); \ 555 __ CmpLogical32(offset, i.InputRegister(2)); \
554 } else { \ 556 } else { \
555 __ CmpLogical32(offset, i.InputImmediate(2)); \ 557 __ CmpLogical32(offset, i.InputImmediate(2)); \
556 } \ 558 } \
557 __ bge(&done); \ 559 __ bge(&done); \
558 Register value = i.InputRegister(3); \ 560 Register value = i.InputRegister(3); \
559 __ asm_instr(value, operand); \ 561 __ asm_instr(value, operand); \
560 __ bind(&done); \ 562 __ bind(&done); \
561 } while (0) 563 } while (0)
562 564
565 void CodeGenerator::AssembleDeconstructFrame() {
566 __ LeaveFrame(StackFrame::MANUAL);
567 }
568
569 void CodeGenerator::AssembleSetupStackPointer() {}
570
563 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) { 571 void CodeGenerator::AssembleDeconstructActivationRecord(int stack_param_delta) {
564 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); 572 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
565 if (sp_slot_delta > 0) { 573 if (sp_slot_delta > 0) {
566 __ AddP(sp, sp, Operand(sp_slot_delta * kPointerSize)); 574 __ AddP(sp, sp, Operand(sp_slot_delta * kPointerSize));
567 } 575 }
568 frame_access_state()->SetFrameAccessToDefault(); 576 frame_access_state()->SetFrameAccessToDefault();
569 } 577 }
570 578
571 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) { 579 void CodeGenerator::AssemblePrepareTailCall(int stack_param_delta) {
572 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta); 580 int sp_slot_delta = TailCallFrameStackSlotDelta(stack_param_delta);
573 if (sp_slot_delta < 0) { 581 if (sp_slot_delta < 0) {
574 __ AddP(sp, sp, Operand(sp_slot_delta * kPointerSize)); 582 __ AddP(sp, sp, Operand(sp_slot_delta * kPointerSize));
575 frame_access_state()->IncreaseSPDelta(-sp_slot_delta); 583 frame_access_state()->IncreaseSPDelta(-sp_slot_delta);
576 } 584 }
577 if (frame()->needs_frame()) { 585 if (frame_access_state()->has_frame()) {
578 __ RestoreFrameStateForTailCall(); 586 __ RestoreFrameStateForTailCall();
579 } 587 }
580 frame_access_state()->SetFrameAccessToSP(); 588 frame_access_state()->SetFrameAccessToSP();
581 } 589 }
582 590
583 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg, 591 void CodeGenerator::AssemblePopArgumentsAdaptorFrame(Register args_reg,
584 Register scratch1, 592 Register scratch1,
585 Register scratch2, 593 Register scratch2,
586 Register scratch3) { 594 Register scratch3) {
587 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3)); 595 DCHECK(!AreAliased(args_reg, scratch1, scratch2, scratch3));
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
733 case kArchRet: 741 case kArchRet:
734 AssembleReturn(); 742 AssembleReturn();
735 break; 743 break;
736 case kArchStackPointer: 744 case kArchStackPointer:
737 __ LoadRR(i.OutputRegister(), sp); 745 __ LoadRR(i.OutputRegister(), sp);
738 break; 746 break;
739 case kArchFramePointer: 747 case kArchFramePointer:
740 __ LoadRR(i.OutputRegister(), fp); 748 __ LoadRR(i.OutputRegister(), fp);
741 break; 749 break;
742 case kArchParentFramePointer: 750 case kArchParentFramePointer:
743 if (frame_access_state()->frame()->needs_frame()) { 751 if (frame_access_state()->has_frame()) {
744 __ LoadP(i.OutputRegister(), MemOperand(fp, 0)); 752 __ LoadP(i.OutputRegister(), MemOperand(fp, 0));
745 } else { 753 } else {
746 __ LoadRR(i.OutputRegister(), fp); 754 __ LoadRR(i.OutputRegister(), fp);
747 } 755 }
748 break; 756 break;
749 case kArchTruncateDoubleToI: 757 case kArchTruncateDoubleToI:
750 // TODO(mbrandy): move slow call to stub out of line. 758 // TODO(mbrandy): move slow call to stub out of line.
751 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0)); 759 __ TruncateDoubleToI(i.OutputRegister(), i.InputDoubleRegister(0));
752 break; 760 break;
753 case kArchStoreWithWriteBarrier: { 761 case kArchStoreWithWriteBarrier: {
(...skipping 1019 matching lines...) Expand 10 before | Expand all | Expand 10 after
1773 isolate(), deoptimization_id, bailout_type); 1781 isolate(), deoptimization_id, bailout_type);
1774 // TODO(turbofan): We should be able to generate better code by sharing the 1782 // TODO(turbofan): We should be able to generate better code by sharing the
1775 // actual final call site and just bl'ing to it here, similar to what we do 1783 // actual final call site and just bl'ing to it here, similar to what we do
1776 // in the lithium backend. 1784 // in the lithium backend.
1777 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY); 1785 __ Call(deopt_entry, RelocInfo::RUNTIME_ENTRY);
1778 } 1786 }
1779 1787
1780 void CodeGenerator::AssemblePrologue() { 1788 void CodeGenerator::AssemblePrologue() {
1781 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor(); 1789 CallDescriptor* descriptor = linkage()->GetIncomingDescriptor();
1782 1790
1783 if (frame()->needs_frame()) { 1791 if (frame_access_state()->has_frame()) {
1784 if (descriptor->IsCFunctionCall()) { 1792 if (descriptor->IsCFunctionCall()) {
1785 __ Push(r14, fp); 1793 __ Push(r14, fp);
1786 __ LoadRR(fp, sp); 1794 __ LoadRR(fp, sp);
1787 } else if (descriptor->IsJSFunctionCall()) { 1795 } else if (descriptor->IsJSFunctionCall()) {
1788 __ Prologue(this->info()->GeneratePreagedPrologue(), ip); 1796 __ Prologue(this->info()->GeneratePreagedPrologue(), ip);
1789 } else { 1797 } else {
1790 StackFrame::Type type = info()->GetOutputStackFrameType(); 1798 StackFrame::Type type = info()->GetOutputStackFrameType();
1791 if (!ABI_CALL_VIA_IP && 1799 // TODO(mbrandy): Detect cases where ip is the entrypoint (for
1792 info()->output_code_kind() == Code::WASM_FUNCTION) { 1800 // efficient intialization of the constant pool pointer register).
1793 // TODO(mbrandy): Restrict only to the wasm wrapper case. 1801 __ StubPrologue(type);
1794 __ StubPrologue(type);
1795 } else {
1796 __ StubPrologue(type, ip);
1797 }
1798 } 1802 }
1799 } else {
1800 frame()->SetElidedFrameSizeInSlots(0);
1801 } 1803 }
1802 frame_access_state()->SetFrameAccessToDefault();
1803 1804
1804 int stack_shrink_slots = frame()->GetSpillSlotCount(); 1805 int stack_shrink_slots = frame()->GetSpillSlotCount();
1805 if (info()->is_osr()) { 1806 if (info()->is_osr()) {
1806 // TurboFan OSR-compiled functions cannot be entered directly. 1807 // TurboFan OSR-compiled functions cannot be entered directly.
1807 __ Abort(kShouldNotDirectlyEnterOsrFunction); 1808 __ Abort(kShouldNotDirectlyEnterOsrFunction);
1808 1809
1809 // Unoptimized code jumps directly to this entrypoint while the unoptimized 1810 // Unoptimized code jumps directly to this entrypoint while the unoptimized
1810 // frame is still on the stack. Optimized code uses OSR values directly from 1811 // frame is still on the stack. Optimized code uses OSR values directly from
1811 // the unoptimized frame. Thus, all that needs to be done is to allocate the 1812 // the unoptimized frame. Thus, all that needs to be done is to allocate the
1812 // remaining stack slots. 1813 // remaining stack slots.
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
1854 __ MultiPop(saves); 1855 __ MultiPop(saves);
1855 } 1856 }
1856 1857
1857 // Restore double registers. 1858 // Restore double registers.
1858 const RegList double_saves = descriptor->CalleeSavedFPRegisters(); 1859 const RegList double_saves = descriptor->CalleeSavedFPRegisters();
1859 if (double_saves != 0) { 1860 if (double_saves != 0) {
1860 __ MultiPopDoubles(double_saves); 1861 __ MultiPopDoubles(double_saves);
1861 } 1862 }
1862 1863
1863 if (descriptor->IsCFunctionCall()) { 1864 if (descriptor->IsCFunctionCall()) {
1864 __ LeaveFrame(StackFrame::MANUAL, pop_count * kPointerSize); 1865 AssembleDeconstructFrame();
1865 } else if (frame()->needs_frame()) { 1866 } else if (frame_access_state()->has_frame()) {
1866 // Canonicalize JSFunction return sites for now. 1867 // Canonicalize JSFunction return sites for now.
1867 if (return_label_.is_bound()) { 1868 if (return_label_.is_bound()) {
1868 __ b(&return_label_); 1869 __ b(&return_label_);
1869 return; 1870 return;
1870 } else { 1871 } else {
1871 __ bind(&return_label_); 1872 __ bind(&return_label_);
1872 __ LeaveFrame(StackFrame::MANUAL, pop_count * kPointerSize); 1873 AssembleDeconstructFrame();
1873 } 1874 }
1874 } else {
1875 __ Drop(pop_count);
1876 } 1875 }
1877 __ Ret(); 1876 __ Ret(pop_count);
1878 } 1877 }
1879 1878
1880 void CodeGenerator::AssembleMove(InstructionOperand* source, 1879 void CodeGenerator::AssembleMove(InstructionOperand* source,
1881 InstructionOperand* destination) { 1880 InstructionOperand* destination) {
1882 S390OperandConverter g(this, nullptr); 1881 S390OperandConverter g(this, nullptr);
1883 // Dispatch on the source and destination operand kinds. Not all 1882 // Dispatch on the source and destination operand kinds. Not all
1884 // combinations are possible. 1883 // combinations are possible.
1885 if (source->IsRegister()) { 1884 if (source->IsRegister()) {
1886 DCHECK(destination->IsRegister() || destination->IsStackSlot()); 1885 DCHECK(destination->IsRegister() || destination->IsStackSlot());
1887 Register src = g.ToRegister(source); 1886 Register src = g.ToRegister(source);
(...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after
2079 padding_size -= 2; 2078 padding_size -= 2;
2080 } 2079 }
2081 } 2080 }
2082 } 2081 }
2083 2082
2084 #undef __ 2083 #undef __
2085 2084
2086 } // namespace compiler 2085 } // namespace compiler
2087 } // namespace internal 2086 } // namespace internal
2088 } // namespace v8 2087 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/s390/macro-assembler-s390.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698