1// Copyright 2013 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_H_
6#define V8_COMPILER_GRAPH_H_
7
8#include "src/zone.h"
9#include "src/zone-containers.h"
10
11namespace v8 {
12namespace internal {
13namespace compiler {
14
15// Forward declarations.
16class GraphDecorator;
17class Node;
18class Operator;
19
20
21// Marks are used during traversal of the graph to distinguish states of nodes.
22// Each node has a mark which is a monotonically increasing integer, and a
23// {NodeMarker} has a range of values that indicate states of a node.
24typedef uint32_t Mark;
25
26
27// NodeIds are identifying numbers for nodes that can be used to index auxiliary
28// out-of-line data associated with each node.
29typedef uint32_t NodeId;
30
31class Graph final : public ZoneObject {
32 public:
33  explicit Graph(Zone* zone);
34
35  // Scope used when creating a subgraph for inlining. Automatically preserves
36  // the original start and end nodes of the graph, and resets them when you
37  // leave the scope.
38  class SubgraphScope final {
39   public:
40    explicit SubgraphScope(Graph* graph)
41        : graph_(graph), start_(graph->start()), end_(graph->end()) {}
42    ~SubgraphScope() {
43      graph_->SetStart(start_);
44      graph_->SetEnd(end_);
45    }
46
47   private:
48    Graph* const graph_;
49    Node* const start_;
50    Node* const end_;
51
52    DISALLOW_COPY_AND_ASSIGN(SubgraphScope);
53  };
54
55  // Base implementation used by all factory methods.
56  Node* NewNodeUnchecked(const Operator* op, int input_count,
57                         Node* const* inputs, bool incomplete = false);
58
59  // Factory that checks the input count.
60  Node* NewNode(const Operator* op, int input_count, Node* const* inputs,
61                bool incomplete = false);
62
63  // Factories for nodes with static input counts.
64  Node* NewNode(const Operator* op) {
65    return NewNode(op, 0, static_cast<Node* const*>(nullptr));
66  }
67  Node* NewNode(const Operator* op, Node* n1) { return NewNode(op, 1, &n1); }
68  Node* NewNode(const Operator* op, Node* n1, Node* n2) {
69    Node* nodes[] = {n1, n2};
70    return NewNode(op, arraysize(nodes), nodes);
71  }
72  Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3) {
73    Node* nodes[] = {n1, n2, n3};
74    return NewNode(op, arraysize(nodes), nodes);
75  }
76  Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4) {
77    Node* nodes[] = {n1, n2, n3, n4};
78    return NewNode(op, arraysize(nodes), nodes);
79  }
80  Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
81                Node* n5) {
82    Node* nodes[] = {n1, n2, n3, n4, n5};
83    return NewNode(op, arraysize(nodes), nodes);
84  }
85  Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
86                Node* n5, Node* n6) {
87    Node* nodes[] = {n1, n2, n3, n4, n5, n6};
88    return NewNode(op, arraysize(nodes), nodes);
89  }
90  Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
91                Node* n5, Node* n6, Node* n7) {
92    Node* nodes[] = {n1, n2, n3, n4, n5, n6, n7};
93    return NewNode(op, arraysize(nodes), nodes);
94  }
95  Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
96                Node* n5, Node* n6, Node* n7, Node* n8) {
97    Node* nodes[] = {n1, n2, n3, n4, n5, n6, n7, n8};
98    return NewNode(op, arraysize(nodes), nodes);
99  }
100  Node* NewNode(const Operator* op, Node* n1, Node* n2, Node* n3, Node* n4,
101                Node* n5, Node* n6, Node* n7, Node* n8, Node* n9) {
102    Node* nodes[] = {n1, n2, n3, n4, n5, n6, n7, n8, n9};
103    return NewNode(op, arraysize(nodes), nodes);
104  }
105
106  // Clone the {node}, and assign a new node id to the copy.
107  Node* CloneNode(const Node* node);
108
109  Zone* zone() const { return zone_; }
110  Node* start() const { return start_; }
111  Node* end() const { return end_; }
112
113  void SetStart(Node* start) { start_ = start; }
114  void SetEnd(Node* end) { end_ = end; }
115
116  size_t NodeCount() const { return next_node_id_; }
117
118  void Decorate(Node* node);
119  void AddDecorator(GraphDecorator* decorator);
120  void RemoveDecorator(GraphDecorator* decorator);
121
122 private:
123  friend class NodeMarkerBase;
124
125  inline NodeId NextNodeId();
126
127  Zone* const zone_;
128  Node* start_;
129  Node* end_;
130  Mark mark_max_;
131  NodeId next_node_id_;
132  ZoneVector<GraphDecorator*> decorators_;
133
134  DISALLOW_COPY_AND_ASSIGN(Graph);
135};
136
137
138// A graph decorator can be used to add behavior to the creation of nodes
139// in a graph.
140class GraphDecorator : public ZoneObject {
141 public:
142  virtual ~GraphDecorator() {}
143  virtual void Decorate(Node* node) = 0;
144};
145
146}  // namespace compiler
147}  // namespace internal
148}  // namespace v8
149
150#endif  // V8_COMPILER_GRAPH_H_
151