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

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

Issue 1527533002: [turbofan] Move replacements out of virtual object (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@fix-cluster-3
Patch Set: Address comment Created 5 years 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 | « src/compiler/escape-analysis.h ('k') | src/compiler/escape-analysis-reducer.cc » ('j') | no next file with comments »
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 "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 11 matching lines...) Expand all
22 namespace compiler { 22 namespace compiler {
23 23
24 24
25 // ------------------------------VirtualObject---------------------------------- 25 // ------------------------------VirtualObject----------------------------------
26 26
27 27
28 class VirtualObject : public ZoneObject { 28 class VirtualObject : public ZoneObject {
29 public: 29 public:
30 enum Status { kUntracked = 0, kTracked = 1 }; 30 enum Status { kUntracked = 0, kTracked = 1 };
31 VirtualObject(NodeId id, Zone* zone) 31 VirtualObject(NodeId id, Zone* zone)
32 : id_(id), 32 : id_(id), status_(kUntracked), fields_(zone), phi_(zone) {}
33 status_(kUntracked),
34 fields_(zone),
35 phi_(zone),
36 replacement_(nullptr) {}
37 33
38 VirtualObject(const VirtualObject& other) 34 VirtualObject(const VirtualObject& other)
39 : id_(other.id_), 35 : id_(other.id_),
40 status_(other.status_), 36 status_(other.status_),
41 fields_(other.fields_), 37 fields_(other.fields_),
42 phi_(other.phi_), 38 phi_(other.phi_) {}
43 replacement_(other.replacement_) {}
44 39
45 VirtualObject(NodeId id, Zone* zone, size_t field_number) 40 VirtualObject(NodeId id, Zone* zone, size_t field_number)
46 : id_(id), 41 : id_(id), status_(kTracked), fields_(zone), phi_(zone) {
47 status_(kTracked),
48 fields_(zone),
49 phi_(zone),
50 replacement_(nullptr) {
51 fields_.resize(field_number); 42 fields_.resize(field_number);
52 phi_.resize(field_number, false); 43 phi_.resize(field_number, false);
53 } 44 }
54 45
55 Node* GetField(size_t offset) { 46 Node* GetField(size_t offset) {
56 if (offset < fields_.size()) { 47 if (offset < fields_.size()) {
57 return fields_[offset]; 48 return fields_[offset];
58 } 49 }
59 return nullptr; 50 return nullptr;
60 } 51 }
(...skipping 10 matching lines...) Expand all
71 fields_[offset] = node; 62 fields_[offset] = node;
72 phi_[offset] = created_phi; 63 phi_[offset] = created_phi;
73 if (changed && FLAG_trace_turbo_escape && node) { 64 if (changed && FLAG_trace_turbo_escape && node) {
74 PrintF("Setting field %zu of #%d to #%d (%s)\n", offset, id(), node->id(), 65 PrintF("Setting field %zu of #%d to #%d (%s)\n", offset, id(), node->id(),
75 node->op()->mnemonic()); 66 node->op()->mnemonic());
76 } 67 }
77 return changed; 68 return changed;
78 } 69 }
79 bool IsVirtual() const { return status_ == kTracked; } 70 bool IsVirtual() const { return status_ == kTracked; }
80 bool IsTracked() const { return status_ != kUntracked; } 71 bool IsTracked() const { return status_ != kUntracked; }
81 Node* GetReplacement() { return replacement_; }
82 bool SetReplacement(Node* node) {
83 bool changed = replacement_ != node;
84 replacement_ = node;
85 return changed;
86 }
87 72
88 Node** fields_array() { return &fields_.front(); } 73 Node** fields_array() { return &fields_.front(); }
89 size_t field_count() { return fields_.size(); } 74 size_t field_count() { return fields_.size(); }
90 bool ResizeFields(size_t field_count) { 75 bool ResizeFields(size_t field_count) {
91 if (field_count != fields_.size()) { 76 if (field_count != fields_.size()) {
92 fields_.resize(field_count); 77 fields_.resize(field_count);
93 phi_.resize(field_count); 78 phi_.resize(field_count);
94 return true; 79 return true;
95 } 80 }
96 return false; 81 return false;
(...skipping 12 matching lines...) Expand all
109 bool UpdateFrom(const VirtualObject& other); 94 bool UpdateFrom(const VirtualObject& other);
110 95
111 NodeId id() { return id_; } 96 NodeId id() { return id_; }
112 void id(NodeId id) { id_ = id; } 97 void id(NodeId id) { id_ = id; }
113 98
114 private: 99 private:
115 NodeId id_; 100 NodeId id_;
116 Status status_; 101 Status status_;
117 ZoneVector<Node*> fields_; 102 ZoneVector<Node*> fields_;
118 ZoneVector<bool> phi_; 103 ZoneVector<bool> phi_;
119 Node* replacement_;
120 }; 104 };
121 105
122 106
123 bool VirtualObject::UpdateFrom(const VirtualObject& other) { 107 bool VirtualObject::UpdateFrom(const VirtualObject& other) {
124 bool changed = status_ != other.status_; 108 bool changed = status_ != other.status_;
125 status_ = other.status_; 109 status_ = other.status_;
126 changed = replacement_ != other.replacement_ || changed;
127 replacement_ = other.replacement_;
128 if (fields_.size() != other.fields_.size()) { 110 if (fields_.size() != other.fields_.size()) {
129 fields_ = other.fields_; 111 fields_ = other.fields_;
130 return true; 112 return true;
131 } 113 }
132 for (size_t i = 0; i < fields_.size(); ++i) { 114 for (size_t i = 0; i < fields_.size(); ++i) {
133 if (fields_[i] != other.fields_[i]) { 115 if (fields_[i] != other.fields_[i]) {
134 changed = true; 116 changed = true;
135 fields_[i] = other.fields_[i]; 117 fields_[i] = other.fields_[i];
136 } 118 }
137 } 119 }
138 return changed; 120 return changed;
139 } 121 }
140 122
141 123
142 // ------------------------------VirtualState----------------------------------- 124 // ------------------------------VirtualState-----------------------------------
143 125
144 126
145 class VirtualState : public ZoneObject { 127 class VirtualState : public ZoneObject {
146 public: 128 public:
147 VirtualState(Zone* zone, size_t size); 129 VirtualState(Zone* zone, size_t size);
148 VirtualState(const VirtualState& states); 130 VirtualState(const VirtualState& states);
149 131
150 VirtualObject* ResolveVirtualObject(Node* node);
151 VirtualObject* GetVirtualObject(Node* node); 132 VirtualObject* GetVirtualObject(Node* node);
152 VirtualObject* GetVirtualObject(size_t id); 133 VirtualObject* GetVirtualObject(size_t id);
153 VirtualObject* GetOrCreateTrackedVirtualObject(NodeId id, Zone* zone); 134 VirtualObject* GetOrCreateTrackedVirtualObject(NodeId id, Zone* zone);
154 void SetVirtualObject(NodeId id, VirtualObject* state); 135 void SetVirtualObject(NodeId id, VirtualObject* state);
155 void LastChangedAt(Node* node) { last_changed_ = node; } 136 void LastChangedAt(Node* node) { last_changed_ = node; }
156 Node* GetLastChanged() { return last_changed_; } 137 Node* GetLastChanged() { return last_changed_; }
157 bool UpdateFrom(NodeId id, VirtualObject* state, Zone* zone); 138 bool UpdateFrom(NodeId id, VirtualObject* state, Zone* zone);
158 Node* ResolveReplacement(Node* node);
159 bool UpdateReplacement(Node* node, Node* rep, Zone* zone);
160 bool UpdateFrom(VirtualState* state, Zone* zone); 139 bool UpdateFrom(VirtualState* state, Zone* zone);
161 bool MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, 140 bool MergeFrom(MergeCache* cache, Zone* zone, Graph* graph,
162 CommonOperatorBuilder* common, Node* control); 141 CommonOperatorBuilder* common, Node* control);
163 142
164 size_t size() { return info_.size(); } 143 size_t size() { return info_.size(); }
165 144
166 private: 145 private:
167 ZoneVector<VirtualObject*> info_; 146 ZoneVector<VirtualObject*> info_;
168 Node* last_changed_; 147 Node* last_changed_;
169 }; 148 };
(...skipping 27 matching lines...) Expand all
197 if (id >= info_.size()) return nullptr; 176 if (id >= info_.size()) return nullptr;
198 return info_[id]; 177 return info_[id];
199 } 178 }
200 179
201 180
202 VirtualObject* VirtualState::GetVirtualObject(Node* node) { 181 VirtualObject* VirtualState::GetVirtualObject(Node* node) {
203 return GetVirtualObject(node->id()); 182 return GetVirtualObject(node->id());
204 } 183 }
205 184
206 185
207 VirtualObject* VirtualState::ResolveVirtualObject(Node* node) {
208 VirtualObject* obj = GetVirtualObject(node->id());
209 while (obj && !obj->IsTracked() && obj->GetReplacement() &&
210 GetVirtualObject(obj->GetReplacement())) {
211 obj = GetVirtualObject(obj->GetReplacement());
212 }
213 return obj;
214 }
215
216
217 VirtualObject* VirtualState::GetOrCreateTrackedVirtualObject(NodeId id, 186 VirtualObject* VirtualState::GetOrCreateTrackedVirtualObject(NodeId id,
218 Zone* zone) { 187 Zone* zone) {
219 if (VirtualObject* obj = GetVirtualObject(id)) { 188 if (VirtualObject* obj = GetVirtualObject(id)) {
220 return obj; 189 return obj;
221 } 190 }
222 VirtualObject* obj = new (zone) VirtualObject(id, zone, 0); 191 VirtualObject* obj = new (zone) VirtualObject(id, zone, 0);
223 SetVirtualObject(id, obj); 192 SetVirtualObject(id, obj);
224 return obj; 193 return obj;
225 } 194 }
226 195
(...skipping 100 matching lines...) Expand 10 before | Expand all | Expand 10 after
327 Node* rep = objs.front()->GetField(pos); 296 Node* rep = objs.front()->GetField(pos);
328 for (VirtualObject* obj : objs) { 297 for (VirtualObject* obj : objs) {
329 if (obj->GetField(pos) != rep) { 298 if (obj->GetField(pos) != rep) {
330 return nullptr; 299 return nullptr;
331 } 300 }
332 } 301 }
333 return rep; 302 return rep;
334 } 303 }
335 304
336 305
337 Node* GetReplacementIfSame(ZoneVector<VirtualObject*>& objs) {
338 Node* rep = objs.front()->GetReplacement();
339 for (VirtualObject* obj : objs) {
340 if (obj->GetReplacement() != rep) {
341 return nullptr;
342 }
343 }
344 return rep;
345 }
346
347
348 void GetFields(ZoneVector<VirtualObject*>& objs, ZoneVector<Node*>& fields, 306 void GetFields(ZoneVector<VirtualObject*>& objs, ZoneVector<Node*>& fields,
349 size_t pos) { 307 size_t pos) {
350 fields.clear(); 308 fields.clear();
351 for (VirtualObject* obj : objs) { 309 for (VirtualObject* obj : objs) {
352 if (Node* field = obj->GetField(pos)) { 310 if (Node* field = obj->GetField(pos)) {
353 fields.push_back(field); 311 fields.push_back(field);
354 } 312 }
355 } 313 }
356 } 314 }
357 315
(...skipping 25 matching lines...) Expand all
383 if (!IsEquivalentPhi(input, inputs[i])) { 341 if (!IsEquivalentPhi(input, inputs[i])) {
384 return false; 342 return false;
385 } 343 }
386 } 344 }
387 return true; 345 return true;
388 } 346 }
389 347
390 } // namespace 348 } // namespace
391 349
392 350
351 Node* EscapeAnalysis::GetReplacementIfSame(ZoneVector<VirtualObject*>& objs) {
352 Node* rep = GetReplacement(objs.front()->id());
353 for (VirtualObject* obj : objs) {
354 if (GetReplacement(obj->id()) != rep) {
355 return nullptr;
356 }
357 }
358 return rep;
359 }
360
361
393 bool VirtualState::MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, 362 bool VirtualState::MergeFrom(MergeCache* cache, Zone* zone, Graph* graph,
394 CommonOperatorBuilder* common, Node* control) { 363 CommonOperatorBuilder* common, Node* control) {
395 DCHECK_GT(cache->states().size(), 0u); 364 DCHECK_GT(cache->states().size(), 0u);
396 bool changed = false; 365 bool changed = false;
397 for (NodeId id = 0; id < min_size(cache->states()); ++id) { 366 for (NodeId id = 0; id < min_size(cache->states()); ++id) {
398 GetVirtualObjects(cache->states(), cache->objects(), id); 367 GetVirtualObjects(cache->states(), cache->objects(), id);
399 if (cache->objects().size() == cache->states().size()) { 368 if (cache->objects().size() == cache->states().size()) {
400 // Don't process linked objects. 369 // Don't process linked objects.
401 if (cache->objects()[0]->id() != id) continue; 370 if (cache->objects()[0]->id() != id) continue;
402 if (FLAG_trace_turbo_escape) { 371 if (FLAG_trace_turbo_escape) {
403 PrintF(" Merging virtual objects of #%d\n", id); 372 PrintF(" Merging virtual objects of #%d\n", id);
404 } 373 }
405 VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject(id, zone); 374 VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject(id, zone);
406 mergeObject->SetReplacement(GetReplacementIfSame(cache->objects()));
407 size_t fields = min_field_count(cache->objects()); 375 size_t fields = min_field_count(cache->objects());
408 changed = mergeObject->ResizeFields(fields) || changed; 376 changed = mergeObject->ResizeFields(fields) || changed;
409 for (size_t i = 0; i < fields; ++i) { 377 for (size_t i = 0; i < fields; ++i) {
410 if (Node* field = GetFieldIfSame(i, cache->objects())) { 378 if (Node* field = GetFieldIfSame(i, cache->objects())) {
411 changed = mergeObject->SetField(i, field) || changed; 379 changed = mergeObject->SetField(i, field) || changed;
412 if (FLAG_trace_turbo_escape) { 380 if (FLAG_trace_turbo_escape) {
413 PrintF(" Field %zu agree on rep #%d\n", i, field->id()); 381 PrintF(" Field %zu agree on rep #%d\n", i, field->id());
414 } 382 }
415 } else { 383 } else {
416 GetFields(cache->objects(), cache->fields(), i); 384 GetFields(cache->objects(), cache->fields(), i);
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
461 if (cache->objects().size() == cache->states().size()) { 429 if (cache->objects().size() == cache->states().size()) {
462 if (cache->objects()[0]->id() != id) { 430 if (cache->objects()[0]->id() != id) {
463 SetVirtualObject(id, GetVirtualObject(cache->objects()[0]->id())); 431 SetVirtualObject(id, GetVirtualObject(cache->objects()[0]->id()));
464 } 432 }
465 } 433 }
466 } 434 }
467 return changed; 435 return changed;
468 } 436 }
469 437
470 438
471 Node* VirtualState::ResolveReplacement(Node* node) {
472 Node* replacement = node;
473 VirtualObject* obj = GetVirtualObject(node);
474 while (obj != nullptr && obj->GetReplacement()) {
475 replacement = obj->GetReplacement();
476 obj = GetVirtualObject(replacement);
477 }
478 return replacement;
479 }
480
481
482 bool VirtualState::UpdateReplacement(Node* node, Node* rep, Zone* zone) {
483 if (!GetVirtualObject(node)) {
484 if (rep) {
485 SetVirtualObject(node->id(), new (zone) VirtualObject(node->id(), zone));
486 } else {
487 return false;
488 }
489 }
490 if (GetVirtualObject(node)->SetReplacement(rep)) {
491 LastChangedAt(node);
492 if (FLAG_trace_turbo_escape) {
493 if (rep) {
494 PrintF("Replacement of #%d is #%d (%s)\n", node->id(), rep->id(),
495 rep->op()->mnemonic());
496 } else {
497 PrintF("Replacement of #%d cleared\n", node->id());
498 }
499 }
500 return true;
501 }
502 return false;
503 }
504
505
506 // ------------------------------EscapeStatusAnalysis--------------------------- 439 // ------------------------------EscapeStatusAnalysis---------------------------
507 440
508 441
509 EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis, 442 EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis,
510 Graph* graph, Zone* zone) 443 Graph* graph, Zone* zone)
511 : object_analysis_(object_analysis), 444 : object_analysis_(object_analysis),
512 graph_(graph), 445 graph_(graph),
513 zone_(zone), 446 zone_(zone),
514 info_(zone), 447 info_(zone),
515 queue_(zone) { 448 queue_(zone) {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
596 ProcessFinishRegion(node); 529 ProcessFinishRegion(node);
597 break; 530 break;
598 case IrOpcode::kStoreField: 531 case IrOpcode::kStoreField:
599 ProcessStoreField(node); 532 ProcessStoreField(node);
600 break; 533 break;
601 case IrOpcode::kStoreElement: 534 case IrOpcode::kStoreElement:
602 ProcessStoreElement(node); 535 ProcessStoreElement(node);
603 break; 536 break;
604 case IrOpcode::kLoadField: 537 case IrOpcode::kLoadField:
605 case IrOpcode::kLoadElement: { 538 case IrOpcode::kLoadElement: {
606 if (Node* rep = object_analysis_->GetReplacement(node, node->id())) { 539 if (Node* rep = object_analysis_->GetReplacement(node)) {
607 if (IsAllocation(rep) && CheckUsesForEscape(node, rep)) { 540 if (IsAllocation(rep) && CheckUsesForEscape(node, rep)) {
608 RevisitInputs(rep); 541 RevisitInputs(rep);
609 RevisitUses(rep); 542 RevisitUses(rep);
610 } 543 }
611 } 544 }
612 break; 545 break;
613 } 546 }
614 case IrOpcode::kPhi: 547 case IrOpcode::kPhi:
615 if (!HasEntry(node)) { 548 if (!HasEntry(node)) {
616 info_[node->id()] = kVirtual; 549 info_[node->id()] = kVirtual;
(...skipping 152 matching lines...) Expand 10 before | Expand all | Expand 10 after
769 702
770 // -----------------------------EscapeAnalysis---------------------------------- 703 // -----------------------------EscapeAnalysis----------------------------------
771 704
772 705
773 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, 706 EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common,
774 Zone* zone) 707 Zone* zone)
775 : graph_(graph), 708 : graph_(graph),
776 common_(common), 709 common_(common),
777 zone_(zone), 710 zone_(zone),
778 virtual_states_(zone), 711 virtual_states_(zone),
712 replacements_(zone),
779 escape_status_(this, graph, zone), 713 escape_status_(this, graph, zone),
780 cache_(zone) {} 714 cache_(zone) {}
781 715
782 716
783 EscapeAnalysis::~EscapeAnalysis() {} 717 EscapeAnalysis::~EscapeAnalysis() {}
784 718
785 719
786 void EscapeAnalysis::Run() { 720 void EscapeAnalysis::Run() {
721 replacements_.resize(graph()->NodeCount());
787 RunObjectAnalysis(); 722 RunObjectAnalysis();
788 escape_status_.Run(); 723 escape_status_.Run();
789 } 724 }
790 725
791 726
792 void EscapeAnalysis::RunObjectAnalysis() { 727 void EscapeAnalysis::RunObjectAnalysis() {
793 virtual_states_.resize(graph()->NodeCount()); 728 virtual_states_.resize(graph()->NodeCount());
794 ZoneVector<Node*> stack(zone()); 729 ZoneVector<Node*> stack(zone());
795 stack.push_back(graph()->start()); 730 stack.push_back(graph()->start());
796 while (!stack.empty()) { 731 while (!stack.empty()) {
(...skipping 101 matching lines...) Expand 10 before | Expand all | Expand 10 after
898 case IrOpcode::kLoadField: 833 case IrOpcode::kLoadField:
899 case IrOpcode::kStoreElement: 834 case IrOpcode::kStoreElement:
900 case IrOpcode::kLoadElement: 835 case IrOpcode::kLoadElement:
901 case IrOpcode::kFrameState: 836 case IrOpcode::kFrameState:
902 case IrOpcode::kStateValues: 837 case IrOpcode::kStateValues:
903 case IrOpcode::kReferenceEqual: 838 case IrOpcode::kReferenceEqual:
904 case IrOpcode::kFinishRegion: 839 case IrOpcode::kFinishRegion:
905 case IrOpcode::kPhi: 840 case IrOpcode::kPhi:
906 break; 841 break;
907 default: 842 default:
908 VirtualState* states = virtual_states_[node->id()]; 843 VirtualState* state = virtual_states_[node->id()];
909 if (VirtualObject* obj = states->ResolveVirtualObject(input)) { 844 if (VirtualObject* obj = ResolveVirtualObject(state, input)) {
910 if (obj->ClearAllFields()) { 845 if (obj->ClearAllFields()) {
911 states->LastChangedAt(node); 846 state->LastChangedAt(node);
912 } 847 }
913 } 848 }
914 break; 849 break;
915 } 850 }
916 } 851 }
917 } 852 }
918 853
919 854
920 bool EscapeAnalysis::IsEffectBranchPoint(Node* node) { 855 bool EscapeAnalysis::IsEffectBranchPoint(Node* node) {
921 int count = 0; 856 int count = 0;
(...skipping 148 matching lines...) Expand 10 before | Expand all | Expand 10 after
1070 if (FLAG_trace_turbo_escape) { 1005 if (FLAG_trace_turbo_escape) {
1071 PrintF("Linked finish region node #%d to node #%d\n", node->id(), 1006 PrintF("Linked finish region node #%d to node #%d\n", node->id(),
1072 allocation->id()); 1007 allocation->id());
1073 } 1008 }
1074 states->LastChangedAt(node); 1009 states->LastChangedAt(node);
1075 } 1010 }
1076 } 1011 }
1077 } 1012 }
1078 1013
1079 1014
1080 Node* EscapeAnalysis::GetReplacement(Node* at, NodeId id) { 1015 Node* EscapeAnalysis::replacement(NodeId id) {
1081 VirtualState* states = virtual_states_[at->id()]; 1016 if (id >= replacements_.size()) return nullptr;
1082 if (VirtualObject* obj = states->GetVirtualObject(id)) { 1017 return replacements_[id];
1083 return obj->GetReplacement();
1084 }
1085 return nullptr;
1086 } 1018 }
1087 1019
1088 1020
1021 Node* EscapeAnalysis::replacement(Node* node) {
1022 return replacement(node->id());
1023 }
1024
1025
1026 bool EscapeAnalysis::SetReplacement(Node* node, Node* rep) {
1027 bool changed = replacements_[node->id()] != rep;
1028 replacements_[node->id()] = rep;
1029 return changed;
1030 }
1031
1032
1033 bool EscapeAnalysis::UpdateReplacement(VirtualState* state, Node* node,
1034 Node* rep) {
1035 if (SetReplacement(node, rep)) {
1036 state->LastChangedAt(node);
1037 if (FLAG_trace_turbo_escape) {
1038 if (rep) {
1039 PrintF("Replacement of #%d is #%d (%s)\n", node->id(), rep->id(),
1040 rep->op()->mnemonic());
1041 } else {
1042 PrintF("Replacement of #%d cleared\n", node->id());
1043 }
1044 }
1045 return true;
1046 }
1047 return false;
1048 }
1049
1050
1051 Node* EscapeAnalysis::ResolveReplacement(Node* node) {
1052 while (replacement(node)) {
1053 node = replacement(node);
1054 }
1055 return node;
1056 }
1057
1058
1059 Node* EscapeAnalysis::GetReplacement(Node* node) {
1060 return GetReplacement(node->id());
1061 }
1062
1063
1064 Node* EscapeAnalysis::GetReplacement(NodeId id) {
1065 Node* node = nullptr;
1066 while (replacement(id)) {
1067 node = replacement(id);
1068 id = node->id();
1069 }
1070 return node;
1071 }
1072
1073
1089 bool EscapeAnalysis::IsVirtual(Node* node) { 1074 bool EscapeAnalysis::IsVirtual(Node* node) {
1090 return escape_status_.IsVirtual(node); 1075 return escape_status_.IsVirtual(node);
1091 } 1076 }
1092 1077
1093 1078
1094 bool EscapeAnalysis::IsEscaped(Node* node) { 1079 bool EscapeAnalysis::IsEscaped(Node* node) {
1095 return escape_status_.IsEscaped(node); 1080 return escape_status_.IsEscaped(node);
1096 } 1081 }
1097 1082
1098 1083
1099 bool EscapeAnalysis::SetEscaped(Node* node) { 1084 bool EscapeAnalysis::SetEscaped(Node* node) {
1100 return escape_status_.SetEscaped(node); 1085 return escape_status_.SetEscaped(node);
1101 } 1086 }
1102 1087
1103 1088
1104 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) { 1089 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) {
1105 if (VirtualState* states = virtual_states_[at->id()]) { 1090 if (VirtualState* states = virtual_states_[at->id()]) {
1106 return states->GetVirtualObject(id); 1091 return states->GetVirtualObject(id);
1107 } 1092 }
1108 return nullptr; 1093 return nullptr;
1109 } 1094 }
1110 1095
1111 1096
1097 VirtualObject* EscapeAnalysis::ResolveVirtualObject(VirtualState* state,
1098 Node* node) {
1099 VirtualObject* obj = state->GetVirtualObject(ResolveReplacement(node));
1100 while (obj && replacement(obj->id()) &&
1101 state->GetVirtualObject(replacement(obj->id()))) {
1102 obj = state->GetVirtualObject(replacement(obj->id()));
1103 }
1104 return obj;
1105 }
1106
1107
1112 int EscapeAnalysis::OffsetFromAccess(Node* node) { 1108 int EscapeAnalysis::OffsetFromAccess(Node* node) {
1113 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0); 1109 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0);
1114 return OpParameter<FieldAccess>(node).offset / kPointerSize; 1110 return OpParameter<FieldAccess>(node).offset / kPointerSize;
1115 } 1111 }
1116 1112
1117 1113
1118 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node, 1114 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node,
1119 VirtualState* state) { 1115 VirtualState* state) {
1120 if (FLAG_trace_turbo_escape) { 1116 if (FLAG_trace_turbo_escape) {
1121 PrintF("Load #%d from phi #%d", node->id(), from->id()); 1117 PrintF("Load #%d from phi #%d", node->id(), from->id());
1122 } 1118 }
1123 1119
1124 ZoneVector<Node*> inputs(zone()); 1120 ZoneVector<Node*> inputs(zone());
1125 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { 1121 for (int i = 0; i < node->op()->ValueInputCount(); ++i) {
1126 Node* input = NodeProperties::GetValueInput(node, i); 1122 Node* input = NodeProperties::GetValueInput(node, i);
1127 inputs.push_back(input); 1123 inputs.push_back(input);
1128 } 1124 }
1129 1125
1130 GetVirtualObjects(state, inputs, cache_.objects()); 1126 GetVirtualObjects(state, inputs, cache_.objects());
1131 if (cache_.objects().size() == inputs.size()) { 1127 if (cache_.objects().size() == inputs.size()) {
1132 GetFields(cache_.objects(), cache_.fields(), offset); 1128 GetFields(cache_.objects(), cache_.fields(), offset);
1133 if (cache_.fields().size() == cache_.objects().size()) { 1129 if (cache_.fields().size() == cache_.objects().size()) {
1134 if (!state->GetVirtualObject(node)) { 1130 Node* rep = replacement(node);
1135 state->SetVirtualObject(node->id(),
1136 new (zone()) VirtualObject(node->id(), zone()));
1137 }
1138 Node* rep = state->GetVirtualObject(node)->GetReplacement();
1139 if (!rep || !IsEquivalentPhi(rep, cache_.fields())) { 1131 if (!rep || !IsEquivalentPhi(rep, cache_.fields())) {
1140 cache_.fields().push_back(NodeProperties::GetControlInput(from)); 1132 cache_.fields().push_back(NodeProperties::GetControlInput(from));
1141 Node* phi = graph()->NewNode( 1133 Node* phi = graph()->NewNode(
1142 common()->Phi(MachineRepresentation::kTagged, 2), 1134 common()->Phi(MachineRepresentation::kTagged, 2),
1143 static_cast<int>(cache_.fields().size()), &cache_.fields().front()); 1135 static_cast<int>(cache_.fields().size()), &cache_.fields().front());
1144 state->GetVirtualObject(node)->SetReplacement(phi); 1136 SetReplacement(node, phi);
1145 state->LastChangedAt(node); 1137 state->LastChangedAt(node);
1146 if (FLAG_trace_turbo_escape) { 1138 if (FLAG_trace_turbo_escape) {
1147 PrintF(" got phi created.\n"); 1139 PrintF(" got phi created.\n");
1148 } 1140 }
1149 } else if (FLAG_trace_turbo_escape) { 1141 } else if (FLAG_trace_turbo_escape) {
1150 PrintF(" has already phi #%d.\n", rep->id()); 1142 PrintF(" has already phi #%d.\n", rep->id());
1151 } 1143 }
1152 } else if (FLAG_trace_turbo_escape) { 1144 } else if (FLAG_trace_turbo_escape) {
1153 PrintF(" has incomplete field info.\n"); 1145 PrintF(" has incomplete field info.\n");
1154 } 1146 }
1155 } else if (FLAG_trace_turbo_escape) { 1147 } else if (FLAG_trace_turbo_escape) {
1156 PrintF(" has incomplete virtual object info.\n"); 1148 PrintF(" has incomplete virtual object info.\n");
1157 } 1149 }
1158 } 1150 }
1159 1151
1160 1152
1161 void EscapeAnalysis::ProcessLoadField(Node* node) { 1153 void EscapeAnalysis::ProcessLoadField(Node* node) {
1162 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField); 1154 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField);
1163 ForwardVirtualState(node); 1155 ForwardVirtualState(node);
1164 Node* from = NodeProperties::GetValueInput(node, 0); 1156 Node* from = NodeProperties::GetValueInput(node, 0);
1165 VirtualState* state = virtual_states_[node->id()]; 1157 VirtualState* state = virtual_states_[node->id()];
1166 if (VirtualObject* object = state->ResolveVirtualObject(from)) { 1158 if (VirtualObject* object = ResolveVirtualObject(state, from)) {
1167 int offset = OffsetFromAccess(node); 1159 int offset = OffsetFromAccess(node);
1168 if (!object->IsTracked()) return; 1160 if (!object->IsTracked()) return;
1169 Node* value = object->GetField(offset); 1161 Node* value = object->GetField(offset);
1170 if (value) { 1162 if (value) {
1171 value = state->ResolveReplacement(value); 1163 value = ResolveReplacement(value);
1172 } 1164 }
1173 // Record that the load has this alias. 1165 // Record that the load has this alias.
1174 state->UpdateReplacement(node, value, zone()); 1166 UpdateReplacement(state, node, value);
1175 } else { 1167 } else {
1176 if (from->opcode() == IrOpcode::kPhi) { 1168 if (from->opcode() == IrOpcode::kPhi &&
1169 OpParameter<FieldAccess>(node).offset % kPointerSize == 0) {
1177 int offset = OffsetFromAccess(node); 1170 int offset = OffsetFromAccess(node);
1178 // Only binary phis are supported for now. 1171 // Only binary phis are supported for now.
1179 ProcessLoadFromPhi(offset, from, node, state); 1172 ProcessLoadFromPhi(offset, from, node, state);
1180 } 1173 }
1181 } 1174 }
1182 } 1175 }
1183 1176
1184 1177
1185 void EscapeAnalysis::ProcessLoadElement(Node* node) { 1178 void EscapeAnalysis::ProcessLoadElement(Node* node) {
1186 DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement); 1179 DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement);
1187 ForwardVirtualState(node); 1180 ForwardVirtualState(node);
1188 Node* from = NodeProperties::GetValueInput(node, 0); 1181 Node* from = NodeProperties::GetValueInput(node, 0);
1189 VirtualState* state = virtual_states_[node->id()]; 1182 VirtualState* state = virtual_states_[node->id()];
1190 Node* index_node = node->InputAt(1); 1183 Node* index_node = node->InputAt(1);
1191 NumberMatcher index(index_node); 1184 NumberMatcher index(index_node);
1192 ElementAccess access = OpParameter<ElementAccess>(node); 1185 ElementAccess access = OpParameter<ElementAccess>(node);
1193 if (index.HasValue()) { 1186 if (index.HasValue()) {
1194 int offset = index.Value() + access.header_size / kPointerSize; 1187 int offset = index.Value() + access.header_size / kPointerSize;
1195 if (VirtualObject* object = state->ResolveVirtualObject(from)) { 1188 if (VirtualObject* object = ResolveVirtualObject(state, from)) {
1196 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()), 1189 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()),
1197 kPointerSizeLog2); 1190 kPointerSizeLog2);
1198 CHECK_EQ(access.header_size % kPointerSize, 0); 1191 CHECK_EQ(access.header_size % kPointerSize, 0);
1199 1192
1200 if (!object->IsTracked()) return; 1193 if (!object->IsTracked()) return;
1201 Node* value = object->GetField(offset); 1194 Node* value = object->GetField(offset);
1202 if (value) { 1195 if (value) {
1203 value = state->ResolveReplacement(value); 1196 value = ResolveReplacement(value);
1204 } 1197 }
1205 // Record that the load has this alias. 1198 // Record that the load has this alias.
1206 state->UpdateReplacement(node, value, zone()); 1199 UpdateReplacement(state, node, value);
1207 } else if (from->opcode() == IrOpcode::kPhi) { 1200 } else if (from->opcode() == IrOpcode::kPhi) {
1208 ElementAccess access = OpParameter<ElementAccess>(node); 1201 ElementAccess access = OpParameter<ElementAccess>(node);
1209 int offset = index.Value() + access.header_size / kPointerSize; 1202 int offset = index.Value() + access.header_size / kPointerSize;
1210 ProcessLoadFromPhi(offset, from, node, state); 1203 ProcessLoadFromPhi(offset, from, node, state);
1211 } 1204 }
1212 } else { 1205 } else {
1213 // We have a load from a non-const index, cannot eliminate object. 1206 // We have a load from a non-const index, cannot eliminate object.
1214 if (SetEscaped(from)) { 1207 if (SetEscaped(from)) {
1215 if (FLAG_trace_turbo_escape) { 1208 if (FLAG_trace_turbo_escape) {
1216 PrintF( 1209 PrintF(
1217 "Setting #%d (%s) to escaped because store element #%d to " 1210 "Setting #%d (%s) to escaped because store element #%d to "
1218 "non-const " 1211 "non-const "
1219 "index #%d (%s)\n", 1212 "index #%d (%s)\n",
1220 from->id(), from->op()->mnemonic(), node->id(), index_node->id(), 1213 from->id(), from->op()->mnemonic(), node->id(), index_node->id(),
1221 index_node->op()->mnemonic()); 1214 index_node->op()->mnemonic());
1222 } 1215 }
1223 } 1216 }
1224 } 1217 }
1225 } 1218 }
1226 1219
1227 1220
1228 void EscapeAnalysis::ProcessStoreField(Node* node) { 1221 void EscapeAnalysis::ProcessStoreField(Node* node) {
1229 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField); 1222 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField);
1230 ForwardVirtualState(node); 1223 ForwardVirtualState(node);
1231 Node* to = NodeProperties::GetValueInput(node, 0); 1224 Node* to = NodeProperties::GetValueInput(node, 0);
1232 Node* val = NodeProperties::GetValueInput(node, 1); 1225 Node* val = NodeProperties::GetValueInput(node, 1);
1233 int offset = OffsetFromAccess(node); 1226 VirtualState* state = virtual_states_[node->id()];
1234 VirtualState* states = virtual_states_[node->id()]; 1227 if (VirtualObject* obj = ResolveVirtualObject(state, to)) {
1235 if (VirtualObject* obj = states->ResolveVirtualObject(to)) {
1236 if (!obj->IsTracked()) return; 1228 if (!obj->IsTracked()) return;
1237 if (obj->SetField(offset, states->ResolveReplacement(val))) { 1229 int offset = OffsetFromAccess(node);
1238 states->LastChangedAt(node); 1230 if (obj->SetField(offset, ResolveReplacement(val))) {
1231 state->LastChangedAt(node);
1239 } 1232 }
1240 } 1233 }
1241 } 1234 }
1242 1235
1243 1236
1244 void EscapeAnalysis::ProcessStoreElement(Node* node) { 1237 void EscapeAnalysis::ProcessStoreElement(Node* node) {
1245 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement); 1238 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement);
1246 ForwardVirtualState(node); 1239 ForwardVirtualState(node);
1247 Node* to = NodeProperties::GetValueInput(node, 0); 1240 Node* to = NodeProperties::GetValueInput(node, 0);
1248 Node* index_node = node->InputAt(1); 1241 Node* index_node = node->InputAt(1);
1249 NumberMatcher index(index_node); 1242 NumberMatcher index(index_node);
1250 ElementAccess access = OpParameter<ElementAccess>(node); 1243 ElementAccess access = OpParameter<ElementAccess>(node);
1251 Node* val = NodeProperties::GetValueInput(node, 2); 1244 Node* val = NodeProperties::GetValueInput(node, 2);
1252 if (index.HasValue()) { 1245 if (index.HasValue()) {
1253 int offset = index.Value() + access.header_size / kPointerSize; 1246 int offset = index.Value() + access.header_size / kPointerSize;
1254 VirtualState* states = virtual_states_[node->id()]; 1247 VirtualState* states = virtual_states_[node->id()];
1255 if (VirtualObject* obj = states->ResolveVirtualObject(to)) { 1248 if (VirtualObject* obj = ResolveVirtualObject(states, to)) {
1256 if (!obj->IsTracked()) return; 1249 if (!obj->IsTracked()) return;
1257 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()), 1250 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()),
1258 kPointerSizeLog2); 1251 kPointerSizeLog2);
1259 CHECK_EQ(access.header_size % kPointerSize, 0); 1252 CHECK_EQ(access.header_size % kPointerSize, 0);
1260 if (obj->SetField(offset, states->ResolveReplacement(val))) { 1253 if (obj->SetField(offset, ResolveReplacement(val))) {
1261 states->LastChangedAt(node); 1254 states->LastChangedAt(node);
1262 } 1255 }
1263 } 1256 }
1264 } else { 1257 } else {
1265 // We have a store to a non-const index, cannot eliminate object. 1258 // We have a store to a non-const index, cannot eliminate object.
1266 if (SetEscaped(to)) { 1259 if (SetEscaped(to)) {
1267 if (FLAG_trace_turbo_escape) { 1260 if (FLAG_trace_turbo_escape) {
1268 PrintF( 1261 PrintF(
1269 "Setting #%d (%s) to escaped because store element #%d to " 1262 "Setting #%d (%s) to escaped because store element #%d to "
1270 "non-const " 1263 "non-const "
1271 "index #%d (%s)\n", 1264 "index #%d (%s)\n",
1272 to->id(), to->op()->mnemonic(), node->id(), index_node->id(), 1265 to->id(), to->op()->mnemonic(), node->id(), index_node->id(),
1273 index_node->op()->mnemonic()); 1266 index_node->op()->mnemonic());
1274 } 1267 }
1275 } 1268 }
1276 } 1269 }
1277 } 1270 }
1278 1271
1279 1272
1280 void EscapeAnalysis::DebugPrintObject(VirtualObject* object, NodeId id) { 1273 void EscapeAnalysis::DebugPrintObject(VirtualObject* object, NodeId id) {
1281 PrintF(" Object #%d with %zu fields", id, object->field_count()); 1274 PrintF(" Object #%d with %zu fields\n", id, object->field_count());
1282 if (Node* rep = object->GetReplacement()) {
1283 PrintF(", rep = #%d (%s)", rep->id(), rep->op()->mnemonic());
1284 }
1285 PrintF("\n");
1286 for (size_t i = 0; i < object->field_count(); ++i) { 1275 for (size_t i = 0; i < object->field_count(); ++i) {
1287 if (Node* f = object->GetField(i)) { 1276 if (Node* f = object->GetField(i)) {
1288 PrintF(" Field %zu = #%d (%s)\n", i, f->id(), f->op()->mnemonic()); 1277 PrintF(" Field %zu = #%d (%s)\n", i, f->id(), f->op()->mnemonic());
1289 } 1278 }
1290 } 1279 }
1291 } 1280 }
1292 1281
1293 1282
1294 void EscapeAnalysis::DebugPrintState(VirtualState* state) { 1283 void EscapeAnalysis::DebugPrintState(VirtualState* state) {
1295 PrintF("Dumping object state %p\n", static_cast<void*>(state)); 1284 PrintF("Dumping object state %p\n", static_cast<void*>(state));
(...skipping 20 matching lines...) Expand all
1316 } 1305 }
1317 } 1306 }
1318 for (size_t n = 0; n < object_states.size(); n++) { 1307 for (size_t n = 0; n < object_states.size(); n++) {
1319 DebugPrintState(object_states[n]); 1308 DebugPrintState(object_states[n]);
1320 } 1309 }
1321 } 1310 }
1322 1311
1323 } // namespace compiler 1312 } // namespace compiler
1324 } // namespace internal 1313 } // namespace internal
1325 } // namespace v8 1314 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/escape-analysis.h ('k') | src/compiler/escape-analysis-reducer.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698