LCOV - code coverage report
Current view: top level - src/compiler - graph-assembler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 71 71 100.0 %
Date: 2019-03-21 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(BigIntMapConstant)                     \
      96             :   V(BooleanMapConstant)                    \
      97             :   V(HeapNumberMapConstant)                 \
      98             :   V(NoContextConstant)                     \
      99             :   V(EmptyStringConstant)                   \
     100             :   V(UndefinedConstant)                     \
     101             :   V(TheHoleConstant)                       \
     102             :   V(FixedArrayMapConstant)                 \
     103             :   V(FixedDoubleArrayMapConstant)           \
     104             :   V(ToNumberBuiltinConstant)               \
     105             :   V(AllocateInYoungGenerationStubConstant) \
     106             :   V(AllocateInOldGenerationStubConstant)
     107             : 
     108             : class GraphAssembler;
     109             : 
     110             : enum class GraphAssemblerLabelType { kDeferred, kNonDeferred, kLoop };
     111             : 
     112             : // Label with statically known count of incoming branches and phis.
     113             : template <size_t VarCount>
     114             : class GraphAssemblerLabel {
     115             :  public:
     116             :   Node* PhiAt(size_t index);
     117             : 
     118             :   template <typename... Reps>
     119             :   explicit GraphAssemblerLabel(GraphAssemblerLabelType type, Reps... reps)
     120             :       : type_(type) {
     121             :     STATIC_ASSERT(VarCount == sizeof...(reps));
     122             :     MachineRepresentation reps_array[] = {MachineRepresentation::kNone,
     123      536162 :                                           reps...};
     124     1076923 :     for (size_t i = 0; i < VarCount; i++) {
     125      540761 :       representations_[i] = reps_array[i + 1];
     126             :     }
     127             :   }
     128             : 
     129     1280986 :   ~GraphAssemblerLabel() { DCHECK(IsBound() || merged_count_ == 0); }
     130             : 
     131             :  private:
     132             :   friend class GraphAssembler;
     133             : 
     134             :   void SetBound() {
     135             :     DCHECK(!IsBound());
     136     1371475 :     is_bound_ = true;
     137             :   }
     138             :   bool IsBound() const { return is_bound_; }
     139             :   bool IsDeferred() const {
     140       25224 :     return type_ == GraphAssemblerLabelType::kDeferred;
     141             :   }
     142             :   bool IsLoop() const { return type_ == GraphAssemblerLabelType::kLoop; }
     143             : 
     144             :   bool is_bound_ = false;
     145             :   GraphAssemblerLabelType const type_;
     146             :   size_t merged_count_ = 0;
     147             :   Node* effect_;
     148             :   Node* control_;
     149             :   Node* bindings_[VarCount + 1];
     150             :   MachineRepresentation representations_[VarCount + 1];
     151             : };
     152             : 
     153             : class GraphAssembler {
     154             :  public:
     155             :   GraphAssembler(JSGraph* jsgraph, Node* effect, Node* control, Zone* zone);
     156             : 
     157             :   void Reset(Node* effect, Node* control);
     158             : 
     159             :   // Create label.
     160             :   template <typename... Reps>
     161             :   static GraphAssemblerLabel<sizeof...(Reps)> MakeLabelFor(
     162             :       GraphAssemblerLabelType type, Reps... reps) {
     163             :     return GraphAssemblerLabel<sizeof...(Reps)>(type, reps...);
     164             :   }
     165             : 
     166             :   // Convenience wrapper for creating non-deferred labels.
     167             :   template <typename... Reps>
     168             :   static GraphAssemblerLabel<sizeof...(Reps)> MakeLabel(Reps... reps) {
     169             :     return MakeLabelFor(GraphAssemblerLabelType::kNonDeferred, reps...);
     170             :   }
     171             : 
     172             :   // Convenience wrapper for creating loop labels.
     173             :   template <typename... Reps>
     174             :   static GraphAssemblerLabel<sizeof...(Reps)> MakeLoopLabel(Reps... reps) {
     175             :     return MakeLabelFor(GraphAssemblerLabelType::kLoop, reps...);
     176             :   }
     177             : 
     178             :   // Convenience wrapper for creating deferred labels.
     179             :   template <typename... Reps>
     180             :   static GraphAssemblerLabel<sizeof...(Reps)> MakeDeferredLabel(Reps... reps) {
     181             :     return MakeLabelFor(GraphAssemblerLabelType::kDeferred, reps...);
     182             :   }
     183             : 
     184             :   // Value creation.
     185             :   Node* IntPtrConstant(intptr_t value);
     186             :   Node* Uint32Constant(int32_t value);
     187             :   Node* Int32Constant(int32_t value);
     188             :   Node* Int64Constant(int64_t value);
     189             :   Node* UniqueIntPtrConstant(intptr_t value);
     190             :   Node* SmiConstant(int32_t value);
     191             :   Node* Float64Constant(double value);
     192             :   Node* Projection(int index, Node* value);
     193             :   Node* HeapConstant(Handle<HeapObject> object);
     194             :   Node* CEntryStubConstant(int result_size);
     195             :   Node* ExternalConstant(ExternalReference ref);
     196             : 
     197             :   Node* LoadFramePointer();
     198             : 
     199             : #define SINGLETON_CONST_DECL(Name) Node* Name();
     200             :   JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_DECL)
     201             : #undef SINGLETON_CONST_DECL
     202             : 
     203             : #define PURE_UNOP_DECL(Name) Node* Name(Node* input);
     204             :   PURE_ASSEMBLER_MACH_UNOP_LIST(PURE_UNOP_DECL)
     205             : #undef PURE_UNOP_DECL
     206             : 
     207             : #define BINOP_DECL(Name) Node* Name(Node* left, Node* right);
     208             :   PURE_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL)
     209             :   CHECKED_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL)
     210             : #undef BINOP_DECL
     211             : 
     212             :   // Debugging
     213             :   Node* DebugBreak();
     214             : 
     215             :   Node* Unreachable();
     216             : 
     217             :   Node* Float64RoundDown(Node* value);
     218             :   Node* Float64RoundTruncate(Node* value);
     219             : 
     220             :   Node* ToNumber(Node* value);
     221             :   Node* BitcastWordToTagged(Node* value);
     222             :   Node* BitcastTaggedToWord(Node* value);
     223             :   Node* Allocate(AllocationType allocation, Node* size);
     224             :   Node* LoadField(FieldAccess const&, Node* object);
     225             :   Node* LoadElement(ElementAccess const&, Node* object, Node* index);
     226             :   Node* StoreField(FieldAccess const&, Node* object, Node* value);
     227             :   Node* StoreElement(ElementAccess const&, Node* object, Node* index,
     228             :                      Node* value);
     229             : 
     230             :   Node* Store(StoreRepresentation rep, Node* object, Node* offset, Node* value);
     231             :   Node* Load(MachineType rep, Node* object, Node* offset);
     232             : 
     233             :   Node* StoreUnaligned(MachineRepresentation rep, Node* object, Node* offset,
     234             :                        Node* value);
     235             :   Node* LoadUnaligned(MachineType rep, Node* object, Node* offset);
     236             : 
     237             :   Node* Retain(Node* buffer);
     238             :   Node* UnsafePointerAdd(Node* base, Node* external);
     239             : 
     240             :   Node* Word32PoisonOnSpeculation(Node* value);
     241             : 
     242             :   Node* DeoptimizeIf(
     243             :       DeoptimizeReason reason, VectorSlotPair const& feedback, Node* condition,
     244             :       Node* frame_state,
     245             :       IsSafetyCheck is_safety_check = IsSafetyCheck::kSafetyCheck);
     246             :   Node* DeoptimizeIfNot(
     247             :       DeoptimizeReason reason, VectorSlotPair const& feedback, Node* condition,
     248             :       Node* frame_state,
     249             :       IsSafetyCheck is_safety_check = IsSafetyCheck::kSafetyCheck);
     250             :   template <typename... Args>
     251             :   Node* Call(const CallDescriptor* call_descriptor, Args... args);
     252             :   template <typename... Args>
     253             :   Node* Call(const Operator* op, Args... args);
     254             : 
     255             :   // Basic control operations.
     256             :   template <size_t VarCount>
     257             :   void Bind(GraphAssemblerLabel<VarCount>* label);
     258             : 
     259             :   template <typename... Vars>
     260             :   void Goto(GraphAssemblerLabel<sizeof...(Vars)>* label, Vars...);
     261             : 
     262             :   void Branch(Node* condition, GraphAssemblerLabel<0u>* if_true,
     263             :               GraphAssemblerLabel<0u>* if_false,
     264             :               IsSafetyCheck is_safety_check = IsSafetyCheck::kNoSafetyCheck);
     265             : 
     266             :   // Control helpers.
     267             :   // {GotoIf(c, l)} is equivalent to {Branch(c, l, templ);Bind(templ)}.
     268             :   template <typename... Vars>
     269             :   void GotoIf(Node* condition, GraphAssemblerLabel<sizeof...(Vars)>* label,
     270             :               Vars...);
     271             : 
     272             :   // {GotoIfNot(c, l)} is equivalent to {Branch(c, templ, l);Bind(templ)}.
     273             :   template <typename... Vars>
     274             :   void GotoIfNot(Node* condition, GraphAssemblerLabel<sizeof...(Vars)>* label,
     275             :                  Vars...);
     276             : 
     277             :   // Extractors (should be only used when destructing/resetting the assembler).
     278             :   Node* ExtractCurrentControl();
     279             :   Node* ExtractCurrentEffect();
     280             : 
     281             :  private:
     282             :   template <typename... Vars>
     283             :   void MergeState(GraphAssemblerLabel<sizeof...(Vars)>* label, Vars... vars);
     284             : 
     285             :   Operator const* ToNumberOperator();
     286             : 
     287             :   JSGraph* jsgraph() const { return jsgraph_; }
     288             :   Isolate* isolate() const { return jsgraph_->isolate(); }
     289             :   Graph* graph() const { return jsgraph_->graph(); }
     290             :   Zone* temp_zone() const { return temp_zone_; }
     291             :   CommonOperatorBuilder* common() const { return jsgraph()->common(); }
     292             :   MachineOperatorBuilder* machine() const { return jsgraph()->machine(); }
     293             :   SimplifiedOperatorBuilder* simplified() const {
     294             :     return jsgraph()->simplified();
     295             :   }
     296             : 
     297             :   SetOncePointer<Operator const> to_number_operator_;
     298             :   Zone* temp_zone_;
     299             :   JSGraph* jsgraph_;
     300             :   Node* current_effect_;
     301             :   Node* current_control_;
     302             : };
     303             : 
     304             : template <size_t VarCount>
     305             : Node* GraphAssemblerLabel<VarCount>::PhiAt(size_t index) {
     306             :   DCHECK(IsBound());
     307             :   DCHECK_LT(index, VarCount);
     308      739400 :   return bindings_[index];
     309             : }
     310             : 
     311             : template <typename... Vars>
     312     2429672 : void GraphAssembler::MergeState(GraphAssemblerLabel<sizeof...(Vars)>* label,
     313             :                                 Vars... vars) {
     314     2429672 :   int merged_count = static_cast<int>(label->merged_count_);
     315     1319351 :   Node* var_array[] = {nullptr, vars...};
     316     2429672 :   if (label->IsLoop()) {
     317        5604 :     if (merged_count == 0) {
     318             :       DCHECK(!label->IsBound());
     319        5604 :       label->control_ = graph()->NewNode(common()->Loop(2), current_control_,
     320             :                                          current_control_);
     321        5604 :       label->effect_ = graph()->NewNode(common()->EffectPhi(2), current_effect_,
     322             :                                         current_effect_, label->control_);
     323             :       Node* terminate = graph()->NewNode(common()->Terminate(), label->effect_,
     324        2802 :                                          label->control_);
     325        2802 :       NodeProperties::MergeControlToEnd(graph(), common(), terminate);
     326       13006 :       for (size_t i = 0; i < sizeof...(vars); i++) {
     327       10204 :         label->bindings_[i] = graph()->NewNode(
     328             :             common()->Phi(label->representations_[i], 2), var_array[i + 1],
     329             :             var_array[i + 1], label->control_);
     330             :       }
     331             :     } else {
     332             :       DCHECK(label->IsBound());
     333             :       DCHECK_EQ(1, merged_count);
     334        2802 :       label->control_->ReplaceInput(1, current_control_);
     335        2802 :       label->effect_->ReplaceInput(1, current_effect_);
     336       13006 :       for (size_t i = 0; i < sizeof...(vars); i++) {
     337        5102 :         label->bindings_[i]->ReplaceInput(1, var_array[i + 1]);
     338             :       }
     339             :     }
     340             :   } else {
     341             :     DCHECK(!label->IsBound());
     342     2424068 :     if (merged_count == 0) {
     343             :       // Just set the control, effect and variables directly.
     344             :       DCHECK(!label->IsBound());
     345     1431301 :       label->control_ = current_control_;
     346     1431301 :       label->effect_ = current_effect_;
     347     1604674 :       for (size_t i = 0; i < sizeof...(vars); i++) {
     348      535658 :         label->bindings_[i] = var_array[i + 1];
     349             :       }
     350      992767 :     } else if (merged_count == 1) {
     351             :       // Create merge, effect phi and a phi for each variable.
     352     1400468 :       label->control_ = graph()->NewNode(common()->Merge(2), label->control_,
     353             :                                          current_control_);
     354     1400469 :       label->effect_ = graph()->NewNode(common()->EffectPhi(2), label->effect_,
     355             :                                         current_effect_, label->control_);
     356     1604682 :       for (size_t i = 0; i < sizeof...(vars); i++) {
     357     1071321 :         label->bindings_[i] = graph()->NewNode(
     358             :             common()->Phi(label->representations_[i], 2), label->bindings_[i],
     359             :             var_array[i + 1], label->control_);
     360             :       }
     361             :     } else {
     362             :       // Append to the merge, effect phi and phis.
     363             :       DCHECK_EQ(IrOpcode::kMerge, label->control_->opcode());
     364      292534 :       label->control_->AppendInput(graph()->zone(), current_control_);
     365      292534 :       NodeProperties::ChangeOp(label->control_,
     366             :                                common()->Merge(merged_count + 1));
     367             : 
     368             :       DCHECK_EQ(IrOpcode::kEffectPhi, label->effect_->opcode());
     369      292534 :       label->effect_->ReplaceInput(merged_count, current_effect_);
     370      292534 :       label->effect_->AppendInput(graph()->zone(), label->control_);
     371      292534 :       NodeProperties::ChangeOp(label->effect_,
     372             :                                common()->EffectPhi(merged_count + 1));
     373             : 
     374      745687 :       for (size_t i = 0; i < sizeof...(vars); i++) {
     375             :         DCHECK_EQ(IrOpcode::kPhi, label->bindings_[i]->opcode());
     376      249329 :         label->bindings_[i]->ReplaceInput(merged_count, var_array[i + 1]);
     377      249329 :         label->bindings_[i]->AppendInput(graph()->zone(), label->control_);
     378      249329 :         NodeProperties::ChangeOp(
     379             :             label->bindings_[i],
     380             :             common()->Phi(label->representations_[i], merged_count + 1));
     381             :       }
     382             :     }
     383             :   }
     384     2429674 :   label->merged_count_++;
     385     2429674 : }
     386             : 
     387             : template <size_t VarCount>
     388             : void GraphAssembler::Bind(GraphAssemblerLabel<VarCount>* label) {
     389             :   DCHECK_NULL(current_control_);
     390             :   DCHECK_NULL(current_effect_);
     391             :   DCHECK_LT(0, label->merged_count_);
     392             : 
     393     1434106 :   current_control_ = label->control_;
     394     1434106 :   current_effect_ = label->effect_;
     395             : 
     396             :   label->SetBound();
     397             : }
     398             : 
     399             : template <typename... Vars>
     400             : void GraphAssembler::Goto(GraphAssemblerLabel<sizeof...(Vars)>* label,
     401             :                           Vars... vars) {
     402             :   DCHECK_NOT_NULL(current_control_);
     403             :   DCHECK_NOT_NULL(current_effect_);
     404     1408886 :   MergeState(label, vars...);
     405     1408882 :   current_control_ = nullptr;
     406     1408882 :   current_effect_ = nullptr;
     407             : }
     408             : 
     409             : template <typename... Vars>
     410      668004 : void GraphAssembler::GotoIf(Node* condition,
     411             :                             GraphAssemblerLabel<sizeof...(Vars)>* label,
     412             :                             Vars... vars) {
     413             :   BranchHint hint =
     414      668004 :       label->IsDeferred() ? BranchHint::kFalse : BranchHint::kNone;
     415             :   Node* branch =
     416      668004 :       graph()->NewNode(common()->Branch(hint), condition, current_control_);
     417             : 
     418     1336010 :   current_control_ = graph()->NewNode(common()->IfTrue(), branch);
     419      668005 :   MergeState(label, vars...);
     420             : 
     421     1336008 :   current_control_ = graph()->NewNode(common()->IfFalse(), branch);
     422      668005 : }
     423             : 
     424             : template <typename... Vars>
     425      302339 : void GraphAssembler::GotoIfNot(Node* condition,
     426             :                                GraphAssemblerLabel<sizeof...(Vars)>* label,
     427             :                                Vars... vars) {
     428      302339 :   BranchHint hint = label->IsDeferred() ? BranchHint::kTrue : BranchHint::kNone;
     429             :   Node* branch =
     430      302339 :       graph()->NewNode(common()->Branch(hint), condition, current_control_);
     431             : 
     432      604681 :   current_control_ = graph()->NewNode(common()->IfFalse(), branch);
     433      302340 :   MergeState(label, vars...);
     434             : 
     435      604682 :   current_control_ = graph()->NewNode(common()->IfTrue(), branch);
     436      302341 : }
     437             : 
     438             : template <typename... Args>
     439       85432 : Node* GraphAssembler::Call(const CallDescriptor* call_descriptor,
     440             :                            Args... args) {
     441       85432 :   const Operator* op = common()->Call(call_descriptor);
     442       85432 :   return Call(op, args...);
     443             : }
     444             : 
     445             : template <typename... Args>
     446      302809 : Node* GraphAssembler::Call(const Operator* op, Args... args) {
     447             :   DCHECK_EQ(IrOpcode::kCall, op->opcode());
     448      302809 :   Node* args_array[] = {args..., current_effect_, current_control_};
     449             :   int size = static_cast<int>(sizeof...(args)) + op->EffectInputCount() +
     450      605618 :              op->ControlInputCount();
     451      302809 :   Node* call = graph()->NewNode(op, size, args_array);
     452             :   DCHECK_EQ(0, op->ControlOutputCount());
     453      302809 :   current_effect_ = call;
     454      302809 :   return call;
     455             : }
     456             : 
     457             : }  // namespace compiler
     458             : }  // namespace internal
     459             : }  // namespace v8
     460             : 
     461             : #endif  // V8_COMPILER_GRAPH_ASSEMBLER_H_

Generated by: LCOV version 1.10