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(bool stack_check = true);
     27 
     28   Graph* graph() const { return jsgraph_->graph(); }
     29 
     30  private:
     31   class Environment;
     32   class FrameStateBeforeAndAfter;
     33 
     34   void CreateGraphBody(bool stack_check);
     35   void VisitBytecodes();
     36 
     37   Node* LoadAccumulator(Node* value);
     38 
     39   // Get or create the node that represents the outer function closure.
     40   Node* GetFunctionClosure();
     41 
     42   // Get or create the node that represents the outer function context.
     43   Node* GetFunctionContext();
     44 
     45   // Get or create the node that represents the incoming new target value.
     46   Node* GetNewTarget();
     47 
     48   // Builder for accessing a (potentially immutable) object field.
     49   Node* BuildLoadObjectField(Node* object, int offset);
     50   Node* BuildLoadImmutableObjectField(Node* object, int offset);
     51 
     52   // Builder for accessing type feedback vector.
     53   Node* BuildLoadFeedbackVector();
     54 
     55   // Builder for loading the a native context field.
     56   Node* BuildLoadNativeContextField(int index);
     57 
     58   // Helper function for creating a pair containing type feedback vector and
     59   // a feedback slot.
     60   VectorSlotPair CreateVectorSlotPair(int slot_id);
     61 
     62   void set_environment(Environment* env) { environment_ = env; }
     63   const Environment* environment() const { return environment_; }
     64   Environment* environment() { return environment_; }
     65 
     66   // Node creation helpers
     67   Node* NewNode(const Operator* op, bool incomplete = false) {
     68     return MakeNode(op, 0, static_cast<Node**>(nullptr), incomplete);
     69   }
     70 
     71   Node* NewNode(const Operator* op, Node* n1) {
     72     Node* buffer[] = {n1};
     73     return MakeNode(op, arraysize(buffer), buffer, false);
     74   }
     75 
     76   Node* NewNode(const Operator* op, Node* n1, Node* n2) {
     77     Node* buffer[] = {n1, n2};
     78     return MakeNode(op, arraysize(buffer), buffer, false);
     79   }
     80 
     81   Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) {
     82     Node* buffer[] = {n1, n2, n3};
     83     return MakeNode(op, arraysize(buffer), buffer, false);
     84   }
     85 
     86   Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) {
     87     Node* buffer[] = {n1, n2, n3, n4};
     88     return MakeNode(op, arraysize(buffer), buffer, false);
     89   }
     90 
     91   // Helpers to create new control nodes.
     92   Node* NewIfTrue() { return NewNode(common()->IfTrue()); }
     93   Node* NewIfFalse() { return NewNode(common()->IfFalse()); }
     94   Node* NewMerge() { return NewNode(common()->Merge(1), true); }
     95   Node* NewLoop() { return NewNode(common()->Loop(1), true); }
     96   Node* NewBranch(Node* condition, BranchHint hint = BranchHint::kNone) {
     97     return NewNode(common()->Branch(hint), condition);
     98   }
     99 
    100   // Creates a new Phi node having {count} input values.
    101   Node* NewPhi(int count, Node* input, Node* control);
    102   Node* NewEffectPhi(int count, Node* input, Node* control);
    103 
    104   // Helpers for merging control, effect or value dependencies.
    105   Node* MergeControl(Node* control, Node* other);
    106   Node* MergeEffect(Node* effect, Node* other_effect, Node* control);
    107   Node* MergeValue(Node* value, Node* other_value, Node* control);
    108 
    109   // The main node creation chokepoint. Adds context, frame state, effect,
    110   // and control dependencies depending on the operator.
    111   Node* MakeNode(const Operator* op, int value_input_count, Node** value_inputs,
    112                  bool incomplete);
    113 
    114   // Helper to indicate a node exits the function body.
    115   void UpdateControlDependencyToLeaveFunction(Node* exit);
    116 
    117   Node** EnsureInputBufferSize(int size);
    118 
    119   Node* ProcessCallArguments(const Operator* call_op, Node* callee,
    120                              interpreter::Register receiver, size_t arity);
    121   Node* ProcessCallNewArguments(const Operator* call_new_op,
    122                                 interpreter::Register callee,
    123                                 interpreter::Register first_arg, size_t arity);
    124   Node* ProcessCallRuntimeArguments(const Operator* call_runtime_op,
    125                                     interpreter::Register first_arg,
    126                                     size_t arity);
    127 
    128   void BuildCreateLiteral(const Operator* op,
    129                           const interpreter::BytecodeArrayIterator& iterator);
    130   void BuildCreateRegExpLiteral(
    131       const interpreter::BytecodeArrayIterator& iterator);
    132   void BuildCreateArrayLiteral(
    133       const interpreter::BytecodeArrayIterator& iterator);
    134   void BuildCreateObjectLiteral(
    135       const interpreter::BytecodeArrayIterator& iterator);
    136   void BuildCreateArguments(CreateArgumentsParameters::Type type,
    137                             const interpreter::BytecodeArrayIterator& iterator);
    138   void BuildLoadGlobal(const interpreter::BytecodeArrayIterator& iterator,
    139                        TypeofMode typeof_mode);
    140   void BuildStoreGlobal(const interpreter::BytecodeArrayIterator& iterator);
    141   void BuildNamedLoad(const interpreter::BytecodeArrayIterator& iterator);
    142   void BuildKeyedLoad(const interpreter::BytecodeArrayIterator& iterator);
    143   void BuildNamedStore(const interpreter::BytecodeArrayIterator& iterator);
    144   void BuildKeyedStore(const interpreter::BytecodeArrayIterator& iterator);
    145   void BuildLdaLookupSlot(TypeofMode typeof_mode,
    146                           const interpreter::BytecodeArrayIterator& iterator);
    147   void BuildStaLookupSlot(LanguageMode language_mode,
    148                           const interpreter::BytecodeArrayIterator& iterator);
    149   void BuildCall(const interpreter::BytecodeArrayIterator& iterator);
    150   void BuildBinaryOp(const Operator* op,
    151                      const interpreter::BytecodeArrayIterator& iterator);
    152   void BuildCompareOp(const Operator* op,
    153                       const interpreter::BytecodeArrayIterator& iterator);
    154   void BuildDelete(const interpreter::BytecodeArrayIterator& iterator);
    155   void BuildCastOperator(const Operator* js_op,
    156                          const interpreter::BytecodeArrayIterator& iterator);
    157 
    158   // Control flow plumbing.
    159   void BuildJump(int source_offset, int target_offset);
    160   void BuildJump();
    161   void BuildConditionalJump(Node* condition);
    162   void BuildJumpIfEqual(Node* comperand);
    163   void BuildJumpIfToBooleanEqual(Node* boolean_comperand);
    164 
    165   // Constructing merge and loop headers.
    166   void MergeEnvironmentsOfBackwardBranches(int source_offset,
    167                                            int target_offset);
    168   void MergeEnvironmentsOfForwardBranches(int source_offset);
    169   void BuildLoopHeaderForBackwardBranches(int source_offset);
    170 
    171   // Attaches a frame state to |node| for the entry to the function.
    172   void PrepareEntryFrameState(Node* node);
    173 
    174   // Growth increment for the temporary buffer used to construct input lists to
    175   // new nodes.
    176   static const int kInputBufferSizeIncrement = 64;
    177 
    178   // Field accessors
    179   CommonOperatorBuilder* common() const { return jsgraph_->common(); }
    180   Zone* graph_zone() const { return graph()->zone(); }
    181   CompilationInfo* info() const { return info_; }
    182   JSGraph* jsgraph() const { return jsgraph_; }
    183   JSOperatorBuilder* javascript() const { return jsgraph_->javascript(); }
    184   Zone* local_zone() const { return local_zone_; }
    185   const Handle<BytecodeArray>& bytecode_array() const {
    186     return bytecode_array_;
    187   }
    188   const FrameStateFunctionInfo* frame_state_function_info() const {
    189     return frame_state_function_info_;
    190   }
    191 
    192   LanguageMode language_mode() const {
    193     // TODO(mythria): Don't rely on parse information to get language mode.
    194     return info()->language_mode();
    195   }
    196 
    197   const interpreter::BytecodeArrayIterator* bytecode_iterator() const {
    198     return bytecode_iterator_;
    199   }
    200 
    201   void set_bytecode_iterator(
    202       const interpreter::BytecodeArrayIterator* bytecode_iterator) {
    203     bytecode_iterator_ = bytecode_iterator;
    204   }
    205 
    206   const BytecodeBranchAnalysis* branch_analysis() const {
    207     return branch_analysis_;
    208   }
    209 
    210   void set_branch_analysis(const BytecodeBranchAnalysis* branch_analysis) {
    211     branch_analysis_ = branch_analysis;
    212   }
    213 
    214 #define DECLARE_VISIT_BYTECODE(name, ...) \
    215   void Visit##name(const interpreter::BytecodeArrayIterator& iterator);
    216   BYTECODE_LIST(DECLARE_VISIT_BYTECODE)
    217 #undef DECLARE_VISIT_BYTECODE
    218 
    219   Zone* local_zone_;
    220   CompilationInfo* info_;
    221   JSGraph* jsgraph_;
    222   Handle<BytecodeArray> bytecode_array_;
    223   const FrameStateFunctionInfo* frame_state_function_info_;
    224   const interpreter::BytecodeArrayIterator* bytecode_iterator_;
    225   const BytecodeBranchAnalysis* branch_analysis_;
    226   Environment* environment_;
    227 
    228 
    229   // Merge environments are snapshots of the environment at a particular
    230   // bytecode offset to be merged into a later environment.
    231   ZoneMap<int, Environment*> merge_environments_;
    232 
    233   // Loop header environments are environments created for bytecodes
    234   // where it is known there are back branches, ie a loop header.
    235   ZoneMap<int, Environment*> loop_header_environments_;
    236 
    237   // Temporary storage for building node input lists.
    238   int input_buffer_size_;
    239   Node** input_buffer_;
    240 
    241   // Nodes representing values in the activation record.
    242   SetOncePointer<Node> function_context_;
    243   SetOncePointer<Node> function_closure_;
    244   SetOncePointer<Node> new_target_;
    245 
    246   // Optimization to cache loaded feedback vector.
    247   SetOncePointer<Node> feedback_vector_;
    248 
    249   // Control nodes that exit the function body.
    250   ZoneVector<Node*> exit_controls_;
    251 
    252   DISALLOW_COPY_AND_ASSIGN(BytecodeGraphBuilder);
    253 };
    254 
    255 
    256 class BytecodeGraphBuilder::Environment : public ZoneObject {
    257  public:
    258   Environment(BytecodeGraphBuilder* builder, int register_count,
    259               int parameter_count, Node* control_dependency, Node* context);
    260 
    261   int parameter_count() const { return parameter_count_; }
    262   int register_count() const { return register_count_; }
    263 
    264   Node* LookupAccumulator() const;
    265   Node* LookupRegister(interpreter::Register the_register) const;
    266 
    267   void ExchangeRegisters(interpreter::Register reg0,
    268                          interpreter::Register reg1);
    269 
    270   void BindAccumulator(Node* node, FrameStateBeforeAndAfter* states = nullptr);
    271   void BindRegister(interpreter::Register the_register, Node* node,
    272                     FrameStateBeforeAndAfter* states = nullptr);
    273   void BindRegistersToProjections(interpreter::Register first_reg, Node* node,
    274                                   FrameStateBeforeAndAfter* states = nullptr);
    275   void RecordAfterState(Node* node, FrameStateBeforeAndAfter* states);
    276 
    277   bool IsMarkedAsUnreachable() const;
    278   void MarkAsUnreachable();
    279 
    280   // Effect dependency tracked by this environment.
    281   Node* GetEffectDependency() { return effect_dependency_; }
    282   void UpdateEffectDependency(Node* dependency) {
    283     effect_dependency_ = dependency;
    284   }
    285 
    286   // Preserve a checkpoint of the environment for the IR graph. Any
    287   // further mutation of the environment will not affect checkpoints.
    288   Node* Checkpoint(BailoutId bytecode_offset, OutputFrameStateCombine combine);
    289 
    290   // Returns true if the state values are up to date with the current
    291   // environment.
    292   bool StateValuesAreUpToDate(int output_poke_offset, int output_poke_count);
    293 
    294   // Control dependency tracked by this environment.
    295   Node* GetControlDependency() const { return control_dependency_; }
    296   void UpdateControlDependency(Node* dependency) {
    297     control_dependency_ = dependency;
    298   }
    299 
    300   Node* Context() const { return context_; }
    301   void SetContext(Node* new_context) { context_ = new_context; }
    302 
    303   Environment* CopyForConditional() const;
    304   Environment* CopyForLoop();
    305   void Merge(Environment* other);
    306 
    307  private:
    308   explicit Environment(const Environment* copy);
    309   void PrepareForLoop();
    310   bool StateValuesAreUpToDate(Node** state_values, int offset, int count,
    311                               int output_poke_start, int output_poke_end);
    312   bool StateValuesRequireUpdate(Node** state_values, int offset, int count);
    313   void UpdateStateValues(Node** state_values, int offset, int count);
    314 
    315   int RegisterToValuesIndex(interpreter::Register the_register) const;
    316 
    317   Zone* zone() const { return builder_->local_zone(); }
    318   Graph* graph() const { return builder_->graph(); }
    319   CommonOperatorBuilder* common() const { return builder_->common(); }
    320   BytecodeGraphBuilder* builder() const { return builder_; }
    321   const NodeVector* values() const { return &values_; }
    322   NodeVector* values() { return &values_; }
    323   int register_base() const { return register_base_; }
    324   int accumulator_base() const { return accumulator_base_; }
    325 
    326   BytecodeGraphBuilder* builder_;
    327   int register_count_;
    328   int parameter_count_;
    329   Node* context_;
    330   Node* control_dependency_;
    331   Node* effect_dependency_;
    332   NodeVector values_;
    333   Node* parameters_state_values_;
    334   Node* registers_state_values_;
    335   Node* accumulator_state_values_;
    336   int register_base_;
    337   int accumulator_base_;
    338 };
    339 
    340 }  // namespace compiler
    341 }  // namespace internal
    342 }  // namespace v8
    343 
    344 #endif  // V8_COMPILER_BYTECODE_GRAPH_BUILDER_H_
    345