Line data Source code
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/compiler/unwinding-info-writer.h"
11 : #include "src/deoptimizer.h"
12 : #include "src/macro-assembler.h"
13 : #include "src/safepoint-table.h"
14 : #include "src/source-position-table.h"
15 : #include "src/trap-handler/trap-handler.h"
16 :
17 : namespace v8 {
18 : namespace internal {
19 :
20 : class CompilationInfo;
21 :
22 : namespace compiler {
23 :
24 : // Forward declarations.
25 : class DeoptimizationExit;
26 : class FrameAccessState;
27 : class Linkage;
28 : class OutOfLineCode;
29 :
30 : struct BranchInfo {
31 : FlagsCondition condition;
32 : Label* true_label;
33 : Label* false_label;
34 : bool fallthru;
35 : };
36 :
37 :
38 : class InstructionOperandIterator {
39 : public:
40 : InstructionOperandIterator(Instruction* instr, size_t pos)
41 4411708 : : instr_(instr), pos_(pos) {}
42 :
43 : Instruction* instruction() const { return instr_; }
44 31696858 : InstructionOperand* Advance() { return instr_->InputAt(pos_++); }
45 :
46 : private:
47 : Instruction* instr_;
48 : size_t pos_;
49 : };
50 :
51 :
52 : // Generates native code for a sequence of instructions.
53 1824784 : class CodeGenerator final : public GapResolver::Assembler {
54 : public:
55 : explicit CodeGenerator(Frame* frame, Linkage* linkage,
56 : InstructionSequence* code, CompilationInfo* info);
57 :
58 : // Generate native code.
59 : Handle<Code> GenerateCode();
60 :
61 : InstructionSequence* code() const { return code_; }
62 : FrameAccessState* frame_access_state() const { return frame_access_state_; }
63 6651553 : const Frame* frame() const { return frame_access_state_->frame(); }
64 : Isolate* isolate() const;
65 : Linkage* linkage() const { return linkage_; }
66 :
67 20409461 : Label* GetLabel(RpoNumber rpo) { return &labels_[rpo.ToSize()]; }
68 :
69 : void AssembleSourcePosition(Instruction* instr);
70 :
71 : void AssembleSourcePosition(SourcePosition source_position);
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 : private:
78 : MacroAssembler* masm() { return &masm_; }
79 : GapResolver* resolver() { return &resolver_; }
80 : SafepointTableBuilder* safepoints() { return &safepoints_; }
81 21924972 : Zone* zone() const { return code()->zone(); }
82 : CompilationInfo* info() const { return info_; }
83 :
84 : // Create the FrameAccessState object. The Frame is immutable from here on.
85 : void CreateFrameAccessState(Frame* frame);
86 :
87 : // Architecture - specific frame finalization.
88 : void FinishFrame(Frame* frame);
89 :
90 : // Checks if {block} will appear directly after {current_block_} when
91 : // assembling code, in which case, a fall-through can be used.
92 : bool IsNextInAssemblyOrder(RpoNumber block) const;
93 :
94 : // Check if a heap object can be materialized by loading from a heap root,
95 : // which is cheaper on some platforms than materializing the actual heap
96 : // object constant.
97 : bool IsMaterializableFromRoot(Handle<HeapObject> object,
98 : Heap::RootListIndex* index_return);
99 :
100 : enum CodeGenResult { kSuccess, kTooManyDeoptimizationBailouts };
101 :
102 : // Assemble instructions for the specified block.
103 : CodeGenResult AssembleBlock(const InstructionBlock* block);
104 :
105 : // Assemble code for the specified instruction.
106 : CodeGenResult AssembleInstruction(Instruction* instr,
107 : const InstructionBlock* block);
108 : void AssembleGaps(Instruction* instr);
109 :
110 : // Returns true if a instruction is a tail call that needs to adjust the stack
111 : // pointer before execution. The stack slot index to the empty slot above the
112 : // adjusted stack pointer is returned in |slot|.
113 : bool GetSlotAboveSPBeforeTailCall(Instruction* instr, int* slot);
114 :
115 : // ===========================================================================
116 : // ============= Architecture-specific code generation methods. ==============
117 : // ===========================================================================
118 :
119 : CodeGenResult AssembleArchInstruction(Instruction* instr);
120 : void AssembleArchJump(RpoNumber target);
121 : void AssembleArchBranch(Instruction* instr, BranchInfo* branch);
122 : void AssembleArchBoolean(Instruction* instr, FlagsCondition condition);
123 : void AssembleArchTrap(Instruction* instr, FlagsCondition condition);
124 : void AssembleArchLookupSwitch(Instruction* instr);
125 : void AssembleArchTableSwitch(Instruction* instr);
126 :
127 : CodeGenResult AssembleDeoptimizerCall(int deoptimization_id,
128 : SourcePosition pos);
129 :
130 : // Generates an architecture-specific, descriptor-specific prologue
131 : // to set up a stack frame.
132 : void AssembleConstructFrame();
133 :
134 : // Generates an architecture-specific, descriptor-specific return sequence
135 : // to tear down a stack frame.
136 : void AssembleReturn(InstructionOperand* pop);
137 :
138 : void AssembleDeconstructFrame();
139 :
140 : // Generates code to manipulate the stack in preparation for a tail call.
141 : void AssemblePrepareTailCall();
142 :
143 : // Generates code to pop current frame if it is an arguments adaptor frame.
144 : void AssemblePopArgumentsAdaptorFrame(Register args_reg, Register scratch1,
145 : Register scratch2, Register scratch3);
146 :
147 : enum PushTypeFlag {
148 : kImmediatePush = 0x1,
149 : kScalarPush = 0x2,
150 : kFloat32Push = 0x4,
151 : kFloat64Push = 0x8,
152 : kFloatPush = kFloat32Push | kFloat64Push
153 : };
154 :
155 : typedef base::Flags<PushTypeFlag> PushTypeFlags;
156 :
157 : static bool IsValidPush(InstructionOperand source, PushTypeFlags push_type);
158 :
159 : // Generate a list moves from an instruction that are candidates to be turned
160 : // into push instructions on platforms that support them. In general, the list
161 : // of push candidates are moves to a set of contiguous destination
162 : // InstructionOperand locations on the stack that don't clobber values that
163 : // are needed for resolve the gap or use values generated by the gap,
164 : // i.e. moves that can be hoisted together before the actual gap and assembled
165 : // together.
166 : static void GetPushCompatibleMoves(Instruction* instr,
167 : PushTypeFlags push_type,
168 : ZoneVector<MoveOperands*>* pushes);
169 :
170 : // Called before a tail call |instr|'s gap moves are assembled and allows
171 : // gap-specific pre-processing, e.g. adjustment of the sp for tail calls that
172 : // need it before gap moves or conversion of certain gap moves into pushes.
173 : void AssembleTailCallBeforeGap(Instruction* instr,
174 : int first_unused_stack_slot);
175 : // Called after a tail call |instr|'s gap moves are assembled and allows
176 : // gap-specific post-processing, e.g. adjustment of the sp for tail calls that
177 : // need it after gap moves.
178 : void AssembleTailCallAfterGap(Instruction* instr,
179 : int first_unused_stack_slot);
180 :
181 : void FinishCode();
182 :
183 : // ===========================================================================
184 : // ============== Architecture-specific gap resolver methods. ================
185 : // ===========================================================================
186 :
187 : // Interface used by the gap resolver to emit moves and swaps.
188 : void AssembleMove(InstructionOperand* source,
189 : InstructionOperand* destination) final;
190 : void AssembleSwap(InstructionOperand* source,
191 : InstructionOperand* destination) final;
192 :
193 : // ===========================================================================
194 : // =================== Jump table construction methods. ======================
195 : // ===========================================================================
196 :
197 : class JumpTable;
198 : // Adds a jump table that is emitted after the actual code. Returns label
199 : // pointing to the beginning of the table. {targets} is assumed to be static
200 : // or zone allocated.
201 : Label* AddJumpTable(Label** targets, size_t target_count);
202 : // Emits a jump table.
203 : void AssembleJumpTable(Label** targets, size_t target_count);
204 :
205 : // ===========================================================================
206 : // ================== Deoptimization table construction. =====================
207 : // ===========================================================================
208 :
209 : void RecordCallPosition(Instruction* instr);
210 : void PopulateDeoptimizationData(Handle<Code> code);
211 : int DefineDeoptimizationLiteral(Handle<Object> literal);
212 : DeoptimizationEntry const& GetDeoptimizationEntry(Instruction* instr,
213 : size_t frame_state_offset);
214 : DeoptimizeKind GetDeoptimizationKind(int deoptimization_id) const;
215 : DeoptimizeReason GetDeoptimizationReason(int deoptimization_id) const;
216 : int BuildTranslation(Instruction* instr, int pc_offset,
217 : size_t frame_state_offset,
218 : OutputFrameStateCombine state_combine);
219 : void BuildTranslationForFrameStateDescriptor(
220 : FrameStateDescriptor* descriptor, InstructionOperandIterator* iter,
221 : Translation* translation, OutputFrameStateCombine state_combine);
222 : void TranslateStateValueDescriptor(StateValueDescriptor* desc,
223 : StateValueList* nested,
224 : Translation* translation,
225 : InstructionOperandIterator* iter);
226 : void TranslateFrameStateDescriptorOperands(FrameStateDescriptor* desc,
227 : InstructionOperandIterator* iter,
228 : OutputFrameStateCombine combine,
229 : Translation* translation);
230 : void AddTranslationForOperand(Translation* translation, Instruction* instr,
231 : InstructionOperand* op, MachineType type);
232 : void EnsureSpaceForLazyDeopt();
233 : void MarkLazyDeoptSite();
234 :
235 : DeoptimizationExit* AddDeoptimizationExit(Instruction* instr,
236 : size_t frame_state_offset);
237 :
238 : // ===========================================================================
239 :
240 : class DeoptimizationState final : public ZoneObject {
241 : public:
242 : DeoptimizationState(BailoutId bailout_id, int translation_id, int pc_offset,
243 : DeoptimizeKind kind, DeoptimizeReason reason)
244 : : bailout_id_(bailout_id),
245 : translation_id_(translation_id),
246 : pc_offset_(pc_offset),
247 : kind_(kind),
248 4411712 : reason_(reason) {}
249 :
250 : BailoutId bailout_id() const { return bailout_id_; }
251 : int translation_id() const { return translation_id_; }
252 : int pc_offset() const { return pc_offset_; }
253 : DeoptimizeKind kind() const { return kind_; }
254 : DeoptimizeReason reason() const { return reason_; }
255 :
256 : private:
257 : BailoutId bailout_id_;
258 : int translation_id_;
259 : int pc_offset_;
260 : DeoptimizeKind kind_;
261 : DeoptimizeReason reason_;
262 : };
263 :
264 : struct HandlerInfo {
265 : Label* handler;
266 : int pc_offset;
267 : };
268 :
269 : friend class OutOfLineCode;
270 :
271 : FrameAccessState* frame_access_state_;
272 : Linkage* const linkage_;
273 : InstructionSequence* const code_;
274 : UnwindingInfoWriter unwinding_info_writer_;
275 : CompilationInfo* const info_;
276 : Label* const labels_;
277 : Label return_label_;
278 : RpoNumber current_block_;
279 : SourcePosition current_source_position_;
280 : MacroAssembler masm_;
281 : GapResolver resolver_;
282 : SafepointTableBuilder safepoints_;
283 : ZoneVector<HandlerInfo> handlers_;
284 : ZoneDeque<DeoptimizationExit*> deoptimization_exits_;
285 : ZoneDeque<DeoptimizationState*> deoptimization_states_;
286 : ZoneDeque<Handle<Object>> deoptimization_literals_;
287 : size_t inlined_function_count_;
288 : TranslationBuffer translations_;
289 : int last_lazy_deopt_pc_;
290 : JumpTable* jump_tables_;
291 : OutOfLineCode* ools_;
292 : int osr_pc_offset_;
293 : int optimized_out_literal_id_;
294 : SourcePositionTableBuilder source_position_table_builder_;
295 : };
296 :
297 : } // namespace compiler
298 : } // namespace internal
299 : } // namespace v8
300 :
301 : #endif // V8_COMPILER_CODE_GENERATOR_H
|