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

Side by Side Diff: src/hydrogen-check-elimination.cc

Issue 300423003: Handle HCheckInstanceType and HIsStringAndBranch in check elimination. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Addressed comments Created 6 years, 6 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 | Annotate | Revision Log
« no previous file with comments | « src/hydrogen-check-elimination.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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 6
7 #include "hydrogen-alias-analysis.h" 7 #include "hydrogen-alias-analysis.h"
8 #include "hydrogen-flow-engine.h" 8 #include "hydrogen-flow-engine.h"
9 9
10 #define GLOBAL 1 10 #define GLOBAL 1
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 break; 97 break;
98 } 98 }
99 case HValue::kCompareMap: { 99 case HValue::kCompareMap: {
100 ReduceCompareMap(HCompareMap::cast(instr)); 100 ReduceCompareMap(HCompareMap::cast(instr));
101 break; 101 break;
102 } 102 }
103 case HValue::kCompareObjectEqAndBranch: { 103 case HValue::kCompareObjectEqAndBranch: {
104 ReduceCompareObjectEqAndBranch(HCompareObjectEqAndBranch::cast(instr)); 104 ReduceCompareObjectEqAndBranch(HCompareObjectEqAndBranch::cast(instr));
105 break; 105 break;
106 } 106 }
107 case HValue::kIsStringAndBranch: {
108 ReduceIsStringAndBranch(HIsStringAndBranch::cast(instr));
109 break;
110 }
107 case HValue::kTransitionElementsKind: { 111 case HValue::kTransitionElementsKind: {
108 ReduceTransitionElementsKind( 112 ReduceTransitionElementsKind(
109 HTransitionElementsKind::cast(instr)); 113 HTransitionElementsKind::cast(instr));
110 break; 114 break;
111 } 115 }
112 case HValue::kCheckHeapObject: { 116 case HValue::kCheckHeapObject: {
113 ReduceCheckHeapObject(HCheckHeapObject::cast(instr)); 117 ReduceCheckHeapObject(HCheckHeapObject::cast(instr));
114 break; 118 break;
115 } 119 }
120 case HValue::kCheckInstanceType: {
121 ReduceCheckInstanceType(HCheckInstanceType::cast(instr));
122 break;
123 }
116 default: { 124 default: {
117 // If the instruction changes maps uncontrollably, drop everything. 125 // If the instruction changes maps uncontrollably, drop everything.
118 if (instr->CheckChangesFlag(kOsrEntries)) { 126 if (instr->CheckChangesFlag(kOsrEntries)) {
119 Kill(); 127 Kill();
120 break; 128 break;
121 } 129 }
122 if (instr->CheckChangesFlag(kElementsKind) || 130 if (instr->CheckChangesFlag(kElementsKind) ||
123 instr->CheckChangesFlag(kMaps)) { 131 instr->CheckChangesFlag(kMaps)) {
124 KillUnstableEntries(); 132 KillUnstableEntries();
125 } 133 }
126 } 134 }
127 // Improvements possible: 135 // Improvements possible:
128 // - eliminate redundant HCheckSmi, HCheckInstanceType instructions 136 // - eliminate redundant HCheckSmi instructions
129 // - track which values have been HCheckHeapObject'd 137 // - track which values have been HCheckHeapObject'd
130 } 138 }
131 139
132 return this; 140 return this;
133 } 141 }
134 142
135 // Support for global analysis with HFlowEngine: Merge given state with 143 // Support for global analysis with HFlowEngine: Merge given state with
136 // the other incoming state. 144 // the other incoming state.
137 static HCheckTable* Merge(HCheckTable* succ_state, HBasicBlock* succ_block, 145 static HCheckTable* Merge(HCheckTable* succ_state, HBasicBlock* succ_block,
138 HCheckTable* pred_state, HBasicBlock* pred_block, 146 HCheckTable* pred_state, HBasicBlock* pred_block,
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 } else { 262 } else {
255 EnsureChecked(le, cmp->left(), cmp); 263 EnsureChecked(le, cmp->left(), cmp);
256 EnsureChecked(re, cmp->right(), cmp); 264 EnsureChecked(re, cmp->right(), cmp);
257 le->maps_ = re->maps_ = le->maps_->Intersect(re->maps_, zone); 265 le->maps_ = re->maps_ = le->maps_->Intersect(re->maps_, zone);
258 le->state_ = re->state_ = HCheckTableEntry::StateMerge( 266 le->state_ = re->state_ = HCheckTableEntry::StateMerge(
259 le->state_, re->state_); 267 le->state_, re->state_);
260 ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, le->state_); 268 ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, le->state_);
261 ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, re->state_); 269 ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, re->state_);
262 } 270 }
263 learned = true; 271 learned = true;
272 } else if (end->IsIsStringAndBranch()) {
273 HIsStringAndBranch* cmp = HIsStringAndBranch::cast(end);
274 HValue* object = cmp->value()->ActualValue();
275 HCheckTableEntry* entry = copy->Find(object);
276 if (is_true_branch) {
277 // Learn on the true branch of if(IsString(x)).
278 if (entry == NULL) {
279 copy->Insert(object, NULL, string_maps(),
280 HCheckTableEntry::CHECKED);
281 } else {
282 EnsureChecked(entry, object, cmp);
283 entry->maps_ = entry->maps_->Intersect(string_maps(), zone);
284 ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, entry->state_);
285 }
286 } else {
287 // Learn on the false branch of if(IsString(x)).
288 if (entry != NULL) {
289 EnsureChecked(entry, object, cmp);
290 entry->maps_ = entry->maps_->Subtract(string_maps(), zone);
291 ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, entry->state_);
292 }
293 }
264 } 294 }
265 // Learning on false branches requires storing negative facts. 295 // Learning on false branches requires storing negative facts.
266 } 296 }
267 297
268 if (FLAG_trace_check_elimination) { 298 if (FLAG_trace_check_elimination) {
269 PrintF("B%d checkmaps-table %s from B%d:\n", 299 PrintF("B%d checkmaps-table %s from B%d:\n",
270 succ->block_id(), 300 succ->block_id(),
271 learned ? "learned" : "copied", 301 learned ? "learned" : "copied",
272 from_block->block_id()); 302 from_block->block_id());
273 Print(copy); 303 Print(copy);
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 } else { 438 } else {
409 // No entry; insert a new one. 439 // No entry; insert a new one.
410 HCheckTableEntry::State state = instr->maps_are_stable() 440 HCheckTableEntry::State state = instr->maps_are_stable()
411 ? HCheckTableEntry::CHECKED_STABLE 441 ? HCheckTableEntry::CHECKED_STABLE
412 : HCheckTableEntry::CHECKED; 442 : HCheckTableEntry::CHECKED;
413 HCheckMaps* check = instr->IsStabilityCheck() ? NULL : instr; 443 HCheckMaps* check = instr->IsStabilityCheck() ? NULL : instr;
414 Insert(object, check, instr->maps(), state); 444 Insert(object, check, instr->maps(), state);
415 } 445 }
416 } 446 }
417 447
448 void ReduceCheckInstanceType(HCheckInstanceType* instr) {
449 HValue* value = instr->value()->ActualValue();
450 HCheckTableEntry* entry = Find(value);
451 if (entry == NULL) {
452 if (instr->check() == HCheckInstanceType::IS_STRING) {
453 Insert(value, NULL, string_maps(), HCheckTableEntry::CHECKED);
454 }
455 return;
456 }
457 UniqueSet<Map>* maps = new(zone()) UniqueSet<Map>(
458 entry->maps_->size(), zone());
459 for (int i = 0; i < entry->maps_->size(); ++i) {
460 InstanceType type;
461 Unique<Map> map = entry->maps_->at(i);
462 {
463 // This is safe, because maps don't move and their instance type does
464 // not change.
465 AllowHandleDereference allow_deref;
466 type = map.handle()->instance_type();
467 }
468 if (instr->is_interval_check()) {
469 InstanceType first_type, last_type;
470 instr->GetCheckInterval(&first_type, &last_type);
471 if (first_type <= type && type <= last_type) maps->Add(map, zone());
472 } else {
473 uint8_t mask, tag;
474 instr->GetCheckMaskAndTag(&mask, &tag);
475 if ((type & mask) == tag) maps->Add(map, zone());
476 }
477 }
478 if (maps->size() == entry->maps_->size()) {
479 TRACE(("Removing redundant CheckInstanceType #%d at B%d\n",
480 instr->id(), instr->block()->block_id()));
481 EnsureChecked(entry, value, instr);
482 instr->DeleteAndReplaceWith(value);
483 INC_STAT(removed_cit_);
484 } else if (maps->size() != 0) {
485 entry->maps_ = maps;
486 if (entry->state_ == HCheckTableEntry::UNCHECKED_STABLE) {
487 entry->state_ = HCheckTableEntry::CHECKED_STABLE;
488 }
489 }
490 }
491
418 void ReduceLoadNamedField(HLoadNamedField* instr) { 492 void ReduceLoadNamedField(HLoadNamedField* instr) {
419 // Reduce a load of the map field when it is known to be a constant. 493 // Reduce a load of the map field when it is known to be a constant.
420 if (!instr->access().IsMap()) { 494 if (!instr->access().IsMap()) {
421 // Check if we introduce field maps here. 495 // Check if we introduce field maps here.
422 MapSet maps = instr->maps(); 496 MapSet maps = instr->maps();
423 if (maps != NULL) { 497 if (maps != NULL) {
424 ASSERT_NE(0, maps->size()); 498 ASSERT_NE(0, maps->size());
425 Insert(instr, NULL, maps, HCheckTableEntry::UNCHECKED_STABLE); 499 Insert(instr, NULL, maps, HCheckTableEntry::UNCHECKED_STABLE);
426 } 500 }
427 return; 501 return;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 595
522 TRACE(("Marking redundant CompareObjectEqAndBranch #%d at B%d as false\n", 596 TRACE(("Marking redundant CompareObjectEqAndBranch #%d at B%d as false\n",
523 instr->id(), instr->block()->block_id())); 597 instr->id(), instr->block()->block_id()));
524 int succ = 1; 598 int succ = 1;
525 instr->set_known_successor_index(succ); 599 instr->set_known_successor_index(succ);
526 600
527 int unreachable_succ = 1 - succ; 601 int unreachable_succ = 1 - succ;
528 instr->block()->MarkSuccEdgeUnreachable(unreachable_succ); 602 instr->block()->MarkSuccEdgeUnreachable(unreachable_succ);
529 } 603 }
530 604
605 void ReduceIsStringAndBranch(HIsStringAndBranch* instr) {
606 HValue* value = instr->value()->ActualValue();
607 HCheckTableEntry* entry = Find(value);
608 if (entry == NULL) return;
609 EnsureChecked(entry, value, instr);
610 int succ;
611 if (entry->maps_->IsSubset(string_maps())) {
612 TRACE(("Marking redundant IsStringAndBranch #%d at B%d as true\n",
613 instr->id(), instr->block()->block_id()));
614 succ = 0;
615 } else {
616 MapSet intersection = entry->maps_->Intersect(string_maps(), zone());
617 if (intersection->size() > 0) return;
618 TRACE(("Marking redundant IsStringAndBranch #%d at B%d as false\n",
619 instr->id(), instr->block()->block_id()));
620 succ = 1;
621 }
622 instr->set_known_successor_index(succ);
623 int unreachable_succ = 1 - succ;
624 instr->block()->MarkSuccEdgeUnreachable(unreachable_succ);
625 }
626
531 void ReduceTransitionElementsKind(HTransitionElementsKind* instr) { 627 void ReduceTransitionElementsKind(HTransitionElementsKind* instr) {
532 HValue* object = instr->object()->ActualValue(); 628 HValue* object = instr->object()->ActualValue();
533 HCheckTableEntry* entry = Find(object); 629 HCheckTableEntry* entry = Find(object);
534 // Can only learn more about an object that already has a known set of maps. 630 // Can only learn more about an object that already has a known set of maps.
535 if (entry == NULL) return; 631 if (entry == NULL) return;
536 EnsureChecked(entry, object, instr); 632 EnsureChecked(entry, object, instr);
537 if (entry->maps_->Contains(instr->original_map())) { 633 if (entry->maps_->Contains(instr->original_map())) {
538 // If the object has the original map, it will be transitioned. 634 // If the object has the original map, it will be transitioned.
539 UniqueSet<Map>* maps = entry->maps_->Copy(zone()); 635 UniqueSet<Map>* maps = entry->maps_->Copy(zone());
540 maps->Remove(instr->original_map()); 636 maps->Remove(instr->original_map());
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 entry->object_ = object; 777 entry->object_ = object;
682 entry->check_ = check; 778 entry->check_ = check;
683 entry->maps_ = maps; 779 entry->maps_ = maps;
684 entry->state_ = state; 780 entry->state_ = state;
685 // If the table becomes full, wrap around and overwrite older entries. 781 // If the table becomes full, wrap around and overwrite older entries.
686 if (cursor_ == kMaxTrackedObjects) cursor_ = 0; 782 if (cursor_ == kMaxTrackedObjects) cursor_ = 0;
687 if (size_ < kMaxTrackedObjects) size_++; 783 if (size_ < kMaxTrackedObjects) size_++;
688 } 784 }
689 785
690 Zone* zone() const { return phase_->zone(); } 786 Zone* zone() const { return phase_->zone(); }
787 MapSet string_maps() const { return phase_->string_maps(); }
691 788
692 friend class HCheckMapsEffects; 789 friend class HCheckMapsEffects;
693 friend class HCheckEliminationPhase; 790 friend class HCheckEliminationPhase;
694 791
695 HCheckEliminationPhase* phase_; 792 HCheckEliminationPhase* phase_;
696 HCheckTableEntry entries_[kMaxTrackedObjects]; 793 HCheckTableEntry entries_[kMaxTrackedObjects];
697 int16_t cursor_; // Must be <= kMaxTrackedObjects 794 int16_t cursor_; // Must be <= kMaxTrackedObjects
698 int16_t size_; // Must be <= kMaxTrackedObjects 795 int16_t size_; // Must be <= kMaxTrackedObjects
699 STATIC_ASSERT(kMaxTrackedObjects < (1 << 15)); 796 STATIC_ASSERT(kMaxTrackedObjects < (1 << 15));
700 }; 797 };
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
787 // Are we eliminated yet? 884 // Are we eliminated yet?
788 void HCheckEliminationPhase::PrintStats() { 885 void HCheckEliminationPhase::PrintStats() {
789 #if DEBUG 886 #if DEBUG
790 #define PRINT_STAT(x) if (x##_ > 0) PrintF(" %-16s = %2d\n", #x, x##_) 887 #define PRINT_STAT(x) if (x##_ > 0) PrintF(" %-16s = %2d\n", #x, x##_)
791 #else 888 #else
792 #define PRINT_STAT(x) 889 #define PRINT_STAT(x)
793 #endif 890 #endif
794 PRINT_STAT(redundant); 891 PRINT_STAT(redundant);
795 PRINT_STAT(removed); 892 PRINT_STAT(removed);
796 PRINT_STAT(removed_cho); 893 PRINT_STAT(removed_cho);
894 PRINT_STAT(removed_cit);
797 PRINT_STAT(narrowed); 895 PRINT_STAT(narrowed);
798 PRINT_STAT(loads); 896 PRINT_STAT(loads);
799 PRINT_STAT(empty); 897 PRINT_STAT(empty);
800 PRINT_STAT(compares_true); 898 PRINT_STAT(compares_true);
801 PRINT_STAT(compares_false); 899 PRINT_STAT(compares_false);
802 PRINT_STAT(transitions); 900 PRINT_STAT(transitions);
803 } 901 }
804 902
805 } } // namespace v8::internal 903 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen-check-elimination.h ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698