LCOV - code coverage report
Current view: top level - src/compiler - graph-assembler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 82 82 100.0 %
Date: 2017-10-20 Functions: 15 15 100.0 %

          Line data    Source code
       1             : // Copyright 2016 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_GRAPH_ASSEMBLER_H_
       6             : #define V8_COMPILER_GRAPH_ASSEMBLER_H_
       7             : 
       8             : #include "src/compiler/js-graph.h"
       9             : #include "src/compiler/node.h"
      10             : #include "src/compiler/simplified-operator.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15             : class JSGraph;
      16             : class Graph;
      17             : 
      18             : namespace compiler {
      19             : 
      20             : #define PURE_ASSEMBLER_MACH_UNOP_LIST(V) \
      21             :   V(ChangeInt32ToInt64)                  \
      22             :   V(ChangeInt32ToFloat64)                \
      23             :   V(ChangeUint32ToFloat64)               \
      24             :   V(ChangeUint32ToUint64)                \
      25             :   V(ChangeFloat64ToInt32)                \
      26             :   V(ChangeFloat64ToUint32)               \
      27             :   V(TruncateInt64ToInt32)                \
      28             :   V(RoundFloat64ToInt32)                 \
      29             :   V(TruncateFloat64ToWord32)             \
      30             :   V(Float64ExtractHighWord32)            \
      31             :   V(Float64Abs)                          \
      32             :   V(BitcastWordToTagged)
      33             : 
      34             : #define PURE_ASSEMBLER_MACH_BINOP_LIST(V) \
      35             :   V(WordShl)                              \
      36             :   V(WordSar)                              \
      37             :   V(WordAnd)                              \
      38             :   V(Word32Or)                             \
      39             :   V(Word32And)                            \
      40             :   V(Word32Xor)                            \
      41             :   V(Word32Shr)                            \
      42             :   V(Word32Shl)                            \
      43             :   V(IntAdd)                               \
      44             :   V(IntSub)                               \
      45             :   V(IntMul)                               \
      46             :   V(IntLessThan)                          \
      47             :   V(UintLessThan)                         \
      48             :   V(Int32Add)                             \
      49             :   V(Int32Sub)                             \
      50             :   V(Int32Mul)                             \
      51             :   V(Int32LessThanOrEqual)                 \
      52             :   V(Uint32LessThanOrEqual)                \
      53             :   V(Uint32LessThan)                       \
      54             :   V(Int32LessThan)                        \
      55             :   V(Float64Add)                           \
      56             :   V(Float64Sub)                           \
      57             :   V(Float64Div)                           \
      58             :   V(Float64Mod)                           \
      59             :   V(Float64Equal)                         \
      60             :   V(Float64LessThan)                      \
      61             :   V(Float64LessThanOrEqual)               \
      62             :   V(Word32Equal)                          \
      63             :   V(WordEqual)
      64             : 
      65             : #define CHECKED_ASSEMBLER_MACH_BINOP_LIST(V) \
      66             :   V(Int32AddWithOverflow)                    \
      67             :   V(Int32SubWithOverflow)                    \
      68             :   V(Int32MulWithOverflow)                    \
      69             :   V(Int32Mod)                                \
      70             :   V(Int32Div)                                \
      71             :   V(Uint32Mod)                               \
      72             :   V(Uint32Div)
      73             : 
      74             : #define JSGRAPH_SINGLETON_CONSTANT_LIST(V) \
      75             :   V(TrueConstant)                          \
      76             :   V(FalseConstant)                         \
      77             :   V(HeapNumberMapConstant)                 \
      78             :   V(NoContextConstant)                     \
      79             :   V(EmptyStringConstant)                   \
      80             :   V(UndefinedConstant)                     \
      81             :   V(TheHoleConstant)                       \
      82             :   V(FixedArrayMapConstant)                 \
      83             :   V(FixedDoubleArrayMapConstant)           \
      84             :   V(ToNumberBuiltinConstant)               \
      85             :   V(AllocateInNewSpaceStubConstant)        \
      86             :   V(AllocateInOldSpaceStubConstant)
      87             : 
      88             : class GraphAssembler;
      89             : 
      90             : enum class GraphAssemblerLabelType { kDeferred, kNonDeferred, kLoop };
      91             : 
      92             : // Label with statically known count of incoming branches and phis.
      93             : template <size_t VarCount>
      94             : class GraphAssemblerLabel {
      95             :  public:
      96             :   Node* PhiAt(size_t index);
      97             : 
      98             :   template <typename... Reps>
      99             :   explicit GraphAssemblerLabel(GraphAssemblerLabelType type, Reps... reps)
     100             :       : type_(type) {
     101             :     STATIC_ASSERT(VarCount == sizeof...(reps));
     102             :     MachineRepresentation reps_array[] = {MachineRepresentation::kNone,
     103      391467 :                                           reps...};
     104      782934 :     for (size_t i = 0; i < VarCount; i++) {
     105      391467 :       representations_[i] = reps_array[i + 1];
     106             :     }
     107             :   }
     108             : 
     109             :   ~GraphAssemblerLabel() { DCHECK(IsBound() || merged_count_ == 0); }
     110             : 
     111             :  private:
     112             :   friend class GraphAssembler;
     113             : 
     114             :   void SetBound() {
     115             :     DCHECK(!IsBound());
     116      930304 :     is_bound_ = true;
     117             :   }
     118             :   bool IsBound() const { return is_bound_; }
     119             :   bool IsDeferred() const {
     120         408 :     return type_ == GraphAssemblerLabelType::kDeferred;
     121             :   }
     122             :   bool IsLoop() const { return type_ == GraphAssemblerLabelType::kLoop; }
     123             : 
     124             :   bool is_bound_ = false;
     125             :   GraphAssemblerLabelType const type_;
     126             :   size_t merged_count_ = 0;
     127             :   Node* effect_;
     128             :   Node* control_;
     129             :   Node* bindings_[VarCount + 1];
     130             :   MachineRepresentation representations_[VarCount + 1];
     131             : };
     132             : 
     133             : class GraphAssembler {
     134             :  public:
     135             :   GraphAssembler(JSGraph* jsgraph, Node* effect, Node* control, Zone* zone);
     136             : 
     137             :   void Reset(Node* effect, Node* control);
     138             : 
     139             :   // Create label.
     140             :   template <typename... Reps>
     141             :   static GraphAssemblerLabel<sizeof...(Reps)> MakeLabelFor(
     142             :       GraphAssemblerLabelType type, Reps... reps) {
     143             :     return GraphAssemblerLabel<sizeof...(Reps)>(type, reps...);
     144             :   }
     145             : 
     146             :   // Convenience wrapper for creating non-deferred labels.
     147             :   template <typename... Reps>
     148             :   static GraphAssemblerLabel<sizeof...(Reps)> MakeLabel(Reps... reps) {
     149             :     return MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, reps...);
     150             :   }
     151             : 
     152             :   // Convenience wrapper for creating loop labels.
     153             :   template <typename... Reps>
     154             :   static GraphAssemblerLabel<sizeof...(Reps)> MakeLoopLabel(Reps... reps) {
     155             :     return MakeLabelFor(GraphAssemblerLabelType::kLoop, reps...);
     156             :   }
     157             : 
     158             :   // Convenience wrapper for creating deferred labels.
     159             :   template <typename... Reps>
     160             :   static GraphAssemblerLabel<sizeof...(Reps)> MakeDeferredLabel(Reps... reps) {
     161             :     return MakeLabelFor(GraphAssemblerLabelType::kDeferred, reps...);
     162             :   }
     163             : 
     164             :   // Value creation.
     165             :   Node* IntPtrConstant(intptr_t value);
     166             :   Node* Uint32Constant(int32_t value);
     167             :   Node* Int32Constant(int32_t value);
     168             :   Node* UniqueInt32Constant(int32_t value);
     169             :   Node* SmiConstant(int32_t value);
     170             :   Node* Float64Constant(double value);
     171             :   Node* Projection(int index, Node* value);
     172             :   Node* HeapConstant(Handle<HeapObject> object);
     173             :   Node* CEntryStubConstant(int result_size);
     174             :   Node* ExternalConstant(ExternalReference ref);
     175             : 
     176             :   Node* LoadFramePointer();
     177             : 
     178             : #define SINGLETON_CONST_DECL(Name) Node* Name();
     179             :   JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_DECL)
     180             : #undef SINGLETON_CONST_DECL
     181             : 
     182             : #define PURE_UNOP_DECL(Name) Node* Name(Node* input);
     183             :   PURE_ASSEMBLER_MACH_UNOP_LIST(PURE_UNOP_DECL)
     184             : #undef PURE_UNOP_DECL
     185             : 
     186             : #define BINOP_DECL(Name) Node* Name(Node* left, Node* right);
     187             :   PURE_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL)
     188             :   CHECKED_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL)
     189             : #undef BINOP_DECL
     190             : 
     191             :   // Debugging
     192             :   Node* DebugBreak();
     193             : 
     194             :   Node* Float64RoundDown(Node* value);
     195             : 
     196             :   Node* ToNumber(Node* value);
     197             :   Node* Allocate(PretenureFlag pretenure, Node* size);
     198             :   Node* LoadField(FieldAccess const&, Node* object);
     199             :   Node* LoadElement(ElementAccess const&, Node* object, Node* index);
     200             :   Node* StoreField(FieldAccess const&, Node* object, Node* value);
     201             :   Node* StoreElement(ElementAccess const&, Node* object, Node* index,
     202             :                      Node* value);
     203             : 
     204             :   Node* Store(StoreRepresentation rep, Node* object, Node* offset, Node* value);
     205             :   Node* Load(MachineType rep, Node* object, Node* offset);
     206             : 
     207             :   Node* Retain(Node* buffer);
     208             :   Node* UnsafePointerAdd(Node* base, Node* external);
     209             : 
     210             :   Node* DeoptimizeIf(DeoptimizeReason reason, Node* condition,
     211             :                      Node* frame_state);
     212             :   Node* DeoptimizeIfNot(DeoptimizeKind kind, DeoptimizeReason reason,
     213             :                         Node* condition, Node* frame_state);
     214             :   Node* DeoptimizeIfNot(DeoptimizeReason reason, Node* condition,
     215             :                         Node* frame_state);
     216             :   template <typename... Args>
     217             :   Node* Call(const CallDescriptor* desc, Args... args);
     218             :   template <typename... Args>
     219             :   Node* Call(const Operator* op, Args... args);
     220             : 
     221             :   // Basic control operations.
     222             :   template <size_t VarCount>
     223             :   void Bind(GraphAssemblerLabel<VarCount>* label);
     224             : 
     225             :   template <typename... Vars>
     226             :   void Goto(GraphAssemblerLabel<sizeof...(Vars)>* label, Vars...);
     227             : 
     228             :   void Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
     229             :               GraphAssemblerLabel<0u>* if_false);
     230             : 
     231             :   // Control helpers.
     232             :   // {GotoIf(c, l)} is equivalent to {Branch(c, l, templ);Bind(templ)}.
     233             :   template <typename... Vars>
     234             :   void GotoIf(Node* condition, GraphAssemblerLabel<sizeof...(Vars)>* label,
     235             :               Vars...);
     236             : 
     237             :   // {GotoIfNot(c, l)} is equivalent to {Branch(c, templ, l);Bind(templ)}.
     238             :   template <typename... Vars>
     239             :   void GotoIfNot(Node* condition, GraphAssemblerLabel<sizeof...(Vars)>* label,
     240             :                  Vars...);
     241             : 
     242             :   // Extractors (should be only used when destructing/resetting the assembler).
     243             :   Node* ExtractCurrentControl();
     244             :   Node* ExtractCurrentEffect();
     245             : 
     246             :  private:
     247             :   template <typename... Vars>
     248             :   void MergeState(GraphAssemblerLabel<sizeof...(Vars)>* label, Vars... vars);
     249             : 
     250             :   Operator const* ToNumberOperator();
     251             : 
     252             :   JSGraph* jsgraph() const { return jsgraph_; }
     253     9294740 :   Graph* graph() const { return jsgraph_->graph(); }
     254             :   Zone* temp_zone() const { return temp_zone_; }
     255     4807301 :   CommonOperatorBuilder* common() const { return jsgraph()->common(); }
     256     3764700 :   MachineOperatorBuilder* machine() const { return jsgraph()->machine(); }
     257      595231 :   SimplifiedOperatorBuilder* simplified() const {
     258      595231 :     return jsgraph()->simplified();
     259             :   }
     260             : 
     261             :   SetOncePointer<Operator const> to_number_operator_;
     262             :   Zone* temp_zone_;
     263             :   JSGraph* jsgraph_;
     264             :   Node* current_effect_;
     265             :   Node* current_control_;
     266             : };
     267             : 
     268             : template <size_t VarCount>
     269             : Node* GraphAssemblerLabel<VarCount>::PhiAt(size_t index) {
     270             :   DCHECK(IsBound());
     271             :   DCHECK_LT(index, VarCount);
     272      509187 :   return bindings_[index];
     273             : }
     274             : 
     275             : template <typename... Vars>
     276     3383042 : void GraphAssembler::MergeState(GraphAssemblerLabel<sizeof...(Vars)>* label,
     277     2028855 :                                 Vars... vars) {
     278     1691521 :   int merged_count = static_cast<int>(label->merged_count_);
     279     1017035 :   Node* var_array[] = {nullptr, vars...};
     280     1691521 :   if (label->IsLoop()) {
     281         708 :     if (merged_count == 0) {
     282             :       DCHECK(!label->IsBound());
     283         354 :       label->control_ = graph()->NewNode(common()->Loop(2), current_control_,
     284         708 :                                          current_control_);
     285        1062 :       label->effect_ = graph()->NewNode(common()->EffectPhi(2), current_effect_,
     286             :                                         current_effect_, label->control_);
     287        1062 :       for (size_t i = 0; i < sizeof...(vars); i++) {
     288        1062 :         label->bindings_[i] = graph()->NewNode(
     289             :             common()->Phi(label->representations_[i], 2), var_array[i + 1],
     290             :             var_array[i + 1], label->control_);
     291             :       }
     292             :     } else {
     293             :       DCHECK(label->IsBound());
     294             :       DCHECK_EQ(1, merged_count);
     295         354 :       label->control_->ReplaceInput(1, current_control_);
     296         354 :       label->effect_->ReplaceInput(1, current_effect_);
     297        1062 :       for (size_t i = 0; i < sizeof...(vars); i++) {
     298         354 :         label->bindings_[i]->ReplaceInput(1, var_array[i + 1]);
     299             :       }
     300             :     }
     301             :   } else {
     302             :     DCHECK(!label->IsBound());
     303     1690813 :     if (merged_count == 0) {
     304             :       // Just set the control, effect and variables directly.
     305             :       DCHECK(!label->IsBound());
     306      989526 :       label->control_ = current_control_;
     307      989526 :       label->effect_ = current_effect_;
     308     1173342 :       for (size_t i = 0; i < sizeof...(vars); i++) {
     309      391114 :         label->bindings_[i] = var_array[i + 1];
     310             :       }
     311      701287 :     } else if (merged_count == 1) {
     312             :       // Create merge, effect phi and a phi for each variable.
     313     1398006 :       label->control_ = graph()->NewNode(common()->Merge(2), label->control_,
     314             :                                          current_control_);
     315     1398013 :       label->effect_ = graph()->NewNode(common()->EffectPhi(2), label->effect_,
     316             :                                         current_effect_, label->control_);
     317     1173352 :       for (size_t i = 0; i < sizeof...(vars); i++) {
     318     1173354 :         label->bindings_[i] = graph()->NewNode(
     319             :             common()->Phi(label->representations_[i], 2), label->bindings_[i],
     320             :             var_array[i + 1], label->control_);
     321             :       }
     322             :     } else {
     323             :       // Append to the merge, effect phi and phis.
     324             :       DCHECK_EQ(IrOpcode::kMerge, label->control_->opcode());
     325      470572 :       label->control_->AppendInput(graph()->zone(), current_control_);
     326      235286 :       NodeProperties::ChangeOp(label->control_,
     327      470572 :                                common()->Merge(merged_count + 1));
     328             : 
     329             :       DCHECK_EQ(IrOpcode::kEffectPhi, label->effect_->opcode());
     330      235286 :       label->effect_->ReplaceInput(merged_count, current_effect_);
     331      470572 :       label->effect_->AppendInput(graph()->zone(), label->control_);
     332      235286 :       NodeProperties::ChangeOp(label->effect_,
     333      235286 :                                common()->EffectPhi(merged_count + 1));
     334             : 
     335      703484 :       for (size_t i = 0; i < sizeof...(vars); i++) {
     336             :         DCHECK_EQ(IrOpcode::kPhi, label->bindings_[i]->opcode());
     337      234099 :         label->bindings_[i]->ReplaceInput(merged_count, var_array[i + 1]);
     338      468198 :         label->bindings_[i]->AppendInput(graph()->zone(), label->control_);
     339      234099 :         NodeProperties::ChangeOp(
     340             :             label->bindings_[i],
     341      468198 :             common()->Phi(label->representations_[i], merged_count + 1));
     342             :       }
     343             :     }
     344             :   }
     345     1691525 :   label->merged_count_++;
     346     1691525 : }
     347             : 
     348             : template <size_t VarCount>
     349             : void GraphAssembler::Bind(GraphAssemblerLabel<VarCount>* label) {
     350             :   DCHECK_NULL(current_control_);
     351             :   DCHECK_NULL(current_effect_);
     352             :   DCHECK_LT(0, label->merged_count_);
     353             : 
     354      989883 :   current_control_ = label->control_;
     355      989883 :   current_effect_ = label->effect_;
     356             : 
     357             :   label->SetBound();
     358             : }
     359             : 
     360             : template <typename... Vars>
     361             : void GraphAssembler::Goto(GraphAssemblerLabel<sizeof...(Vars)>* label,
     362             :                           Vars... vars) {
     363             :   DCHECK_NOT_NULL(current_control_);
     364             :   DCHECK_NOT_NULL(current_effect_);
     365      989683 :   MergeState(label, vars...);
     366      989679 :   current_control_ = nullptr;
     367      989679 :   current_effect_ = nullptr;
     368             : }
     369             : 
     370             : template <typename... Vars>
     371      470840 : void GraphAssembler::GotoIf(Node* condition,
     372      470840 :                             GraphAssemblerLabel<sizeof...(Vars)>* label,
     373     1412521 :                             Vars... vars) {
     374             :   BranchHint hint =
     375      470840 :       label->IsDeferred() ? BranchHint::kFalse : BranchHint::kNone;
     376             :   Node* branch =
     377      941680 :       graph()->NewNode(common()->Branch(hint), condition, current_control_);
     378             : 
     379      941682 :   current_control_ = graph()->NewNode(common()->IfTrue(), branch);
     380      470841 :   MergeState(label, vars...);
     381             : 
     382      941681 :   current_control_ = graph()->NewNode(common()->IfFalse(), branch);
     383      470841 : }
     384             : 
     385             : template <typename... Vars>
     386      230597 : void GraphAssembler::GotoIfNot(Node* condition,
     387      230597 :                                GraphAssemblerLabel<sizeof...(Vars)>* label,
     388      691798 :                                Vars... vars) {
     389      230597 :   BranchHint hint = label->IsDeferred() ? BranchHint::kTrue : BranchHint::kNone;
     390             :   Node* branch =
     391      461194 :       graph()->NewNode(common()->Branch(hint), condition, current_control_);
     392             : 
     393      461202 :   current_control_ = graph()->NewNode(common()->IfFalse(), branch);
     394      230601 :   MergeState(label, vars...);
     395             : 
     396      461198 :   current_control_ = graph()->NewNode(common()->IfTrue(), branch);
     397      230601 : }
     398             : 
     399             : template <typename... Args>
     400       50743 : Node* GraphAssembler::Call(const CallDescriptor* desc, Args... args) {
     401       50743 :   const Operator* op = common()->Call(desc);
     402       50743 :   return Call(op, args...);
     403             : }
     404             : 
     405             : template <typename... Args>
     406      675660 : Node* GraphAssembler::Call(const Operator* op, Args... args) {
     407             :   DCHECK_EQ(IrOpcode::kCall, op->opcode());
     408      168915 :   Node* args_array[] = {args..., current_effect_, current_control_};
     409             :   int size = static_cast<int>(sizeof...(args)) + op->EffectInputCount() +
     410      337830 :              op->ControlInputCount();
     411      168915 :   Node* call = graph()->NewNode(op, size, args_array);
     412             :   DCHECK_EQ(0, op->ControlOutputCount());
     413      168915 :   current_effect_ = call;
     414      168915 :   return call;
     415             : }
     416             : 
     417             : }  // namespace compiler
     418             : }  // namespace internal
     419             : }  // namespace v8
     420             : 
     421             : #endif  // V8_COMPILER_GRAPH_ASSEMBLER_H_

Generated by: LCOV version 1.10