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

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

Issue 1608073003: [turbofan] Add TRACE macro for escape analysis. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Rebase Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/compiler/escape-analysis-reducer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 2015 the V8 project authors. All rights reserved. 1 // Copyright 2015 the V8 project authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "src/compiler/escape-analysis.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"
11 #include "src/compilation-dependencies.h" 11 #include "src/compilation-dependencies.h"
12 #include "src/compiler/common-operator.h" 12 #include "src/compiler/common-operator.h"
13 #include "src/compiler/graph-reducer.h" 13 #include "src/compiler/graph-reducer.h"
14 #include "src/compiler/js-operator.h" 14 #include "src/compiler/js-operator.h"
15 #include "src/compiler/node.h" 15 #include "src/compiler/node.h"
16 #include "src/compiler/node-matchers.h" 16 #include "src/compiler/node-matchers.h"
17 #include "src/compiler/node-properties.h" 17 #include "src/compiler/node-properties.h"
18 #include "src/compiler/operator-properties.h" 18 #include "src/compiler/operator-properties.h"
19 #include "src/compiler/simplified-operator.h" 19 #include "src/compiler/simplified-operator.h"
20 #include "src/objects-inl.h" 20 #include "src/objects-inl.h"
21 #include "src/type-cache.h" 21 #include "src/type-cache.h"
22 22
23 namespace v8 { 23 namespace v8 {
24 namespace internal { 24 namespace internal {
25 namespace compiler { 25 namespace compiler {
26 26
27 #ifdef DEBUG
28 #define TRACE(...) \
29 do { \
30 if (FLAG_trace_turbo_escape) PrintF(__VA_ARGS__); \
31 } while (false)
32 #else
33 #define TRACE(...)
34 #endif
35
27 const EscapeAnalysis::Alias EscapeAnalysis::kNotReachable = 36 const EscapeAnalysis::Alias EscapeAnalysis::kNotReachable =
28 std::numeric_limits<Alias>::max(); 37 std::numeric_limits<Alias>::max();
29 const EscapeAnalysis::Alias EscapeAnalysis::kUntrackable = 38 const EscapeAnalysis::Alias EscapeAnalysis::kUntrackable =
30 std::numeric_limits<Alias>::max() - 1; 39 std::numeric_limits<Alias>::max() - 1;
31 40
32 41
33 class VirtualObject : public ZoneObject { 42 class VirtualObject : public ZoneObject {
34 public: 43 public:
35 enum Status { kUntracked = 0, kTracked = 1 }; 44 enum Status { kUntracked = 0, kTracked = 1 };
36 VirtualObject(NodeId id, Zone* zone) 45 VirtualObject(NodeId id, Zone* zone)
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 if (offset < phi_.size()) { 77 if (offset < phi_.size()) {
69 return phi_[offset]; 78 return phi_[offset];
70 } 79 }
71 return false; 80 return false;
72 } 81 }
73 82
74 bool SetField(size_t offset, Node* node, bool created_phi = false) { 83 bool SetField(size_t offset, Node* node, bool created_phi = false) {
75 bool changed = fields_[offset] != node || phi_[offset] != created_phi; 84 bool changed = fields_[offset] != node || phi_[offset] != created_phi;
76 fields_[offset] = node; 85 fields_[offset] = node;
77 phi_[offset] = created_phi; 86 phi_[offset] = created_phi;
78 if (changed && FLAG_trace_turbo_escape && node) { 87 if (changed && node) {
79 PrintF("Setting field %zu of #%d to #%d (%s)\n", offset, id(), node->id(), 88 TRACE("Setting field %zu of #%d to #%d (%s)\n", offset, id(), node->id(),
80 node->op()->mnemonic()); 89 node->op()->mnemonic());
81 } 90 }
82 return changed; 91 return changed;
83 } 92 }
84 bool IsVirtual() const { return status_ == kTracked; } 93 bool IsVirtual() const { return status_ == kTracked; }
85 bool IsTracked() const { return status_ != kUntracked; } 94 bool IsTracked() const { return status_ != kUntracked; }
86 95
87 Node** fields_array() { return &fields_.front(); } 96 Node** fields_array() { return &fields_.front(); }
88 size_t field_count() { return fields_.size(); } 97 size_t field_count() { return fields_.size(); }
89 bool ResizeFields(size_t field_count) { 98 bool ResizeFields(size_t field_count) {
90 if (field_count != fields_.size()) { 99 if (field_count != fields_.size()) {
(...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after
283 continue; 292 continue;
284 } 293 }
285 294
286 if (ls == nullptr) { 295 if (ls == nullptr) {
287 ls = new (zone) VirtualObject(*rs); 296 ls = new (zone) VirtualObject(*rs);
288 SetVirtualObject(alias, ls); 297 SetVirtualObject(alias, ls);
289 changed = true; 298 changed = true;
290 continue; 299 continue;
291 } 300 }
292 301
293 if (FLAG_trace_turbo_escape) { 302 TRACE(" Updating fields of @%d\n", alias);
294 PrintF(" Updating fields of @%d\n", alias);
295 }
296 303
297 changed = ls->UpdateFrom(*rs) || changed; 304 changed = ls->UpdateFrom(*rs) || changed;
298 } 305 }
299 return false; 306 return false;
300 } 307 }
301 308
302 309
303 namespace { 310 namespace {
304 311
305 bool IsEquivalentPhi(Node* node1, Node* node2) { 312 bool IsEquivalentPhi(Node* node1, Node* node2) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
347 } 354 }
348 355
349 356
350 bool VirtualState::MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, 357 bool VirtualState::MergeFrom(MergeCache* cache, Zone* zone, Graph* graph,
351 CommonOperatorBuilder* common, Node* control) { 358 CommonOperatorBuilder* common, Node* control) {
352 DCHECK_GT(cache->states().size(), 0u); 359 DCHECK_GT(cache->states().size(), 0u);
353 bool changed = false; 360 bool changed = false;
354 for (EscapeAnalysis::Alias alias = 0; alias < size(); ++alias) { 361 for (EscapeAnalysis::Alias alias = 0; alias < size(); ++alias) {
355 size_t fields = cache->LoadVirtualObjectsFromStatesFor(alias); 362 size_t fields = cache->LoadVirtualObjectsFromStatesFor(alias);
356 if (cache->objects().size() == cache->states().size()) { 363 if (cache->objects().size() == cache->states().size()) {
357 if (FLAG_trace_turbo_escape) {
358 PrintF(" Merging virtual objects of @%d\n", alias);
359 }
360 VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject( 364 VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject(
361 alias, cache->objects().front()->id(), fields, zone); 365 alias, cache->objects().front()->id(), fields, zone);
366 #ifdef DEBUG
367 if (FLAG_trace_turbo_escape) {
368 PrintF(" Alias @%d, merging into %p virtual objects", alias,
369 static_cast<void*>(mergeObject));
370 for (size_t i = 0; i < cache->objects().size(); i++) {
371 PrintF(" %p", static_cast<void*>(cache->objects()[i]));
372 }
373 PrintF("\n");
374 }
375 #endif // DEBUG
362 changed = mergeObject->ResizeFields(fields) || changed; 376 changed = mergeObject->ResizeFields(fields) || changed;
363 for (size_t i = 0; i < fields; ++i) { 377 for (size_t i = 0; i < fields; ++i) {
364 if (Node* field = cache->GetFields(i)) { 378 if (Node* field = cache->GetFields(i)) {
365 changed = mergeObject->SetField(i, field) || changed; 379 changed = mergeObject->SetField(i, field) || changed;
366 if (FLAG_trace_turbo_escape) { 380 TRACE(" Field %zu agree on rep #%d\n", i, field->id());
367 PrintF(" Field %zu agree on rep #%d\n", i, field->id());
368 }
369 } else { 381 } else {
370 int value_input_count = static_cast<int>(cache->fields().size()); 382 int value_input_count = static_cast<int>(cache->fields().size());
371 if (cache->fields().size() == cache->objects().size()) { 383 if (cache->fields().size() == cache->objects().size()) {
372 Node* rep = mergeObject->GetField(i); 384 Node* rep = mergeObject->GetField(i);
373 if (!rep || !mergeObject->IsCreatedPhi(i)) { 385 if (!rep || !mergeObject->IsCreatedPhi(i)) {
374 cache->fields().push_back(control); 386 cache->fields().push_back(control);
375 Node* phi = graph->NewNode( 387 Node* phi = graph->NewNode(
376 common->Phi(MachineRepresentation::kTagged, 388 common->Phi(MachineRepresentation::kTagged,
377 value_input_count), 389 value_input_count),
378 value_input_count + 1, &cache->fields().front()); 390 value_input_count + 1, &cache->fields().front());
379 mergeObject->SetField(i, phi, true); 391 mergeObject->SetField(i, phi, true);
392 #ifdef DEBUG
380 if (FLAG_trace_turbo_escape) { 393 if (FLAG_trace_turbo_escape) {
381 PrintF(" Creating Phi #%d as merge of", phi->id()); 394 PrintF(" Creating Phi #%d as merge of", phi->id());
382 for (int i = 0; i < value_input_count; i++) { 395 for (int i = 0; i < value_input_count; i++) {
383 PrintF(" #%d (%s)", cache->fields()[i]->id(), 396 PrintF(" #%d (%s)", cache->fields()[i]->id(),
384 cache->fields()[i]->op()->mnemonic()); 397 cache->fields()[i]->op()->mnemonic());
385 } 398 }
386 PrintF("\n"); 399 PrintF("\n");
387 } 400 }
401 #endif // DEBUG
388 changed = true; 402 changed = true;
389 } else { 403 } else {
390 DCHECK(rep->opcode() == IrOpcode::kPhi); 404 DCHECK(rep->opcode() == IrOpcode::kPhi);
391 for (int n = 0; n < value_input_count; ++n) { 405 for (int n = 0; n < value_input_count; ++n) {
392 if (n < rep->op()->ValueInputCount()) { 406 if (n < rep->op()->ValueInputCount()) {
393 Node* old = NodeProperties::GetValueInput(rep, n); 407 Node* old = NodeProperties::GetValueInput(rep, n);
394 if (old != cache->fields()[n]) { 408 if (old != cache->fields()[n]) {
395 changed = true; 409 changed = true;
396 NodeProperties::ReplaceValueInput(rep, cache->fields()[n], 410 NodeProperties::ReplaceValueInput(rep, cache->fields()[n],
397 n); 411 n);
398 } 412 }
399 } else { 413 } else {
400 changed = true; 414 changed = true;
401 rep->InsertInput(graph->zone(), n, cache->fields()[n]); 415 rep->InsertInput(graph->zone(), n, cache->fields()[n]);
402 } 416 }
403 } 417 }
404 if (rep->op()->ValueInputCount() != value_input_count) { 418 if (rep->op()->ValueInputCount() != value_input_count) {
405 if (FLAG_trace_turbo_escape) { 419 TRACE(" Widening Phi #%d of arity %d to %d\n", rep->id(),
406 PrintF(" Widening Phi #%d of arity %d to %d", rep->id(), 420 rep->op()->ValueInputCount(), value_input_count);
407 rep->op()->ValueInputCount(), value_input_count);
408 }
409 NodeProperties::ChangeOp( 421 NodeProperties::ChangeOp(
410 rep, common->Phi(MachineRepresentation::kTagged, 422 rep, common->Phi(MachineRepresentation::kTagged,
411 value_input_count)); 423 value_input_count));
412 } 424 }
413 } 425 }
414 } else { 426 } else {
415 if (FLAG_trace_turbo_escape) { 427 if (mergeObject->GetField(i) != nullptr) {
416 PrintF(" Field %zu cleared\n", i); 428 TRACE(" Field %zu cleared\n", i);
429 changed = true;
417 } 430 }
418 changed = mergeObject->SetField(i, nullptr) || changed; 431 changed = mergeObject->SetField(i, nullptr) || changed;
419 } 432 }
420 } 433 }
421 } 434 }
422 } else { 435 } else {
423 SetVirtualObject(alias, nullptr); 436 SetVirtualObject(alias, nullptr);
424 } 437 }
425 } 438 }
426 return changed; 439 return changed;
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 } 586 }
574 587
575 588
576 void EscapeStatusAnalysis::ProcessStoreField(Node* node) { 589 void EscapeStatusAnalysis::ProcessStoreField(Node* node) {
577 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField); 590 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField);
578 Node* to = NodeProperties::GetValueInput(node, 0); 591 Node* to = NodeProperties::GetValueInput(node, 0);
579 Node* val = NodeProperties::GetValueInput(node, 1); 592 Node* val = NodeProperties::GetValueInput(node, 1);
580 if ((IsEscaped(to) || !IsAllocation(to)) && SetEscaped(val)) { 593 if ((IsEscaped(to) || !IsAllocation(to)) && SetEscaped(val)) {
581 RevisitUses(val); 594 RevisitUses(val);
582 RevisitInputs(val); 595 RevisitInputs(val);
583 if (FLAG_trace_turbo_escape) { 596 TRACE("Setting #%d (%s) to escaped because of store to field of #%d\n",
584 PrintF("Setting #%d (%s) to escaped because of store to field of #%d\n", 597 val->id(), val->op()->mnemonic(), to->id());
585 val->id(), val->op()->mnemonic(), to->id());
586 }
587 } 598 }
588 } 599 }
589 600
590 601
591 void EscapeStatusAnalysis::ProcessStoreElement(Node* node) { 602 void EscapeStatusAnalysis::ProcessStoreElement(Node* node) {
592 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement); 603 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement);
593 Node* to = NodeProperties::GetValueInput(node, 0); 604 Node* to = NodeProperties::GetValueInput(node, 0);
594 Node* val = NodeProperties::GetValueInput(node, 2); 605 Node* val = NodeProperties::GetValueInput(node, 2);
595 if ((IsEscaped(to) || !IsAllocation(to)) && SetEscaped(val)) { 606 if ((IsEscaped(to) || !IsAllocation(to)) && SetEscaped(val)) {
596 RevisitUses(val); 607 RevisitUses(val);
597 RevisitInputs(val); 608 RevisitInputs(val);
598 if (FLAG_trace_turbo_escape) { 609 TRACE("Setting #%d (%s) to escaped because of store to field of #%d\n",
599 PrintF("Setting #%d (%s) to escaped because of store to field of #%d\n", 610 val->id(), val->op()->mnemonic(), to->id());
600 val->id(), val->op()->mnemonic(), to->id());
601 }
602 } 611 }
603 } 612 }
604 613
605 614
606 void EscapeStatusAnalysis::ProcessAllocate(Node* node) { 615 void EscapeStatusAnalysis::ProcessAllocate(Node* node) {
607 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); 616 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate);
608 if (!HasEntry(node)) { 617 if (!HasEntry(node)) {
609 status_[node->id()] |= kTracked; 618 status_[node->id()] |= kTracked;
610 if (FLAG_trace_turbo_escape) { 619 TRACE("Created status entry for node #%d (%s)\n", node->id(),
611 PrintF("Created status entry for node #%d (%s)\n", node->id(), 620 node->op()->mnemonic());
612 node->op()->mnemonic());
613 }
614 NumberMatcher size(node->InputAt(0)); 621 NumberMatcher size(node->InputAt(0));
615 DCHECK(node->InputAt(0)->opcode() != IrOpcode::kInt32Constant && 622 DCHECK(node->InputAt(0)->opcode() != IrOpcode::kInt32Constant &&
616 node->InputAt(0)->opcode() != IrOpcode::kInt64Constant && 623 node->InputAt(0)->opcode() != IrOpcode::kInt64Constant &&
617 node->InputAt(0)->opcode() != IrOpcode::kFloat32Constant && 624 node->InputAt(0)->opcode() != IrOpcode::kFloat32Constant &&
618 node->InputAt(0)->opcode() != IrOpcode::kFloat64Constant); 625 node->InputAt(0)->opcode() != IrOpcode::kFloat64Constant);
619 if (!size.HasValue() && SetEscaped(node)) { 626 if (!size.HasValue() && SetEscaped(node)) {
620 RevisitUses(node); 627 RevisitUses(node);
621 if (FLAG_trace_turbo_escape) { 628 TRACE("Setting #%d to escaped because of non-const alloc\n", node->id());
622 PrintF("Setting #%d to escaped because of non-const alloc\n",
623 node->id());
624 }
625 // This node is known to escape, uses do not have to be checked. 629 // This node is known to escape, uses do not have to be checked.
626 return; 630 return;
627 } 631 }
628 } 632 }
629 if (CheckUsesForEscape(node, true)) { 633 if (CheckUsesForEscape(node, true)) {
630 RevisitUses(node); 634 RevisitUses(node);
631 } 635 }
632 } 636 }
633 637
634 638
635 bool EscapeStatusAnalysis::CheckUsesForEscape(Node* uses, Node* rep, 639 bool EscapeStatusAnalysis::CheckUsesForEscape(Node* uses, Node* rep,
636 bool phi_escaping) { 640 bool phi_escaping) {
637 for (Edge edge : uses->use_edges()) { 641 for (Edge edge : uses->use_edges()) {
638 Node* use = edge.from(); 642 Node* use = edge.from();
639 if (edge.index() >= use->op()->ValueInputCount() + 643 if (edge.index() >= use->op()->ValueInputCount() +
640 OperatorProperties::GetContextInputCount(use->op())) 644 OperatorProperties::GetContextInputCount(use->op()))
641 continue; 645 continue;
642 switch (use->opcode()) { 646 switch (use->opcode()) {
643 case IrOpcode::kPhi: 647 case IrOpcode::kPhi:
644 if (phi_escaping && SetEscaped(rep)) { 648 if (phi_escaping && SetEscaped(rep)) {
645 if (FLAG_trace_turbo_escape) { 649 TRACE(
646 PrintF( 650 "Setting #%d (%s) to escaped because of use by phi node "
647 "Setting #%d (%s) to escaped because of use by phi node " 651 "#%d (%s)\n",
648 "#%d (%s)\n", 652 rep->id(), rep->op()->mnemonic(), use->id(),
649 rep->id(), rep->op()->mnemonic(), use->id(), 653 use->op()->mnemonic());
650 use->op()->mnemonic());
651 }
652 return true; 654 return true;
653 } 655 }
654 // Fallthrough. 656 // Fallthrough.
655 case IrOpcode::kStoreField: 657 case IrOpcode::kStoreField:
656 case IrOpcode::kLoadField: 658 case IrOpcode::kLoadField:
657 case IrOpcode::kStoreElement: 659 case IrOpcode::kStoreElement:
658 case IrOpcode::kLoadElement: 660 case IrOpcode::kLoadElement:
659 case IrOpcode::kFrameState: 661 case IrOpcode::kFrameState:
660 case IrOpcode::kStateValues: 662 case IrOpcode::kStateValues:
661 case IrOpcode::kReferenceEqual: 663 case IrOpcode::kReferenceEqual:
662 case IrOpcode::kFinishRegion: 664 case IrOpcode::kFinishRegion:
663 if (IsEscaped(use) && SetEscaped(rep)) { 665 if (IsEscaped(use) && SetEscaped(rep)) {
664 if (FLAG_trace_turbo_escape) { 666 TRACE(
665 PrintF( 667 "Setting #%d (%s) to escaped because of use by escaping node "
666 "Setting #%d (%s) to escaped because of use by escaping node " 668 "#%d (%s)\n",
667 "#%d (%s)\n", 669 rep->id(), rep->op()->mnemonic(), use->id(),
668 rep->id(), rep->op()->mnemonic(), use->id(), 670 use->op()->mnemonic());
669 use->op()->mnemonic());
670 }
671 return true; 671 return true;
672 } 672 }
673 break; 673 break;
674 case IrOpcode::kObjectIsSmi: 674 case IrOpcode::kObjectIsSmi:
675 if (!IsAllocation(rep) && SetEscaped(rep)) { 675 if (!IsAllocation(rep) && SetEscaped(rep)) {
676 PrintF("Setting #%d (%s) to escaped because of use by #%d (%s)\n", 676 TRACE("Setting #%d (%s) to escaped because of use by #%d (%s)\n",
677 rep->id(), rep->op()->mnemonic(), use->id(), 677 rep->id(), rep->op()->mnemonic(), use->id(),
678 use->op()->mnemonic()); 678 use->op()->mnemonic());
679 return true; 679 return true;
680 } 680 }
681 break; 681 break;
682 case IrOpcode::kSelect: 682 case IrOpcode::kSelect:
683 if (SetEscaped(rep)) { 683 if (SetEscaped(rep)) {
684 PrintF("Setting #%d (%s) to escaped because of use by #%d (%s)\n", 684 TRACE("Setting #%d (%s) to escaped because of use by #%d (%s)\n",
685 rep->id(), rep->op()->mnemonic(), use->id(), 685 rep->id(), rep->op()->mnemonic(), use->id(),
686 use->op()->mnemonic()); 686 use->op()->mnemonic());
687 return true; 687 return true;
688 } 688 }
689 break; 689 break;
690 default: 690 default:
691 if (use->op()->EffectInputCount() == 0 && 691 if (use->op()->EffectInputCount() == 0 &&
692 uses->op()->EffectInputCount() > 0) { 692 uses->op()->EffectInputCount() > 0) {
693 PrintF("Encountered unaccounted use by #%d (%s)\n", use->id(), 693 TRACE("Encountered unaccounted use by #%d (%s)\n", use->id(),
694 use->op()->mnemonic()); 694 use->op()->mnemonic());
695 UNREACHABLE(); 695 UNREACHABLE();
696 } 696 }
697 if (SetEscaped(rep)) { 697 if (SetEscaped(rep)) {
698 if (FLAG_trace_turbo_escape) { 698 TRACE("Setting #%d (%s) to escaped because of use by #%d (%s)\n",
699 PrintF("Setting #%d (%s) to escaped because of use by #%d (%s)\n", 699 rep->id(), rep->op()->mnemonic(), use->id(),
700 rep->id(), rep->op()->mnemonic(), use->id(), 700 use->op()->mnemonic());
701 use->op()->mnemonic());
702 }
703 return true; 701 return true;
704 } 702 }
705 } 703 }
706 } 704 }
707 return false; 705 return false;
708 } 706 }
709 707
710 708
711 void EscapeStatusAnalysis::ProcessFinishRegion(Node* node) { 709 void EscapeStatusAnalysis::ProcessFinishRegion(Node* node) {
712 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion); 710 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
755 escape_status_.Run(); 753 escape_status_.Run();
756 } 754 }
757 755
758 756
759 void EscapeAnalysis::AssignAliases() { 757 void EscapeAnalysis::AssignAliases() {
760 ZoneVector<Node*> stack(zone()); 758 ZoneVector<Node*> stack(zone());
761 stack.push_back(graph()->end()); 759 stack.push_back(graph()->end());
762 CHECK_LT(graph()->NodeCount(), kUntrackable); 760 CHECK_LT(graph()->NodeCount(), kUntrackable);
763 aliases_.resize(graph()->NodeCount(), kNotReachable); 761 aliases_.resize(graph()->NodeCount(), kNotReachable);
764 aliases_[graph()->end()->id()] = kUntrackable; 762 aliases_[graph()->end()->id()] = kUntrackable;
763 TRACE("Discovering trackable nodes");
765 while (!stack.empty()) { 764 while (!stack.empty()) {
766 Node* node = stack.back(); 765 Node* node = stack.back();
767 stack.pop_back(); 766 stack.pop_back();
768 switch (node->opcode()) { 767 switch (node->opcode()) {
769 case IrOpcode::kAllocate: 768 case IrOpcode::kAllocate:
770 if (aliases_[node->id()] >= kUntrackable) { 769 if (aliases_[node->id()] >= kUntrackable) {
771 aliases_[node->id()] = NextAlias(); 770 aliases_[node->id()] = NextAlias();
771 TRACE(" @%d:%s#%u", aliases_[node->id()], node->op()->mnemonic(),
772 node->id());
772 } 773 }
773 break; 774 break;
774 case IrOpcode::kFinishRegion: { 775 case IrOpcode::kFinishRegion: {
775 Node* allocate = NodeProperties::GetValueInput(node, 0); 776 Node* allocate = NodeProperties::GetValueInput(node, 0);
776 if (allocate->opcode() == IrOpcode::kAllocate) { 777 if (allocate->opcode() == IrOpcode::kAllocate) {
777 if (aliases_[allocate->id()] >= kUntrackable) { 778 if (aliases_[allocate->id()] >= kUntrackable) {
778 if (aliases_[allocate->id()] == kNotReachable) { 779 if (aliases_[allocate->id()] == kNotReachable) {
779 stack.push_back(allocate); 780 stack.push_back(allocate);
780 } 781 }
781 aliases_[allocate->id()] = NextAlias(); 782 aliases_[allocate->id()] = NextAlias();
783 TRACE(" @%d:%s#%u", aliases_[allocate->id()],
784 allocate->op()->mnemonic(), allocate->id());
782 } 785 }
783 aliases_[node->id()] = aliases_[allocate->id()]; 786 aliases_[node->id()] = aliases_[allocate->id()];
787 TRACE(" @%d:%s#%u", aliases_[node->id()], node->op()->mnemonic(),
788 node->id());
789
784 } else { 790 } else {
785 aliases_[node->id()] = NextAlias(); 791 aliases_[node->id()] = NextAlias();
792 TRACE(" @%d:%s#%u", aliases_[node->id()], node->op()->mnemonic(),
793 node->id());
786 } 794 }
787 break; 795 break;
788 } 796 }
789 default: 797 default:
790 DCHECK_EQ(aliases_[node->id()], kUntrackable); 798 DCHECK_EQ(aliases_[node->id()], kUntrackable);
791 break; 799 break;
792 } 800 }
793 for (Edge edge : node->input_edges()) { 801 for (Edge edge : node->input_edges()) {
794 Node* input = edge.to(); 802 Node* input = edge.to();
795 if (aliases_[input->id()] == kNotReachable) { 803 if (aliases_[input->id()] == kNotReachable) {
796 stack.push_back(input); 804 stack.push_back(input);
797 aliases_[input->id()] = kUntrackable; 805 aliases_[input->id()] = kUntrackable;
798 } 806 }
799 } 807 }
800 } 808 }
801 809 TRACE("\n");
802 if (FLAG_trace_turbo_escape) {
803 PrintF("Discovered trackable nodes");
804 for (EscapeAnalysis::Alias id = 0; id < graph()->NodeCount(); ++id) {
805 if (aliases_[id] < kUntrackable) {
806 if (FLAG_trace_turbo_escape) {
807 PrintF(" #%u", id);
808 }
809 }
810 }
811 PrintF("\n");
812 }
813 } 810 }
814 811
815 812
816 void EscapeAnalysis::RunObjectAnalysis() { 813 void EscapeAnalysis::RunObjectAnalysis() {
817 virtual_states_.resize(graph()->NodeCount()); 814 virtual_states_.resize(graph()->NodeCount());
818 ZoneVector<Node*> stack(zone()); 815 ZoneVector<Node*> stack(zone());
819 stack.push_back(graph()->start()); 816 stack.push_back(graph()->start());
820 while (!stack.empty()) { 817 while (!stack.empty()) {
821 Node* node = stack.back(); 818 Node* node = stack.back();
822 stack.pop_back(); 819 stack.pop_back();
(...skipping 14 matching lines...) Expand all
837 Node* use = edge.from(); 834 Node* use = edge.from();
838 if ((use->opcode() == IrOpcode::kLoadField || 835 if ((use->opcode() == IrOpcode::kLoadField ||
839 use->opcode() == IrOpcode::kLoadElement) && 836 use->opcode() == IrOpcode::kLoadElement) &&
840 IsDanglingEffectNode(use)) { 837 IsDanglingEffectNode(use)) {
841 stack.push_back(use); 838 stack.push_back(use);
842 } 839 }
843 } 840 }
844 } 841 }
845 } 842 }
846 } 843 }
844 #ifdef DEBUG
847 if (FLAG_trace_turbo_escape) { 845 if (FLAG_trace_turbo_escape) {
848 DebugPrint(); 846 DebugPrint();
849 } 847 }
848 #endif
850 } 849 }
851 850
852 851
853 bool EscapeAnalysis::IsDanglingEffectNode(Node* node) { 852 bool EscapeAnalysis::IsDanglingEffectNode(Node* node) {
854 if (node->op()->EffectInputCount() == 0) return false; 853 if (node->op()->EffectInputCount() == 0) return false;
855 if (node->op()->EffectOutputCount() == 0) return false; 854 if (node->op()->EffectOutputCount() == 0) return false;
856 if (node->op()->EffectInputCount() == 1 && 855 if (node->op()->EffectInputCount() == 1 &&
857 NodeProperties::GetEffectInput(node)->opcode() == IrOpcode::kStart) { 856 NodeProperties::GetEffectInput(node)->opcode() == IrOpcode::kStart) {
858 // The start node is used as sentinel for nodes that are in general 857 // The start node is used as sentinel for nodes that are in general
859 // effectful, but of which an analysis has determined that they do not 858 // effectful, but of which an analysis has determined that they do not
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
964 Node* effect = NodeProperties::GetEffectInput(node); 963 Node* effect = NodeProperties::GetEffectInput(node);
965 // Break the cycle for effect phis. 964 // Break the cycle for effect phis.
966 if (effect->opcode() == IrOpcode::kEffectPhi) { 965 if (effect->opcode() == IrOpcode::kEffectPhi) {
967 if (virtual_states_[effect->id()] == nullptr) { 966 if (virtual_states_[effect->id()] == nullptr) {
968 virtual_states_[effect->id()] = 967 virtual_states_[effect->id()] =
969 new (zone()) VirtualState(zone(), AliasCount()); 968 new (zone()) VirtualState(zone(), AliasCount());
970 } 969 }
971 } 970 }
972 DCHECK_NOT_NULL(virtual_states_[effect->id()]); 971 DCHECK_NOT_NULL(virtual_states_[effect->id()]);
973 if (IsEffectBranchPoint(effect)) { 972 if (IsEffectBranchPoint(effect)) {
974 if (FLAG_trace_turbo_escape) { 973 TRACE("Copying virtual state %p from #%d (%s) to #%d (%s)\n",
975 PrintF("Copying object state %p from #%d (%s) to #%d (%s)\n", 974 static_cast<void*>(virtual_states_[effect->id()]), effect->id(),
976 static_cast<void*>(virtual_states_[effect->id()]), effect->id(), 975 effect->op()->mnemonic(), node->id(), node->op()->mnemonic());
977 effect->op()->mnemonic(), node->id(), node->op()->mnemonic());
978 }
979 if (!virtual_states_[node->id()]) { 976 if (!virtual_states_[node->id()]) {
980 virtual_states_[node->id()] = 977 virtual_states_[node->id()] =
981 new (zone()) VirtualState(*virtual_states_[effect->id()]); 978 new (zone()) VirtualState(*virtual_states_[effect->id()]);
982 } else { 979 } else {
983 virtual_states_[node->id()]->UpdateFrom(virtual_states_[effect->id()], 980 virtual_states_[node->id()]->UpdateFrom(virtual_states_[effect->id()],
984 zone()); 981 zone());
985 } 982 }
986 } else { 983 } else {
987 virtual_states_[node->id()] = virtual_states_[effect->id()]; 984 virtual_states_[node->id()] = virtual_states_[effect->id()];
988 if (FLAG_trace_turbo_escape) { 985 TRACE("Forwarding virtual state %p from #%d (%s) to #%d (%s)\n",
989 PrintF("Forwarding object state %p from #%d (%s) to #%d (%s)\n", 986 static_cast<void*>(virtual_states_[effect->id()]), effect->id(),
990 static_cast<void*>(virtual_states_[effect->id()]), effect->id(), 987 effect->op()->mnemonic(), node->id(), node->op()->mnemonic());
991 effect->op()->mnemonic(), node->id(), node->op()->mnemonic());
992 }
993 } 988 }
994 } 989 }
995 990
996 991
997 void EscapeAnalysis::ProcessStart(Node* node) { 992 void EscapeAnalysis::ProcessStart(Node* node) {
998 DCHECK_EQ(node->opcode(), IrOpcode::kStart); 993 DCHECK_EQ(node->opcode(), IrOpcode::kStart);
999 virtual_states_[node->id()] = new (zone()) VirtualState(zone(), AliasCount()); 994 virtual_states_[node->id()] = new (zone()) VirtualState(zone(), AliasCount());
1000 } 995 }
1001 996
1002 997
1003 bool EscapeAnalysis::ProcessEffectPhi(Node* node) { 998 bool EscapeAnalysis::ProcessEffectPhi(Node* node) {
1004 DCHECK_EQ(node->opcode(), IrOpcode::kEffectPhi); 999 DCHECK_EQ(node->opcode(), IrOpcode::kEffectPhi);
1005 bool changed = false; 1000 bool changed = false;
1006 1001
1007 VirtualState* mergeState = virtual_states_[node->id()]; 1002 VirtualState* mergeState = virtual_states_[node->id()];
1008 if (!mergeState) { 1003 if (!mergeState) {
1009 mergeState = new (zone()) VirtualState(zone(), AliasCount()); 1004 mergeState = new (zone()) VirtualState(zone(), AliasCount());
1010 virtual_states_[node->id()] = mergeState; 1005 virtual_states_[node->id()] = mergeState;
1011 changed = true; 1006 changed = true;
1012 if (FLAG_trace_turbo_escape) { 1007 TRACE("Effect Phi #%d got new virtual state %p.\n", node->id(),
1013 PrintF("Effect Phi #%d got new states map %p.\n", node->id(), 1008 static_cast<void*>(mergeState));
1014 static_cast<void*>(mergeState));
1015 }
1016 } else if (mergeState->GetLastChanged() != node) { 1009 } else if (mergeState->GetLastChanged() != node) {
1017 changed = true; 1010 changed = true;
1018 } 1011 }
1019 1012
1020 cache_->Clear(); 1013 cache_->Clear();
1021 1014
1022 if (FLAG_trace_turbo_escape) { 1015 TRACE("At Effect Phi #%d, merging states into %p:", node->id(),
1023 PrintF("At Effect Phi #%d, merging states into %p:", node->id(), 1016 static_cast<void*>(mergeState));
1024 static_cast<void*>(mergeState));
1025 }
1026 1017
1027 for (int i = 0; i < node->op()->EffectInputCount(); ++i) { 1018 for (int i = 0; i < node->op()->EffectInputCount(); ++i) {
1028 Node* input = NodeProperties::GetEffectInput(node, i); 1019 Node* input = NodeProperties::GetEffectInput(node, i);
1029 VirtualState* state = virtual_states_[input->id()]; 1020 VirtualState* state = virtual_states_[input->id()];
1030 if (state) { 1021 if (state) {
1031 cache_->states().push_back(state); 1022 cache_->states().push_back(state);
1032 } 1023 }
1033 if (FLAG_trace_turbo_escape) { 1024 TRACE(" %p (from %d %s)", static_cast<void*>(state), input->id(),
1034 PrintF(" %p (from %d %s)", static_cast<void*>(state), input->id(), 1025 input->op()->mnemonic());
1035 input->op()->mnemonic());
1036 }
1037 } 1026 }
1038 if (FLAG_trace_turbo_escape) { 1027 TRACE("\n");
1039 PrintF("\n");
1040 }
1041 1028
1042 if (cache_->states().size() == 0) { 1029 if (cache_->states().size() == 0) {
1043 return changed; 1030 return changed;
1044 } 1031 }
1045 1032
1046 changed = mergeState->MergeFrom(cache_, zone(), graph(), common(), 1033 changed = mergeState->MergeFrom(cache_, zone(), graph(), common(),
1047 NodeProperties::GetControlInput(node)) || 1034 NodeProperties::GetControlInput(node)) ||
1048 changed; 1035 changed;
1049 1036
1050 if (FLAG_trace_turbo_escape) { 1037 TRACE("Merge %s the node.\n", changed ? "changed" : "did not change");
1051 PrintF("Merge %s the node.\n", changed ? "changed" : "did not change");
1052 }
1053 1038
1054 if (changed) { 1039 if (changed) {
1055 mergeState->LastChangedAt(node); 1040 mergeState->LastChangedAt(node);
1056 escape_status_.Resize(); 1041 escape_status_.Resize();
1057 } 1042 }
1058 return changed; 1043 return changed;
1059 } 1044 }
1060 1045
1061 1046
1062 void EscapeAnalysis::ProcessAllocation(Node* node) { 1047 void EscapeAnalysis::ProcessAllocation(Node* node) {
(...skipping 28 matching lines...) Expand all
1091 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion); 1076 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion);
1092 ForwardVirtualState(node); 1077 ForwardVirtualState(node);
1093 Node* allocation = NodeProperties::GetValueInput(node, 0); 1078 Node* allocation = NodeProperties::GetValueInput(node, 0);
1094 if (allocation->opcode() == IrOpcode::kAllocate) { 1079 if (allocation->opcode() == IrOpcode::kAllocate) {
1095 VirtualState* state = virtual_states_[node->id()]; 1080 VirtualState* state = virtual_states_[node->id()];
1096 if (!state->VirtualObjectFromAlias(aliases_[node->id()])) { 1081 if (!state->VirtualObjectFromAlias(aliases_[node->id()])) {
1097 VirtualObject* vobj_alloc = 1082 VirtualObject* vobj_alloc =
1098 state->VirtualObjectFromAlias(aliases_[allocation->id()]); 1083 state->VirtualObjectFromAlias(aliases_[allocation->id()]);
1099 DCHECK_NOT_NULL(vobj_alloc); 1084 DCHECK_NOT_NULL(vobj_alloc);
1100 state->SetVirtualObject(aliases_[node->id()], vobj_alloc); 1085 state->SetVirtualObject(aliases_[node->id()], vobj_alloc);
1101 if (FLAG_trace_turbo_escape) { 1086 TRACE("Linked finish region node #%d to node #%d\n", node->id(),
1102 PrintF("Linked finish region node #%d to node #%d\n", node->id(), 1087 allocation->id());
1103 allocation->id());
1104 }
1105 state->LastChangedAt(node); 1088 state->LastChangedAt(node);
1106 } 1089 }
1107 } 1090 }
1108 } 1091 }
1109 1092
1110 1093
1111 Node* EscapeAnalysis::replacement(NodeId id) { 1094 Node* EscapeAnalysis::replacement(NodeId id) {
1112 if (id >= replacements_.size()) return nullptr; 1095 if (id >= replacements_.size()) return nullptr;
1113 return replacements_[id]; 1096 return replacements_[id];
1114 } 1097 }
1115 1098
1116 1099
1117 Node* EscapeAnalysis::replacement(Node* node) { 1100 Node* EscapeAnalysis::replacement(Node* node) {
1118 return replacement(node->id()); 1101 return replacement(node->id());
1119 } 1102 }
1120 1103
1121 1104
1122 bool EscapeAnalysis::SetReplacement(Node* node, Node* rep) { 1105 bool EscapeAnalysis::SetReplacement(Node* node, Node* rep) {
1123 bool changed = replacements_[node->id()] != rep; 1106 bool changed = replacements_[node->id()] != rep;
1124 replacements_[node->id()] = rep; 1107 replacements_[node->id()] = rep;
1125 return changed; 1108 return changed;
1126 } 1109 }
1127 1110
1128 1111
1129 bool EscapeAnalysis::UpdateReplacement(VirtualState* state, Node* node, 1112 bool EscapeAnalysis::UpdateReplacement(VirtualState* state, Node* node,
1130 Node* rep) { 1113 Node* rep) {
1131 if (SetReplacement(node, rep)) { 1114 if (SetReplacement(node, rep)) {
1132 state->LastChangedAt(node); 1115 state->LastChangedAt(node);
1133 if (FLAG_trace_turbo_escape) { 1116 if (rep) {
1134 if (rep) { 1117 TRACE("Replacement of #%d is #%d (%s)\n", node->id(), rep->id(),
1135 PrintF("Replacement of #%d is #%d (%s)\n", node->id(), rep->id(), 1118 rep->op()->mnemonic());
1136 rep->op()->mnemonic()); 1119 } else {
1137 } else { 1120 TRACE("Replacement of #%d cleared\n", node->id());
1138 PrintF("Replacement of #%d cleared\n", node->id());
1139 }
1140 } 1121 }
1141 return true; 1122 return true;
1142 } 1123 }
1143 return false; 1124 return false;
1144 } 1125 }
1145 1126
1146 1127
1147 Node* EscapeAnalysis::ResolveReplacement(Node* node) { 1128 Node* EscapeAnalysis::ResolveReplacement(Node* node) {
1148 while (replacement(node)) { 1129 while (replacement(node)) {
1149 node = replacement(node); 1130 node = replacement(node);
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
1214 1195
1215 1196
1216 int EscapeAnalysis::OffsetFromAccess(Node* node) { 1197 int EscapeAnalysis::OffsetFromAccess(Node* node) {
1217 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0); 1198 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0);
1218 return OpParameter<FieldAccess>(node).offset / kPointerSize; 1199 return OpParameter<FieldAccess>(node).offset / kPointerSize;
1219 } 1200 }
1220 1201
1221 1202
1222 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node, 1203 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node,
1223 VirtualState* state) { 1204 VirtualState* state) {
1224 if (FLAG_trace_turbo_escape) { 1205 TRACE("Load #%d from phi #%d", node->id(), from->id());
1225 PrintF("Load #%d from phi #%d", node->id(), from->id());
1226 }
1227 1206
1228 cache_->fields().clear(); 1207 cache_->fields().clear();
1229 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { 1208 for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
1230 Node* input = NodeProperties::GetValueInput(node, i); 1209 Node* input = NodeProperties::GetValueInput(node, i);
1231 cache_->fields().push_back(input); 1210 cache_->fields().push_back(input);
1232 } 1211 }
1233 1212
1234 cache_->LoadVirtualObjectsForFieldsFrom(state, aliases_); 1213 cache_->LoadVirtualObjectsForFieldsFrom(state, aliases_);
1235 if (cache_->objects().size() == cache_->fields().size()) { 1214 if (cache_->objects().size() == cache_->fields().size()) {
1236 cache_->GetFields(offset); 1215 cache_->GetFields(offset);
1237 if (cache_->fields().size() == cache_->objects().size()) { 1216 if (cache_->fields().size() == cache_->objects().size()) {
1238 Node* rep = replacement(node); 1217 Node* rep = replacement(node);
1239 if (!rep || !IsEquivalentPhi(rep, cache_->fields())) { 1218 if (!rep || !IsEquivalentPhi(rep, cache_->fields())) {
1240 int value_input_count = static_cast<int>(cache_->fields().size()); 1219 int value_input_count = static_cast<int>(cache_->fields().size());
1241 cache_->fields().push_back(NodeProperties::GetControlInput(from)); 1220 cache_->fields().push_back(NodeProperties::GetControlInput(from));
1242 Node* phi = graph()->NewNode( 1221 Node* phi = graph()->NewNode(
1243 common()->Phi(MachineRepresentation::kTagged, value_input_count), 1222 common()->Phi(MachineRepresentation::kTagged, value_input_count),
1244 value_input_count + 1, &cache_->fields().front()); 1223 value_input_count + 1, &cache_->fields().front());
1245 escape_status_.Resize(); 1224 escape_status_.Resize();
1246 SetReplacement(node, phi); 1225 SetReplacement(node, phi);
1247 state->LastChangedAt(node); 1226 state->LastChangedAt(node);
1248 if (FLAG_trace_turbo_escape) { 1227 TRACE(" got phi created.\n");
1249 PrintF(" got phi created.\n"); 1228 } else {
1250 } 1229 TRACE(" has already phi #%d.\n", rep->id());
1251 } else if (FLAG_trace_turbo_escape) {
1252 PrintF(" has already phi #%d.\n", rep->id());
1253 } 1230 }
1254 } else if (FLAG_trace_turbo_escape) { 1231 } else {
1255 PrintF(" has incomplete field info.\n"); 1232 TRACE(" has incomplete field info.\n");
1256 } 1233 }
1257 } else if (FLAG_trace_turbo_escape) { 1234 } else {
1258 PrintF(" has incomplete virtual object info.\n"); 1235 TRACE(" has incomplete virtual object info.\n");
1259 } 1236 }
1260 } 1237 }
1261 1238
1262 1239
1263 void EscapeAnalysis::ProcessLoadField(Node* node) { 1240 void EscapeAnalysis::ProcessLoadField(Node* node) {
1264 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField); 1241 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField);
1265 ForwardVirtualState(node); 1242 ForwardVirtualState(node);
1266 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); 1243 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1267 VirtualState* state = virtual_states_[node->id()]; 1244 VirtualState* state = virtual_states_[node->id()];
1268 if (VirtualObject* object = GetVirtualObject(state, from)) { 1245 if (VirtualObject* object = GetVirtualObject(state, from)) {
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after
1314 } else if (from->opcode() == IrOpcode::kPhi) { 1291 } else if (from->opcode() == IrOpcode::kPhi) {
1315 ElementAccess access = OpParameter<ElementAccess>(node); 1292 ElementAccess access = OpParameter<ElementAccess>(node);
1316 int offset = index.Value() + access.header_size / kPointerSize; 1293 int offset = index.Value() + access.header_size / kPointerSize;
1317 ProcessLoadFromPhi(offset, from, node, state); 1294 ProcessLoadFromPhi(offset, from, node, state);
1318 } else { 1295 } else {
1319 UpdateReplacement(state, node, nullptr); 1296 UpdateReplacement(state, node, nullptr);
1320 } 1297 }
1321 } else { 1298 } else {
1322 // We have a load from a non-const index, cannot eliminate object. 1299 // We have a load from a non-const index, cannot eliminate object.
1323 if (SetEscaped(from)) { 1300 if (SetEscaped(from)) {
1324 if (FLAG_trace_turbo_escape) { 1301 TRACE(
1325 PrintF( 1302 "Setting #%d (%s) to escaped because load element #%d from non-const "
1326 "Setting #%d (%s) to escaped because load element #%d from " 1303 "index #%d (%s)\n",
1327 "non-const " 1304 from->id(), from->op()->mnemonic(), node->id(), index_node->id(),
1328 "index #%d (%s)\n", 1305 index_node->op()->mnemonic());
1329 from->id(), from->op()->mnemonic(), node->id(), index_node->id(),
1330 index_node->op()->mnemonic());
1331 }
1332 } 1306 }
1333 } 1307 }
1334 } 1308 }
1335 1309
1336 1310
1337 void EscapeAnalysis::ProcessStoreField(Node* node) { 1311 void EscapeAnalysis::ProcessStoreField(Node* node) {
1338 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField); 1312 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField);
1339 ForwardVirtualState(node); 1313 ForwardVirtualState(node);
1340 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0)); 1314 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1341 VirtualState* state = virtual_states_[node->id()]; 1315 VirtualState* state = virtual_states_[node->id()];
(...skipping 28 matching lines...) Expand all
1370 kPointerSizeLog2); 1344 kPointerSizeLog2);
1371 CHECK_EQ(access.header_size % kPointerSize, 0); 1345 CHECK_EQ(access.header_size % kPointerSize, 0);
1372 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 2)); 1346 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 2));
1373 if (obj->SetField(offset, val)) { 1347 if (obj->SetField(offset, val)) {
1374 state->LastChangedAt(node); 1348 state->LastChangedAt(node);
1375 } 1349 }
1376 } 1350 }
1377 } else { 1351 } else {
1378 // We have a store to a non-const index, cannot eliminate object. 1352 // We have a store to a non-const index, cannot eliminate object.
1379 if (SetEscaped(to)) { 1353 if (SetEscaped(to)) {
1380 if (FLAG_trace_turbo_escape) { 1354 TRACE(
1381 PrintF( 1355 "Setting #%d (%s) to escaped because store element #%d to non-const "
1382 "Setting #%d (%s) to escaped because store element #%d to " 1356 "index #%d (%s)\n",
1383 "non-const " 1357 to->id(), to->op()->mnemonic(), node->id(), index_node->id(),
1384 "index #%d (%s)\n", 1358 index_node->op()->mnemonic());
1385 to->id(), to->op()->mnemonic(), node->id(), index_node->id(),
1386 index_node->op()->mnemonic());
1387 }
1388 } 1359 }
1389 if (obj && obj->IsTracked() && obj->ClearAllFields()) { 1360 if (obj && obj->IsTracked() && obj->ClearAllFields()) {
1390 state->LastChangedAt(node); 1361 state->LastChangedAt(node);
1362 TRACE("Cleared all fields of @%d:#%d\n", aliases_[obj->id()], obj->id());
1391 } 1363 }
1392 } 1364 }
1393 } 1365 }
1394 1366
1395 1367
1396 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) { 1368 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) {
1397 if ((node->opcode() == IrOpcode::kFinishRegion || 1369 if ((node->opcode() == IrOpcode::kFinishRegion ||
1398 node->opcode() == IrOpcode::kAllocate) && 1370 node->opcode() == IrOpcode::kAllocate) &&
1399 IsVirtual(node)) { 1371 IsVirtual(node)) {
1400 if (VirtualObject* vobj = 1372 if (VirtualObject* vobj =
1401 ResolveVirtualObject(virtual_states_[effect->id()], node)) { 1373 ResolveVirtualObject(virtual_states_[effect->id()], node)) {
1402 if (Node* object_state = vobj->GetObjectState()) { 1374 if (Node* object_state = vobj->GetObjectState()) {
1403 return object_state; 1375 return object_state;
1404 } else { 1376 } else {
1405 cache_->fields().clear(); 1377 cache_->fields().clear();
1406 for (size_t i = 0; i < vobj->field_count(); ++i) { 1378 for (size_t i = 0; i < vobj->field_count(); ++i) {
1407 if (Node* field = vobj->GetField(i)) { 1379 if (Node* field = vobj->GetField(i)) {
1408 cache_->fields().push_back(field); 1380 cache_->fields().push_back(field);
1409 } 1381 }
1410 } 1382 }
1411 int input_count = static_cast<int>(cache_->fields().size()); 1383 int input_count = static_cast<int>(cache_->fields().size());
1412 Node* new_object_state = 1384 Node* new_object_state =
1413 graph()->NewNode(common()->ObjectState(input_count, vobj->id()), 1385 graph()->NewNode(common()->ObjectState(input_count, vobj->id()),
1414 input_count, &cache_->fields().front()); 1386 input_count, &cache_->fields().front());
1415 vobj->SetObjectState(new_object_state); 1387 vobj->SetObjectState(new_object_state);
1416 if (FLAG_trace_turbo_escape) { 1388 TRACE(
1417 PrintF( 1389 "Creating object state #%d for vobj %p (from node #%d) at effect "
1418 "Creating object state #%d for vobj %p (from node #%d) at effect " 1390 "#%d\n",
1419 "#%d\n", 1391 new_object_state->id(), static_cast<void*>(vobj), node->id(),
1420 new_object_state->id(), static_cast<void*>(vobj), node->id(), 1392 effect->id());
1421 effect->id());
1422 }
1423 // Now fix uses of other objects. 1393 // Now fix uses of other objects.
1424 for (size_t i = 0; i < vobj->field_count(); ++i) { 1394 for (size_t i = 0; i < vobj->field_count(); ++i) {
1425 if (Node* field = vobj->GetField(i)) { 1395 if (Node* field = vobj->GetField(i)) {
1426 if (Node* field_object_state = 1396 if (Node* field_object_state =
1427 GetOrCreateObjectState(effect, field)) { 1397 GetOrCreateObjectState(effect, field)) {
1428 NodeProperties::ReplaceValueInput( 1398 NodeProperties::ReplaceValueInput(
1429 new_object_state, field_object_state, static_cast<int>(i)); 1399 new_object_state, field_object_state, static_cast<int>(i));
1430 } 1400 }
1431 } 1401 }
1432 } 1402 }
(...skipping 10 matching lines...) Expand all
1443 object->field_count()); 1413 object->field_count());
1444 for (size_t i = 0; i < object->field_count(); ++i) { 1414 for (size_t i = 0; i < object->field_count(); ++i) {
1445 if (Node* f = object->GetField(i)) { 1415 if (Node* f = object->GetField(i)) {
1446 PrintF(" Field %zu = #%d (%s)\n", i, f->id(), f->op()->mnemonic()); 1416 PrintF(" Field %zu = #%d (%s)\n", i, f->id(), f->op()->mnemonic());
1447 } 1417 }
1448 } 1418 }
1449 } 1419 }
1450 1420
1451 1421
1452 void EscapeAnalysis::DebugPrintState(VirtualState* state) { 1422 void EscapeAnalysis::DebugPrintState(VirtualState* state) {
1453 PrintF("Dumping object state %p\n", static_cast<void*>(state)); 1423 PrintF("Dumping virtual state %p\n", static_cast<void*>(state));
1454 for (Alias alias = 0; alias < AliasCount(); ++alias) { 1424 for (Alias alias = 0; alias < AliasCount(); ++alias) {
1455 if (VirtualObject* object = state->VirtualObjectFromAlias(alias)) { 1425 if (VirtualObject* object = state->VirtualObjectFromAlias(alias)) {
1456 DebugPrintObject(object, alias); 1426 DebugPrintObject(object, alias);
1457 } 1427 }
1458 } 1428 }
1459 } 1429 }
1460 1430
1461 1431
1462 void EscapeAnalysis::DebugPrint() { 1432 void EscapeAnalysis::DebugPrint() {
1463 ZoneVector<VirtualState*> object_states(zone()); 1433 ZoneVector<VirtualState*> object_states(zone());
(...skipping 28 matching lines...) Expand all
1492 return true; 1462 return true;
1493 } 1463 }
1494 } 1464 }
1495 } 1465 }
1496 return false; 1466 return false;
1497 } 1467 }
1498 1468
1499 } // namespace compiler 1469 } // namespace compiler
1500 } // namespace internal 1470 } // namespace internal
1501 } // namespace v8 1471 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/escape-analysis-reducer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698