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

Generated by: LCOV version 1.10