Chromium Code Reviews| 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" |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 22 namespace compiler { | 22 namespace compiler { |
| 23 | 23 |
| 24 | 24 |
| 25 // ------------------------------VirtualObject---------------------------------- | 25 // ------------------------------VirtualObject---------------------------------- |
| 26 | 26 |
| 27 | 27 |
| 28 class VirtualObject : public ZoneObject { | 28 class VirtualObject : public ZoneObject { |
| 29 public: | 29 public: |
| 30 enum Status { kUntracked = 0, kTracked = 1 }; | 30 enum Status { kUntracked = 0, kTracked = 1 }; |
| 31 VirtualObject(NodeId id, Zone* zone) | 31 VirtualObject(NodeId id, Zone* zone) |
| 32 : id_(id), status_(kUntracked), fields_(zone), replacement_(nullptr) {} | 32 : id_(id), |
| 33 status_(kUntracked), | |
| 34 fields_(zone), | |
| 35 replacement_(nullptr), | |
| 36 object_state_(nullptr) {} | |
| 33 | 37 |
| 34 VirtualObject(const VirtualObject& other) | 38 VirtualObject(const VirtualObject& other) |
| 35 : id_(other.id_), | 39 : id_(other.id_), |
| 36 status_(other.status_), | 40 status_(other.status_), |
| 37 fields_(other.fields_), | 41 fields_(other.fields_), |
| 38 replacement_(other.replacement_) {} | 42 replacement_(other.replacement_), |
| 43 object_state_(other.object_state_) {} | |
| 39 | 44 |
| 40 VirtualObject(NodeId id, Zone* zone, size_t field_number) | 45 VirtualObject(NodeId id, Zone* zone, size_t field_count) |
| 41 : id_(id), status_(kTracked), fields_(zone), replacement_(nullptr) { | 46 : id_(id), |
| 42 fields_.resize(field_number); | 47 status_(kTracked), |
| 48 fields_(zone), | |
| 49 replacement_(nullptr), | |
| 50 object_state_(nullptr) { | |
| 51 fields_.resize(field_count); | |
| 43 } | 52 } |
| 44 | 53 |
| 45 Node* GetField(size_t offset) { | 54 Node* GetField(size_t offset) { |
| 46 if (offset < fields_.size()) { | 55 if (offset < fields_.size()) { |
| 47 return fields_[offset]; | 56 return fields_[offset]; |
| 48 } | 57 } |
| 49 return nullptr; | 58 return nullptr; |
| 50 } | 59 } |
| 51 | 60 |
| 52 bool SetField(size_t offset, Node* node) { | 61 bool SetField(size_t offset, Node* node) { |
| 53 bool changed = fields_[offset] != node; | 62 bool changed = fields_[offset] != node; |
| 54 fields_[offset] = node; | 63 fields_[offset] = node; |
| 55 return changed; | 64 return changed; |
| 56 } | 65 } |
| 57 bool IsVirtual() const { return status_ == kTracked; } | 66 bool IsVirtual() const { return status_ == kTracked; } |
| 58 bool IsTracked() const { return status_ != kUntracked; } | 67 bool IsTracked() const { return status_ != kUntracked; } |
| 59 Node* GetReplacement() { return replacement_; } | 68 Node* GetReplacement() { return replacement_; } |
| 60 bool SetReplacement(Node* node) { | 69 bool SetReplacement(Node* node) { |
| 61 bool changed = replacement_ != node; | 70 bool changed = replacement_ != node; |
| 62 replacement_ = node; | 71 replacement_ = node; |
| 63 return changed; | 72 return changed; |
| 64 } | 73 } |
| 65 | 74 |
| 66 size_t fields() { return fields_.size(); } | 75 Node** fields_array() { return &fields_.front(); } |
| 67 bool ResizeFields(size_t field_number) { | 76 size_t field_count() { return fields_.size(); } |
| 68 if (field_number != fields_.size()) { | 77 bool ResizeFields(size_t field_count) { |
| 69 fields_.resize(field_number); | 78 if (field_count != fields_.size()) { |
| 79 fields_.resize(field_count); | |
| 70 return true; | 80 return true; |
| 71 } | 81 } |
| 72 return false; | 82 return false; |
| 73 } | 83 } |
| 74 | 84 void SetObjectState(Node* node) { object_state_ = node; } |
| 85 Node* GetObjectState() { return object_state_; } | |
| 75 bool UpdateFrom(const VirtualObject& other); | 86 bool UpdateFrom(const VirtualObject& other); |
| 76 | 87 |
| 77 NodeId id() { return id_; } | 88 NodeId id() { return id_; } |
| 78 void id(NodeId id) { id_ = id; } | 89 void id(NodeId id) { id_ = id; } |
| 79 | 90 |
| 80 private: | 91 private: |
| 81 NodeId id_; | 92 NodeId id_; |
| 82 Status status_; | 93 Status status_; |
| 83 ZoneVector<Node*> fields_; | 94 ZoneVector<Node*> fields_; |
| 84 Node* replacement_; | 95 Node* replacement_; |
| 96 Node* object_state_; | |
| 85 }; | 97 }; |
| 86 | 98 |
| 87 | 99 |
| 88 bool VirtualObject::UpdateFrom(const VirtualObject& other) { | 100 bool VirtualObject::UpdateFrom(const VirtualObject& other) { |
| 89 bool changed = status_ != other.status_; | 101 bool changed = status_ != other.status_; |
| 90 status_ = other.status_; | 102 status_ = other.status_; |
| 91 changed = replacement_ != other.replacement_ || changed; | 103 changed = replacement_ != other.replacement_ || changed; |
| 92 replacement_ = other.replacement_; | 104 replacement_ = other.replacement_; |
| 93 if (fields_.size() != other.fields_.size()) { | 105 if (fields_.size() != other.fields_.size()) { |
| 94 fields_ = other.fields_; | 106 fields_ = other.fields_; |
| (...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 bool changed = false; | 251 bool changed = false; |
| 240 for (NodeId id = 0; id < std::min(left->size(), right->size()); ++id) { | 252 for (NodeId id = 0; id < std::min(left->size(), right->size()); ++id) { |
| 241 VirtualObject* ls = left->GetVirtualObject(id); | 253 VirtualObject* ls = left->GetVirtualObject(id); |
| 242 VirtualObject* rs = right->GetVirtualObject(id); | 254 VirtualObject* rs = right->GetVirtualObject(id); |
| 243 | 255 |
| 244 if (ls != nullptr && rs != nullptr) { | 256 if (ls != nullptr && rs != nullptr) { |
| 245 if (FLAG_trace_turbo_escape) { | 257 if (FLAG_trace_turbo_escape) { |
| 246 PrintF(" Merging fields of #%d\n", id); | 258 PrintF(" Merging fields of #%d\n", id); |
| 247 } | 259 } |
| 248 VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject(id, zone); | 260 VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject(id, zone); |
| 249 size_t fields = std::max(ls->fields(), rs->fields()); | 261 size_t fields = std::max(ls->field_count(), rs->field_count()); |
| 250 changed = mergeObject->ResizeFields(fields) || changed; | 262 changed = mergeObject->ResizeFields(fields) || changed; |
| 251 for (size_t i = 0; i < fields; ++i) { | 263 for (size_t i = 0; i < fields; ++i) { |
| 252 if (ls->GetField(i) == rs->GetField(i)) { | 264 if (ls->GetField(i) == rs->GetField(i)) { |
| 253 changed = mergeObject->SetField(i, ls->GetField(i)) || changed; | 265 changed = mergeObject->SetField(i, ls->GetField(i)) || changed; |
| 254 if (FLAG_trace_turbo_escape && ls->GetField(i)) { | 266 if (FLAG_trace_turbo_escape && ls->GetField(i)) { |
| 255 PrintF(" Field %zu agree on rep #%d\n", i, | 267 PrintF(" Field %zu agree on rep #%d\n", i, |
| 256 ls->GetField(i)->id()); | 268 ls->GetField(i)->id()); |
| 257 } | 269 } |
| 258 } else if (ls->GetField(i) != nullptr && rs->GetField(i) != nullptr) { | 270 } else if (ls->GetField(i) != nullptr && rs->GetField(i) != nullptr) { |
| 259 Node* phi = graph->NewNode(common->Phi(kMachAnyTagged, 2), | 271 Node* phi = graph->NewNode(common->Phi(kMachAnyTagged, 2), |
| (...skipping 261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 521 | 533 |
| 522 // -----------------------------EscapeAnalysis---------------------------------- | 534 // -----------------------------EscapeAnalysis---------------------------------- |
| 523 | 535 |
| 524 | 536 |
| 525 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, | 537 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, |
| 526 Zone* zone) | 538 Zone* zone) |
| 527 : graph_(graph), | 539 : graph_(graph), |
| 528 common_(common), | 540 common_(common), |
| 529 zone_(zone), | 541 zone_(zone), |
| 530 virtual_states_(zone), | 542 virtual_states_(zone), |
| 531 escape_status_(this, graph, zone) {} | 543 escape_status_(this, graph, zone), |
| 544 effects_(zone) {} | |
| 532 | 545 |
| 533 | 546 |
| 534 EscapeAnalysis::~EscapeAnalysis() {} | 547 EscapeAnalysis::~EscapeAnalysis() {} |
| 535 | 548 |
| 536 | 549 |
| 537 void EscapeAnalysis::Run() { | 550 void EscapeAnalysis::Run() { |
| 538 RunObjectAnalysis(); | 551 RunObjectAnalysis(); |
| 539 escape_status_.Run(); | 552 escape_status_.Run(); |
| 540 } | 553 } |
| 541 | 554 |
| 542 | 555 |
| 543 void EscapeAnalysis::RunObjectAnalysis() { | 556 void EscapeAnalysis::RunObjectAnalysis() { |
| 557 effects_.resize(graph()->NodeCount()); | |
| 544 virtual_states_.resize(graph()->NodeCount()); | 558 virtual_states_.resize(graph()->NodeCount()); |
| 545 ZoneVector<Node*> queue(zone()); | 559 ZoneVector<Node*> stack(zone()); |
|
Jarin
2015/12/04 13:41:11
Nit: you can actually even say ZoneStack<...> here
| |
| 546 queue.push_back(graph()->start()); | 560 stack.push_back(graph()->start()); |
| 547 while (!queue.empty()) { | 561 while (!stack.empty()) { |
| 548 Node* node = queue.back(); | 562 Node* node = stack.back(); |
| 549 queue.pop_back(); | 563 stack.pop_back(); |
| 550 if (Process(node)) { | 564 if (Process(node)) { |
| 551 for (Edge edge : node->use_edges()) { | 565 for (Edge edge : node->use_edges()) { |
| 552 if (NodeProperties::IsEffectEdge(edge)) { | 566 if (NodeProperties::IsEffectEdge(edge)) { |
| 553 Node* use = edge.from(); | 567 Node* use = edge.from(); |
| 554 if (use->opcode() != IrOpcode::kLoadField || | 568 if (use->opcode() != IrOpcode::kLoadField || |
| 555 !IsDanglingEffectNode(use)) { | 569 !IsDanglingEffectNode(use)) { |
| 556 queue.push_back(use); | 570 stack.push_back(use); |
| 557 } | 571 } |
| 558 } | 572 } |
| 559 } | 573 } |
| 560 // First process loads: dangling loads are a problem otherwise. | 574 // First process loads: dangling loads are a problem otherwise. |
| 561 for (Edge edge : node->use_edges()) { | 575 for (Edge edge : node->use_edges()) { |
| 562 if (NodeProperties::IsEffectEdge(edge)) { | 576 if (NodeProperties::IsEffectEdge(edge)) { |
| 563 Node* use = edge.from(); | 577 Node* use = edge.from(); |
| 564 if (use->opcode() == IrOpcode::kLoadField && | 578 if (use->opcode() == IrOpcode::kLoadField && |
| 565 IsDanglingEffectNode(use)) { | 579 IsDanglingEffectNode(use)) { |
| 566 queue.push_back(use); | 580 stack.push_back(use); |
| 567 } | 581 } |
| 568 } | 582 } |
| 569 } | 583 } |
| 570 } | 584 } |
| 571 } | 585 } |
| 572 if (FLAG_trace_turbo_escape) { | 586 if (FLAG_trace_turbo_escape) { |
| 573 DebugPrint(); | 587 DebugPrint(); |
| 574 } | 588 } |
| 575 } | 589 } |
| 576 | 590 |
| 577 | 591 |
| 578 bool EscapeAnalysis::IsDanglingEffectNode(Node* node) { | 592 bool EscapeAnalysis::IsDanglingEffectNode(Node* node) { |
| 579 if (node->op()->EffectInputCount() == 0) return false; | 593 if (node->op()->EffectInputCount() == 0) return false; |
| 580 if (node->op()->EffectOutputCount() == 0) return false; | 594 if (node->op()->EffectOutputCount() == 0) return false; |
| 581 for (Edge edge : node->use_edges()) { | 595 for (Edge edge : node->use_edges()) { |
| 582 if (NodeProperties::IsEffectEdge(edge)) { | 596 if (NodeProperties::IsEffectEdge(edge)) { |
| 583 return false; | 597 return false; |
| 584 } | 598 } |
| 585 } | 599 } |
| 586 return true; | 600 return true; |
| 587 } | 601 } |
| 588 | 602 |
| 589 | 603 |
| 604 void EscapeAnalysis::RecordEffectForFrameStateUses(Node* node, Node* effect) { | |
| 605 DCHECK(effect->op()->EffectInputCount() > 0); | |
| 606 ZoneVector<Node*> stack(zone()); | |
| 607 stack.push_back(node); | |
| 608 while (!stack.empty()) { | |
| 609 Node* cur = stack.back(); | |
| 610 stack.pop_back(); | |
| 611 for (Edge edge : cur->input_edges()) { | |
| 612 Node* input = edge.to(); | |
| 613 if (input->opcode() == IrOpcode::kFrameState || | |
| 614 input->opcode() == IrOpcode::kStateValues) { | |
| 615 if (effects_[input->id()] != effect) { | |
| 616 effects_[input->id()] = effect; | |
| 617 if (FLAG_trace_turbo_escape) { | |
| 618 PrintF("Recorded effect #%d (%s) for frame state %d\n", | |
| 619 effect->id(), effect->op()->mnemonic(), input->id()); | |
| 620 } | |
| 621 } | |
| 622 // Climb up the chain. | |
| 623 stack.push_back(input); | |
| 624 } | |
| 625 } | |
| 626 } | |
| 627 } | |
| 628 | |
| 629 | |
| 590 bool EscapeAnalysis::Process(Node* node) { | 630 bool EscapeAnalysis::Process(Node* node) { |
| 591 switch (node->opcode()) { | 631 switch (node->opcode()) { |
| 592 case IrOpcode::kAllocate: | 632 case IrOpcode::kAllocate: |
| 593 ProcessAllocation(node); | 633 ProcessAllocation(node); |
| 594 break; | 634 break; |
| 595 case IrOpcode::kBeginRegion: | 635 case IrOpcode::kBeginRegion: |
| 596 ForwardVirtualState(node); | 636 ForwardVirtualState(node); |
| 597 break; | 637 break; |
| 598 case IrOpcode::kFinishRegion: | 638 case IrOpcode::kFinishRegion: |
| 599 ProcessFinishRegion(node); | 639 ProcessFinishRegion(node); |
| 600 break; | 640 break; |
| 601 case IrOpcode::kStoreField: | 641 case IrOpcode::kStoreField: |
| 602 ProcessStoreField(node); | 642 ProcessStoreField(node); |
| 603 break; | 643 break; |
| 604 case IrOpcode::kLoadField: | 644 case IrOpcode::kLoadField: |
| 605 ProcessLoadField(node); | 645 ProcessLoadField(node); |
| 606 break; | 646 break; |
| 607 case IrOpcode::kStart: | 647 case IrOpcode::kStart: |
| 608 ProcessStart(node); | 648 ProcessStart(node); |
| 609 break; | 649 break; |
| 610 case IrOpcode::kEffectPhi: | 650 case IrOpcode::kEffectPhi: |
| 611 return ProcessEffectPhi(node); | 651 return ProcessEffectPhi(node); |
| 612 break; | 652 break; |
| 613 default: | 653 default: |
| 614 if (node->op()->EffectInputCount() > 0) { | 654 if (node->op()->EffectInputCount() > 0) { |
| 615 ForwardVirtualState(node); | 655 ForwardVirtualState(node); |
| 656 RecordEffectForFrameStateUses(node, node); | |
| 616 } | 657 } |
| 617 break; | 658 break; |
| 618 } | 659 } |
| 619 return true; | 660 return true; |
| 620 } | 661 } |
| 621 | 662 |
| 622 | 663 |
| 623 bool EscapeAnalysis::IsEffectBranchPoint(Node* node) { | 664 bool EscapeAnalysis::IsEffectBranchPoint(Node* node) { |
| 624 int count = 0; | 665 int count = 0; |
| 625 for (Edge edge : node->use_edges()) { | 666 for (Edge edge : node->use_edges()) { |
| 626 Node* use = edge.from(); | 667 Node* use = edge.from(); |
| 627 if (NodeProperties::IsEffectEdge(edge) && | 668 if (NodeProperties::IsEffectEdge(edge) && |
| 628 use->opcode() != IrOpcode::kLoadField) { | 669 use->opcode() != IrOpcode::kLoadField) { |
| 629 if (++count > 1) { | 670 if (++count > 1) { |
| 630 return true; | 671 return true; |
| 631 } | 672 } |
| 632 } | 673 } |
| 633 } | 674 } |
| 634 return false; | 675 return false; |
| 635 } | 676 } |
| 636 | 677 |
| 637 | 678 |
| 638 void EscapeAnalysis::ForwardVirtualState(Node* node) { | 679 void EscapeAnalysis::ForwardVirtualState(Node* node) { |
| 639 DCHECK_EQ(node->op()->EffectInputCount(), 1); | 680 DCHECK_EQ(node->op()->EffectInputCount(), 1); |
| 640 if (node->opcode() != IrOpcode::kLoadField && IsDanglingEffectNode(node)) { | 681 if (node->opcode() != IrOpcode::kLoadField && |
| 682 node->opcode() != IrOpcode::kLoad && IsDanglingEffectNode(node)) { | |
| 641 PrintF("Dangeling effect node: #%d (%s)\n", node->id(), | 683 PrintF("Dangeling effect node: #%d (%s)\n", node->id(), |
| 642 node->op()->mnemonic()); | 684 node->op()->mnemonic()); |
| 643 DCHECK(false); | 685 DCHECK(false); |
| 644 } | 686 } |
| 645 Node* effect = NodeProperties::GetEffectInput(node); | 687 Node* effect = NodeProperties::GetEffectInput(node); |
| 646 // Break the cycle for effect phis. | 688 // Break the cycle for effect phis. |
| 647 if (effect->opcode() == IrOpcode::kEffectPhi) { | 689 if (effect->opcode() == IrOpcode::kEffectPhi) { |
| 648 if (virtual_states_[effect->id()] == nullptr) { | 690 if (virtual_states_[effect->id()] == nullptr) { |
| 649 virtual_states_[effect->id()] = | 691 virtual_states_[effect->id()] = |
| 650 new (zone()) VirtualState(zone(), graph()->NodeCount()); | 692 new (zone()) VirtualState(zone(), graph()->NodeCount()); |
| (...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 783 bool EscapeAnalysis::IsVirtual(Node* node) { | 825 bool EscapeAnalysis::IsVirtual(Node* node) { |
| 784 return escape_status_.IsVirtual(node); | 826 return escape_status_.IsVirtual(node); |
| 785 } | 827 } |
| 786 | 828 |
| 787 | 829 |
| 788 bool EscapeAnalysis::IsEscaped(Node* node) { | 830 bool EscapeAnalysis::IsEscaped(Node* node) { |
| 789 return escape_status_.IsEscaped(node); | 831 return escape_status_.IsEscaped(node); |
| 790 } | 832 } |
| 791 | 833 |
| 792 | 834 |
| 835 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) { | |
| 836 if (VirtualState* states = virtual_states_[at->id()]) { | |
| 837 return states->GetVirtualObject(id); | |
| 838 } | |
| 839 return nullptr; | |
| 840 } | |
| 841 | |
| 842 | |
| 843 Node* EscapeAnalysis::GetEffect(Node* node) { return effects_[node->id()]; } | |
| 844 | |
| 845 | |
| 793 int EscapeAnalysis::OffsetFromAccess(Node* node) { | 846 int EscapeAnalysis::OffsetFromAccess(Node* node) { |
| 794 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0); | 847 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0); |
| 795 return OpParameter<FieldAccess>(node).offset / kPointerSize; | 848 return OpParameter<FieldAccess>(node).offset / kPointerSize; |
| 796 } | 849 } |
| 797 | 850 |
| 798 | 851 |
| 799 void EscapeAnalysis::ProcessLoadField(Node* node) { | 852 void EscapeAnalysis::ProcessLoadField(Node* node) { |
| 800 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField); | 853 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField); |
| 801 ForwardVirtualState(node); | 854 ForwardVirtualState(node); |
| 802 Node* from = NodeProperties::GetValueInput(node, 0); | 855 Node* from = NodeProperties::GetValueInput(node, 0); |
| 803 int offset = OffsetFromAccess(node); | |
| 804 VirtualState* states = virtual_states_[node->id()]; | 856 VirtualState* states = virtual_states_[node->id()]; |
| 805 if (VirtualObject* state = states->GetVirtualObject(from)) { | 857 if (VirtualObject* state = states->GetVirtualObject(from)) { |
| 858 int offset = OffsetFromAccess(node); | |
| 806 if (!state->IsTracked()) return; | 859 if (!state->IsTracked()) return; |
| 807 Node* value = state->GetField(offset); | 860 Node* value = state->GetField(offset); |
| 808 if (value) { | 861 if (value) { |
| 809 // Record that the load has this alias. | 862 // Record that the load has this alias. |
| 810 states->UpdateReplacement(node, value, zone()); | 863 states->UpdateReplacement(node, value, zone()); |
| 811 } else if (FLAG_trace_turbo_escape) { | 864 } else if (FLAG_trace_turbo_escape) { |
| 812 PrintF("No field %d on record for #%d\n", offset, from->id()); | 865 PrintF("No field %d on record for #%d\n", offset, from->id()); |
| 813 } | 866 } |
| 814 } else { | 867 } else { |
| 815 if (from->opcode() == IrOpcode::kPhi) { | 868 if (from->opcode() == IrOpcode::kPhi) { |
| 869 int offset = OffsetFromAccess(node); | |
| 816 // Only binary phis are supported for now. | 870 // Only binary phis are supported for now. |
| 817 CHECK_EQ(from->op()->ValueInputCount(), 2); | 871 CHECK_EQ(from->op()->ValueInputCount(), 2); |
| 818 if (FLAG_trace_turbo_escape) { | 872 if (FLAG_trace_turbo_escape) { |
| 819 PrintF("Load #%d from phi #%d", node->id(), from->id()); | 873 PrintF("Load #%d from phi #%d", node->id(), from->id()); |
| 820 } | 874 } |
| 821 Node* left = NodeProperties::GetValueInput(from, 0); | 875 Node* left = NodeProperties::GetValueInput(from, 0); |
| 822 Node* right = NodeProperties::GetValueInput(from, 1); | 876 Node* right = NodeProperties::GetValueInput(from, 1); |
| 823 VirtualObject* l = states->GetVirtualObject(left); | 877 VirtualObject* l = states->GetVirtualObject(left); |
| 824 VirtualObject* r = states->GetVirtualObject(right); | 878 VirtualObject* r = states->GetVirtualObject(right); |
| 825 if (l && r) { | 879 if (l && r) { |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 867 VirtualState* states = virtual_states_[node->id()]; | 921 VirtualState* states = virtual_states_[node->id()]; |
| 868 if (VirtualObject* obj = states->GetVirtualObject(to)) { | 922 if (VirtualObject* obj = states->GetVirtualObject(to)) { |
| 869 if (!obj->IsTracked()) return; | 923 if (!obj->IsTracked()) return; |
| 870 if (obj->SetField(offset, states->ResolveReplacement(val))) { | 924 if (obj->SetField(offset, states->ResolveReplacement(val))) { |
| 871 states->LastChangedAt(node); | 925 states->LastChangedAt(node); |
| 872 } | 926 } |
| 873 } | 927 } |
| 874 } | 928 } |
| 875 | 929 |
| 876 | 930 |
| 931 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) { | |
| 932 if ((node->opcode() == IrOpcode::kFinishRegion || | |
| 933 node->opcode() == IrOpcode::kAllocate) && | |
| 934 IsVirtual(node)) { | |
| 935 if (VirtualObject* vobj = GetVirtualObject(effect, node->id())) { | |
| 936 if (Node* object_state = vobj->GetObjectState()) { | |
| 937 return object_state; | |
| 938 } else { | |
| 939 Node* new_object_state = graph()->NewNode( | |
| 940 common()->ObjectState(static_cast<int>(vobj->field_count()), | |
| 941 vobj->id()), | |
| 942 static_cast<int>(vobj->field_count()), vobj->fields_array()); | |
| 943 vobj->SetObjectState(new_object_state); | |
| 944 // Now fix uses of other objects. | |
| 945 for (size_t i = 0; i < vobj->field_count(); ++i) { | |
| 946 if (Node* field = vobj->GetField(i)) { | |
| 947 if (Node* field_object_state = | |
| 948 GetOrCreateObjectState(effect, field)) { | |
| 949 NodeProperties::ReplaceValueInput( | |
| 950 new_object_state, field_object_state, static_cast<int>(i)); | |
| 951 } | |
| 952 } | |
| 953 } | |
| 954 return new_object_state; | |
| 955 } | |
| 956 } | |
| 957 } | |
| 958 return nullptr; | |
| 959 } | |
| 960 | |
| 961 | |
| 877 void EscapeAnalysis::DebugPrint() { | 962 void EscapeAnalysis::DebugPrint() { |
| 878 ZoneVector<VirtualState*> object_states(zone()); | 963 ZoneVector<VirtualState*> object_states(zone()); |
| 879 for (NodeId id = 0; id < virtual_states_.size(); id++) { | 964 for (NodeId id = 0; id < virtual_states_.size(); id++) { |
| 880 if (VirtualState* states = virtual_states_[id]) { | 965 if (VirtualState* states = virtual_states_[id]) { |
| 881 if (std::find(object_states.begin(), object_states.end(), states) == | 966 if (std::find(object_states.begin(), object_states.end(), states) == |
| 882 object_states.end()) { | 967 object_states.end()) { |
| 883 object_states.push_back(states); | 968 object_states.push_back(states); |
| 884 } | 969 } |
| 885 } | 970 } |
| 886 } | 971 } |
| 887 for (size_t n = 0; n < object_states.size(); n++) { | 972 for (size_t n = 0; n < object_states.size(); n++) { |
| 888 PrintF("Dumping object state %p\n", static_cast<void*>(object_states[n])); | 973 PrintF("Dumping object state %p\n", static_cast<void*>(object_states[n])); |
| 889 for (size_t id = 0; id < object_states[n]->size(); id++) { | 974 for (size_t id = 0; id < object_states[n]->size(); id++) { |
| 890 if (VirtualObject* obj = object_states[n]->GetVirtualObject(id)) { | 975 if (VirtualObject* obj = object_states[n]->GetVirtualObject(id)) { |
| 891 if (obj->id() == id) { | 976 if (obj->id() == id) { |
| 892 PrintF(" Object #%zu with %zu fields", id, obj->fields()); | 977 PrintF(" Object #%zu with %zu fields", id, obj->field_count()); |
| 893 if (Node* rep = obj->GetReplacement()) { | 978 if (Node* rep = obj->GetReplacement()) { |
| 894 PrintF(", rep = #%d (%s)", rep->id(), rep->op()->mnemonic()); | 979 PrintF(", rep = #%d (%s)", rep->id(), rep->op()->mnemonic()); |
| 895 } | 980 } |
| 896 PrintF("\n"); | 981 PrintF("\n"); |
| 897 for (size_t i = 0; i < obj->fields(); ++i) { | 982 for (size_t i = 0; i < obj->field_count(); ++i) { |
| 898 if (Node* f = obj->GetField(i)) { | 983 if (Node* f = obj->GetField(i)) { |
| 899 PrintF(" Field %zu = #%d (%s)\n", i, f->id(), | 984 PrintF(" Field %zu = #%d (%s)\n", i, f->id(), |
| 900 f->op()->mnemonic()); | 985 f->op()->mnemonic()); |
| 901 } | 986 } |
| 902 } | 987 } |
| 903 } else { | 988 } else { |
| 904 PrintF(" Object #%zu links to object #%d\n", id, obj->id()); | 989 PrintF(" Object #%zu links to object #%d\n", id, obj->id()); |
| 905 } | 990 } |
| 906 } | 991 } |
| 907 } | 992 } |
| 908 } | 993 } |
| 909 } | 994 } |
| 910 | 995 |
| 911 } // namespace compiler | 996 } // namespace compiler |
| 912 } // namespace internal | 997 } // namespace internal |
| 913 } // namespace v8 | 998 } // namespace v8 |
| OLD | NEW |