blob: 70bf81f5afede940cbe927afbaf315e3e1ef0891 [file] [log] [blame]
Ben Murdochb8a8cc12014-11-26 15:28:44 +00001// 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +00008#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
Emily Bernierd0a1eb72015-03-24 16:35:39 -040018// Forward declarations.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000019class FrameAccessState;
Emily Bernierd0a1eb72015-03-24 16:35:39 -040020class Linkage;
21class OutOfLineCode;
22
23struct BranchInfo {
24 FlagsCondition condition;
25 Label* true_label;
26 Label* false_label;
27 bool fallthru;
28};
29
30
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000031class 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +000045// Generates native code for a sequence of instructions.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000046class CodeGenerator final : public GapResolver::Assembler {
Ben Murdochb8a8cc12014-11-26 15:28:44 +000047 public:
Emily Bernierd0a1eb72015-03-24 16:35:39 -040048 explicit CodeGenerator(Frame* frame, Linkage* linkage,
49 InstructionSequence* code, CompilationInfo* info);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000050
51 // Generate native code.
52 Handle<Code> GenerateCode();
53
54 InstructionSequence* code() const { return code_; }
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000055 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(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040058 Linkage* linkage() const { return linkage_; }
59
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000060 Label* GetLabel(RpoNumber rpo) { return &labels_[rpo.ToSize()]; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000061
62 private:
63 MacroAssembler* masm() { return &masm_; }
64 GapResolver* resolver() { return &resolver_; }
65 SafepointTableBuilder* safepoints() { return &safepoints_; }
66 Zone* zone() const { return code()->zone(); }
Emily Bernierd0a1eb72015-03-24 16:35:39 -040067 CompilationInfo* info() const { return info_; }
Ben Murdochb8a8cc12014-11-26 15:28:44 +000068
69 // Checks if {block} will appear directly after {current_block_} when
70 // assembling code, in which case, a fall-through can be used.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000071 bool IsNextInAssemblyOrder(RpoNumber block) const;
Ben Murdochb8a8cc12014-11-26 15:28:44 +000072
73 // Record a safepoint with the given pointer map.
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000074 void RecordSafepoint(ReferenceMap* references, Safepoint::Kind kind,
Ben Murdochb8a8cc12014-11-26 15:28:44 +000075 int arguments, Safepoint::DeoptMode deopt_mode);
76
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000077 // 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +000086 // Assemble code for the specified instruction.
87 void AssembleInstruction(Instruction* instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000088 void AssembleSourcePosition(Instruction* instr);
89 void AssembleGaps(Instruction* instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000090
91 // ===========================================================================
92 // ============= Architecture-specific code generation methods. ==============
93 // ===========================================================================
94
95 void AssembleArchInstruction(Instruction* instr);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000096 void AssembleArchJump(RpoNumber target);
Emily Bernierd0a1eb72015-03-24 16:35:39 -040097 void AssembleArchBranch(Instruction* instr, BranchInfo* branch);
Ben Murdochb8a8cc12014-11-26 15:28:44 +000098 void AssembleArchBoolean(Instruction* instr, FlagsCondition condition);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +000099 void AssembleArchLookupSwitch(Instruction* instr);
100 void AssembleArchTableSwitch(Instruction* instr);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000101
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000102 void AssembleDeoptimizerCall(int deoptimization_id,
103 Deoptimizer::BailoutType bailout_type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000104
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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000112 // 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000118 // ===========================================================================
119 // ============== Architecture-specific gap resolver methods. ================
120 // ===========================================================================
121
122 // Interface used by the gap resolver to emit moves and swaps.
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400123 void AssembleMove(InstructionOperand* source,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000124 InstructionOperand* destination) final;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400125 void AssembleSwap(InstructionOperand* source,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000126 InstructionOperand* destination) final;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000127
128 // ===========================================================================
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000129 // =================== 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);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000145 void PopulateDeoptimizationData(Handle<Code> code);
146 int DefineDeoptimizationLiteral(Handle<Object> literal);
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000147 FrameStateDescriptor* GetFrameStateDescriptor(
148 Instruction* instr, size_t frame_access_state_offset);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000149 int BuildTranslation(Instruction* instr, int pc_offset,
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000150 size_t frame_access_state_offset,
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000151 OutputFrameStateCombine state_combine);
152 void BuildTranslationForFrameStateDescriptor(
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000153 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);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000162 void AddTranslationForOperand(Translation* translation, Instruction* instr,
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400163 InstructionOperand* op, MachineType type);
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000164 void AddNopForSmiCodeInlining();
165 void EnsureSpaceForLazyDeopt();
166 void MarkLazyDeoptSite();
167
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000168 // 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
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000174 // ===========================================================================
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000175
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000176 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
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000193 struct HandlerInfo {
194 bool caught_locally;
195 Label* handler;
196 int pc_offset;
197 };
198
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400199 friend class OutOfLineCode;
200
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000201 FrameAccessState* frame_access_state_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400202 Linkage* const linkage_;
203 InstructionSequence* const code_;
204 CompilationInfo* const info_;
205 Label* const labels_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000206 Label return_label_;
207 RpoNumber current_block_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000208 SourcePosition current_source_position_;
209 MacroAssembler masm_;
210 GapResolver resolver_;
211 SafepointTableBuilder safepoints_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000212 ZoneVector<HandlerInfo> handlers_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000213 ZoneDeque<DeoptimizationState*> deoptimization_states_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000214 ZoneDeque<Handle<Object>> deoptimization_literals_;
215 size_t inlined_function_count_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000216 TranslationBuffer translations_;
217 int last_lazy_deopt_pc_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000218 JumpTable* jump_tables_;
Emily Bernierd0a1eb72015-03-24 16:35:39 -0400219 OutOfLineCode* ools_;
Ben Murdoch4a90d5f2016-03-22 12:00:34 +0000220 int osr_pc_offset_;
Ben Murdochb8a8cc12014-11-26 15:28:44 +0000221};
222
223} // namespace compiler
224} // namespace internal
225} // namespace v8
226
227#endif // V8_COMPILER_CODE_GENERATOR_H