OLD | NEW |
1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/compiler/escape-analysis.h" | 5 #include "src/compiler/escape-analysis.h" |
6 | 6 |
7 #include <limits> | 7 #include <limits> |
8 | 8 |
9 #include "src/base/flags.h" | 9 #include "src/base/flags.h" |
10 #include "src/bootstrapper.h" | 10 #include "src/bootstrapper.h" |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
109 } | 109 } |
110 bool AllFieldsClear() { | 110 bool AllFieldsClear() { |
111 for (size_t i = 0; i < fields_.size(); ++i) { | 111 for (size_t i = 0; i < fields_.size(); ++i) { |
112 if (fields_[i] != nullptr) { | 112 if (fields_[i] != nullptr) { |
113 return false; | 113 return false; |
114 } | 114 } |
115 } | 115 } |
116 return true; | 116 return true; |
117 } | 117 } |
118 bool UpdateFrom(const VirtualObject& other); | 118 bool UpdateFrom(const VirtualObject& other); |
| 119 bool MergeFrom(MergeCache* cache, Node* at, Graph* graph, |
| 120 CommonOperatorBuilder* common); |
119 void SetObjectState(Node* node) { object_state_ = node; } | 121 void SetObjectState(Node* node) { object_state_ = node; } |
120 Node* GetObjectState() const { return object_state_; } | 122 Node* GetObjectState() const { return object_state_; } |
121 bool IsCopyRequired() const { return status_ & kCopyRequired; } | 123 bool IsCopyRequired() const { return status_ & kCopyRequired; } |
122 void SetCopyRequired() { status_ |= kCopyRequired; } | 124 void SetCopyRequired() { status_ |= kCopyRequired; } |
123 bool NeedCopyForModification() { | 125 bool NeedCopyForModification() { |
124 if (!IsCopyRequired() || !IsInitialized()) { | 126 if (!IsCopyRequired() || !IsInitialized()) { |
125 return false; | 127 return false; |
126 } | 128 } |
127 return true; | 129 return true; |
128 } | 130 } |
129 | 131 |
130 NodeId id() const { return id_; } | 132 NodeId id() const { return id_; } |
131 void id(NodeId id) { id_ = id; } | 133 void id(NodeId id) { id_ = id; } |
132 | 134 |
133 private: | 135 private: |
| 136 bool MergeFields(size_t i, Node* at, MergeCache* cache, Graph* graph, |
| 137 CommonOperatorBuilder* common); |
| 138 |
134 NodeId id_; | 139 NodeId id_; |
135 StatusFlags status_; | 140 StatusFlags status_; |
136 ZoneVector<Node*> fields_; | 141 ZoneVector<Node*> fields_; |
137 ZoneVector<bool> phi_; | 142 ZoneVector<bool> phi_; |
138 Node* object_state_; | 143 Node* object_state_; |
139 VirtualState* owner_; | 144 VirtualState* owner_; |
140 | 145 |
141 DISALLOW_COPY_AND_ASSIGN(VirtualObject); | 146 DISALLOW_COPY_AND_ASSIGN(VirtualObject); |
142 }; | 147 }; |
143 | 148 |
(...skipping 25 matching lines...) Expand all Loading... |
169 : info_(state.info_.size(), nullptr, state.info_.get_allocator().zone()), | 174 : info_(state.info_.size(), nullptr, state.info_.get_allocator().zone()), |
170 owner_(owner) { | 175 owner_(owner) { |
171 for (size_t i = 0; i < info_.size(); ++i) { | 176 for (size_t i = 0; i < info_.size(); ++i) { |
172 if (state.info_[i]) { | 177 if (state.info_[i]) { |
173 info_[i] = state.info_[i]; | 178 info_[i] = state.info_[i]; |
174 } | 179 } |
175 } | 180 } |
176 } | 181 } |
177 | 182 |
178 VirtualObject* VirtualObjectFromAlias(size_t alias); | 183 VirtualObject* VirtualObjectFromAlias(size_t alias); |
179 VirtualObject* GetOrCreateTrackedVirtualObject(Alias alias, NodeId id, | |
180 size_t fields, | |
181 bool initialized, Zone* zone, | |
182 bool force_copy); | |
183 void SetVirtualObject(Alias alias, VirtualObject* state); | 184 void SetVirtualObject(Alias alias, VirtualObject* state); |
184 bool UpdateFrom(VirtualState* state, Zone* zone); | 185 bool UpdateFrom(VirtualState* state, Zone* zone); |
185 bool MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, | 186 bool MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, |
186 CommonOperatorBuilder* common, Node* control, int arity); | 187 CommonOperatorBuilder* common, Node* at); |
187 size_t size() const { return info_.size(); } | 188 size_t size() const { return info_.size(); } |
188 Node* owner() const { return owner_; } | 189 Node* owner() const { return owner_; } |
189 VirtualObject* Copy(VirtualObject* obj, Alias alias); | 190 VirtualObject* Copy(VirtualObject* obj, Alias alias); |
190 void SetCopyRequired() { | 191 void SetCopyRequired() { |
191 for (VirtualObject* obj : info_) { | 192 for (VirtualObject* obj : info_) { |
192 if (obj) obj->SetCopyRequired(); | 193 if (obj) obj->SetCopyRequired(); |
193 } | 194 } |
194 } | 195 } |
195 | 196 |
196 private: | 197 private: |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
281 static_cast<void*>(this), alias, obj->id(), static_cast<void*>(obj), | 282 static_cast<void*>(this), alias, obj->id(), static_cast<void*>(obj), |
282 static_cast<void*>(new_obj)); | 283 static_cast<void*>(new_obj)); |
283 info_[alias] = new_obj; | 284 info_[alias] = new_obj; |
284 return new_obj; | 285 return new_obj; |
285 } | 286 } |
286 | 287 |
287 VirtualObject* VirtualState::VirtualObjectFromAlias(size_t alias) { | 288 VirtualObject* VirtualState::VirtualObjectFromAlias(size_t alias) { |
288 return info_[alias]; | 289 return info_[alias]; |
289 } | 290 } |
290 | 291 |
291 VirtualObject* VirtualState::GetOrCreateTrackedVirtualObject( | |
292 Alias alias, NodeId id, size_t field_number, bool initialized, Zone* zone, | |
293 bool force_copy) { | |
294 if (!force_copy) { | |
295 if (VirtualObject* obj = VirtualObjectFromAlias(alias)) { | |
296 return obj; | |
297 } | |
298 } | |
299 VirtualObject* obj = new (zone) VirtualObject(id, this, zone, 0, initialized); | |
300 SetVirtualObject(alias, obj); | |
301 return obj; | |
302 } | |
303 | |
304 void VirtualState::SetVirtualObject(Alias alias, VirtualObject* obj) { | 292 void VirtualState::SetVirtualObject(Alias alias, VirtualObject* obj) { |
305 info_[alias] = obj; | 293 info_[alias] = obj; |
306 } | 294 } |
307 | 295 |
308 bool VirtualState::UpdateFrom(VirtualState* from, Zone* zone) { | 296 bool VirtualState::UpdateFrom(VirtualState* from, Zone* zone) { |
309 if (from == this) return false; | 297 if (from == this) return false; |
310 bool changed = false; | 298 bool changed = false; |
311 for (Alias alias = 0; alias < size(); ++alias) { | 299 for (Alias alias = 0; alias < size(); ++alias) { |
312 VirtualObject* ls = VirtualObjectFromAlias(alias); | 300 VirtualObject* ls = VirtualObjectFromAlias(alias); |
313 VirtualObject* rs = from->VirtualObjectFromAlias(alias); | 301 VirtualObject* rs = from->VirtualObjectFromAlias(alias); |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
355 Node* input = NodeProperties::GetValueInput(phi, static_cast<int>(i)); | 343 Node* input = NodeProperties::GetValueInput(phi, static_cast<int>(i)); |
356 if (!IsEquivalentPhi(input, inputs[i])) { | 344 if (!IsEquivalentPhi(input, inputs[i])) { |
357 return false; | 345 return false; |
358 } | 346 } |
359 } | 347 } |
360 return true; | 348 return true; |
361 } | 349 } |
362 | 350 |
363 } // namespace | 351 } // namespace |
364 | 352 |
365 Node* EscapeAnalysis::GetReplacementIfSame(ZoneVector<VirtualObject*>& objs) { | 353 bool VirtualObject::MergeFields(size_t i, Node* at, MergeCache* cache, |
366 Node* rep = GetReplacement(objs.front()->id()); | 354 Graph* graph, CommonOperatorBuilder* common) { |
367 for (VirtualObject* obj : objs) { | 355 bool changed = false; |
368 if (GetReplacement(obj->id()) != rep) { | 356 int value_input_count = static_cast<int>(cache->fields().size()); |
369 return nullptr; | 357 Node* rep = GetField(i); |
| 358 if (!rep || !IsCreatedPhi(i)) { |
| 359 Node* control = NodeProperties::GetControlInput(at); |
| 360 cache->fields().push_back(control); |
| 361 Node* phi = graph->NewNode( |
| 362 common->Phi(MachineRepresentation::kTagged, value_input_count), |
| 363 value_input_count + 1, &cache->fields().front()); |
| 364 SetField(i, phi, true); |
| 365 #ifdef DEBUG |
| 366 if (FLAG_trace_turbo_escape) { |
| 367 PrintF(" Creating Phi #%d as merge of", phi->id()); |
| 368 for (int i = 0; i < value_input_count; i++) { |
| 369 PrintF(" #%d (%s)", cache->fields()[i]->id(), |
| 370 cache->fields()[i]->op()->mnemonic()); |
| 371 } |
| 372 PrintF("\n"); |
| 373 } |
| 374 #endif |
| 375 changed = true; |
| 376 } else { |
| 377 DCHECK(rep->opcode() == IrOpcode::kPhi); |
| 378 for (int n = 0; n < value_input_count; ++n) { |
| 379 Node* old = NodeProperties::GetValueInput(rep, n); |
| 380 if (old != cache->fields()[n]) { |
| 381 changed = true; |
| 382 NodeProperties::ReplaceValueInput(rep, cache->fields()[n], n); |
| 383 } |
370 } | 384 } |
371 } | 385 } |
372 return rep; | 386 return changed; |
| 387 } |
| 388 |
| 389 bool VirtualObject::MergeFrom(MergeCache* cache, Node* at, Graph* graph, |
| 390 CommonOperatorBuilder* common) { |
| 391 DCHECK(at->opcode() == IrOpcode::kEffectPhi || |
| 392 at->opcode() == IrOpcode::kPhi); |
| 393 bool changed = false; |
| 394 for (size_t i = 0; i < field_count(); ++i) { |
| 395 if (Node* field = cache->GetFields(i)) { |
| 396 changed = changed || GetField(i) != field; |
| 397 SetField(i, field); |
| 398 TRACE(" Field %zu agree on rep #%d\n", i, field->id()); |
| 399 } else { |
| 400 int arity = at->opcode() == IrOpcode::kEffectPhi |
| 401 ? at->op()->EffectInputCount() |
| 402 : at->op()->ValueInputCount(); |
| 403 if (cache->fields().size() == arity) { |
| 404 changed = MergeFields(i, at, cache, graph, common) || changed; |
| 405 } else { |
| 406 if (GetField(i) != nullptr) { |
| 407 TRACE(" Field %zu cleared\n", i); |
| 408 changed = true; |
| 409 } |
| 410 SetField(i, nullptr); |
| 411 } |
| 412 } |
| 413 } |
| 414 return changed; |
373 } | 415 } |
374 | 416 |
375 bool VirtualState::MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, | 417 bool VirtualState::MergeFrom(MergeCache* cache, Zone* zone, Graph* graph, |
376 CommonOperatorBuilder* common, Node* control, | 418 CommonOperatorBuilder* common, Node* at) { |
377 int arity) { | |
378 DCHECK_GT(cache->states().size(), 0u); | 419 DCHECK_GT(cache->states().size(), 0u); |
379 bool changed = false; | 420 bool changed = false; |
380 for (Alias alias = 0; alias < size(); ++alias) { | 421 for (Alias alias = 0; alias < size(); ++alias) { |
381 cache->objects().clear(); | 422 cache->objects().clear(); |
382 VirtualObject* mergeObject = VirtualObjectFromAlias(alias); | 423 VirtualObject* mergeObject = VirtualObjectFromAlias(alias); |
383 bool copy_merge_object = false; | 424 bool copy_merge_object = false; |
384 size_t fields = std::numeric_limits<size_t>::max(); | 425 size_t fields = std::numeric_limits<size_t>::max(); |
385 for (VirtualState* state : cache->states()) { | 426 for (VirtualState* state : cache->states()) { |
386 if (VirtualObject* obj = state->VirtualObjectFromAlias(alias)) { | 427 if (VirtualObject* obj = state->VirtualObjectFromAlias(alias)) { |
387 cache->objects().push_back(obj); | 428 cache->objects().push_back(obj); |
388 if (mergeObject == obj) { | 429 if (mergeObject == obj) { |
389 copy_merge_object = true; | 430 copy_merge_object = true; |
390 changed = true; | |
391 } | 431 } |
392 fields = std::min(obj->field_count(), fields); | 432 fields = std::min(obj->field_count(), fields); |
393 } | 433 } |
394 } | 434 } |
395 if (cache->objects().size() == cache->states().size()) { | 435 if (cache->objects().size() == cache->states().size()) { |
396 mergeObject = GetOrCreateTrackedVirtualObject( | 436 if (!mergeObject) { |
397 alias, cache->objects().front()->id(), | 437 VirtualObject* obj = new (zone) |
398 cache->objects().front()->IsInitialized(), fields, zone, | 438 VirtualObject(cache->objects().front()->id(), this, zone, fields, |
399 copy_merge_object); | 439 cache->objects().front()->IsInitialized()); |
| 440 SetVirtualObject(alias, obj); |
| 441 mergeObject = obj; |
| 442 changed = true; |
| 443 } else if (copy_merge_object) { |
| 444 VirtualObject* obj = new (zone) VirtualObject(this, *mergeObject); |
| 445 SetVirtualObject(alias, obj); |
| 446 mergeObject = obj; |
| 447 changed = true; |
| 448 } else { |
| 449 changed = mergeObject->ResizeFields(fields) || changed; |
| 450 } |
400 #ifdef DEBUG | 451 #ifdef DEBUG |
401 if (FLAG_trace_turbo_escape) { | 452 if (FLAG_trace_turbo_escape) { |
402 PrintF(" Alias @%d, merging into %p virtual objects", alias, | 453 PrintF(" Alias @%d, merging into %p virtual objects", alias, |
403 static_cast<void*>(mergeObject)); | 454 static_cast<void*>(mergeObject)); |
404 for (size_t i = 0; i < cache->objects().size(); i++) { | 455 for (size_t i = 0; i < cache->objects().size(); i++) { |
405 PrintF(" %p", static_cast<void*>(cache->objects()[i])); | 456 PrintF(" %p", static_cast<void*>(cache->objects()[i])); |
406 } | 457 } |
407 PrintF("\n"); | 458 PrintF("\n"); |
408 } | 459 } |
409 #endif // DEBUG | 460 #endif // DEBUG |
410 changed = mergeObject->ResizeFields(fields) || changed; | 461 changed = mergeObject->MergeFrom(cache, at, graph, common) || changed; |
411 for (size_t i = 0; i < fields; ++i) { | |
412 if (Node* field = cache->GetFields(i)) { | |
413 changed = changed || mergeObject->GetField(i) != field; | |
414 mergeObject->SetField(i, field); | |
415 TRACE(" Field %zu agree on rep #%d\n", i, field->id()); | |
416 } else { | |
417 int value_input_count = static_cast<int>(cache->fields().size()); | |
418 if (cache->fields().size() == arity) { | |
419 Node* rep = mergeObject->GetField(i); | |
420 if (!rep || !mergeObject->IsCreatedPhi(i)) { | |
421 cache->fields().push_back(control); | |
422 Node* phi = graph->NewNode( | |
423 common->Phi(MachineRepresentation::kTagged, | |
424 value_input_count), | |
425 value_input_count + 1, &cache->fields().front()); | |
426 mergeObject->SetField(i, phi, true); | |
427 #ifdef DEBUG | |
428 if (FLAG_trace_turbo_escape) { | |
429 PrintF(" Creating Phi #%d as merge of", phi->id()); | |
430 for (int i = 0; i < value_input_count; i++) { | |
431 PrintF(" #%d (%s)", cache->fields()[i]->id(), | |
432 cache->fields()[i]->op()->mnemonic()); | |
433 } | |
434 PrintF("\n"); | |
435 } | |
436 #endif // DEBUG | |
437 changed = true; | |
438 } else { | |
439 DCHECK(rep->opcode() == IrOpcode::kPhi); | |
440 for (int n = 0; n < value_input_count; ++n) { | |
441 Node* old = NodeProperties::GetValueInput(rep, n); | |
442 if (old != cache->fields()[n]) { | |
443 changed = true; | |
444 NodeProperties::ReplaceValueInput(rep, cache->fields()[n], n); | |
445 } | |
446 } | |
447 } | |
448 } else { | |
449 if (mergeObject->GetField(i) != nullptr) { | |
450 TRACE(" Field %zu cleared\n", i); | |
451 changed = true; | |
452 } | |
453 mergeObject->SetField(i, nullptr); | |
454 } | |
455 } | |
456 } | |
457 } else { | 462 } else { |
458 if (mergeObject) { | 463 if (mergeObject) { |
459 TRACE(" Alias %d, virtual object removed\n", alias); | 464 TRACE(" Alias %d, virtual object removed\n", alias); |
460 changed = true; | 465 changed = true; |
461 } | 466 } |
462 SetVirtualObject(alias, nullptr); | 467 SetVirtualObject(alias, nullptr); |
463 } | 468 } |
464 } | 469 } |
465 return changed; | 470 return changed; |
466 } | 471 } |
467 | 472 |
468 EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis, | 473 EscapeStatusAnalysis::EscapeStatusAnalysis(EscapeAnalysis* object_analysis, |
469 Graph* graph, Zone* zone) | 474 Graph* graph, Zone* zone) |
470 : stack_(zone), | 475 : stack_(zone), |
471 object_analysis_(object_analysis), | 476 object_analysis_(object_analysis), |
472 graph_(graph), | 477 graph_(graph), |
473 zone_(zone), | 478 zone_(zone), |
474 status_(graph->NodeCount(), kUnknown, zone), | 479 status_(zone), |
475 next_free_alias_(0), | 480 next_free_alias_(0), |
476 status_stack_(zone), | 481 status_stack_(zone), |
477 aliases_(zone) {} | 482 aliases_(zone) {} |
478 | 483 |
479 EscapeStatusAnalysis::~EscapeStatusAnalysis() {} | 484 EscapeStatusAnalysis::~EscapeStatusAnalysis() {} |
480 | 485 |
481 bool EscapeStatusAnalysis::HasEntry(Node* node) { | 486 bool EscapeStatusAnalysis::HasEntry(Node* node) { |
482 return status_[node->id()] & (kTracked | kEscaped); | 487 return status_[node->id()] & (kTracked | kEscaped); |
483 } | 488 } |
484 | 489 |
(...skipping 285 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
770 replacements_.resize(graph()->NodeCount()); | 775 replacements_.resize(graph()->NodeCount()); |
771 status_analysis_.ResizeStatusVector(); | 776 status_analysis_.ResizeStatusVector(); |
772 RunObjectAnalysis(); | 777 RunObjectAnalysis(); |
773 status_analysis_.RunStatusAnalysis(); | 778 status_analysis_.RunStatusAnalysis(); |
774 } | 779 } |
775 } | 780 } |
776 | 781 |
777 void EscapeStatusAnalysis::AssignAliases() { | 782 void EscapeStatusAnalysis::AssignAliases() { |
778 size_t max_size = 1024; | 783 size_t max_size = 1024; |
779 size_t min_size = 32; | 784 size_t min_size = 32; |
780 size_t stack_size = std::min( | 785 size_t stack_size = |
781 std::max( | 786 std::min(std::max(graph()->NodeCount() / 5, min_size), max_size); |
782 std::min(graph()->NodeCount() / 5, graph()->NodeCount() / 20 + 128), | |
783 min_size), | |
784 max_size); | |
785 stack_.reserve(stack_size); | 787 stack_.reserve(stack_size); |
786 ResizeStatusVector(); | 788 ResizeStatusVector(); |
787 stack_.push_back(graph()->end()); | 789 stack_.push_back(graph()->end()); |
788 CHECK_LT(graph()->NodeCount(), kUntrackable); | 790 CHECK_LT(graph()->NodeCount(), kUntrackable); |
789 aliases_.resize(graph()->NodeCount(), kNotReachable); | 791 aliases_.resize(graph()->NodeCount(), kNotReachable); |
790 aliases_[graph()->end()->id()] = kUntrackable; | 792 aliases_[graph()->end()->id()] = kUntrackable; |
791 status_stack_.reserve(8); | 793 status_stack_.reserve(8); |
792 TRACE("Discovering trackable nodes"); | 794 TRACE("Discovering trackable nodes"); |
793 while (!stack_.empty()) { | 795 while (!stack_.empty()) { |
794 Node* node = stack_.back(); | 796 Node* node = stack_.back(); |
(...skipping 199 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
994 case IrOpcode::kStoreElement: | 996 case IrOpcode::kStoreElement: |
995 case IrOpcode::kLoadElement: | 997 case IrOpcode::kLoadElement: |
996 case IrOpcode::kFrameState: | 998 case IrOpcode::kFrameState: |
997 case IrOpcode::kStateValues: | 999 case IrOpcode::kStateValues: |
998 case IrOpcode::kReferenceEqual: | 1000 case IrOpcode::kReferenceEqual: |
999 case IrOpcode::kFinishRegion: | 1001 case IrOpcode::kFinishRegion: |
1000 case IrOpcode::kObjectIsSmi: | 1002 case IrOpcode::kObjectIsSmi: |
1001 break; | 1003 break; |
1002 default: | 1004 default: |
1003 VirtualState* state = virtual_states_[node->id()]; | 1005 VirtualState* state = virtual_states_[node->id()]; |
1004 if (VirtualObject* obj = ResolveVirtualObject(state, input)) { | 1006 if (VirtualObject* obj = |
| 1007 GetVirtualObject(state, ResolveReplacement(input))) { |
1005 if (!obj->AllFieldsClear()) { | 1008 if (!obj->AllFieldsClear()) { |
1006 obj = CopyForModificationAt(obj, state, node); | 1009 obj = CopyForModificationAt(obj, state, node); |
1007 obj->ClearAllFields(); | 1010 obj->ClearAllFields(); |
1008 TRACE("Cleared all fields of @%d:#%d\n", GetAlias(obj->id()), | 1011 TRACE("Cleared all fields of @%d:#%d\n", GetAlias(obj->id()), |
1009 obj->id()); | 1012 obj->id()); |
1010 } | 1013 } |
1011 } | 1014 } |
1012 break; | 1015 break; |
1013 } | 1016 } |
1014 } | 1017 } |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1106 } | 1109 } |
1107 TRACE(" %p (from %d %s)", static_cast<void*>(state), input->id(), | 1110 TRACE(" %p (from %d %s)", static_cast<void*>(state), input->id(), |
1108 input->op()->mnemonic()); | 1111 input->op()->mnemonic()); |
1109 } | 1112 } |
1110 TRACE("\n"); | 1113 TRACE("\n"); |
1111 | 1114 |
1112 if (cache_->states().size() == 0) { | 1115 if (cache_->states().size() == 0) { |
1113 return changed; | 1116 return changed; |
1114 } | 1117 } |
1115 | 1118 |
1116 changed = mergeState->MergeFrom(cache_, zone(), graph(), common(), | 1119 changed = |
1117 NodeProperties::GetControlInput(node), | 1120 mergeState->MergeFrom(cache_, zone(), graph(), common(), node) || changed; |
1118 node->op()->EffectInputCount()) || | |
1119 changed; | |
1120 | 1121 |
1121 TRACE("Merge %s the node.\n", changed ? "changed" : "did not change"); | 1122 TRACE("Merge %s the node.\n", changed ? "changed" : "did not change"); |
1122 | 1123 |
1123 if (changed) { | 1124 if (changed) { |
1124 status_analysis_.ResizeStatusVector(); | 1125 status_analysis_.ResizeStatusVector(); |
1125 } | 1126 } |
1126 return changed; | 1127 return changed; |
1127 } | 1128 } |
1128 | 1129 |
1129 void EscapeAnalysis::ProcessAllocation(Node* node) { | 1130 void EscapeAnalysis::ProcessAllocation(Node* node) { |
(...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1235 return status_analysis_.SetEscaped(node); | 1236 return status_analysis_.SetEscaped(node); |
1236 } | 1237 } |
1237 | 1238 |
1238 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) { | 1239 VirtualObject* EscapeAnalysis::GetVirtualObject(Node* at, NodeId id) { |
1239 if (VirtualState* states = virtual_states_[at->id()]) { | 1240 if (VirtualState* states = virtual_states_[at->id()]) { |
1240 return states->VirtualObjectFromAlias(GetAlias(id)); | 1241 return states->VirtualObjectFromAlias(GetAlias(id)); |
1241 } | 1242 } |
1242 return nullptr; | 1243 return nullptr; |
1243 } | 1244 } |
1244 | 1245 |
1245 VirtualObject* EscapeAnalysis::ResolveVirtualObject(VirtualState* state, | |
1246 Node* node) { | |
1247 return GetVirtualObject(state, ResolveReplacement(node)); | |
1248 } | |
1249 | |
1250 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) { | 1246 bool EscapeAnalysis::CompareVirtualObjects(Node* left, Node* right) { |
1251 DCHECK(IsVirtual(left) && IsVirtual(right)); | 1247 DCHECK(IsVirtual(left) && IsVirtual(right)); |
1252 left = ResolveReplacement(left); | 1248 left = ResolveReplacement(left); |
1253 right = ResolveReplacement(right); | 1249 right = ResolveReplacement(right); |
1254 if (IsEquivalentPhi(left, right)) { | 1250 if (IsEquivalentPhi(left, right)) { |
1255 return true; | 1251 return true; |
1256 } | 1252 } |
1257 return false; | 1253 return false; |
1258 } | 1254 } |
1259 | 1255 |
1260 int EscapeAnalysis::OffsetFromAccess(Node* node) { | 1256 int EscapeAnalysis::OffsetFromAccess(Node* node) { |
1261 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0); | 1257 DCHECK(OpParameter<FieldAccess>(node).offset % kPointerSize == 0); |
1262 return OpParameter<FieldAccess>(node).offset / kPointerSize; | 1258 return OpParameter<FieldAccess>(node).offset / kPointerSize; |
1263 } | 1259 } |
1264 | 1260 |
1265 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* node, | 1261 void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* load, |
1266 VirtualState* state) { | 1262 VirtualState* state) { |
1267 TRACE("Load #%d from phi #%d", node->id(), from->id()); | 1263 TRACE("Load #%d from phi #%d", load->id(), from->id()); |
1268 | 1264 |
1269 cache_->fields().clear(); | 1265 cache_->fields().clear(); |
1270 for (int i = 0; i < node->op()->ValueInputCount(); ++i) { | 1266 for (int i = 0; i < load->op()->ValueInputCount(); ++i) { |
1271 Node* input = NodeProperties::GetValueInput(node, i); | 1267 Node* input = NodeProperties::GetValueInput(load, i); |
1272 cache_->fields().push_back(input); | 1268 cache_->fields().push_back(input); |
1273 } | 1269 } |
1274 | 1270 |
1275 cache_->LoadVirtualObjectsForFieldsFrom(state, | 1271 cache_->LoadVirtualObjectsForFieldsFrom(state, |
1276 status_analysis_.GetAliasMap()); | 1272 status_analysis_.GetAliasMap()); |
1277 if (cache_->objects().size() == cache_->fields().size()) { | 1273 if (cache_->objects().size() == cache_->fields().size()) { |
1278 cache_->GetFields(offset); | 1274 cache_->GetFields(offset); |
1279 if (cache_->fields().size() == cache_->objects().size()) { | 1275 if (cache_->fields().size() == cache_->objects().size()) { |
1280 Node* rep = replacement(node); | 1276 Node* rep = replacement(load); |
1281 if (!rep || !IsEquivalentPhi(rep, cache_->fields())) { | 1277 if (!rep || !IsEquivalentPhi(rep, cache_->fields())) { |
1282 int value_input_count = static_cast<int>(cache_->fields().size()); | 1278 int value_input_count = static_cast<int>(cache_->fields().size()); |
1283 cache_->fields().push_back(NodeProperties::GetControlInput(from)); | 1279 cache_->fields().push_back(NodeProperties::GetControlInput(from)); |
1284 Node* phi = graph()->NewNode( | 1280 Node* phi = graph()->NewNode( |
1285 common()->Phi(MachineRepresentation::kTagged, value_input_count), | 1281 common()->Phi(MachineRepresentation::kTagged, value_input_count), |
1286 value_input_count + 1, &cache_->fields().front()); | 1282 value_input_count + 1, &cache_->fields().front()); |
1287 status_analysis_.ResizeStatusVector(); | 1283 status_analysis_.ResizeStatusVector(); |
1288 SetReplacement(node, phi); | 1284 SetReplacement(load, phi); |
1289 TRACE(" got phi created.\n"); | 1285 TRACE(" got phi created.\n"); |
1290 } else { | 1286 } else { |
1291 TRACE(" has already phi #%d.\n", rep->id()); | 1287 TRACE(" has already phi #%d.\n", rep->id()); |
1292 } | 1288 } |
1293 } else { | 1289 } else { |
1294 TRACE(" has incomplete field info.\n"); | 1290 TRACE(" has incomplete field info.\n"); |
1295 } | 1291 } |
1296 } else { | 1292 } else { |
1297 TRACE(" has incomplete virtual object info.\n"); | 1293 TRACE(" has incomplete virtual object info.\n"); |
1298 } | 1294 } |
(...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1434 obj->id()); | 1430 obj->id()); |
1435 } | 1431 } |
1436 } | 1432 } |
1437 } | 1433 } |
1438 } | 1434 } |
1439 | 1435 |
1440 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) { | 1436 Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) { |
1441 if ((node->opcode() == IrOpcode::kFinishRegion || | 1437 if ((node->opcode() == IrOpcode::kFinishRegion || |
1442 node->opcode() == IrOpcode::kAllocate) && | 1438 node->opcode() == IrOpcode::kAllocate) && |
1443 IsVirtual(node)) { | 1439 IsVirtual(node)) { |
1444 if (VirtualObject* vobj = | 1440 if (VirtualObject* vobj = GetVirtualObject(virtual_states_[effect->id()], |
1445 ResolveVirtualObject(virtual_states_[effect->id()], node)) { | 1441 ResolveReplacement(node))) { |
1446 if (Node* object_state = vobj->GetObjectState()) { | 1442 if (Node* object_state = vobj->GetObjectState()) { |
1447 return object_state; | 1443 return object_state; |
1448 } else { | 1444 } else { |
1449 cache_->fields().clear(); | 1445 cache_->fields().clear(); |
1450 for (size_t i = 0; i < vobj->field_count(); ++i) { | 1446 for (size_t i = 0; i < vobj->field_count(); ++i) { |
1451 if (Node* field = vobj->GetField(i)) { | 1447 if (Node* field = vobj->GetField(i)) { |
1452 cache_->fields().push_back(field); | 1448 cache_->fields().push_back(field); |
1453 } | 1449 } |
1454 } | 1450 } |
1455 int input_count = static_cast<int>(cache_->fields().size()); | 1451 int input_count = static_cast<int>(cache_->fields().size()); |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1529 return true; | 1525 return true; |
1530 } | 1526 } |
1531 } | 1527 } |
1532 } | 1528 } |
1533 return false; | 1529 return false; |
1534 } | 1530 } |
1535 | 1531 |
1536 } // namespace compiler | 1532 } // namespace compiler |
1537 } // namespace internal | 1533 } // namespace internal |
1538 } // namespace v8 | 1534 } // namespace v8 |
OLD | NEW |