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

Generated by: LCOV version 1.10