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