Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: src/compiler/escape-analysis-reducer.cc

Issue 1485183002: [turbofan] Deopt support for escape analysis (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@ea-local
Patch Set: Rebase Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « src/compiler/escape-analysis-reducer.h ('k') | src/compiler/frame-states.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/escape-analysis-reducer.h" 5 #include "src/compiler/escape-analysis-reducer.h"
6 6
7 #include "src/compiler/js-graph.h" 7 #include "src/compiler/js-graph.h"
8 #include "src/counters.h" 8 #include "src/counters.h"
9 9
10 namespace v8 { 10 namespace v8 {
(...skipping 18 matching lines...) Expand all
29 case IrOpcode::kStoreElement: 29 case IrOpcode::kStoreElement:
30 return ReduceStore(node); 30 return ReduceStore(node);
31 case IrOpcode::kAllocate: 31 case IrOpcode::kAllocate:
32 return ReduceAllocate(node); 32 return ReduceAllocate(node);
33 case IrOpcode::kFinishRegion: 33 case IrOpcode::kFinishRegion:
34 return ReduceFinishRegion(node); 34 return ReduceFinishRegion(node);
35 case IrOpcode::kReferenceEqual: 35 case IrOpcode::kReferenceEqual:
36 return ReduceReferenceEqual(node); 36 return ReduceReferenceEqual(node);
37 case IrOpcode::kObjectIsSmi: 37 case IrOpcode::kObjectIsSmi:
38 return ReduceObjectIsSmi(node); 38 return ReduceObjectIsSmi(node);
39 case IrOpcode::kStateValues:
40 case IrOpcode::kFrameState:
41 return ReplaceWithDeoptDummy(node);
42 default: 39 default:
40 // TODO(sigurds): Change this to GetFrameStateInputCount once
41 // it is working. For now we use EffectInputCount > 0 to determine
42 // whether a node might have a frame state input.
43 if (node->op()->EffectInputCount() > 0) {
44 return ReduceFrameStateUses(node);
45 }
43 break; 46 break;
44 } 47 }
45 return NoChange(); 48 return NoChange();
46 } 49 }
47 50
48 51
49 Reduction EscapeAnalysisReducer::ReduceLoad(Node* node) { 52 Reduction EscapeAnalysisReducer::ReduceLoad(Node* node) {
50 DCHECK(node->opcode() == IrOpcode::kLoadField || 53 DCHECK(node->opcode() == IrOpcode::kLoadField ||
51 node->opcode() == IrOpcode::kLoadElement); 54 node->opcode() == IrOpcode::kLoadElement);
52 if (Node* rep = escape_analysis()->GetReplacement(node)) { 55 if (Node* rep = escape_analysis()->GetReplacement(node)) {
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 } 113 }
111 return NoChange(); 114 return NoChange();
112 } 115 }
113 116
114 117
115 Reduction EscapeAnalysisReducer::ReduceReferenceEqual(Node* node) { 118 Reduction EscapeAnalysisReducer::ReduceReferenceEqual(Node* node) {
116 DCHECK_EQ(node->opcode(), IrOpcode::kReferenceEqual); 119 DCHECK_EQ(node->opcode(), IrOpcode::kReferenceEqual);
117 Node* left = NodeProperties::GetValueInput(node, 0); 120 Node* left = NodeProperties::GetValueInput(node, 0);
118 Node* right = NodeProperties::GetValueInput(node, 1); 121 Node* right = NodeProperties::GetValueInput(node, 1);
119 if (escape_analysis()->IsVirtual(left)) { 122 if (escape_analysis()->IsVirtual(left)) {
120 if (escape_analysis()->IsVirtual(right)) { 123 if (escape_analysis()->IsVirtual(right) &&
121 if (Node* rep = escape_analysis()->GetReplacement(left)) { 124 escape_analysis()->CompareVirtualObjects(left, right)) {
122 left = rep; 125 ReplaceWithValue(node, jsgraph()->TrueConstant());
123 } 126 if (FLAG_trace_turbo_escape) {
124 if (Node* rep = escape_analysis()->GetReplacement(right)) { 127 PrintF("Replaced ref eq #%d with true\n", node->id());
125 right = rep;
126 }
127 // TODO(sigurds): What to do if either is a PHI?
128 if (left == right) {
129 ReplaceWithValue(node, jsgraph()->TrueConstant());
130 if (FLAG_trace_turbo_escape) {
131 PrintF("Replaced ref eq #%d with true\n", node->id());
132 }
133 return Replace(node);
134 } 128 }
135 } 129 }
136 // Right-hand side is either not virtual, or a different node. 130 // Right-hand side is not a virtual object, or a different one.
137 ReplaceWithValue(node, jsgraph()->FalseConstant()); 131 ReplaceWithValue(node, jsgraph()->FalseConstant());
138 if (FLAG_trace_turbo_escape) { 132 if (FLAG_trace_turbo_escape) {
139 PrintF("Replaced ref eq #%d with false\n", node->id()); 133 PrintF("Replaced ref eq #%d with false\n", node->id());
140 } 134 }
141 return Replace(node); 135 return Replace(node);
142 } else if (escape_analysis()->IsVirtual(right)) { 136 } else if (escape_analysis()->IsVirtual(right)) {
143 // Left-hand side is not a virtual object. 137 // Left-hand side is not a virtual object.
144 ReplaceWithValue(node, jsgraph()->FalseConstant()); 138 ReplaceWithValue(node, jsgraph()->FalseConstant());
145 if (FLAG_trace_turbo_escape) { 139 if (FLAG_trace_turbo_escape) {
146 PrintF("Replaced ref eq #%d with false\n", node->id()); 140 PrintF("Replaced ref eq #%d with false\n", node->id());
(...skipping 10 matching lines...) Expand all
157 ReplaceWithValue(node, jsgraph()->FalseConstant()); 151 ReplaceWithValue(node, jsgraph()->FalseConstant());
158 if (FLAG_trace_turbo_escape) { 152 if (FLAG_trace_turbo_escape) {
159 PrintF("Replaced ObjectIsSmi #%d with false\n", node->id()); 153 PrintF("Replaced ObjectIsSmi #%d with false\n", node->id());
160 } 154 }
161 return Replace(node); 155 return Replace(node);
162 } 156 }
163 return NoChange(); 157 return NoChange();
164 } 158 }
165 159
166 160
167 // TODO(sigurds): This is a temporary solution until escape analysis 161 Reduction EscapeAnalysisReducer::ReduceFrameStateUses(Node* node) {
168 // supports deoptimization. 162 DCHECK_GE(node->op()->EffectInputCount(), 1);
169 Reduction EscapeAnalysisReducer::ReplaceWithDeoptDummy(Node* node) { 163 bool changed = false;
170 DCHECK(node->opcode() == IrOpcode::kStateValues || 164 for (int i = 0; i < node->InputCount(); ++i) {
171 node->opcode() == IrOpcode::kFrameState); 165 Node* input = node->InputAt(i);
172 Reduction r = NoChange(); 166 if (input->opcode() == IrOpcode::kFrameState) {
173 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { 167 if (Node* ret = ReduceFrameState(input, node, false)) {
174 Node* input = NodeProperties::GetValueInput(node, i); 168 node->ReplaceInput(i, ret);
175 if (input->opcode() == IrOpcode::kFinishRegion || 169 changed = true;
176 input->opcode() == IrOpcode::kAllocate ||
177 input->opcode() == IrOpcode::kPhi) {
178 if (escape_analysis()->IsVirtual(input)) {
179 NodeProperties::ReplaceValueInput(node, jsgraph()->UndefinedConstant(),
180 i);
181 if (FLAG_trace_turbo_escape) {
182 PrintF("Replaced state value (#%d) input with dummy\n", node->id());
183 }
184 r = Changed(node);
185 } 170 }
186 } 171 }
187 } 172 }
188 return r; 173 if (changed) {
174 return Changed(node);
175 }
176 return NoChange();
189 } 177 }
190 178
191 179
180 // Returns the clone if it duplicated the node, and null otherwise.
181 Node* EscapeAnalysisReducer::ReduceFrameState(Node* node, Node* effect,
182 bool multiple_users) {
183 DCHECK(node->opcode() == IrOpcode::kFrameState);
184 if (FLAG_trace_turbo_escape) {
185 PrintF("Reducing FrameState %d\n", node->id());
186 }
187 Node* clone = nullptr;
188 for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
189 Node* input = NodeProperties::GetValueInput(node, i);
190 Node* ret =
191 input->opcode() == IrOpcode::kStateValues
192 ? ReduceStateValueInputs(input, effect, node->UseCount() > 1)
193 : ReduceStateValueInput(node, i, effect, node->UseCount() > 1);
194 if (ret) {
195 if (node->UseCount() > 1 || multiple_users) {
196 if (FLAG_trace_turbo_escape) {
197 PrintF(" Cloning #%d", node->id());
198 }
199 node = clone = jsgraph()->graph()->CloneNode(node);
200 if (FLAG_trace_turbo_escape) {
201 PrintF(" to #%d\n", node->id());
202 }
203 multiple_users = false; // Don't clone anymore.
204 }
205 NodeProperties::ReplaceValueInput(node, ret, i);
206 }
207 }
208 Node* outer_frame_state = NodeProperties::GetFrameStateInput(node, 0);
209 if (outer_frame_state->opcode() == IrOpcode::kFrameState) {
210 if (Node* ret =
211 ReduceFrameState(outer_frame_state, effect, node->UseCount() > 1)) {
212 if (node->UseCount() > 1 || multiple_users) {
213 if (FLAG_trace_turbo_escape) {
214 PrintF(" Cloning #%d", node->id());
215 }
216 node = clone = jsgraph()->graph()->CloneNode(node);
217 if (FLAG_trace_turbo_escape) {
218 PrintF(" to #%d\n", node->id());
219 }
220 multiple_users = false;
221 }
222 NodeProperties::ReplaceFrameStateInput(node, 0, ret);
223 }
224 }
225 return clone;
226 }
227
228
229 // Returns the clone if it duplicated the node, and null otherwise.
230 Node* EscapeAnalysisReducer::ReduceStateValueInputs(Node* node, Node* effect,
231 bool multiple_users) {
232 if (FLAG_trace_turbo_escape) {
233 PrintF("Reducing StateValue #%d\n", node->id());
234 }
235 DCHECK(node->opcode() == IrOpcode::kStateValues);
236 DCHECK_NOT_NULL(effect);
237 Node* clone = nullptr;
238 for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
239 if (Node* ret = ReduceStateValueInput(node, i, effect, multiple_users)) {
240 node = ret;
241 DCHECK_NULL(clone);
242 clone = ret;
243 multiple_users = false;
244 }
245 }
246 return clone;
247 }
248
249
250 // Returns the clone if it duplicated the node, and null otherwise.
251 Node* EscapeAnalysisReducer::ReduceStateValueInput(Node* node, int node_index,
252 Node* effect,
253 bool multiple_users) {
254 Node* input = NodeProperties::GetValueInput(node, node_index);
255 if (FLAG_trace_turbo_escape) {
256 PrintF("Reducing State Input #%d (%s)\n", input->id(),
257 input->op()->mnemonic());
258 }
259 Node* clone = nullptr;
260 if (input->opcode() == IrOpcode::kFinishRegion ||
261 input->opcode() == IrOpcode::kAllocate) {
262 if (escape_analysis()->IsVirtual(input)) {
263 if (Node* object_state =
264 escape_analysis()->GetOrCreateObjectState(effect, input)) {
265 if (node->UseCount() > 1 || multiple_users) {
266 if (FLAG_trace_turbo_escape) {
267 PrintF("Cloning #%d", node->id());
268 }
269 node = clone = jsgraph()->graph()->CloneNode(node);
270 if (FLAG_trace_turbo_escape) {
271 PrintF(" to #%d\n", node->id());
272 }
273 }
274 NodeProperties::ReplaceValueInput(node, object_state, node_index);
275 if (FLAG_trace_turbo_escape) {
276 PrintF("Replaced state #%d input #%d with object state #%d\n",
277 node->id(), input->id(), object_state->id());
278 }
279 } else {
280 if (FLAG_trace_turbo_escape) {
281 PrintF("No object state replacement available.\n");
282 }
283 }
284 }
285 }
286 return clone;
287 }
288
289
192 Counters* EscapeAnalysisReducer::counters() const { 290 Counters* EscapeAnalysisReducer::counters() const {
193 return jsgraph_->isolate()->counters(); 291 return jsgraph_->isolate()->counters();
194 } 292 }
195 293
196 } // namespace compiler 294 } // namespace compiler
197 } // namespace internal 295 } // namespace internal
198 } // namespace v8 296 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/escape-analysis-reducer.h ('k') | src/compiler/frame-states.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698