LCOV - code coverage report
Current view: top level - src/compiler - code-generator.h (source / functions) Hit Total Coverage
Test: app.info Lines: 11 11 100.0 %
Date: 2017-10-20 Functions: 2 3 66.7 %

          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/base/optional.h"
       9             : #include "src/compiler/gap-resolver.h"
      10             : #include "src/compiler/instruction.h"
      11             : #include "src/compiler/osr.h"
      12             : #include "src/compiler/unwinding-info-writer.h"
      13             : #include "src/deoptimizer.h"
      14             : #include "src/macro-assembler.h"
      15             : #include "src/safepoint-table.h"
      16             : #include "src/source-position-table.h"
      17             : #include "src/trap-handler/trap-handler.h"
      18             : 
      19             : namespace v8 {
      20             : namespace internal {
      21             : 
      22             : class CompilationInfo;
      23             : 
      24             : namespace compiler {
      25             : 
      26             : // Forward declarations.
      27             : class DeoptimizationExit;
      28             : class FrameAccessState;
      29             : class Linkage;
      30             : class OutOfLineCode;
      31             : 
      32             : struct BranchInfo {
      33             :   FlagsCondition condition;
      34             :   Label* true_label;
      35             :   Label* false_label;
      36             :   bool fallthru;
      37             : };
      38             : 
      39             : 
      40             : class InstructionOperandIterator {
      41             :  public:
      42             :   InstructionOperandIterator(Instruction* instr, size_t pos)
      43     3087693 :       : instr_(instr), pos_(pos) {}
      44             : 
      45             :   Instruction* instruction() const { return instr_; }
      46    20713945 :   InstructionOperand* Advance() { return instr_->InputAt(pos_++); }
      47             : 
      48             :  private:
      49             :   Instruction* instr_;
      50             :   size_t pos_;
      51             : };
      52             : 
      53             : // Either a non-null Handle<Object> or a double.
      54             : class DeoptimizationLiteral {
      55             :  public:
      56     5511216 :   DeoptimizationLiteral() : object_(), number_(0) {}
      57             :   explicit DeoptimizationLiteral(Handle<Object> object)
      58     3863390 :       : object_(object), number_(0) {
      59             :     DCHECK(!object_.is_null());
      60             :   }
      61             :   explicit DeoptimizationLiteral(double number) : object_(), number_(number) {}
      62             : 
      63             :   Handle<Object> object() const { return object_; }
      64             : 
      65    27665933 :   bool operator==(const DeoptimizationLiteral& other) const {
      66    34709335 :     return object_.equals(other.object_) &&
      67    41752737 :            bit_cast<uint64_t>(number_) == bit_cast<uint64_t>(other.number_);
      68             :   }
      69             : 
      70             :   Handle<Object> Reify(Isolate* isolate) const;
      71             : 
      72             :  private:
      73             :   Handle<Object> object_;
      74             :   double number_;
      75             : };
      76             : 
      77             : // Generates native code for a sequence of instructions.
      78     3904742 : class CodeGenerator final : public GapResolver::Assembler {
      79             :  public:
      80             :   explicit CodeGenerator(Zone* codegen_zone, Frame* frame, Linkage* linkage,
      81             :                          InstructionSequence* code, CompilationInfo* info,
      82             :                          base::Optional<OsrHelper> osr_helper,
      83             :                          int start_source_position,
      84             :                          JumpOptimizationInfo* jump_opt);
      85             : 
      86             :   // Generate native code. After calling AssembleCode, call FinalizeCode to
      87             :   // produce the actual code object. If an error occurs during either phase,
      88             :   // FinalizeCode returns a null handle.
      89             :   void AssembleCode();  // Does not need to run on main thread.
      90             :   Handle<Code> FinalizeCode();
      91             : 
      92             :   InstructionSequence* code() const { return code_; }
      93             :   FrameAccessState* frame_access_state() const { return frame_access_state_; }
      94     9032964 :   const Frame* frame() const { return frame_access_state_->frame(); }
      95             :   Isolate* isolate() const;
      96             :   Linkage* linkage() const { return linkage_; }
      97             : 
      98    22998589 :   Label* GetLabel(RpoNumber rpo) { return &labels_[rpo.ToSize()]; }
      99             : 
     100             :   SourcePosition start_source_position() const {
     101             :     return start_source_position_;
     102             :   }
     103             : 
     104             :   void AssembleSourcePosition(Instruction* instr);
     105             :   void AssembleSourcePosition(SourcePosition source_position);
     106             : 
     107             :   // Record a safepoint with the given pointer map.
     108             :   void RecordSafepoint(ReferenceMap* references, Safepoint::Kind kind,
     109             :                        int arguments, Safepoint::DeoptMode deopt_mode);
     110             : 
     111             :   Zone* zone() const { return zone_; }
     112             : 
     113             :  private:
     114             :   TurboAssembler* tasm() { return &tasm_; }
     115             :   GapResolver* resolver() { return &resolver_; }
     116             :   SafepointTableBuilder* safepoints() { return &safepoints_; }
     117             :   CompilationInfo* info() const { return info_; }
     118             :   OsrHelper* osr_helper() { return &(*osr_helper_); }
     119             : 
     120             :   // Create the FrameAccessState object. The Frame is immutable from here on.
     121             :   void CreateFrameAccessState(Frame* frame);
     122             : 
     123             :   // Architecture - specific frame finalization.
     124             :   void FinishFrame(Frame* frame);
     125             : 
     126             :   // Checks if {block} will appear directly after {current_block_} when
     127             :   // assembling code, in which case, a fall-through can be used.
     128             :   bool IsNextInAssemblyOrder(RpoNumber block) const;
     129             : 
     130             :   // Check if a heap object can be materialized by loading from a heap root,
     131             :   // which is cheaper on some platforms than materializing the actual heap
     132             :   // object constant.
     133             :   bool IsMaterializableFromRoot(Handle<HeapObject> object,
     134             :                                 Heap::RootListIndex* index_return);
     135             : 
     136             :   enum CodeGenResult { kSuccess, kTooManyDeoptimizationBailouts };
     137             : 
     138             :   // Assemble instructions for the specified block.
     139             :   CodeGenResult AssembleBlock(const InstructionBlock* block);
     140             : 
     141             :   // Assemble code for the specified instruction.
     142             :   CodeGenResult AssembleInstruction(Instruction* instr,
     143             :                                     const InstructionBlock* block);
     144             :   void AssembleGaps(Instruction* instr);
     145             : 
     146             :   // Returns true if a instruction is a tail call that needs to adjust the stack
     147             :   // pointer before execution. The stack slot index to the empty slot above the
     148             :   // adjusted stack pointer is returned in |slot|.
     149             :   bool GetSlotAboveSPBeforeTailCall(Instruction* instr, int* slot);
     150             : 
     151             :   CodeGenResult AssembleDeoptimizerCall(int deoptimization_id,
     152             :                                         SourcePosition pos);
     153             : 
     154             :   // ===========================================================================
     155             :   // ============= Architecture-specific code generation methods. ==============
     156             :   // ===========================================================================
     157             : 
     158             :   CodeGenResult AssembleArchInstruction(Instruction* instr);
     159             :   void AssembleArchJump(RpoNumber target);
     160             :   void AssembleArchBranch(Instruction* instr, BranchInfo* branch);
     161             : 
     162             :   // Generates special branch for deoptimization condition.
     163             :   void AssembleArchDeoptBranch(Instruction* instr, BranchInfo* branch);
     164             : 
     165             :   void AssembleArchBoolean(Instruction* instr, FlagsCondition condition);
     166             :   void AssembleArchTrap(Instruction* instr, FlagsCondition condition);
     167             :   void AssembleArchLookupSwitch(Instruction* instr);
     168             :   void AssembleArchTableSwitch(Instruction* instr);
     169             : 
     170             :   // When entering a code that is marked for deoptimization, rather continuing
     171             :   // with its execution, we jump to a lazy compiled code. We need to do this
     172             :   // because this code has already been deoptimized and needs to be unlinked
     173             :   // from the JS functions referring it.
     174             :   void BailoutIfDeoptimized();
     175             : 
     176             :   // Generates an architecture-specific, descriptor-specific prologue
     177             :   // to set up a stack frame.
     178             :   void AssembleConstructFrame();
     179             : 
     180             :   // Generates an architecture-specific, descriptor-specific return sequence
     181             :   // to tear down a stack frame.
     182             :   void AssembleReturn(InstructionOperand* pop);
     183             : 
     184             :   void AssembleDeconstructFrame();
     185             : 
     186             :   // Generates code to manipulate the stack in preparation for a tail call.
     187             :   void AssemblePrepareTailCall();
     188             : 
     189             :   // Generates code to pop current frame if it is an arguments adaptor frame.
     190             :   void AssemblePopArgumentsAdaptorFrame(Register args_reg, Register scratch1,
     191             :                                         Register scratch2, Register scratch3);
     192             : 
     193             :   enum PushTypeFlag {
     194             :     kImmediatePush = 0x1,
     195             :     kRegisterPush = 0x2,
     196             :     kStackSlotPush = 0x4,
     197             :     kScalarPush = kRegisterPush | kStackSlotPush
     198             :   };
     199             : 
     200             :   typedef base::Flags<PushTypeFlag> PushTypeFlags;
     201             : 
     202             :   static bool IsValidPush(InstructionOperand source, PushTypeFlags push_type);
     203             : 
     204             :   // Generate a list moves from an instruction that are candidates to be turned
     205             :   // into push instructions on platforms that support them. In general, the list
     206             :   // of push candidates are moves to a set of contiguous destination
     207             :   // InstructionOperand locations on the stack that don't clobber values that
     208             :   // are needed for resolve the gap or use values generated by the gap,
     209             :   // i.e. moves that can be hoisted together before the actual gap and assembled
     210             :   // together.
     211             :   static void GetPushCompatibleMoves(Instruction* instr,
     212             :                                      PushTypeFlags push_type,
     213             :                                      ZoneVector<MoveOperands*>* pushes);
     214             : 
     215             :   // Called before a tail call |instr|'s gap moves are assembled and allows
     216             :   // gap-specific pre-processing, e.g. adjustment of the sp for tail calls that
     217             :   // need it before gap moves or conversion of certain gap moves into pushes.
     218             :   void AssembleTailCallBeforeGap(Instruction* instr,
     219             :                                  int first_unused_stack_slot);
     220             :   // Called after a tail call |instr|'s gap moves are assembled and allows
     221             :   // gap-specific post-processing, e.g. adjustment of the sp for tail calls that
     222             :   // need it after gap moves.
     223             :   void AssembleTailCallAfterGap(Instruction* instr,
     224             :                                 int first_unused_stack_slot);
     225             : 
     226             :   void FinishCode();
     227             : 
     228             :   // ===========================================================================
     229             :   // ============== Architecture-specific gap resolver methods. ================
     230             :   // ===========================================================================
     231             : 
     232             :   // Interface used by the gap resolver to emit moves and swaps.
     233             :   void AssembleMove(InstructionOperand* source,
     234             :                     InstructionOperand* destination) final;
     235             :   void AssembleSwap(InstructionOperand* source,
     236             :                     InstructionOperand* destination) final;
     237             : 
     238             :   // ===========================================================================
     239             :   // =================== Jump table construction methods. ======================
     240             :   // ===========================================================================
     241             : 
     242             :   class JumpTable;
     243             :   // Adds a jump table that is emitted after the actual code.  Returns label
     244             :   // pointing to the beginning of the table.  {targets} is assumed to be static
     245             :   // or zone allocated.
     246             :   Label* AddJumpTable(Label** targets, size_t target_count);
     247             :   // Emits a jump table.
     248             :   void AssembleJumpTable(Label** targets, size_t target_count);
     249             : 
     250             :   // ===========================================================================
     251             :   // ================== Deoptimization table construction. =====================
     252             :   // ===========================================================================
     253             : 
     254             :   void RecordCallPosition(Instruction* instr);
     255             :   Handle<DeoptimizationData> GenerateDeoptimizationData();
     256             :   int DefineDeoptimizationLiteral(DeoptimizationLiteral literal);
     257             :   DeoptimizationEntry const& GetDeoptimizationEntry(Instruction* instr,
     258             :                                                     size_t frame_state_offset);
     259             :   DeoptimizeKind GetDeoptimizationKind(int deoptimization_id) const;
     260             :   DeoptimizeReason GetDeoptimizationReason(int deoptimization_id) const;
     261             :   int BuildTranslation(Instruction* instr, int pc_offset,
     262             :                        size_t frame_state_offset,
     263             :                        OutputFrameStateCombine state_combine);
     264             :   void BuildTranslationForFrameStateDescriptor(
     265             :       FrameStateDescriptor* descriptor, InstructionOperandIterator* iter,
     266             :       Translation* translation, OutputFrameStateCombine state_combine);
     267             :   void TranslateStateValueDescriptor(StateValueDescriptor* desc,
     268             :                                      StateValueList* nested,
     269             :                                      Translation* translation,
     270             :                                      InstructionOperandIterator* iter);
     271             :   void TranslateFrameStateDescriptorOperands(FrameStateDescriptor* desc,
     272             :                                              InstructionOperandIterator* iter,
     273             :                                              OutputFrameStateCombine combine,
     274             :                                              Translation* translation);
     275             :   void AddTranslationForOperand(Translation* translation, Instruction* instr,
     276             :                                 InstructionOperand* op, MachineType type);
     277             :   void MarkLazyDeoptSite();
     278             : 
     279             :   DeoptimizationExit* AddDeoptimizationExit(Instruction* instr,
     280             :                                             size_t frame_state_offset);
     281             : 
     282             :   // ===========================================================================
     283             : 
     284             :   class DeoptimizationState final : public ZoneObject {
     285             :    public:
     286             :     DeoptimizationState(BailoutId bailout_id, int translation_id, int pc_offset,
     287             :                         DeoptimizeKind kind, DeoptimizeReason reason)
     288             :         : bailout_id_(bailout_id),
     289             :           translation_id_(translation_id),
     290             :           pc_offset_(pc_offset),
     291             :           kind_(kind),
     292     3087703 :           reason_(reason) {}
     293             : 
     294             :     BailoutId bailout_id() const { return bailout_id_; }
     295             :     int translation_id() const { return translation_id_; }
     296             :     int pc_offset() const { return pc_offset_; }
     297             :     DeoptimizeKind kind() const { return kind_; }
     298             :     DeoptimizeReason reason() const { return reason_; }
     299             : 
     300             :    private:
     301             :     BailoutId bailout_id_;
     302             :     int translation_id_;
     303             :     int pc_offset_;
     304             :     DeoptimizeKind kind_;
     305             :     DeoptimizeReason reason_;
     306             :   };
     307             : 
     308             :   struct HandlerInfo {
     309             :     Label* handler;
     310             :     int pc_offset;
     311             :   };
     312             : 
     313             :   friend class OutOfLineCode;
     314             :   friend class CodeGeneratorTester;
     315             : 
     316             :   Zone* zone_;
     317             :   FrameAccessState* frame_access_state_;
     318             :   Linkage* const linkage_;
     319             :   InstructionSequence* const code_;
     320             :   UnwindingInfoWriter unwinding_info_writer_;
     321             :   CompilationInfo* const info_;
     322             :   Label* const labels_;
     323             :   Label return_label_;
     324             :   RpoNumber current_block_;
     325             :   SourcePosition start_source_position_;
     326             :   SourcePosition current_source_position_;
     327             :   TurboAssembler tasm_;
     328             :   GapResolver resolver_;
     329             :   SafepointTableBuilder safepoints_;
     330             :   ZoneVector<HandlerInfo> handlers_;
     331             :   ZoneDeque<DeoptimizationExit*> deoptimization_exits_;
     332             :   ZoneDeque<DeoptimizationState*> deoptimization_states_;
     333             :   ZoneDeque<DeoptimizationLiteral> deoptimization_literals_;
     334             :   size_t inlined_function_count_;
     335             :   TranslationBuffer translations_;
     336             :   int last_lazy_deopt_pc_;
     337             : 
     338             :   // kArchCallCFunction could be reached either:
     339             :   //   kArchCallCFunction;
     340             :   // or:
     341             :   //   kArchSaveCallerRegisters;
     342             :   //   kArchCallCFunction;
     343             :   //   kArchRestoreCallerRegisters;
     344             :   // The boolean is used to distinguish the two cases. In the latter case, we
     345             :   // also need to decide if FP registers need to be saved, which is controlled
     346             :   // by fp_mode_.
     347             :   bool caller_registers_saved_;
     348             :   SaveFPRegsMode fp_mode_;
     349             : 
     350             :   JumpTable* jump_tables_;
     351             :   OutOfLineCode* ools_;
     352             :   base::Optional<OsrHelper> osr_helper_;
     353             :   int osr_pc_offset_;
     354             :   int optimized_out_literal_id_;
     355             :   SourcePositionTableBuilder source_position_table_builder_;
     356             :   CodeGenResult result_;
     357             : };
     358             : 
     359             : }  // namespace compiler
     360             : }  // namespace internal
     361             : }  // namespace v8
     362             : 
     363             : #endif  // V8_COMPILER_CODE_GENERATOR_H

Generated by: LCOV version 1.10