v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
escape-analysis.h
Go to the documentation of this file.
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/hashing.h"
13#include "src/objects/name.h"
14
15namespace v8 {
16namespace internal {
17
18class TickCounter;
19
20namespace compiler {
21
22class CommonOperatorBuilder;
23class VariableTracker;
24class EscapeAnalysisTracker;
25
26// {EffectGraphReducer} reduces up to a fixed point. It distinguishes changes to
27// the effect output of a node from changes to the value output to reduce the
28// number of revisitations.
30 public:
31 class Reduction {
32 public:
33 bool value_changed() const { return value_changed_; }
35 bool effect_changed() const { return effect_changed_; }
37
38 private:
39 bool value_changed_ = false;
40 bool effect_changed_ = false;
41 };
42
44 std::function<void(Node*, Reduction*)> reduce,
46
48
49 // Mark node for revisitation.
50 void Revisit(Node* node);
51
52 // Add a new root node to start reduction from. This is useful if the reducer
53 // adds nodes that are not yet reachable, but should already be considered
54 // part of the graph.
55 void AddRoot(Node* node) {
57 state_.Set(node, State::kRevisit);
58 revisit_.push(node);
59 }
60
61 bool Complete() { return stack_.empty() && revisit_.empty(); }
62
64
65 private:
66 struct NodeState {
69 };
70 void ReduceFrom(Node* node);
71 enum class State : uint8_t { kUnvisited = 0, kRevisit, kOnStack, kVisited };
72 const uint8_t kNumStates = static_cast<uint8_t>(State::kVisited) + 1;
77 std::function<void(Node*, Reduction*)> reduce_;
79};
80
81// A variable is an abstract storage location, which is lowered to SSA values
82// and phi nodes by {VariableTracker}.
83class Variable {
84 public:
86 bool operator==(Variable other) const { return id_ == other.id_; }
87 bool operator!=(Variable other) const { return id_ != other.id_; }
88 bool operator<(Variable other) const { return id_ < other.id_; }
89 static Variable Invalid() { return Variable(kInvalid); }
90 friend V8_INLINE size_t hash_value(Variable v) {
91 return base::hash_value(v.id_);
92 }
93 friend std::ostream& operator<<(std::ostream& os, Variable var) {
94 return os << var.id_;
95 }
96
97 private:
98 using Id = int;
99 explicit Variable(Id id) : id_(id) {}
101 static const Id kInvalid = -1;
102
103 friend class VariableTracker;
104};
105
106// An object that can track the nodes in the graph whose current reduction
107// depends on the value of the object.
108class Dependable : public ZoneObject {
109 public:
110 explicit Dependable(Zone* zone) : dependants_(zone) {}
113 for (Node* node : dependants_) {
114 reducer->Revisit(node);
115 }
117 }
118
119 private:
121};
122
123// A virtual object represents an allocation site and tracks the Variables
124// associated with its fields as well as its global escape status.
125class VirtualObject : public Dependable {
126 public:
127 using Id = uint32_t;
129 VirtualObject(VariableTracker* var_states, Id id, int size);
132 CHECK(!HasEscaped());
133 if (offset >= size()) {
134 // TODO(turbofan): Reading out-of-bounds can only happen in unreachable
135 // code. In this case, we have to mark the object as escaping to avoid
136 // dead nodes in the graph. This is a workaround that should be removed
137 // once we can handle dead nodes everywhere.
138 return Nothing<Variable>();
139 }
140 return Just(fields_.at(offset / kTaggedSize));
141 }
142 Maybe<Variable> FieldAt(Maybe<int> maybe_offset) const {
143 int offset;
144 if (!maybe_offset.To(&offset)) return Nothing<Variable>();
145 return FieldAt(offset);
146 }
147 Id id() const { return id_; }
148 int size() const { return static_cast<int>(kTaggedSize * fields_.size()); }
149 // Escaped might mean that the object escaped to untracked memory or that it
150 // is used in an operation that requires materialization.
151 void SetEscaped() { escaped_ = true; }
152 bool HasEscaped() const { return escaped_; }
153 const_iterator begin() const { return fields_.begin(); }
154 const_iterator end() const { return fields_.end(); }
155
156 private:
157 bool escaped_ = false;
160};
161
163 public:
165 : tracker_(tracker) {}
166
167 const VirtualObject* GetVirtualObject(Node* node);
168 Node* GetVirtualObjectField(const VirtualObject* vobject, int field,
169 Node* effect);
170 Node* GetReplacementOf(Node* node);
171
172 private:
174};
175
177 : public NON_EXPORTED_BASE(EffectGraphReducer) {
178 public:
179 EscapeAnalysis(JSGraph* jsgraph, TickCounter* tick_counter, Zone* zone);
180
182 DCHECK(Complete());
183 return EscapeAnalysisResult(tracker_);
184 }
185
186 private:
187 void Reduce(Node* node, Reduction* reduction);
188 JSGraph* jsgraph() { return jsgraph_; }
189 Isolate* isolate() const { return jsgraph_->isolate(); }
192};
193
194} // namespace compiler
195} // namespace internal
196} // namespace v8
197
198#endif // V8_COMPILER_ESCAPE_ANALYSIS_H_
JSGraph * jsgraph
V8_WARN_UNUSED_RESULT V8_INLINE bool To(T *out) const
Definition v8-maybe.h:55
Isolate * isolate() const
Definition factory.h:1281
void push_back(const T &value)
void RevisitDependants(EffectGraphReducer *reducer)
std::function< void(Node *, Reduction *)> reduce_
EffectGraphReducer(TFGraph *graph, std::function< void(Node *, Reduction *)> reduce, TickCounter *tick_counter, Zone *zone)
Node * GetVirtualObjectField(const VirtualObject *vobject, int field, Node *effect)
const VirtualObject * GetVirtualObject(Node *node)
EscapeAnalysisResult(EscapeAnalysisTracker *tracker)
bool operator==(Variable other) const
friend V8_INLINE size_t hash_value(Variable v)
bool operator!=(Variable other) const
bool operator<(Variable other) const
friend std::ostream & operator<<(std::ostream &os, Variable var)
Maybe< Variable > FieldAt(int offset) const
Maybe< Variable > FieldAt(Maybe< int > maybe_offset) const
VirtualObject(VariableTracker *var_states, Id id, int size)
int32_t offset
V8_INLINE size_t hash_value(unsigned int v)
Definition hashing.h:205
constexpr int kTaggedSize
Definition globals.h:542
Maybe< T > Nothing()
Definition v8-maybe.h:112
Maybe< T > Just(const T &t)
Definition v8-maybe.h:117
#define NON_EXPORTED_BASE(code)
#define CHECK(condition)
Definition logging.h:124
#define DCHECK(condition)
Definition logging.h:482
#define DCHECK_EQ(v1, v2)
Definition logging.h:485
#define V8_EXPORT_PRIVATE
Definition macros.h:460
constexpr bool IsAligned(T value, U alignment)
Definition macros.h:403
#define V8_INLINE
Definition v8config.h:500