Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "src/compiler/escape-analysis.h" | 5 #include "src/compiler/escape-analysis.h" |
| 6 | 6 |
| 7 #include "src/base/flags.h" | 7 #include "src/base/flags.h" |
| 8 #include "src/bootstrapper.h" | 8 #include "src/bootstrapper.h" |
| 9 #include "src/compilation-dependencies.h" | 9 #include "src/compilation-dependencies.h" |
| 10 #include "src/compiler/common-operator.h" | 10 #include "src/compiler/common-operator.h" |
| (...skipping 372 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 383 } else { | 383 } else { |
| 384 GetFields(cache->objects(), cache->fields(), i); | 384 GetFields(cache->objects(), cache->fields(), i); |
| 385 if (cache->fields().size() == cache->objects().size()) { | 385 if (cache->fields().size() == cache->objects().size()) { |
| 386 Node* rep = mergeObject->GetField(i); | 386 Node* rep = mergeObject->GetField(i); |
| 387 if (!rep || !mergeObject->IsCreatedPhi(i)) { | 387 if (!rep || !mergeObject->IsCreatedPhi(i)) { |
| 388 cache->fields().push_back(control); | 388 cache->fields().push_back(control); |
| 389 Node* phi = | 389 Node* phi = |
| 390 graph->NewNode(common->Phi(MachineRepresentation::kTagged, 2), | 390 graph->NewNode(common->Phi(MachineRepresentation::kTagged, 2), |
| 391 static_cast<int>(cache->fields().size()), | 391 static_cast<int>(cache->fields().size()), |
| 392 &cache->fields().front()); | 392 &cache->fields().front()); |
| 393 if (mergeObject->SetField(i, phi, true)) { | 393 DCHECK(mergeObject->SetField(i, phi, true)); |
| 394 if (FLAG_trace_turbo_escape) { | 394 if (FLAG_trace_turbo_escape) { |
| 395 PrintF(" Creating Phi #%d as merge of", phi->id()); | 395 PrintF(" Creating Phi #%d as merge of", phi->id()); |
| 396 for (size_t i = 0; i + 1 < cache->fields().size(); i++) { | 396 for (size_t i = 0; i + 1 < cache->fields().size(); i++) { |
| 397 PrintF(" #%d (%s)", cache->fields()[i]->id(), | 397 PrintF(" #%d (%s)", cache->fields()[i]->id(), |
| 398 cache->fields()[i]->op()->mnemonic()); | 398 cache->fields()[i]->op()->mnemonic()); |
| 399 } | |
| 400 PrintF("\n"); | |
| 401 } | 399 } |
| 402 changed = true; | 400 PrintF("\n"); |
| 403 } | 401 } |
| 402 changed = true; | |
| 404 } else { | 403 } else { |
| 405 DCHECK(rep->opcode() == IrOpcode::kPhi); | 404 DCHECK(rep->opcode() == IrOpcode::kPhi); |
| 406 for (size_t n = 0; n < cache->fields().size(); ++n) { | 405 for (size_t n = 0; n < cache->fields().size(); ++n) { |
| 407 Node* old = | 406 Node* old = |
| 408 NodeProperties::GetValueInput(rep, static_cast<int>(n)); | 407 NodeProperties::GetValueInput(rep, static_cast<int>(n)); |
| 409 if (old != cache->fields()[n]) { | 408 if (old != cache->fields()[n]) { |
| 410 changed = true; | 409 changed = true; |
| 411 NodeProperties::ReplaceValueInput(rep, cache->fields()[n], | 410 NodeProperties::ReplaceValueInput(rep, cache->fields()[n], |
| 412 static_cast<int>(n)); | 411 static_cast<int>(n)); |
| 413 } | 412 } |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 437 | 436 |
| 438 | 437 |
| 439 // ------------------------------EscapeStatusAnalysis--------------------------- | 438 // ------------------------------EscapeStatusAnalysis--------------------------- |
| 440 | 439 |
| 441 | 440 |
| 442 EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis, | 441 EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis, |
| 443 Graph* graph, Zone* zone) | 442 Graph* graph, Zone* zone) |
| 444 : object_analysis_(object_analysis), | 443 : object_analysis_(object_analysis), |
| 445 graph_(graph), | 444 graph_(graph), |
| 446 zone_(zone), | 445 zone_(zone), |
| 447 info_(zone), | 446 info_(graph->NodeCount(), kUnknown, zone), |
| 448 queue_(zone) { | 447 queue_(zone) {} |
| 449 info_.resize(graph->NodeCount()); | |
| 450 } | |
| 451 | 448 |
| 452 | 449 |
| 453 EscapeStatusAnalysis::~EscapeStatusAnalysis() {} | 450 EscapeStatusAnalysis::~EscapeStatusAnalysis() {} |
| 454 | 451 |
| 455 | 452 |
| 456 bool EscapeStatusAnalysis::HasEntry(Node* node) { | 453 bool EscapeStatusAnalysis::HasEntry(Node* node) { |
| 457 return info_[node->id()] != kUnknown; | 454 return info_[node->id()] != kUnknown; |
| 458 } | 455 } |
| 459 | 456 |
| 460 | 457 |
| 461 bool EscapeStatusAnalysis::IsVirtual(Node* node) { | 458 bool EscapeStatusAnalysis::IsVirtual(Node* node) { |
| 462 if (node->id() >= info_.size()) { | |
| 463 return false; | |
|
sigurds
2015/12/17 10:16:32
I'm removing this check here, because the class ha
| |
| 464 } | |
| 465 return info_[node->id()] == kVirtual; | 459 return info_[node->id()] == kVirtual; |
| 466 } | 460 } |
| 467 | 461 |
| 468 | 462 |
| 469 bool EscapeStatusAnalysis::IsEscaped(Node* node) { | 463 bool EscapeStatusAnalysis::IsEscaped(Node* node) { |
| 470 return info_[node->id()] == kEscaped; | 464 return info_[node->id()] == kEscaped; |
| 471 } | 465 } |
| 472 | 466 |
| 473 | 467 |
| 474 bool EscapeStatusAnalysis::IsAllocation(Node* node) { | 468 bool EscapeStatusAnalysis::IsAllocation(Node* node) { |
| 475 return node->opcode() == IrOpcode::kAllocate || | 469 return node->opcode() == IrOpcode::kAllocate || |
| 476 node->opcode() == IrOpcode::kFinishRegion; | 470 node->opcode() == IrOpcode::kFinishRegion; |
| 477 } | 471 } |
| 478 | 472 |
| 479 | 473 |
| 480 bool EscapeStatusAnalysis::SetEscaped(Node* node) { | 474 bool EscapeStatusAnalysis::SetEscaped(Node* node) { |
| 481 bool changed = info_[node->id()] != kEscaped; | 475 bool changed = info_[node->id()] != kEscaped; |
| 482 info_[node->id()] = kEscaped; | 476 info_[node->id()] = kEscaped; |
| 483 return changed; | 477 return changed; |
| 484 } | 478 } |
| 485 | 479 |
| 486 | 480 |
| 481 void EscapeStatusAnalysis::Resize() { | |
| 482 info_.resize(graph()->NodeCount(), kUnknown); | |
| 483 } | |
| 484 | |
| 485 | |
| 486 size_t EscapeStatusAnalysis::size() { return info_.size(); } | |
| 487 | |
| 488 | |
| 487 void EscapeStatusAnalysis::Run() { | 489 void EscapeStatusAnalysis::Run() { |
| 488 info_.resize(graph()->NodeCount()); | 490 Resize(); |
| 489 ZoneVector<bool> visited(zone()); | 491 ZoneVector<bool> visited(zone()); |
| 490 visited.resize(graph()->NodeCount()); | 492 visited.resize(graph()->NodeCount()); |
| 491 queue_.push_back(graph()->end()); | 493 queue_.push_back(graph()->end()); |
| 492 while (!queue_.empty()) { | 494 while (!queue_.empty()) { |
| 493 Node* node = queue_.front(); | 495 Node* node = queue_.front(); |
| 494 queue_.pop_front(); | 496 queue_.pop_front(); |
| 495 Process(node); | 497 Process(node); |
| 496 if (!visited[node->id()]) { | 498 if (!visited[node->id()]) { |
| 497 RevisitInputs(node); | 499 RevisitInputs(node); |
| 498 } | 500 } |
| (...skipping 461 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 960 changed = mergeState->MergeFrom(&cache_, zone(), graph(), common(), | 962 changed = mergeState->MergeFrom(&cache_, zone(), graph(), common(), |
| 961 NodeProperties::GetControlInput(node)) || | 963 NodeProperties::GetControlInput(node)) || |
| 962 changed; | 964 changed; |
| 963 | 965 |
| 964 if (FLAG_trace_turbo_escape) { | 966 if (FLAG_trace_turbo_escape) { |
| 965 PrintF("Merge %s the node.\n", changed ? "changed" : "did not change"); | 967 PrintF("Merge %s the node.\n", changed ? "changed" : "did not change"); |
| 966 } | 968 } |
| 967 | 969 |
| 968 if (changed) { | 970 if (changed) { |
| 969 mergeState->LastChangedAt(node); | 971 mergeState->LastChangedAt(node); |
| 972 escape_status_.Resize(); | |
| 970 } | 973 } |
| 971 return changed; | 974 return changed; |
| 972 } | 975 } |
| 973 | 976 |
| 974 | 977 |
| 975 void EscapeAnalysis::ProcessAllocation(Node* node) { | 978 void EscapeAnalysis::ProcessAllocation(Node* node) { |
| 976 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); | 979 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); |
| 977 ForwardVirtualState(node); | 980 ForwardVirtualState(node); |
| 978 | 981 |
| 979 // Check if we have already processed this node. | 982 // Check if we have already processed this node. |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1065 Node* node = nullptr; | 1068 Node* node = nullptr; |
| 1066 while (replacement(id)) { | 1069 while (replacement(id)) { |
| 1067 node = replacement(id); | 1070 node = replacement(id); |
| 1068 id = node->id(); | 1071 id = node->id(); |
| 1069 } | 1072 } |
| 1070 return node; | 1073 return node; |
| 1071 } | 1074 } |
| 1072 | 1075 |
| 1073 | 1076 |
| 1074 bool EscapeAnalysis::IsVirtual(Node* node) { | 1077 bool EscapeAnalysis::IsVirtual(Node* node) { |
| 1078 if (node->id() >= escape_status_.size()) { | |
| 1079 return false; | |
|
sigurds
2015/12/17 10:16:32
IsVirtual and IsEscaped below are public methods t
| |
| 1080 } | |
| 1075 return escape_status_.IsVirtual(node); | 1081 return escape_status_.IsVirtual(node); |
| 1076 } | 1082 } |
| 1077 | 1083 |
| 1078 | 1084 |
| 1079 bool EscapeAnalysis::IsEscaped(Node* node) { | 1085 bool EscapeAnalysis::IsEscaped(Node* node) { |
| 1086 if (node->id() >= escape_status_.size()) { | |
| 1087 return false; | |
| 1088 } | |
| 1080 return escape_status_.IsEscaped(node); | 1089 return escape_status_.IsEscaped(node); |
| 1081 } | 1090 } |
| 1082 | 1091 |
| 1083 | 1092 |
| 1084 bool EscapeAnalysis::SetEscaped(Node* node) { | 1093 bool EscapeAnalysis::SetEscaped(Node* node) { |
| 1085 return escape_status_.SetEscaped(node); | 1094 return escape_status_.SetEscaped(node); |
| 1086 } | 1095 } |
| 1087 | 1096 |
| 1088 | 1097 |
| 1089 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) { | 1098 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) { |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1126 GetVirtualObjects(state, inputs, cache_.objects()); | 1135 GetVirtualObjects(state, inputs, cache_.objects()); |
| 1127 if (cache_.objects().size() == inputs.size()) { | 1136 if (cache_.objects().size() == inputs.size()) { |
| 1128 GetFields(cache_.objects(), cache_.fields(), offset); | 1137 GetFields(cache_.objects(), cache_.fields(), offset); |
| 1129 if (cache_.fields().size() == cache_.objects().size()) { | 1138 if (cache_.fields().size() == cache_.objects().size()) { |
| 1130 Node* rep = replacement(node); | 1139 Node* rep = replacement(node); |
| 1131 if (!rep || !IsEquivalentPhi(rep, cache_.fields())) { | 1140 if (!rep || !IsEquivalentPhi(rep, cache_.fields())) { |
| 1132 cache_.fields().push_back(NodeProperties::GetControlInput(from)); | 1141 cache_.fields().push_back(NodeProperties::GetControlInput(from)); |
| 1133 Node* phi = graph()->NewNode( | 1142 Node* phi = graph()->NewNode( |
| 1134 common()->Phi(MachineRepresentation::kTagged, 2), | 1143 common()->Phi(MachineRepresentation::kTagged, 2), |
| 1135 static_cast<int>(cache_.fields().size()), &cache_.fields().front()); | 1144 static_cast<int>(cache_.fields().size()), &cache_.fields().front()); |
| 1145 escape_status_.Resize(); | |
| 1136 SetReplacement(node, phi); | 1146 SetReplacement(node, phi); |
| 1137 state->LastChangedAt(node); | 1147 state->LastChangedAt(node); |
| 1138 if (FLAG_trace_turbo_escape) { | 1148 if (FLAG_trace_turbo_escape) { |
| 1139 PrintF(" got phi created.\n"); | 1149 PrintF(" got phi created.\n"); |
| 1140 } | 1150 } |
| 1141 } else if (FLAG_trace_turbo_escape) { | 1151 } else if (FLAG_trace_turbo_escape) { |
| 1142 PrintF(" has already phi #%d.\n", rep->id()); | 1152 PrintF(" has already phi #%d.\n", rep->id()); |
| 1143 } | 1153 } |
| 1144 } else if (FLAG_trace_turbo_escape) { | 1154 } else if (FLAG_trace_turbo_escape) { |
| 1145 PrintF(" has incomplete field info.\n"); | 1155 PrintF(" has incomplete field info.\n"); |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1305 } | 1315 } |
| 1306 } | 1316 } |
| 1307 for (size_t n = 0; n < object_states.size(); n++) { | 1317 for (size_t n = 0; n < object_states.size(); n++) { |
| 1308 DebugPrintState(object_states[n]); | 1318 DebugPrintState(object_states[n]); |
| 1309 } | 1319 } |
| 1310 } | 1320 } |
| 1311 | 1321 |
| 1312 } // namespace compiler | 1322 } // namespace compiler |
| 1313 } // namespace internal | 1323 } // namespace internal |
| 1314 } // namespace v8 | 1324 } // namespace v8 |
| OLD | NEW |