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 <limits> | 7 #include <limits> |
8 | 8 |
9 #include "src/base/flags.h" | 9 #include "src/base/flags.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
11 #include "src/compilation-dependencies.h" | 11 #include "src/compilation-dependencies.h" |
12 #include "src/compiler/common-operator.h" | 12 #include "src/compiler/common-operator.h" |
13 #include "src/compiler/graph-reducer.h" | 13 #include "src/compiler/graph-reducer.h" |
14 #include "src/compiler/js-operator.h" | 14 #include "src/compiler/js-operator.h" |
15 #include "src/compiler/node.h" | 15 #include "src/compiler/node.h" |
16 #include "src/compiler/node-matchers.h" | 16 #include "src/compiler/node-matchers.h" |
17 #include "src/compiler/node-properties.h" | 17 #include "src/compiler/node-properties.h" |
18 #include "src/compiler/operator-properties.h" | 18 #include "src/compiler/operator-properties.h" |
19 #include "src/compiler/simplified-operator.h" | 19 #include "src/compiler/simplified-operator.h" |
20 #include "src/objects-inl.h" | 20 #include "src/objects-inl.h" |
21 #include "src/type-cache.h" | 21 #include "src/type-cache.h" |
22 | 22 |
23 namespace v8 { | 23 namespace v8 { |
24 namespace internal { | 24 namespace internal { |
25 namespace compiler { | 25 namespace compiler { |
26 | 26 |
27 using Alias = EscapeStatusAnalysis::Alias; | 27 using Alias = EscapeAnalysis::Alias; |
28 | 28 |
29 #ifdef DEBUG | 29 #ifdef DEBUG |
30 #define TRACE(...) \ | 30 #define TRACE(...) \ |
31 do { \ | 31 do { \ |
32 if (FLAG_trace_turbo_escape) PrintF(__VA_ARGS__); \ | 32 if (FLAG_trace_turbo_escape) PrintF(__VA_ARGS__); \ |
33 } while (false) | 33 } while (false) |
34 #else | 34 #else |
35 #define TRACE(...) | 35 #define TRACE(...) |
36 #endif | 36 #endif |
37 | 37 |
| 38 // EscapeStatusAnalysis determines for each allocation whether it escapes. |
| 39 class EscapeStatusAnalysis : public ZoneObject { |
| 40 public: |
| 41 enum Status { |
| 42 kUnknown = 0u, |
| 43 kTracked = 1u << 0, |
| 44 kEscaped = 1u << 1, |
| 45 kOnStack = 1u << 2, |
| 46 kVisited = 1u << 3, |
| 47 // A node is dangling, if it is a load of some kind, and does not have |
| 48 // an effect successor. |
| 49 kDanglingComputed = 1u << 4, |
| 50 kDangling = 1u << 5, |
| 51 // A node is is an effect branch point, if it has more than 2 non-dangling |
| 52 // effect successors. |
| 53 kBranchPointComputed = 1u << 6, |
| 54 kBranchPoint = 1u << 7, |
| 55 kInQueue = 1u << 8 |
| 56 }; |
| 57 typedef base::Flags<Status, uint16_t> StatusFlags; |
| 58 |
| 59 void RunStatusAnalysis(); |
| 60 |
| 61 bool IsVirtual(Node* node); |
| 62 bool IsEscaped(Node* node); |
| 63 bool IsAllocation(Node* node); |
| 64 |
| 65 bool IsInQueue(NodeId id); |
| 66 void SetInQueue(NodeId id, bool on_stack); |
| 67 |
| 68 void DebugPrint(); |
| 69 |
| 70 EscapeStatusAnalysis(EscapeAnalysis* object_analysis, Graph* graph, |
| 71 Zone* zone); |
| 72 void EnqueueForStatusAnalysis(Node* node); |
| 73 bool SetEscaped(Node* node); |
| 74 bool IsEffectBranchPoint(Node* node); |
| 75 bool IsDanglingEffectNode(Node* node); |
| 76 void ResizeStatusVector(); |
| 77 size_t GetStatusVectorSize(); |
| 78 bool IsVirtual(NodeId id); |
| 79 |
| 80 Graph* graph() const { return graph_; } |
| 81 void AssignAliases(); |
| 82 Alias GetAlias(NodeId id) const { return aliases_[id]; } |
| 83 const ZoneVector<Alias>& GetAliasMap() const { return aliases_; } |
| 84 Alias AliasCount() const { return next_free_alias_; } |
| 85 static const Alias kNotReachable; |
| 86 static const Alias kUntrackable; |
| 87 |
| 88 bool IsNotReachable(Node* node); |
| 89 |
| 90 private: |
| 91 void Process(Node* node); |
| 92 void ProcessAllocate(Node* node); |
| 93 void ProcessFinishRegion(Node* node); |
| 94 void ProcessStoreField(Node* node); |
| 95 void ProcessStoreElement(Node* node); |
| 96 bool CheckUsesForEscape(Node* node, bool phi_escaping = false) { |
| 97 return CheckUsesForEscape(node, node, phi_escaping); |
| 98 } |
| 99 bool CheckUsesForEscape(Node* node, Node* rep, bool phi_escaping = false); |
| 100 void RevisitUses(Node* node); |
| 101 void RevisitInputs(Node* node); |
| 102 |
| 103 Alias NextAlias() { return next_free_alias_++; } |
| 104 |
| 105 bool HasEntry(Node* node); |
| 106 |
| 107 bool IsAllocationPhi(Node* node); |
| 108 |
| 109 ZoneVector<Node*> stack_; |
| 110 EscapeAnalysis* object_analysis_; |
| 111 Graph* const graph_; |
| 112 ZoneVector<StatusFlags> status_; |
| 113 Alias next_free_alias_; |
| 114 ZoneVector<Node*> status_stack_; |
| 115 ZoneVector<Alias> aliases_; |
| 116 |
| 117 DISALLOW_COPY_AND_ASSIGN(EscapeStatusAnalysis); |
| 118 }; |
| 119 |
| 120 DEFINE_OPERATORS_FOR_FLAGS(EscapeStatusAnalysis::StatusFlags) |
| 121 |
38 const Alias EscapeStatusAnalysis::kNotReachable = | 122 const Alias EscapeStatusAnalysis::kNotReachable = |
39 std::numeric_limits<Alias>::max(); | 123 std::numeric_limits<Alias>::max(); |
40 const Alias EscapeStatusAnalysis::kUntrackable = | 124 const Alias EscapeStatusAnalysis::kUntrackable = |
41 std::numeric_limits<Alias>::max() - 1; | 125 std::numeric_limits<Alias>::max() - 1; |
42 | 126 |
43 class VirtualObject : public ZoneObject { | 127 class VirtualObject : public ZoneObject { |
44 public: | 128 public: |
45 enum Status { | 129 enum Status { |
46 kInitial = 0, | 130 kInitial = 0, |
47 kTracked = 1u << 0, | 131 kTracked = 1u << 0, |
(...skipping 420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 } | 552 } |
469 } | 553 } |
470 return changed; | 554 return changed; |
471 } | 555 } |
472 | 556 |
473 EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis, | 557 EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis, |
474 Graph* graph, Zone* zone) | 558 Graph* graph, Zone* zone) |
475 : stack_(zone), | 559 : stack_(zone), |
476 object_analysis_(object_analysis), | 560 object_analysis_(object_analysis), |
477 graph_(graph), | 561 graph_(graph), |
478 zone_(zone), | |
479 status_(zone), | 562 status_(zone), |
480 next_free_alias_(0), | 563 next_free_alias_(0), |
481 status_stack_(zone), | 564 status_stack_(zone), |
482 aliases_(zone) {} | 565 aliases_(zone) {} |
483 | 566 |
484 EscapeStatusAnalysis::~EscapeStatusAnalysis() {} | |
485 | |
486 bool EscapeStatusAnalysis::HasEntry(Node* node) { | 567 bool EscapeStatusAnalysis::HasEntry(Node* node) { |
487 return status_[node->id()] & (kTracked | kEscaped); | 568 return status_[node->id()] & (kTracked | kEscaped); |
488 } | 569 } |
489 | 570 |
490 bool EscapeStatusAnalysis::IsVirtual(Node* node) { | 571 bool EscapeStatusAnalysis::IsVirtual(Node* node) { |
491 return IsVirtual(node->id()); | 572 return IsVirtual(node->id()); |
492 } | 573 } |
493 | 574 |
494 bool EscapeStatusAnalysis::IsVirtual(NodeId id) { | 575 bool EscapeStatusAnalysis::IsVirtual(NodeId id) { |
495 return (status_[id] & kTracked) && !(status_[id] & kEscaped); | 576 return (status_[id] & kTracked) && !(status_[id] & kEscaped); |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
754 for (NodeId id = 0; id < status_.size(); id++) { | 835 for (NodeId id = 0; id < status_.size(); id++) { |
755 if (status_[id] & kTracked) { | 836 if (status_[id] & kTracked) { |
756 PrintF("Node #%d is %s\n", id, | 837 PrintF("Node #%d is %s\n", id, |
757 (status_[id] & kEscaped) ? "escaping" : "virtual"); | 838 (status_[id] & kEscaped) ? "escaping" : "virtual"); |
758 } | 839 } |
759 } | 840 } |
760 } | 841 } |
761 | 842 |
762 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, | 843 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, |
763 Zone* zone) | 844 Zone* zone) |
764 : status_analysis_(this, graph, zone), | 845 : zone_(zone), |
765 common_(common), | 846 common_(common), |
| 847 status_analysis_(new (zone) EscapeStatusAnalysis(this, graph, zone)), |
766 virtual_states_(zone), | 848 virtual_states_(zone), |
767 replacements_(zone), | 849 replacements_(zone), |
768 cache_(nullptr) {} | 850 cache_(nullptr) {} |
769 | 851 |
770 EscapeAnalysis::~EscapeAnalysis() {} | 852 EscapeAnalysis::~EscapeAnalysis() {} |
771 | 853 |
772 void EscapeAnalysis::Run() { | 854 void EscapeAnalysis::Run() { |
773 replacements_.resize(graph()->NodeCount()); | 855 replacements_.resize(graph()->NodeCount()); |
774 status_analysis_.AssignAliases(); | 856 status_analysis_->AssignAliases(); |
775 if (status_analysis_.AliasCount() > 0) { | 857 if (status_analysis_->AliasCount() > 0) { |
776 cache_ = new (zone()) MergeCache(zone()); | 858 cache_ = new (zone()) MergeCache(zone()); |
777 replacements_.resize(graph()->NodeCount()); | 859 replacements_.resize(graph()->NodeCount()); |
778 status_analysis_.ResizeStatusVector(); | 860 status_analysis_->ResizeStatusVector(); |
779 RunObjectAnalysis(); | 861 RunObjectAnalysis(); |
780 status_analysis_.RunStatusAnalysis(); | 862 status_analysis_->RunStatusAnalysis(); |
781 } | 863 } |
782 } | 864 } |
783 | 865 |
784 void EscapeStatusAnalysis::AssignAliases() { | 866 void EscapeStatusAnalysis::AssignAliases() { |
785 size_t max_size = 1024; | 867 size_t max_size = 1024; |
786 size_t min_size = 32; | 868 size_t min_size = 32; |
787 size_t stack_size = | 869 size_t stack_size = |
788 std::min(std::max(graph()->NodeCount() / 5, min_size), max_size); | 870 std::min(std::max(graph()->NodeCount() / 5, min_size), max_size); |
789 stack_.reserve(stack_size); | 871 stack_.reserve(stack_size); |
790 ResizeStatusVector(); | 872 ResizeStatusVector(); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
848 } | 930 } |
849 | 931 |
850 void EscapeAnalysis::RunObjectAnalysis() { | 932 void EscapeAnalysis::RunObjectAnalysis() { |
851 virtual_states_.resize(graph()->NodeCount()); | 933 virtual_states_.resize(graph()->NodeCount()); |
852 ZoneDeque<Node*> queue(zone()); | 934 ZoneDeque<Node*> queue(zone()); |
853 queue.push_back(graph()->start()); | 935 queue.push_back(graph()->start()); |
854 ZoneVector<Node*> danglers(zone()); | 936 ZoneVector<Node*> danglers(zone()); |
855 while (!queue.empty()) { | 937 while (!queue.empty()) { |
856 Node* node = queue.back(); | 938 Node* node = queue.back(); |
857 queue.pop_back(); | 939 queue.pop_back(); |
858 status_analysis_.SetInQueue(node->id(), false); | 940 status_analysis_->SetInQueue(node->id(), false); |
859 if (Process(node)) { | 941 if (Process(node)) { |
860 for (Edge edge : node->use_edges()) { | 942 for (Edge edge : node->use_edges()) { |
861 Node* use = edge.from(); | 943 Node* use = edge.from(); |
862 if (IsNotReachable(use)) { | 944 if (status_analysis_->IsNotReachable(use)) { |
863 continue; | 945 continue; |
864 } | 946 } |
865 if (NodeProperties::IsEffectEdge(edge)) { | 947 if (NodeProperties::IsEffectEdge(edge)) { |
866 // Iteration order: depth first, but delay phis. | 948 // Iteration order: depth first, but delay phis. |
867 // We need DFS do avoid some duplication of VirtualStates and | 949 // We need DFS do avoid some duplication of VirtualStates and |
868 // VirtualObjects, and we want to delay phis to improve performance. | 950 // VirtualObjects, and we want to delay phis to improve performance. |
869 if (use->opcode() == IrOpcode::kEffectPhi) { | 951 if (use->opcode() == IrOpcode::kEffectPhi) { |
870 if (!status_analysis_.IsInQueue(use->id())) { | 952 if (!status_analysis_->IsInQueue(use->id())) { |
871 queue.push_front(use); | 953 queue.push_front(use); |
872 } | 954 } |
873 } else if ((use->opcode() != IrOpcode::kLoadField && | 955 } else if ((use->opcode() != IrOpcode::kLoadField && |
874 use->opcode() != IrOpcode::kLoadElement) || | 956 use->opcode() != IrOpcode::kLoadElement) || |
875 !IsDanglingEffectNode(use)) { | 957 !status_analysis_->IsDanglingEffectNode(use)) { |
876 if (!status_analysis_.IsInQueue(use->id())) { | 958 if (!status_analysis_->IsInQueue(use->id())) { |
877 status_analysis_.SetInQueue(use->id(), true); | 959 status_analysis_->SetInQueue(use->id(), true); |
878 queue.push_back(use); | 960 queue.push_back(use); |
879 } | 961 } |
880 } else { | 962 } else { |
881 danglers.push_back(use); | 963 danglers.push_back(use); |
882 } | 964 } |
883 } | 965 } |
884 } | 966 } |
885 // Danglers need to be processed immediately, even if they are | 967 // Danglers need to be processed immediately, even if they are |
886 // on the stack. Since they do not have effect outputs, | 968 // on the stack. Since they do not have effect outputs, |
887 // we don't have to track whether they are on the stack. | 969 // we don't have to track whether they are on the stack. |
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1040 return state->Copy(obj, GetAlias(obj->id())); | 1122 return state->Copy(obj, GetAlias(obj->id())); |
1041 } | 1123 } |
1042 return obj; | 1124 return obj; |
1043 } | 1125 } |
1044 | 1126 |
1045 void EscapeAnalysis::ForwardVirtualState(Node* node) { | 1127 void EscapeAnalysis::ForwardVirtualState(Node* node) { |
1046 DCHECK_EQ(node->op()->EffectInputCount(), 1); | 1128 DCHECK_EQ(node->op()->EffectInputCount(), 1); |
1047 #ifdef DEBUG | 1129 #ifdef DEBUG |
1048 if (node->opcode() != IrOpcode::kLoadField && | 1130 if (node->opcode() != IrOpcode::kLoadField && |
1049 node->opcode() != IrOpcode::kLoadElement && | 1131 node->opcode() != IrOpcode::kLoadElement && |
1050 node->opcode() != IrOpcode::kLoad && IsDanglingEffectNode(node)) { | 1132 node->opcode() != IrOpcode::kLoad && |
| 1133 status_analysis_->IsDanglingEffectNode(node)) { |
1051 PrintF("Dangeling effect node: #%d (%s)\n", node->id(), | 1134 PrintF("Dangeling effect node: #%d (%s)\n", node->id(), |
1052 node->op()->mnemonic()); | 1135 node->op()->mnemonic()); |
1053 UNREACHABLE(); | 1136 UNREACHABLE(); |
1054 } | 1137 } |
1055 #endif // DEBUG | 1138 #endif // DEBUG |
1056 Node* effect = NodeProperties::GetEffectInput(node); | 1139 Node* effect = NodeProperties::GetEffectInput(node); |
1057 DCHECK_NOT_NULL(virtual_states_[effect->id()]); | 1140 DCHECK_NOT_NULL(virtual_states_[effect->id()]); |
1058 if (virtual_states_[node->id()]) { | 1141 if (virtual_states_[node->id()]) { |
1059 virtual_states_[node->id()]->UpdateFrom(virtual_states_[effect->id()], | 1142 virtual_states_[node->id()]->UpdateFrom(virtual_states_[effect->id()], |
1060 zone()); | 1143 zone()); |
1061 } else { | 1144 } else { |
1062 virtual_states_[node->id()] = virtual_states_[effect->id()]; | 1145 virtual_states_[node->id()] = virtual_states_[effect->id()]; |
1063 TRACE("Forwarding object state %p from %s#%d to %s#%d", | 1146 TRACE("Forwarding object state %p from %s#%d to %s#%d", |
1064 static_cast<void*>(virtual_states_[effect->id()]), | 1147 static_cast<void*>(virtual_states_[effect->id()]), |
1065 effect->op()->mnemonic(), effect->id(), node->op()->mnemonic(), | 1148 effect->op()->mnemonic(), effect->id(), node->op()->mnemonic(), |
1066 node->id()); | 1149 node->id()); |
1067 if (IsEffectBranchPoint(effect) || | 1150 if (status_analysis_->IsEffectBranchPoint(effect) || |
1068 OperatorProperties::GetFrameStateInputCount(node->op()) > 0) { | 1151 OperatorProperties::GetFrameStateInputCount(node->op()) > 0) { |
1069 virtual_states_[node->id()]->SetCopyRequired(); | 1152 virtual_states_[node->id()]->SetCopyRequired(); |
1070 TRACE(", effect input %s#%d is branch point", effect->op()->mnemonic(), | 1153 TRACE(", effect input %s#%d is branch point", effect->op()->mnemonic(), |
1071 effect->id()); | 1154 effect->id()); |
1072 } | 1155 } |
1073 TRACE("\n"); | 1156 TRACE("\n"); |
1074 } | 1157 } |
1075 } | 1158 } |
1076 | 1159 |
1077 void EscapeAnalysis::ProcessStart(Node* node) { | 1160 void EscapeAnalysis::ProcessStart(Node* node) { |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1117 if (cache_->states().size() == 0) { | 1200 if (cache_->states().size() == 0) { |
1118 return changed; | 1201 return changed; |
1119 } | 1202 } |
1120 | 1203 |
1121 changed = | 1204 changed = |
1122 mergeState->MergeFrom(cache_, zone(), graph(), common(), node) || changed; | 1205 mergeState->MergeFrom(cache_, zone(), graph(), common(), node) || changed; |
1123 | 1206 |
1124 TRACE("Merge %s the node.\n", changed ? "changed" : "did not change"); | 1207 TRACE("Merge %s the node.\n", changed ? "changed" : "did not change"); |
1125 | 1208 |
1126 if (changed) { | 1209 if (changed) { |
1127 status_analysis_.ResizeStatusVector(); | 1210 status_analysis_->ResizeStatusVector(); |
1128 } | 1211 } |
1129 return changed; | 1212 return changed; |
1130 } | 1213 } |
1131 | 1214 |
1132 void EscapeAnalysis::ProcessAllocation(Node* node) { | 1215 void EscapeAnalysis::ProcessAllocation(Node* node) { |
1133 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); | 1216 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); |
1134 ForwardVirtualState(node); | 1217 ForwardVirtualState(node); |
1135 VirtualState* state = virtual_states_[node->id()]; | 1218 VirtualState* state = virtual_states_[node->id()]; |
1136 Alias alias = GetAlias(node->id()); | 1219 Alias alias = GetAlias(node->id()); |
1137 | 1220 |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1214 Node* EscapeAnalysis::GetReplacement(NodeId id) { | 1297 Node* EscapeAnalysis::GetReplacement(NodeId id) { |
1215 Node* node = nullptr; | 1298 Node* node = nullptr; |
1216 while (replacement(id)) { | 1299 while (replacement(id)) { |
1217 node = replacement(id); | 1300 node = replacement(id); |
1218 id = node->id(); | 1301 id = node->id(); |
1219 } | 1302 } |
1220 return node; | 1303 return node; |
1221 } | 1304 } |
1222 | 1305 |
1223 bool EscapeAnalysis::IsVirtual(Node* node) { | 1306 bool EscapeAnalysis::IsVirtual(Node* node) { |
1224 if (node->id() >= status_analysis_.GetStatusVectorSize()) { | 1307 if (node->id() >= status_analysis_->GetStatusVectorSize()) { |
1225 return false; | 1308 return false; |
1226 } | 1309 } |
1227 return status_analysis_.IsVirtual(node); | 1310 return status_analysis_->IsVirtual(node); |
1228 } | 1311 } |
1229 | 1312 |
1230 bool EscapeAnalysis::IsEscaped(Node* node) { | 1313 bool EscapeAnalysis::IsEscaped(Node* node) { |
1231 if (node->id() >= status_analysis_.GetStatusVectorSize()) { | 1314 if (node->id() >= status_analysis_->GetStatusVectorSize()) { |
1232 return false; | 1315 return false; |
1233 } | 1316 } |
1234 return status_analysis_.IsEscaped(node); | 1317 return status_analysis_->IsEscaped(node); |
1235 } | 1318 } |
1236 | 1319 |
1237 bool EscapeAnalysis::SetEscaped(Node* node) { | 1320 bool EscapeAnalysis::SetEscaped(Node* node) { |
1238 return status_analysis_.SetEscaped(node); | 1321 return status_analysis_->SetEscaped(node); |
1239 } | 1322 } |
1240 | 1323 |
1241 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) { | 1324 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) { |
1242 if (VirtualState* states = virtual_states_[at->id()]) { | 1325 if (VirtualState* states = virtual_states_[at->id()]) { |
1243 return states->VirtualObjectFromAlias(GetAlias(id)); | 1326 return states->VirtualObjectFromAlias(GetAlias(id)); |
1244 } | 1327 } |
1245 return nullptr; | 1328 return nullptr; |
1246 } | 1329 } |
1247 | 1330 |
1248 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) { | 1331 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) { |
(...skipping 15 matching lines...) Expand all Loading... |
1264 VirtualState* state) { | 1347 VirtualState* state) { |
1265 TRACE("Load #%d from phi #%d", load->id(), from->id()); | 1348 TRACE("Load #%d from phi #%d", load->id(), from->id()); |
1266 | 1349 |
1267 cache_->fields().clear(); | 1350 cache_->fields().clear(); |
1268 for (int i = 0; i < load->op()->ValueInputCount(); ++i) { | 1351 for (int i = 0; i < load->op()->ValueInputCount(); ++i) { |
1269 Node* input = NodeProperties::GetValueInput(load, i); | 1352 Node* input = NodeProperties::GetValueInput(load, i); |
1270 cache_->fields().push_back(input); | 1353 cache_->fields().push_back(input); |
1271 } | 1354 } |
1272 | 1355 |
1273 cache_->LoadVirtualObjectsForFieldsFrom(state, | 1356 cache_->LoadVirtualObjectsForFieldsFrom(state, |
1274 status_analysis_.GetAliasMap()); | 1357 status_analysis_->GetAliasMap()); |
1275 if (cache_->objects().size() == cache_->fields().size()) { | 1358 if (cache_->objects().size() == cache_->fields().size()) { |
1276 cache_->GetFields(offset); | 1359 cache_->GetFields(offset); |
1277 if (cache_->fields().size() == cache_->objects().size()) { | 1360 if (cache_->fields().size() == cache_->objects().size()) { |
1278 Node* rep = replacement(load); | 1361 Node* rep = replacement(load); |
1279 if (!rep || !IsEquivalentPhi(rep, cache_->fields())) { | 1362 if (!rep || !IsEquivalentPhi(rep, cache_->fields())) { |
1280 int value_input_count = static_cast<int>(cache_->fields().size()); | 1363 int value_input_count = static_cast<int>(cache_->fields().size()); |
1281 cache_->fields().push_back(NodeProperties::GetControlInput(from)); | 1364 cache_->fields().push_back(NodeProperties::GetControlInput(from)); |
1282 Node* phi = graph()->NewNode( | 1365 Node* phi = graph()->NewNode( |
1283 common()->Phi(MachineRepresentation::kTagged, value_input_count), | 1366 common()->Phi(MachineRepresentation::kTagged, value_input_count), |
1284 value_input_count + 1, &cache_->fields().front()); | 1367 value_input_count + 1, &cache_->fields().front()); |
1285 status_analysis_.ResizeStatusVector(); | 1368 status_analysis_->ResizeStatusVector(); |
1286 SetReplacement(load, phi); | 1369 SetReplacement(load, phi); |
1287 TRACE(" got phi created.\n"); | 1370 TRACE(" got phi created.\n"); |
1288 } else { | 1371 } else { |
1289 TRACE(" has already phi #%d.\n", rep->id()); | 1372 TRACE(" has already phi #%d.\n", rep->id()); |
1290 } | 1373 } |
1291 } else { | 1374 } else { |
1292 TRACE(" has incomplete field info.\n"); | 1375 TRACE(" has incomplete field info.\n"); |
1293 } | 1376 } |
1294 } else { | 1377 } else { |
1295 TRACE(" has incomplete virtual object info.\n"); | 1378 TRACE(" has incomplete virtual object info.\n"); |
(...skipping 210 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1506 } | 1589 } |
1507 } | 1590 } |
1508 } | 1591 } |
1509 for (size_t n = 0; n < object_states.size(); n++) { | 1592 for (size_t n = 0; n < object_states.size(); n++) { |
1510 DebugPrintState(object_states[n]); | 1593 DebugPrintState(object_states[n]); |
1511 } | 1594 } |
1512 } | 1595 } |
1513 | 1596 |
1514 VirtualObject* EscapeAnalysis::GetVirtualObject(VirtualState* state, | 1597 VirtualObject* EscapeAnalysis::GetVirtualObject(VirtualState* state, |
1515 Node* node) { | 1598 Node* node) { |
1516 if (node->id() >= status_analysis_.GetAliasMap().size()) return nullptr; | 1599 if (node->id() >= status_analysis_->GetAliasMap().size()) return nullptr; |
1517 Alias alias = GetAlias(node->id()); | 1600 Alias alias = GetAlias(node->id()); |
1518 if (alias >= state->size()) return nullptr; | 1601 if (alias >= state->size()) return nullptr; |
1519 return state->VirtualObjectFromAlias(alias); | 1602 return state->VirtualObjectFromAlias(alias); |
1520 } | 1603 } |
1521 | 1604 |
1522 bool EscapeAnalysis::ExistsVirtualAllocate() { | 1605 bool EscapeAnalysis::ExistsVirtualAllocate() { |
1523 for (size_t id = 0; id < status_analysis_.GetAliasMap().size(); ++id) { | 1606 for (size_t id = 0; id < status_analysis_->GetAliasMap().size(); ++id) { |
1524 Alias alias = GetAlias(static_cast<NodeId>(id)); | 1607 Alias alias = GetAlias(static_cast<NodeId>(id)); |
1525 if (alias < EscapeStatusAnalysis::kUntrackable) { | 1608 if (alias < EscapeStatusAnalysis::kUntrackable) { |
1526 if (status_analysis_.IsVirtual(static_cast<int>(id))) { | 1609 if (status_analysis_->IsVirtual(static_cast<int>(id))) { |
1527 return true; | 1610 return true; |
1528 } | 1611 } |
1529 } | 1612 } |
1530 } | 1613 } |
1531 return false; | 1614 return false; |
1532 } | 1615 } |
1533 | 1616 |
| 1617 Alias EscapeAnalysis::GetAlias(NodeId id) const { |
| 1618 return status_analysis_->GetAlias(id); |
| 1619 } |
| 1620 |
| 1621 Alias EscapeAnalysis::AliasCount() const { |
| 1622 return status_analysis_->AliasCount(); |
| 1623 } |
| 1624 |
| 1625 Graph* EscapeAnalysis::graph() const { return status_analysis_->graph(); } |
| 1626 |
1534 } // namespace compiler | 1627 } // namespace compiler |
1535 } // namespace internal | 1628 } // namespace internal |
1536 } // namespace v8 | 1629 } // namespace v8 |
OLD | NEW |