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