| 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 = EscapeAnalysis::Alias; | 27 typedef NodeId 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 |
| (...skipping 1047 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1085 case IrOpcode::kFinishRegion: | 1085 case IrOpcode::kFinishRegion: |
| 1086 case IrOpcode::kObjectIsSmi: | 1086 case IrOpcode::kObjectIsSmi: |
| 1087 break; | 1087 break; |
| 1088 default: | 1088 default: |
| 1089 VirtualState* state = virtual_states_[node->id()]; | 1089 VirtualState* state = virtual_states_[node->id()]; |
| 1090 if (VirtualObject* obj = | 1090 if (VirtualObject* obj = |
| 1091 GetVirtualObject(state, ResolveReplacement(input))) { | 1091 GetVirtualObject(state, ResolveReplacement(input))) { |
| 1092 if (!obj->AllFieldsClear()) { | 1092 if (!obj->AllFieldsClear()) { |
| 1093 obj = CopyForModificationAt(obj, state, node); | 1093 obj = CopyForModificationAt(obj, state, node); |
| 1094 obj->ClearAllFields(); | 1094 obj->ClearAllFields(); |
| 1095 TRACE("Cleared all fields of @%d:#%d\n", GetAlias(obj->id()), | 1095 TRACE("Cleared all fields of @%d:#%d\n", |
| 1096 obj->id()); | 1096 status_analysis_->GetAlias(obj->id()), obj->id()); |
| 1097 } | 1097 } |
| 1098 } | 1098 } |
| 1099 break; | 1099 break; |
| 1100 } | 1100 } |
| 1101 } | 1101 } |
| 1102 } | 1102 } |
| 1103 | 1103 |
| 1104 VirtualState* EscapeAnalysis::CopyForModificationAt(VirtualState* state, | 1104 VirtualState* EscapeAnalysis::CopyForModificationAt(VirtualState* state, |
| 1105 Node* node) { | 1105 Node* node) { |
| 1106 if (state->owner() != node) { | 1106 if (state->owner() != node) { |
| 1107 VirtualState* new_state = new (zone()) VirtualState(node, *state); | 1107 VirtualState* new_state = new (zone()) VirtualState(node, *state); |
| 1108 virtual_states_[node->id()] = new_state; | 1108 virtual_states_[node->id()] = new_state; |
| 1109 TRACE("Copying virtual state %p to new state %p at node %s#%d\n", | 1109 TRACE("Copying virtual state %p to new state %p at node %s#%d\n", |
| 1110 static_cast<void*>(state), static_cast<void*>(new_state), | 1110 static_cast<void*>(state), static_cast<void*>(new_state), |
| 1111 node->op()->mnemonic(), node->id()); | 1111 node->op()->mnemonic(), node->id()); |
| 1112 return new_state; | 1112 return new_state; |
| 1113 } | 1113 } |
| 1114 return state; | 1114 return state; |
| 1115 } | 1115 } |
| 1116 | 1116 |
| 1117 VirtualObject* EscapeAnalysis::CopyForModificationAt(VirtualObject* obj, | 1117 VirtualObject* EscapeAnalysis::CopyForModificationAt(VirtualObject* obj, |
| 1118 VirtualState* state, | 1118 VirtualState* state, |
| 1119 Node* node) { | 1119 Node* node) { |
| 1120 if (obj->NeedCopyForModification()) { | 1120 if (obj->NeedCopyForModification()) { |
| 1121 state = CopyForModificationAt(state, node); | 1121 state = CopyForModificationAt(state, node); |
| 1122 return state->Copy(obj, GetAlias(obj->id())); | 1122 return state->Copy(obj, status_analysis_->GetAlias(obj->id())); |
| 1123 } | 1123 } |
| 1124 return obj; | 1124 return obj; |
| 1125 } | 1125 } |
| 1126 | 1126 |
| 1127 void EscapeAnalysis::ForwardVirtualState(Node* node) { | 1127 void EscapeAnalysis::ForwardVirtualState(Node* node) { |
| 1128 DCHECK_EQ(node->op()->EffectInputCount(), 1); | 1128 DCHECK_EQ(node->op()->EffectInputCount(), 1); |
| 1129 #ifdef DEBUG | 1129 #ifdef DEBUG |
| 1130 if (node->opcode() != IrOpcode::kLoadField && | 1130 if (node->opcode() != IrOpcode::kLoadField && |
| 1131 node->opcode() != IrOpcode::kLoadElement && | 1131 node->opcode() != IrOpcode::kLoadElement && |
| 1132 node->opcode() != IrOpcode::kLoad && | 1132 node->opcode() != IrOpcode::kLoad && |
| (...skipping 20 matching lines...) Expand all Loading... |
| 1153 TRACE(", effect input %s#%d is branch point", effect->op()->mnemonic(), | 1153 TRACE(", effect input %s#%d is branch point", effect->op()->mnemonic(), |
| 1154 effect->id()); | 1154 effect->id()); |
| 1155 } | 1155 } |
| 1156 TRACE("\n"); | 1156 TRACE("\n"); |
| 1157 } | 1157 } |
| 1158 } | 1158 } |
| 1159 | 1159 |
| 1160 void EscapeAnalysis::ProcessStart(Node* node) { | 1160 void EscapeAnalysis::ProcessStart(Node* node) { |
| 1161 DCHECK_EQ(node->opcode(), IrOpcode::kStart); | 1161 DCHECK_EQ(node->opcode(), IrOpcode::kStart); |
| 1162 virtual_states_[node->id()] = | 1162 virtual_states_[node->id()] = |
| 1163 new (zone()) VirtualState(node, zone(), AliasCount()); | 1163 new (zone()) VirtualState(node, zone(), status_analysis_->AliasCount()); |
| 1164 } | 1164 } |
| 1165 | 1165 |
| 1166 bool EscapeAnalysis::ProcessEffectPhi(Node* node) { | 1166 bool EscapeAnalysis::ProcessEffectPhi(Node* node) { |
| 1167 DCHECK_EQ(node->opcode(), IrOpcode::kEffectPhi); | 1167 DCHECK_EQ(node->opcode(), IrOpcode::kEffectPhi); |
| 1168 bool changed = false; | 1168 bool changed = false; |
| 1169 | 1169 |
| 1170 VirtualState* mergeState = virtual_states_[node->id()]; | 1170 VirtualState* mergeState = virtual_states_[node->id()]; |
| 1171 if (!mergeState) { | 1171 if (!mergeState) { |
| 1172 mergeState = new (zone()) VirtualState(node, zone(), AliasCount()); | 1172 mergeState = |
| 1173 new (zone()) VirtualState(node, zone(), status_analysis_->AliasCount()); |
| 1173 virtual_states_[node->id()] = mergeState; | 1174 virtual_states_[node->id()] = mergeState; |
| 1174 changed = true; | 1175 changed = true; |
| 1175 TRACE("Effect Phi #%d got new virtual state %p.\n", node->id(), | 1176 TRACE("Effect Phi #%d got new virtual state %p.\n", node->id(), |
| 1176 static_cast<void*>(mergeState)); | 1177 static_cast<void*>(mergeState)); |
| 1177 } | 1178 } |
| 1178 | 1179 |
| 1179 cache_->Clear(); | 1180 cache_->Clear(); |
| 1180 | 1181 |
| 1181 TRACE("At Effect Phi #%d, merging states into %p:", node->id(), | 1182 TRACE("At Effect Phi #%d, merging states into %p:", node->id(), |
| 1182 static_cast<void*>(mergeState)); | 1183 static_cast<void*>(mergeState)); |
| 1183 | 1184 |
| 1184 for (int i = 0; i < node->op()->EffectInputCount(); ++i) { | 1185 for (int i = 0; i < node->op()->EffectInputCount(); ++i) { |
| 1185 Node* input = NodeProperties::GetEffectInput(node, i); | 1186 Node* input = NodeProperties::GetEffectInput(node, i); |
| 1186 VirtualState* state = virtual_states_[input->id()]; | 1187 VirtualState* state = virtual_states_[input->id()]; |
| 1187 if (state) { | 1188 if (state) { |
| 1188 cache_->states().push_back(state); | 1189 cache_->states().push_back(state); |
| 1189 if (state == mergeState) { | 1190 if (state == mergeState) { |
| 1190 mergeState = new (zone()) VirtualState(node, zone(), AliasCount()); | 1191 mergeState = new (zone()) |
| 1192 VirtualState(node, zone(), status_analysis_->AliasCount()); |
| 1191 virtual_states_[node->id()] = mergeState; | 1193 virtual_states_[node->id()] = mergeState; |
| 1192 changed = true; | 1194 changed = true; |
| 1193 } | 1195 } |
| 1194 } | 1196 } |
| 1195 TRACE(" %p (from %d %s)", static_cast<void*>(state), input->id(), | 1197 TRACE(" %p (from %d %s)", static_cast<void*>(state), input->id(), |
| 1196 input->op()->mnemonic()); | 1198 input->op()->mnemonic()); |
| 1197 } | 1199 } |
| 1198 TRACE("\n"); | 1200 TRACE("\n"); |
| 1199 | 1201 |
| 1200 if (cache_->states().size() == 0) { | 1202 if (cache_->states().size() == 0) { |
| 1201 return changed; | 1203 return changed; |
| 1202 } | 1204 } |
| 1203 | 1205 |
| 1204 changed = | 1206 changed = |
| 1205 mergeState->MergeFrom(cache_, zone(), graph(), common(), node) || changed; | 1207 mergeState->MergeFrom(cache_, zone(), graph(), common(), node) || changed; |
| 1206 | 1208 |
| 1207 TRACE("Merge %s the node.\n", changed ? "changed" : "did not change"); | 1209 TRACE("Merge %s the node.\n", changed ? "changed" : "did not change"); |
| 1208 | 1210 |
| 1209 if (changed) { | 1211 if (changed) { |
| 1210 status_analysis_->ResizeStatusVector(); | 1212 status_analysis_->ResizeStatusVector(); |
| 1211 } | 1213 } |
| 1212 return changed; | 1214 return changed; |
| 1213 } | 1215 } |
| 1214 | 1216 |
| 1215 void EscapeAnalysis::ProcessAllocation(Node* node) { | 1217 void EscapeAnalysis::ProcessAllocation(Node* node) { |
| 1216 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); | 1218 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); |
| 1217 ForwardVirtualState(node); | 1219 ForwardVirtualState(node); |
| 1218 VirtualState* state = virtual_states_[node->id()]; | 1220 VirtualState* state = virtual_states_[node->id()]; |
| 1219 Alias alias = GetAlias(node->id()); | 1221 Alias alias = status_analysis_->GetAlias(node->id()); |
| 1220 | 1222 |
| 1221 // Check if we have already processed this node. | 1223 // Check if we have already processed this node. |
| 1222 if (state->VirtualObjectFromAlias(alias)) { | 1224 if (state->VirtualObjectFromAlias(alias)) { |
| 1223 return; | 1225 return; |
| 1224 } | 1226 } |
| 1225 | 1227 |
| 1226 if (state->owner()->opcode() == IrOpcode::kEffectPhi) { | 1228 if (state->owner()->opcode() == IrOpcode::kEffectPhi) { |
| 1227 state = CopyForModificationAt(state, node); | 1229 state = CopyForModificationAt(state, node); |
| 1228 } | 1230 } |
| 1229 | 1231 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 1241 alias, new (zone()) VirtualObject(node->id(), state, zone())); | 1243 alias, new (zone()) VirtualObject(node->id(), state, zone())); |
| 1242 } | 1244 } |
| 1243 } | 1245 } |
| 1244 | 1246 |
| 1245 void EscapeAnalysis::ProcessFinishRegion(Node* node) { | 1247 void EscapeAnalysis::ProcessFinishRegion(Node* node) { |
| 1246 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion); | 1248 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion); |
| 1247 ForwardVirtualState(node); | 1249 ForwardVirtualState(node); |
| 1248 Node* allocation = NodeProperties::GetValueInput(node, 0); | 1250 Node* allocation = NodeProperties::GetValueInput(node, 0); |
| 1249 if (allocation->opcode() == IrOpcode::kAllocate) { | 1251 if (allocation->opcode() == IrOpcode::kAllocate) { |
| 1250 VirtualState* state = virtual_states_[node->id()]; | 1252 VirtualState* state = virtual_states_[node->id()]; |
| 1251 VirtualObject* obj = state->VirtualObjectFromAlias(GetAlias(node->id())); | 1253 VirtualObject* obj = |
| 1254 state->VirtualObjectFromAlias(status_analysis_->GetAlias(node->id())); |
| 1252 DCHECK_NOT_NULL(obj); | 1255 DCHECK_NOT_NULL(obj); |
| 1253 obj->SetInitialized(); | 1256 obj->SetInitialized(); |
| 1254 } | 1257 } |
| 1255 } | 1258 } |
| 1256 | 1259 |
| 1257 Node* EscapeAnalysis::replacement(NodeId id) { | |
| 1258 if (id >= replacements_.size()) return nullptr; | |
| 1259 return replacements_[id]; | |
| 1260 } | |
| 1261 | |
| 1262 Node* EscapeAnalysis::replacement(Node* node) { | 1260 Node* EscapeAnalysis::replacement(Node* node) { |
| 1263 return replacement(node->id()); | 1261 if (node->id() >= replacements_.size()) return nullptr; |
| 1262 return replacements_[node->id()]; |
| 1264 } | 1263 } |
| 1265 | 1264 |
| 1266 bool EscapeAnalysis::SetReplacement(Node* node, Node* rep) { | 1265 bool EscapeAnalysis::SetReplacement(Node* node, Node* rep) { |
| 1267 bool changed = replacements_[node->id()] != rep; | 1266 bool changed = replacements_[node->id()] != rep; |
| 1268 replacements_[node->id()] = rep; | 1267 replacements_[node->id()] = rep; |
| 1269 return changed; | 1268 return changed; |
| 1270 } | 1269 } |
| 1271 | 1270 |
| 1272 bool EscapeAnalysis::UpdateReplacement(VirtualState* state, Node* node, | 1271 bool EscapeAnalysis::UpdateReplacement(VirtualState* state, Node* node, |
| 1273 Node* rep) { | 1272 Node* rep) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1284 } | 1283 } |
| 1285 | 1284 |
| 1286 Node* EscapeAnalysis::ResolveReplacement(Node* node) { | 1285 Node* EscapeAnalysis::ResolveReplacement(Node* node) { |
| 1287 while (replacement(node)) { | 1286 while (replacement(node)) { |
| 1288 node = replacement(node); | 1287 node = replacement(node); |
| 1289 } | 1288 } |
| 1290 return node; | 1289 return node; |
| 1291 } | 1290 } |
| 1292 | 1291 |
| 1293 Node* EscapeAnalysis::GetReplacement(Node* node) { | 1292 Node* EscapeAnalysis::GetReplacement(Node* node) { |
| 1294 return GetReplacement(node->id()); | 1293 Node* result = nullptr; |
| 1295 } | 1294 while (replacement(node)) { |
| 1296 | 1295 node = result = replacement(node); |
| 1297 Node* EscapeAnalysis::GetReplacement(NodeId id) { | |
| 1298 Node* node = nullptr; | |
| 1299 while (replacement(id)) { | |
| 1300 node = replacement(id); | |
| 1301 id = node->id(); | |
| 1302 } | 1296 } |
| 1303 return node; | 1297 return result; |
| 1304 } | 1298 } |
| 1305 | 1299 |
| 1306 bool EscapeAnalysis::IsVirtual(Node* node) { | 1300 bool EscapeAnalysis::IsVirtual(Node* node) { |
| 1307 if (node->id() >= status_analysis_->GetStatusVectorSize()) { | 1301 if (node->id() >= status_analysis_->GetStatusVectorSize()) { |
| 1308 return false; | 1302 return false; |
| 1309 } | 1303 } |
| 1310 return status_analysis_->IsVirtual(node); | 1304 return status_analysis_->IsVirtual(node); |
| 1311 } | 1305 } |
| 1312 | 1306 |
| 1313 bool EscapeAnalysis::IsEscaped(Node* node) { | 1307 bool EscapeAnalysis::IsEscaped(Node* node) { |
| 1314 if (node->id() >= status_analysis_->GetStatusVectorSize()) { | 1308 if (node->id() >= status_analysis_->GetStatusVectorSize()) { |
| 1315 return false; | 1309 return false; |
| 1316 } | 1310 } |
| 1317 return status_analysis_->IsEscaped(node); | 1311 return status_analysis_->IsEscaped(node); |
| 1318 } | 1312 } |
| 1319 | 1313 |
| 1320 bool EscapeAnalysis::SetEscaped(Node* node) { | |
| 1321 return status_analysis_->SetEscaped(node); | |
| 1322 } | |
| 1323 | |
| 1324 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) { | |
| 1325 if (VirtualState* states = virtual_states_[at->id()]) { | |
| 1326 return states->VirtualObjectFromAlias(GetAlias(id)); | |
| 1327 } | |
| 1328 return nullptr; | |
| 1329 } | |
| 1330 | |
| 1331 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) { | 1314 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) { |
| 1332 DCHECK(IsVirtual(left) && IsVirtual(right)); | 1315 DCHECK(IsVirtual(left) && IsVirtual(right)); |
| 1333 left = ResolveReplacement(left); | 1316 left = ResolveReplacement(left); |
| 1334 right = ResolveReplacement(right); | 1317 right = ResolveReplacement(right); |
| 1335 if (IsEquivalentPhi(left, right)) { | 1318 if (IsEquivalentPhi(left, right)) { |
| 1336 return true; | 1319 return true; |
| 1337 } | 1320 } |
| 1338 return false; | 1321 return false; |
| 1339 } | 1322 } |
| 1340 | 1323 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1438 UpdateReplacement(state, node, value); | 1421 UpdateReplacement(state, node, value); |
| 1439 } else if (from->opcode() == IrOpcode::kPhi) { | 1422 } else if (from->opcode() == IrOpcode::kPhi) { |
| 1440 ElementAccess access = OpParameter<ElementAccess>(node); | 1423 ElementAccess access = OpParameter<ElementAccess>(node); |
| 1441 int offset = index.Value() + access.header_size / kPointerSize; | 1424 int offset = index.Value() + access.header_size / kPointerSize; |
| 1442 ProcessLoadFromPhi(offset, from, node, state); | 1425 ProcessLoadFromPhi(offset, from, node, state); |
| 1443 } else { | 1426 } else { |
| 1444 UpdateReplacement(state, node, nullptr); | 1427 UpdateReplacement(state, node, nullptr); |
| 1445 } | 1428 } |
| 1446 } else { | 1429 } else { |
| 1447 // We have a load from a non-const index, cannot eliminate object. | 1430 // We have a load from a non-const index, cannot eliminate object. |
| 1448 if (SetEscaped(from)) { | 1431 if (status_analysis_->SetEscaped(from)) { |
| 1449 TRACE( | 1432 TRACE( |
| 1450 "Setting #%d (%s) to escaped because load element #%d from non-const " | 1433 "Setting #%d (%s) to escaped because load element #%d from non-const " |
| 1451 "index #%d (%s)\n", | 1434 "index #%d (%s)\n", |
| 1452 from->id(), from->op()->mnemonic(), node->id(), index_node->id(), | 1435 from->id(), from->op()->mnemonic(), node->id(), index_node->id(), |
| 1453 index_node->op()->mnemonic()); | 1436 index_node->op()->mnemonic()); |
| 1454 } | 1437 } |
| 1455 } | 1438 } |
| 1456 } | 1439 } |
| 1457 | 1440 |
| 1458 void EscapeAnalysis::ProcessStoreField(Node* node) { | 1441 void EscapeAnalysis::ProcessStoreField(Node* node) { |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1493 kPointerSizeLog2); | 1476 kPointerSizeLog2); |
| 1494 CHECK_EQ(access.header_size % kPointerSize, 0); | 1477 CHECK_EQ(access.header_size % kPointerSize, 0); |
| 1495 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 2)); | 1478 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 2)); |
| 1496 if (obj->GetField(offset) != val) { | 1479 if (obj->GetField(offset) != val) { |
| 1497 obj = CopyForModificationAt(obj, state, node); | 1480 obj = CopyForModificationAt(obj, state, node); |
| 1498 obj->SetField(offset, val); | 1481 obj->SetField(offset, val); |
| 1499 } | 1482 } |
| 1500 } | 1483 } |
| 1501 } else { | 1484 } else { |
| 1502 // We have a store to a non-const index, cannot eliminate object. | 1485 // We have a store to a non-const index, cannot eliminate object. |
| 1503 if (SetEscaped(to)) { | 1486 if (status_analysis_->SetEscaped(to)) { |
| 1504 TRACE( | 1487 TRACE( |
| 1505 "Setting #%d (%s) to escaped because store element #%d to non-const " | 1488 "Setting #%d (%s) to escaped because store element #%d to non-const " |
| 1506 "index #%d (%s)\n", | 1489 "index #%d (%s)\n", |
| 1507 to->id(), to->op()->mnemonic(), node->id(), index_node->id(), | 1490 to->id(), to->op()->mnemonic(), node->id(), index_node->id(), |
| 1508 index_node->op()->mnemonic()); | 1491 index_node->op()->mnemonic()); |
| 1509 } | 1492 } |
| 1510 if (obj && obj->IsTracked()) { | 1493 if (obj && obj->IsTracked()) { |
| 1511 if (!obj->AllFieldsClear()) { | 1494 if (!obj->AllFieldsClear()) { |
| 1512 obj = CopyForModificationAt(obj, state, node); | 1495 obj = CopyForModificationAt(obj, state, node); |
| 1513 obj->ClearAllFields(); | 1496 obj->ClearAllFields(); |
| 1514 TRACE("Cleared all fields of @%d:#%d\n", GetAlias(obj->id()), | 1497 TRACE("Cleared all fields of @%d:#%d\n", |
| 1515 obj->id()); | 1498 status_analysis_->GetAlias(obj->id()), obj->id()); |
| 1516 } | 1499 } |
| 1517 } | 1500 } |
| 1518 } | 1501 } |
| 1519 } | 1502 } |
| 1520 | 1503 |
| 1521 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) { | 1504 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) { |
| 1522 if ((node->opcode() == IrOpcode::kFinishRegion || | 1505 if ((node->opcode() == IrOpcode::kFinishRegion || |
| 1523 node->opcode() == IrOpcode::kAllocate) && | 1506 node->opcode() == IrOpcode::kAllocate) && |
| 1524 IsVirtual(node)) { | 1507 IsVirtual(node)) { |
| 1525 if (VirtualObject* vobj = GetVirtualObject(virtual_states_[effect->id()], | 1508 if (VirtualObject* vobj = GetVirtualObject(virtual_states_[effect->id()], |
| (...skipping 27 matching lines...) Expand all Loading... |
| 1553 } | 1536 } |
| 1554 } | 1537 } |
| 1555 } | 1538 } |
| 1556 return new_object_state; | 1539 return new_object_state; |
| 1557 } | 1540 } |
| 1558 } | 1541 } |
| 1559 } | 1542 } |
| 1560 return nullptr; | 1543 return nullptr; |
| 1561 } | 1544 } |
| 1562 | 1545 |
| 1563 void EscapeAnalysis::DebugPrintObject(VirtualObject* object, Alias alias) { | |
| 1564 PrintF(" Alias @%d: Object #%d with %zu fields\n", alias, object->id(), | |
| 1565 object->field_count()); | |
| 1566 for (size_t i = 0; i < object->field_count(); ++i) { | |
| 1567 if (Node* f = object->GetField(i)) { | |
| 1568 PrintF(" Field %zu = #%d (%s)\n", i, f->id(), f->op()->mnemonic()); | |
| 1569 } | |
| 1570 } | |
| 1571 } | |
| 1572 | |
| 1573 void EscapeAnalysis::DebugPrintState(VirtualState* state) { | 1546 void EscapeAnalysis::DebugPrintState(VirtualState* state) { |
| 1574 PrintF("Dumping virtual state %p\n", static_cast<void*>(state)); | 1547 PrintF("Dumping virtual state %p\n", static_cast<void*>(state)); |
| 1575 for (Alias alias = 0; alias < AliasCount(); ++alias) { | 1548 for (Alias alias = 0; alias < status_analysis_->AliasCount(); ++alias) { |
| 1576 if (VirtualObject* object = state->VirtualObjectFromAlias(alias)) { | 1549 if (VirtualObject* object = state->VirtualObjectFromAlias(alias)) { |
| 1577 DebugPrintObject(object, alias); | 1550 PrintF(" Alias @%d: Object #%d with %zu fields\n", alias, object->id(), |
| 1551 object->field_count()); |
| 1552 for (size_t i = 0; i < object->field_count(); ++i) { |
| 1553 if (Node* f = object->GetField(i)) { |
| 1554 PrintF(" Field %zu = #%d (%s)\n", i, f->id(), f->op()->mnemonic()); |
| 1555 } |
| 1556 } |
| 1578 } | 1557 } |
| 1579 } | 1558 } |
| 1580 } | 1559 } |
| 1581 | 1560 |
| 1582 void EscapeAnalysis::DebugPrint() { | 1561 void EscapeAnalysis::DebugPrint() { |
| 1583 ZoneVector<VirtualState*> object_states(zone()); | 1562 ZoneVector<VirtualState*> object_states(zone()); |
| 1584 for (NodeId id = 0; id < virtual_states_.size(); id++) { | 1563 for (NodeId id = 0; id < virtual_states_.size(); id++) { |
| 1585 if (VirtualState* states = virtual_states_[id]) { | 1564 if (VirtualState* states = virtual_states_[id]) { |
| 1586 if (std::find(object_states.begin(), object_states.end(), states) == | 1565 if (std::find(object_states.begin(), object_states.end(), states) == |
| 1587 object_states.end()) { | 1566 object_states.end()) { |
| 1588 object_states.push_back(states); | 1567 object_states.push_back(states); |
| 1589 } | 1568 } |
| 1590 } | 1569 } |
| 1591 } | 1570 } |
| 1592 for (size_t n = 0; n < object_states.size(); n++) { | 1571 for (size_t n = 0; n < object_states.size(); n++) { |
| 1593 DebugPrintState(object_states[n]); | 1572 DebugPrintState(object_states[n]); |
| 1594 } | 1573 } |
| 1595 } | 1574 } |
| 1596 | 1575 |
| 1597 VirtualObject* EscapeAnalysis::GetVirtualObject(VirtualState* state, | 1576 VirtualObject* EscapeAnalysis::GetVirtualObject(VirtualState* state, |
| 1598 Node* node) { | 1577 Node* node) { |
| 1599 if (node->id() >= status_analysis_->GetAliasMap().size()) return nullptr; | 1578 if (node->id() >= status_analysis_->GetAliasMap().size()) return nullptr; |
| 1600 Alias alias = GetAlias(node->id()); | 1579 Alias alias = status_analysis_->GetAlias(node->id()); |
| 1601 if (alias >= state->size()) return nullptr; | 1580 if (alias >= state->size()) return nullptr; |
| 1602 return state->VirtualObjectFromAlias(alias); | 1581 return state->VirtualObjectFromAlias(alias); |
| 1603 } | 1582 } |
| 1604 | 1583 |
| 1605 bool EscapeAnalysis::ExistsVirtualAllocate() { | 1584 bool EscapeAnalysis::ExistsVirtualAllocate() { |
| 1606 for (size_t id = 0; id < status_analysis_->GetAliasMap().size(); ++id) { | 1585 for (size_t id = 0; id < status_analysis_->GetAliasMap().size(); ++id) { |
| 1607 Alias alias = GetAlias(static_cast<NodeId>(id)); | 1586 Alias alias = status_analysis_->GetAlias(static_cast<NodeId>(id)); |
| 1608 if (alias < EscapeStatusAnalysis::kUntrackable) { | 1587 if (alias < EscapeStatusAnalysis::kUntrackable) { |
| 1609 if (status_analysis_->IsVirtual(static_cast<int>(id))) { | 1588 if (status_analysis_->IsVirtual(static_cast<int>(id))) { |
| 1610 return true; | 1589 return true; |
| 1611 } | 1590 } |
| 1612 } | 1591 } |
| 1613 } | 1592 } |
| 1614 return false; | 1593 return false; |
| 1615 } | 1594 } |
| 1616 | 1595 |
| 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(); } | 1596 Graph* EscapeAnalysis::graph() const { return status_analysis_->graph(); } |
| 1626 | 1597 |
| 1627 } // namespace compiler | 1598 } // namespace compiler |
| 1628 } // namespace internal | 1599 } // namespace internal |
| 1629 } // namespace v8 | 1600 } // namespace v8 |
| OLD | NEW |