Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(76)

Side by Side Diff: src/compiler/escape-analysis.cc

Issue 1619103004: [turbofan] Minor performance tweaks in escape analysis (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@perf-improv-2
Patch Set: Unstage Created 4 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | src/compiler/escape-analysis-reducer.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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"
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
159 changed = true; 159 changed = true;
160 fields_[i] = other.fields_[i]; 160 fields_[i] = other.fields_[i];
161 } 161 }
162 } 162 }
163 return changed; 163 return changed;
164 } 164 }
165 165
166 166
167 class VirtualState : public ZoneObject { 167 class VirtualState : public ZoneObject {
168 public: 168 public:
169 VirtualState(Node* owner, Zone* zone, size_t size); 169 VirtualState(NodeId owner, Zone* zone, size_t size);
170 VirtualState(Node* owner, const VirtualState& states); 170 VirtualState(NodeId owner, const VirtualState& states);
171 171
172 VirtualObject* VirtualObjectFromAlias(size_t alias); 172 VirtualObject* VirtualObjectFromAlias(size_t alias);
173 VirtualObject* GetOrCreateTrackedVirtualObject(Alias alias, NodeId id, 173 VirtualObject* GetOrCreateTrackedVirtualObject(Alias alias, NodeId id,
174 size_t fields, 174 size_t fields,
175 bool initialized, Zone* zone, 175 bool initialized, Zone* zone,
176 bool force_copy); 176 bool force_copy);
177 void SetVirtualObject(Alias alias, VirtualObject* state); 177 void SetVirtualObject(Alias alias, VirtualObject* state);
178 bool UpdateFrom(VirtualState* state, Zone* zone); 178 bool UpdateFrom(VirtualState* state, Zone* zone);
179 bool MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, 179 bool MergeFrom(MergeCache* cache, Zone* zone, Graph* graph,
180 CommonOperatorBuilder* common, Node* control, int arity); 180 CommonOperatorBuilder* common, Node* control, int arity);
181 size_t size() const { return info_.size(); } 181 size_t size() const { return info_.size(); }
182 Node* owner() const { return owner_; } 182 NodeId owner() const { return owner_; }
183 VirtualObject* Copy(VirtualObject* obj, Alias alias); 183 VirtualObject* Copy(VirtualObject* obj, Alias alias);
184 void SetCopyRequired() { 184 void SetCopyRequired() {
185 for (VirtualObject* obj : info_) { 185 for (VirtualObject* obj : info_) {
186 if (obj) obj->SetCopyRequired(); 186 if (obj) obj->SetCopyRequired();
187 } 187 }
188 } 188 }
189 189
190 private: 190 private:
191 ZoneVector<VirtualObject*> info_; 191 ZoneVector<VirtualObject*> info_;
192 Node* owner_; 192 NodeId owner_;
193 193
194 DISALLOW_COPY_AND_ASSIGN(VirtualState); 194 DISALLOW_COPY_AND_ASSIGN(VirtualState);
195 }; 195 };
196 196
197 197
198 class MergeCache : public ZoneObject { 198 class MergeCache : public ZoneObject {
199 public: 199 public:
200 explicit MergeCache(Zone* zone) 200 explicit MergeCache(Zone* zone)
201 : states_(zone), objects_(zone), fields_(zone) { 201 : states_(zone), objects_(zone), fields_(zone) {
202 states_.reserve(5); 202 states_.reserve(5);
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
265 fields_.push_back(field); 265 fields_.push_back(field);
266 } 266 }
267 if (field != rep) { 267 if (field != rep) {
268 rep = nullptr; 268 rep = nullptr;
269 } 269 }
270 } 270 }
271 return rep; 271 return rep;
272 } 272 }
273 273
274 274
275 VirtualState::VirtualState(Node* owner, Zone* zone, size_t size) 275 VirtualState::VirtualState(NodeId owner, Zone* zone, size_t size)
276 : info_(size, nullptr, zone), owner_(owner) {} 276 : info_(size, nullptr, zone), owner_(owner) {}
277 277
278 278
279 VirtualState::VirtualState(Node* owner, const VirtualState& state) 279 VirtualState::VirtualState(NodeId owner, const VirtualState& state)
280 : info_(state.info_.size(), nullptr, state.info_.get_allocator().zone()), 280 : info_(state.info_.size(), nullptr, state.info_.get_allocator().zone()),
281 owner_(owner) { 281 owner_(owner) {
282 for (size_t i = 0; i < info_.size(); ++i) { 282 for (size_t i = 0; i < info_.size(); ++i) {
283 if (state.info_[i]) { 283 if (state.info_[i]) {
284 info_[i] = state.info_[i]; 284 info_[i] = state.info_[i];
285 } 285 }
286 } 286 }
287 } 287 }
288 288
289 289
(...skipping 582 matching lines...) Expand 10 before | Expand all | Expand 10 after
872 if (node->id() >= aliases_.size()) { 872 if (node->id() >= aliases_.size()) {
873 return false; 873 return false;
874 } 874 }
875 return aliases_[node->id()] == kNotReachable; 875 return aliases_[node->id()] == kNotReachable;
876 } 876 }
877 877
878 878
879 void EscapeAnalysis::RunObjectAnalysis() { 879 void EscapeAnalysis::RunObjectAnalysis() {
880 virtual_states_.resize(graph()->NodeCount()); 880 virtual_states_.resize(graph()->NodeCount());
881 stack().push_back(graph()->start()); 881 stack().push_back(graph()->start());
882 ZoneVector<Node*> danglers(zone());
882 while (!stack().empty()) { 883 while (!stack().empty()) {
883 Node* node = stack().back(); 884 Node* node = stack().back();
884 stack().pop_back(); 885 stack().pop_back();
885 if (Process(node)) { 886 if (Process(node)) {
886 for (Edge edge : node->use_edges()) { 887 for (Edge edge : node->use_edges()) {
887 Node* use = edge.from(); 888 Node* use = edge.from();
888 if (IsNotReachable(use)) { 889 if (IsNotReachable(use)) {
889 continue; 890 continue;
890 } 891 }
891 if (NodeProperties::IsEffectEdge(edge)) { 892 if (NodeProperties::IsEffectEdge(edge)) {
892 if ((use->opcode() != IrOpcode::kLoadField && 893 if ((use->opcode() != IrOpcode::kLoadField &&
893 use->opcode() != IrOpcode::kLoadElement) || 894 use->opcode() != IrOpcode::kLoadElement) ||
894 !IsDanglingEffectNode(use)) { 895 !IsDanglingEffectNode(use)) {
895 stack().push_back(use); 896 stack().push_back(use);
897 } else {
898 danglers.push_back(use);
896 } 899 }
897 } 900 }
898 } 901 }
899 // First process loads: dangling loads are a problem otherwise. 902 stack().insert(stack().end(), danglers.begin(), danglers.end());
900 for (Edge edge : node->use_edges()) { 903 danglers.clear();
901 Node* use = edge.from();
902 if (IsNotReachable(use)) {
903 continue;
904 }
905 if (NodeProperties::IsEffectEdge(edge)) {
906 if ((use->opcode() == IrOpcode::kLoadField ||
907 use->opcode() == IrOpcode::kLoadElement) &&
908 IsDanglingEffectNode(use)) {
909 stack().push_back(use);
910 }
911 }
912 }
913 } 904 }
914 } 905 }
915 #ifdef DEBUG 906 #ifdef DEBUG
916 if (FLAG_trace_turbo_escape) { 907 if (FLAG_trace_turbo_escape) {
917 DebugPrint(); 908 DebugPrint();
918 } 909 }
919 #endif 910 #endif
920 } 911 }
921 912
922 913
923 bool EscapeStatusAnalysis::IsDanglingEffectNode(Node* node) { 914 bool EscapeStatusAnalysis::IsDanglingEffectNode(Node* node) {
924 if (status_[node->id()] & kDanglingComputed) { 915 if (status_[node->id()] & kDanglingComputed) {
925 return status_[node->id()] & kDangling; 916 return status_[node->id()] & kDangling;
926 } 917 }
927 if (node->op()->EffectInputCount() == 0) return false; 918 if (node->op()->EffectInputCount() == 0 ||
928 if (node->op()->EffectOutputCount() == 0) return false; 919 node->op()->EffectOutputCount() == 0 ||
929 if (node->op()->EffectInputCount() == 1 && 920 (node->op()->EffectInputCount() == 1 &&
930 NodeProperties::GetEffectInput(node)->opcode() == IrOpcode::kStart) { 921 NodeProperties::GetEffectInput(node)->opcode() == IrOpcode::kStart)) {
931 // The start node is used as sentinel for nodes that are in general 922 // The start node is used as sentinel for nodes that are in general
932 // effectful, but of which an analysis has determined that they do not 923 // effectful, but of which an analysis has determined that they do not
933 // produce effects in this instance. We don't consider these nodes dangling. 924 // produce effects in this instance. We don't consider these nodes dangling.
934 status_[node->id()] |= kDanglingComputed; 925 status_[node->id()] |= kDanglingComputed;
935 return false; 926 return false;
936 } 927 }
937 for (Edge edge : node->use_edges()) { 928 for (Edge edge : node->use_edges()) {
938 Node* use = edge.from(); 929 Node* use = edge.from();
939 if (aliases_[use->id()] == kNotReachable) continue; 930 if (aliases_[use->id()] == kNotReachable) continue;
940 if (NodeProperties::IsEffectEdge(edge)) { 931 if (NodeProperties::IsEffectEdge(edge)) {
941 status_[node->id()] |= kDanglingComputed; 932 status_[node->id()] |= kDanglingComputed;
942 return false; 933 return false;
943 } 934 }
944 } 935 }
945 status_[node->id()] |= kDanglingComputed | kDangling; 936 status_[node->id()] |= kDanglingComputed | kDangling;
946 return true; 937 return true;
947 } 938 }
948 939
949 940
950 bool EscapeStatusAnalysis::IsEffectBranchPoint(Node* node) { 941 bool EscapeStatusAnalysis::IsEffectBranchPoint(Node* node) {
951 if (status_[node->id()] & kBranchPointComputed) { 942 if (status_[node->id()] & kBranchPointComputed) {
952 return status_[node->id()] & kBranchPoint; 943 return status_[node->id()] & kBranchPoint;
953 } 944 }
954 int count = 0; 945 int count = 0;
955 for (Edge edge : node->use_edges()) { 946 for (Edge edge : node->use_edges()) {
956 Node* use = edge.from(); 947 Node* use = edge.from();
957 if (aliases_[use->id()] == kNotReachable) continue; 948 if (aliases_[use->id()] == kNotReachable) continue;
958 if (NodeProperties::IsEffectEdge(edge)) { 949 if (NodeProperties::IsEffectEdge(edge)) {
959 if ((node->opcode() == IrOpcode::kLoadField || 950 if ((use->opcode() == IrOpcode::kLoadField ||
960 node->opcode() == IrOpcode::kLoadElement || 951 use->opcode() == IrOpcode::kLoadElement ||
961 node->opcode() == IrOpcode::kLoad) && 952 use->opcode() == IrOpcode::kLoad) &&
962 IsDanglingEffectNode(node)) 953 IsDanglingEffectNode(use))
963 continue; 954 continue;
964 if (++count > 1) { 955 if (++count > 1) {
965 status_[node->id()] |= kBranchPointComputed | kBranchPoint; 956 status_[node->id()] |= kBranchPointComputed | kBranchPoint;
966 return true; 957 return true;
967 } 958 }
968 } 959 }
969 } 960 }
970 status_[node->id()] |= kBranchPointComputed; 961 status_[node->id()] |= kBranchPointComputed;
971 return false; 962 return false;
972 } 963 }
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
1041 } 1032 }
1042 } 1033 }
1043 break; 1034 break;
1044 } 1035 }
1045 } 1036 }
1046 } 1037 }
1047 1038
1048 1039
1049 VirtualState* EscapeAnalysis::CopyForModificationAt(VirtualState* state, 1040 VirtualState* EscapeAnalysis::CopyForModificationAt(VirtualState* state,
1050 Node* node) { 1041 Node* node) {
1051 if (state->owner() != node) { 1042 if (state->owner() != node->id()) {
1052 VirtualState* new_state = new (zone()) VirtualState(node, *state); 1043 VirtualState* new_state = new (zone()) VirtualState(node->id(), *state);
1053 virtual_states_[node->id()] = new_state; 1044 virtual_states_[node->id()] = new_state;
1054 TRACE("Copying virtual state %p to new state %p at node %s#%d\n", 1045 TRACE("Copying virtual state %p to new state %p at node %s#%d\n",
1055 static_cast<void*>(state), static_cast<void*>(new_state), 1046 static_cast<void*>(state), static_cast<void*>(new_state),
1056 node->op()->mnemonic(), node->id()); 1047 node->op()->mnemonic(), node->id());
1057 return new_state; 1048 return new_state;
1058 } 1049 }
1059 return state; 1050 return state;
1060 } 1051 }
1061 1052
1062 1053
(...skipping 17 matching lines...) Expand all
1080 PrintF("Dangeling effect node: #%d (%s)\n", node->id(), 1071 PrintF("Dangeling effect node: #%d (%s)\n", node->id(),
1081 node->op()->mnemonic()); 1072 node->op()->mnemonic());
1082 UNREACHABLE(); 1073 UNREACHABLE();
1083 } 1074 }
1084 #endif // DEBUG 1075 #endif // DEBUG
1085 Node* effect = NodeProperties::GetEffectInput(node); 1076 Node* effect = NodeProperties::GetEffectInput(node);
1086 // Break the cycle for effect phis. 1077 // Break the cycle for effect phis.
1087 if (effect->opcode() == IrOpcode::kEffectPhi && 1078 if (effect->opcode() == IrOpcode::kEffectPhi &&
1088 virtual_states_[effect->id()] == nullptr) { 1079 virtual_states_[effect->id()] == nullptr) {
1089 VirtualState* state = 1080 VirtualState* state =
1090 new (zone()) VirtualState(effect, zone(), AliasCount()); 1081 new (zone()) VirtualState(effect->id(), zone(), AliasCount());
1091 virtual_states_[effect->id()] = state; 1082 virtual_states_[effect->id()] = state;
1092 TRACE("Effect Phi #%d got new virtual state %p.\n", effect->id(), 1083 TRACE("Effect Phi #%d got new virtual state %p.\n", effect->id(),
1093 static_cast<void*>(virtual_states_[effect->id()])); 1084 static_cast<void*>(virtual_states_[effect->id()]));
1094 } 1085 }
1095 DCHECK_NOT_NULL(virtual_states_[effect->id()]); 1086 DCHECK_NOT_NULL(virtual_states_[effect->id()]);
1096 if (virtual_states_[node->id()]) { 1087 if (virtual_states_[node->id()]) {
1097 virtual_states_[node->id()]->UpdateFrom(virtual_states_[effect->id()], 1088 virtual_states_[node->id()]->UpdateFrom(virtual_states_[effect->id()],
1098 zone()); 1089 zone());
1099 } else { 1090 } else {
1100 virtual_states_[node->id()] = virtual_states_[effect->id()]; 1091 virtual_states_[node->id()] = virtual_states_[effect->id()];
1101 TRACE("Forwarding object state %p from %s#%d to %s#%d", 1092 TRACE("Forwarding object state %p from %s#%d to %s#%d",
1102 static_cast<void*>(virtual_states_[effect->id()]), 1093 static_cast<void*>(virtual_states_[effect->id()]),
1103 effect->op()->mnemonic(), effect->id(), node->op()->mnemonic(), 1094 effect->op()->mnemonic(), effect->id(), node->op()->mnemonic(),
1104 node->id()); 1095 node->id());
1105 if (IsEffectBranchPoint(effect) || 1096 if (IsEffectBranchPoint(effect) ||
1106 OperatorProperties::GetFrameStateInputCount(node->op()) > 0) { 1097 OperatorProperties::GetFrameStateInputCount(node->op()) > 0) {
1107 virtual_states_[node->id()]->SetCopyRequired(); 1098 virtual_states_[node->id()]->SetCopyRequired();
1108 TRACE(", effect input %s#%d is branch point", effect->op()->mnemonic(), 1099 TRACE(", effect input %s#%d is branch point", effect->op()->mnemonic(),
1109 effect->id()); 1100 effect->id());
1110 } 1101 }
1111 TRACE("\n"); 1102 TRACE("\n");
1112 } 1103 }
1113 } 1104 }
1114 1105
1115 1106
1116 void EscapeAnalysis::ProcessStart(Node* node) { 1107 void EscapeAnalysis::ProcessStart(Node* node) {
1117 DCHECK_EQ(node->opcode(), IrOpcode::kStart); 1108 DCHECK_EQ(node->opcode(), IrOpcode::kStart);
1118 virtual_states_[node->id()] = 1109 virtual_states_[node->id()] =
1119 new (zone()) VirtualState(node, zone(), AliasCount()); 1110 new (zone()) VirtualState(node->id(), zone(), AliasCount());
1120 } 1111 }
1121 1112
1122 1113
1123 bool EscapeAnalysis::ProcessEffectPhi(Node* node) { 1114 bool EscapeAnalysis::ProcessEffectPhi(Node* node) {
1124 DCHECK_EQ(node->opcode(), IrOpcode::kEffectPhi); 1115 DCHECK_EQ(node->opcode(), IrOpcode::kEffectPhi);
1125 bool changed = false; 1116 bool changed = false;
1126 1117
1127 VirtualState* mergeState = virtual_states_[node->id()]; 1118 VirtualState* mergeState = virtual_states_[node->id()];
1128 if (!mergeState) { 1119 if (!mergeState) {
1129 mergeState = new (zone()) VirtualState(node, zone(), AliasCount()); 1120 mergeState = new (zone()) VirtualState(node->id(), zone(), AliasCount());
1130 virtual_states_[node->id()] = mergeState; 1121 virtual_states_[node->id()] = mergeState;
1131 changed = true; 1122 changed = true;
1132 TRACE("Effect Phi #%d got new virtual state %p.\n", node->id(), 1123 TRACE("Effect Phi #%d got new virtual state %p.\n", node->id(),
1133 static_cast<void*>(mergeState)); 1124 static_cast<void*>(mergeState));
1134 } 1125 }
1135 1126
1136 cache_->Clear(); 1127 cache_->Clear();
1137 1128
1138 TRACE("At Effect Phi #%d, merging states into %p:", node->id(), 1129 TRACE("At Effect Phi #%d, merging states into %p:", node->id(),
1139 static_cast<void*>(mergeState)); 1130 static_cast<void*>(mergeState));
1140 1131
1141 for (int i = 0; i < node->op()->EffectInputCount(); ++i) { 1132 for (int i = 0; i < node->op()->EffectInputCount(); ++i) {
1142 Node* input = NodeProperties::GetEffectInput(node, i); 1133 Node* input = NodeProperties::GetEffectInput(node, i);
1143 VirtualState* state = virtual_states_[input->id()]; 1134 VirtualState* state = virtual_states_[input->id()];
1144 if (state) { 1135 if (state) {
1145 cache_->states().push_back(state); 1136 cache_->states().push_back(state);
1146 if (state == mergeState) { 1137 if (state == mergeState) {
1147 mergeState = new (zone()) VirtualState(node, zone(), AliasCount()); 1138 mergeState =
1139 new (zone()) VirtualState(node->id(), zone(), AliasCount());
1148 virtual_states_[node->id()] = mergeState; 1140 virtual_states_[node->id()] = mergeState;
1149 changed = true; 1141 changed = true;
1150 } 1142 }
1151 } 1143 }
1152 TRACE(" %p (from %d %s)", static_cast<void*>(state), input->id(), 1144 TRACE(" %p (from %d %s)", static_cast<void*>(state), input->id(),
1153 input->op()->mnemonic()); 1145 input->op()->mnemonic());
1154 } 1146 }
1155 TRACE("\n"); 1147 TRACE("\n");
1156 1148
1157 if (cache_->states().size() == 0) { 1149 if (cache_->states().size() == 0) {
(...skipping 441 matching lines...) Expand 10 before | Expand all | Expand 10 after
1599 return true; 1591 return true;
1600 } 1592 }
1601 } 1593 }
1602 } 1594 }
1603 return false; 1595 return false;
1604 } 1596 }
1605 1597
1606 } // namespace compiler 1598 } // namespace compiler
1607 } // namespace internal 1599 } // namespace internal
1608 } // namespace v8 1600 } // namespace v8
OLDNEW
« no previous file with comments | « no previous file | src/compiler/escape-analysis-reducer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698