V8 API Reference, 7.2.502.16 (for Deno 0.2.4)
escape-analysis.h
1 // Copyright 2017 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_ESCAPE_ANALYSIS_H_
6 #define V8_COMPILER_ESCAPE_ANALYSIS_H_
7 
8 #include "src/base/functional.h"
9 #include "src/compiler/graph-reducer.h"
10 #include "src/compiler/js-graph.h"
11 #include "src/compiler/persistent-map.h"
12 #include "src/globals.h"
13 #include "src/objects/name.h"
14 
15 namespace v8 {
16 namespace internal {
17 namespace compiler {
18 
19 class CommonOperatorBuilder;
20 class VariableTracker;
21 class EscapeAnalysisTracker;
22 
23 // {EffectGraphReducer} reduces up to a fixed point. It distinguishes changes to
24 // the effect output of a node from changes to the value output to reduce the
25 // number of revisitations.
27  public:
28  class Reduction {
29  public:
30  bool value_changed() const { return value_changed_; }
31  void set_value_changed() { value_changed_ = true; }
32  bool effect_changed() const { return effect_changed_; }
33  void set_effect_changed() { effect_changed_ = true; }
34 
35  private:
36  bool value_changed_ = false;
37  bool effect_changed_ = false;
38  };
39 
41  std::function<void(Node*, Reduction*)> reduce, Zone* zone);
42 
43  void ReduceGraph() { ReduceFrom(graph_->end()); }
44 
45  // Mark node for revisitation.
46  void Revisit(Node* node);
47 
48  // Add a new root node to start reduction from. This is useful if the reducer
49  // adds nodes that are not yet reachable, but should already be considered
50  // part of the graph.
51  void AddRoot(Node* node) {
52  DCHECK_EQ(State::kUnvisited, state_.Get(node));
53  state_.Set(node, State::kRevisit);
54  revisit_.push(node);
55  }
56 
57  bool Complete() { return stack_.empty() && revisit_.empty(); }
58 
59  private:
60  struct NodeState {
61  Node* node;
62  int input_index;
63  };
64  void ReduceFrom(Node* node);
65  enum class State : uint8_t { kUnvisited = 0, kRevisit, kOnStack, kVisited };
66  const uint8_t kNumStates = static_cast<uint8_t>(State::kVisited) + 1;
67  Graph* graph_;
68  NodeMarker<State> state_;
69  ZoneStack<Node*> revisit_;
70  ZoneStack<NodeState> stack_;
71  std::function<void(Node*, Reduction*)> reduce_;
72 };
73 
74 // A variable is an abstract storage location, which is lowered to SSA values
75 // and phi nodes by {VariableTracker}.
76 class Variable {
77  public:
78  Variable() : id_(kInvalid) {}
79  bool operator==(Variable other) const { return id_ == other.id_; }
80  bool operator!=(Variable other) const { return id_ != other.id_; }
81  bool operator<(Variable other) const { return id_ < other.id_; }
82  static Variable Invalid() { return Variable(kInvalid); }
83  friend V8_INLINE size_t hash_value(Variable v) {
84  return base::hash_value(v.id_);
85  }
86  friend std::ostream& operator<<(std::ostream& os, Variable var) {
87  return os << var.id_;
88  }
89 
90  private:
91  typedef int Id;
92  explicit Variable(Id id) : id_(id) {}
93  Id id_;
94  static const Id kInvalid = -1;
95 
96  friend class VariableTracker;
97 };
98 
99 // An object that can track the nodes in the graph whose current reduction
100 // depends on the value of the object.
101 class Dependable : public ZoneObject {
102  public:
103  explicit Dependable(Zone* zone) : dependants_(zone) {}
104  void AddDependency(Node* node) { dependants_.push_back(node); }
105  void RevisitDependants(EffectGraphReducer* reducer) {
106  for (Node* node : dependants_) {
107  reducer->Revisit(node);
108  }
109  dependants_.clear();
110  }
111 
112  private:
113  ZoneVector<Node*> dependants_;
114 };
115 
116 // A virtual object represents an allocation site and tracks the Variables
117 // associated with its fields as well as its global escape status.
118 class VirtualObject : public Dependable {
119  public:
120  typedef uint32_t Id;
121  typedef ZoneVector<Variable>::const_iterator const_iterator;
122  VirtualObject(VariableTracker* var_states, Id id, int size);
123  Maybe<Variable> FieldAt(int offset) const {
124  CHECK_EQ(0, offset % kPointerSize);
125  CHECK(!HasEscaped());
126  if (offset >= size()) {
127  // TODO(tebbi): Reading out-of-bounds can only happen in unreachable
128  // code. In this case, we have to mark the object as escaping to avoid
129  // dead nodes in the graph. This is a workaround that should be removed
130  // once we can handle dead nodes everywhere.
131  return Nothing<Variable>();
132  }
133  return Just(fields_.at(offset / kPointerSize));
134  }
135  Id id() const { return id_; }
136  int size() const { return static_cast<int>(kPointerSize * fields_.size()); }
137  // Escaped might mean that the object escaped to untracked memory or that it
138  // is used in an operation that requires materialization.
139  void SetEscaped() { escaped_ = true; }
140  bool HasEscaped() const { return escaped_; }
141  const_iterator begin() const { return fields_.begin(); }
142  const_iterator end() const { return fields_.end(); }
143 
144  private:
145  bool escaped_ = false;
146  Id id_;
147  ZoneVector<Variable> fields_;
148 };
149 
151  public:
153  : tracker_(tracker) {}
154 
155  const VirtualObject* GetVirtualObject(Node* node);
156  Node* GetVirtualObjectField(const VirtualObject* vobject, int field,
157  Node* effect);
158  Node* GetReplacementOf(Node* node);
159 
160  private:
161  EscapeAnalysisTracker* tracker_;
162 };
163 
164 class V8_EXPORT_PRIVATE EscapeAnalysis final
165  : public NON_EXPORTED_BASE(EffectGraphReducer) {
166  public:
167  EscapeAnalysis(JSGraph* jsgraph, Zone* zone);
168 
169  EscapeAnalysisResult analysis_result() {
170  DCHECK(Complete());
171  return EscapeAnalysisResult(tracker_);
172  }
173 
174  private:
175  void Reduce(Node* node, Reduction* reduction);
176  JSGraph* jsgraph() { return jsgraph_; }
177  Isolate* isolate() const { return jsgraph_->isolate(); }
178  EscapeAnalysisTracker* tracker_;
179  JSGraph* jsgraph_;
180 };
181 
182 } // namespace compiler
183 } // namespace internal
184 } // namespace v8
185 
186 #endif // V8_COMPILER_ESCAPE_ANALYSIS_H_
Definition: v8.h:56
Definition: libplatform.h:13