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 |