Home | History | Annotate | Download | only in compiler
      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:
     34   InstructionOperandIterator(Instruction* instr, size_t pos)
     35       : instr_(instr), pos_(pos) {}
     36 
     37   Instruction* instruction() const { return instr_; }
     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 
     55   InstructionSequence* code() const { return code_; }
     56   FrameAccessState* frame_access_state() const { return frame_access_state_; }
     57   const Frame* frame() const { return frame_access_state_->frame(); }
     58   Isolate* isolate() const { return info_->isolate(); }
     59   Linkage* linkage() const { return linkage_; }
     60 
     61   Label* GetLabel(RpoNumber rpo) { return &labels_[rpo.ToSize()]; }
     62 
     63  private:
     64   MacroAssembler* masm() { return &masm_; }
     65   GapResolver* resolver() { return &resolver_; }
     66   SafepointTableBuilder* safepoints() { return &safepoints_; }
     67   Zone* zone() const { return code()->zone(); }
     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:
    200     BailoutId bailout_id() const { return bailout_id_; }
    201     int translation_id() const { return translation_id_; }
    202     int pc_offset() const { return pc_offset_; }
    203 
    204     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