OLD | NEW |
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" |
11 #include "src/compiler/graph-reducer.h" | 11 #include "src/compiler/graph-reducer.h" |
12 #include "src/compiler/js-operator.h" | 12 #include "src/compiler/js-operator.h" |
13 #include "src/compiler/node.h" | 13 #include "src/compiler/node.h" |
14 #include "src/compiler/node-matchers.h" | 14 #include "src/compiler/node-matchers.h" |
15 #include "src/compiler/node-properties.h" | 15 #include "src/compiler/node-properties.h" |
16 #include "src/compiler/simplified-operator.h" | 16 #include "src/compiler/simplified-operator.h" |
17 #include "src/objects-inl.h" | 17 #include "src/objects-inl.h" |
18 #include "src/type-cache.h" | 18 #include "src/type-cache.h" |
19 | 19 |
20 namespace v8 { | 20 namespace v8 { |
21 namespace internal { | 21 namespace internal { |
22 namespace compiler { | 22 namespace compiler { |
23 | 23 |
24 | 24 |
| 25 // ------------------------------VirtualObject---------------------------------- |
| 26 |
| 27 |
25 class VirtualObject : public ZoneObject { | 28 class VirtualObject : public ZoneObject { |
26 public: | 29 public: |
27 enum Status { kUntracked = 0, kTracked = 1 }; | 30 enum Status { kUntracked = 0, kTracked = 1 }; |
28 VirtualObject(NodeId id, Zone* zone) | 31 VirtualObject(NodeId id, Zone* zone) |
29 : id_(id), status_(kUntracked), fields_(zone), replacement_(nullptr) {} | 32 : id_(id), status_(kUntracked), fields_(zone), replacement_(nullptr) {} |
30 | 33 |
31 VirtualObject(const VirtualObject& other) | 34 VirtualObject(const VirtualObject& other) |
32 : id_(other.id_), | 35 : id_(other.id_), |
33 status_(other.status_), | 36 status_(other.status_), |
34 fields_(other.fields_), | 37 fields_(other.fields_), |
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 void id(NodeId id) { id_ = id; } | 78 void id(NodeId id) { id_ = id; } |
76 | 79 |
77 private: | 80 private: |
78 NodeId id_; | 81 NodeId id_; |
79 Status status_; | 82 Status status_; |
80 ZoneVector<Node*> fields_; | 83 ZoneVector<Node*> fields_; |
81 Node* replacement_; | 84 Node* replacement_; |
82 }; | 85 }; |
83 | 86 |
84 | 87 |
| 88 bool VirtualObject::UpdateFrom(const VirtualObject& other) { |
| 89 bool changed = status_ != other.status_; |
| 90 status_ = other.status_; |
| 91 changed = replacement_ != other.replacement_ || changed; |
| 92 replacement_ = other.replacement_; |
| 93 if (fields_.size() != other.fields_.size()) { |
| 94 fields_ = other.fields_; |
| 95 return true; |
| 96 } |
| 97 for (size_t i = 0; i < fields_.size(); ++i) { |
| 98 if (fields_[i] != other.fields_[i]) { |
| 99 changed = true; |
| 100 fields_[i] = other.fields_[i]; |
| 101 } |
| 102 } |
| 103 return changed; |
| 104 } |
| 105 |
| 106 |
| 107 // ------------------------------VirtualState----------------------------------- |
| 108 |
| 109 |
85 class VirtualState : public ZoneObject { | 110 class VirtualState : public ZoneObject { |
86 public: | 111 public: |
87 VirtualState(Zone* zone, size_t size); | 112 VirtualState(Zone* zone, size_t size); |
88 VirtualState(const VirtualState& states); | 113 VirtualState(const VirtualState& states); |
89 | 114 |
90 VirtualObject* GetVirtualObject(Node* node); | 115 VirtualObject* GetVirtualObject(Node* node); |
91 VirtualObject* GetVirtualObject(size_t id); | 116 VirtualObject* GetVirtualObject(size_t id); |
92 VirtualObject* GetOrCreateTrackedVirtualObject(NodeId id, Zone* zone); | 117 VirtualObject* GetOrCreateTrackedVirtualObject(NodeId id, Zone* zone); |
93 void SetVirtualObject(NodeId id, VirtualObject* state); | 118 void SetVirtualObject(NodeId id, VirtualObject* state); |
94 void LastChangedAt(Node* node) { last_changed_ = node; } | 119 void LastChangedAt(Node* node) { last_changed_ = node; } |
95 Node* GetLastChanged() { return last_changed_; } | 120 Node* GetLastChanged() { return last_changed_; } |
96 bool UpdateFrom(NodeId id, VirtualObject* state, Zone* zone); | 121 bool UpdateFrom(NodeId id, VirtualObject* state, Zone* zone); |
97 Node* ResolveReplacement(Node* node); | 122 Node* ResolveReplacement(Node* node); |
98 bool UpdateReplacement(Node* node, Node* rep, Zone* zone); | 123 bool UpdateReplacement(Node* node, Node* rep, Zone* zone); |
99 bool UpdateFrom(VirtualState* state, Zone* zone); | 124 bool UpdateFrom(VirtualState* state, Zone* zone); |
100 bool MergeFrom(VirtualState* left, VirtualState* right, Zone* zone, | 125 bool MergeFrom(VirtualState* left, VirtualState* right, Zone* zone, |
101 Graph* graph, CommonOperatorBuilder* common, Node* control); | 126 Graph* graph, CommonOperatorBuilder* common, Node* control); |
102 | 127 |
103 size_t size() { return info_.size(); } | 128 size_t size() { return info_.size(); } |
104 | 129 |
105 private: | 130 private: |
106 ZoneVector<VirtualObject*> info_; | 131 ZoneVector<VirtualObject*> info_; |
107 Node* last_changed_; | 132 Node* last_changed_; |
108 }; | 133 }; |
109 | 134 |
110 | 135 |
111 bool VirtualObject::UpdateFrom(const VirtualObject& other) { | |
112 bool changed = status_ != other.status_; | |
113 status_ = other.status_; | |
114 changed = replacement_ != other.replacement_ || changed; | |
115 replacement_ = other.replacement_; | |
116 if (fields_.size() != other.fields_.size()) { | |
117 fields_ = other.fields_; | |
118 return true; | |
119 } | |
120 for (size_t i = 0; i < fields_.size(); ++i) { | |
121 if (fields_[i] != other.fields_[i]) { | |
122 changed = true; | |
123 fields_[i] = other.fields_[i]; | |
124 } | |
125 } | |
126 return changed; | |
127 } | |
128 | |
129 | |
130 VirtualState::VirtualState(Zone* zone, size_t size) | 136 VirtualState::VirtualState(Zone* zone, size_t size) |
131 : info_(zone), last_changed_(nullptr) { | 137 : info_(zone), last_changed_(nullptr) { |
132 info_.resize(size); | 138 info_.resize(size); |
133 } | 139 } |
134 | 140 |
135 | 141 |
136 VirtualState::VirtualState(const VirtualState& state) | 142 VirtualState::VirtualState(const VirtualState& state) |
137 : info_(state.info_.get_allocator().zone()), | 143 : info_(state.info_.get_allocator().zone()), |
138 last_changed_(state.last_changed_) { | 144 last_changed_(state.last_changed_) { |
139 info_.resize(state.info_.size()); | 145 info_.resize(state.info_.size()); |
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
291 } | 297 } |
292 return true; | 298 return true; |
293 } | 299 } |
294 return false; | 300 return false; |
295 } | 301 } |
296 | 302 |
297 | 303 |
298 // ------------------------------EscapeStatusAnalysis--------------------------- | 304 // ------------------------------EscapeStatusAnalysis--------------------------- |
299 | 305 |
300 | 306 |
301 EscapeStatusAnalysis::EscapeStatusAnalysis( | 307 EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis, |
302 EscapeObjectAnalysis* object_analysis, Graph* graph, Zone* zone) | 308 Graph* graph, Zone* zone) |
303 : object_analysis_(object_analysis), | 309 : object_analysis_(object_analysis), |
304 graph_(graph), | 310 graph_(graph), |
305 zone_(zone), | 311 zone_(zone), |
306 info_(zone), | 312 info_(zone), |
307 queue_(zone) {} | 313 queue_(zone) {} |
308 | 314 |
309 | 315 |
310 EscapeStatusAnalysis::~EscapeStatusAnalysis() {} | 316 EscapeStatusAnalysis::~EscapeStatusAnalysis() {} |
311 | 317 |
312 | 318 |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
506 void EscapeStatusAnalysis::DebugPrint() { | 512 void EscapeStatusAnalysis::DebugPrint() { |
507 for (NodeId id = 0; id < info_.size(); id++) { | 513 for (NodeId id = 0; id < info_.size(); id++) { |
508 if (info_[id] != kUnknown) { | 514 if (info_[id] != kUnknown) { |
509 PrintF("Node #%d is %s\n", id, | 515 PrintF("Node #%d is %s\n", id, |
510 info_[id] == kEscaped ? "escaping" : "virtual"); | 516 info_[id] == kEscaped ? "escaping" : "virtual"); |
511 } | 517 } |
512 } | 518 } |
513 } | 519 } |
514 | 520 |
515 | 521 |
516 // -----------------------------EscapeObjectAnalysis--------------------------- | 522 // -----------------------------EscapeAnalysis---------------------------------- |
517 | 523 |
518 | 524 |
519 EscapeObjectAnalysis::EscapeObjectAnalysis(Graph* graph, | 525 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, |
520 CommonOperatorBuilder* common, | 526 Zone* zone) |
521 Zone* zone) | 527 : graph_(graph), |
522 : graph_(graph), common_(common), zone_(zone), virtual_states_(zone) {} | 528 common_(common), |
| 529 zone_(zone), |
| 530 virtual_states_(zone), |
| 531 escape_status_(this, graph, zone) {} |
523 | 532 |
524 | 533 |
525 EscapeObjectAnalysis::~EscapeObjectAnalysis() {} | 534 EscapeAnalysis::~EscapeAnalysis() {} |
526 | 535 |
527 | 536 |
528 void EscapeObjectAnalysis::Run() { | 537 void EscapeAnalysis::Run() { |
| 538 RunObjectAnalysis(); |
| 539 escape_status_.Run(); |
| 540 } |
| 541 |
| 542 |
| 543 void EscapeAnalysis::RunObjectAnalysis() { |
529 virtual_states_.resize(graph()->NodeCount()); | 544 virtual_states_.resize(graph()->NodeCount()); |
530 ZoneVector<Node*> queue(zone()); | 545 ZoneVector<Node*> queue(zone()); |
531 queue.push_back(graph()->start()); | 546 queue.push_back(graph()->start()); |
532 while (!queue.empty()) { | 547 while (!queue.empty()) { |
533 Node* node = queue.back(); | 548 Node* node = queue.back(); |
534 queue.pop_back(); | 549 queue.pop_back(); |
535 if (Process(node)) { | 550 if (Process(node)) { |
536 for (Edge edge : node->use_edges()) { | 551 for (Edge edge : node->use_edges()) { |
537 if (NodeProperties::IsEffectEdge(edge)) { | 552 if (NodeProperties::IsEffectEdge(edge)) { |
538 Node* use = edge.from(); | 553 Node* use = edge.from(); |
(...skipping 14 matching lines...) Expand all Loading... |
553 } | 568 } |
554 } | 569 } |
555 } | 570 } |
556 } | 571 } |
557 if (FLAG_trace_turbo_escape) { | 572 if (FLAG_trace_turbo_escape) { |
558 DebugPrint(); | 573 DebugPrint(); |
559 } | 574 } |
560 } | 575 } |
561 | 576 |
562 | 577 |
563 bool EscapeObjectAnalysis::IsDanglingEffectNode(Node* node) { | 578 bool EscapeAnalysis::IsDanglingEffectNode(Node* node) { |
564 if (node->op()->EffectInputCount() == 0) return false; | 579 if (node->op()->EffectInputCount() == 0) return false; |
565 if (node->op()->EffectOutputCount() == 0) return false; | 580 if (node->op()->EffectOutputCount() == 0) return false; |
566 for (Edge edge : node->use_edges()) { | 581 for (Edge edge : node->use_edges()) { |
567 if (NodeProperties::IsEffectEdge(edge)) { | 582 if (NodeProperties::IsEffectEdge(edge)) { |
568 return false; | 583 return false; |
569 } | 584 } |
570 } | 585 } |
571 return true; | 586 return true; |
572 } | 587 } |
573 | 588 |
574 | 589 |
575 bool EscapeObjectAnalysis::Process(Node* node) { | 590 bool EscapeAnalysis::Process(Node* node) { |
576 switch (node->opcode()) { | 591 switch (node->opcode()) { |
577 case IrOpcode::kAllocate: | 592 case IrOpcode::kAllocate: |
578 ProcessAllocation(node); | 593 ProcessAllocation(node); |
579 break; | 594 break; |
580 case IrOpcode::kBeginRegion: | 595 case IrOpcode::kBeginRegion: |
581 ForwardVirtualState(node); | 596 ForwardVirtualState(node); |
582 break; | 597 break; |
583 case IrOpcode::kFinishRegion: | 598 case IrOpcode::kFinishRegion: |
584 ProcessFinishRegion(node); | 599 ProcessFinishRegion(node); |
585 break; | 600 break; |
(...skipping 12 matching lines...) Expand all Loading... |
598 default: | 613 default: |
599 if (node->op()->EffectInputCount() > 0) { | 614 if (node->op()->EffectInputCount() > 0) { |
600 ForwardVirtualState(node); | 615 ForwardVirtualState(node); |
601 } | 616 } |
602 break; | 617 break; |
603 } | 618 } |
604 return true; | 619 return true; |
605 } | 620 } |
606 | 621 |
607 | 622 |
608 bool EscapeObjectAnalysis::IsEffectBranchPoint(Node* node) { | 623 bool EscapeAnalysis::IsEffectBranchPoint(Node* node) { |
609 int count = 0; | 624 int count = 0; |
610 for (Edge edge : node->use_edges()) { | 625 for (Edge edge : node->use_edges()) { |
611 Node* use = edge.from(); | 626 Node* use = edge.from(); |
612 if (NodeProperties::IsEffectEdge(edge) && | 627 if (NodeProperties::IsEffectEdge(edge) && |
613 use->opcode() != IrOpcode::kLoadField) { | 628 use->opcode() != IrOpcode::kLoadField) { |
614 if (++count > 1) { | 629 if (++count > 1) { |
615 return true; | 630 return true; |
616 } | 631 } |
617 } | 632 } |
618 } | 633 } |
619 return false; | 634 return false; |
620 } | 635 } |
621 | 636 |
622 | 637 |
623 void EscapeObjectAnalysis::ForwardVirtualState(Node* node) { | 638 void EscapeAnalysis::ForwardVirtualState(Node* node) { |
624 DCHECK_EQ(node->op()->EffectInputCount(), 1); | 639 DCHECK_EQ(node->op()->EffectInputCount(), 1); |
625 if (node->opcode() != IrOpcode::kLoadField && IsDanglingEffectNode(node)) { | 640 if (node->opcode() != IrOpcode::kLoadField && IsDanglingEffectNode(node)) { |
626 PrintF("Dangeling effect node: #%d (%s)\n", node->id(), | 641 PrintF("Dangeling effect node: #%d (%s)\n", node->id(), |
627 node->op()->mnemonic()); | 642 node->op()->mnemonic()); |
628 DCHECK(false); | 643 DCHECK(false); |
629 } | 644 } |
630 Node* effect = NodeProperties::GetEffectInput(node); | 645 Node* effect = NodeProperties::GetEffectInput(node); |
631 // Break the cycle for effect phis. | 646 // Break the cycle for effect phis. |
632 if (effect->opcode() == IrOpcode::kEffectPhi) { | 647 if (effect->opcode() == IrOpcode::kEffectPhi) { |
633 if (virtual_states_[effect->id()] == nullptr) { | 648 if (virtual_states_[effect->id()] == nullptr) { |
(...skipping 15 matching lines...) Expand all Loading... |
649 virtual_states_[node->id()] = virtual_states_[effect->id()]; | 664 virtual_states_[node->id()] = virtual_states_[effect->id()]; |
650 if (FLAG_trace_turbo_escape) { | 665 if (FLAG_trace_turbo_escape) { |
651 PrintF("Forwarding object state %p from #%d (%s) to #%d (%s)\n", | 666 PrintF("Forwarding object state %p from #%d (%s) to #%d (%s)\n", |
652 static_cast<void*>(virtual_states_[effect->id()]), effect->id(), | 667 static_cast<void*>(virtual_states_[effect->id()]), effect->id(), |
653 effect->op()->mnemonic(), node->id(), node->op()->mnemonic()); | 668 effect->op()->mnemonic(), node->id(), node->op()->mnemonic()); |
654 } | 669 } |
655 } | 670 } |
656 } | 671 } |
657 | 672 |
658 | 673 |
659 void EscapeObjectAnalysis::ProcessStart(Node* node) { | 674 void EscapeAnalysis::ProcessStart(Node* node) { |
660 DCHECK_EQ(node->opcode(), IrOpcode::kStart); | 675 DCHECK_EQ(node->opcode(), IrOpcode::kStart); |
661 virtual_states_[node->id()] = | 676 virtual_states_[node->id()] = |
662 new (zone()) VirtualState(zone(), graph()->NodeCount()); | 677 new (zone()) VirtualState(zone(), graph()->NodeCount()); |
663 } | 678 } |
664 | 679 |
665 | 680 |
666 bool EscapeObjectAnalysis::ProcessEffectPhi(Node* node) { | 681 bool EscapeAnalysis::ProcessEffectPhi(Node* node) { |
667 DCHECK_EQ(node->opcode(), IrOpcode::kEffectPhi); | 682 DCHECK_EQ(node->opcode(), IrOpcode::kEffectPhi); |
668 // For now only support binary phis. | 683 // For now only support binary phis. |
669 DCHECK_EQ(node->op()->EffectInputCount(), 2); | 684 DCHECK_EQ(node->op()->EffectInputCount(), 2); |
670 Node* left = NodeProperties::GetEffectInput(node, 0); | 685 Node* left = NodeProperties::GetEffectInput(node, 0); |
671 Node* right = NodeProperties::GetEffectInput(node, 1); | 686 Node* right = NodeProperties::GetEffectInput(node, 1); |
672 bool changed = false; | 687 bool changed = false; |
673 | 688 |
674 VirtualState* mergeState = virtual_states_[node->id()]; | 689 VirtualState* mergeState = virtual_states_[node->id()]; |
675 if (!mergeState) { | 690 if (!mergeState) { |
676 mergeState = new (zone()) VirtualState(zone(), graph()->NodeCount()); | 691 mergeState = new (zone()) VirtualState(zone(), graph()->NodeCount()); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
709 if (FLAG_trace_turbo_escape) { | 724 if (FLAG_trace_turbo_escape) { |
710 PrintF("Merge %s the node.\n", changed ? "changed" : "did not change"); | 725 PrintF("Merge %s the node.\n", changed ? "changed" : "did not change"); |
711 } | 726 } |
712 if (changed) { | 727 if (changed) { |
713 mergeState->LastChangedAt(node); | 728 mergeState->LastChangedAt(node); |
714 } | 729 } |
715 return changed; | 730 return changed; |
716 } | 731 } |
717 | 732 |
718 | 733 |
719 void EscapeObjectAnalysis::ProcessAllocation(Node* node) { | 734 void EscapeAnalysis::ProcessAllocation(Node* node) { |
720 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); | 735 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); |
721 ForwardVirtualState(node); | 736 ForwardVirtualState(node); |
722 | 737 |
723 // Check if we have already processed this node. | 738 // Check if we have already processed this node. |
724 if (virtual_states_[node->id()]->GetVirtualObject(node)) return; | 739 if (virtual_states_[node->id()]->GetVirtualObject(node)) return; |
725 | 740 |
726 NumberMatcher size(node->InputAt(0)); | 741 NumberMatcher size(node->InputAt(0)); |
727 if (size.HasValue()) { | 742 if (size.HasValue()) { |
728 virtual_states_[node->id()]->SetVirtualObject( | 743 virtual_states_[node->id()]->SetVirtualObject( |
729 node->id(), new (zone()) VirtualObject(node->id(), zone(), | 744 node->id(), new (zone()) VirtualObject(node->id(), zone(), |
730 size.Value() / kPointerSize)); | 745 size.Value() / kPointerSize)); |
731 } else { | 746 } else { |
732 virtual_states_[node->id()]->SetVirtualObject( | 747 virtual_states_[node->id()]->SetVirtualObject( |
733 node->id(), new (zone()) VirtualObject(node->id(), zone())); | 748 node->id(), new (zone()) VirtualObject(node->id(), zone())); |
734 } | 749 } |
735 virtual_states_[node->id()]->LastChangedAt(node); | 750 virtual_states_[node->id()]->LastChangedAt(node); |
736 } | 751 } |
737 | 752 |
738 | 753 |
739 void EscapeObjectAnalysis::ProcessFinishRegion(Node* node) { | 754 void EscapeAnalysis::ProcessFinishRegion(Node* node) { |
740 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion); | 755 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion); |
741 ForwardVirtualState(node); | 756 ForwardVirtualState(node); |
742 Node* allocation = NodeProperties::GetValueInput(node, 0); | 757 Node* allocation = NodeProperties::GetValueInput(node, 0); |
743 if (allocation->opcode() == IrOpcode::kAllocate) { | 758 if (allocation->opcode() == IrOpcode::kAllocate) { |
744 VirtualState* states = virtual_states_[node->id()]; | 759 VirtualState* states = virtual_states_[node->id()]; |
745 DCHECK_NOT_NULL(states->GetVirtualObject(allocation)); | 760 DCHECK_NOT_NULL(states->GetVirtualObject(allocation)); |
746 if (!states->GetVirtualObject(node->id())) { | 761 if (!states->GetVirtualObject(node->id())) { |
747 states->SetVirtualObject(node->id(), | 762 states->SetVirtualObject(node->id(), |
748 states->GetVirtualObject(allocation)); | 763 states->GetVirtualObject(allocation)); |
749 if (FLAG_trace_turbo_escape) { | 764 if (FLAG_trace_turbo_escape) { |
750 PrintF("Linked finish region node #%d to node #%d\n", node->id(), | 765 PrintF("Linked finish region node #%d to node #%d\n", node->id(), |
751 allocation->id()); | 766 allocation->id()); |
752 } | 767 } |
753 states->LastChangedAt(node); | 768 states->LastChangedAt(node); |
754 } | 769 } |
755 } | 770 } |
756 } | 771 } |
757 | 772 |
758 | 773 |
759 Node* EscapeObjectAnalysis::GetReplacement(Node* at, NodeId id) { | 774 Node* EscapeAnalysis::GetReplacement(Node* at, NodeId id) { |
760 VirtualState* states = virtual_states_[at->id()]; | 775 VirtualState* states = virtual_states_[at->id()]; |
761 if (VirtualObject* obj = states->GetVirtualObject(id)) { | 776 if (VirtualObject* obj = states->GetVirtualObject(id)) { |
762 return obj->GetReplacement(); | 777 return obj->GetReplacement(); |
763 } | 778 } |
764 return nullptr; | 779 return nullptr; |
765 } | 780 } |
766 | 781 |
767 | 782 |
768 int EscapeObjectAnalysis::OffsetFromAccess(Node* node) { | 783 bool EscapeAnalysis::IsVirtual(Node* node) { |
| 784 return escape_status_.IsVirtual(node); |
| 785 } |
| 786 |
| 787 |
| 788 bool EscapeAnalysis::IsEscaped(Node* node) { |
| 789 return escape_status_.IsEscaped(node); |
| 790 } |
| 791 |
| 792 |
| 793 int EscapeAnalysis::OffsetFromAccess(Node* node) { |
769 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0); | 794 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0); |
770 return OpParameter<FieldAccess>(node).offset / kPointerSize; | 795 return OpParameter<FieldAccess>(node).offset / kPointerSize; |
771 } | 796 } |
772 | 797 |
773 | 798 |
774 void EscapeObjectAnalysis::ProcessLoadField(Node* node) { | 799 void EscapeAnalysis::ProcessLoadField(Node* node) { |
775 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField); | 800 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField); |
776 ForwardVirtualState(node); | 801 ForwardVirtualState(node); |
777 Node* from = NodeProperties::GetValueInput(node, 0); | 802 Node* from = NodeProperties::GetValueInput(node, 0); |
778 int offset = OffsetFromAccess(node); | 803 int offset = OffsetFromAccess(node); |
779 VirtualState* states = virtual_states_[node->id()]; | 804 VirtualState* states = virtual_states_[node->id()]; |
780 if (VirtualObject* state = states->GetVirtualObject(from)) { | 805 if (VirtualObject* state = states->GetVirtualObject(from)) { |
781 if (!state->IsTracked()) return; | 806 if (!state->IsTracked()) return; |
782 Node* value = state->GetField(offset); | 807 Node* value = state->GetField(offset); |
783 if (value) { | 808 if (value) { |
784 // Record that the load has this alias. | 809 // Record that the load has this alias. |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
826 } | 851 } |
827 } else if (FLAG_trace_turbo_escape) { | 852 } else if (FLAG_trace_turbo_escape) { |
828 PrintF(" has incomplete virtual object info: %p %p\n", | 853 PrintF(" has incomplete virtual object info: %p %p\n", |
829 static_cast<void*>(l), static_cast<void*>(r)); | 854 static_cast<void*>(l), static_cast<void*>(r)); |
830 } | 855 } |
831 } | 856 } |
832 } | 857 } |
833 } | 858 } |
834 | 859 |
835 | 860 |
836 void EscapeObjectAnalysis::ProcessStoreField(Node* node) { | 861 void EscapeAnalysis::ProcessStoreField(Node* node) { |
837 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField); | 862 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField); |
838 ForwardVirtualState(node); | 863 ForwardVirtualState(node); |
839 Node* to = NodeProperties::GetValueInput(node, 0); | 864 Node* to = NodeProperties::GetValueInput(node, 0); |
840 Node* val = NodeProperties::GetValueInput(node, 1); | 865 Node* val = NodeProperties::GetValueInput(node, 1); |
841 int offset = OffsetFromAccess(node); | 866 int offset = OffsetFromAccess(node); |
842 VirtualState* states = virtual_states_[node->id()]; | 867 VirtualState* states = virtual_states_[node->id()]; |
843 if (VirtualObject* obj = states->GetVirtualObject(to)) { | 868 if (VirtualObject* obj = states->GetVirtualObject(to)) { |
844 if (!obj->IsTracked()) return; | 869 if (!obj->IsTracked()) return; |
845 if (obj->SetField(offset, states->ResolveReplacement(val))) { | 870 if (obj->SetField(offset, states->ResolveReplacement(val))) { |
846 states->LastChangedAt(node); | 871 states->LastChangedAt(node); |
847 } | 872 } |
848 } | 873 } |
849 } | 874 } |
850 | 875 |
851 | 876 |
852 void EscapeObjectAnalysis::DebugPrint() { | 877 void EscapeAnalysis::DebugPrint() { |
853 ZoneVector<VirtualState*> object_states(zone()); | 878 ZoneVector<VirtualState*> object_states(zone()); |
854 for (NodeId id = 0; id < virtual_states_.size(); id++) { | 879 for (NodeId id = 0; id < virtual_states_.size(); id++) { |
855 if (VirtualState* states = virtual_states_[id]) { | 880 if (VirtualState* states = virtual_states_[id]) { |
856 if (std::find(object_states.begin(), object_states.end(), states) == | 881 if (std::find(object_states.begin(), object_states.end(), states) == |
857 object_states.end()) { | 882 object_states.end()) { |
858 object_states.push_back(states); | 883 object_states.push_back(states); |
859 } | 884 } |
860 } | 885 } |
861 } | 886 } |
862 for (size_t n = 0; n < object_states.size(); n++) { | 887 for (size_t n = 0; n < object_states.size(); n++) { |
(...skipping 16 matching lines...) Expand all Loading... |
879 PrintF(" Object #%zu links to object #%d\n", id, obj->id()); | 904 PrintF(" Object #%zu links to object #%d\n", id, obj->id()); |
880 } | 905 } |
881 } | 906 } |
882 } | 907 } |
883 } | 908 } |
884 } | 909 } |
885 | 910 |
886 } // namespace compiler | 911 } // namespace compiler |
887 } // namespace internal | 912 } // namespace internal |
888 } // namespace v8 | 913 } // namespace v8 |
OLD | NEW |