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

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

Issue 1499143002: Improve escape analysis (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Fix bug Created 5 years 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') | src/compiler/escape-analysis-reducer.h » ('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 "src/base/flags.h" 7 #include "src/base/flags.h"
8 #include "src/bootstrapper.h" 8 #include "src/bootstrapper.h"
9 #include "src/compilation-dependencies.h" 9 #include "src/compilation-dependencies.h"
10 #include "src/compiler/common-operator.h" 10 #include "src/compiler/common-operator.h"
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
56 } 56 }
57 bool IsVirtual() const { return status_ == kTracked; } 57 bool IsVirtual() const { return status_ == kTracked; }
58 bool IsTracked() const { return status_ != kUntracked; } 58 bool IsTracked() const { return status_ != kUntracked; }
59 Node* GetReplacement() { return replacement_; } 59 Node* GetReplacement() { return replacement_; }
60 bool SetReplacement(Node* node) { 60 bool SetReplacement(Node* node) {
61 bool changed = replacement_ != node; 61 bool changed = replacement_ != node;
62 replacement_ = node; 62 replacement_ = node;
63 return changed; 63 return changed;
64 } 64 }
65 65
66 size_t fields() { return fields_.size(); } 66 Node** fields_array() { return &fields_.front(); }
67 bool ResizeFields(size_t field_number) { 67 size_t field_count() { return fields_.size(); }
68 if (field_number != fields_.size()) { 68 bool ResizeFields(size_t field_count) {
69 fields_.resize(field_number); 69 if (field_count != fields_.size()) {
70 fields_.resize(field_count);
70 return true; 71 return true;
71 } 72 }
72 return false; 73 return false;
73 } 74 }
74 75 bool ClearAllFields() {
76 bool changed = false;
77 for (size_t i = 0; i < fields_.size(); ++i) {
78 if (fields_[i] != nullptr) {
79 fields_[i] = nullptr;
80 changed = true;
81 }
82 }
83 return changed;
84 }
75 bool UpdateFrom(const VirtualObject& other); 85 bool UpdateFrom(const VirtualObject& other);
76 86
77 NodeId id() { return id_; } 87 NodeId id() { return id_; }
78 void id(NodeId id) { id_ = id; } 88 void id(NodeId id) { id_ = id; }
79 89
80 private: 90 private:
81 NodeId id_; 91 NodeId id_;
82 Status status_; 92 Status status_;
83 ZoneVector<Node*> fields_; 93 ZoneVector<Node*> fields_;
84 Node* replacement_; 94 Node* replacement_;
(...skipping 20 matching lines...) Expand all
105 115
106 116
107 // ------------------------------VirtualState----------------------------------- 117 // ------------------------------VirtualState-----------------------------------
108 118
109 119
110 class VirtualState : public ZoneObject { 120 class VirtualState : public ZoneObject {
111 public: 121 public:
112 VirtualState(Zone* zone, size_t size); 122 VirtualState(Zone* zone, size_t size);
113 VirtualState(const VirtualState& states); 123 VirtualState(const VirtualState& states);
114 124
125 VirtualObject* ResolveVirtualObject(Node* node);
115 VirtualObject* GetVirtualObject(Node* node); 126 VirtualObject* GetVirtualObject(Node* node);
116 VirtualObject* GetVirtualObject(size_t id); 127 VirtualObject* GetVirtualObject(size_t id);
117 VirtualObject* GetOrCreateTrackedVirtualObject(NodeId id, Zone* zone); 128 VirtualObject* GetOrCreateTrackedVirtualObject(NodeId id, Zone* zone);
118 void SetVirtualObject(NodeId id, VirtualObject* state); 129 void SetVirtualObject(NodeId id, VirtualObject* state);
119 void LastChangedAt(Node* node) { last_changed_ = node; } 130 void LastChangedAt(Node* node) { last_changed_ = node; }
120 Node* GetLastChanged() { return last_changed_; } 131 Node* GetLastChanged() { return last_changed_; }
121 bool UpdateFrom(NodeId id, VirtualObject* state, Zone* zone); 132 bool UpdateFrom(NodeId id, VirtualObject* state, Zone* zone);
122 Node* ResolveReplacement(Node* node); 133 Node* ResolveReplacement(Node* node);
123 bool UpdateReplacement(Node* node, Node* rep, Zone* zone); 134 bool UpdateReplacement(Node* node, Node* rep, Zone* zone);
124 bool UpdateFrom(VirtualState* state, Zone* zone); 135 bool UpdateFrom(VirtualState* state, Zone* zone);
(...skipping 25 matching lines...) Expand all
150 } 161 }
151 } 162 }
152 for (size_t i = 0; i < state.info_.size(); ++i) { 163 for (size_t i = 0; i < state.info_.size(); ++i) {
153 if (state.info_[i] && state.info_[i]->id() != i) { 164 if (state.info_[i] && state.info_[i]->id() != i) {
154 info_[i] = info_[state.info_[i]->id()]; 165 info_[i] = info_[state.info_[i]->id()];
155 } 166 }
156 } 167 }
157 } 168 }
158 169
159 170
160 VirtualObject* VirtualState::GetVirtualObject(size_t id) { return info_[id]; } 171 VirtualObject* VirtualState::GetVirtualObject(size_t id) {
172 if (id >= info_.size()) return nullptr;
173 return info_[id];
174 }
161 175
162 176
163 VirtualObject* VirtualState::GetVirtualObject(Node* node) { 177 VirtualObject* VirtualState::GetVirtualObject(Node* node) {
164 return GetVirtualObject(node->id()); 178 return GetVirtualObject(node->id());
165 } 179 }
166 180
167 181
182 VirtualObject* VirtualState::ResolveVirtualObject(Node* node) {
183 VirtualObject* obj = GetVirtualObject(node->id());
184 while (obj && !obj->IsTracked() && obj->GetReplacement() &&
185 GetVirtualObject(obj->GetReplacement())) {
186 obj = GetVirtualObject(obj->GetReplacement());
187 }
188 return obj;
189 }
190
191
168 VirtualObject* VirtualState::GetOrCreateTrackedVirtualObject(NodeId id, 192 VirtualObject* VirtualState::GetOrCreateTrackedVirtualObject(NodeId id,
169 Zone* zone) { 193 Zone* zone) {
170 if (VirtualObject* obj = GetVirtualObject(id)) { 194 if (VirtualObject* obj = GetVirtualObject(id)) {
171 return obj; 195 return obj;
172 } 196 }
173 VirtualObject* obj = new (zone) VirtualObject(id, zone, 0); 197 VirtualObject* obj = new (zone) VirtualObject(id, zone, 0);
174 SetVirtualObject(id, obj); 198 SetVirtualObject(id, obj);
175 return obj; 199 return obj;
176 } 200 }
177 201
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
239 bool changed = false; 263 bool changed = false;
240 for (NodeId id = 0; id < std::min(left->size(), right->size()); ++id) { 264 for (NodeId id = 0; id < std::min(left->size(), right->size()); ++id) {
241 VirtualObject* ls = left->GetVirtualObject(id); 265 VirtualObject* ls = left->GetVirtualObject(id);
242 VirtualObject* rs = right->GetVirtualObject(id); 266 VirtualObject* rs = right->GetVirtualObject(id);
243 267
244 if (ls != nullptr && rs != nullptr) { 268 if (ls != nullptr && rs != nullptr) {
245 if (FLAG_trace_turbo_escape) { 269 if (FLAG_trace_turbo_escape) {
246 PrintF(" Merging fields of #%d\n", id); 270 PrintF(" Merging fields of #%d\n", id);
247 } 271 }
248 VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject(id, zone); 272 VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject(id, zone);
249 size_t fields = std::max(ls->fields(), rs->fields()); 273 size_t fields = std::max(ls->field_count(), rs->field_count());
250 changed = mergeObject->ResizeFields(fields) || changed; 274 changed = mergeObject->ResizeFields(fields) || changed;
251 for (size_t i = 0; i < fields; ++i) { 275 for (size_t i = 0; i < fields; ++i) {
252 if (ls->GetField(i) == rs->GetField(i)) { 276 if (ls->GetField(i) == rs->GetField(i)) {
253 changed = mergeObject->SetField(i, ls->GetField(i)) || changed; 277 changed = mergeObject->SetField(i, ls->GetField(i)) || changed;
254 if (FLAG_trace_turbo_escape && ls->GetField(i)) { 278 if (FLAG_trace_turbo_escape && ls->GetField(i)) {
255 PrintF(" Field %zu agree on rep #%d\n", i, 279 PrintF(" Field %zu agree on rep #%d\n", i,
256 ls->GetField(i)->id()); 280 ls->GetField(i)->id());
257 } 281 }
258 } else if (ls->GetField(i) != nullptr && rs->GetField(i) != nullptr) { 282 } else if (ls->GetField(i) != nullptr && rs->GetField(i) != nullptr) {
259 Node* phi = graph->NewNode(common->Phi(kMachAnyTagged, 2), 283 Node* rep = mergeObject->GetField(i);
260 ls->GetField(i), rs->GetField(i), control); 284 if (!rep || rep->opcode() != IrOpcode::kPhi ||
261 if (mergeObject->SetField(i, phi)) { 285 NodeProperties::GetValueInput(rep, 0) != ls->GetField(i) ||
286 NodeProperties::GetValueInput(rep, 1) != rs->GetField(i)) {
287 Node* phi =
288 graph->NewNode(common->Phi(kMachAnyTagged, 2), ls->GetField(i),
289 rs->GetField(i), control);
290 if (mergeObject->SetField(i, phi)) {
291 if (FLAG_trace_turbo_escape) {
292 PrintF(" Creating Phi #%d as merge of #%d and #%d\n",
293 phi->id(), ls->GetField(i)->id(), rs->GetField(i)->id());
294 }
295 changed = true;
296 }
297 } else {
262 if (FLAG_trace_turbo_escape) { 298 if (FLAG_trace_turbo_escape) {
263 PrintF(" Creating Phi #%d as merge of #%d and #%d\n", 299 PrintF(" Retaining Phi #%d as merge of #%d and #%d\n",
264 phi->id(), ls->GetField(i)->id(), rs->GetField(i)->id()); 300 rep->id(), ls->GetField(i)->id(), rs->GetField(i)->id());
265 } 301 }
266 changed = true;
267 } 302 }
268 } else { 303 } else {
269 changed = mergeObject->SetField(i, nullptr) || changed; 304 changed = mergeObject->SetField(i, nullptr) || changed;
270 } 305 }
271 } 306 }
307 } else if (ls) {
308 VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject(id, zone);
309 changed = mergeObject->UpdateFrom(*ls) || changed;
310 } else if (rs) {
311 VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject(id, zone);
312 changed = mergeObject->UpdateFrom(*rs) || changed;
272 } 313 }
273 } 314 }
274 return changed; 315 return changed;
275 } 316 }
276 317
277 318
278 Node* VirtualState::ResolveReplacement(Node* node) { 319 Node* VirtualState::ResolveReplacement(Node* node) {
279 if (VirtualObject* obj = GetVirtualObject(node)) { 320 Node* replacement = node;
280 if (Node* rep = obj->GetReplacement()) { 321 VirtualObject* obj = GetVirtualObject(node);
281 return rep; 322 while (obj != nullptr && obj->GetReplacement()) {
282 } 323 replacement = obj->GetReplacement();
324 obj = GetVirtualObject(replacement);
283 } 325 }
284 return node; 326 return replacement;
285 } 327 }
286 328
287 329
288 bool VirtualState::UpdateReplacement(Node* node, Node* rep, Zone* zone) { 330 bool VirtualState::UpdateReplacement(Node* node, Node* rep, Zone* zone) {
289 if (!GetVirtualObject(node)) { 331 if (!GetVirtualObject(node)) {
290 SetVirtualObject(node->id(), new (zone) VirtualObject(node->id(), zone)); 332 SetVirtualObject(node->id(), new (zone) VirtualObject(node->id(), zone));
291 } 333 }
292 if (GetVirtualObject(node)->SetReplacement(rep)) { 334 if (GetVirtualObject(node)->SetReplacement(rep)) {
293 LastChangedAt(node); 335 LastChangedAt(node);
294 if (FLAG_trace_turbo_escape) { 336 if (FLAG_trace_turbo_escape) {
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 switch (node->opcode()) { 423 switch (node->opcode()) {
382 case IrOpcode::kAllocate: 424 case IrOpcode::kAllocate:
383 ProcessAllocate(node); 425 ProcessAllocate(node);
384 break; 426 break;
385 case IrOpcode::kFinishRegion: 427 case IrOpcode::kFinishRegion:
386 ProcessFinishRegion(node); 428 ProcessFinishRegion(node);
387 break; 429 break;
388 case IrOpcode::kStoreField: 430 case IrOpcode::kStoreField:
389 ProcessStoreField(node); 431 ProcessStoreField(node);
390 break; 432 break;
391 case IrOpcode::kLoadField: { 433 case IrOpcode::kStoreElement:
434 ProcessStoreElement(node);
435 break;
436 case IrOpcode::kLoadField:
437 case IrOpcode::kLoadElement: {
392 if (Node* rep = object_analysis_->GetReplacement(node, node->id())) { 438 if (Node* rep = object_analysis_->GetReplacement(node, node->id())) {
393 if (rep->opcode() == IrOpcode::kAllocate || 439 if (rep->opcode() == IrOpcode::kAllocate ||
394 rep->opcode() == IrOpcode::kFinishRegion) { 440 rep->opcode() == IrOpcode::kFinishRegion) {
395 if (CheckUsesForEscape(node, rep)) { 441 if (CheckUsesForEscape(node, rep)) {
396 RevisitInputs(rep); 442 RevisitInputs(rep);
397 RevisitUses(rep); 443 RevisitUses(rep);
398 } 444 }
399 } 445 }
400 } 446 }
401 break; 447 break;
(...skipping 16 matching lines...) Expand all
418 if (IsEscaped(to) && SetEscaped(val)) { 464 if (IsEscaped(to) && SetEscaped(val)) {
419 RevisitUses(val); 465 RevisitUses(val);
420 if (FLAG_trace_turbo_escape) { 466 if (FLAG_trace_turbo_escape) {
421 PrintF("Setting #%d (%s) to escaped because of store to field of #%d\n", 467 PrintF("Setting #%d (%s) to escaped because of store to field of #%d\n",
422 val->id(), val->op()->mnemonic(), to->id()); 468 val->id(), val->op()->mnemonic(), to->id());
423 } 469 }
424 } 470 }
425 } 471 }
426 472
427 473
474 void EscapeStatusAnalysis::ProcessStoreElement(Node* node) {
475 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement);
476 Node* to = NodeProperties::GetValueInput(node, 0);
477 Node* val = NodeProperties::GetValueInput(node, 2);
478 if (IsEscaped(to) && SetEscaped(val)) {
479 RevisitUses(val);
480 if (FLAG_trace_turbo_escape) {
481 PrintF("Setting #%d (%s) to escaped because of store to field of #%d\n",
482 val->id(), val->op()->mnemonic(), to->id());
483 }
484 }
485 }
486
487
428 void EscapeStatusAnalysis::ProcessAllocate(Node* node) { 488 void EscapeStatusAnalysis::ProcessAllocate(Node* node) {
429 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); 489 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate);
430 if (!HasEntry(node)) { 490 if (!HasEntry(node)) {
431 info_[node->id()] = kVirtual; 491 info_[node->id()] = kVirtual;
432 if (FLAG_trace_turbo_escape) { 492 if (FLAG_trace_turbo_escape) {
433 PrintF("Created status entry for node #%d (%s)\n", node->id(), 493 PrintF("Created status entry for node #%d (%s)\n", node->id(),
434 node->op()->mnemonic()); 494 node->op()->mnemonic());
435 } 495 }
436 NumberMatcher size(node->InputAt(0)); 496 NumberMatcher size(node->InputAt(0));
437 if (!size.HasValue() && SetEscaped(node)) { 497 if (!size.HasValue() && SetEscaped(node)) {
438 RevisitUses(node); 498 RevisitUses(node);
439 if (FLAG_trace_turbo_escape) { 499 if (FLAG_trace_turbo_escape) {
440 PrintF("Setting #%d to escaped because of non-const alloc\n", 500 PrintF("Setting #%d to escaped because of non-const alloc\n",
441 node->id()); 501 node->id());
442 } 502 }
443 // This node is known to escape, uses do not have to be checked. 503 // This node is known to escape, uses do not have to be checked.
444 return; 504 return;
445 } 505 }
446 } 506 }
447 if (CheckUsesForEscape(node)) { 507 if (CheckUsesForEscape(node, true)) {
448 RevisitUses(node); 508 RevisitUses(node);
449 } 509 }
450 } 510 }
451 511
452 512
453 bool EscapeStatusAnalysis::CheckUsesForEscape(Node* uses, Node* rep) { 513 bool EscapeStatusAnalysis::CheckUsesForEscape(Node* uses, Node* rep,
514 bool phi_escaping) {
454 for (Edge edge : uses->use_edges()) { 515 for (Edge edge : uses->use_edges()) {
455 Node* use = edge.from(); 516 Node* use = edge.from();
456 if (!NodeProperties::IsValueEdge(edge)) continue; 517 if (!NodeProperties::IsValueEdge(edge) &&
518 !NodeProperties::IsContextEdge(edge))
519 continue;
457 switch (use->opcode()) { 520 switch (use->opcode()) {
458 case IrOpcode::kStoreField: 521 case IrOpcode::kStoreField:
459 case IrOpcode::kLoadField: 522 case IrOpcode::kLoadField:
523 case IrOpcode::kStoreElement:
524 case IrOpcode::kLoadElement:
460 case IrOpcode::kFrameState: 525 case IrOpcode::kFrameState:
461 case IrOpcode::kStateValues: 526 case IrOpcode::kStateValues:
462 case IrOpcode::kReferenceEqual: 527 case IrOpcode::kReferenceEqual:
463 case IrOpcode::kFinishRegion: 528 case IrOpcode::kFinishRegion:
464 case IrOpcode::kPhi: 529 case IrOpcode::kPhi:
465 if (HasEntry(use) && IsEscaped(use) && SetEscaped(rep)) { 530 if (HasEntry(use) && IsEscaped(use) && SetEscaped(rep)) {
466 if (FLAG_trace_turbo_escape) { 531 if (FLAG_trace_turbo_escape) {
467 PrintF( 532 PrintF(
468 "Setting #%d (%s) to escaped because of use by escaping node " 533 "Setting #%d (%s) to escaped because of use by escaping node "
469 "#%d (%s)\n", 534 "#%d (%s)\n",
470 rep->id(), rep->op()->mnemonic(), use->id(), 535 rep->id(), rep->op()->mnemonic(), use->id(),
471 use->op()->mnemonic()); 536 use->op()->mnemonic());
472 } 537 }
473 return true; 538 return true;
474 } 539 }
540 if (phi_escaping && use->opcode() == IrOpcode::kPhi &&
541 SetEscaped(rep)) {
542 if (FLAG_trace_turbo_escape) {
543 PrintF(
544 "Setting #%d (%s) to escaped because of use by phi node "
545 "#%d (%s)\n",
546 rep->id(), rep->op()->mnemonic(), use->id(),
547 use->op()->mnemonic());
548 }
549 return true;
550 }
475 break; 551 break;
476 default: 552 default:
477 if (SetEscaped(rep)) { 553 if (SetEscaped(rep)) {
478 if (FLAG_trace_turbo_escape) { 554 if (FLAG_trace_turbo_escape) {
479 PrintF("Setting #%d (%s) to escaped because of use by #%d (%s)\n", 555 PrintF("Setting #%d (%s) to escaped because of use by #%d (%s)\n",
480 rep->id(), rep->op()->mnemonic(), use->id(), 556 rep->id(), rep->op()->mnemonic(), use->id(),
481 use->op()->mnemonic()); 557 use->op()->mnemonic());
482 } 558 }
483 return true; 559 return true;
484 } 560 }
(...skipping 11 matching lines...) Expand all
496 return false; 572 return false;
497 } 573 }
498 574
499 575
500 void EscapeStatusAnalysis::ProcessFinishRegion(Node* node) { 576 void EscapeStatusAnalysis::ProcessFinishRegion(Node* node) {
501 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion); 577 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion);
502 if (!HasEntry(node)) { 578 if (!HasEntry(node)) {
503 info_[node->id()] = kVirtual; 579 info_[node->id()] = kVirtual;
504 RevisitUses(node); 580 RevisitUses(node);
505 } 581 }
506 if (CheckUsesForEscape(node)) { 582 if (CheckUsesForEscape(node, true)) {
507 RevisitInputs(node); 583 RevisitInputs(node);
508 } 584 }
509 } 585 }
510 586
511 587
512 void EscapeStatusAnalysis::DebugPrint() { 588 void EscapeStatusAnalysis::DebugPrint() {
513 for (NodeId id = 0; id < info_.size(); id++) { 589 for (NodeId id = 0; id < info_.size(); id++) {
514 if (info_[id] != kUnknown) { 590 if (info_[id] != kUnknown) {
515 PrintF("Node #%d is %s\n", id, 591 PrintF("Node #%d is %s\n", id,
516 info_[id] == kEscaped ? "escaping" : "virtual"); 592 info_[id] == kEscaped ? "escaping" : "virtual");
(...skipping 18 matching lines...) Expand all
535 611
536 612
537 void EscapeAnalysis::Run() { 613 void EscapeAnalysis::Run() {
538 RunObjectAnalysis(); 614 RunObjectAnalysis();
539 escape_status_.Run(); 615 escape_status_.Run();
540 } 616 }
541 617
542 618
543 void EscapeAnalysis::RunObjectAnalysis() { 619 void EscapeAnalysis::RunObjectAnalysis() {
544 virtual_states_.resize(graph()->NodeCount()); 620 virtual_states_.resize(graph()->NodeCount());
545 ZoneVector<Node*> queue(zone()); 621 ZoneVector<Node*> stack(zone());
546 queue.push_back(graph()->start()); 622 stack.push_back(graph()->start());
547 while (!queue.empty()) { 623 while (!stack.empty()) {
548 Node* node = queue.back(); 624 Node* node = stack.back();
549 queue.pop_back(); 625 stack.pop_back();
550 if (Process(node)) { 626 if (Process(node)) {
551 for (Edge edge : node->use_edges()) { 627 for (Edge edge : node->use_edges()) {
552 if (NodeProperties::IsEffectEdge(edge)) { 628 if (NodeProperties::IsEffectEdge(edge)) {
553 Node* use = edge.from(); 629 Node* use = edge.from();
554 if (use->opcode() != IrOpcode::kLoadField || 630 if ((use->opcode() != IrOpcode::kLoadField &&
631 use->opcode() != IrOpcode::kLoadElement) ||
555 !IsDanglingEffectNode(use)) { 632 !IsDanglingEffectNode(use)) {
556 queue.push_back(use); 633 stack.push_back(use);
557 } 634 }
558 } 635 }
559 } 636 }
560 // First process loads: dangling loads are a problem otherwise. 637 // First process loads: dangling loads are a problem otherwise.
561 for (Edge edge : node->use_edges()) { 638 for (Edge edge : node->use_edges()) {
562 if (NodeProperties::IsEffectEdge(edge)) { 639 if (NodeProperties::IsEffectEdge(edge)) {
563 Node* use = edge.from(); 640 Node* use = edge.from();
564 if (use->opcode() == IrOpcode::kLoadField && 641 if ((use->opcode() == IrOpcode::kLoadField ||
642 use->opcode() == IrOpcode::kLoadElement) &&
643
644
565 IsDanglingEffectNode(use)) { 645 IsDanglingEffectNode(use)) {
566 queue.push_back(use); 646 stack.push_back(use);
567 } 647 }
568 } 648 }
569 } 649 }
570 } 650 }
571 } 651 }
572 if (FLAG_trace_turbo_escape) { 652 if (FLAG_trace_turbo_escape) {
573 DebugPrint(); 653 DebugPrint();
574 } 654 }
575 } 655 }
576 656
(...skipping 20 matching lines...) Expand all
597 break; 677 break;
598 case IrOpcode::kFinishRegion: 678 case IrOpcode::kFinishRegion:
599 ProcessFinishRegion(node); 679 ProcessFinishRegion(node);
600 break; 680 break;
601 case IrOpcode::kStoreField: 681 case IrOpcode::kStoreField:
602 ProcessStoreField(node); 682 ProcessStoreField(node);
603 break; 683 break;
604 case IrOpcode::kLoadField: 684 case IrOpcode::kLoadField:
605 ProcessLoadField(node); 685 ProcessLoadField(node);
606 break; 686 break;
687 case IrOpcode::kStoreElement:
688 ProcessStoreElement(node);
689 break;
690 case IrOpcode::kLoadElement:
691 ProcessLoadElement(node);
692 break;
607 case IrOpcode::kStart: 693 case IrOpcode::kStart:
608 ProcessStart(node); 694 ProcessStart(node);
609 break; 695 break;
610 case IrOpcode::kEffectPhi: 696 case IrOpcode::kEffectPhi:
611 return ProcessEffectPhi(node); 697 return ProcessEffectPhi(node);
612 break; 698 break;
613 default: 699 default:
614 if (node->op()->EffectInputCount() > 0) { 700 if (node->op()->EffectInputCount() > 0) {
615 ForwardVirtualState(node); 701 ForwardVirtualState(node);
616 } 702 }
703 ProcessAllocationUsers(node);
617 break; 704 break;
618 } 705 }
619 return true; 706 return true;
620 } 707 }
621 708
622 709
710 void EscapeAnalysis::ProcessAllocationUsers(Node* node) {
711 for (Edge edge : node->input_edges()) {
712 Node* input = edge.to();
713 if (!NodeProperties::IsValueEdge(edge) &&
714 !NodeProperties::IsContextEdge(edge))
715 continue;
716 switch (node->opcode()) {
717 case IrOpcode::kStoreField:
718 case IrOpcode::kLoadField:
719 case IrOpcode::kStoreElement:
720 case IrOpcode::kLoadElement:
721 case IrOpcode::kFrameState:
722 case IrOpcode::kStateValues:
723 case IrOpcode::kReferenceEqual:
724 case IrOpcode::kFinishRegion:
725 case IrOpcode::kPhi:
726 break;
727 default:
728 VirtualState* states = virtual_states_[node->id()];
729 if (VirtualObject* obj = states->ResolveVirtualObject(input)) {
730 if (obj->ClearAllFields()) {
731 states->LastChangedAt(node);
732 }
733 }
734 break;
735 }
736 }
737 }
738
739
623 bool EscapeAnalysis::IsEffectBranchPoint(Node* node) { 740 bool EscapeAnalysis::IsEffectBranchPoint(Node* node) {
624 int count = 0; 741 int count = 0;
625 for (Edge edge : node->use_edges()) { 742 for (Edge edge : node->use_edges()) {
626 Node* use = edge.from(); 743 Node* use = edge.from();
627 if (NodeProperties::IsEffectEdge(edge) && 744 if (NodeProperties::IsEffectEdge(edge) &&
628 use->opcode() != IrOpcode::kLoadField) { 745 use->opcode() != IrOpcode::kLoadField) {
629 if (++count > 1) { 746 if (++count > 1) {
630 return true; 747 return true;
631 } 748 }
632 } 749 }
633 } 750 }
634 return false; 751 return false;
635 } 752 }
636 753
637 754
638 void EscapeAnalysis::ForwardVirtualState(Node* node) { 755 void EscapeAnalysis::ForwardVirtualState(Node* node) {
639 DCHECK_EQ(node->op()->EffectInputCount(), 1); 756 DCHECK_EQ(node->op()->EffectInputCount(), 1);
640 if (node->opcode() != IrOpcode::kLoadField && IsDanglingEffectNode(node)) { 757 if (node->opcode() != IrOpcode::kLoadField &&
758 node->opcode() != IrOpcode::kLoadElement &&
759 node->opcode() != IrOpcode::kLoad && IsDanglingEffectNode(node)) {
641 PrintF("Dangeling effect node: #%d (%s)\n", node->id(), 760 PrintF("Dangeling effect node: #%d (%s)\n", node->id(),
642 node->op()->mnemonic()); 761 node->op()->mnemonic());
643 DCHECK(false); 762 UNREACHABLE();
644 } 763 }
645 Node* effect = NodeProperties::GetEffectInput(node); 764 Node* effect = NodeProperties::GetEffectInput(node);
646 // Break the cycle for effect phis. 765 // Break the cycle for effect phis.
647 if (effect->opcode() == IrOpcode::kEffectPhi) { 766 if (effect->opcode() == IrOpcode::kEffectPhi) {
648 if (virtual_states_[effect->id()] == nullptr) { 767 if (virtual_states_[effect->id()] == nullptr) {
649 virtual_states_[effect->id()] = 768 virtual_states_[effect->id()] =
650 new (zone()) VirtualState(zone(), graph()->NodeCount()); 769 new (zone()) VirtualState(zone(), graph()->NodeCount());
651 } 770 }
652 } 771 }
653 DCHECK_NOT_NULL(virtual_states_[effect->id()]); 772 DCHECK_NOT_NULL(virtual_states_[effect->id()]);
654 if (IsEffectBranchPoint(effect)) { 773 if (IsEffectBranchPoint(effect)) {
655 if (virtual_states_[node->id()]) return; 774 if (!virtual_states_[node->id()]) {
656 virtual_states_[node->id()] = 775 virtual_states_[node->id()] =
657 new (zone()) VirtualState(*virtual_states_[effect->id()]); 776 new (zone()) VirtualState(*virtual_states_[effect->id()]);
777 } else {
778 virtual_states_[node->id()]->UpdateFrom(virtual_states_[effect->id()],
779 zone());
780 }
658 if (FLAG_trace_turbo_escape) { 781 if (FLAG_trace_turbo_escape) {
659 PrintF("Copying object state %p from #%d (%s) to #%d (%s)\n", 782 PrintF("Copying object state %p from #%d (%s) to #%d (%s)\n",
660 static_cast<void*>(virtual_states_[effect->id()]), effect->id(), 783 static_cast<void*>(virtual_states_[effect->id()]), effect->id(),
661 effect->op()->mnemonic(), node->id(), node->op()->mnemonic()); 784 effect->op()->mnemonic(), node->id(), node->op()->mnemonic());
662 } 785 }
663 } else { 786 } else {
664 virtual_states_[node->id()] = virtual_states_[effect->id()]; 787 virtual_states_[node->id()] = virtual_states_[effect->id()];
665 if (FLAG_trace_turbo_escape) { 788 if (FLAG_trace_turbo_escape) {
666 PrintF("Forwarding object state %p from #%d (%s) to #%d (%s)\n", 789 PrintF("Forwarding object state %p from #%d (%s) to #%d (%s)\n",
667 static_cast<void*>(virtual_states_[effect->id()]), effect->id(), 790 static_cast<void*>(virtual_states_[effect->id()]), effect->id(),
668 effect->op()->mnemonic(), node->id(), node->op()->mnemonic()); 791 effect->op()->mnemonic(), node->id(), node->op()->mnemonic());
669 } 792 }
670 } 793 }
671 } 794 }
672 795
673 796
674 void EscapeAnalysis::ProcessStart(Node* node) { 797 void EscapeAnalysis::ProcessStart(Node* node) {
675 DCHECK_EQ(node->opcode(), IrOpcode::kStart); 798 DCHECK_EQ(node->opcode(), IrOpcode::kStart);
676 virtual_states_[node->id()] = 799 virtual_states_[node->id()] =
677 new (zone()) VirtualState(zone(), graph()->NodeCount()); 800 new (zone()) VirtualState(zone(), graph()->NodeCount());
678 } 801 }
679 802
680 803
681 bool EscapeAnalysis::ProcessEffectPhi(Node* node) { 804 bool EscapeAnalysis::ProcessEffectPhi(Node* node) {
682 DCHECK_EQ(node->opcode(), IrOpcode::kEffectPhi); 805 DCHECK_EQ(node->opcode(), IrOpcode::kEffectPhi);
683 // For now only support binary phis. 806 // For now only support binary phis.
684 DCHECK_EQ(node->op()->EffectInputCount(), 2); 807 CHECK_EQ(node->op()->EffectInputCount(), 2);
685 Node* left = NodeProperties::GetEffectInput(node, 0); 808 Node* left = NodeProperties::GetEffectInput(node, 0);
686 Node* right = NodeProperties::GetEffectInput(node, 1); 809 Node* right = NodeProperties::GetEffectInput(node, 1);
687 bool changed = false; 810 bool changed = false;
688 811
689 VirtualState* mergeState = virtual_states_[node->id()]; 812 VirtualState* mergeState = virtual_states_[node->id()];
690 if (!mergeState) { 813 if (!mergeState) {
691 mergeState = new (zone()) VirtualState(zone(), graph()->NodeCount()); 814 mergeState = new (zone()) VirtualState(zone(), graph()->NodeCount());
692 virtual_states_[node->id()] = mergeState; 815 virtual_states_[node->id()] = mergeState;
693 changed = true; 816 changed = true;
694 if (FLAG_trace_turbo_escape) { 817 if (FLAG_trace_turbo_escape) {
695 PrintF("Phi #%d got new states map %p.\n", node->id(), 818 PrintF("Effect Phi #%d got new states map %p.\n", node->id(),
696 static_cast<void*>(mergeState)); 819 static_cast<void*>(mergeState));
697 } 820 }
698 } else if (mergeState->GetLastChanged() != node) { 821 } else if (mergeState->GetLastChanged() != node) {
699 changed = true; 822 changed = true;
700 } 823 }
701 824
702 VirtualState* l = virtual_states_[left->id()]; 825 VirtualState* l = virtual_states_[left->id()];
703 VirtualState* r = virtual_states_[right->id()]; 826 VirtualState* r = virtual_states_[right->id()];
704 827
705 if (l == nullptr && r == nullptr) { 828 if (l == nullptr && r == nullptr) {
706 return changed; 829 return changed;
707 } 830 }
708 831
709 if (FLAG_trace_turbo_escape) { 832 if (FLAG_trace_turbo_escape) {
710 PrintF("At Phi #%d, merging states %p (from #%d) and %p (from #%d)\n", 833 PrintF(
711 node->id(), static_cast<void*>(l), left->id(), static_cast<void*>(r), 834 "At Effect Phi #%d, merging states %p (from #%d) and %p (from #%d) "
712 right->id()); 835 "into %p\n",
836 node->id(), static_cast<void*>(l), left->id(), static_cast<void*>(r),
837 right->id(), static_cast<void*>(mergeState));
713 } 838 }
714 839
715 if (r && l == nullptr) { 840 if (r && l == nullptr) {
716 changed = mergeState->UpdateFrom(r, zone()) || changed; 841 changed = mergeState->UpdateFrom(r, zone()) || changed;
717 } else if (l && r == nullptr) { 842 } else if (l && r == nullptr) {
718 changed = mergeState->UpdateFrom(l, zone()) || changed; 843 changed = mergeState->UpdateFrom(l, zone()) || changed;
719 } else { 844 } else {
720 changed = mergeState->MergeFrom(l, r, zone(), graph(), common(), 845 changed = mergeState->MergeFrom(l, r, zone(), graph(), common(),
721 NodeProperties::GetControlInput(node)) || 846 NodeProperties::GetControlInput(node)) ||
722 changed; 847 changed;
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
783 bool EscapeAnalysis::IsVirtual(Node* node) { 908 bool EscapeAnalysis::IsVirtual(Node* node) {
784 return escape_status_.IsVirtual(node); 909 return escape_status_.IsVirtual(node);
785 } 910 }
786 911
787 912
788 bool EscapeAnalysis::IsEscaped(Node* node) { 913 bool EscapeAnalysis::IsEscaped(Node* node) {
789 return escape_status_.IsEscaped(node); 914 return escape_status_.IsEscaped(node);
790 } 915 }
791 916
792 917
918 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) {
919 if (VirtualState* states = virtual_states_[at->id()]) {
920 return states->GetVirtualObject(id);
921 }
922 return nullptr;
923 }
924
925
793 int EscapeAnalysis::OffsetFromAccess(Node* node) { 926 int EscapeAnalysis::OffsetFromAccess(Node* node) {
794 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0); 927 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0);
795 return OpParameter<FieldAccess>(node).offset / kPointerSize; 928 return OpParameter<FieldAccess>(node).offset / kPointerSize;
796 } 929 }
797 930
798 931
932 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node,
933 VirtualState* state) {
934 // Only binary phis are supported for now.
935 CHECK_EQ(from->op()->ValueInputCount(), 2);
936 if (FLAG_trace_turbo_escape) {
937 PrintF("Load #%d from phi #%d", node->id(), from->id());
938 }
939 Node* left = NodeProperties::GetValueInput(from, 0);
940 Node* right = NodeProperties::GetValueInput(from, 1);
941 VirtualObject* l = state->GetVirtualObject(left);
942 VirtualObject* r = state->GetVirtualObject(right);
943 if (l && r) {
944 Node* lv = l->GetField(offset);
945 Node* rv = r->GetField(offset);
946 if (lv && rv) {
947 if (!state->GetVirtualObject(node)) {
948 state->SetVirtualObject(node->id(),
949 new (zone()) VirtualObject(node->id(), zone()));
950 }
951 Node* rep = state->GetVirtualObject(node)->GetReplacement();
952 if (!rep || rep->opcode() != IrOpcode::kPhi ||
953 NodeProperties::GetValueInput(rep, 0) != lv ||
954 NodeProperties::GetValueInput(rep, 1) != rv) {
955 Node* phi = graph()->NewNode(common()->Phi(kMachAnyTagged, 2), lv, rv,
956 NodeProperties::GetControlInput(from));
957 state->GetVirtualObject(node)->SetReplacement(phi);
958 state->LastChangedAt(node);
959 if (FLAG_trace_turbo_escape) {
960 PrintF(" got phi of #%d is #%d created.\n", lv->id(), rv->id());
961 }
962 } else if (FLAG_trace_turbo_escape) {
963 PrintF(" has already the right phi representation.\n");
964 }
965 } else if (FLAG_trace_turbo_escape) {
966 PrintF(" has incomplete field info: %p %p\n", static_cast<void*>(lv),
967 static_cast<void*>(rv));
968 }
969 } else if (FLAG_trace_turbo_escape) {
970 PrintF(" has incomplete virtual object info: %p %p\n",
971 static_cast<void*>(l), static_cast<void*>(r));
972 }
973 }
974
975
799 void EscapeAnalysis::ProcessLoadField(Node* node) { 976 void EscapeAnalysis::ProcessLoadField(Node* node) {
800 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField); 977 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField);
801 ForwardVirtualState(node); 978 ForwardVirtualState(node);
802 Node* from = NodeProperties::GetValueInput(node, 0); 979 Node* from = NodeProperties::GetValueInput(node, 0);
803 int offset = OffsetFromAccess(node); 980 VirtualState* state = virtual_states_[node->id()];
804 VirtualState* states = virtual_states_[node->id()]; 981 if (VirtualObject* object = state->ResolveVirtualObject(from)) {
805 if (VirtualObject* state = states->GetVirtualObject(from)) { 982 int offset = OffsetFromAccess(node);
806 if (!state->IsTracked()) return; 983 if (!object->IsTracked()) return;
807 Node* value = state->GetField(offset); 984 Node* value = object->GetField(offset);
808 if (value) { 985 if (value) {
986 value = state->ResolveReplacement(value);
809 // Record that the load has this alias. 987 // Record that the load has this alias.
810 states->UpdateReplacement(node, value, zone()); 988 state->UpdateReplacement(node, value, zone());
811 } else if (FLAG_trace_turbo_escape) { 989 } else if (FLAG_trace_turbo_escape) {
812 PrintF("No field %d on record for #%d\n", offset, from->id()); 990 PrintF("No field %d on record for #%d\n", offset, from->id());
813 } 991 }
814 } else { 992 } else {
815 if (from->opcode() == IrOpcode::kPhi) { 993 if (from->opcode() == IrOpcode::kPhi) {
994 int offset = OffsetFromAccess(node);
816 // Only binary phis are supported for now. 995 // Only binary phis are supported for now.
817 CHECK_EQ(from->op()->ValueInputCount(), 2); 996 ProcessLoadFromPhi(offset, from, node, state);
818 if (FLAG_trace_turbo_escape) { 997 }
819 PrintF("Load #%d from phi #%d", node->id(), from->id()); 998 }
999 }
1000
1001
1002 void EscapeAnalysis::ProcessLoadElement(Node* node) {
1003 DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement);
1004 ForwardVirtualState(node);
1005 Node* from = NodeProperties::GetValueInput(node, 0);
1006 VirtualState* state = virtual_states_[node->id()];
1007 if (VirtualObject* object = state->ResolveVirtualObject(from)) {
1008 NumberMatcher index(node->InputAt(1));
1009 ElementAccess access = OpParameter<ElementAccess>(node);
1010 if (index.HasValue()) {
1011 CHECK_EQ(ElementSizeLog2Of(access.machine_type), kPointerSizeLog2);
1012 CHECK_EQ(access.header_size % kPointerSize, 0);
1013 int offset = index.Value() + access.header_size / kPointerSize;
1014 if (!object->IsTracked()) return;
1015 Node* value = object->GetField(offset);
1016 if (value) {
1017 value = state->ResolveReplacement(value);
1018 // Record that the load has this alias.
1019 state->UpdateReplacement(node, value, zone());
1020 } else if (FLAG_trace_turbo_escape) {
1021 PrintF("No field %d on record for #%d\n", offset, from->id());
820 } 1022 }
821 Node* left = NodeProperties::GetValueInput(from, 0); 1023 }
822 Node* right = NodeProperties::GetValueInput(from, 1); 1024 } else {
823 VirtualObject* l = states->GetVirtualObject(left); 1025 if (from->opcode() == IrOpcode::kPhi) {
824 VirtualObject* r = states->GetVirtualObject(right); 1026 NumberMatcher index(node->InputAt(1));
825 if (l && r) { 1027 ElementAccess access = OpParameter<ElementAccess>(node);
826 Node* lv = l->GetField(offset); 1028 int offset = index.Value() + access.header_size / kPointerSize;
827 Node* rv = r->GetField(offset); 1029 if (index.HasValue()) {
828 if (lv && rv) { 1030 ProcessLoadFromPhi(offset, from, node, state);
829 if (!states->GetVirtualObject(node)) {
830 states->SetVirtualObject(
831 node->id(), new (zone()) VirtualObject(node->id(), zone()));
832 }
833 Node* rep = states->GetVirtualObject(node)->GetReplacement();
834 if (!rep || rep->opcode() != IrOpcode::kPhi ||
835 NodeProperties::GetValueInput(rep, 0) != lv ||
836 NodeProperties::GetValueInput(rep, 1) != rv) {
837 Node* phi =
838 graph()->NewNode(common()->Phi(kMachAnyTagged, 2), lv, rv,
839 NodeProperties::GetControlInput(from));
840 states->GetVirtualObject(node)->SetReplacement(phi);
841 states->LastChangedAt(node);
842 if (FLAG_trace_turbo_escape) {
843 PrintF(" got phi of #%d is #%d created.\n", lv->id(), rv->id());
844 }
845 } else if (FLAG_trace_turbo_escape) {
846 PrintF(" has already the right phi representation.\n");
847 }
848 } else if (FLAG_trace_turbo_escape) {
849 PrintF(" has incomplete field info: %p %p\n", static_cast<void*>(lv),
850 static_cast<void*>(rv));
851 }
852 } else if (FLAG_trace_turbo_escape) {
853 PrintF(" has incomplete virtual object info: %p %p\n",
854 static_cast<void*>(l), static_cast<void*>(r));
855 } 1031 }
856 } 1032 }
857 } 1033 }
858 } 1034 }
859 1035
860 1036
861 void EscapeAnalysis::ProcessStoreField(Node* node) { 1037 void EscapeAnalysis::ProcessStoreField(Node* node) {
862 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField); 1038 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField);
863 ForwardVirtualState(node); 1039 ForwardVirtualState(node);
864 Node* to = NodeProperties::GetValueInput(node, 0); 1040 Node* to = NodeProperties::GetValueInput(node, 0);
865 Node* val = NodeProperties::GetValueInput(node, 1); 1041 Node* val = NodeProperties::GetValueInput(node, 1);
866 int offset = OffsetFromAccess(node); 1042 int offset = OffsetFromAccess(node);
867 VirtualState* states = virtual_states_[node->id()]; 1043 VirtualState* states = virtual_states_[node->id()];
868 if (VirtualObject* obj = states->GetVirtualObject(to)) { 1044 if (VirtualObject* obj = states->ResolveVirtualObject(to)) {
869 if (!obj->IsTracked()) return; 1045 if (!obj->IsTracked()) return;
870 if (obj->SetField(offset, states->ResolveReplacement(val))) { 1046 if (obj->SetField(offset, states->ResolveReplacement(val))) {
871 states->LastChangedAt(node); 1047 states->LastChangedAt(node);
872 } 1048 }
873 } 1049 }
874 } 1050 }
875 1051
876 1052
1053 void EscapeAnalysis::ProcessStoreElement(Node* node) {
1054 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement);
1055 ForwardVirtualState(node);
1056 Node* to = NodeProperties::GetValueInput(node, 0);
1057 NumberMatcher index(node->InputAt(1));
1058 ElementAccess access = OpParameter<ElementAccess>(node);
1059 Node* val = NodeProperties::GetValueInput(node, 2);
1060 if (index.HasValue()) {
1061 CHECK_EQ(ElementSizeLog2Of(access.machine_type), kPointerSizeLog2);
1062 CHECK_EQ(access.header_size % kPointerSize, 0);
1063 int offset = index.Value() + access.header_size / kPointerSize;
1064 VirtualState* states = virtual_states_[node->id()];
1065 if (VirtualObject* obj = states->ResolveVirtualObject(to)) {
1066 if (!obj->IsTracked()) return;
1067 if (obj->SetField(offset, states->ResolveReplacement(val))) {
1068 states->LastChangedAt(node);
1069 }
1070 }
1071 }
1072 }
1073
1074
1075 void EscapeAnalysis::DebugPrintObject(VirtualObject* object, NodeId id) {
1076 PrintF(" Object #%d with %zu fields", id, object->field_count());
1077 if (Node* rep = object->GetReplacement()) {
1078 PrintF(", rep = #%d (%s)", rep->id(), rep->op()->mnemonic());
1079 }
1080 PrintF("\n");
1081 for (size_t i = 0; i < object->field_count(); ++i) {
1082 if (Node* f = object->GetField(i)) {
1083 PrintF(" Field %zu = #%d (%s)\n", i, f->id(), f->op()->mnemonic());
1084 }
1085 }
1086 }
1087
1088
1089 void EscapeAnalysis::DebugPrintState(VirtualState* state) {
1090 PrintF("Dumping object state %p\n", static_cast<void*>(state));
1091 for (size_t id = 0; id < state->size(); id++) {
1092 if (VirtualObject* object = state->GetVirtualObject(id)) {
1093 if (object->id() == id) {
1094 DebugPrintObject(object, static_cast<int>(id));
1095 } else {
1096 PrintF(" Object #%zu links to object #%d\n", id, object->id());
1097 }
1098 }
1099 }
1100 }
1101
1102
877 void EscapeAnalysis::DebugPrint() { 1103 void EscapeAnalysis::DebugPrint() {
878 ZoneVector<VirtualState*> object_states(zone()); 1104 ZoneVector<VirtualState*> object_states(zone());
879 for (NodeId id = 0; id < virtual_states_.size(); id++) { 1105 for (NodeId id = 0; id < virtual_states_.size(); id++) {
880 if (VirtualState* states = virtual_states_[id]) { 1106 if (VirtualState* states = virtual_states_[id]) {
881 if (std::find(object_states.begin(), object_states.end(), states) == 1107 if (std::find(object_states.begin(), object_states.end(), states) ==
882 object_states.end()) { 1108 object_states.end()) {
883 object_states.push_back(states); 1109 object_states.push_back(states);
884 } 1110 }
885 } 1111 }
886 } 1112 }
887 for (size_t n = 0; n < object_states.size(); n++) { 1113 for (size_t n = 0; n < object_states.size(); n++) {
888 PrintF("Dumping object state %p\n", static_cast<void*>(object_states[n])); 1114 DebugPrintState(object_states[n]);
889 for (size_t id = 0; id < object_states[n]->size(); id++) {
890 if (VirtualObject* obj = object_states[n]->GetVirtualObject(id)) {
891 if (obj->id() == id) {
892 PrintF(" Object #%zu with %zu fields", id, obj->fields());
893 if (Node* rep = obj->GetReplacement()) {
894 PrintF(", rep = #%d (%s)", rep->id(), rep->op()->mnemonic());
895 }
896 PrintF("\n");
897 for (size_t i = 0; i < obj->fields(); ++i) {
898 if (Node* f = obj->GetField(i)) {
899 PrintF(" Field %zu = #%d (%s)\n", i, f->id(),
900 f->op()->mnemonic());
901 }
902 }
903 } else {
904 PrintF(" Object #%zu links to object #%d\n", id, obj->id());
905 }
906 }
907 }
908 } 1115 }
909 } 1116 }
910 1117
911 } // namespace compiler 1118 } // namespace compiler
912 } // namespace internal 1119 } // namespace internal
913 } // namespace v8 1120 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/escape-analysis.h ('k') | src/compiler/escape-analysis-reducer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698