| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 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 "hydrogen-check-elimination.h" | 5 #include "hydrogen-check-elimination.h" |
| 6 #include "hydrogen-alias-analysis.h" | 6 #include "hydrogen-alias-analysis.h" |
| 7 #include "hydrogen-flow-engine.h" | 7 #include "hydrogen-flow-engine.h" |
| 8 | 8 |
| 9 #define GLOBAL 1 | 9 #define GLOBAL 1 |
| 10 | 10 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 63 } | 63 } |
| 64 case HValue::kCompareObjectEqAndBranch: { | 64 case HValue::kCompareObjectEqAndBranch: { |
| 65 ReduceCompareObjectEqAndBranch(HCompareObjectEqAndBranch::cast(instr)); | 65 ReduceCompareObjectEqAndBranch(HCompareObjectEqAndBranch::cast(instr)); |
| 66 break; | 66 break; |
| 67 } | 67 } |
| 68 case HValue::kTransitionElementsKind: { | 68 case HValue::kTransitionElementsKind: { |
| 69 ReduceTransitionElementsKind( | 69 ReduceTransitionElementsKind( |
| 70 HTransitionElementsKind::cast(instr)); | 70 HTransitionElementsKind::cast(instr)); |
| 71 break; | 71 break; |
| 72 } | 72 } |
| 73 case HValue::kCheckMapValue: { | |
| 74 ReduceCheckMapValue(HCheckMapValue::cast(instr)); | |
| 75 break; | |
| 76 } | |
| 77 case HValue::kCheckHeapObject: { | 73 case HValue::kCheckHeapObject: { |
| 78 ReduceCheckHeapObject(HCheckHeapObject::cast(instr)); | 74 ReduceCheckHeapObject(HCheckHeapObject::cast(instr)); |
| 79 break; | 75 break; |
| 80 } | 76 } |
| 81 default: { | 77 default: { |
| 82 // If the instruction changes maps uncontrollably, drop everything. | 78 // If the instruction changes maps uncontrollably, drop everything. |
| 83 if (instr->CheckChangesFlag(kElementsKind) || | 79 if (instr->CheckChangesFlag(kElementsKind) || |
| 84 instr->CheckChangesFlag(kMaps) || | 80 instr->CheckChangesFlag(kMaps) || |
| 85 instr->CheckChangesFlag(kOsrEntries)) { | 81 instr->CheckChangesFlag(kOsrEntries)) { |
| 86 Kill(); | 82 Kill(); |
| (...skipping 267 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 354 MapSet maps = FindMaps(object); | 350 MapSet maps = FindMaps(object); |
| 355 if (maps == NULL || maps->size() != 1) return; // Not a constant. | 351 if (maps == NULL || maps->size() != 1) return; // Not a constant. |
| 356 | 352 |
| 357 Unique<Map> map = maps->at(0); | 353 Unique<Map> map = maps->at(0); |
| 358 HConstant* constant = HConstant::CreateAndInsertBefore( | 354 HConstant* constant = HConstant::CreateAndInsertBefore( |
| 359 instr->block()->graph()->zone(), map, true, instr); | 355 instr->block()->graph()->zone(), map, true, instr); |
| 360 instr->DeleteAndReplaceWith(constant); | 356 instr->DeleteAndReplaceWith(constant); |
| 361 INC_STAT(loads_); | 357 INC_STAT(loads_); |
| 362 } | 358 } |
| 363 | 359 |
| 364 void ReduceCheckMapValue(HCheckMapValue* instr) { | |
| 365 if (!instr->map()->IsConstant()) return; // Nothing to learn. | |
| 366 | |
| 367 HValue* object = instr->value()->ActualValue(); | |
| 368 // Match a HCheckMapValue(object, HConstant(map)) | |
| 369 Unique<Map> map = MapConstant(instr->map()); | |
| 370 | |
| 371 HCheckTableEntry* entry = Find(object); | |
| 372 if (entry != NULL) { | |
| 373 if (entry->maps_->Contains(map)) { | |
| 374 if (entry->maps_->size() == 1) { | |
| 375 // Object is known to have exactly this map. | |
| 376 if (entry->check_ != NULL) { | |
| 377 instr->DeleteAndReplaceWith(entry->check_); | |
| 378 } else { | |
| 379 // Mark check as dead but leave it in the graph as a checkpoint for | |
| 380 // subsequent checks. | |
| 381 instr->SetFlag(HValue::kIsDead); | |
| 382 entry->check_ = instr; | |
| 383 } | |
| 384 INC_STAT(removed_); | |
| 385 } else { | |
| 386 // Only one map survives the check. | |
| 387 entry->maps_ = new(zone()) UniqueSet<Map>(map, zone()); | |
| 388 entry->check_ = instr; | |
| 389 } | |
| 390 } | |
| 391 } else { | |
| 392 // No prior information. | |
| 393 Insert(object, instr, map); | |
| 394 } | |
| 395 } | |
| 396 | |
| 397 void ReduceCheckHeapObject(HCheckHeapObject* instr) { | 360 void ReduceCheckHeapObject(HCheckHeapObject* instr) { |
| 398 if (FindMaps(instr->value()->ActualValue()) != NULL) { | 361 if (FindMaps(instr->value()->ActualValue()) != NULL) { |
| 399 // If the object has known maps, it's definitely a heap object. | 362 // If the object has known maps, it's definitely a heap object. |
| 400 instr->DeleteAndReplaceWith(instr->value()); | 363 instr->DeleteAndReplaceWith(instr->value()); |
| 401 INC_STAT(removed_cho_); | 364 INC_STAT(removed_cho_); |
| 402 } | 365 } |
| 403 } | 366 } |
| 404 | 367 |
| 405 void ReduceStoreNamedField(HStoreNamedField* instr) { | 368 void ReduceStoreNamedField(HStoreNamedField* instr) { |
| 406 HValue* object = instr->object()->ActualValue(); | 369 HValue* object = instr->object()->ActualValue(); |
| 407 if (instr->has_transition()) { | 370 if (instr->has_transition()) { |
| 408 // This store transitions the object to a new map. | 371 // This store transitions the object to a new map. |
| 409 Kill(object); | 372 Kill(object); |
| 410 Insert(object, NULL, MapConstant(instr->transition())); | 373 Insert(object, NULL, HConstant::cast(instr->transition())->MapValue()); |
| 411 } else if (instr->access().IsMap()) { | 374 } else if (instr->access().IsMap()) { |
| 412 // This is a store directly to the map field of the object. | 375 // This is a store directly to the map field of the object. |
| 413 Kill(object); | 376 Kill(object); |
| 414 if (!instr->value()->IsConstant()) return; | 377 if (!instr->value()->IsConstant()) return; |
| 415 Insert(object, NULL, MapConstant(instr->value())); | 378 Insert(object, NULL, HConstant::cast(instr->value())->MapValue()); |
| 416 } else { | 379 } else { |
| 417 // If the instruction changes maps, it should be handled above. | 380 // If the instruction changes maps, it should be handled above. |
| 418 CHECK(!instr->CheckChangesFlag(kMaps)); | 381 CHECK(!instr->CheckChangesFlag(kMaps)); |
| 419 } | 382 } |
| 420 } | 383 } |
| 421 | 384 |
| 422 void ReduceCompareMap(HCompareMap* instr) { | 385 void ReduceCompareMap(HCompareMap* instr) { |
| 423 MapSet maps = FindMaps(instr->value()->ActualValue()); | 386 MapSet maps = FindMaps(instr->value()->ActualValue()); |
| 424 if (maps == NULL) return; | 387 if (maps == NULL) return; |
| 425 | 388 |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 580 void Insert(HValue* object, HInstruction* check, MapSet maps) { | 543 void Insert(HValue* object, HInstruction* check, MapSet maps) { |
| 581 HCheckTableEntry* entry = &entries_[cursor_++]; | 544 HCheckTableEntry* entry = &entries_[cursor_++]; |
| 582 entry->object_ = object; | 545 entry->object_ = object; |
| 583 entry->check_ = check; | 546 entry->check_ = check; |
| 584 entry->maps_ = maps; | 547 entry->maps_ = maps; |
| 585 // If the table becomes full, wrap around and overwrite older entries. | 548 // If the table becomes full, wrap around and overwrite older entries. |
| 586 if (cursor_ == kMaxTrackedObjects) cursor_ = 0; | 549 if (cursor_ == kMaxTrackedObjects) cursor_ = 0; |
| 587 if (size_ < kMaxTrackedObjects) size_++; | 550 if (size_ < kMaxTrackedObjects) size_++; |
| 588 } | 551 } |
| 589 | 552 |
| 590 Unique<Map> MapConstant(HValue* value) { | |
| 591 return Unique<Map>::cast(HConstant::cast(value)->GetUnique()); | |
| 592 } | |
| 593 | |
| 594 Zone* zone() const { return phase_->zone(); } | 553 Zone* zone() const { return phase_->zone(); } |
| 595 | 554 |
| 596 friend class HCheckMapsEffects; | 555 friend class HCheckMapsEffects; |
| 597 friend class HCheckEliminationPhase; | 556 friend class HCheckEliminationPhase; |
| 598 | 557 |
| 599 HCheckEliminationPhase* phase_; | 558 HCheckEliminationPhase* phase_; |
| 600 HCheckTableEntry entries_[kMaxTrackedObjects]; | 559 HCheckTableEntry entries_[kMaxTrackedObjects]; |
| 601 int16_t cursor_; // Must be <= kMaxTrackedObjects | 560 int16_t cursor_; // Must be <= kMaxTrackedObjects |
| 602 int16_t size_; // Must be <= kMaxTrackedObjects | 561 int16_t size_; // Must be <= kMaxTrackedObjects |
| 603 // TODO(titzer): STATIC_ASSERT kMaxTrackedObjects < max(cursor_) | 562 // TODO(titzer): STATIC_ASSERT kMaxTrackedObjects < max(cursor_) |
| (...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 697 PRINT_STAT(removed_cho); | 656 PRINT_STAT(removed_cho); |
| 698 PRINT_STAT(narrowed); | 657 PRINT_STAT(narrowed); |
| 699 PRINT_STAT(loads); | 658 PRINT_STAT(loads); |
| 700 PRINT_STAT(empty); | 659 PRINT_STAT(empty); |
| 701 PRINT_STAT(compares_true); | 660 PRINT_STAT(compares_true); |
| 702 PRINT_STAT(compares_false); | 661 PRINT_STAT(compares_false); |
| 703 PRINT_STAT(transitions); | 662 PRINT_STAT(transitions); |
| 704 } | 663 } |
| 705 | 664 |
| 706 } } // namespace v8::internal | 665 } } // namespace v8::internal |
| OLD | NEW |