LCOV - code coverage report
Current view: top level - src/compiler - graph-assembler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 84 84 100.0 %
Date: 2019-01-20 Functions: 16 16 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             : #include "src/vector-slot-pair.h"
      12             : 
      13             : namespace v8 {
      14             : namespace internal {
      15             : 
      16             : class JSGraph;
      17             : class Graph;
      18             : 
      19             : namespace compiler {
      20             : 
      21             : #define PURE_ASSEMBLER_MACH_UNOP_LIST(V) \
      22             :   V(ChangeInt32ToInt64)                  \
      23             :   V(ChangeInt32ToFloat64)                \
      24             :   V(ChangeInt64ToFloat64)                \
      25             :   V(ChangeUint32ToFloat64)               \
      26             :   V(ChangeUint32ToUint64)                \
      27             :   V(ChangeFloat64ToInt32)                \
      28             :   V(ChangeFloat64ToInt64)                \
      29             :   V(ChangeFloat64ToUint32)               \
      30             :   V(TruncateInt64ToInt32)                \
      31             :   V(RoundFloat64ToInt32)                 \
      32             :   V(TruncateFloat64ToInt64)              \
      33             :   V(TruncateFloat64ToWord32)             \
      34             :   V(Float64ExtractLowWord32)             \
      35             :   V(Float64ExtractHighWord32)            \
      36             :   V(BitcastInt32ToFloat32)               \
      37             :   V(BitcastInt64ToFloat64)               \
      38             :   V(BitcastFloat32ToInt32)               \
      39             :   V(BitcastFloat64ToInt64)               \
      40             :   V(Float64Abs)                          \
      41             :   V(Word32ReverseBytes)                  \
      42             :   V(Word64ReverseBytes)
      43             : 
      44             : #define PURE_ASSEMBLER_MACH_BINOP_LIST(V) \
      45             :   V(WordShl)                              \
      46             :   V(WordSar)                              \
      47             :   V(WordAnd)                              \
      48             :   V(Word32Or)                             \
      49             :   V(Word32And)                            \
      50             :   V(Word32Xor)                            \
      51             :   V(Word32Shr)                            \
      52             :   V(Word32Shl)                            \
      53             :   V(Word32Sar)                            \
      54             :   V(IntAdd)                               \
      55             :   V(IntSub)                               \
      56             :   V(IntMul)                               \
      57             :   V(IntLessThan)                          \
      58             :   V(UintLessThan)                         \
      59             :   V(Int32Add)                             \
      60             :   V(Int32Sub)                             \
      61             :   V(Int32Mul)                             \
      62             :   V(Int32LessThanOrEqual)                 \
      63             :   V(Uint32LessThan)                       \
      64             :   V(Uint32LessThanOrEqual)                \
      65             :   V(Uint64LessThan)                       \
      66             :   V(Uint64LessThanOrEqual)                \
      67             :   V(Int32LessThan)                        \
      68             :   V(Float64Add)                           \
      69             :   V(Float64Sub)                           \
      70             :   V(Float64Div)                           \
      71             :   V(Float64Mod)                           \
      72             :   V(Float64Equal)                         \
      73             :   V(Float64LessThan)                      \
      74             :   V(Float64LessThanOrEqual)               \
      75             :   V(Float64InsertLowWord32)               \
      76             :   V(Float64InsertHighWord32)              \
      77             :   V(Word32Equal)                          \
      78             :   V(Word64Equal)                          \
      79             :   V(WordEqual)
      80             : 
      81             : #define CHECKED_ASSEMBLER_MACH_BINOP_LIST(V) \
      82             :   V(Int32AddWithOverflow)                    \
      83             :   V(Int32SubWithOverflow)                    \
      84             :   V(Int32MulWithOverflow)                    \
      85             :   V(Int32Mod)                                \
      86             :   V(Int32Div)                                \
      87             :   V(Uint32Mod)                               \
      88             :   V(Uint32Div)
      89             : 
      90             : #define JSGRAPH_SINGLETON_CONSTANT_LIST(V) \
      91             :   V(TrueConstant)                          \
      92             :   V(FalseConstant)                         \
      93             :   V(NullConstant)                          \
      94             :   V(BooleanMapConstant)                    \
      95             :   V(HeapNumberMapConstant)                 \
      96             :   V(NoContextConstant)                     \
      97             :   V(EmptyStringConstant)                   \
      98             :   V(UndefinedConstant)                     \
      99             :   V(TheHoleConstant)                       \
     100             :   V(FixedArrayMapConstant)                 \
     101             :   V(FixedDoubleArrayMapConstant)           \
     102             :   V(ToNumberBuiltinConstant)               \
     103             :   V(AllocateInNewSpaceStubConstant)        \
     104             :   V(AllocateInOldSpaceStubConstant)
     105             : 
     106             : class GraphAssembler;
     107             : 
     108             : enum class GraphAssemblerLabelType { kDeferred, kNonDeferred, kLoop };
     109             : 
     110             : // Label with statically known count of incoming branches and phis.
     111             : template <size_t VarCount>
     112             : class GraphAssemblerLabel {
     113             :  public:
     114             :   Node* PhiAt(size_t index);
     115             : 
     116             :   template <typename... Reps>
     117             :   explicit GraphAssemblerLabel(GraphAssemblerLabelType type, Reps... reps)
     118             :       : type_(type) {
     119             :     STATIC_ASSERT(VarCount == sizeof...(reps));
     120             :     MachineRepresentation reps_array[] = {MachineRepresentation::kNone,
     121      499065 :                                           reps...};
     122     1002926 :     for (size_t i = 0; i < VarCount; i++) {
     123      503861 :       representations_[i] = reps_array[i + 1];
     124             :     }
     125             :   }
     126             : 
     127             :   ~GraphAssemblerLabel() { DCHECK(IsBound() || merged_count_ == 0); }
     128             : 
     129             :  private:
     130             :   friend class GraphAssembler;
     131             : 
     132             :   void SetBound() {
     133             :     DCHECK(!IsBound());
     134     1285416 :     is_bound_ = true;
     135             :   }
     136             :   bool IsBound() const { return is_bound_; }
     137             :   bool IsDeferred() const {
     138       43008 :     return type_ == GraphAssemblerLabelType::kDeferred;
     139             :   }
     140             :   bool IsLoop() const { return type_ == GraphAssemblerLabelType::kLoop; }
     141             : 
     142             :   bool is_bound_ = false;
     143             :   GraphAssemblerLabelType const type_;
     144             :   size_t merged_count_ = 0;
     145             :   Node* effect_;
     146             :   Node* control_;
     147             :   Node* bindings_[VarCount + 1];
     148             :   MachineRepresentation representations_[VarCount + 1];
     149             : };
     150             : 
     151             : class GraphAssembler {
     152             :  public:
     153             :   GraphAssembler(JSGraph* jsgraph, Node* effect, Node* control, Zone* zone);
     154             : 
     155             :   void Reset(Node* effect, Node* control);
     156             : 
     157             :   // Create label.
     158             :   template <typename... Reps>
     159             :   static GraphAssemblerLabel<sizeof...(Reps)> MakeLabelFor(
     160             :       GraphAssemblerLabelType type, Reps... reps) {
     161             :     return GraphAssemblerLabel<sizeof...(Reps)>(type, reps...);
     162             :   }
     163             : 
     164             :   // Convenience wrapper for creating non-deferred labels.
     165             :   template <typename... Reps>
     166             :   static GraphAssemblerLabel<sizeof...(Reps)> MakeLabel(Reps... reps) {
     167             :     return MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, reps...);
     168             :   }
     169             : 
     170             :   // Convenience wrapper for creating loop labels.
     171             :   template <typename... Reps>
     172             :   static GraphAssemblerLabel<sizeof...(Reps)> MakeLoopLabel(Reps... reps) {
     173             :     return MakeLabelFor(GraphAssemblerLabelType::kLoop, reps...);
     174             :   }
     175             : 
     176             :   // Convenience wrapper for creating deferred labels.
     177             :   template <typename... Reps>
     178             :   static GraphAssemblerLabel<sizeof...(Reps)> MakeDeferredLabel(Reps... reps) {
     179             :     return MakeLabelFor(GraphAssemblerLabelType::kDeferred, reps...);
     180             :   }
     181             : 
     182             :   // Value creation.
     183             :   Node* IntPtrConstant(intptr_t value);
     184             :   Node* Uint32Constant(int32_t value);
     185             :   Node* Int32Constant(int32_t value);
     186             :   Node* Int64Constant(int64_t value);
     187             :   Node* UniqueIntPtrConstant(intptr_t value);
     188             :   Node* SmiConstant(int32_t value);
     189             :   Node* Float64Constant(double value);
     190             :   Node* Projection(int index, Node* value);
     191             :   Node* HeapConstant(Handle<HeapObject> object);
     192             :   Node* CEntryStubConstant(int result_size);
     193             :   Node* ExternalConstant(ExternalReference ref);
     194             : 
     195             :   Node* LoadFramePointer();
     196             : 
     197             : #define SINGLETON_CONST_DECL(Name) Node* Name();
     198             :   JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_DECL)
     199             : #undef SINGLETON_CONST_DECL
     200             : 
     201             : #define PURE_UNOP_DECL(Name) Node* Name(Node* input);
     202             :   PURE_ASSEMBLER_MACH_UNOP_LIST(PURE_UNOP_DECL)
     203             : #undef PURE_UNOP_DECL
     204             : 
     205             : #define BINOP_DECL(Name) Node* Name(Node* left, Node* right);
     206             :   PURE_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL)
     207             :   CHECKED_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL)
     208             : #undef BINOP_DECL
     209             : 
     210             :   // Debugging
     211             :   Node* DebugBreak();
     212             : 
     213             :   Node* Unreachable();
     214             : 
     215             :   Node* Float64RoundDown(Node* value);
     216             :   Node* Float64RoundTruncate(Node* value);
     217             : 
     218             :   Node* ToNumber(Node* value);
     219             :   Node* BitcastWordToTagged(Node* value);
     220             :   Node* BitcastTaggedToWord(Node* value);
     221             :   Node* Allocate(PretenureFlag pretenure, Node* size);
     222             :   Node* LoadField(FieldAccess const&, Node* object);
     223             :   Node* LoadElement(ElementAccess const&, Node* object, Node* index);
     224             :   Node* StoreField(FieldAccess const&, Node* object, Node* value);
     225             :   Node* StoreElement(ElementAccess const&, Node* object, Node* index,
     226             :                      Node* value);
     227             : 
     228             :   Node* Store(StoreRepresentation rep, Node* object, Node* offset, Node* value);
     229             :   Node* Load(MachineType rep, Node* object, Node* offset);
     230             : 
     231             :   Node* StoreUnaligned(MachineRepresentation rep, Node* object, Node* offset,
     232             :                        Node* value);
     233             :   Node* LoadUnaligned(MachineType rep, Node* object, Node* offset);
     234             : 
     235             :   Node* Retain(Node* buffer);
     236             :   Node* UnsafePointerAdd(Node* base, Node* external);
     237             : 
     238             :   Node* Word32PoisonOnSpeculation(Node* value);
     239             : 
     240             :   Node* DeoptimizeIf(
     241             :       DeoptimizeReason reason, VectorSlotPair const& feedback, Node* condition,
     242             :       Node* frame_state,
     243             :       IsSafetyCheck is_safety_check = IsSafetyCheck::kSafetyCheck);
     244             :   Node* DeoptimizeIfNot(
     245             :       DeoptimizeReason reason, VectorSlotPair const& feedback, Node* condition,
     246             :       Node* frame_state,
     247             :       IsSafetyCheck is_safety_check = IsSafetyCheck::kSafetyCheck);
     248             :   template <typename... Args>
     249             :   Node* Call(const CallDescriptor* call_descriptor, Args... args);
     250             :   template <typename... Args>
     251             :   Node* Call(const Operator* op, Args... args);
     252             : 
     253             :   // Basic control operations.
     254             :   template <size_t VarCount>
     255             :   void Bind(GraphAssemblerLabel<VarCount>* label);
     256             : 
     257             :   template <typename... Vars>
     258             :   void Goto(GraphAssemblerLabel<sizeof...(Vars)>* label, Vars...);
     259             : 
     260             :   void Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
     261             :               GraphAssemblerLabel<0u>* if_false,
     262             :               IsSafetyCheck is_safety_check = IsSafetyCheck::kNoSafetyCheck);
     263             : 
     264             :   // Control helpers.
     265             :   // {GotoIf(c, l)} is equivalent to {Branch(c, l, templ);Bind(templ)}.
     266             :   template <typename... Vars>
     267             :   void GotoIf(Node* condition, GraphAssemblerLabel<sizeof...(Vars)>* label,
     268             :               Vars...);
     269             : 
     270             :   // {GotoIfNot(c, l)} is equivalent to {Branch(c, templ, l);Bind(templ)}.
     271             :   template <typename... Vars>
     272             :   void GotoIfNot(Node* condition, GraphAssemblerLabel<sizeof...(Vars)>* label,
     273             :                  Vars...);
     274             : 
     275             :   // Extractors (should be only used when destructing/resetting the assembler).
     276             :   Node* ExtractCurrentControl();
     277             :   Node* ExtractCurrentEffect();
     278             : 
     279             :  private:
     280             :   template <typename... Vars>
     281             :   void MergeState(GraphAssemblerLabel<sizeof...(Vars)>* label, Vars... vars);
     282             : 
     283             :   Operator const* ToNumberOperator();
     284             : 
     285             :   JSGraph* jsgraph() const { return jsgraph_; }
     286             :   Isolate* isolate() const { return jsgraph_->isolate(); }
     287    11897273 :   Graph* graph() const { return jsgraph_->graph(); }
     288             :   Zone* temp_zone() const { return temp_zone_; }
     289     5869968 :   CommonOperatorBuilder* common() const { return jsgraph()->common(); }
     290     5050763 :   MachineOperatorBuilder* machine() const { return jsgraph()->machine(); }
     291      961046 :   SimplifiedOperatorBuilder* simplified() const {
     292      961046 :     return jsgraph()->simplified();
     293             :   }
     294             : 
     295             :   SetOncePointer<Operator const> to_number_operator_;
     296             :   Zone* temp_zone_;
     297             :   JSGraph* jsgraph_;
     298             :   Node* current_effect_;
     299             :   Node* current_control_;
     300             : };
     301             : 
     302             : template <size_t VarCount>
     303             : Node* GraphAssemblerLabel<VarCount>::PhiAt(size_t index) {
     304             :   DCHECK(IsBound());
     305             :   DCHECK_LT(index, VarCount);
     306      678014 :   return bindings_[index];
     307             : }
     308             : 
     309             : template <typename... Vars>
     310     4446690 : void GraphAssembler::MergeState(GraphAssemblerLabel<sizeof...(Vars)>* label,
     311     2476137 :                                 Vars... vars) {
     312     2223345 :   int merged_count = static_cast<int>(label->merged_count_);
     313     1215900 :   Node* var_array[] = {nullptr, vars...};
     314     2223345 :   if (label->IsLoop()) {
     315        5896 :     if (merged_count == 0) {
     316             :       DCHECK(!label->IsBound());
     317        2948 :       label->control_ = graph()->NewNode(common()->Loop(2), current_control_,
     318        5896 :                                          current_control_);
     319        8844 :       label->effect_ = graph()->NewNode(common()->EffectPhi(2), current_effect_,
     320             :                                         current_effect_, label->control_);
     321             :       Node* terminate = graph()->NewNode(common()->Terminate(), label->effect_,
     322        5896 :                                          label->control_);
     323        2948 :       NodeProperties::MergeControlToEnd(graph(), common(), terminate);
     324       11242 :       for (size_t i = 0; i < sizeof...(vars); i++) {
     325       16038 :         label->bindings_[i] = graph()->NewNode(
     326             :             common()->Phi(label->representations_[i], 2), var_array[i + 1],
     327             :             var_array[i + 1], label->control_);
     328             :       }
     329             :     } else {
     330             :       DCHECK(label->IsBound());
     331             :       DCHECK_EQ(1, merged_count);
     332        2948 :       label->control_->ReplaceInput(1, current_control_);
     333        2948 :       label->effect_->ReplaceInput(1, current_effect_);
     334       11242 :       for (size_t i = 0; i < sizeof...(vars); i++) {
     335        5346 :         label->bindings_[i]->ReplaceInput(1, var_array[i + 1]);
     336             :       }
     337             :     }
     338             :   } else {
     339             :     DCHECK(!label->IsBound());
     340     2217449 :     if (merged_count == 0) {
     341             :       // Just set the control, effect and variables directly.
     342             :       DCHECK(!label->IsBound());
     343     1345813 :       label->control_ = current_control_;
     344     1345813 :       label->effect_ = current_effect_;
     345     1490764 :       for (size_t i = 0; i < sizeof...(vars); i++) {
     346      498520 :         label->bindings_[i] = var_array[i + 1];
     347             :       }
     348      871636 :     } else if (merged_count == 1) {
     349             :       // Create merge, effect phi and a phi for each variable.
     350     1950082 :       label->control_ = graph()->NewNode(common()->Merge(2), label->control_,
     351             :                                          current_control_);
     352     1950084 :       label->effect_ = graph()->NewNode(common()->EffectPhi(2), label->effect_,
     353             :                                         current_effect_, label->control_);
     354     1490772 :       for (size_t i = 0; i < sizeof...(vars); i++) {
     355     1495568 :         label->bindings_[i] = graph()->NewNode(
     356             :             common()->Phi(label->representations_[i], 2), label->bindings_[i],
     357             :             var_array[i + 1], label->control_);
     358             :       }
     359             :     } else {
     360             :       // Append to the merge, effect phi and phis.
     361             :       DCHECK_EQ(IrOpcode::kMerge, label->control_->opcode());
     362      443218 :       label->control_->AppendInput(graph()->zone(), current_control_);
     363      221609 :       NodeProperties::ChangeOp(label->control_,
     364      443218 :                                common()->Merge(merged_count + 1));
     365             : 
     366             :       DCHECK_EQ(IrOpcode::kEffectPhi, label->effect_->opcode());
     367      221609 :       label->effect_->ReplaceInput(merged_count, current_effect_);
     368      443218 :       label->effect_->AppendInput(graph()->zone(), label->control_);
     369      221609 :       NodeProperties::ChangeOp(label->effect_,
     370      221609 :                                common()->EffectPhi(merged_count + 1));
     371             : 
     372      659523 :       for (size_t i = 0; i < sizeof...(vars); i++) {
     373             :         DCHECK_EQ(IrOpcode::kPhi, label->bindings_[i]->opcode());
     374      220156 :         label->bindings_[i]->ReplaceInput(merged_count, var_array[i + 1]);
     375      440312 :         label->bindings_[i]->AppendInput(graph()->zone(), label->control_);
     376      220156 :         NodeProperties::ChangeOp(
     377             :             label->bindings_[i],
     378      440312 :             common()->Phi(label->representations_[i], merged_count + 1));
     379             :       }
     380             :     }
     381             :   }
     382     2223345 :   label->merged_count_++;
     383     2223345 : }
     384             : 
     385             : template <size_t VarCount>
     386             : void GraphAssembler::Bind(GraphAssemblerLabel<VarCount>* label) {
     387             :   DCHECK_NULL(current_control_);
     388             :   DCHECK_NULL(current_effect_);
     389             :   DCHECK_LT(0, label->merged_count_);
     390             : 
     391     1348762 :   current_control_ = label->control_;
     392     1348762 :   current_effect_ = label->effect_;
     393             : 
     394             :   label->SetBound();
     395             : }
     396             : 
     397             : template <typename... Vars>
     398             : void GraphAssembler::Goto(GraphAssemblerLabel<sizeof...(Vars)>* label,
     399             :                           Vars... vars) {
     400             :   DCHECK_NOT_NULL(current_control_);
     401             :   DCHECK_NOT_NULL(current_effect_);
     402     1327258 :   MergeState(label, vars...);
     403     1327258 :   current_control_ = nullptr;
     404     1327258 :   current_effect_ = nullptr;
     405             : }
     406             : 
     407             : template <typename... Vars>
     408      579035 : void GraphAssembler::GotoIf(Node* condition,
     409      579035 :                             GraphAssemblerLabel<sizeof...(Vars)>* label,
     410     1737112 :                             Vars... vars) {
     411             :   BranchHint hint =
     412      579035 :       label->IsDeferred() ? BranchHint::kFalse : BranchHint::kNone;
     413             :   Node* branch =
     414     1158070 :       graph()->NewNode(common()->Branch(hint), condition, current_control_);
     415             : 
     416     1158076 :   current_control_ = graph()->NewNode(common()->IfTrue(), branch);
     417      579038 :   MergeState(label, vars...);
     418             : 
     419     1158075 :   current_control_ = graph()->NewNode(common()->IfFalse(), branch);
     420      579038 : }
     421             : 
     422             : template <typename... Vars>
     423      274041 : void GraphAssembler::GotoIfNot(Node* condition,
     424      274041 :                                GraphAssemblerLabel<sizeof...(Vars)>* label,
     425      822128 :                                Vars... vars) {
     426      274041 :   BranchHint hint = label->IsDeferred() ? BranchHint::kTrue : BranchHint::kNone;
     427             :   Node* branch =
     428      548082 :       graph()->NewNode(common()->Branch(hint), condition, current_control_);
     429             : 
     430      548086 :   current_control_ = graph()->NewNode(common()->IfFalse(), branch);
     431      274043 :   MergeState(label, vars...);
     432             : 
     433      548086 :   current_control_ = graph()->NewNode(common()->IfTrue(), branch);
     434      274043 : }
     435             : 
     436             : template <typename... Args>
     437       81486 : Node* GraphAssembler::Call(const CallDescriptor* call_descriptor,
     438             :                            Args... args) {
     439       81486 :   const Operator* op = common()->Call(call_descriptor);
     440       81486 :   return Call(op, args...);
     441             : }
     442             : 
     443             : template <typename... Args>
     444     1105368 : Node* GraphAssembler::Call(const Operator* op, Args... args) {
     445             :   DCHECK_EQ(IrOpcode::kCall, op->opcode());
     446      276342 :   Node* args_array[] = {args..., current_effect_, current_control_};
     447             :   int size = static_cast<int>(sizeof...(args)) + op->EffectInputCount() +
     448      552684 :              op->ControlInputCount();
     449      276342 :   Node* call = graph()->NewNode(op, size, args_array);
     450             :   DCHECK_EQ(0, op->ControlOutputCount());
     451      276342 :   current_effect_ = call;
     452      276342 :   return call;
     453             : }
     454             : 
     455             : }  // namespace compiler
     456             : }  // namespace internal
     457             : }  // namespace v8
     458             : 
     459             : #endif  // V8_COMPILER_GRAPH_ASSEMBLER_H_

Generated by: LCOV version 1.10