| 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 "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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 Loading... |
| 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 |
| OLD | NEW |