node.h 16 KB
Newer Older
1 2 3 4 5 6 7 8 9
// Copyright 2013 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_COMPILER_NODE_H_
#define V8_COMPILER_NODE_H_

#include "src/compiler/opcodes.h"
#include "src/compiler/operator.h"
10
#include "src/types.h"
11
#include "src/zone-containers.h"
12 13 14 15 16

namespace v8 {
namespace internal {
namespace compiler {

17
// Forward declarations.
danno's avatar
danno committed
18
class Edge;
19 20
class Graph;

21

22 23 24 25 26
// Marks are used during traversal of the graph to distinguish states of nodes.
// Each node has a mark which is a monotonically increasing integer, and a
// {NodeMarker} has a range of values that indicate states of a node.
typedef uint32_t Mark;

27

28 29
// NodeIds are identifying numbers for nodes that can be used to index auxiliary
// out-of-line data associated with each node.
30
typedef uint32_t NodeId;
31

32

33 34 35 36 37 38 39 40 41
// A Node is the basic primitive of graphs. Nodes are chained together by
// input/use chains but by default otherwise contain only an identifying number
// which specific applications of graphs and nodes can use to index auxiliary
// out-of-line data, especially transient data.
//
// In addition Nodes only contain a mutable Operator that may change during
// compilation, e.g. during lowering passes. Other information that needs to be
// associated with Nodes during compilation must be stored out-of-line indexed
// by the Node's id.
42
class Node final {
43
 public:
44
  static Node* New(Zone* zone, NodeId id, const Operator* op, int input_count,
45 46
                   Node* const* inputs, bool has_extensible_inputs);
  static Node* Clone(Zone* zone, NodeId id, const Node* node);
47

48 49
  bool IsDead() const { return InputCount() > 0 && !InputAt(0); }
  void Kill();
50

51 52 53 54 55 56 57
  const Operator* op() const { return op_; }

  IrOpcode::Value opcode() const {
    DCHECK(op_->opcode() <= IrOpcode::kLast);
    return static_cast<IrOpcode::Value>(op_->opcode());
  }

58 59 60 61 62 63
  NodeId id() const { return IdField::decode(bit_field_); }

  int InputCount() const {
    return has_inline_inputs() ? InlineCountField::decode(bit_field_)
                               : inputs_.outline_->count_;
  }
64

65
#if DEBUG
66 67 68 69 70 71 72 73 74 75 76 77 78 79
  void Verify();
#define BOUNDS_CHECK(index)                                                  \
  do {                                                                       \
    if (index < 0 || index >= InputCount()) {                                \
      V8_Fatal(__FILE__, __LINE__, "Node #%d:%s->InputAt(%d) out of bounds", \
               id(), op()->mnemonic(), index);                               \
    }                                                                        \
  } while (false)
#else
  // No bounds checks or verification in release mode.
  inline void Verify() {}
#define BOUNDS_CHECK(index) \
  do {                      \
  } while (false)
80
#endif
81 82 83 84

  Node* InputAt(int index) const {
    BOUNDS_CHECK(index);
    return *GetInputPtrConst(index);
85
  }
86 87 88 89 90 91 92 93 94 95 96 97 98 99 100

  void ReplaceInput(int index, Node* new_to) {
    BOUNDS_CHECK(index);
    Node** input_ptr = GetInputPtr(index);
    Node* old_to = *input_ptr;
    if (old_to != new_to) {
      Use* use = GetUsePtr(index);
      if (old_to) old_to->RemoveUse(use);
      *input_ptr = new_to;
      if (new_to) new_to->AppendUse(use);
    }
  }

#undef BOUNDS_CHECK

101 102 103
  void AppendInput(Zone* zone, Node* new_to);
  void InsertInput(Zone* zone, int index, Node* new_to);
  void RemoveInput(int index);
104
  void NullAllInputs();
105
  void TrimInputCount(int new_input_count);
106

107
  int UseCount() const;
108
  void ReplaceUses(Node* replace_to);
109

110
  class InputEdges final {
danno's avatar
danno committed
111
   public:
112 113
    typedef Edge value_type;

danno's avatar
danno committed
114
    class iterator;
115 116 117
    inline iterator begin() const;
    inline iterator end() const;

danno's avatar
danno committed
118 119 120 121 122 123 124 125
    bool empty() const;

    explicit InputEdges(Node* node) : node_(node) {}

   private:
    Node* node_;
  };

126 127
  InputEdges input_edges() { return InputEdges(this); }

128
  class Inputs final {
129
   public:
130 131 132 133 134 135
    typedef Node* value_type;

    class const_iterator;
    inline const_iterator begin() const;
    inline const_iterator end() const;

danno's avatar
danno committed
136
    bool empty() const;
137 138 139 140 141 142 143 144

    explicit Inputs(Node* node) : node_(node) {}

   private:
    Node* node_;
  };

  Inputs inputs() { return Inputs(this); }
danno's avatar
danno committed
145

146
  class UseEdges final {
danno's avatar
danno committed
147
   public:
148 149
    typedef Edge value_type;

danno's avatar
danno committed
150
    class iterator;
151 152 153
    inline iterator begin() const;
    inline iterator end() const;

danno's avatar
danno committed
154 155 156 157 158 159 160
    bool empty() const;

    explicit UseEdges(Node* node) : node_(node) {}

   private:
    Node* node_;
  };
161

162 163
  UseEdges use_edges() { return UseEdges(this); }

164
  class Uses final {
165
   public:
166 167 168 169 170 171
    typedef Node* value_type;

    class const_iterator;
    inline const_iterator begin() const;
    inline const_iterator end() const;

danno's avatar
danno committed
172
    bool empty() const;
173 174 175 176 177 178 179 180 181

    explicit Uses(Node* node) : node_(node) {}

   private:
    Node* node_;
  };

  Uses uses() { return Uses(this); }

182 183
  // Returns true if {owner} is the user of {this} node.
  bool OwnedBy(Node* owner) const {
184
    return first_use_ && first_use_->from() == owner && !first_use_->next;
185
  }
186

187 188
  // Returns true if {owner1} and {owner2} are the only users of {this} node.
  bool OwnedBy(Node const* owner1, Node const* owner2) const;
189
  void Print() const;
190

191
 private:
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
  struct Use;
  // Out of line storage for inputs when the number of inputs overflowed the
  // capacity of the inline-allocated space.
  struct OutOfLineInputs {
    Node* node_;
    int count_;
    int capacity_;
    Node* inputs_[1];

    static OutOfLineInputs* New(Zone* zone, int capacity);
    void ExtractFrom(Use* use_ptr, Node** input_ptr, int count);
  };

  // A link in the use chain for a node. Every input {i} to a node {n} has an
  // associated {Use} which is linked into the use chain of the {i} node.
  struct Use {
208 209
    Use* next;
    Use* prev;
210 211 212 213 214 215 216 217 218 219 220 221
    uint32_t bit_field_;

    int input_index() const { return InputIndexField::decode(bit_field_); }
    bool is_inline_use() const { return InlineField::decode(bit_field_); }
    Node** input_ptr() {
      int index = input_index();
      Use* start = this + 1 + index;
      Node** inputs = is_inline_use()
                          ? reinterpret_cast<Node*>(start)->inputs_.inline_
                          : reinterpret_cast<OutOfLineInputs*>(start)->inputs_;
      return &inputs[index];
    }
222

223 224 225 226 227
    Node* from() {
      Use* start = this + 1 + input_index();
      return is_inline_use() ? reinterpret_cast<Node*>(start)
                             : reinterpret_cast<OutOfLineInputs*>(start)->node_;
    }
228

229 230
    typedef BitField<bool, 0, 1> InlineField;
    typedef BitField<unsigned, 1, 17> InputIndexField;
231 232
    // Leaving some space in the bitset in case we ever decide to record
    // the output index.
233 234
  };

235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
  //============================================================================
  //== Memory layout ===========================================================
  //============================================================================
  // Saving space for big graphs is important. We use a memory layout trick to
  // be able to map {Node} objects to {Use} objects and vice-versa in a
  // space-efficient manner.
  //
  // {Use} links are laid out in memory directly before a {Node}, followed by
  // direct pointers to input {Nodes}.
  //
  // inline case:
  // |Use #N  |Use #N-1|...|Use #1  |Use #0  |Node xxxx |I#0|I#1|...|I#N-1|I#N|
  //          ^                              ^                  ^
  //          + Use                          + Node             + Input
  //
  // Since every {Use} instance records its {input_index}, pointer arithmetic
  // can compute the {Node}.
  //
  // out-of-line case:
  //     |Node xxxx |
  //     ^       + outline ------------------+
  //     +----------------------------------------+
  //                                         |    |
  //                                         v    | node
  // |Use #N  |Use #N-1|...|Use #1  |Use #0  |OOL xxxxx |I#0|I#1|...|I#N-1|I#N|
  //          ^                                                 ^
  //          + Use                                             + Input
  //
  // Out-of-line storage of input lists is needed if appending an input to
  // a node exceeds the maximum inline capacity.

  Node(NodeId id, const Operator* op, int inline_count, int inline_capacity);

  Node* const* GetInputPtrConst(int input_index) const {
    return has_inline_inputs() ? &(inputs_.inline_[input_index])
                               : &inputs_.outline_->inputs_[input_index];
271
  }
272 273 274 275 276 277 278 279
  Node** GetInputPtr(int input_index) {
    return has_inline_inputs() ? &(inputs_.inline_[input_index])
                               : &inputs_.outline_->inputs_[input_index];
  }
  Use* GetUsePtr(int input_index) {
    Use* ptr = has_inline_inputs() ? reinterpret_cast<Use*>(this)
                                   : reinterpret_cast<Use*>(inputs_.outline_);
    return &ptr[-1 - input_index];
280 281
  }

282 283
  void AppendUse(Use* use);
  void RemoveUse(Use* use);
284 285 286

  void* operator new(size_t, void* location) { return location; }

287 288 289
  // Only NodeProperties should manipulate the op.
  void set_op(const Operator* op) { op_ = op; }

290 291 292
  // Only NodeProperties should manipulate the type.
  Type* type() const { return type_; }
  void set_type(Type* type) { type_ = type; }
293 294 295 296 297

  // Only NodeMarkers should manipulate the marks on nodes.
  Mark mark() { return mark_; }
  void set_mark(Mark mark) { mark_ = mark; }

298 299
  inline bool has_inline_inputs() const {
    return InlineCountField::decode(bit_field_) != kOutlineMarker;
300 301
  }

302
  void ClearInputs(int start, int count);
303

304 305 306 307 308 309
  typedef BitField<NodeId, 0, 24> IdField;
  typedef BitField<unsigned, 24, 4> InlineCountField;
  typedef BitField<unsigned, 28, 4> InlineCapacityField;
  static const int kOutlineMarker = InlineCountField::kMax;
  static const int kMaxInlineCount = InlineCountField::kMax - 1;
  static const int kMaxInlineCapacity = InlineCapacityField::kMax - 1;
310

311
  const Operator* op_;
312
  Type* type_;
313
  Mark mark_;
314
  uint32_t bit_field_;
315
  Use* first_use_;
316
  union {
317 318 319
    // Inline storage for inputs or out-of-line storage.
    Node* inline_[1];
    OutOfLineInputs* outline_;
320 321
  } inputs_;

322 323 324 325
  friend class Edge;
  friend class NodeMarkerBase;
  friend class NodeProperties;

326 327 328
  DISALLOW_COPY_AND_ASSIGN(Node);
};

329

330 331 332 333 334
std::ostream& operator<<(std::ostream& os, const Node& n);


// Typedefs to shorten commonly used Node containers.
typedef ZoneDeque<Node*> NodeDeque;
335
typedef ZoneSet<Node*> NodeSet;
336 337 338 339 340 341 342 343 344 345 346
typedef ZoneVector<Node*> NodeVector;
typedef ZoneVector<NodeVector> NodeVectorVector;


// Helper to extract parameters from Operator1<*> nodes.
template <typename T>
static inline const T& OpParameter(const Node* node) {
  return OpParameter<T>(node->op());
}


347 348
// An encapsulation for information associated with a single use of node as a
// input from another node, allowing access to both the defining node and
danno's avatar
danno committed
349
// the node having the input.
350
class Edge final {
351
 public:
352 353
  Node* from() const { return use_->from(); }
  Node* to() const { return *input_ptr_; }
354
  int index() const {
355 356
    int const index = use_->input_index();
    DCHECK_LT(index, use_->from()->InputCount());
357 358 359
    return index;
  }

360
  bool operator==(const Edge& other) { return input_ptr_ == other.input_ptr_; }
danno's avatar
danno committed
361 362
  bool operator!=(const Edge& other) { return !(*this == other); }

363 364 365 366 367 368 369 370
  void UpdateTo(Node* new_to) {
    Node* old_to = *input_ptr_;
    if (old_to != new_to) {
      if (old_to) old_to->RemoveUse(use_);
      *input_ptr_ = new_to;
      if (new_to) new_to->AppendUse(use_);
    }
  }
danno's avatar
danno committed
371

372
 private:
danno's avatar
danno committed
373 374
  friend class Node::UseEdges::iterator;
  friend class Node::InputEdges::iterator;
375

376 377 378 379 380
  Edge(Node::Use* use, Node** input_ptr) : use_(use), input_ptr_(input_ptr) {
    DCHECK_NOT_NULL(use);
    DCHECK_NOT_NULL(input_ptr);
    DCHECK_EQ(input_ptr, use->input_ptr());
  }
381

382 383
  Node::Use* use_;
  Node** input_ptr_;
384 385
};

386

387
// A forward iterator to visit the edges for the input dependencies of a node.
388
class Node::InputEdges::iterator final {
danno's avatar
danno committed
389 390 391 392 393 394
 public:
  typedef std::forward_iterator_tag iterator_category;
  typedef int difference_type;
  typedef Edge value_type;
  typedef Edge* pointer;
  typedef Edge& reference;
395

396 397 398
  iterator() : use_(nullptr), input_ptr_(nullptr) {}
  iterator(const iterator& other)
      : use_(other.use_), input_ptr_(other.input_ptr_) {}
danno's avatar
danno committed
399

400
  Edge operator*() const { return Edge(use_, input_ptr_); }
401
  bool operator==(const iterator& other) const {
402
    return input_ptr_ == other.input_ptr_;
403 404
  }
  bool operator!=(const iterator& other) const { return !(*this == other); }
danno's avatar
danno committed
405
  iterator& operator++() {
406 407
    input_ptr_++;
    use_--;
danno's avatar
danno committed
408 409
    return *this;
  }
410
  iterator operator++(int);
danno's avatar
danno committed
411 412 413 414

 private:
  friend class Node;

415 416
  explicit iterator(Node* from, int index = 0)
      : use_(from->GetUsePtr(index)), input_ptr_(from->GetInputPtr(index)) {}
danno's avatar
danno committed
417

418 419
  Use* use_;
  Node** input_ptr_;
danno's avatar
danno committed
420 421 422
};


423 424 425 426 427 428 429 430 431 432
Node::InputEdges::iterator Node::InputEdges::begin() const {
  return Node::InputEdges::iterator(this->node_, 0);
}


Node::InputEdges::iterator Node::InputEdges::end() const {
  return Node::InputEdges::iterator(this->node_, this->node_->InputCount());
}


danno's avatar
danno committed
433
// A forward iterator to visit the inputs of a node.
434
class Node::Inputs::const_iterator final {
435
 public:
danno's avatar
danno committed
436 437 438 439 440 441
  typedef std::forward_iterator_tag iterator_category;
  typedef int difference_type;
  typedef Node* value_type;
  typedef Node** pointer;
  typedef Node*& reference;

442
  const_iterator(const const_iterator& other) : iter_(other.iter_) {}
443

danno's avatar
danno committed
444
  Node* operator*() const { return (*iter_).to(); }
445 446 447 448 449 450 451
  bool operator==(const const_iterator& other) const {
    return iter_ == other.iter_;
  }
  bool operator!=(const const_iterator& other) const {
    return !(*this == other);
  }
  const_iterator& operator++() {
danno's avatar
danno committed
452
    ++iter_;
453 454
    return *this;
  }
455
  const_iterator operator++(int);
danno's avatar
danno committed
456 457 458 459

 private:
  friend class Node::Inputs;

460
  const_iterator(Node* node, int index) : iter_(node, index) {}
danno's avatar
danno committed
461 462 463 464

  Node::InputEdges::iterator iter_;
};

465 466 467 468 469 470 471 472 473 474 475

Node::Inputs::const_iterator Node::Inputs::begin() const {
  return const_iterator(this->node_, 0);
}


Node::Inputs::const_iterator Node::Inputs::end() const {
  return const_iterator(this->node_, this->node_->InputCount());
}


476
// A forward iterator to visit the uses edges of a node.
477
class Node::UseEdges::iterator final {
danno's avatar
danno committed
478
 public:
479 480
  iterator(const iterator& other)
      : current_(other.current_), next_(other.next_) {}
danno's avatar
danno committed
481

482
  Edge operator*() const { return Edge(current_, current_->input_ptr()); }
483 484 485 486
  bool operator==(const iterator& other) const {
    return current_ == other.current_;
  }
  bool operator!=(const iterator& other) const { return !(*this == other); }
danno's avatar
danno committed
487
  iterator& operator++() {
488
    DCHECK_NOT_NULL(current_);
danno's avatar
danno committed
489
    current_ = next_;
490
    next_ = current_ ? current_->next : nullptr;
491 492
    return *this;
  }
493
  iterator operator++(int);
494 495

 private:
danno's avatar
danno committed
496 497
  friend class Node::UseEdges;

498
  iterator() : current_(nullptr), next_(nullptr) {}
danno's avatar
danno committed
499 500
  explicit iterator(Node* node)
      : current_(node->first_use_),
501
        next_(current_ ? current_->next : nullptr) {}
502

danno's avatar
danno committed
503 504
  Node::Use* current_;
  Node::Use* next_;
505 506
};

507

508
Node::UseEdges::iterator Node::UseEdges::begin() const {
danno's avatar
danno committed
509 510 511 512
  return Node::UseEdges::iterator(this->node_);
}


513 514
Node::UseEdges::iterator Node::UseEdges::end() const {
  return Node::UseEdges::iterator();
515 516 517
}


518
// A forward iterator to visit the uses of a node.
519
class Node::Uses::const_iterator final {
520 521 522 523 524 525
 public:
  typedef std::forward_iterator_tag iterator_category;
  typedef int difference_type;
  typedef Node* value_type;
  typedef Node** pointer;
  typedef Node*& reference;
526

527
  const_iterator(const const_iterator& other) : current_(other.current_) {}
528

529
  Node* operator*() const { return current_->from(); }
530 531
  bool operator==(const const_iterator& other) const {
    return other.current_ == current_;
532
  }
533 534
  bool operator!=(const const_iterator& other) const {
    return other.current_ != current_;
535
  }
536 537 538 539
  const_iterator& operator++() {
    DCHECK_NOT_NULL(current_);
    current_ = current_->next;
    return *this;
540
  }
541
  const_iterator operator++(int);
542

543 544
 private:
  friend class Node::Uses;
545

546 547
  const_iterator() : current_(nullptr) {}
  explicit const_iterator(Node* node) : current_(node->first_use_) {}
548

549 550
  Node::Use* current_;
};
551 552


553 554
Node::Uses::const_iterator Node::Uses::begin() const {
  return const_iterator(this->node_);
555 556 557
}


558
Node::Uses::const_iterator Node::Uses::end() const { return const_iterator(); }
559

560 561 562
}  // namespace compiler
}  // namespace internal
}  // namespace v8
563 564

#endif  // V8_COMPILER_NODE_H_