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

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

Issue 2606273002: [Turbofan] Run escape analysis concurrently. (Closed)
Patch Set: REBASE. Created 3 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') | src/compiler/pipeline.cc » ('J')
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 182 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « no previous file | src/compiler/escape-analysis-reducer.cc » ('j') | src/compiler/pipeline.cc » ('J')

Powered by Google App Engine
This is Rietveld 408576698