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

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

Issue 1631333002: [turbofan] Fix iteration order (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Reactivate test 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.h ('k') | test/mjsunit/mjsunit.status » ('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.h" 5 #include "src/compiler/escape-analysis.h"
6 6
7 #include <limits> 7 #include <limits>
8 8
9 #include "src/base/flags.h" 9 #include "src/base/flags.h"
10 #include "src/bootstrapper.h" 10 #include "src/bootstrapper.h"
(...skipping 22 matching lines...) Expand all
33 } while (false) 33 } while (false)
34 #else 34 #else
35 #define TRACE(...) 35 #define TRACE(...)
36 #endif 36 #endif
37 37
38 const Alias EscapeStatusAnalysis::kNotReachable = 38 const Alias EscapeStatusAnalysis::kNotReachable =
39 std::numeric_limits<Alias>::max(); 39 std::numeric_limits<Alias>::max();
40 const Alias EscapeStatusAnalysis::kUntrackable = 40 const Alias EscapeStatusAnalysis::kUntrackable =
41 std::numeric_limits<Alias>::max() - 1; 41 std::numeric_limits<Alias>::max() - 1;
42 42
43
44 class VirtualObject : public ZoneObject { 43 class VirtualObject : public ZoneObject {
45 public: 44 public:
46 enum Status { 45 enum Status {
47 kInitial = 0, 46 kInitial = 0,
48 kTracked = 1u << 0, 47 kTracked = 1u << 0,
49 kInitialized = 1u << 1, 48 kInitialized = 1u << 1,
50 kCopyRequired = 1u << 2, 49 kCopyRequired = 1u << 2,
51 }; 50 };
52 typedef base::Flags<Status, unsigned char> StatusFlags; 51 typedef base::Flags<Status, unsigned char> StatusFlags;
53 52
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
135 NodeId id_; 134 NodeId id_;
136 StatusFlags status_; 135 StatusFlags status_;
137 ZoneVector<Node*> fields_; 136 ZoneVector<Node*> fields_;
138 ZoneVector<bool> phi_; 137 ZoneVector<bool> phi_;
139 Node* object_state_; 138 Node* object_state_;
140 VirtualState* owner_; 139 VirtualState* owner_;
141 140
142 DISALLOW_COPY_AND_ASSIGN(VirtualObject); 141 DISALLOW_COPY_AND_ASSIGN(VirtualObject);
143 }; 142 };
144 143
145
146 DEFINE_OPERATORS_FOR_FLAGS(VirtualObject::StatusFlags) 144 DEFINE_OPERATORS_FOR_FLAGS(VirtualObject::StatusFlags)
147 145
148
149 bool VirtualObject::UpdateFrom(const VirtualObject& other) { 146 bool VirtualObject::UpdateFrom(const VirtualObject& other) {
150 bool changed = status_ != other.status_; 147 bool changed = status_ != other.status_;
151 status_ = other.status_; 148 status_ = other.status_;
152 phi_ = other.phi_; 149 phi_ = other.phi_;
153 if (fields_.size() != other.fields_.size()) { 150 if (fields_.size() != other.fields_.size()) {
154 fields_ = other.fields_; 151 fields_ = other.fields_;
155 return true; 152 return true;
156 } 153 }
157 for (size_t i = 0; i < fields_.size(); ++i) { 154 for (size_t i = 0; i < fields_.size(); ++i) {
158 if (fields_[i] != other.fields_[i]) { 155 if (fields_[i] != other.fields_[i]) {
159 changed = true; 156 changed = true;
160 fields_[i] = other.fields_[i]; 157 fields_[i] = other.fields_[i];
161 } 158 }
162 } 159 }
163 return changed; 160 return changed;
164 } 161 }
165 162
166
167 class VirtualState : public ZoneObject { 163 class VirtualState : public ZoneObject {
168 public: 164 public:
169 VirtualState(NodeId owner, Zone* zone, size_t size); 165 VirtualState(Node* owner, Zone* zone, size_t size)
170 VirtualState(NodeId owner, const VirtualState& states); 166 : info_(size, nullptr, zone), owner_(owner) {}
167
168 VirtualState(Node* owner, const VirtualState& state)
169 : info_(state.info_.size(), nullptr, state.info_.get_allocator().zone()),
170 owner_(owner) {
171 for (size_t i = 0; i < info_.size(); ++i) {
172 if (state.info_[i]) {
173 info_[i] = state.info_[i];
174 }
175 }
176 }
171 177
172 VirtualObject* VirtualObjectFromAlias(size_t alias); 178 VirtualObject* VirtualObjectFromAlias(size_t alias);
173 VirtualObject* GetOrCreateTrackedVirtualObject(Alias alias, NodeId id, 179 VirtualObject* GetOrCreateTrackedVirtualObject(Alias alias, NodeId id,
174 size_t fields, 180 size_t fields,
175 bool initialized, Zone* zone, 181 bool initialized, Zone* zone,
176 bool force_copy); 182 bool force_copy);
177 void SetVirtualObject(Alias alias, VirtualObject* state); 183 void SetVirtualObject(Alias alias, VirtualObject* state);
178 bool UpdateFrom(VirtualState* state, Zone* zone); 184 bool UpdateFrom(VirtualState* state, Zone* zone);
179 bool MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, 185 bool MergeFrom(MergeCache* cache, Zone* zone, Graph* graph,
180 CommonOperatorBuilder* common, Node* control, int arity); 186 CommonOperatorBuilder* common, Node* control, int arity);
181 size_t size() const { return info_.size(); } 187 size_t size() const { return info_.size(); }
182 NodeId owner() const { return owner_; } 188 Node* owner() const { return owner_; }
183 VirtualObject* Copy(VirtualObject* obj, Alias alias); 189 VirtualObject* Copy(VirtualObject* obj, Alias alias);
184 void SetCopyRequired() { 190 void SetCopyRequired() {
185 for (VirtualObject* obj : info_) { 191 for (VirtualObject* obj : info_) {
186 if (obj) obj->SetCopyRequired(); 192 if (obj) obj->SetCopyRequired();
187 } 193 }
188 } 194 }
189 195
190 private: 196 private:
191 ZoneVector<VirtualObject*> info_; 197 ZoneVector<VirtualObject*> info_;
192 NodeId owner_; 198 Node* owner_;
193 199
194 DISALLOW_COPY_AND_ASSIGN(VirtualState); 200 DISALLOW_COPY_AND_ASSIGN(VirtualState);
195 }; 201 };
196 202
197
198 class MergeCache : public ZoneObject { 203 class MergeCache : public ZoneObject {
199 public: 204 public:
200 explicit MergeCache(Zone* zone) 205 explicit MergeCache(Zone* zone)
201 : states_(zone), objects_(zone), fields_(zone) { 206 : states_(zone), objects_(zone), fields_(zone) {
202 states_.reserve(5); 207 states_.reserve(5);
203 objects_.reserve(5); 208 objects_.reserve(5);
204 fields_.reserve(5); 209 fields_.reserve(5);
205 } 210 }
206 ZoneVector<VirtualState*>& states() { return states_; } 211 ZoneVector<VirtualState*>& states() { return states_; }
207 ZoneVector<VirtualObject*>& objects() { return objects_; } 212 ZoneVector<VirtualObject*>& objects() { return objects_; }
208 ZoneVector<Node*>& fields() { return fields_; } 213 ZoneVector<Node*>& fields() { return fields_; }
209 void Clear() { 214 void Clear() {
210 states_.clear(); 215 states_.clear();
211 objects_.clear(); 216 objects_.clear();
212 fields_.clear(); 217 fields_.clear();
213 } 218 }
214 size_t LoadVirtualObjectsFromStatesFor(Alias alias); 219 size_t LoadVirtualObjectsFromStatesFor(Alias alias);
215 void LoadVirtualObjectsForFieldsFrom(VirtualState* state, 220 void LoadVirtualObjectsForFieldsFrom(VirtualState* state,
216 const ZoneVector<Alias>& aliases); 221 const ZoneVector<Alias>& aliases);
217 Node* GetFields(size_t pos); 222 Node* GetFields(size_t pos);
218 223
219 private: 224 private:
220 ZoneVector<VirtualState*> states_; 225 ZoneVector<VirtualState*> states_;
221 ZoneVector<VirtualObject*> objects_; 226 ZoneVector<VirtualObject*> objects_;
222 ZoneVector<Node*> fields_; 227 ZoneVector<Node*> fields_;
223 228
224 DISALLOW_COPY_AND_ASSIGN(MergeCache); 229 DISALLOW_COPY_AND_ASSIGN(MergeCache);
225 }; 230 };
226 231
227
228 size_t MergeCache::LoadVirtualObjectsFromStatesFor(Alias alias) { 232 size_t MergeCache::LoadVirtualObjectsFromStatesFor(Alias alias) {
229 objects_.clear(); 233 objects_.clear();
230 DCHECK_GT(states_.size(), 0u); 234 DCHECK_GT(states_.size(), 0u);
231 size_t min = std::numeric_limits<size_t>::max(); 235 size_t min = std::numeric_limits<size_t>::max();
232 for (VirtualState* state : states_) { 236 for (VirtualState* state : states_) {
233 if (VirtualObject* obj = state->VirtualObjectFromAlias(alias)) { 237 if (VirtualObject* obj = state->VirtualObjectFromAlias(alias)) {
234 objects_.push_back(obj); 238 objects_.push_back(obj);
235 min = std::min(obj->field_count(), min); 239 min = std::min(obj->field_count(), min);
236 } 240 }
237 } 241 }
238 return min; 242 return min;
239 } 243 }
240 244
241
242 void MergeCache::LoadVirtualObjectsForFieldsFrom( 245 void MergeCache::LoadVirtualObjectsForFieldsFrom(
243 VirtualState* state, const ZoneVector<Alias>& aliases) { 246 VirtualState* state, const ZoneVector<Alias>& aliases) {
244 objects_.clear(); 247 objects_.clear();
245 size_t max_alias = state->size(); 248 size_t max_alias = state->size();
246 for (Node* field : fields_) { 249 for (Node* field : fields_) {
247 Alias alias = aliases[field->id()]; 250 Alias alias = aliases[field->id()];
248 if (alias >= max_alias) continue; 251 if (alias >= max_alias) continue;
249 if (VirtualObject* obj = state->VirtualObjectFromAlias(alias)) { 252 if (VirtualObject* obj = state->VirtualObjectFromAlias(alias)) {
250 objects_.push_back(obj); 253 objects_.push_back(obj);
251 } 254 }
252 } 255 }
253 } 256 }
254 257
255
256 Node* MergeCache::GetFields(size_t pos) { 258 Node* MergeCache::GetFields(size_t pos) {
257 fields_.clear(); 259 fields_.clear();
258 Node* rep = pos >= objects_.front()->field_count() 260 Node* rep = pos >= objects_.front()->field_count()
259 ? nullptr 261 ? nullptr
260 : objects_.front()->GetField(pos); 262 : objects_.front()->GetField(pos);
261 for (VirtualObject* obj : objects_) { 263 for (VirtualObject* obj : objects_) {
262 if (pos >= obj->field_count()) continue; 264 if (pos >= obj->field_count()) continue;
263 Node* field = obj->GetField(pos); 265 Node* field = obj->GetField(pos);
264 if (field) { 266 if (field) {
265 fields_.push_back(field); 267 fields_.push_back(field);
266 } 268 }
267 if (field != rep) { 269 if (field != rep) {
268 rep = nullptr; 270 rep = nullptr;
269 } 271 }
270 } 272 }
271 return rep; 273 return rep;
272 } 274 }
273 275
274
275 VirtualState::VirtualState(NodeId owner, Zone* zone, size_t size)
276 : info_(size, nullptr, zone), owner_(owner) {}
277
278
279 VirtualState::VirtualState(NodeId owner, const VirtualState& state)
280 : info_(state.info_.size(), nullptr, state.info_.get_allocator().zone()),
281 owner_(owner) {
282 for (size_t i = 0; i < info_.size(); ++i) {
283 if (state.info_[i]) {
284 info_[i] = state.info_[i];
285 }
286 }
287 }
288
289
290 VirtualObject* VirtualState::Copy(VirtualObject* obj, Alias alias) { 276 VirtualObject* VirtualState::Copy(VirtualObject* obj, Alias alias) {
291 if (obj->owner() == this) return obj; 277 if (obj->owner() == this) return obj;
292 VirtualObject* new_obj = 278 VirtualObject* new_obj =
293 new (info_.get_allocator().zone()) VirtualObject(this, *obj); 279 new (info_.get_allocator().zone()) VirtualObject(this, *obj);
294 TRACE("At state %p, alias @%d (#%d), copying virtual object from %p to %p\n", 280 TRACE("At state %p, alias @%d (#%d), copying virtual object from %p to %p\n",
295 static_cast<void*>(this), alias, obj->id(), static_cast<void*>(obj), 281 static_cast<void*>(this), alias, obj->id(), static_cast<void*>(obj),
296 static_cast<void*>(new_obj)); 282 static_cast<void*>(new_obj));
297 info_[alias] = new_obj; 283 info_[alias] = new_obj;
298 return new_obj; 284 return new_obj;
299 } 285 }
300 286
301
302 VirtualObject* VirtualState::VirtualObjectFromAlias(size_t alias) { 287 VirtualObject* VirtualState::VirtualObjectFromAlias(size_t alias) {
303 return info_[alias]; 288 return info_[alias];
304 } 289 }
305 290
306
307 VirtualObject* VirtualState::GetOrCreateTrackedVirtualObject( 291 VirtualObject* VirtualState::GetOrCreateTrackedVirtualObject(
308 Alias alias, NodeId id, size_t field_number, bool initialized, Zone* zone, 292 Alias alias, NodeId id, size_t field_number, bool initialized, Zone* zone,
309 bool force_copy) { 293 bool force_copy) {
310 if (!force_copy) { 294 if (!force_copy) {
311 if (VirtualObject* obj = VirtualObjectFromAlias(alias)) { 295 if (VirtualObject* obj = VirtualObjectFromAlias(alias)) {
312 return obj; 296 return obj;
313 } 297 }
314 } 298 }
315 VirtualObject* obj = new (zone) VirtualObject(id, this, zone, 0, initialized); 299 VirtualObject* obj = new (zone) VirtualObject(id, this, zone, 0, initialized);
316 SetVirtualObject(alias, obj); 300 SetVirtualObject(alias, obj);
317 return obj; 301 return obj;
318 } 302 }
319 303
320
321 void VirtualState::SetVirtualObject(Alias alias, VirtualObject* obj) { 304 void VirtualState::SetVirtualObject(Alias alias, VirtualObject* obj) {
322 info_[alias] = obj; 305 info_[alias] = obj;
323 } 306 }
324 307
325
326 bool VirtualState::UpdateFrom(VirtualState* from, Zone* zone) { 308 bool VirtualState::UpdateFrom(VirtualState* from, Zone* zone) {
327 if (from == this) return false; 309 if (from == this) return false;
328 bool changed = false; 310 bool changed = false;
329 for (Alias alias = 0; alias < size(); ++alias) { 311 for (Alias alias = 0; alias < size(); ++alias) {
330 VirtualObject* ls = VirtualObjectFromAlias(alias); 312 VirtualObject* ls = VirtualObjectFromAlias(alias);
331 VirtualObject* rs = from->VirtualObjectFromAlias(alias); 313 VirtualObject* rs = from->VirtualObjectFromAlias(alias);
332 314
333 if (ls == rs || rs == nullptr) continue; 315 if (ls == rs || rs == nullptr) continue;
334 316
335 if (ls == nullptr) { 317 if (ls == nullptr) {
336 ls = new (zone) VirtualObject(this, *rs); 318 ls = new (zone) VirtualObject(this, *rs);
337 SetVirtualObject(alias, ls); 319 SetVirtualObject(alias, ls);
338 changed = true; 320 changed = true;
339 continue; 321 continue;
340 } 322 }
341 323
342 TRACE(" Updating fields of @%d\n", alias); 324 TRACE(" Updating fields of @%d\n", alias);
343 325
344 changed = ls->UpdateFrom(*rs) || changed; 326 changed = ls->UpdateFrom(*rs) || changed;
345 } 327 }
346 return false; 328 return false;
347 } 329 }
348 330
349
350 namespace { 331 namespace {
351 332
352 bool IsEquivalentPhi(Node* node1, Node* node2) { 333 bool IsEquivalentPhi(Node* node1, Node* node2) {
353 if (node1 == node2) return true; 334 if (node1 == node2) return true;
354 if (node1->opcode() != IrOpcode::kPhi || node2->opcode() != IrOpcode::kPhi || 335 if (node1->opcode() != IrOpcode::kPhi || node2->opcode() != IrOpcode::kPhi ||
355 node1->op()->ValueInputCount() != node2->op()->ValueInputCount()) { 336 node1->op()->ValueInputCount() != node2->op()->ValueInputCount()) {
356 return false; 337 return false;
357 } 338 }
358 for (int i = 0; i < node1->op()->ValueInputCount(); ++i) { 339 for (int i = 0; i < node1->op()->ValueInputCount(); ++i) {
359 Node* input1 = NodeProperties::GetValueInput(node1, i); 340 Node* input1 = NodeProperties::GetValueInput(node1, i);
360 Node* input2 = NodeProperties::GetValueInput(node2, i); 341 Node* input2 = NodeProperties::GetValueInput(node2, i);
361 if (!IsEquivalentPhi(input1, input2)) { 342 if (!IsEquivalentPhi(input1, input2)) {
362 return false; 343 return false;
363 } 344 }
364 } 345 }
365 return true; 346 return true;
366 } 347 }
367 348
368
369 bool IsEquivalentPhi(Node* phi, ZoneVector<Node*>& inputs) { 349 bool IsEquivalentPhi(Node* phi, ZoneVector<Node*>& inputs) {
370 if (phi->opcode() != IrOpcode::kPhi) return false; 350 if (phi->opcode() != IrOpcode::kPhi) return false;
371 if (phi->op()->ValueInputCount() != inputs.size()) { 351 if (phi->op()->ValueInputCount() != inputs.size()) {
372 return false; 352 return false;
373 } 353 }
374 for (size_t i = 0; i < inputs.size(); ++i) { 354 for (size_t i = 0; i < inputs.size(); ++i) {
375 Node* input = NodeProperties::GetValueInput(phi, static_cast<int>(i)); 355 Node* input = NodeProperties::GetValueInput(phi, static_cast<int>(i));
376 if (!IsEquivalentPhi(input, inputs[i])) { 356 if (!IsEquivalentPhi(input, inputs[i])) {
377 return false; 357 return false;
378 } 358 }
379 } 359 }
380 return true; 360 return true;
381 } 361 }
382 362
383 } // namespace 363 } // namespace
384 364
385
386 Node* EscapeAnalysis::GetReplacementIfSame(ZoneVector<VirtualObject*>& objs) { 365 Node* EscapeAnalysis::GetReplacementIfSame(ZoneVector<VirtualObject*>& objs) {
387 Node* rep = GetReplacement(objs.front()->id()); 366 Node* rep = GetReplacement(objs.front()->id());
388 for (VirtualObject* obj : objs) { 367 for (VirtualObject* obj : objs) {
389 if (GetReplacement(obj->id()) != rep) { 368 if (GetReplacement(obj->id()) != rep) {
390 return nullptr; 369 return nullptr;
391 } 370 }
392 } 371 }
393 return rep; 372 return rep;
394 } 373 }
395 374
396
397 bool VirtualState::MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, 375 bool VirtualState::MergeFrom(MergeCache* cache, Zone* zone, Graph* graph,
398 CommonOperatorBuilder* common, Node* control, 376 CommonOperatorBuilder* common, Node* control,
399 int arity) { 377 int arity) {
400 DCHECK_GT(cache->states().size(), 0u); 378 DCHECK_GT(cache->states().size(), 0u);
401 bool changed = false; 379 bool changed = false;
402 for (Alias alias = 0; alias < size(); ++alias) { 380 for (Alias alias = 0; alias < size(); ++alias) {
403 cache->objects().clear(); 381 cache->objects().clear();
404 VirtualObject* mergeObject = VirtualObjectFromAlias(alias); 382 VirtualObject* mergeObject = VirtualObjectFromAlias(alias);
405 bool copy_merge_object = false; 383 bool copy_merge_object = false;
406 size_t fields = std::numeric_limits<size_t>::max(); 384 size_t fields = std::numeric_limits<size_t>::max();
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after
480 if (mergeObject) { 458 if (mergeObject) {
481 TRACE(" Alias %d, virtual object removed\n", alias); 459 TRACE(" Alias %d, virtual object removed\n", alias);
482 changed = true; 460 changed = true;
483 } 461 }
484 SetVirtualObject(alias, nullptr); 462 SetVirtualObject(alias, nullptr);
485 } 463 }
486 } 464 }
487 return changed; 465 return changed;
488 } 466 }
489 467
490
491 EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis, 468 EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis,
492 Graph* graph, Zone* zone) 469 Graph* graph, Zone* zone)
493 : stack_(zone), 470 : stack_(zone),
494 object_analysis_(object_analysis), 471 object_analysis_(object_analysis),
495 graph_(graph), 472 graph_(graph),
496 zone_(zone), 473 zone_(zone),
497 status_(graph->NodeCount(), kUnknown, zone), 474 status_(graph->NodeCount(), kUnknown, zone),
498 next_free_alias_(0), 475 next_free_alias_(0),
499 status_stack_(zone), 476 status_stack_(zone),
500 aliases_(zone) {} 477 aliases_(zone) {}
501 478
502
503 EscapeStatusAnalysis::~EscapeStatusAnalysis() {} 479 EscapeStatusAnalysis::~EscapeStatusAnalysis() {}
504 480
505
506 bool EscapeStatusAnalysis::HasEntry(Node* node) { 481 bool EscapeStatusAnalysis::HasEntry(Node* node) {
507 return status_[node->id()] & (kTracked | kEscaped); 482 return status_[node->id()] & (kTracked | kEscaped);
508 } 483 }
509 484
510
511 bool EscapeStatusAnalysis::IsVirtual(Node* node) { 485 bool EscapeStatusAnalysis::IsVirtual(Node* node) {
512 return IsVirtual(node->id()); 486 return IsVirtual(node->id());
513 } 487 }
514 488
515
516 bool EscapeStatusAnalysis::IsVirtual(NodeId id) { 489 bool EscapeStatusAnalysis::IsVirtual(NodeId id) {
517 return (status_[id] & kTracked) && !(status_[id] & kEscaped); 490 return (status_[id] & kTracked) && !(status_[id] & kEscaped);
518 } 491 }
519 492
520
521 bool EscapeStatusAnalysis::IsEscaped(Node* node) { 493 bool EscapeStatusAnalysis::IsEscaped(Node* node) {
522 return status_[node->id()] & kEscaped; 494 return status_[node->id()] & kEscaped;
523 } 495 }
524 496
525
526 bool EscapeStatusAnalysis::IsAllocation(Node* node) { 497 bool EscapeStatusAnalysis::IsAllocation(Node* node) {
527 return node->opcode() == IrOpcode::kAllocate || 498 return node->opcode() == IrOpcode::kAllocate ||
528 node->opcode() == IrOpcode::kFinishRegion; 499 node->opcode() == IrOpcode::kFinishRegion;
529 } 500 }
530 501
531
532 bool EscapeStatusAnalysis::SetEscaped(Node* node) { 502 bool EscapeStatusAnalysis::SetEscaped(Node* node) {
533 bool changed = !(status_[node->id()] & kEscaped); 503 bool changed = !(status_[node->id()] & kEscaped);
534 status_[node->id()] |= kEscaped | kTracked; 504 status_[node->id()] |= kEscaped | kTracked;
535 return changed; 505 return changed;
536 } 506 }
537 507
508 bool EscapeStatusAnalysis::IsInQueue(NodeId id) {
509 return status_[id] & kInQueue;
510 }
511
512 void EscapeStatusAnalysis::SetInQueue(NodeId id, bool on_stack) {
513 if (on_stack) {
514 status_[id] |= kInQueue;
515 } else {
516 status_[id] &= ~kInQueue;
517 }
518 }
538 519
539 void EscapeStatusAnalysis::ResizeStatusVector() { 520 void EscapeStatusAnalysis::ResizeStatusVector() {
540 if (status_.size() <= graph()->NodeCount()) { 521 if (status_.size() <= graph()->NodeCount()) {
541 status_.resize(graph()->NodeCount() * 1.1, kUnknown); 522 status_.resize(graph()->NodeCount() * 1.1, kUnknown);
542 } 523 }
543 } 524 }
544 525
545
546 size_t EscapeStatusAnalysis::GetStatusVectorSize() { return status_.size(); } 526 size_t EscapeStatusAnalysis::GetStatusVectorSize() { return status_.size(); }
547 527
548
549 void EscapeStatusAnalysis::RunStatusAnalysis() { 528 void EscapeStatusAnalysis::RunStatusAnalysis() {
550 ResizeStatusVector(); 529 ResizeStatusVector();
551 while (!status_stack_.empty()) { 530 while (!status_stack_.empty()) {
552 Node* node = status_stack_.back(); 531 Node* node = status_stack_.back();
553 status_stack_.pop_back(); 532 status_stack_.pop_back();
554 status_[node->id()] &= ~kOnStack; 533 status_[node->id()] &= ~kOnStack;
555 Process(node); 534 Process(node);
556 status_[node->id()] |= kVisited; 535 status_[node->id()] |= kVisited;
557 } 536 }
558 } 537 }
559 538
560
561 void EscapeStatusAnalysis::EnqueueForStatusAnalysis(Node* node) { 539 void EscapeStatusAnalysis::EnqueueForStatusAnalysis(Node* node) {
562 DCHECK_NOT_NULL(node); 540 DCHECK_NOT_NULL(node);
563 if (!(status_[node->id()] & kOnStack)) { 541 if (!(status_[node->id()] & kOnStack)) {
564 status_stack_.push_back(node); 542 status_stack_.push_back(node);
565 status_[node->id()] |= kOnStack; 543 status_[node->id()] |= kOnStack;
566 } 544 }
567 } 545 }
568 546
569
570 void EscapeStatusAnalysis::RevisitInputs(Node* node) { 547 void EscapeStatusAnalysis::RevisitInputs(Node* node) {
571 for (Edge edge : node->input_edges()) { 548 for (Edge edge : node->input_edges()) {
572 Node* input = edge.to(); 549 Node* input = edge.to();
573 if (!(status_[input->id()] & kOnStack)) { 550 if (!(status_[input->id()] & kOnStack)) {
574 status_stack_.push_back(input); 551 status_stack_.push_back(input);
575 status_[input->id()] |= kOnStack; 552 status_[input->id()] |= kOnStack;
576 } 553 }
577 } 554 }
578 } 555 }
579 556
580
581 void EscapeStatusAnalysis::RevisitUses(Node* node) { 557 void EscapeStatusAnalysis::RevisitUses(Node* node) {
582 for (Edge edge : node->use_edges()) { 558 for (Edge edge : node->use_edges()) {
583 Node* use = edge.from(); 559 Node* use = edge.from();
584 if (!(status_[use->id()] & kOnStack) && !IsNotReachable(use)) { 560 if (!(status_[use->id()] & kOnStack) && !IsNotReachable(use)) {
585 status_stack_.push_back(use); 561 status_stack_.push_back(use);
586 status_[use->id()] |= kOnStack; 562 status_[use->id()] |= kOnStack;
587 } 563 }
588 } 564 }
589 } 565 }
590 566
591
592 void EscapeStatusAnalysis::Process(Node* node) { 567 void EscapeStatusAnalysis::Process(Node* node) {
593 switch (node->opcode()) { 568 switch (node->opcode()) {
594 case IrOpcode::kAllocate: 569 case IrOpcode::kAllocate:
595 ProcessAllocate(node); 570 ProcessAllocate(node);
596 break; 571 break;
597 case IrOpcode::kFinishRegion: 572 case IrOpcode::kFinishRegion:
598 ProcessFinishRegion(node); 573 ProcessFinishRegion(node);
599 break; 574 break;
600 case IrOpcode::kStoreField: 575 case IrOpcode::kStoreField:
601 ProcessStoreField(node); 576 ProcessStoreField(node);
(...skipping 20 matching lines...) Expand all
622 if (!IsAllocationPhi(node) && SetEscaped(node)) { 597 if (!IsAllocationPhi(node) && SetEscaped(node)) {
623 RevisitInputs(node); 598 RevisitInputs(node);
624 RevisitUses(node); 599 RevisitUses(node);
625 } 600 }
626 CheckUsesForEscape(node); 601 CheckUsesForEscape(node);
627 default: 602 default:
628 break; 603 break;
629 } 604 }
630 } 605 }
631 606
632
633 bool EscapeStatusAnalysis::IsAllocationPhi(Node* node) { 607 bool EscapeStatusAnalysis::IsAllocationPhi(Node* node) {
634 for (Edge edge : node->input_edges()) { 608 for (Edge edge : node->input_edges()) {
635 Node* input = edge.to(); 609 Node* input = edge.to();
636 if (input->opcode() == IrOpcode::kPhi && !IsEscaped(input)) continue; 610 if (input->opcode() == IrOpcode::kPhi && !IsEscaped(input)) continue;
637 if (IsAllocation(input)) continue; 611 if (IsAllocation(input)) continue;
638 return false; 612 return false;
639 } 613 }
640 return true; 614 return true;
641 } 615 }
642 616
643
644 void EscapeStatusAnalysis::ProcessStoreField(Node* node) { 617 void EscapeStatusAnalysis::ProcessStoreField(Node* node) {
645 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField); 618 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField);
646 Node* to = NodeProperties::GetValueInput(node, 0); 619 Node* to = NodeProperties::GetValueInput(node, 0);
647 Node* val = NodeProperties::GetValueInput(node, 1); 620 Node* val = NodeProperties::GetValueInput(node, 1);
648 if ((IsEscaped(to) || !IsAllocation(to)) && SetEscaped(val)) { 621 if ((IsEscaped(to) || !IsAllocation(to)) && SetEscaped(val)) {
649 RevisitUses(val); 622 RevisitUses(val);
650 RevisitInputs(val); 623 RevisitInputs(val);
651 TRACE("Setting #%d (%s) to escaped because of store to field of #%d\n", 624 TRACE("Setting #%d (%s) to escaped because of store to field of #%d\n",
652 val->id(), val->op()->mnemonic(), to->id()); 625 val->id(), val->op()->mnemonic(), to->id());
653 } 626 }
654 } 627 }
655 628
656
657 void EscapeStatusAnalysis::ProcessStoreElement(Node* node) { 629 void EscapeStatusAnalysis::ProcessStoreElement(Node* node) {
658 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement); 630 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement);
659 Node* to = NodeProperties::GetValueInput(node, 0); 631 Node* to = NodeProperties::GetValueInput(node, 0);
660 Node* val = NodeProperties::GetValueInput(node, 2); 632 Node* val = NodeProperties::GetValueInput(node, 2);
661 if ((IsEscaped(to) || !IsAllocation(to)) && SetEscaped(val)) { 633 if ((IsEscaped(to) || !IsAllocation(to)) && SetEscaped(val)) {
662 RevisitUses(val); 634 RevisitUses(val);
663 RevisitInputs(val); 635 RevisitInputs(val);
664 TRACE("Setting #%d (%s) to escaped because of store to field of #%d\n", 636 TRACE("Setting #%d (%s) to escaped because of store to field of #%d\n",
665 val->id(), val->op()->mnemonic(), to->id()); 637 val->id(), val->op()->mnemonic(), to->id());
666 } 638 }
667 } 639 }
668 640
669
670 void EscapeStatusAnalysis::ProcessAllocate(Node* node) { 641 void EscapeStatusAnalysis::ProcessAllocate(Node* node) {
671 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); 642 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate);
672 if (!HasEntry(node)) { 643 if (!HasEntry(node)) {
673 status_[node->id()] |= kTracked; 644 status_[node->id()] |= kTracked;
674 TRACE("Created status entry for node #%d (%s)\n", node->id(), 645 TRACE("Created status entry for node #%d (%s)\n", node->id(),
675 node->op()->mnemonic()); 646 node->op()->mnemonic());
676 NumberMatcher size(node->InputAt(0)); 647 NumberMatcher size(node->InputAt(0));
677 DCHECK(node->InputAt(0)->opcode() != IrOpcode::kInt32Constant && 648 DCHECK(node->InputAt(0)->opcode() != IrOpcode::kInt32Constant &&
678 node->InputAt(0)->opcode() != IrOpcode::kInt64Constant && 649 node->InputAt(0)->opcode() != IrOpcode::kInt64Constant &&
679 node->InputAt(0)->opcode() != IrOpcode::kFloat32Constant && 650 node->InputAt(0)->opcode() != IrOpcode::kFloat32Constant &&
680 node->InputAt(0)->opcode() != IrOpcode::kFloat64Constant); 651 node->InputAt(0)->opcode() != IrOpcode::kFloat64Constant);
681 RevisitUses(node); 652 RevisitUses(node);
682 if (!size.HasValue() && SetEscaped(node)) { 653 if (!size.HasValue() && SetEscaped(node)) {
683 TRACE("Setting #%d to escaped because of non-const alloc\n", node->id()); 654 TRACE("Setting #%d to escaped because of non-const alloc\n", node->id());
684 // This node is already known to escape, uses do not have to be checked 655 // This node is already known to escape, uses do not have to be checked
685 // for escape. 656 // for escape.
686 return; 657 return;
687 } 658 }
688 } 659 }
689 if (CheckUsesForEscape(node, true)) { 660 if (CheckUsesForEscape(node, true)) {
690 RevisitUses(node); 661 RevisitUses(node);
691 } 662 }
692 } 663 }
693 664
694
695 bool EscapeStatusAnalysis::CheckUsesForEscape(Node* uses, Node* rep, 665 bool EscapeStatusAnalysis::CheckUsesForEscape(Node* uses, Node* rep,
696 bool phi_escaping) { 666 bool phi_escaping) {
697 for (Edge edge : uses->use_edges()) { 667 for (Edge edge : uses->use_edges()) {
698 Node* use = edge.from(); 668 Node* use = edge.from();
699 if (IsNotReachable(use)) continue; 669 if (IsNotReachable(use)) continue;
700 if (edge.index() >= use->op()->ValueInputCount() + 670 if (edge.index() >= use->op()->ValueInputCount() +
701 OperatorProperties::GetContextInputCount(use->op())) 671 OperatorProperties::GetContextInputCount(use->op()))
702 continue; 672 continue;
703 switch (use->opcode()) { 673 switch (use->opcode()) {
704 case IrOpcode::kPhi: 674 case IrOpcode::kPhi:
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 TRACE("Setting #%d (%s) to escaped because of use by #%d (%s)\n", 725 TRACE("Setting #%d (%s) to escaped because of use by #%d (%s)\n",
756 rep->id(), rep->op()->mnemonic(), use->id(), 726 rep->id(), rep->op()->mnemonic(), use->id(),
757 use->op()->mnemonic()); 727 use->op()->mnemonic());
758 return true; 728 return true;
759 } 729 }
760 } 730 }
761 } 731 }
762 return false; 732 return false;
763 } 733 }
764 734
765
766 void EscapeStatusAnalysis::ProcessFinishRegion(Node* node) { 735 void EscapeStatusAnalysis::ProcessFinishRegion(Node* node) {
767 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion); 736 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion);
768 if (!HasEntry(node)) { 737 if (!HasEntry(node)) {
769 status_[node->id()] |= kTracked; 738 status_[node->id()] |= kTracked;
770 RevisitUses(node); 739 RevisitUses(node);
771 } 740 }
772 if (CheckUsesForEscape(node, true)) { 741 if (CheckUsesForEscape(node, true)) {
773 RevisitInputs(node); 742 RevisitInputs(node);
774 } 743 }
775 } 744 }
776 745
777
778 void EscapeStatusAnalysis::DebugPrint() { 746 void EscapeStatusAnalysis::DebugPrint() {
779 for (NodeId id = 0; id < status_.size(); id++) { 747 for (NodeId id = 0; id < status_.size(); id++) {
780 if (status_[id] & kTracked) { 748 if (status_[id] & kTracked) {
781 PrintF("Node #%d is %s\n", id, 749 PrintF("Node #%d is %s\n", id,
782 (status_[id] & kEscaped) ? "escaping" : "virtual"); 750 (status_[id] & kEscaped) ? "escaping" : "virtual");
783 } 751 }
784 } 752 }
785 } 753 }
786 754
787
788 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, 755 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common,
789 Zone* zone) 756 Zone* zone)
790 : status_analysis_(this, graph, zone), 757 : status_analysis_(this, graph, zone),
791 common_(common), 758 common_(common),
792 virtual_states_(zone), 759 virtual_states_(zone),
793 replacements_(zone), 760 replacements_(zone),
794 cache_(new (zone) MergeCache(zone)) {} 761 cache_(new (zone) MergeCache(zone)) {}
795 762
796
797 EscapeAnalysis::~EscapeAnalysis() {} 763 EscapeAnalysis::~EscapeAnalysis() {}
798 764
799
800 void EscapeAnalysis::Run() { 765 void EscapeAnalysis::Run() {
801 replacements_.resize(graph()->NodeCount()); 766 replacements_.resize(graph()->NodeCount());
802 status_analysis_.AssignAliases(); 767 status_analysis_.AssignAliases();
803 if (status_analysis_.AliasCount() == 0) return; 768 if (status_analysis_.AliasCount() == 0) return;
804 status_analysis_.ResizeStatusVector(); 769 status_analysis_.ResizeStatusVector();
805 RunObjectAnalysis(); 770 RunObjectAnalysis();
806 status_analysis_.RunStatusAnalysis(); 771 status_analysis_.RunStatusAnalysis();
807 } 772 }
808 773
809
810 void EscapeStatusAnalysis::AssignAliases() { 774 void EscapeStatusAnalysis::AssignAliases() {
811 stack_.reserve(graph()->NodeCount() * 0.2); 775 stack_.reserve(graph()->NodeCount() * 0.2);
812 ResizeStatusVector(); 776 ResizeStatusVector();
813 stack_.push_back(graph()->end()); 777 stack_.push_back(graph()->end());
814 CHECK_LT(graph()->NodeCount(), kUntrackable); 778 CHECK_LT(graph()->NodeCount(), kUntrackable);
815 aliases_.resize(graph()->NodeCount(), kNotReachable); 779 aliases_.resize(graph()->NodeCount(), kNotReachable);
816 aliases_[graph()->end()->id()] = kUntrackable; 780 aliases_[graph()->end()->id()] = kUntrackable;
817 status_stack_.reserve(8); 781 status_stack_.reserve(8);
818 TRACE("Discovering trackable nodes"); 782 TRACE("Discovering trackable nodes");
819 while (!stack_.empty()) { 783 while (!stack_.empty()) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 Node* input = edge.to(); 824 Node* input = edge.to();
861 if (aliases_[input->id()] == kNotReachable) { 825 if (aliases_[input->id()] == kNotReachable) {
862 stack_.push_back(input); 826 stack_.push_back(input);
863 aliases_[input->id()] = kUntrackable; 827 aliases_[input->id()] = kUntrackable;
864 } 828 }
865 } 829 }
866 } 830 }
867 TRACE("\n"); 831 TRACE("\n");
868 } 832 }
869 833
870
871 bool EscapeStatusAnalysis::IsNotReachable(Node* node) { 834 bool EscapeStatusAnalysis::IsNotReachable(Node* node) {
872 if (node->id() >= aliases_.size()) { 835 if (node->id() >= aliases_.size()) {
873 return false; 836 return false;
874 } 837 }
875 return aliases_[node->id()] == kNotReachable; 838 return aliases_[node->id()] == kNotReachable;
876 } 839 }
877 840
878
879 void EscapeAnalysis::RunObjectAnalysis() { 841 void EscapeAnalysis::RunObjectAnalysis() {
880 virtual_states_.resize(graph()->NodeCount()); 842 virtual_states_.resize(graph()->NodeCount());
881 stack().push_back(graph()->start()); 843 ZoneDeque<Node*> queue(zone());
844 queue.push_back(graph()->start());
882 ZoneVector<Node*> danglers(zone()); 845 ZoneVector<Node*> danglers(zone());
883 while (!stack().empty()) { 846 while (!queue.empty()) {
884 Node* node = stack().back(); 847 Node* node = queue.back();
885 stack().pop_back(); 848 queue.pop_back();
849 status_analysis_.SetInQueue(node->id(), false);
886 if (Process(node)) { 850 if (Process(node)) {
887 for (Edge edge : node->use_edges()) { 851 for (Edge edge : node->use_edges()) {
888 Node* use = edge.from(); 852 Node* use = edge.from();
889 if (IsNotReachable(use)) { 853 if (IsNotReachable(use)) {
890 continue; 854 continue;
891 } 855 }
892 if (NodeProperties::IsEffectEdge(edge)) { 856 if (NodeProperties::IsEffectEdge(edge)) {
893 if ((use->opcode() != IrOpcode::kLoadField && 857 // Iteration order: depth first, but delay phis.
894 use->opcode() != IrOpcode::kLoadElement) || 858 // We need DFS do avoid some duplication of VirtualStates and
895 !IsDanglingEffectNode(use)) { 859 // VirtualObjects, and we want to delay phis to improve performance.
896 stack().push_back(use); 860 if (use->opcode() == IrOpcode::kEffectPhi) {
861 if (!status_analysis_.IsInQueue(use->id())) {
862 queue.push_front(use);
863 }
864 } else if ((use->opcode() != IrOpcode::kLoadField &&
865 use->opcode() != IrOpcode::kLoadElement) ||
866 !IsDanglingEffectNode(use)) {
867 if (!status_analysis_.IsInQueue(use->id())) {
868 status_analysis_.SetInQueue(use->id(), true);
869 queue.push_back(use);
870 }
897 } else { 871 } else {
898 danglers.push_back(use); 872 danglers.push_back(use);
899 } 873 }
900 } 874 }
901 } 875 }
902 stack().insert(stack().end(), danglers.begin(), danglers.end()); 876 // Danglers need to be processed immediately, even if they are
877 // on the stack. Since they do not have effect outputs,
878 // we don't have to track whether they are on the stack.
879 queue.insert(queue.end(), danglers.begin(), danglers.end());
903 danglers.clear(); 880 danglers.clear();
904 } 881 }
905 } 882 }
906 #ifdef DEBUG 883 #ifdef DEBUG
907 if (FLAG_trace_turbo_escape) { 884 if (FLAG_trace_turbo_escape) {
908 DebugPrint(); 885 DebugPrint();
909 } 886 }
910 #endif 887 #endif
911 } 888 }
912 889
913
914 bool EscapeStatusAnalysis::IsDanglingEffectNode(Node* node) { 890 bool EscapeStatusAnalysis::IsDanglingEffectNode(Node* node) {
915 if (status_[node->id()] & kDanglingComputed) { 891 if (status_[node->id()] & kDanglingComputed) {
916 return status_[node->id()] & kDangling; 892 return status_[node->id()] & kDangling;
917 } 893 }
918 if (node->op()->EffectInputCount() == 0 || 894 if (node->op()->EffectInputCount() == 0 ||
919 node->op()->EffectOutputCount() == 0 || 895 node->op()->EffectOutputCount() == 0 ||
920 (node->op()->EffectInputCount() == 1 && 896 (node->op()->EffectInputCount() == 1 &&
921 NodeProperties::GetEffectInput(node)->opcode() == IrOpcode::kStart)) { 897 NodeProperties::GetEffectInput(node)->opcode() == IrOpcode::kStart)) {
922 // The start node is used as sentinel for nodes that are in general 898 // The start node is used as sentinel for nodes that are in general
923 // effectful, but of which an analysis has determined that they do not 899 // effectful, but of which an analysis has determined that they do not
924 // produce effects in this instance. We don't consider these nodes dangling. 900 // produce effects in this instance. We don't consider these nodes dangling.
925 status_[node->id()] |= kDanglingComputed; 901 status_[node->id()] |= kDanglingComputed;
926 return false; 902 return false;
927 } 903 }
928 for (Edge edge : node->use_edges()) { 904 for (Edge edge : node->use_edges()) {
929 Node* use = edge.from(); 905 Node* use = edge.from();
930 if (aliases_[use->id()] == kNotReachable) continue; 906 if (aliases_[use->id()] == kNotReachable) continue;
931 if (NodeProperties::IsEffectEdge(edge)) { 907 if (NodeProperties::IsEffectEdge(edge)) {
932 status_[node->id()] |= kDanglingComputed; 908 status_[node->id()] |= kDanglingComputed;
933 return false; 909 return false;
934 } 910 }
935 } 911 }
936 status_[node->id()] |= kDanglingComputed | kDangling; 912 status_[node->id()] |= kDanglingComputed | kDangling;
937 return true; 913 return true;
938 } 914 }
939 915
940
941 bool EscapeStatusAnalysis::IsEffectBranchPoint(Node* node) { 916 bool EscapeStatusAnalysis::IsEffectBranchPoint(Node* node) {
942 if (status_[node->id()] & kBranchPointComputed) { 917 if (status_[node->id()] & kBranchPointComputed) {
943 return status_[node->id()] & kBranchPoint; 918 return status_[node->id()] & kBranchPoint;
944 } 919 }
945 int count = 0; 920 int count = 0;
946 for (Edge edge : node->use_edges()) { 921 for (Edge edge : node->use_edges()) {
947 Node* use = edge.from(); 922 Node* use = edge.from();
948 if (aliases_[use->id()] == kNotReachable) continue; 923 if (aliases_[use->id()] == kNotReachable) continue;
949 if (NodeProperties::IsEffectEdge(edge)) { 924 if (NodeProperties::IsEffectEdge(edge)) {
950 if ((use->opcode() == IrOpcode::kLoadField || 925 if ((use->opcode() == IrOpcode::kLoadField ||
951 use->opcode() == IrOpcode::kLoadElement || 926 use->opcode() == IrOpcode::kLoadElement ||
952 use->opcode() == IrOpcode::kLoad) && 927 use->opcode() == IrOpcode::kLoad) &&
953 IsDanglingEffectNode(use)) 928 IsDanglingEffectNode(use))
954 continue; 929 continue;
955 if (++count > 1) { 930 if (++count > 1) {
956 status_[node->id()] |= kBranchPointComputed | kBranchPoint; 931 status_[node->id()] |= kBranchPointComputed | kBranchPoint;
957 return true; 932 return true;
958 } 933 }
959 } 934 }
960 } 935 }
961 status_[node->id()] |= kBranchPointComputed; 936 status_[node->id()] |= kBranchPointComputed;
962 return false; 937 return false;
963 } 938 }
964 939
965
966 bool EscapeAnalysis::Process(Node* node) { 940 bool EscapeAnalysis::Process(Node* node) {
967 switch (node->opcode()) { 941 switch (node->opcode()) {
968 case IrOpcode::kAllocate: 942 case IrOpcode::kAllocate:
969 ProcessAllocation(node); 943 ProcessAllocation(node);
970 break; 944 break;
971 case IrOpcode::kBeginRegion: 945 case IrOpcode::kBeginRegion:
972 ForwardVirtualState(node); 946 ForwardVirtualState(node);
973 break; 947 break;
974 case IrOpcode::kFinishRegion: 948 case IrOpcode::kFinishRegion:
975 ProcessFinishRegion(node); 949 ProcessFinishRegion(node);
(...skipping 19 matching lines...) Expand all
995 default: 969 default:
996 if (node->op()->EffectInputCount() > 0) { 970 if (node->op()->EffectInputCount() > 0) {
997 ForwardVirtualState(node); 971 ForwardVirtualState(node);
998 } 972 }
999 ProcessAllocationUsers(node); 973 ProcessAllocationUsers(node);
1000 break; 974 break;
1001 } 975 }
1002 return true; 976 return true;
1003 } 977 }
1004 978
1005
1006 void EscapeAnalysis::ProcessAllocationUsers(Node* node) { 979 void EscapeAnalysis::ProcessAllocationUsers(Node* node) {
1007 for (Edge edge : node->input_edges()) { 980 for (Edge edge : node->input_edges()) {
1008 Node* input = edge.to(); 981 Node* input = edge.to();
1009 Node* use = edge.from(); 982 Node* use = edge.from();
1010 if (edge.index() >= use->op()->ValueInputCount() + 983 if (edge.index() >= use->op()->ValueInputCount() +
1011 OperatorProperties::GetContextInputCount(use->op())) 984 OperatorProperties::GetContextInputCount(use->op()))
1012 continue; 985 continue;
1013 switch (node->opcode()) { 986 switch (node->opcode()) {
1014 case IrOpcode::kStoreField: 987 case IrOpcode::kStoreField:
1015 case IrOpcode::kLoadField: 988 case IrOpcode::kLoadField:
(...skipping 13 matching lines...) Expand all
1029 obj->ClearAllFields(); 1002 obj->ClearAllFields();
1030 TRACE("Cleared all fields of @%d:#%d\n", GetAlias(obj->id()), 1003 TRACE("Cleared all fields of @%d:#%d\n", GetAlias(obj->id()),
1031 obj->id()); 1004 obj->id());
1032 } 1005 }
1033 } 1006 }
1034 break; 1007 break;
1035 } 1008 }
1036 } 1009 }
1037 } 1010 }
1038 1011
1039
1040 VirtualState* EscapeAnalysis::CopyForModificationAt(VirtualState* state, 1012 VirtualState* EscapeAnalysis::CopyForModificationAt(VirtualState* state,
1041 Node* node) { 1013 Node* node) {
1042 if (state->owner() != node->id()) { 1014 if (state->owner() != node) {
1043 VirtualState* new_state = new (zone()) VirtualState(node->id(), *state); 1015 VirtualState* new_state = new (zone()) VirtualState(node, *state);
1044 virtual_states_[node->id()] = new_state; 1016 virtual_states_[node->id()] = new_state;
1045 TRACE("Copying virtual state %p to new state %p at node %s#%d\n", 1017 TRACE("Copying virtual state %p to new state %p at node %s#%d\n",
1046 static_cast<void*>(state), static_cast<void*>(new_state), 1018 static_cast<void*>(state), static_cast<void*>(new_state),
1047 node->op()->mnemonic(), node->id()); 1019 node->op()->mnemonic(), node->id());
1048 return new_state; 1020 return new_state;
1049 } 1021 }
1050 return state; 1022 return state;
1051 } 1023 }
1052 1024
1053
1054 VirtualObject* EscapeAnalysis::CopyForModificationAt(VirtualObject* obj, 1025 VirtualObject* EscapeAnalysis::CopyForModificationAt(VirtualObject* obj,
1055 VirtualState* state, 1026 VirtualState* state,
1056 Node* node) { 1027 Node* node) {
1057 if (obj->NeedCopyForModification()) { 1028 if (obj->NeedCopyForModification()) {
1058 state = CopyForModificationAt(state, node); 1029 state = CopyForModificationAt(state, node);
1059 return state->Copy(obj, GetAlias(obj->id())); 1030 return state->Copy(obj, GetAlias(obj->id()));
1060 } 1031 }
1061 return obj; 1032 return obj;
1062 } 1033 }
1063 1034
1064
1065 void EscapeAnalysis::ForwardVirtualState(Node* node) { 1035 void EscapeAnalysis::ForwardVirtualState(Node* node) {
1066 DCHECK_EQ(node->op()->EffectInputCount(), 1); 1036 DCHECK_EQ(node->op()->EffectInputCount(), 1);
1067 #ifdef DEBUG 1037 #ifdef DEBUG
1068 if (node->opcode() != IrOpcode::kLoadField && 1038 if (node->opcode() != IrOpcode::kLoadField &&
1069 node->opcode() != IrOpcode::kLoadElement && 1039 node->opcode() != IrOpcode::kLoadElement &&
1070 node->opcode() != IrOpcode::kLoad && IsDanglingEffectNode(node)) { 1040 node->opcode() != IrOpcode::kLoad && IsDanglingEffectNode(node)) {
1071 PrintF("Dangeling effect node: #%d (%s)\n", node->id(), 1041 PrintF("Dangeling effect node: #%d (%s)\n", node->id(),
1072 node->op()->mnemonic()); 1042 node->op()->mnemonic());
1073 UNREACHABLE(); 1043 UNREACHABLE();
1074 } 1044 }
1075 #endif // DEBUG 1045 #endif // DEBUG
1076 Node* effect = NodeProperties::GetEffectInput(node); 1046 Node* effect = NodeProperties::GetEffectInput(node);
1077 // Break the cycle for effect phis. 1047 // Break the cycle for effect phis.
1078 if (effect->opcode() == IrOpcode::kEffectPhi && 1048 if (effect->opcode() == IrOpcode::kEffectPhi &&
1079 virtual_states_[effect->id()] == nullptr) { 1049 virtual_states_[effect->id()] == nullptr) {
1080 VirtualState* state = 1050 VirtualState* state =
1081 new (zone()) VirtualState(effect->id(), zone(), AliasCount()); 1051 new (zone()) VirtualState(effect, zone(), AliasCount());
1082 virtual_states_[effect->id()] = state; 1052 virtual_states_[effect->id()] = state;
1083 TRACE("Effect Phi #%d got new virtual state %p.\n", effect->id(), 1053 TRACE("Effect Phi #%d got new virtual state %p.\n", effect->id(),
1084 static_cast<void*>(virtual_states_[effect->id()])); 1054 static_cast<void*>(virtual_states_[effect->id()]));
1085 } 1055 }
1086 DCHECK_NOT_NULL(virtual_states_[effect->id()]); 1056 DCHECK_NOT_NULL(virtual_states_[effect->id()]);
1087 if (virtual_states_[node->id()]) { 1057 if (virtual_states_[node->id()]) {
1088 virtual_states_[node->id()]->UpdateFrom(virtual_states_[effect->id()], 1058 virtual_states_[node->id()]->UpdateFrom(virtual_states_[effect->id()],
1089 zone()); 1059 zone());
1090 } else { 1060 } else {
1091 virtual_states_[node->id()] = virtual_states_[effect->id()]; 1061 virtual_states_[node->id()] = virtual_states_[effect->id()];
1092 TRACE("Forwarding object state %p from %s#%d to %s#%d", 1062 TRACE("Forwarding object state %p from %s#%d to %s#%d",
1093 static_cast<void*>(virtual_states_[effect->id()]), 1063 static_cast<void*>(virtual_states_[effect->id()]),
1094 effect->op()->mnemonic(), effect->id(), node->op()->mnemonic(), 1064 effect->op()->mnemonic(), effect->id(), node->op()->mnemonic(),
1095 node->id()); 1065 node->id());
1096 if (IsEffectBranchPoint(effect) || 1066 if (IsEffectBranchPoint(effect) ||
1097 OperatorProperties::GetFrameStateInputCount(node->op()) > 0) { 1067 OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
1098 virtual_states_[node->id()]->SetCopyRequired(); 1068 virtual_states_[node->id()]->SetCopyRequired();
1099 TRACE(", effect input %s#%d is branch point", effect->op()->mnemonic(), 1069 TRACE(", effect input %s#%d is branch point", effect->op()->mnemonic(),
1100 effect->id()); 1070 effect->id());
1101 } 1071 }
1102 TRACE("\n"); 1072 TRACE("\n");
1103 } 1073 }
1104 } 1074 }
1105 1075
1106
1107 void EscapeAnalysis::ProcessStart(Node* node) { 1076 void EscapeAnalysis::ProcessStart(Node* node) {
1108 DCHECK_EQ(node->opcode(), IrOpcode::kStart); 1077 DCHECK_EQ(node->opcode(), IrOpcode::kStart);
1109 virtual_states_[node->id()] = 1078 virtual_states_[node->id()] =
1110 new (zone()) VirtualState(node->id(), zone(), AliasCount()); 1079 new (zone()) VirtualState(node, zone(), AliasCount());
1111 } 1080 }
1112 1081
1113
1114 bool EscapeAnalysis::ProcessEffectPhi(Node* node) { 1082 bool EscapeAnalysis::ProcessEffectPhi(Node* node) {
1115 DCHECK_EQ(node->opcode(), IrOpcode::kEffectPhi); 1083 DCHECK_EQ(node->opcode(), IrOpcode::kEffectPhi);
1116 bool changed = false; 1084 bool changed = false;
1117 1085
1118 VirtualState* mergeState = virtual_states_[node->id()]; 1086 VirtualState* mergeState = virtual_states_[node->id()];
1119 if (!mergeState) { 1087 if (!mergeState) {
1120 mergeState = new (zone()) VirtualState(node->id(), zone(), AliasCount()); 1088 mergeState = new (zone()) VirtualState(node, zone(), AliasCount());
1121 virtual_states_[node->id()] = mergeState; 1089 virtual_states_[node->id()] = mergeState;
1122 changed = true; 1090 changed = true;
1123 TRACE("Effect Phi #%d got new virtual state %p.\n", node->id(), 1091 TRACE("Effect Phi #%d got new virtual state %p.\n", node->id(),
1124 static_cast<void*>(mergeState)); 1092 static_cast<void*>(mergeState));
1125 } 1093 }
1126 1094
1127 cache_->Clear(); 1095 cache_->Clear();
1128 1096
1129 TRACE("At Effect Phi #%d, merging states into %p:", node->id(), 1097 TRACE("At Effect Phi #%d, merging states into %p:", node->id(),
1130 static_cast<void*>(mergeState)); 1098 static_cast<void*>(mergeState));
1131 1099
1132 for (int i = 0; i < node->op()->EffectInputCount(); ++i) { 1100 for (int i = 0; i < node->op()->EffectInputCount(); ++i) {
1133 Node* input = NodeProperties::GetEffectInput(node, i); 1101 Node* input = NodeProperties::GetEffectInput(node, i);
1134 VirtualState* state = virtual_states_[input->id()]; 1102 VirtualState* state = virtual_states_[input->id()];
1135 if (state) { 1103 if (state) {
1136 cache_->states().push_back(state); 1104 cache_->states().push_back(state);
1137 if (state == mergeState) { 1105 if (state == mergeState) {
1138 mergeState = 1106 mergeState = new (zone()) VirtualState(node, zone(), AliasCount());
1139 new (zone()) VirtualState(node->id(), zone(), AliasCount());
1140 virtual_states_[node->id()] = mergeState; 1107 virtual_states_[node->id()] = mergeState;
1141 changed = true; 1108 changed = true;
1142 } 1109 }
1143 } 1110 }
1144 TRACE(" %p (from %d %s)", static_cast<void*>(state), input->id(), 1111 TRACE(" %p (from %d %s)", static_cast<void*>(state), input->id(),
1145 input->op()->mnemonic()); 1112 input->op()->mnemonic());
1146 } 1113 }
1147 TRACE("\n"); 1114 TRACE("\n");
1148 1115
1149 if (cache_->states().size() == 0) { 1116 if (cache_->states().size() == 0) {
1150 return changed; 1117 return changed;
1151 } 1118 }
1152 1119
1153 changed = mergeState->MergeFrom(cache_, zone(), graph(), common(), 1120 changed = mergeState->MergeFrom(cache_, zone(), graph(), common(),
1154 NodeProperties::GetControlInput(node), 1121 NodeProperties::GetControlInput(node),
1155 node->op()->EffectInputCount()) || 1122 node->op()->EffectInputCount()) ||
1156 changed; 1123 changed;
1157 1124
1158 TRACE("Merge %s the node.\n", changed ? "changed" : "did not change"); 1125 TRACE("Merge %s the node.\n", changed ? "changed" : "did not change");
1159 1126
1160 if (changed) { 1127 if (changed) {
1161 status_analysis_.ResizeStatusVector(); 1128 status_analysis_.ResizeStatusVector();
1162 } 1129 }
1163 return changed; 1130 return changed;
1164 } 1131 }
1165 1132
1166
1167 void EscapeAnalysis::ProcessAllocation(Node* node) { 1133 void EscapeAnalysis::ProcessAllocation(Node* node) {
1168 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); 1134 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate);
1169 ForwardVirtualState(node); 1135 ForwardVirtualState(node);
1170 VirtualState* state = virtual_states_[node->id()]; 1136 VirtualState* state = virtual_states_[node->id()];
1171 Alias alias = GetAlias(node->id()); 1137 Alias alias = GetAlias(node->id());
1172 1138
1173 // Check if we have already processed this node. 1139 // Check if we have already processed this node.
1174 if (state->VirtualObjectFromAlias(alias)) { 1140 if (state->VirtualObjectFromAlias(alias)) {
1175 return; 1141 return;
1176 } 1142 }
1177 1143
1178 state = CopyForModificationAt(state, node); 1144 if (state->owner()->opcode() == IrOpcode::kEffectPhi) {
1145 state = CopyForModificationAt(state, node);
1146 }
1179 1147
1180 NumberMatcher size(node->InputAt(0)); 1148 NumberMatcher size(node->InputAt(0));
1181 DCHECK(node->InputAt(0)->opcode() != IrOpcode::kInt32Constant && 1149 DCHECK(node->InputAt(0)->opcode() != IrOpcode::kInt32Constant &&
1182 node->InputAt(0)->opcode() != IrOpcode::kInt64Constant && 1150 node->InputAt(0)->opcode() != IrOpcode::kInt64Constant &&
1183 node->InputAt(0)->opcode() != IrOpcode::kFloat32Constant && 1151 node->InputAt(0)->opcode() != IrOpcode::kFloat32Constant &&
1184 node->InputAt(0)->opcode() != IrOpcode::kFloat64Constant); 1152 node->InputAt(0)->opcode() != IrOpcode::kFloat64Constant);
1185 if (size.HasValue()) { 1153 if (size.HasValue()) {
1186 state->SetVirtualObject( 1154 VirtualObject* obj = new (zone()) VirtualObject(
1187 alias, new (zone()) VirtualObject(node->id(), state, zone(), 1155 node->id(), state, zone(), size.Value() / kPointerSize, false);
1188 size.Value() / kPointerSize, false)); 1156 state->SetVirtualObject(alias, obj);
1189 } else { 1157 } else {
1190 state->SetVirtualObject( 1158 state->SetVirtualObject(
1191 alias, new (zone()) VirtualObject(node->id(), state, zone())); 1159 alias, new (zone()) VirtualObject(node->id(), state, zone()));
1192 } 1160 }
1193 } 1161 }
1194 1162
1195
1196 void EscapeAnalysis::ProcessFinishRegion(Node* node) { 1163 void EscapeAnalysis::ProcessFinishRegion(Node* node) {
1197 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion); 1164 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion);
1198 ForwardVirtualState(node); 1165 ForwardVirtualState(node);
1199 Node* allocation = NodeProperties::GetValueInput(node, 0); 1166 Node* allocation = NodeProperties::GetValueInput(node, 0);
1200 if (allocation->opcode() == IrOpcode::kAllocate) { 1167 if (allocation->opcode() == IrOpcode::kAllocate) {
1201 VirtualState* state = virtual_states_[node->id()]; 1168 VirtualState* state = virtual_states_[node->id()];
1202 VirtualObject* obj = state->VirtualObjectFromAlias(GetAlias(node->id())); 1169 VirtualObject* obj = state->VirtualObjectFromAlias(GetAlias(node->id()));
1203 DCHECK_NOT_NULL(obj); 1170 DCHECK_NOT_NULL(obj);
1204 obj->SetInitialized(); 1171 obj->SetInitialized();
1205 } 1172 }
1206 } 1173 }
1207 1174
1208
1209 Node* EscapeAnalysis::replacement(NodeId id) { 1175 Node* EscapeAnalysis::replacement(NodeId id) {
1210 if (id >= replacements_.size()) return nullptr; 1176 if (id >= replacements_.size()) return nullptr;
1211 return replacements_[id]; 1177 return replacements_[id];
1212 } 1178 }
1213 1179
1214
1215 Node* EscapeAnalysis::replacement(Node* node) { 1180 Node* EscapeAnalysis::replacement(Node* node) {
1216 return replacement(node->id()); 1181 return replacement(node->id());
1217 } 1182 }
1218 1183
1219
1220 bool EscapeAnalysis::SetReplacement(Node* node, Node* rep) { 1184 bool EscapeAnalysis::SetReplacement(Node* node, Node* rep) {
1221 bool changed = replacements_[node->id()] != rep; 1185 bool changed = replacements_[node->id()] != rep;
1222 replacements_[node->id()] = rep; 1186 replacements_[node->id()] = rep;
1223 return changed; 1187 return changed;
1224 } 1188 }
1225 1189
1226
1227 bool EscapeAnalysis::UpdateReplacement(VirtualState* state, Node* node, 1190 bool EscapeAnalysis::UpdateReplacement(VirtualState* state, Node* node,
1228 Node* rep) { 1191 Node* rep) {
1229 if (SetReplacement(node, rep)) { 1192 if (SetReplacement(node, rep)) {
1230 if (rep) { 1193 if (rep) {
1231 TRACE("Replacement of #%d is #%d (%s)\n", node->id(), rep->id(), 1194 TRACE("Replacement of #%d is #%d (%s)\n", node->id(), rep->id(),
1232 rep->op()->mnemonic()); 1195 rep->op()->mnemonic());
1233 } else { 1196 } else {
1234 TRACE("Replacement of #%d cleared\n", node->id()); 1197 TRACE("Replacement of #%d cleared\n", node->id());
1235 } 1198 }
1236 return true; 1199 return true;
1237 } 1200 }
1238 return false; 1201 return false;
1239 } 1202 }
1240 1203
1241
1242 Node* EscapeAnalysis::ResolveReplacement(Node* node) { 1204 Node* EscapeAnalysis::ResolveReplacement(Node* node) {
1243 while (replacement(node)) { 1205 while (replacement(node)) {
1244 node = replacement(node); 1206 node = replacement(node);
1245 } 1207 }
1246 return node; 1208 return node;
1247 } 1209 }
1248 1210
1249
1250 Node* EscapeAnalysis::GetReplacement(Node* node) { 1211 Node* EscapeAnalysis::GetReplacement(Node* node) {
1251 return GetReplacement(node->id()); 1212 return GetReplacement(node->id());
1252 } 1213 }
1253 1214
1254
1255 Node* EscapeAnalysis::GetReplacement(NodeId id) { 1215 Node* EscapeAnalysis::GetReplacement(NodeId id) {
1256 Node* node = nullptr; 1216 Node* node = nullptr;
1257 while (replacement(id)) { 1217 while (replacement(id)) {
1258 node = replacement(id); 1218 node = replacement(id);
1259 id = node->id(); 1219 id = node->id();
1260 } 1220 }
1261 return node; 1221 return node;
1262 } 1222 }
1263 1223
1264
1265 bool EscapeAnalysis::IsVirtual(Node* node) { 1224 bool EscapeAnalysis::IsVirtual(Node* node) {
1266 if (node->id() >= status_analysis_.GetStatusVectorSize()) { 1225 if (node->id() >= status_analysis_.GetStatusVectorSize()) {
1267 return false; 1226 return false;
1268 } 1227 }
1269 return status_analysis_.IsVirtual(node); 1228 return status_analysis_.IsVirtual(node);
1270 } 1229 }
1271 1230
1272
1273 bool EscapeAnalysis::IsEscaped(Node* node) { 1231 bool EscapeAnalysis::IsEscaped(Node* node) {
1274 if (node->id() >= status_analysis_.GetStatusVectorSize()) { 1232 if (node->id() >= status_analysis_.GetStatusVectorSize()) {
1275 return false; 1233 return false;
1276 } 1234 }
1277 return status_analysis_.IsEscaped(node); 1235 return status_analysis_.IsEscaped(node);
1278 } 1236 }
1279 1237
1280
1281 bool EscapeAnalysis::SetEscaped(Node* node) { 1238 bool EscapeAnalysis::SetEscaped(Node* node) {
1282 return status_analysis_.SetEscaped(node); 1239 return status_analysis_.SetEscaped(node);
1283 } 1240 }
1284 1241
1285
1286 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) { 1242 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) {
1287 if (VirtualState* states = virtual_states_[at->id()]) { 1243 if (VirtualState* states = virtual_states_[at->id()]) {
1288 return states->VirtualObjectFromAlias(GetAlias(id)); 1244 return states->VirtualObjectFromAlias(GetAlias(id));
1289 } 1245 }
1290 return nullptr; 1246 return nullptr;
1291 } 1247 }
1292 1248
1293
1294 VirtualObject* EscapeAnalysis::ResolveVirtualObject(VirtualState* state, 1249 VirtualObject* EscapeAnalysis::ResolveVirtualObject(VirtualState* state,
1295 Node* node) { 1250 Node* node) {
1296 return GetVirtualObject(state, ResolveReplacement(node)); 1251 return GetVirtualObject(state, ResolveReplacement(node));
1297 } 1252 }
1298 1253
1299
1300 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) { 1254 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) {
1301 DCHECK(IsVirtual(left) && IsVirtual(right)); 1255 DCHECK(IsVirtual(left) && IsVirtual(right));
1302 left = ResolveReplacement(left); 1256 left = ResolveReplacement(left);
1303 right = ResolveReplacement(right); 1257 right = ResolveReplacement(right);
1304 if (IsEquivalentPhi(left, right)) { 1258 if (IsEquivalentPhi(left, right)) {
1305 return true; 1259 return true;
1306 } 1260 }
1307 return false; 1261 return false;
1308 } 1262 }
1309 1263
1310
1311 int EscapeAnalysis::OffsetFromAccess(Node* node) { 1264 int EscapeAnalysis::OffsetFromAccess(Node* node) {
1312 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0); 1265 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0);
1313 return OpParameter<FieldAccess>(node).offset / kPointerSize; 1266 return OpParameter<FieldAccess>(node).offset / kPointerSize;
1314 } 1267 }
1315 1268
1316
1317 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node, 1269 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node,
1318 VirtualState* state) { 1270 VirtualState* state) {
1319 TRACE("Load #%d from phi #%d", node->id(), from->id()); 1271 TRACE("Load #%d from phi #%d", node->id(), from->id());
1320 1272
1321 cache_->fields().clear(); 1273 cache_->fields().clear();
1322 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { 1274 for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
1323 Node* input = NodeProperties::GetValueInput(node, i); 1275 Node* input = NodeProperties::GetValueInput(node, i);
1324 cache_->fields().push_back(input); 1276 cache_->fields().push_back(input);
1325 } 1277 }
1326 1278
(...skipping 16 matching lines...) Expand all
1343 TRACE(" has already phi #%d.\n", rep->id()); 1295 TRACE(" has already phi #%d.\n", rep->id());
1344 } 1296 }
1345 } else { 1297 } else {
1346 TRACE(" has incomplete field info.\n"); 1298 TRACE(" has incomplete field info.\n");
1347 } 1299 }
1348 } else { 1300 } else {
1349 TRACE(" has incomplete virtual object info.\n"); 1301 TRACE(" has incomplete virtual object info.\n");
1350 } 1302 }
1351 } 1303 }
1352 1304
1353
1354 void EscapeAnalysis::ProcessLoadField(Node* node) { 1305 void EscapeAnalysis::ProcessLoadField(Node* node) {
1355 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField); 1306 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField);
1356 ForwardVirtualState(node); 1307 ForwardVirtualState(node);
1357 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); 1308 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1358 VirtualState* state = virtual_states_[node->id()]; 1309 VirtualState* state = virtual_states_[node->id()];
1359 if (VirtualObject* object = GetVirtualObject(state, from)) { 1310 if (VirtualObject* object = GetVirtualObject(state, from)) {
1360 int offset = OffsetFromAccess(node); 1311 int offset = OffsetFromAccess(node);
1361 if (!object->IsTracked() || 1312 if (!object->IsTracked() ||
1362 static_cast<size_t>(offset) >= object->field_count()) { 1313 static_cast<size_t>(offset) >= object->field_count()) {
1363 return; 1314 return;
1364 } 1315 }
1365 Node* value = object->GetField(offset); 1316 Node* value = object->GetField(offset);
1366 if (value) { 1317 if (value) {
1367 value = ResolveReplacement(value); 1318 value = ResolveReplacement(value);
1368 } 1319 }
1369 // Record that the load has this alias. 1320 // Record that the load has this alias.
1370 UpdateReplacement(state, node, value); 1321 UpdateReplacement(state, node, value);
1371 } else if (from->opcode() == IrOpcode::kPhi && 1322 } else if (from->opcode() == IrOpcode::kPhi &&
1372 OpParameter<FieldAccess>(node).offset % kPointerSize == 0) { 1323 OpParameter<FieldAccess>(node).offset % kPointerSize == 0) {
1373 int offset = OffsetFromAccess(node); 1324 int offset = OffsetFromAccess(node);
1374 // Only binary phis are supported for now. 1325 // Only binary phis are supported for now.
1375 ProcessLoadFromPhi(offset, from, node, state); 1326 ProcessLoadFromPhi(offset, from, node, state);
1376 } else { 1327 } else {
1377 UpdateReplacement(state, node, nullptr); 1328 UpdateReplacement(state, node, nullptr);
1378 } 1329 }
1379 } 1330 }
1380 1331
1381
1382 void EscapeAnalysis::ProcessLoadElement(Node* node) { 1332 void EscapeAnalysis::ProcessLoadElement(Node* node) {
1383 DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement); 1333 DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement);
1384 ForwardVirtualState(node); 1334 ForwardVirtualState(node);
1385 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); 1335 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1386 VirtualState* state = virtual_states_[node->id()]; 1336 VirtualState* state = virtual_states_[node->id()];
1387 Node* index_node = node->InputAt(1); 1337 Node* index_node = node->InputAt(1);
1388 NumberMatcher index(index_node); 1338 NumberMatcher index(index_node);
1389 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant && 1339 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant &&
1390 index_node->opcode() != IrOpcode::kInt64Constant && 1340 index_node->opcode() != IrOpcode::kInt64Constant &&
1391 index_node->opcode() != IrOpcode::kFloat32Constant && 1341 index_node->opcode() != IrOpcode::kFloat32Constant &&
(...skipping 29 matching lines...) Expand all
1421 if (SetEscaped(from)) { 1371 if (SetEscaped(from)) {
1422 TRACE( 1372 TRACE(
1423 "Setting #%d (%s) to escaped because load element #%d from non-const " 1373 "Setting #%d (%s) to escaped because load element #%d from non-const "
1424 "index #%d (%s)\n", 1374 "index #%d (%s)\n",
1425 from->id(), from->op()->mnemonic(), node->id(), index_node->id(), 1375 from->id(), from->op()->mnemonic(), node->id(), index_node->id(),
1426 index_node->op()->mnemonic()); 1376 index_node->op()->mnemonic());
1427 } 1377 }
1428 } 1378 }
1429 } 1379 }
1430 1380
1431
1432 void EscapeAnalysis::ProcessStoreField(Node* node) { 1381 void EscapeAnalysis::ProcessStoreField(Node* node) {
1433 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField); 1382 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField);
1434 ForwardVirtualState(node); 1383 ForwardVirtualState(node);
1435 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); 1384 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1436 VirtualState* state = virtual_states_[node->id()]; 1385 VirtualState* state = virtual_states_[node->id()];
1437 VirtualObject* obj = GetVirtualObject(state, to); 1386 VirtualObject* obj = GetVirtualObject(state, to);
1438 int offset = OffsetFromAccess(node); 1387 int offset = OffsetFromAccess(node);
1439 if (obj && obj->IsTracked() && 1388 if (obj && obj->IsTracked() &&
1440 static_cast<size_t>(offset) < obj->field_count()) { 1389 static_cast<size_t>(offset) < obj->field_count()) {
1441 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 1)); 1390 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 1));
1442 if (obj->GetField(offset) != val) { 1391 if (obj->GetField(offset) != val) {
1443 obj = CopyForModificationAt(obj, state, node); 1392 obj = CopyForModificationAt(obj, state, node);
1444 obj->SetField(offset, val); 1393 obj->SetField(offset, val);
1445 } 1394 }
1446 } 1395 }
1447 } 1396 }
1448 1397
1449
1450 void EscapeAnalysis::ProcessStoreElement(Node* node) { 1398 void EscapeAnalysis::ProcessStoreElement(Node* node) {
1451 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement); 1399 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement);
1452 ForwardVirtualState(node); 1400 ForwardVirtualState(node);
1453 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); 1401 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1454 Node* index_node = node->InputAt(1); 1402 Node* index_node = node->InputAt(1);
1455 NumberMatcher index(index_node); 1403 NumberMatcher index(index_node);
1456 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant && 1404 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant &&
1457 index_node->opcode() != IrOpcode::kInt64Constant && 1405 index_node->opcode() != IrOpcode::kInt64Constant &&
1458 index_node->opcode() != IrOpcode::kFloat32Constant && 1406 index_node->opcode() != IrOpcode::kFloat32Constant &&
1459 index_node->opcode() != IrOpcode::kFloat64Constant); 1407 index_node->opcode() != IrOpcode::kFloat64Constant);
(...skipping 26 matching lines...) Expand all
1486 if (!obj->AllFieldsClear()) { 1434 if (!obj->AllFieldsClear()) {
1487 obj = CopyForModificationAt(obj, state, node); 1435 obj = CopyForModificationAt(obj, state, node);
1488 obj->ClearAllFields(); 1436 obj->ClearAllFields();
1489 TRACE("Cleared all fields of @%d:#%d\n", GetAlias(obj->id()), 1437 TRACE("Cleared all fields of @%d:#%d\n", GetAlias(obj->id()),
1490 obj->id()); 1438 obj->id());
1491 } 1439 }
1492 } 1440 }
1493 } 1441 }
1494 } 1442 }
1495 1443
1496
1497 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) { 1444 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) {
1498 if ((node->opcode() == IrOpcode::kFinishRegion || 1445 if ((node->opcode() == IrOpcode::kFinishRegion ||
1499 node->opcode() == IrOpcode::kAllocate) && 1446 node->opcode() == IrOpcode::kAllocate) &&
1500 IsVirtual(node)) { 1447 IsVirtual(node)) {
1501 if (VirtualObject* vobj = 1448 if (VirtualObject* vobj =
1502 ResolveVirtualObject(virtual_states_[effect->id()], node)) { 1449 ResolveVirtualObject(virtual_states_[effect->id()], node)) {
1503 if (Node* object_state = vobj->GetObjectState()) { 1450 if (Node* object_state = vobj->GetObjectState()) {
1504 return object_state; 1451 return object_state;
1505 } else { 1452 } else {
1506 cache_->fields().clear(); 1453 cache_->fields().clear();
(...skipping 22 matching lines...) Expand all
1529 } 1476 }
1530 } 1477 }
1531 } 1478 }
1532 return new_object_state; 1479 return new_object_state;
1533 } 1480 }
1534 } 1481 }
1535 } 1482 }
1536 return nullptr; 1483 return nullptr;
1537 } 1484 }
1538 1485
1539
1540 void EscapeAnalysis::DebugPrintObject(VirtualObject* object, Alias alias) { 1486 void EscapeAnalysis::DebugPrintObject(VirtualObject* object, Alias alias) {
1541 PrintF(" Alias @%d: Object #%d with %zu fields\n", alias, object->id(), 1487 PrintF(" Alias @%d: Object #%d with %zu fields\n", alias, object->id(),
1542 object->field_count()); 1488 object->field_count());
1543 for (size_t i = 0; i < object->field_count(); ++i) { 1489 for (size_t i = 0; i < object->field_count(); ++i) {
1544 if (Node* f = object->GetField(i)) { 1490 if (Node* f = object->GetField(i)) {
1545 PrintF(" Field %zu = #%d (%s)\n", i, f->id(), f->op()->mnemonic()); 1491 PrintF(" Field %zu = #%d (%s)\n", i, f->id(), f->op()->mnemonic());
1546 } 1492 }
1547 } 1493 }
1548 } 1494 }
1549 1495
1550
1551 void EscapeAnalysis::DebugPrintState(VirtualState* state) { 1496 void EscapeAnalysis::DebugPrintState(VirtualState* state) {
1552 PrintF("Dumping virtual state %p\n", static_cast<void*>(state)); 1497 PrintF("Dumping virtual state %p\n", static_cast<void*>(state));
1553 for (Alias alias = 0; alias < AliasCount(); ++alias) { 1498 for (Alias alias = 0; alias < AliasCount(); ++alias) {
1554 if (VirtualObject* object = state->VirtualObjectFromAlias(alias)) { 1499 if (VirtualObject* object = state->VirtualObjectFromAlias(alias)) {
1555 DebugPrintObject(object, alias); 1500 DebugPrintObject(object, alias);
1556 } 1501 }
1557 } 1502 }
1558 } 1503 }
1559 1504
1560
1561 void EscapeAnalysis::DebugPrint() { 1505 void EscapeAnalysis::DebugPrint() {
1562 ZoneVector<VirtualState*> object_states(zone()); 1506 ZoneVector<VirtualState*> object_states(zone());
1563 for (NodeId id = 0; id < virtual_states_.size(); id++) { 1507 for (NodeId id = 0; id < virtual_states_.size(); id++) {
1564 if (VirtualState* states = virtual_states_[id]) { 1508 if (VirtualState* states = virtual_states_[id]) {
1565 if (std::find(object_states.begin(), object_states.end(), states) == 1509 if (std::find(object_states.begin(), object_states.end(), states) ==
1566 object_states.end()) { 1510 object_states.end()) {
1567 object_states.push_back(states); 1511 object_states.push_back(states);
1568 } 1512 }
1569 } 1513 }
1570 } 1514 }
1571 for (size_t n = 0; n < object_states.size(); n++) { 1515 for (size_t n = 0; n < object_states.size(); n++) {
1572 DebugPrintState(object_states[n]); 1516 DebugPrintState(object_states[n]);
1573 } 1517 }
1574 } 1518 }
1575 1519
1576
1577 VirtualObject* EscapeAnalysis::GetVirtualObject(VirtualState* state, 1520 VirtualObject* EscapeAnalysis::GetVirtualObject(VirtualState* state,
1578 Node* node) { 1521 Node* node) {
1579 if (node->id() >= status_analysis_.GetAliasMap().size()) return nullptr; 1522 if (node->id() >= status_analysis_.GetAliasMap().size()) return nullptr;
1580 Alias alias = GetAlias(node->id()); 1523 Alias alias = GetAlias(node->id());
1581 if (alias >= state->size()) return nullptr; 1524 if (alias >= state->size()) return nullptr;
1582 return state->VirtualObjectFromAlias(alias); 1525 return state->VirtualObjectFromAlias(alias);
1583 } 1526 }
1584 1527
1585
1586 bool EscapeAnalysis::ExistsVirtualAllocate() { 1528 bool EscapeAnalysis::ExistsVirtualAllocate() {
1587 for (size_t id = 0; id < status_analysis_.GetAliasMap().size(); ++id) { 1529 for (size_t id = 0; id < status_analysis_.GetAliasMap().size(); ++id) {
1588 Alias alias = GetAlias(static_cast<NodeId>(id)); 1530 Alias alias = GetAlias(static_cast<NodeId>(id));
1589 if (alias < EscapeStatusAnalysis::kUntrackable) { 1531 if (alias < EscapeStatusAnalysis::kUntrackable) {
1590 if (status_analysis_.IsVirtual(static_cast<int>(id))) { 1532 if (status_analysis_.IsVirtual(static_cast<int>(id))) {
1591 return true; 1533 return true;
1592 } 1534 }
1593 } 1535 }
1594 } 1536 }
1595 return false; 1537 return false;
1596 } 1538 }
1597 1539
1598 } // namespace compiler 1540 } // namespace compiler
1599 } // namespace internal 1541 } // namespace internal
1600 } // namespace v8 1542 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/escape-analysis.h ('k') | test/mjsunit/mjsunit.status » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698