• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
3 // found in the LICENSE file.
4 
5 #ifndef V8_COMPILER_CODE_GENERATOR_H_
6 #define V8_COMPILER_CODE_GENERATOR_H_
7 
8 #include "src/compiler/gap-resolver.h"
9 #include "src/compiler/instruction.h"
10 #include "src/deoptimizer.h"
11 #include "src/macro-assembler.h"
12 #include "src/safepoint-table.h"
13 
14 namespace v8 {
15 namespace internal {
16 namespace compiler {
17 
18 // Forward declarations.
19 class DeoptimizationExit;
20 class FrameAccessState;
21 class Linkage;
22 class OutOfLineCode;
23 
24 struct BranchInfo {
25   FlagsCondition condition;
26   Label* true_label;
27   Label* false_label;
28   bool fallthru;
29 };
30 
31 
32 class InstructionOperandIterator {
33  public:
InstructionOperandIterator(Instruction * instr,size_t pos)34   InstructionOperandIterator(Instruction* instr, size_t pos)
35       : instr_(instr), pos_(pos) {}
36 
instruction()37   Instruction* instruction() const { return instr_; }
Advance()38   InstructionOperand* Advance() { return instr_->InputAt(pos_++); }
39 
40  private:
41   Instruction* instr_;
42   size_t pos_;
43 };
44 
45 
46 // Generates native code for a sequence of instructions.
47 class CodeGenerator final : public GapResolver::Assembler {
48  public:
49   explicit CodeGenerator(Frame* frame, Linkage* linkage,
50                          InstructionSequence* code, CompilationInfo* info);
51 
52   // Generate native code.
53   Handle<Code> GenerateCode();
54 
code()55   InstructionSequence* code() const { return code_; }
frame_access_state()56   FrameAccessState* frame_access_state() const { return frame_access_state_; }
frame()57   const Frame* frame() const { return frame_access_state_->frame(); }
isolate()58   Isolate* isolate() const { return info_->isolate(); }
linkage()59   Linkage* linkage() const { return linkage_; }
60 
GetLabel(RpoNumber rpo)61   Label* GetLabel(RpoNumber rpo) { return &labels_[rpo.ToSize()]; }
62 
63  private:
masm()64   MacroAssembler* masm() { return &masm_; }
resolver()65   GapResolver* resolver() { return &resolver_; }
safepoints()66   SafepointTableBuilder* safepoints() { return &safepoints_; }
zone()67   Zone* zone() const { return code()->zone(); }
info()68   CompilationInfo* info() const { return info_; }
69 
70   // Create the FrameAccessState object. The Frame is immutable from here on.
71   void CreateFrameAccessState(Frame* frame);
72 
73   // Architecture - specific frame finalization.
74   void FinishFrame(Frame* frame);
75 
76   // Checks if {block} will appear directly after {current_block_} when
77   // assembling code, in which case, a fall-through can be used.
78   bool IsNextInAssemblyOrder(RpoNumber block) const;
79 
80   // Record a safepoint with the given pointer map.
81   void RecordSafepoint(ReferenceMap* references, Safepoint::Kind kind,
82                        int arguments, Safepoint::DeoptMode deopt_mode);
83 
84   // Check if a heap object can be materialized by loading from the frame, which
85   // is usually way cheaper than materializing the actual heap object constant.
86   bool IsMaterializableFromFrame(Handle<HeapObject> object, int* slot_return);
87   // Check if a heap object can be materialized by loading from a heap root,
88   // which is cheaper on some platforms than materializing the actual heap
89   // object constant.
90   bool IsMaterializableFromRoot(Handle<HeapObject> object,
91                                 Heap::RootListIndex* index_return);
92 
93   enum CodeGenResult { kSuccess, kTooManyDeoptimizationBailouts };
94 
95   // Assemble instructions for the specified block.
96   CodeGenResult AssembleBlock(const InstructionBlock* block);
97 
98   // Assemble code for the specified instruction.
99   CodeGenResult AssembleInstruction(Instruction* instr,
100                                     const InstructionBlock* block);
101   void AssembleSourcePosition(Instruction* instr);
102   void AssembleGaps(Instruction* instr);
103 
104   // ===========================================================================
105   // ============= Architecture-specific code generation methods. ==============
106   // ===========================================================================
107 
108   CodeGenResult AssembleArchInstruction(Instruction* instr);
109   void AssembleArchJump(RpoNumber target);
110   void AssembleArchBranch(Instruction* instr, BranchInfo* branch);
111   void AssembleArchBoolean(Instruction* instr, FlagsCondition condition);
112   void AssembleArchLookupSwitch(Instruction* instr);
113   void AssembleArchTableSwitch(Instruction* instr);
114 
115   CodeGenResult AssembleDeoptimizerCall(int deoptimization_id,
116                                         Deoptimizer::BailoutType bailout_type);
117 
118   // Generates an architecture-specific, descriptor-specific prologue
119   // to set up a stack frame.
120   void AssembleConstructFrame();
121 
122   // Generates an architecture-specific, descriptor-specific return sequence
123   // to tear down a stack frame.
124   void AssembleReturn();
125 
126   // Generates code to deconstruct a the caller's frame, including arguments.
127   void AssembleDeconstructActivationRecord(int stack_param_delta);
128 
129   void AssembleDeconstructFrame();
130 
131   // Generates code to manipulate the stack in preparation for a tail call.
132   void AssemblePrepareTailCall(int stack_param_delta);
133 
134   // Generates code to pop current frame if it is an arguments adaptor frame.
135   void AssemblePopArgumentsAdaptorFrame(Register args_reg, Register scratch1,
136                                         Register scratch2, Register scratch3);
137 
138   // ===========================================================================
139   // ============== Architecture-specific gap resolver methods. ================
140   // ===========================================================================
141 
142   // Interface used by the gap resolver to emit moves and swaps.
143   void AssembleMove(InstructionOperand* source,
144                     InstructionOperand* destination) final;
145   void AssembleSwap(InstructionOperand* source,
146                     InstructionOperand* destination) final;
147 
148   // ===========================================================================
149   // =================== Jump table construction methods. ======================
150   // ===========================================================================
151 
152   class JumpTable;
153   // Adds a jump table that is emitted after the actual code.  Returns label
154   // pointing to the beginning of the table.  {targets} is assumed to be static
155   // or zone allocated.
156   Label* AddJumpTable(Label** targets, size_t target_count);
157   // Emits a jump table.
158   void AssembleJumpTable(Label** targets, size_t target_count);
159 
160   // ===========================================================================
161   // ================== Deoptimization table construction. =====================
162   // ===========================================================================
163 
164   void RecordCallPosition(Instruction* instr);
165   void PopulateDeoptimizationData(Handle<Code> code);
166   int DefineDeoptimizationLiteral(Handle<Object> literal);
167   FrameStateDescriptor* GetFrameStateDescriptor(Instruction* instr,
168                                                 size_t frame_state_offset);
169   int BuildTranslation(Instruction* instr, int pc_offset,
170                        size_t frame_state_offset,
171                        OutputFrameStateCombine state_combine);
172   void BuildTranslationForFrameStateDescriptor(
173       FrameStateDescriptor* descriptor, InstructionOperandIterator* iter,
174       Translation* translation, OutputFrameStateCombine state_combine);
175   void TranslateStateValueDescriptor(StateValueDescriptor* desc,
176                                      Translation* translation,
177                                      InstructionOperandIterator* iter);
178   void TranslateFrameStateDescriptorOperands(FrameStateDescriptor* desc,
179                                              InstructionOperandIterator* iter,
180                                              OutputFrameStateCombine combine,
181                                              Translation* translation);
182   void AddTranslationForOperand(Translation* translation, Instruction* instr,
183                                 InstructionOperand* op, MachineType type);
184   void EnsureSpaceForLazyDeopt();
185   void MarkLazyDeoptSite();
186 
187   DeoptimizationExit* AddDeoptimizationExit(Instruction* instr,
188                                             size_t frame_state_offset);
189 
190   // Converts the delta in the number of stack parameter passed from a tail
191   // caller to the callee into the distance (in pointers) the SP must be
192   // adjusted, taking frame elision and other relevant factors into
193   // consideration.
194   int TailCallFrameStackSlotDelta(int stack_param_delta);
195 
196   // ===========================================================================
197 
198   struct DeoptimizationState : ZoneObject {
199    public:
bailout_idDeoptimizationState200     BailoutId bailout_id() const { return bailout_id_; }
translation_idDeoptimizationState201     int translation_id() const { return translation_id_; }
pc_offsetDeoptimizationState202     int pc_offset() const { return pc_offset_; }
203 
DeoptimizationStateDeoptimizationState204     DeoptimizationState(BailoutId bailout_id, int translation_id, int pc_offset)
205         : bailout_id_(bailout_id),
206           translation_id_(translation_id),
207           pc_offset_(pc_offset) {}
208 
209    private:
210     BailoutId bailout_id_;
211     int translation_id_;
212     int pc_offset_;
213   };
214 
215   struct HandlerInfo {
216     bool caught_locally;
217     Label* handler;
218     int pc_offset;
219   };
220 
221   friend class OutOfLineCode;
222 
223   FrameAccessState* frame_access_state_;
224   Linkage* const linkage_;
225   InstructionSequence* const code_;
226   CompilationInfo* const info_;
227   Label* const labels_;
228   Label return_label_;
229   RpoNumber current_block_;
230   SourcePosition current_source_position_;
231   MacroAssembler masm_;
232   GapResolver resolver_;
233   SafepointTableBuilder safepoints_;
234   ZoneVector<HandlerInfo> handlers_;
235   ZoneDeque<DeoptimizationExit*> deoptimization_exits_;
236   ZoneDeque<DeoptimizationState*> deoptimization_states_;
237   ZoneDeque<Handle<Object>> deoptimization_literals_;
238   size_t inlined_function_count_;
239   TranslationBuffer translations_;
240   int last_lazy_deopt_pc_;
241   JumpTable* jump_tables_;
242   OutOfLineCode* ools_;
243   int osr_pc_offset_;
244 };
245 
246 }  // namespace compiler
247 }  // namespace internal
248 }  // namespace v8
249 
250 #endif  // V8_COMPILER_CODE_GENERATOR_H
251