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" |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
193 } | 193 } |
194 bool AllFieldsClear() { | 194 bool AllFieldsClear() { |
195 for (size_t i = 0; i < fields_.size(); ++i) { | 195 for (size_t i = 0; i < fields_.size(); ++i) { |
196 if (fields_[i] != nullptr) { | 196 if (fields_[i] != nullptr) { |
197 return false; | 197 return false; |
198 } | 198 } |
199 } | 199 } |
200 return true; | 200 return true; |
201 } | 201 } |
202 bool UpdateFrom(const VirtualObject& other); | 202 bool UpdateFrom(const VirtualObject& other); |
203 bool MergeFrom(MergeCache* cache, Node* at, Graph* graph, | 203 bool MergeFrom(MergeCache* cache, Zone* zone, Node* at, Graph* graph, |
204 CommonOperatorBuilder* common); | 204 CommonOperatorBuilder* common); |
205 void SetObjectState(Node* node) { object_state_ = node; } | 205 void SetObjectState(Node* node) { object_state_ = node; } |
206 Node* GetObjectState() const { return object_state_; } | 206 Node* GetObjectState() const { return object_state_; } |
207 bool IsCopyRequired() const { return status_ & kCopyRequired; } | 207 bool IsCopyRequired() const { return status_ & kCopyRequired; } |
208 void SetCopyRequired() { status_ |= kCopyRequired; } | 208 void SetCopyRequired() { status_ |= kCopyRequired; } |
209 bool NeedCopyForModification() { | 209 bool NeedCopyForModification() { |
210 if (!IsCopyRequired() || !IsInitialized()) { | 210 if (!IsCopyRequired() || !IsInitialized()) { |
211 return false; | 211 return false; |
212 } | 212 } |
213 return true; | 213 return true; |
214 } | 214 } |
215 | 215 |
216 NodeId id() const { return id_; } | 216 NodeId id() const { return id_; } |
217 void id(NodeId id) { id_ = id; } | 217 void id(NodeId id) { id_ = id; } |
218 | 218 |
219 private: | 219 private: |
220 bool MergeFields(size_t i, Node* at, MergeCache* cache, Graph* graph, | 220 bool MergeFields(size_t i, Zone* zone, Node* at, MergeCache* cache, |
221 CommonOperatorBuilder* common); | 221 Graph* graph, CommonOperatorBuilder* common); |
222 | 222 |
223 NodeId id_; | 223 NodeId id_; |
224 StatusFlags status_; | 224 StatusFlags status_; |
225 ZoneVector<Node*> fields_; | 225 ZoneVector<Node*> fields_; |
226 ZoneVector<bool> phi_; | 226 ZoneVector<bool> phi_; |
227 Node* object_state_; | 227 Node* object_state_; |
228 VirtualState* owner_; | 228 VirtualState* owner_; |
229 | 229 |
230 DISALLOW_COPY_AND_ASSIGN(VirtualObject); | 230 DISALLOW_COPY_AND_ASSIGN(VirtualObject); |
231 }; | 231 }; |
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
425 } | 425 } |
426 for (size_t i = 0; i < inputs.size(); ++i) { | 426 for (size_t i = 0; i < inputs.size(); ++i) { |
427 Node* input = NodeProperties::GetValueInput(phi, static_cast<int>(i)); | 427 Node* input = NodeProperties::GetValueInput(phi, static_cast<int>(i)); |
428 if (!IsEquivalentPhi(input, inputs[i])) { | 428 if (!IsEquivalentPhi(input, inputs[i])) { |
429 return false; | 429 return false; |
430 } | 430 } |
431 } | 431 } |
432 return true; | 432 return true; |
433 } | 433 } |
434 | 434 |
| 435 Type* GetTypeForPhi(Node* phi, Zone* zone) { |
| 436 int arity = phi->op()->ValueInputCount(); |
| 437 Type* type = Type::None(); |
| 438 for (int i = 1; i < arity; ++i) { |
| 439 Node* inner_node = NodeProperties::GetValueInput(phi, i); |
| 440 Type* inner_type = NodeProperties::IsTyped(inner_node) |
| 441 ? NodeProperties::GetType(inner_node) |
| 442 : Type::None(); |
| 443 type = Type::Union(type, inner_type, zone); |
| 444 } |
| 445 return type; |
| 446 } |
435 } // namespace | 447 } // namespace |
436 | 448 |
437 bool VirtualObject::MergeFields(size_t i, Node* at, MergeCache* cache, | 449 bool VirtualObject::MergeFields(size_t i, Zone* zone, Node* at, |
438 Graph* graph, CommonOperatorBuilder* common) { | 450 MergeCache* cache, Graph* graph, |
| 451 CommonOperatorBuilder* common) { |
439 bool changed = false; | 452 bool changed = false; |
440 int value_input_count = static_cast<int>(cache->fields().size()); | 453 int value_input_count = static_cast<int>(cache->fields().size()); |
441 Node* rep = GetField(i); | 454 Node* rep = GetField(i); |
442 if (!rep || !IsCreatedPhi(i)) { | 455 if (!rep || !IsCreatedPhi(i)) { |
443 Node* control = NodeProperties::GetControlInput(at); | 456 Node* control = NodeProperties::GetControlInput(at); |
444 cache->fields().push_back(control); | 457 cache->fields().push_back(control); |
445 Node* phi = graph->NewNode( | 458 Node* phi = graph->NewNode( |
446 common->Phi(MachineRepresentation::kTagged, value_input_count), | 459 common->Phi(MachineRepresentation::kTagged, value_input_count), |
447 value_input_count + 1, &cache->fields().front()); | 460 value_input_count + 1, &cache->fields().front()); |
448 SetField(i, phi, true); | 461 SetField(i, phi, true); |
| 462 NodeProperties::SetType(phi, GetTypeForPhi(phi, zone)); |
| 463 |
449 #ifdef DEBUG | 464 #ifdef DEBUG |
450 if (FLAG_trace_turbo_escape) { | 465 if (FLAG_trace_turbo_escape) { |
451 PrintF(" Creating Phi #%d as merge of", phi->id()); | 466 PrintF(" Creating Phi #%d as merge of", phi->id()); |
452 for (int i = 0; i < value_input_count; i++) { | 467 for (int i = 0; i < value_input_count; i++) { |
453 PrintF(" #%d (%s)", cache->fields()[i]->id(), | 468 PrintF(" #%d (%s)", cache->fields()[i]->id(), |
454 cache->fields()[i]->op()->mnemonic()); | 469 cache->fields()[i]->op()->mnemonic()); |
455 } | 470 } |
456 PrintF("\n"); | 471 PrintF("\n"); |
457 } | 472 } |
458 #endif | 473 #endif |
459 changed = true; | 474 changed = true; |
460 } else { | 475 } else { |
461 DCHECK(rep->opcode() == IrOpcode::kPhi); | 476 DCHECK(rep->opcode() == IrOpcode::kPhi); |
462 for (int n = 0; n < value_input_count; ++n) { | 477 for (int n = 0; n < value_input_count; ++n) { |
463 Node* old = NodeProperties::GetValueInput(rep, n); | 478 Node* old = NodeProperties::GetValueInput(rep, n); |
464 if (old != cache->fields()[n]) { | 479 if (old != cache->fields()[n]) { |
465 changed = true; | 480 changed = true; |
466 NodeProperties::ReplaceValueInput(rep, cache->fields()[n], n); | 481 NodeProperties::ReplaceValueInput(rep, cache->fields()[n], n); |
467 } | 482 } |
468 } | 483 } |
469 } | 484 } |
470 return changed; | 485 return changed; |
471 } | 486 } |
472 | 487 |
473 bool VirtualObject::MergeFrom(MergeCache* cache, Node* at, Graph* graph, | 488 bool VirtualObject::MergeFrom(MergeCache* cache, Zone* zone, Node* at, |
474 CommonOperatorBuilder* common) { | 489 Graph* graph, CommonOperatorBuilder* common) { |
475 DCHECK(at->opcode() == IrOpcode::kEffectPhi || | 490 DCHECK(at->opcode() == IrOpcode::kEffectPhi || |
476 at->opcode() == IrOpcode::kPhi); | 491 at->opcode() == IrOpcode::kPhi); |
477 bool changed = false; | 492 bool changed = false; |
478 for (size_t i = 0; i < field_count(); ++i) { | 493 for (size_t i = 0; i < field_count(); ++i) { |
479 Node* field = cache->GetFields(i); | 494 Node* field = cache->GetFields(i); |
480 if (field && !IsCreatedPhi(i)) { | 495 if (field && !IsCreatedPhi(i)) { |
481 changed = changed || GetField(i) != field; | 496 changed = changed || GetField(i) != field; |
482 SetField(i, field); | 497 SetField(i, field); |
483 TRACE(" Field %zu agree on rep #%d\n", i, field->id()); | 498 TRACE(" Field %zu agree on rep #%d\n", i, field->id()); |
484 } else { | 499 } else { |
485 size_t arity = at->opcode() == IrOpcode::kEffectPhi | 500 size_t arity = at->opcode() == IrOpcode::kEffectPhi |
486 ? at->op()->EffectInputCount() | 501 ? at->op()->EffectInputCount() |
487 : at->op()->ValueInputCount(); | 502 : at->op()->ValueInputCount(); |
488 if (cache->fields().size() == arity && | 503 if (cache->fields().size() == arity && |
489 (GetField(i) || !IsCreatedPhi(i))) { | 504 (GetField(i) || !IsCreatedPhi(i))) { |
490 changed = MergeFields(i, at, cache, graph, common) || changed; | 505 changed = MergeFields(i, zone, at, cache, graph, common) || changed; |
491 } else { | 506 } else { |
492 if (GetField(i) != nullptr) { | 507 if (GetField(i) != nullptr) { |
493 TRACE(" Field %zu cleared\n", i); | 508 TRACE(" Field %zu cleared\n", i); |
494 changed = true; | 509 changed = true; |
495 } | 510 } |
496 SetField(i, nullptr); | 511 SetField(i, nullptr); |
497 } | 512 } |
498 } | 513 } |
499 } | 514 } |
500 return changed; | 515 return changed; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
537 #ifdef DEBUG | 552 #ifdef DEBUG |
538 if (FLAG_trace_turbo_escape) { | 553 if (FLAG_trace_turbo_escape) { |
539 PrintF(" Alias @%d, merging into %p virtual objects", alias, | 554 PrintF(" Alias @%d, merging into %p virtual objects", alias, |
540 static_cast<void*>(mergeObject)); | 555 static_cast<void*>(mergeObject)); |
541 for (size_t i = 0; i < cache->objects().size(); i++) { | 556 for (size_t i = 0; i < cache->objects().size(); i++) { |
542 PrintF(" %p", static_cast<void*>(cache->objects()[i])); | 557 PrintF(" %p", static_cast<void*>(cache->objects()[i])); |
543 } | 558 } |
544 PrintF("\n"); | 559 PrintF("\n"); |
545 } | 560 } |
546 #endif // DEBUG | 561 #endif // DEBUG |
547 changed = mergeObject->MergeFrom(cache, at, graph, common) || changed; | 562 changed = |
| 563 mergeObject->MergeFrom(cache, zone, at, graph, common) || changed; |
548 } else { | 564 } else { |
549 if (mergeObject) { | 565 if (mergeObject) { |
550 TRACE(" Alias %d, virtual object removed\n", alias); | 566 TRACE(" Alias %d, virtual object removed\n", alias); |
551 changed = true; | 567 changed = true; |
552 } | 568 } |
553 SetVirtualObject(alias, nullptr); | 569 SetVirtualObject(alias, nullptr); |
554 } | 570 } |
555 } | 571 } |
556 return changed; | 572 return changed; |
557 } | 573 } |
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
859 | 875 |
860 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, | 876 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, |
861 Zone* zone) | 877 Zone* zone) |
862 : zone_(zone), | 878 : zone_(zone), |
863 slot_not_analyzed_(graph->NewNode(common->NumberConstant(0x1c0debad))), | 879 slot_not_analyzed_(graph->NewNode(common->NumberConstant(0x1c0debad))), |
864 common_(common), | 880 common_(common), |
865 status_analysis_(new (zone) EscapeStatusAnalysis(this, graph, zone)), | 881 status_analysis_(new (zone) EscapeStatusAnalysis(this, graph, zone)), |
866 virtual_states_(zone), | 882 virtual_states_(zone), |
867 replacements_(zone), | 883 replacements_(zone), |
868 cycle_detection_(zone), | 884 cycle_detection_(zone), |
869 cache_(nullptr) {} | 885 cache_(nullptr) { |
| 886 // Type slot_not_analyzed_ manually. |
| 887 double v = OpParameter<double>(slot_not_analyzed_); |
| 888 NodeProperties::SetType(slot_not_analyzed_, Type::Range(v, v, zone)); |
| 889 } |
870 | 890 |
871 EscapeAnalysis::~EscapeAnalysis() {} | 891 EscapeAnalysis::~EscapeAnalysis() {} |
872 | 892 |
873 void EscapeAnalysis::Run() { | 893 void EscapeAnalysis::Run() { |
874 replacements_.resize(graph()->NodeCount()); | 894 replacements_.resize(graph()->NodeCount()); |
875 status_analysis_->AssignAliases(); | 895 status_analysis_->AssignAliases(); |
876 if (status_analysis_->AliasCount() > 0) { | 896 if (status_analysis_->AliasCount() > 0) { |
877 cache_ = new (zone()) MergeCache(zone()); | 897 cache_ = new (zone()) MergeCache(zone()); |
878 replacements_.resize(graph()->NodeCount()); | 898 replacements_.resize(graph()->NodeCount()); |
879 status_analysis_->ResizeStatusVector(); | 899 status_analysis_->ResizeStatusVector(); |
(...skipping 516 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1396 if (cache_->objects().size() == cache_->fields().size()) { | 1416 if (cache_->objects().size() == cache_->fields().size()) { |
1397 cache_->GetFields(offset); | 1417 cache_->GetFields(offset); |
1398 if (cache_->fields().size() == cache_->objects().size()) { | 1418 if (cache_->fields().size() == cache_->objects().size()) { |
1399 Node* rep = replacement(load); | 1419 Node* rep = replacement(load); |
1400 if (!rep || !IsEquivalentPhi(rep, cache_->fields())) { | 1420 if (!rep || !IsEquivalentPhi(rep, cache_->fields())) { |
1401 int value_input_count = static_cast<int>(cache_->fields().size()); | 1421 int value_input_count = static_cast<int>(cache_->fields().size()); |
1402 cache_->fields().push_back(NodeProperties::GetControlInput(from)); | 1422 cache_->fields().push_back(NodeProperties::GetControlInput(from)); |
1403 Node* phi = graph()->NewNode( | 1423 Node* phi = graph()->NewNode( |
1404 common()->Phi(MachineRepresentation::kTagged, value_input_count), | 1424 common()->Phi(MachineRepresentation::kTagged, value_input_count), |
1405 value_input_count + 1, &cache_->fields().front()); | 1425 value_input_count + 1, &cache_->fields().front()); |
| 1426 NodeProperties::SetType(phi, GetTypeForPhi(phi, zone())); |
1406 status_analysis_->ResizeStatusVector(); | 1427 status_analysis_->ResizeStatusVector(); |
1407 SetReplacement(load, phi); | 1428 SetReplacement(load, phi); |
1408 TRACE(" got phi created.\n"); | 1429 TRACE(" got phi created.\n"); |
1409 } else { | 1430 } else { |
1410 TRACE(" has already phi #%d.\n", rep->id()); | 1431 TRACE(" has already phi #%d.\n", rep->id()); |
1411 } | 1432 } |
1412 } else { | 1433 } else { |
1413 TRACE(" has incomplete field info.\n"); | 1434 TRACE(" has incomplete field info.\n"); |
1414 } | 1435 } |
1415 } else { | 1436 } else { |
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1589 cache_->fields().clear(); | 1610 cache_->fields().clear(); |
1590 for (size_t i = 0; i < vobj->field_count(); ++i) { | 1611 for (size_t i = 0; i < vobj->field_count(); ++i) { |
1591 if (Node* field = vobj->GetField(i)) { | 1612 if (Node* field = vobj->GetField(i)) { |
1592 cache_->fields().push_back(ResolveReplacement(field)); | 1613 cache_->fields().push_back(ResolveReplacement(field)); |
1593 } | 1614 } |
1594 } | 1615 } |
1595 int input_count = static_cast<int>(cache_->fields().size()); | 1616 int input_count = static_cast<int>(cache_->fields().size()); |
1596 Node* new_object_state = | 1617 Node* new_object_state = |
1597 graph()->NewNode(common()->ObjectState(input_count), input_count, | 1618 graph()->NewNode(common()->ObjectState(input_count), input_count, |
1598 &cache_->fields().front()); | 1619 &cache_->fields().front()); |
| 1620 NodeProperties::SetType(new_object_state, Type::Internal()); |
1599 vobj->SetObjectState(new_object_state); | 1621 vobj->SetObjectState(new_object_state); |
1600 TRACE( | 1622 TRACE( |
1601 "Creating object state #%d for vobj %p (from node #%d) at effect " | 1623 "Creating object state #%d for vobj %p (from node #%d) at effect " |
1602 "#%d\n", | 1624 "#%d\n", |
1603 new_object_state->id(), static_cast<void*>(vobj), node->id(), | 1625 new_object_state->id(), static_cast<void*>(vobj), node->id(), |
1604 effect->id()); | 1626 effect->id()); |
1605 // Now fix uses of other objects. | 1627 // Now fix uses of other objects. |
1606 for (size_t i = 0; i < vobj->field_count(); ++i) { | 1628 for (size_t i = 0; i < vobj->field_count(); ++i) { |
1607 if (Node* field = vobj->GetField(i)) { | 1629 if (Node* field = vobj->GetField(i)) { |
1608 if (Node* field_object_state = | 1630 if (Node* field_object_state = |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1688 } | 1710 } |
1689 } | 1711 } |
1690 return false; | 1712 return false; |
1691 } | 1713 } |
1692 | 1714 |
1693 Graph* EscapeAnalysis::graph() const { return status_analysis_->graph(); } | 1715 Graph* EscapeAnalysis::graph() const { return status_analysis_->graph(); } |
1694 | 1716 |
1695 } // namespace compiler | 1717 } // namespace compiler |
1696 } // namespace internal | 1718 } // namespace internal |
1697 } // namespace v8 | 1719 } // namespace v8 |
OLD | NEW |