| 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 |