LCOV - code coverage report
Current view: top level - src/compiler - graph-assembler.h (source / functions) Hit Total Coverage
Test: app.info Lines: 72 72 100.0 %
Date: 2017-04-26 Functions: 34 39 87.2 %

          Line data    Source code
       1             : // Copyright 2016 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #ifndef V8_COMPILER_GRAPH_ASSEMBLER_H_
       6             : #define V8_COMPILER_GRAPH_ASSEMBLER_H_
       7             : 
       8             : #include "src/compiler/js-graph.h"
       9             : #include "src/compiler/node.h"
      10             : #include "src/compiler/simplified-operator.h"
      11             : 
      12             : namespace v8 {
      13             : namespace internal {
      14             : 
      15             : class JSGraph;
      16             : class Graph;
      17             : 
      18             : namespace compiler {
      19             : 
      20             : #define PURE_ASSEMBLER_MACH_UNOP_LIST(V) \
      21             :   V(ChangeInt32ToInt64)                  \
      22             :   V(ChangeInt32ToFloat64)                \
      23             :   V(ChangeUint32ToFloat64)               \
      24             :   V(ChangeUint32ToUint64)                \
      25             :   V(ChangeFloat64ToInt32)                \
      26             :   V(ChangeFloat64ToUint32)               \
      27             :   V(TruncateInt64ToInt32)                \
      28             :   V(RoundFloat64ToInt32)                 \
      29             :   V(TruncateFloat64ToWord32)             \
      30             :   V(Float64ExtractHighWord32)            \
      31             :   V(Float64Abs)                          \
      32             :   V(BitcastWordToTagged)
      33             : 
      34             : #define PURE_ASSEMBLER_MACH_BINOP_LIST(V) \
      35             :   V(WordShl)                              \
      36             :   V(WordSar)                              \
      37             :   V(WordAnd)                              \
      38             :   V(Word32Or)                             \
      39             :   V(Word32And)                            \
      40             :   V(Word32Shr)                            \
      41             :   V(Word32Shl)                            \
      42             :   V(IntAdd)                               \
      43             :   V(IntSub)                               \
      44             :   V(IntLessThan)                          \
      45             :   V(UintLessThan)                         \
      46             :   V(Int32Add)                             \
      47             :   V(Int32Sub)                             \
      48             :   V(Int32Mul)                             \
      49             :   V(Int32LessThanOrEqual)                 \
      50             :   V(Uint32LessThanOrEqual)                \
      51             :   V(Uint32LessThan)                       \
      52             :   V(Int32LessThan)                        \
      53             :   V(Float64Add)                           \
      54             :   V(Float64Sub)                           \
      55             :   V(Float64Mod)                           \
      56             :   V(Float64Equal)                         \
      57             :   V(Float64LessThan)                      \
      58             :   V(Float64LessThanOrEqual)               \
      59             :   V(Word32Equal)                          \
      60             :   V(WordEqual)
      61             : 
      62             : #define CHECKED_ASSEMBLER_MACH_BINOP_LIST(V) \
      63             :   V(Int32AddWithOverflow)                    \
      64             :   V(Int32SubWithOverflow)                    \
      65             :   V(Int32MulWithOverflow)                    \
      66             :   V(Int32Mod)                                \
      67             :   V(Int32Div)                                \
      68             :   V(Uint32Mod)                               \
      69             :   V(Uint32Div)
      70             : 
      71             : #define JSGRAPH_SINGLETON_CONSTANT_LIST(V) \
      72             :   V(TrueConstant)                          \
      73             :   V(FalseConstant)                         \
      74             :   V(HeapNumberMapConstant)                 \
      75             :   V(NoContextConstant)                     \
      76             :   V(EmptyStringConstant)                   \
      77             :   V(UndefinedConstant)                     \
      78             :   V(TheHoleConstant)                       \
      79             :   V(FixedArrayMapConstant)                 \
      80             :   V(ToNumberBuiltinConstant)               \
      81             :   V(AllocateInNewSpaceStubConstant)        \
      82             :   V(AllocateInOldSpaceStubConstant)
      83             : 
      84             : class GraphAssembler;
      85             : 
      86             : enum class GraphAssemblerLabelType { kDeferred, kNonDeferred };
      87             : 
      88             : // Label with statically known count of incoming branches and phis.
      89             : template <size_t MergeCount, size_t VarCount = 0u>
      90             : class GraphAssemblerStaticLabel {
      91             :  public:
      92             :   Node* PhiAt(size_t index);
      93             : 
      94             :   template <typename... Reps>
      95             :   explicit GraphAssemblerStaticLabel(GraphAssemblerLabelType is_deferred,
      96             :                                      Reps... reps)
      97             :       : is_deferred_(is_deferred == GraphAssemblerLabelType::kDeferred) {
      98             :     STATIC_ASSERT(VarCount == sizeof...(reps));
      99             :     MachineRepresentation reps_array[] = {MachineRepresentation::kNone,
     100      423670 :                                           reps...};
     101      847340 :     for (size_t i = 0; i < VarCount; i++) {
     102      423670 :       representations_[i] = reps_array[i + 1];
     103             :     }
     104             :   }
     105             : 
     106             :   ~GraphAssemblerStaticLabel() { DCHECK(IsBound() || MergedCount() == 0); }
     107             : 
     108             :  private:
     109             :   friend class GraphAssembler;
     110             : 
     111             :   void SetBound() {
     112             :     DCHECK(!IsBound());
     113             :     DCHECK_EQ(merged_count_, MergeCount);
     114     1018400 :     is_bound_ = true;
     115             :   }
     116             :   bool IsBound() const { return is_bound_; }
     117             : 
     118             :   size_t PhiCount() const { return VarCount; }
     119             :   size_t MaxMergeCount() const { return MergeCount; }
     120             :   size_t MergedCount() const { return merged_count_; }
     121             :   bool IsDeferred() const { return is_deferred_; }
     122             : 
     123             :   // For each phi, the buffer must have at least MaxMergeCount() + 1
     124             :   // node entries.
     125             :   Node** GetBindingsPtrFor(size_t phi_index) {
     126             :     DCHECK_LT(phi_index, PhiCount());
     127      423670 :     return &bindings_[phi_index * (MergeCount + 1)];
     128             :   }
     129             :   void SetBinding(size_t phi_index, size_t merge_index, Node* binding) {
     130             :     DCHECK_LT(phi_index, PhiCount());
     131             :     DCHECK_LT(merge_index, MergeCount);
     132     1177172 :     bindings_[phi_index * (MergeCount + 1) + merge_index] = binding;
     133             :   }
     134             :   MachineRepresentation GetRepresentationFor(size_t phi_index) {
     135             :     DCHECK_LT(phi_index, PhiCount());
     136      423670 :     return representations_[phi_index];
     137             :   }
     138             :   // The controls buffer must have at least MaxMergeCount() entries.
     139             :   Node** GetControlsPtr() { return controls_; }
     140             :   // The effects buffer must have at least MaxMergeCount() + 1 entries.
     141             :   Node** GetEffectsPtr() { return effects_; }
     142     1835919 :   void IncrementMergedCount() { merged_count_++; }
     143             : 
     144             :   bool is_bound_ = false;
     145             :   bool is_deferred_;
     146             :   size_t merged_count_ = 0;
     147             :   Node* effects_[MergeCount + 1];  // Extra element for control edge,
     148             :                                    // so that we can use the array to
     149             :                                    // construct EffectPhi.
     150             :   Node* controls_[MergeCount];
     151             :   Node* bindings_[(MergeCount + 1) * VarCount + 1];
     152             :   MachineRepresentation representations_[VarCount + 1];
     153             : };
     154             : 
     155             : // General label (with zone allocated buffers for incoming branches and phi
     156             : // inputs).
     157             : class GraphAssemblerLabel {
     158             :  public:
     159             :   Node* PhiAt(size_t index);
     160             : 
     161             :   GraphAssemblerLabel(GraphAssemblerLabelType is_deferred, size_t merge_count,
     162             :                       size_t var_count, MachineRepresentation* representations,
     163             :                       Zone* zone);
     164             : 
     165             :   ~GraphAssemblerLabel();
     166             : 
     167             :  private:
     168             :   friend class GraphAssembler;
     169             : 
     170             :   void SetBound() {
     171             :     DCHECK(!is_bound_);
     172       93866 :     is_bound_ = true;
     173             :   }
     174             :   bool IsBound() const { return is_bound_; }
     175             :   size_t PhiCount() const { return var_count_; }
     176             :   size_t MaxMergeCount() const { return max_merge_count_; }
     177             :   size_t MergedCount() const { return merged_count_; }
     178             :   bool IsDeferred() const { return is_deferred_; }
     179             : 
     180             :   // For each phi, the buffer must have at least MaxMergeCount() + 1
     181             :   // node entries.
     182             :   Node** GetBindingsPtrFor(size_t phi_index);
     183             :   void SetBinding(size_t phi_index, size_t merge_index, Node* binding);
     184             :   MachineRepresentation GetRepresentationFor(size_t phi_index);
     185             :   // The controls buffer must have at least MaxMergeCount() entries.
     186             :   Node** GetControlsPtr();
     187             :   // The effects buffer must have at least MaxMergeCount() + 1 entries.
     188             :   Node** GetEffectsPtr();
     189      123208 :   void IncrementMergedCount() { merged_count_++; }
     190             : 
     191             :   bool is_bound_ = false;
     192             :   bool is_deferred_;
     193             :   size_t merged_count_ = 0;
     194             :   size_t max_merge_count_;
     195             :   size_t var_count_;
     196             :   Node** effects_ = nullptr;
     197             :   Node** controls_ = nullptr;
     198             :   Node** bindings_ = nullptr;
     199             :   MachineRepresentation* representations_ = nullptr;
     200             : };
     201             : 
     202             : class GraphAssembler {
     203             :  public:
     204             :   GraphAssembler(JSGraph* jsgraph, Node* effect, Node* control, Zone* zone);
     205             : 
     206             :   void Reset(Node* effect, Node* control);
     207             : 
     208             :   // Create non-deferred label with statically known number of incoming
     209             :   // gotos/branches.
     210             :   template <size_t MergeCount, typename... Reps>
     211             :   static GraphAssemblerStaticLabel<MergeCount, sizeof...(Reps)> MakeLabel(
     212             :       Reps... reps) {
     213             :     return GraphAssemblerStaticLabel<MergeCount, sizeof...(Reps)>(
     214             :         GraphAssemblerLabelType::kNonDeferred, reps...);
     215             :   }
     216             : 
     217             :   // Create deferred label with statically known number of incoming
     218             :   // gotos/branches.
     219             :   template <size_t MergeCount, typename... Reps>
     220             :   static GraphAssemblerStaticLabel<MergeCount, sizeof...(Reps)>
     221             :   MakeDeferredLabel(Reps... reps) {
     222             :     return GraphAssemblerStaticLabel<MergeCount, sizeof...(Reps)>(
     223             :         GraphAssemblerLabelType::kDeferred, reps...);
     224             :   }
     225             : 
     226             :   // Create label with number of incoming branches supplied at runtime.
     227             :   template <typename... Reps>
     228             :   GraphAssemblerLabel MakeLabelFor(GraphAssemblerLabelType is_deferred,
     229       93867 :                                    size_t merge_count, Reps... reps) {
     230             :     MachineRepresentation reps_array[] = {MachineRepresentation::kNone,
     231       93867 :                                           reps...};
     232             :     return GraphAssemblerLabel(is_deferred, merge_count, sizeof...(reps),
     233       93867 :                                &(reps_array[1]), temp_zone());
     234             :   }
     235             : 
     236             :   // Value creation.
     237             :   Node* IntPtrConstant(intptr_t value);
     238             :   Node* Uint32Constant(int32_t value);
     239             :   Node* Int32Constant(int32_t value);
     240             :   Node* UniqueInt32Constant(int32_t value);
     241             :   Node* SmiConstant(int32_t value);
     242             :   Node* Float64Constant(double value);
     243             :   Node* Projection(int index, Node* value);
     244             :   Node* HeapConstant(Handle<HeapObject> object);
     245             :   Node* CEntryStubConstant(int result_size);
     246             :   Node* ExternalConstant(ExternalReference ref);
     247             : 
     248             :   Node* LoadFramePointer();
     249             : 
     250             : #define SINGLETON_CONST_DECL(Name) Node* Name();
     251             :   JSGRAPH_SINGLETON_CONSTANT_LIST(SINGLETON_CONST_DECL)
     252             : #undef SINGLETON_CONST_DECL
     253             : 
     254             : #define PURE_UNOP_DECL(Name) Node* Name(Node* input);
     255             :   PURE_ASSEMBLER_MACH_UNOP_LIST(PURE_UNOP_DECL)
     256             : #undef PURE_UNOP_DECL
     257             : 
     258             : #define BINOP_DECL(Name) Node* Name(Node* left, Node* right);
     259             :   PURE_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL)
     260             :   CHECKED_ASSEMBLER_MACH_BINOP_LIST(BINOP_DECL)
     261             : #undef BINOP_DECL
     262             : 
     263             :   Node* Float64RoundDown(Node* value);
     264             : 
     265             :   Node* ToNumber(Node* value);
     266             :   Node* Allocate(PretenureFlag pretenure, Node* size);
     267             :   Node* LoadField(FieldAccess const&, Node* object);
     268             :   Node* LoadElement(ElementAccess const&, Node* object, Node* index);
     269             :   Node* StoreField(FieldAccess const&, Node* object, Node* value);
     270             :   Node* StoreElement(ElementAccess const&, Node* object, Node* index,
     271             :                      Node* value);
     272             : 
     273             :   Node* Store(StoreRepresentation rep, Node* object, Node* offset, Node* value);
     274             :   Node* Load(MachineType rep, Node* object, Node* offset);
     275             : 
     276             :   Node* Retain(Node* buffer);
     277             :   Node* UnsafePointerAdd(Node* base, Node* external);
     278             : 
     279             :   Node* DeoptimizeIf(DeoptimizeReason reason, Node* condition,
     280             :                      Node* frame_state);
     281             :   Node* DeoptimizeUnless(DeoptimizeKind kind, DeoptimizeReason reason,
     282             :                          Node* condition, Node* frame_state);
     283             :   Node* DeoptimizeUnless(DeoptimizeReason reason, Node* condition,
     284             :                          Node* frame_state);
     285             :   template <typename... Args>
     286             :   Node* Call(const CallDescriptor* desc, Args... args);
     287             :   template <typename... Args>
     288             :   Node* Call(const Operator* op, Args... args);
     289             : 
     290             :   // Basic control operations.
     291             :   template <class LabelType>
     292             :   void Bind(LabelType* label);
     293             : 
     294             :   template <class LabelType, typename... vars>
     295             :   void Goto(LabelType* label, vars...);
     296             : 
     297             :   void Branch(Node* condition, GraphAssemblerStaticLabel<1>* if_true,
     298             :               GraphAssemblerStaticLabel<1>* if_false);
     299             : 
     300             :   // Control helpers.
     301             :   // {GotoIf(c, l)} is equivalent to {Branch(c, l, templ);Bind(templ)}.
     302             :   template <class LabelType, typename... vars>
     303             :   void GotoIf(Node* condition, LabelType* label, vars...);
     304             : 
     305             :   // {GotoUnless(c, l)} is equivalent to {Branch(c, templ, l);Bind(templ)}.
     306             :   template <class LabelType, typename... vars>
     307             :   void GotoUnless(Node* condition, LabelType* label, vars...);
     308             : 
     309             :   // Extractors (should be only used when destructing/resetting the assembler).
     310             :   Node* ExtractCurrentControl();
     311             :   Node* ExtractCurrentEffect();
     312             : 
     313             :  private:
     314             :   template <class LabelType, typename... Vars>
     315             :   void MergeState(LabelType label, Vars... vars);
     316             : 
     317             :   Operator const* ToNumberOperator();
     318             : 
     319             :   JSGraph* jsgraph() const { return jsgraph_; }
     320     9371085 :   Graph* graph() const { return jsgraph_->graph(); }
     321             :   Zone* temp_zone() const { return temp_zone_; }
     322     4486990 :   CommonOperatorBuilder* common() const { return jsgraph()->common(); }
     323     4044584 :   MachineOperatorBuilder* machine() const { return jsgraph()->machine(); }
     324      716711 :   SimplifiedOperatorBuilder* simplified() const {
     325      716711 :     return jsgraph()->simplified();
     326             :   }
     327             : 
     328             :   SetOncePointer<Operator const> to_number_operator_;
     329             :   Zone* temp_zone_;
     330             :   JSGraph* jsgraph_;
     331             :   Node* current_effect_;
     332             :   Node* current_control_;
     333             : };
     334             : 
     335             : template <size_t MergeCount, size_t VarCount>
     336             : Node* GraphAssemblerStaticLabel<MergeCount, VarCount>::PhiAt(size_t index) {
     337             :   DCHECK(IsBound());
     338      538181 :   return GetBindingsPtrFor(index)[0];
     339             : }
     340             : 
     341             : template <class LabelType, typename... Vars>
     342     1955128 : void GraphAssembler::MergeState(LabelType label, Vars... vars) {
     343             :   DCHECK(!label->IsBound());
     344             :   size_t merged_count = label->MergedCount();
     345             :   DCHECK_LT(merged_count, label->MaxMergeCount());
     346             :   DCHECK_EQ(label->PhiCount(), sizeof...(vars));
     347     1959126 :   label->GetEffectsPtr()[merged_count] = current_effect_;
     348     1959126 :   label->GetControlsPtr()[merged_count] = current_control_;
     349             :   // We need to start with nullptr to avoid 0-length arrays.
     350     1177173 :   Node* var_array[] = {nullptr, vars...};
     351     3531518 :   for (size_t i = 0; i < sizeof...(vars); i++) {
     352     1177172 :     label->SetBinding(i, merged_count, var_array[i + 1]);
     353             :   }
     354             :   label->IncrementMergedCount();
     355     1300381 : }
     356             : 
     357             : template <class LabelType>
     358     2046843 : void GraphAssembler::Bind(LabelType* label) {
     359             :   DCHECK(current_control_ == nullptr);
     360             :   DCHECK(current_effect_ == nullptr);
     361             :   DCHECK(label->MaxMergeCount() > 0);
     362             :   DCHECK_EQ(label->MaxMergeCount(), label->MergedCount());
     363             : 
     364       93867 :   int merge_count = static_cast<int>(label->MaxMergeCount());
     365       93867 :   if (merge_count == 1) {
     366      595877 :     current_control_ = label->GetControlsPtr()[0];
     367      595877 :     current_effect_ = label->GetEffectsPtr()[0];
     368             :     label->SetBound();
     369      581549 :     return;
     370             :   }
     371             : 
     372     1549168 :   current_control_ = graph()->NewNode(common()->Merge(merge_count), merge_count,
     373             :                                       label->GetControlsPtr());
     374             : 
     375      516391 :   Node** effects = label->GetEffectsPtr();
     376      516390 :   current_effect_ = effects[0];
     377      727662 :   for (size_t i = 1; i < label->MaxMergeCount(); i++) {
     378      597199 :     if (current_effect_ != effects[i]) {
     379      441229 :       effects[label->MaxMergeCount()] = current_control_;
     380      441229 :       current_effect_ = graph()->NewNode(common()->EffectPhi(merge_count),
     381      885095 :                                          merge_count + 1, effects);
     382      441229 :       break;
     383             :     }
     384             :   }
     385             : 
     386      452375 :   for (size_t var = 0; var < label->PhiCount(); var++) {
     387      423670 :     Node** bindings = label->GetBindingsPtrFor(var);
     388      423670 :     bindings[label->MaxMergeCount()] = current_control_;
     389      847338 :     bindings[0] = graph()->NewNode(
     390             :         common()->Phi(label->GetRepresentationFor(var), merge_count),
     391             :         merge_count + 1, bindings);
     392             :   }
     393             : 
     394             :   label->SetBound();
     395             : }
     396             : 
     397             : template <class LabelType, typename... Vars>
     398             : void GraphAssembler::Goto(LabelType* label, Vars... vars) {
     399             :   DCHECK_NOT_NULL(current_control_);
     400             :   DCHECK_NOT_NULL(current_effect_);
     401     1019493 :   MergeState(label, vars...);
     402     1112268 :   current_control_ = nullptr;
     403     1112268 :   current_effect_ = nullptr;
     404             : }
     405             : 
     406             : template <class LabelType, typename... Vars>
     407     2330945 : void GraphAssembler::GotoIf(Node* condition, LabelType* label, Vars... vars) {
     408             :   BranchHint hint =
     409      582736 :       label->IsDeferred() ? BranchHint::kFalse : BranchHint::kNone;
     410             :   Node* branch =
     411     1165472 :       graph()->NewNode(common()->Branch(hint), condition, current_control_);
     412             : 
     413     1165475 :   current_control_ = graph()->NewNode(common()->IfTrue(), branch);
     414      198648 :   MergeState(label, vars...);
     415             : 
     416     1165474 :   current_control_ = graph()->NewNode(common()->IfFalse(), branch);
     417      582737 : }
     418             : 
     419             : template <class LabelType, typename... Vars>
     420      264120 : void GraphAssembler::GotoUnless(Node* condition, LabelType* label,
     421      792366 :                                 Vars... vars) {
     422      264120 :   BranchHint hint = label->IsDeferred() ? BranchHint::kTrue : BranchHint::kNone;
     423             :   Node* branch =
     424      528240 :       graph()->NewNode(common()->Branch(hint), condition, current_control_);
     425             : 
     426      528246 :   current_control_ = graph()->NewNode(common()->IfFalse(), branch);
     427       82240 :   MergeState(label, vars...);
     428             : 
     429      528246 :   current_control_ = graph()->NewNode(common()->IfTrue(), branch);
     430      264123 : }
     431             : 
     432             : template <typename... Args>
     433       11265 : Node* GraphAssembler::Call(const CallDescriptor* desc, Args... args) {
     434       11265 :   const Operator* op = common()->Call(desc);
     435       11265 :   return Call(op, args...);
     436             : }
     437             : 
     438             : template <typename... Args>
     439      503104 : Node* GraphAssembler::Call(const Operator* op, Args... args) {
     440             :   DCHECK_EQ(IrOpcode::kCall, op->opcode());
     441      125776 :   Node* args_array[] = {args..., current_effect_, current_control_};
     442             :   int size = static_cast<int>(sizeof...(args)) + op->EffectInputCount() +
     443      251552 :              op->ControlInputCount();
     444      125776 :   Node* call = graph()->NewNode(op, size, args_array);
     445             :   DCHECK_EQ(0, op->ControlOutputCount());
     446      125777 :   current_effect_ = call;
     447      125777 :   return call;
     448             : }
     449             : 
     450             : }  // namespace compiler
     451             : }  // namespace internal
     452             : }  // namespace v8
     453             : 
     454             : #endif  // V8_COMPILER_GRAPH_ASSEMBLER_H_

Generated by: LCOV version 1.10