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

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: OMG fix 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
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;
734 RunObjectAnalysis(); 753 RunObjectAnalysis();
735 escape_status_.Run(); 754 escape_status_.Run();
736 } 755 }
737 756
738 757
739 void EscapeAnalysis::AssignAliases() { 758 void EscapeAnalysis::AssignAliases() {
740 ZoneVector<Node*> stack(zone()); 759 ZoneVector<Node*> stack(zone());
741 stack.push_back(graph()->end()); 760 stack.push_back(graph()->end());
742 CHECK_LT(graph()->NodeCount(), kUntrackable); 761 CHECK_LT(graph()->NodeCount(), kUntrackable);
743 aliases_.resize(graph()->NodeCount(), kNotReachable); 762 aliases_.resize(graph()->NodeCount(), kNotReachable);
(...skipping 291 matching lines...) Expand 10 before | Expand all | Expand 10 after
1035 mergeState->LastChangedAt(node); 1054 mergeState->LastChangedAt(node);
1036 escape_status_.Resize(); 1055 escape_status_.Resize();
1037 } 1056 }
1038 return changed; 1057 return changed;
1039 } 1058 }
1040 1059
1041 1060
1042 void EscapeAnalysis::ProcessAllocation(Node* node) { 1061 void EscapeAnalysis::ProcessAllocation(Node* node) {
1043 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate); 1062 DCHECK_EQ(node->opcode(), IrOpcode::kAllocate);
1044 ForwardVirtualState(node); 1063 ForwardVirtualState(node);
1064 VirtualState* state = virtual_states_[node->id()];
1065 Alias alias = aliases_[node->id()];
1045 1066
1046 // Check if we have already processed this node. 1067 // Check if we have already processed this node.
1047 if (virtual_states_[node->id()]->VirtualObjectFromAlias( 1068 if (state->VirtualObjectFromAlias(alias)) {
1048 aliases_[node->id()])) {
1049 return; 1069 return;
1050 } 1070 }
1051 1071
1052 NumberMatcher size(node->InputAt(0)); 1072 NumberMatcher size(node->InputAt(0));
1053 DCHECK(node->InputAt(0)->opcode() != IrOpcode::kInt32Constant && 1073 DCHECK(node->InputAt(0)->opcode() != IrOpcode::kInt32Constant &&
1054 node->InputAt(0)->opcode() != IrOpcode::kInt64Constant && 1074 node->InputAt(0)->opcode() != IrOpcode::kInt64Constant &&
1055 node->InputAt(0)->opcode() != IrOpcode::kFloat32Constant && 1075 node->InputAt(0)->opcode() != IrOpcode::kFloat32Constant &&
1056 node->InputAt(0)->opcode() != IrOpcode::kFloat64Constant); 1076 node->InputAt(0)->opcode() != IrOpcode::kFloat64Constant);
1057 if (size.HasValue()) { 1077 if (size.HasValue()) {
1058 virtual_states_[node->id()]->SetVirtualObject( 1078 state->SetVirtualObject(
1059 aliases_[node->id()], 1079 alias, new (zone()) VirtualObject(node->id(), zone(),
1060 new (zone()) 1080 size.Value() / kPointerSize));
1061 VirtualObject(node->id(), zone(), size.Value() / kPointerSize));
1062 } else { 1081 } else {
1063 virtual_states_[node->id()]->SetVirtualObject( 1082 state->SetVirtualObject(alias,
1064 aliases_[node->id()], new (zone()) VirtualObject(node->id(), zone())); 1083 new (zone()) VirtualObject(node->id(), zone()));
1065 } 1084 }
1066 virtual_states_[node->id()]->LastChangedAt(node); 1085 state->LastChangedAt(node);
1067 } 1086 }
1068 1087
1069 1088
1070 void EscapeAnalysis::ProcessFinishRegion(Node* node) { 1089 void EscapeAnalysis::ProcessFinishRegion(Node* node) {
1071 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion); 1090 DCHECK_EQ(node->opcode(), IrOpcode::kFinishRegion);
1072 ForwardVirtualState(node); 1091 ForwardVirtualState(node);
1073 Node* allocation = NodeProperties::GetValueInput(node, 0); 1092 Node* allocation = NodeProperties::GetValueInput(node, 0);
1074 if (allocation->opcode() == IrOpcode::kAllocate) { 1093 if (allocation->opcode() == IrOpcode::kAllocate) {
1075 VirtualState* state = virtual_states_[node->id()]; 1094 VirtualState* state = virtual_states_[node->id()];
1076 if (!state->VirtualObjectFromAlias(aliases_[node->id()])) { 1095 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) { 1190 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) {
1172 if (VirtualState* states = virtual_states_[at->id()]) { 1191 if (VirtualState* states = virtual_states_[at->id()]) {
1173 return states->VirtualObjectFromAlias(aliases_[id]); 1192 return states->VirtualObjectFromAlias(aliases_[id]);
1174 } 1193 }
1175 return nullptr; 1194 return nullptr;
1176 } 1195 }
1177 1196
1178 1197
1179 VirtualObject* EscapeAnalysis::ResolveVirtualObject(VirtualState* state, 1198 VirtualObject* EscapeAnalysis::ResolveVirtualObject(VirtualState* state,
1180 Node* node) { 1199 Node* node) {
1181 VirtualObject* obj = GetVirtualObject(state, ResolveReplacement(node)); 1200 return GetVirtualObject(state, ResolveReplacement(node));
sigurds 2016/01/18 12:13:17 The loop is not necessary since we rely on aliases
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 } 1201 }
1191 1202
1192 1203
1193 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) { 1204 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) {
1194 DCHECK(IsVirtual(left) && IsVirtual(right)); 1205 DCHECK(IsVirtual(left) && IsVirtual(right));
1195 left = ResolveReplacement(left); 1206 left = ResolveReplacement(left);
1196 right = ResolveReplacement(right); 1207 right = ResolveReplacement(right);
1197 if (IsEquivalentPhi(left, right)) { 1208 if (IsEquivalentPhi(left, right)) {
1198 return true; 1209 return true;
1199 } 1210 }
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
1244 } 1255 }
1245 } else if (FLAG_trace_turbo_escape) { 1256 } else if (FLAG_trace_turbo_escape) {
1246 PrintF(" has incomplete virtual object info.\n"); 1257 PrintF(" has incomplete virtual object info.\n");
1247 } 1258 }
1248 } 1259 }
1249 1260
1250 1261
1251 void EscapeAnalysis::ProcessLoadField(Node* node) { 1262 void EscapeAnalysis::ProcessLoadField(Node* node) {
1252 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField); 1263 DCHECK_EQ(node->opcode(), IrOpcode::kLoadField);
1253 ForwardVirtualState(node); 1264 ForwardVirtualState(node);
1254 Node* from = NodeProperties::GetValueInput(node, 0); 1265 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1255 VirtualState* state = virtual_states_[node->id()]; 1266 VirtualState* state = virtual_states_[node->id()];
1256 if (VirtualObject* object = ResolveVirtualObject(state, from)) { 1267 if (VirtualObject* object = GetVirtualObject(state, from)) {
1257 int offset = OffsetFromAccess(node); 1268 int offset = OffsetFromAccess(node);
1258 if (!object->IsTracked()) return; 1269 if (!object->IsTracked()) return;
1259 Node* value = object->GetField(offset); 1270 Node* value = object->GetField(offset);
1260 if (value) { 1271 if (value) {
1261 value = ResolveReplacement(value); 1272 value = ResolveReplacement(value);
1262 } 1273 }
1263 // Record that the load has this alias. 1274 // Record that the load has this alias.
1264 UpdateReplacement(state, node, value); 1275 UpdateReplacement(state, node, value);
1265 } else { 1276 } else if (from->opcode() == IrOpcode::kPhi &&
1266 if (from->opcode() == IrOpcode::kPhi && 1277 OpParameter<FieldAccess>(node).offset % kPointerSize == 0) {
1267 OpParameter<FieldAccess>(node).offset % kPointerSize == 0) {
1268 int offset = OffsetFromAccess(node); 1278 int offset = OffsetFromAccess(node);
1269 // Only binary phis are supported for now. 1279 // Only binary phis are supported for now.
1270 ProcessLoadFromPhi(offset, from, node, state); 1280 ProcessLoadFromPhi(offset, from, node, state);
1271 } 1281 } else {
1282 UpdateReplacement(state, node, nullptr);
1272 } 1283 }
1273 } 1284 }
1274 1285
1275 1286
1276 void EscapeAnalysis::ProcessLoadElement(Node* node) { 1287 void EscapeAnalysis::ProcessLoadElement(Node* node) {
1277 DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement); 1288 DCHECK_EQ(node->opcode(), IrOpcode::kLoadElement);
1278 ForwardVirtualState(node); 1289 ForwardVirtualState(node);
1279 Node* from = NodeProperties::GetValueInput(node, 0); 1290 Node* from = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1280 VirtualState* state = virtual_states_[node->id()]; 1291 VirtualState* state = virtual_states_[node->id()];
1281 Node* index_node = node->InputAt(1); 1292 Node* index_node = node->InputAt(1);
1282 NumberMatcher index(index_node); 1293 NumberMatcher index(index_node);
1283 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant && 1294 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant &&
1284 index_node->opcode() != IrOpcode::kInt64Constant && 1295 index_node->opcode() != IrOpcode::kInt64Constant &&
1285 index_node->opcode() != IrOpcode::kFloat32Constant && 1296 index_node->opcode() != IrOpcode::kFloat32Constant &&
1286 index_node->opcode() != IrOpcode::kFloat64Constant); 1297 index_node->opcode() != IrOpcode::kFloat64Constant);
1287 ElementAccess access = OpParameter<ElementAccess>(node); 1298 ElementAccess access = OpParameter<ElementAccess>(node);
1288 if (index.HasValue()) { 1299 if (index.HasValue()) {
1289 int offset = index.Value() + access.header_size / kPointerSize; 1300 int offset = index.Value() + access.header_size / kPointerSize;
1290 if (VirtualObject* object = ResolveVirtualObject(state, from)) { 1301 if (VirtualObject* object = GetVirtualObject(state, from)) {
1291 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()), 1302 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()),
1292 kPointerSizeLog2); 1303 kPointerSizeLog2);
1293 CHECK_EQ(access.header_size % kPointerSize, 0); 1304 CHECK_EQ(access.header_size % kPointerSize, 0);
1294 1305
1295 if (!object->IsTracked()) return; 1306 if (!object->IsTracked()) return;
1296 Node* value = object->GetField(offset); 1307 Node* value = object->GetField(offset);
1297 if (value) { 1308 if (value) {
1298 value = ResolveReplacement(value); 1309 value = ResolveReplacement(value);
1299 } 1310 }
1300 // Record that the load has this alias. 1311 // Record that the load has this alias.
1301 UpdateReplacement(state, node, value); 1312 UpdateReplacement(state, node, value);
1302 } else if (from->opcode() == IrOpcode::kPhi) { 1313 } else if (from->opcode() == IrOpcode::kPhi) {
1303 ElementAccess access = OpParameter<ElementAccess>(node); 1314 ElementAccess access = OpParameter<ElementAccess>(node);
1304 int offset = index.Value() + access.header_size / kPointerSize; 1315 int offset = index.Value() + access.header_size / kPointerSize;
1305 ProcessLoadFromPhi(offset, from, node, state); 1316 ProcessLoadFromPhi(offset, from, node, state);
1317 } else {
1318 UpdateReplacement(state, node, nullptr);
sigurds 2016/01/18 12:13:17 This is a critical bug-fix
1306 } 1319 }
1307 } else { 1320 } else {
1308 // We have a load from a non-const index, cannot eliminate object. 1321 // We have a load from a non-const index, cannot eliminate object.
1309 if (SetEscaped(from)) { 1322 if (SetEscaped(from)) {
1310 if (FLAG_trace_turbo_escape) { 1323 if (FLAG_trace_turbo_escape) {
1311 PrintF( 1324 PrintF(
1312 "Setting #%d (%s) to escaped because store element #%d to " 1325 "Setting #%d (%s) to escaped because load element #%d from "
1313 "non-const " 1326 "non-const "
1314 "index #%d (%s)\n", 1327 "index #%d (%s)\n",
1315 from->id(), from->op()->mnemonic(), node->id(), index_node->id(), 1328 from->id(), from->op()->mnemonic(), node->id(), index_node->id(),
1316 index_node->op()->mnemonic()); 1329 index_node->op()->mnemonic());
1317 } 1330 }
1318 } 1331 }
1319 } 1332 }
1320 } 1333 }
1321 1334
1322 1335
1323 void EscapeAnalysis::ProcessStoreField(Node* node) { 1336 void EscapeAnalysis::ProcessStoreField(Node* node) {
1324 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField); 1337 DCHECK_EQ(node->opcode(), IrOpcode::kStoreField);
1325 ForwardVirtualState(node); 1338 ForwardVirtualState(node);
1326 Node* to = NodeProperties::GetValueInput(node, 0); 1339 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1327 Node* val = NodeProperties::GetValueInput(node, 1);
1328 VirtualState* state = virtual_states_[node->id()]; 1340 VirtualState* state = virtual_states_[node->id()];
1329 if (VirtualObject* obj = ResolveVirtualObject(state, to)) { 1341 VirtualObject* obj = GetVirtualObject(state, to);
1330 if (!obj->IsTracked()) return; 1342 if (obj && obj->IsTracked()) {
1331 int offset = OffsetFromAccess(node); 1343 int offset = OffsetFromAccess(node);
1332 if (obj->SetField(offset, ResolveReplacement(val))) { 1344 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 1));
1345 if (obj->SetField(offset, val)) {
1333 state->LastChangedAt(node); 1346 state->LastChangedAt(node);
1334 } 1347 }
1335 } 1348 }
1336 } 1349 }
1337 1350
1338 1351
1339 void EscapeAnalysis::ProcessStoreElement(Node* node) { 1352 void EscapeAnalysis::ProcessStoreElement(Node* node) {
1340 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement); 1353 DCHECK_EQ(node->opcode(), IrOpcode::kStoreElement);
1341 ForwardVirtualState(node); 1354 ForwardVirtualState(node);
1342 Node* to = NodeProperties::GetValueInput(node, 0); 1355 Node* to = ResolveReplacement(NodeProperties::GetValueInput(node, 0));
1343 Node* index_node = node->InputAt(1); 1356 Node* index_node = node->InputAt(1);
1344 NumberMatcher index(index_node); 1357 NumberMatcher index(index_node);
1345 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant && 1358 DCHECK(index_node->opcode() != IrOpcode::kInt32Constant &&
1346 index_node->opcode() != IrOpcode::kInt64Constant && 1359 index_node->opcode() != IrOpcode::kInt64Constant &&
1347 index_node->opcode() != IrOpcode::kFloat32Constant && 1360 index_node->opcode() != IrOpcode::kFloat32Constant &&
1348 index_node->opcode() != IrOpcode::kFloat64Constant); 1361 index_node->opcode() != IrOpcode::kFloat64Constant);
1349 ElementAccess access = OpParameter<ElementAccess>(node); 1362 ElementAccess access = OpParameter<ElementAccess>(node);
1350 Node* val = NodeProperties::GetValueInput(node, 2);
1351 if (index.HasValue()) { 1363 if (index.HasValue()) {
1352 int offset = index.Value() + access.header_size / kPointerSize; 1364 int offset = index.Value() + access.header_size / kPointerSize;
1353 VirtualState* states = virtual_states_[node->id()]; 1365 VirtualState* state = virtual_states_[node->id()];
1354 if (VirtualObject* obj = ResolveVirtualObject(states, to)) { 1366 VirtualObject* obj = GetVirtualObject(state, to);
1355 if (!obj->IsTracked()) return; 1367 if (obj && obj->IsTracked()) {
1356 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()), 1368 CHECK_GE(ElementSizeLog2Of(access.machine_type.representation()),
1357 kPointerSizeLog2); 1369 kPointerSizeLog2);
1358 CHECK_EQ(access.header_size % kPointerSize, 0); 1370 CHECK_EQ(access.header_size % kPointerSize, 0);
1359 if (obj->SetField(offset, ResolveReplacement(val))) { 1371 Node* val = ResolveReplacement(NodeProperties::GetValueInput(node, 2));
1360 states->LastChangedAt(node); 1372 if (obj->SetField(offset, val)) {
1373 state->LastChangedAt(node);
1361 } 1374 }
1362 } 1375 }
1363 } else { 1376 } else {
1364 // We have a store to a non-const index, cannot eliminate object. 1377 // We have a store to a non-const index, cannot eliminate object.
1365 if (SetEscaped(to)) { 1378 if (SetEscaped(to)) {
1366 if (FLAG_trace_turbo_escape) { 1379 if (FLAG_trace_turbo_escape) {
1367 PrintF( 1380 PrintF(
1368 "Setting #%d (%s) to escaped because store element #%d to " 1381 "Setting #%d (%s) to escaped because store element #%d to "
1369 "non-const " 1382 "non-const "
1370 "index #%d (%s)\n", 1383 "index #%d (%s)\n",
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
1459 1472
1460 1473
1461 VirtualObject* EscapeAnalysis::GetVirtualObject(VirtualState* state, 1474 VirtualObject* EscapeAnalysis::GetVirtualObject(VirtualState* state,
1462 Node* node) { 1475 Node* node) {
1463 if (node->id() >= aliases_.size()) return nullptr; 1476 if (node->id() >= aliases_.size()) return nullptr;
1464 Alias alias = aliases_[node->id()]; 1477 Alias alias = aliases_[node->id()];
1465 if (alias >= state->size()) return nullptr; 1478 if (alias >= state->size()) return nullptr;
1466 return state->VirtualObjectFromAlias(alias); 1479 return state->VirtualObjectFromAlias(alias);
1467 } 1480 }
1468 1481
1482
1483 bool EscapeAnalysis::ExistsVirtualAllocate() {
1484 for (size_t id = 0; id < aliases_.size(); ++id) {
1485 Alias alias = aliases_[id];
1486 if (alias < kUntrackable) {
1487 if (escape_status_.IsVirtual(static_cast<int>(id))) {
1488 return true;
1489 }
1490 }
1491 }
1492 return false;
1493 }
1494
1469 } // namespace compiler 1495 } // namespace compiler
1470 } // namespace internal 1496 } // namespace internal
1471 } // namespace v8 1497 } // namespace v8
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698