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 FrameAccessState; 20 class Linkage; 21 class OutOfLineCode; 22 23 struct BranchInfo { 24 FlagsCondition condition; 25 Label* true_label; 26 Label* false_label; 27 bool fallthru; 28 }; 29 30 31 class InstructionOperandIterator { 32 public: InstructionOperandIterator(Instruction * instr,size_t pos)33 InstructionOperandIterator(Instruction* instr, size_t pos) 34 : instr_(instr), pos_(pos) {} 35 instruction()36 Instruction* instruction() const { return instr_; } Advance()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. 46 class 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 code()54 InstructionSequence* code() const { return code_; } frame_access_state()55 FrameAccessState* frame_access_state() const { return frame_access_state_; } frame()56 Frame* frame() const { return frame_access_state_->frame(); } isolate()57 Isolate* isolate() const { return info_->isolate(); } linkage()58 Linkage* linkage() const { return linkage_; } 59 GetLabel(RpoNumber rpo)60 Label* GetLabel(RpoNumber rpo) { return &labels_[rpo.ToSize()]; } 61 62 private: masm()63 MacroAssembler* masm() { return &masm_; } resolver()64 GapResolver* resolver() { return &resolver_; } safepoints()65 SafepointTableBuilder* safepoints() { return &safepoints_; } zone()66 Zone* zone() const { return code()->zone(); } info()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: bailout_idDeoptimizationState178 BailoutId bailout_id() const { return bailout_id_; } translation_idDeoptimizationState179 int translation_id() const { return translation_id_; } pc_offsetDeoptimizationState180 int pc_offset() const { return pc_offset_; } 181 DeoptimizationStateDeoptimizationState182 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