Home | History | Annotate | Download | only in compiler
      1 // Copyright 2015 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_BYTECODE_GRAPH_BUILDER_H_
      6 #define V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_
      7 
      8 #include "src/compiler.h"
      9 #include "src/compiler/bytecode-branch-analysis.h"
     10 #include "src/compiler/js-graph.h"
     11 #include "src/interpreter/bytecode-array-iterator.h"
     12 #include "src/interpreter/bytecodes.h"
     13 
     14 namespace v8 {
     15 namespace internal {
     16 namespace compiler {
     17 
     18 // The BytecodeGraphBuilder produces a high-level IR graph based on
     19 // interpreter bytecodes.
     20 class BytecodeGraphBuilder {
     21  public:
     22   BytecodeGraphBuilder(Zone* local_zone, CompilationInfo* info,
     23                        JSGraph* jsgraph);
     24 
     25   // Creates a graph by visiting bytecodes.
     26   bool CreateGraph();
     27 
     28  private:
     29   class Environment;
     30   class FrameStateBeforeAndAfter;
     31 
     32   void VisitBytecodes();
     33 
     34   // Get or create the node that represents the outer function closure.
     35   Node* GetFunctionClosure();
     36 
     37   // Get or create the node that represents the outer function context.
     38   Node* GetFunctionContext();
     39 
     40   // Get or create the node that represents the incoming new target value.
     41   Node* GetNewTarget();
     42 
     43   // Builder for loading the a native context field.
     44   Node* BuildLoadNativeContextField(int index);
     45 
     46   // Helper function for creating a pair containing type feedback vector and
     47   // a feedback slot.
     48   VectorSlotPair CreateVectorSlotPair(int slot_id);
     49 
     50   void set_environment(Environment* env) { environment_ = env; }
     51   const Environment* environment() const { return environment_; }
     52   Environment* environment() { return environment_; }
     53 
     54   // Node creation helpers
     55   Node* NewNode(const Operator* op, bool incomplete = false) {
     56     return MakeNode(op, 0, static_cast<Node**>(nullptr), incomplete);
     57   }
     58 
     59   Node* NewNode(const Operator* op, Node* n1) {
     60     Node* buffer[] = {n1};
     61     return MakeNode(op, arraysize(buffer), buffer, false);
     62   }
     63 
     64   Node* NewNode(const Operator* op, Node* n1, Node* n2) {
     65     Node* buffer[] = {n1, n2};
     66     return MakeNode(op, arraysize(buffer), buffer, false);
     67   }
     68 
     69   Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) {
     70     Node* buffer[] = {n1, n2, n3};
     71     return MakeNode(op, arraysize(buffer), buffer, false);
     72   }
     73 
     74   Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) {
     75     Node* buffer[] = {n1, n2, n3, n4};
     76     return MakeNode(op, arraysize(buffer), buffer, false);
     77   }
     78 
     79   // Helpers to create new control nodes.
     80   Node* NewIfTrue() { return NewNode(common()->IfTrue()); }
     81   Node* NewIfFalse() { return NewNode(common()->IfFalse()); }
     82   Node* NewMerge() { return NewNode(common()->Merge(1), true); }
     83   Node* NewLoop() { return NewNode(common()->Loop(1), true); }
     84   Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) {
     85     return NewNode(common()->Branch(hint), condition);
     86   }
     87 
     88   // Creates a new Phi node having {count} input values.
     89   Node* NewPhi(int count, Node* input, Node* control);
     90   Node* NewEffectPhi(int count, Node* input, Node* control);
     91 
     92   // Helpers for merging control, effect or value dependencies.
     93   Node* MergeControl(Node* control, Node* other);
     94   Node* MergeEffect(Node* effect, Node* other_effect, Node* control);
     95   Node* MergeValue(Node* value, Node* other_value, Node* control);
     96 
     97   // The main node creation chokepoint. Adds context, frame state, effect,
     98   // and control dependencies depending on the operator.
     99   Node* MakeNode(const Operator* op, int value_input_count, Node** value_inputs,
    100                  bool incomplete);
    101 
    102   Node** EnsureInputBufferSize(int size);
    103 
    104   Node* ProcessCallArguments(const Operator* call_op, Node* callee,
    105                              interpreter::Register receiver, size_t arity);
    106   Node* ProcessCallNewArguments(const Operator* call_new_op, Node* callee,
    107                                 Node* new_target,
    108                                 interpreter::Register first_arg, size_t arity);
    109   Node* ProcessCallRuntimeArguments(const Operator* call_runtime_op,
    110                                     interpreter::Register first_arg,
    111                                     size_t arity);
    112 
    113   void BuildCreateLiteral(const Operator* op);
    114   void BuildCreateArguments(CreateArgumentsType type);
    115   Node* BuildLoadContextSlot();
    116   Node* BuildLoadGlobal(TypeofMode typeof_mode);
    117   void BuildStoreGlobal(LanguageMode language_mode);
    118   Node* BuildNamedLoad();
    119   void BuildNamedStore(LanguageMode language_mode);
    120   Node* BuildKeyedLoad();
    121   void BuildKeyedStore(LanguageMode language_mode);
    122   void BuildLdaLookupSlot(TypeofMode typeof_mode);
    123   void BuildStaLookupSlot(LanguageMode language_mode);
    124   void BuildCall(TailCallMode tail_call_mode);
    125   void BuildThrow();
    126   void BuildBinaryOp(const Operator* op);
    127   void BuildCompareOp(const Operator* op);
    128   void BuildDelete(LanguageMode language_mode);
    129   void BuildCastOperator(const Operator* op);
    130   void BuildForInPrepare();
    131   void BuildForInNext();
    132   void BuildInvokeIntrinsic();
    133 
    134   // Control flow plumbing.
    135   void BuildJump();
    136   void BuildConditionalJump(Node* condition);
    137   void BuildJumpIfEqual(Node* comperand);
    138   void BuildJumpIfToBooleanEqual(Node* boolean_comperand);
    139   void BuildJumpIfNotHole();
    140 
    141   // Simulates control flow by forward-propagating environments.
    142   void MergeIntoSuccessorEnvironment(int target_offset);
    143   void BuildLoopHeaderEnvironment(int current_offset);
    144   void SwitchToMergeEnvironment(int current_offset);
    145 
    146   // Simulates control flow that exits the function body.
    147   void MergeControlToLeaveFunction(Node* exit);
    148 
    149   // Simulates entry and exit of exception handlers.
    150   void EnterAndExitExceptionHandlers(int current_offset);
    151 
    152   // Growth increment for the temporary buffer used to construct input lists to
    153   // new nodes.
    154   static const int kInputBufferSizeIncrement = 64;
    155 
    156   // The catch prediction from the handler table is reused.
    157   typedef HandlerTable::CatchPrediction CatchPrediction;
    158 
    159   // An abstract representation for an exception handler that is being
    160   // entered and exited while the graph builder is iterating over the
    161   // underlying bytecode. The exception handlers within the bytecode are
    162   // well scoped, hence will form a stack during iteration.
    163   struct ExceptionHandler {
    164     int start_offset_;      // Start offset of the handled area in the bytecode.
    165     int end_offset_;        // End offset of the handled area in the bytecode.
    166     int handler_offset_;    // Handler entry offset within the bytecode.
    167     int context_register_;  // Index of register holding handler context.
    168     CatchPrediction pred_;  // Prediction of whether handler is catching.
    169   };
    170 
    171   // Field accessors
    172   Graph* graph() const { return jsgraph_->graph(); }
    173   CommonOperatorBuilder* common() const { return jsgraph_->common(); }
    174   Zone* graph_zone() const { return graph()->zone(); }
    175   JSGraph* jsgraph() const { return jsgraph_; }
    176   JSOperatorBuilder* javascript() const { return jsgraph_->javascript(); }
    177   Zone* local_zone() const { return local_zone_; }
    178   const Handle<BytecodeArray>& bytecode_array() const {
    179     return bytecode_array_;
    180   }
    181   const Handle<HandlerTable>& exception_handler_table() const {
    182     return exception_handler_table_;
    183   }
    184   const Handle<TypeFeedbackVector>& feedback_vector() const {
    185     return feedback_vector_;
    186   }
    187   const FrameStateFunctionInfo* frame_state_function_info() const {
    188     return frame_state_function_info_;
    189   }
    190 
    191   const interpreter::BytecodeArrayIterator& bytecode_iterator() const {
    192     return *bytecode_iterator_;
    193   }
    194 
    195   void set_bytecode_iterator(
    196       const interpreter::BytecodeArrayIterator* bytecode_iterator) {
    197     bytecode_iterator_ = bytecode_iterator;
    198   }
    199 
    200   const BytecodeBranchAnalysis* branch_analysis() const {
    201     return branch_analysis_;
    202   }
    203 
    204   void set_branch_analysis(const BytecodeBranchAnalysis* branch_analysis) {
    205     branch_analysis_ = branch_analysis;
    206   }
    207 
    208 #define DECLARE_VISIT_BYTECODE(name, ...) void Visit##name();
    209   BYTECODE_LIST(DECLARE_VISIT_BYTECODE)
    210 #undef DECLARE_VISIT_BYTECODE
    211 
    212   Zone* local_zone_;
    213   JSGraph* jsgraph_;
    214   Handle<BytecodeArray> bytecode_array_;
    215   Handle<HandlerTable> exception_handler_table_;
    216   Handle<TypeFeedbackVector> feedback_vector_;
    217   const FrameStateFunctionInfo* frame_state_function_info_;
    218   const interpreter::BytecodeArrayIterator* bytecode_iterator_;
    219   const BytecodeBranchAnalysis* branch_analysis_;
    220   Environment* environment_;
    221 
    222   // Merge environments are snapshots of the environment at points where the
    223   // control flow merges. This models a forward data flow propagation of all
    224   // values from all predecessors of the merge in question.
    225   ZoneMap<int, Environment*> merge_environments_;
    226 
    227   // Exception handlers currently entered by the iteration.
    228   ZoneStack<ExceptionHandler> exception_handlers_;
    229   int current_exception_handler_;
    230 
    231   // Temporary storage for building node input lists.
    232   int input_buffer_size_;
    233   Node** input_buffer_;
    234 
    235   // Nodes representing values in the activation record.
    236   SetOncePointer<Node> function_context_;
    237   SetOncePointer<Node> function_closure_;
    238   SetOncePointer<Node> new_target_;
    239 
    240   // Control nodes that exit the function body.
    241   ZoneVector<Node*> exit_controls_;
    242 
    243   DISALLOW_COPY_AND_ASSIGN(BytecodeGraphBuilder);
    244 };
    245 
    246 }  // namespace compiler
    247 }  // namespace internal
    248 }  // namespace v8
    249 
    250 #endif  // V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_
    251