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 |