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

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

Issue 1583213003: [turbofan] Fix bugs in escape analysis. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: Unstage Created 4 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 | « src/compiler/escape-analysis.h ('k') | src/compiler/escape-analysis-reducer.h » ('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 <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 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
117 Status status_; 117 Status status_;
118 ZoneVector<Node*> fields_; 118 ZoneVector<Node*> fields_;
119 ZoneVector<bool> phi_; 119 ZoneVector<bool> phi_;
120 Node* object_state_; 120 Node* object_state_;
121 }; 121 };
122 122
123 123
124 bool VirtualObject::UpdateFrom(const VirtualObject& other) { 124 bool VirtualObject::UpdateFrom(const VirtualObject& other) {
125 bool changed = status_ != other.status_; 125 bool changed = status_ != other.status_;
126 status_ = other.status_; 126 status_ = other.status_;
127 phi_ = other.phi_;
127 if (fields_.size() != other.fields_.size()) { 128 if (fields_.size() != other.fields_.size()) {
128 fields_ = other.fields_; 129 fields_ = other.fields_;
129 return true; 130 return true;
130 } 131 }
131 for (size_t i = 0; i < fields_.size(); ++i) { 132 for (size_t i = 0; i < fields_.size(); ++i) {
132 if (fields_[i] != other.fields_[i]) { 133 if (fields_[i] != other.fields_[i]) {
133 changed = true; 134 changed = true;
134 fields_[i] = other.fields_[i]; 135 fields_[i] = other.fields_[i];
135 } 136 }
136 } 137 }
137 return changed; 138 return changed;
138 } 139 }
139 140
140 141
141 class VirtualState : public ZoneObject { 142 class VirtualState : public ZoneObject {
142 public: 143 public:
143 VirtualState(Zone* zone, size_t size); 144 VirtualState(Zone* zone, size_t size);
144 VirtualState(const VirtualState& states); 145 VirtualState(const VirtualState& states);
145 146
146 VirtualObject* VirtualObjectFromAlias(size_t alias); 147 VirtualObject* VirtualObjectFromAlias(size_t alias);
147 VirtualObject* GetOrCreateTrackedVirtualObject(EscapeAnalysis::Alias alias, 148 VirtualObject* GetOrCreateTrackedVirtualObject(EscapeAnalysis::Alias alias,
148 NodeId id, Zone* zone); 149 NodeId id, size_t fields,
150 Zone* zone);
149 void SetVirtualObject(EscapeAnalysis::Alias alias, VirtualObject* state); 151 void SetVirtualObject(EscapeAnalysis::Alias alias, VirtualObject* state);
150 void LastChangedAt(Node* node) { last_changed_ = node; } 152 void LastChangedAt(Node* node) { last_changed_ = node; }
151 Node* GetLastChanged() { return last_changed_; } 153 Node* GetLastChanged() { return last_changed_; }
152 bool UpdateFrom(VirtualState* state, Zone* zone); 154 bool UpdateFrom(VirtualState* state, Zone* zone);
153 bool MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, 155 bool MergeFrom(MergeCache* cache, Zone* zone, Graph* graph,
154 CommonOperatorBuilder* common, Node* control); 156 CommonOperatorBuilder* common, Node* control);
155 size_t size() const { return info_.size(); } 157 size_t size() const { return info_.size(); }
156 158
157 private: 159 private:
158 ZoneVector<VirtualObject*> info_; 160 ZoneVector<VirtualObject*> info_;
(...skipping 89 matching lines...) Expand 10 before | Expand all | Expand 10 after
248 } 250 }
249 } 251 }
250 252
251 253
252 VirtualObject* VirtualState::VirtualObjectFromAlias(size_t alias) { 254 VirtualObject* VirtualState::VirtualObjectFromAlias(size_t alias) {
253 return info_[alias]; 255 return info_[alias];
254 } 256 }
255 257
256 258
257 VirtualObject* VirtualState::GetOrCreateTrackedVirtualObject( 259 VirtualObject* VirtualState::GetOrCreateTrackedVirtualObject(
258 EscapeAnalysis::Alias alias, NodeId id, Zone* zone) { 260 EscapeAnalysis::Alias alias, NodeId id, size_t field_number, Zone* zone) {
259 if (VirtualObject* obj = VirtualObjectFromAlias(alias)) { 261 if (VirtualObject* obj = VirtualObjectFromAlias(alias)) {
260 return obj; 262 return obj;
261 } 263 }
262 VirtualObject* obj = new (zone) VirtualObject(id, zone, 0); 264 VirtualObject* obj = new (zone) VirtualObject(id, zone, 0);
263 SetVirtualObject(alias, obj); 265 SetVirtualObject(alias, obj);
264 return obj; 266 return obj;
265 } 267 }
266 268
267 269
268 void VirtualState::SetVirtualObject(EscapeAnalysis::Alias alias, 270 void VirtualState::SetVirtualObject(EscapeAnalysis::Alias alias,
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
349 CommonOperatorBuilder* common, Node* control) { 351 CommonOperatorBuilder* common, Node* control) {
350 DCHECK_GT(cache->states().size(), 0u); 352 DCHECK_GT(cache->states().size(), 0u);
351 bool changed = false; 353 bool changed = false;
352 for (EscapeAnalysis::Alias alias = 0; alias < size(); ++alias) { 354 for (EscapeAnalysis::Alias alias = 0; alias < size(); ++alias) {
353 size_t fields = cache->LoadVirtualObjectsFromStatesFor(alias); 355 size_t fields = cache->LoadVirtualObjectsFromStatesFor(alias);
354 if (cache->objects().size() == cache->states().size()) { 356 if (cache->objects().size() == cache->states().size()) {
355 if (FLAG_trace_turbo_escape) { 357 if (FLAG_trace_turbo_escape) {
356 PrintF(" Merging virtual objects of @%d\n", alias); 358 PrintF(" Merging virtual objects of @%d\n", alias);
357 } 359 }
358 VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject( 360 VirtualObject* mergeObject = GetOrCreateTrackedVirtualObject(
359 alias, cache->objects().front()->id(), zone); 361 alias, cache->objects().front()->id(), fields, zone);
360 changed = mergeObject->ResizeFields(fields) || changed; 362 changed = mergeObject->ResizeFields(fields) || changed;
361 for (size_t i = 0; i < fields; ++i) { 363 for (size_t i = 0; i < fields; ++i) {
362 if (Node* field = cache->GetFields(i)) { 364 if (Node* field = cache->GetFields(i)) {
363 changed = mergeObject->SetField(i, field) || changed; 365 changed = mergeObject->SetField(i, field) || changed;
364 if (FLAG_trace_turbo_escape) { 366 if (FLAG_trace_turbo_escape) {
365 PrintF(" Field %zu agree on rep #%d\n", i, field->id()); 367 PrintF(" Field %zu agree on rep #%d\n", i, field->id());
366 } 368 }
367 } else { 369 } else {
368 int value_input_count = static_cast<int>(cache->fields().size()); 370 int value_input_count = static_cast<int>(cache->fields().size());
369 if (cache->fields().size() == cache->objects().size()) { 371 if (cache->fields().size() == cache->objects().size()) {
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
403 if (FLAG_trace_turbo_escape) { 405 if (FLAG_trace_turbo_escape) {
404 PrintF(" Widening Phi #%d of arity %d to %d", rep->id(), 406 PrintF(" Widening Phi #%d of arity %d to %d", rep->id(),
405 rep->op()->ValueInputCount(), value_input_count); 407 rep->op()->ValueInputCount(), value_input_count);
406 } 408 }
407 NodeProperties::ChangeOp( 409 NodeProperties::ChangeOp(
408 rep, common->Phi(MachineRepresentation::kTagged, 410 rep, common->Phi(MachineRepresentation::kTagged,
409 value_input_count)); 411 value_input_count));
410 } 412 }
411 } 413 }
412 } else { 414 } else {
415 if (FLAG_trace_turbo_escape) {
416 PrintF(" Field %zu cleared\n", i);
417 }
413 changed = mergeObject->SetField(i, nullptr) || changed; 418 changed = mergeObject->SetField(i, nullptr) || changed;
414 } 419 }
415 } 420 }
416 } 421 }
417 } else { 422 } else {
418 SetVirtualObject(alias, nullptr); 423 SetVirtualObject(alias, nullptr);
419 } 424 }
420 } 425 }
421 return changed; 426 return changed;
422 } 427 }
(...skipping 10 matching lines...) Expand all
433 438
434 EscapeStatusAnalysis::~EscapeStatusAnalysis() {} 439 EscapeStatusAnalysis::~EscapeStatusAnalysis() {}
435 440
436 441
437 bool EscapeStatusAnalysis::HasEntry(Node* node) { 442 bool EscapeStatusAnalysis::HasEntry(Node* node) {
438 return status_[node->id()] & (kTracked | kEscaped); 443 return status_[node->id()] & (kTracked | kEscaped);
439 } 444 }
440 445
441 446
442 bool EscapeStatusAnalysis::IsVirtual(Node* node) { 447 bool EscapeStatusAnalysis::IsVirtual(Node* node) {
443 return (status_[node->id()] & kTracked) && !(status_[node->id()] & kEscaped); 448 return IsVirtual(node->id());
444 } 449 }
445 450
446 451
452 bool EscapeStatusAnalysis::IsVirtual(NodeId id) {
453 return (status_[id] & kTracked) && !(status_[id] & kEscaped);
454 }
455
456
447 bool EscapeStatusAnalysis::IsEscaped(Node* node) { 457 bool EscapeStatusAnalysis::IsEscaped(Node* node) {
448 return status_[node->id()] & kEscaped; 458 return status_[node->id()] & kEscaped;
449 } 459 }
450 460
451 461
452 bool EscapeStatusAnalysis::IsAllocation(Node* node) { 462 bool EscapeStatusAnalysis::IsAllocation(Node* node) {
453 return node->opcode() == IrOpcode::kAllocate || 463 return node->opcode() == IrOpcode::kAllocate ||
454 node->opcode() == IrOpcode::kFinishRegion; 464 node->opcode() == IrOpcode::kFinishRegion;
455 } 465 }
456 466
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after
662 } 672 }
663 break; 673 break;
664 case IrOpcode::kObjectIsSmi: 674 case IrOpcode::kObjectIsSmi:
665 if (!IsAllocation(rep) && SetEscaped(rep)) { 675 if (!IsAllocation(rep) && SetEscaped(rep)) {
666 PrintF("Setting #%d (%s) to escaped because of use by #%d (%s)\n", 676 PrintF("Setting #%d (%s) to escaped because of use by #%d (%s)\n",
667 rep->id(), rep->op()->mnemonic(), use->id(), 677 rep->id(), rep->op()->mnemonic(), use->id(),
668 use->op()->mnemonic()); 678 use->op()->mnemonic());
669 return true; 679 return true;
670 } 680 }
671 break; 681 break;
682 case IrOpcode::kSelect:
683 if (SetEscaped(rep)) {
684 PrintF("Setting #%d (%s) to escaped because of use by #%d (%s)\n",
685 rep->id(), rep->op()->mnemonic(), use->id(),
686 use->op()->mnemonic());
687 return true;
688 }
689 break;
672 default: 690 default:
673 if (use->op()->EffectInputCount() == 0 && 691 if (use->op()->EffectInputCount() == 0 &&
674 uses->op()->EffectInputCount() > 0) { 692 uses->op()->EffectInputCount() > 0) {
675 PrintF("Encountered unaccounted use by #%d (%s)\n", use->id(), 693 PrintF("Encountered unaccounted use by #%d (%s)\n", use->id(),
676 use->op()->mnemonic()); 694 use->op()->mnemonic());
677 UNREACHABLE(); 695 UNREACHABLE();
678 } 696 }
679 if (SetEscaped(rep)) { 697 if (SetEscaped(rep)) {
680 if (FLAG_trace_turbo_escape) { 698 if (FLAG_trace_turbo_escape) {
681 PrintF("Setting #%d (%s) to escaped because of use by #%d (%s)\n", 699 PrintF("Setting #%d (%s) to escaped because of use by #%d (%s)\n",
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
724 aliases_(zone), 742 aliases_(zone),
725 next_free_alias_(0) {} 743 next_free_alias_(0) {}
726 744
727 745
728 EscapeAnalysis::~EscapeAnalysis() {} 746 EscapeAnalysis::~EscapeAnalysis() {}
729 747
730 748
731 void EscapeAnalysis::Run() { 749 void EscapeAnalysis::Run() {
732 replacements_.resize(graph()->NodeCount()); 750 replacements_.resize(graph()->NodeCount());
733 AssignAliases(); 751 AssignAliases();
752 if (AliasCount() == 0) return;
753 escape_status_.Resize();
734 RunObjectAnalysis(); 754 RunObjectAnalysis();
735 escape_status_.Run(); 755 escape_status_.Run();
736 } 756 }
737 757
738 758
739 void EscapeAnalysis::AssignAliases() { 759 void EscapeAnalysis::AssignAliases() {
740 ZoneVector<Node*> stack(zone()); 760 ZoneVector<Node*> stack(zone());
741 stack.push_back(graph()->end()); 761 stack.push_back(graph()->end());
742 CHECK_LT(graph()->NodeCount(), kUntrackable); 762 CHECK_LT(graph()->NodeCount(), kUntrackable);
743 aliases_.resize(graph()->NodeCount(), kNotReachable); 763 aliases_.resize(graph()->NodeCount(), kNotReachable);
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
1035 mergeState->LastChangedAt(node); 1055 mergeState->LastChangedAt(node);
1036 escape_status_.Resize(); 1056 escape_status_.Resize();
1037 } 1057 }
1038 return changed; 1058 return changed;
1039 } 1059 }
1040 1060
1041 1061
1042 void EscapeAnalysis::ProcessAllocation(Node* node) { 1062 void EscapeAnalysis::ProcessAllocation(Node* node) {
1043 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); 1063 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate);
1044 ForwardVirtualState(node); 1064 ForwardVirtualState(node);
1065 VirtualState* state = virtual_states_[node->id()];
1066 Alias alias = aliases_[node->id()];
1045 1067
1046 // Check if we have already processed this node. 1068 // Check if we have already processed this node.
1047 if (virtual_states_[node->id()]->VirtualObjectFromAlias( 1069 if (state->VirtualObjectFromAlias(alias)) {
1048 aliases_[node->id()])) {
1049 return; 1070 return;
1050 } 1071 }
1051 1072
1052 NumberMatcher size(node->InputAt(0)); 1073 NumberMatcher size(node->InputAt(0));
1053 DCHECK(node->InputAt(0)->opcode() != IrOpcode::kInt32Constant && 1074 DCHECK(node->InputAt(0)->opcode() != IrOpcode::kInt32Constant &&
1054 node->InputAt(0)->opcode() != IrOpcode::kInt64Constant && 1075 node->InputAt(0)->opcode() != IrOpcode::kInt64Constant &&
1055 node->InputAt(0)->opcode() != IrOpcode::kFloat32Constant && 1076 node->InputAt(0)->opcode() != IrOpcode::kFloat32Constant &&
1056 node->InputAt(0)->opcode() != IrOpcode::kFloat64Constant); 1077 node->InputAt(0)->opcode() != IrOpcode::kFloat64Constant);
1057 if (size.HasValue()) { 1078 if (size.HasValue()) {
1058 virtual_states_[node->id()]->SetVirtualObject( 1079 state->SetVirtualObject(
1059 aliases_[node->id()], 1080 alias, new (zone()) VirtualObject(node->id(), zone(),
1060 new (zone()) 1081 size.Value() / kPointerSize));
1061 VirtualObject(node->id(), zone(), size.Value() / kPointerSize));
1062 } else { 1082 } else {
1063 virtual_states_[node->id()]->SetVirtualObject( 1083 state->SetVirtualObject(alias,
1064 aliases_[node->id()], new (zone()) VirtualObject(node->id(), zone())); 1084 new (zone()) VirtualObject(node->id(), zone()));
1065 } 1085 }
1066 virtual_states_[node->id()]->LastChangedAt(node); 1086 state->LastChangedAt(node);
1067 } 1087 }
1068 1088
1069 1089
1070 void EscapeAnalysis::ProcessFinishRegion(Node* node) { 1090 void EscapeAnalysis::ProcessFinishRegion(Node* node) {
1071 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion); 1091 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion);
1072 ForwardVirtualState(node); 1092 ForwardVirtualState(node);
1073 Node* allocation = NodeProperties::GetValueInput(node, 0); 1093 Node* allocation = NodeProperties::GetValueInput(node, 0);
1074 if (allocation->opcode() == IrOpcode::kAllocate) { 1094 if (allocation->opcode() == IrOpcode::kAllocate) {
1075 VirtualState* state = virtual_states_[node->id()]; 1095 VirtualState* state = virtual_states_[node->id()];
1076 if (!state->VirtualObjectFromAlias(aliases_[node->id()])) { 1096 if (!state->VirtualObjectFromAlias(aliases_[node->id()])) {
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
1171 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) { 1191 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) {
1172 if (VirtualState* states = virtual_states_[at->id()]) { 1192 if (VirtualState* states = virtual_states_[at->id()]) {
1173 return states->VirtualObjectFromAlias(aliases_[id]); 1193 return states->VirtualObjectFromAlias(aliases_[id]);
1174 } 1194 }
1175 return nullptr; 1195 return nullptr;
1176 } 1196 }
1177 1197
1178 1198
1179 VirtualObject* EscapeAnalysis::ResolveVirtualObject(VirtualState* state, 1199 VirtualObject* EscapeAnalysis::ResolveVirtualObject(VirtualState* state,
1180 Node* node) { 1200 Node* node) {
1181 VirtualObject* obj = GetVirtualObject(state, ResolveReplacement(node)); 1201 return GetVirtualObject(state, ResolveReplacement(node));
1182 while (obj && replacement(obj->id())) {
1183 if (VirtualObject* next = GetVirtualObject(state, replacement(obj->id()))) {
1184 obj = next;
1185 } else {
1186 break;
1187 }
1188 }
1189 return obj;
1190 } 1202 }
1191 1203
1192 1204
1193 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) { 1205 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) {
1194 DCHECK(IsVirtual(left) && IsVirtual(right)); 1206 DCHECK(IsVirtual(left) && IsVirtual(right));
1195 left = ResolveReplacement(left); 1207 left = ResolveReplacement(left);
1196 right = ResolveReplacement(right); 1208 right = ResolveReplacement(right);
1197 if (IsEquivalentPhi(left, right)) { 1209 if (IsEquivalentPhi(left, right)) {
1198 return true; 1210 return true;
1199 } 1211 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1244 } 1256 }
1245 } else if (FLAG_trace_turbo_escape) { 1257 } else if (FLAG_trace_turbo_escape) {
1246 PrintF(" has incomplete virtual object info.\n"); 1258 PrintF(" has incomplete virtual object info.\n");
1247 } 1259 }
1248 } 1260 }
1249 1261
1250 1262
1251 void EscapeAnalysis::ProcessLoadField(Node* node) { 1263 void EscapeAnalysis::ProcessLoadField(Node* node) {
1252 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField); 1264 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField);
1253 ForwardVirtualState(node); 1265 ForwardVirtualState(node);
1254 Node* from = NodeProperties::GetValueInput(node, 0); 1266 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1255 VirtualState* state = virtual_states_[node->id()]; 1267 VirtualState* state = virtual_states_[node->id()];
1256 if (VirtualObject* object = ResolveVirtualObject(state, from)) { 1268 if (VirtualObject* object = GetVirtualObject(state, from)) {
1257 int offset = OffsetFromAccess(node); 1269 int offset = OffsetFromAccess(node);
1258 if (!object->IsTracked()) return; 1270 if (!object->IsTracked()) return;
1259 Node* value = object->GetField(offset); 1271 Node* value = object->GetField(offset);
1260 if (value) { 1272 if (value) {
1261 value = ResolveReplacement(value); 1273 value = ResolveReplacement(value);
1262 } 1274 }
1263 // Record that the load has this alias. 1275 // Record that the load has this alias.
1264 UpdateReplacement(state, node, value); 1276 UpdateReplacement(state, node, value);
1265 } else { 1277 } else if (from->opcode() == IrOpcode::kPhi &&
1266 if (from->opcode() == IrOpcode::kPhi && 1278 OpParameter<FieldAccess>(node).offset % kPointerSize == 0) {
1267 OpParameter<FieldAccess>(node).offset % kPointerSize == 0) {
1268 int offset = OffsetFromAccess(node); 1279 int offset = OffsetFromAccess(node);
1269 // Only binary phis are supported for now. 1280 // Only binary phis are supported for now.
1270 ProcessLoadFromPhi(offset, from, node, state); 1281 ProcessLoadFromPhi(offset, from, node, state);
1271 } 1282 } else {
1283 UpdateReplacement(state, node, nullptr);
1272 } 1284 }
1273 } 1285 }
1274 1286
1275 1287
1276 void EscapeAnalysis::ProcessLoadElement(Node* node) { 1288 void EscapeAnalysis::ProcessLoadElement(Node* node) {
1277 DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement); 1289 DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement);
1278 ForwardVirtualState(node); 1290 ForwardVirtualState(node);
1279 Node* from = NodeProperties::GetValueInput(node, 0); 1291 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1280 VirtualState* state = virtual_states_[node->id()]; 1292 VirtualState* state = virtual_states_[node->id()];
1281 Node* index_node = node->InputAt(1); 1293 Node* index_node = node->InputAt(1);
1282 NumberMatcher index(index_node); 1294 NumberMatcher index(index_node);
1283 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant && 1295 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant &&
1284 index_node->opcode() != IrOpcode::kInt64Constant && 1296 index_node->opcode() != IrOpcode::kInt64Constant &&
1285 index_node->opcode() != IrOpcode::kFloat32Constant && 1297 index_node->opcode() != IrOpcode::kFloat32Constant &&
1286 index_node->opcode() != IrOpcode::kFloat64Constant); 1298 index_node->opcode() != IrOpcode::kFloat64Constant);
1287 ElementAccess access = OpParameter<ElementAccess>(node); 1299 ElementAccess access = OpParameter<ElementAccess>(node);
1288 if (index.HasValue()) { 1300 if (index.HasValue()) {
1289 int offset = index.Value() + access.header_size / kPointerSize; 1301 int offset = index.Value() + access.header_size / kPointerSize;
1290 if (VirtualObject* object = ResolveVirtualObject(state, from)) { 1302 if (VirtualObject* object = GetVirtualObject(state, from)) {
1291 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()), 1303 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()),
1292 kPointerSizeLog2); 1304 kPointerSizeLog2);
1293 CHECK_EQ(access.header_size % kPointerSize, 0); 1305 CHECK_EQ(access.header_size % kPointerSize, 0);
1294 1306
1295 if (!object->IsTracked()) return; 1307 if (!object->IsTracked()) return;
1296 Node* value = object->GetField(offset); 1308 Node* value = object->GetField(offset);
1297 if (value) { 1309 if (value) {
1298 value = ResolveReplacement(value); 1310 value = ResolveReplacement(value);
1299 } 1311 }
1300 // Record that the load has this alias. 1312 // Record that the load has this alias.
1301 UpdateReplacement(state, node, value); 1313 UpdateReplacement(state, node, value);
1302 } else if (from->opcode() == IrOpcode::kPhi) { 1314 } else if (from->opcode() == IrOpcode::kPhi) {
1303 ElementAccess access = OpParameter<ElementAccess>(node); 1315 ElementAccess access = OpParameter<ElementAccess>(node);
1304 int offset = index.Value() + access.header_size / kPointerSize; 1316 int offset = index.Value() + access.header_size / kPointerSize;
1305 ProcessLoadFromPhi(offset, from, node, state); 1317 ProcessLoadFromPhi(offset, from, node, state);
1318 } else {
1319 UpdateReplacement(state, node, nullptr);
1306 } 1320 }
1307 } else { 1321 } else {
1308 // We have a load from a non-const index, cannot eliminate object. 1322 // We have a load from a non-const index, cannot eliminate object.
1309 if (SetEscaped(from)) { 1323 if (SetEscaped(from)) {
1310 if (FLAG_trace_turbo_escape) { 1324 if (FLAG_trace_turbo_escape) {
1311 PrintF( 1325 PrintF(
1312 "Setting #%d (%s) to escaped because store element #%d to " 1326 "Setting #%d (%s) to escaped because load element #%d from "
1313 "non-const " 1327 "non-const "
1314 "index #%d (%s)\n", 1328 "index #%d (%s)\n",
1315 from->id(), from->op()->mnemonic(), node->id(), index_node->id(), 1329 from->id(), from->op()->mnemonic(), node->id(), index_node->id(),
1316 index_node->op()->mnemonic()); 1330 index_node->op()->mnemonic());
1317 } 1331 }
1318 } 1332 }
1319 } 1333 }
1320 } 1334 }
1321 1335
1322 1336
1323 void EscapeAnalysis::ProcessStoreField(Node* node) { 1337 void EscapeAnalysis::ProcessStoreField(Node* node) {
1324 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField); 1338 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField);
1325 ForwardVirtualState(node); 1339 ForwardVirtualState(node);
1326 Node* to = NodeProperties::GetValueInput(node, 0); 1340 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1327 Node* val = NodeProperties::GetValueInput(node, 1);
1328 VirtualState* state = virtual_states_[node->id()]; 1341 VirtualState* state = virtual_states_[node->id()];
1329 if (VirtualObject* obj = ResolveVirtualObject(state, to)) { 1342 VirtualObject* obj = GetVirtualObject(state, to);
1330 if (!obj->IsTracked()) return; 1343 if (obj && obj->IsTracked()) {
1331 int offset = OffsetFromAccess(node); 1344 int offset = OffsetFromAccess(node);
1332 if (obj->SetField(offset, ResolveReplacement(val))) { 1345 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 1));
1346 if (obj->SetField(offset, val)) {
1333 state->LastChangedAt(node); 1347 state->LastChangedAt(node);
1334 } 1348 }
1335 } 1349 }
1336 } 1350 }
1337 1351
1338 1352
1339 void EscapeAnalysis::ProcessStoreElement(Node* node) { 1353 void EscapeAnalysis::ProcessStoreElement(Node* node) {
1340 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement); 1354 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement);
1341 ForwardVirtualState(node); 1355 ForwardVirtualState(node);
1342 Node* to = NodeProperties::GetValueInput(node, 0); 1356 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1343 Node* index_node = node->InputAt(1); 1357 Node* index_node = node->InputAt(1);
1344 NumberMatcher index(index_node); 1358 NumberMatcher index(index_node);
1345 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant && 1359 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant &&
1346 index_node->opcode() != IrOpcode::kInt64Constant && 1360 index_node->opcode() != IrOpcode::kInt64Constant &&
1347 index_node->opcode() != IrOpcode::kFloat32Constant && 1361 index_node->opcode() != IrOpcode::kFloat32Constant &&
1348 index_node->opcode() != IrOpcode::kFloat64Constant); 1362 index_node->opcode() != IrOpcode::kFloat64Constant);
1349 ElementAccess access = OpParameter<ElementAccess>(node); 1363 ElementAccess access = OpParameter<ElementAccess>(node);
1350 Node* val = NodeProperties::GetValueInput(node, 2); 1364 VirtualState* state = virtual_states_[node->id()];
1365 VirtualObject* obj = GetVirtualObject(state, to);
1351 if (index.HasValue()) { 1366 if (index.HasValue()) {
1352 int offset = index.Value() + access.header_size / kPointerSize; 1367 int offset = index.Value() + access.header_size / kPointerSize;
1353 VirtualState* states = virtual_states_[node->id()]; 1368 if (obj && obj->IsTracked()) {
1354 if (VirtualObject* obj = ResolveVirtualObject(states, to)) {
1355 if (!obj->IsTracked()) return;
1356 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()), 1369 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()),
1357 kPointerSizeLog2); 1370 kPointerSizeLog2);
1358 CHECK_EQ(access.header_size % kPointerSize, 0); 1371 CHECK_EQ(access.header_size % kPointerSize, 0);
1359 if (obj->SetField(offset, ResolveReplacement(val))) { 1372 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 2));
1360 states->LastChangedAt(node); 1373 if (obj->SetField(offset, val)) {
1374 state->LastChangedAt(node);
1361 } 1375 }
1362 } 1376 }
1363 } else { 1377 } else {
1364 // We have a store to a non-const index, cannot eliminate object. 1378 // We have a store to a non-const index, cannot eliminate object.
1365 if (SetEscaped(to)) { 1379 if (SetEscaped(to)) {
1366 if (FLAG_trace_turbo_escape) { 1380 if (FLAG_trace_turbo_escape) {
1367 PrintF( 1381 PrintF(
1368 "Setting #%d (%s) to escaped because store element #%d to " 1382 "Setting #%d (%s) to escaped because store element #%d to "
1369 "non-const " 1383 "non-const "
1370 "index #%d (%s)\n", 1384 "index #%d (%s)\n",
1371 to->id(), to->op()->mnemonic(), node->id(), index_node->id(), 1385 to->id(), to->op()->mnemonic(), node->id(), index_node->id(),
1372 index_node->op()->mnemonic()); 1386 index_node->op()->mnemonic());
1373 } 1387 }
1374 } 1388 }
1389 if (obj && obj->IsTracked() && obj->ClearAllFields()) {
1390 state->LastChangedAt(node);
1391 }
1375 } 1392 }
1376 } 1393 }
1377 1394
1378 1395
1379 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) { 1396 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) {
1380 if ((node->opcode() == IrOpcode::kFinishRegion || 1397 if ((node->opcode() == IrOpcode::kFinishRegion ||
1381 node->opcode() == IrOpcode::kAllocate) && 1398 node->opcode() == IrOpcode::kAllocate) &&
1382 IsVirtual(node)) { 1399 IsVirtual(node)) {
1383 if (VirtualObject* vobj = 1400 if (VirtualObject* vobj =
1384 ResolveVirtualObject(virtual_states_[effect->id()], node)) { 1401 ResolveVirtualObject(virtual_states_[effect->id()], node)) {
(...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after
1459 1476
1460 1477
1461 VirtualObject* EscapeAnalysis::GetVirtualObject(VirtualState* state, 1478 VirtualObject* EscapeAnalysis::GetVirtualObject(VirtualState* state,
1462 Node* node) { 1479 Node* node) {
1463 if (node->id() >= aliases_.size()) return nullptr; 1480 if (node->id() >= aliases_.size()) return nullptr;
1464 Alias alias = aliases_[node->id()]; 1481 Alias alias = aliases_[node->id()];
1465 if (alias >= state->size()) return nullptr; 1482 if (alias >= state->size()) return nullptr;
1466 return state->VirtualObjectFromAlias(alias); 1483 return state->VirtualObjectFromAlias(alias);
1467 } 1484 }
1468 1485
1486
1487 bool EscapeAnalysis::ExistsVirtualAllocate() {
1488 for (size_t id = 0; id < aliases_.size(); ++id) {
1489 Alias alias = aliases_[id];
1490 if (alias < kUntrackable) {
1491 if (escape_status_.IsVirtual(static_cast<int>(id))) {
1492 return true;
1493 }
1494 }
1495 }
1496 return false;
1497 }
1498
1469 } // namespace compiler 1499 } // namespace compiler
1470 } // namespace internal 1500 } // namespace internal
1471 } // namespace v8 1501 } // namespace v8
OLDNEW
« no previous file with comments | « src/compiler/escape-analysis.h ('k') | src/compiler/escape-analysis-reducer.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698