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

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: 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
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 UniqueSet<Map>* maps = new(zone) UniqueSet<Map>();
291 for (int i = 0; i < entry->maps_->size(); ++i) {
292 Unique<Map> map = entry->maps_->at(i);
293 if (!string_maps()->Contains(map)) maps->Add(map, zone);
294 }
Igor Sheludko 2014/05/30 10:00:41 Suggestion: What about adding Subtract() method to
Benedikt Meurer 2014/05/31 11:15:46 Done.
295 entry->maps_ = maps;
296 ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, entry->state_);
297 }
298 }
264 } 299 }
265 // Learning on false branches requires storing negative facts. 300 // Learning on false branches requires storing negative facts.
266 } 301 }
267 302
268 if (FLAG_trace_check_elimination) { 303 if (FLAG_trace_check_elimination) {
269 PrintF("B%d checkmaps-table %s from B%d:\n", 304 PrintF("B%d checkmaps-table %s from B%d:\n",
270 succ->block_id(), 305 succ->block_id(),
271 learned ? "learned" : "copied", 306 learned ? "learned" : "copied",
272 from_block->block_id()); 307 from_block->block_id());
273 Print(copy); 308 Print(copy);
(...skipping 134 matching lines...) Expand 10 before | Expand all | Expand 10 after
408 } else { 443 } else {
409 // No entry; insert a new one. 444 // No entry; insert a new one.
410 HCheckTableEntry::State state = instr->maps_are_stable() 445 HCheckTableEntry::State state = instr->maps_are_stable()
411 ? HCheckTableEntry::CHECKED_STABLE 446 ? HCheckTableEntry::CHECKED_STABLE
412 : HCheckTableEntry::CHECKED; 447 : HCheckTableEntry::CHECKED;
413 HCheckMaps* check = instr->IsStabilityCheck() ? NULL : instr; 448 HCheckMaps* check = instr->IsStabilityCheck() ? NULL : instr;
414 Insert(object, check, instr->maps(), state); 449 Insert(object, check, instr->maps(), state);
415 } 450 }
416 } 451 }
417 452
453 void ReduceCheckInstanceType(HCheckInstanceType* instr) {
454 HValue* value = instr->value()->ActualValue();
455 HCheckTableEntry* entry = Find(value);
456 if (entry == NULL) return;
457 for (int i = 0; i < entry->maps_->size(); ++i) {
458 InstanceType type;
459 Handle<Map> map = entry->maps_->at(i).handle();
460 {
461 // This is safe, because maps don't move and their instance type does
462 // not change.
463 AllowHandleDereference allow_deref;
464 type = map->instance_type();
465 }
466 if (instr->is_interval_check()) {
467 InstanceType first_type, last_type;
468 instr->GetCheckInterval(&first_type, &last_type);
469 if (type < first_type || last_type < type) return;
470 } else {
471 uint8_t mask, tag;
472 instr->GetCheckMaskAndTag(&mask, &tag);
473 if ((type & mask) != tag) return;
474 }
475 }
Igor Sheludko 2014/05/30 10:00:41 Does it make sense to update set of entry maps if
Benedikt Meurer 2014/05/31 11:15:46 Done.
476 TRACE(("Removing redundant CheckInstanceType #%d at B%d\n",
477 instr->id(), instr->block()->block_id()));
478 EnsureChecked(entry, value, instr);
479 instr->DeleteAndReplaceWith(value);
480 INC_STAT(removed_cit_);
481 return;
482 }
483
418 void ReduceLoadNamedField(HLoadNamedField* instr) { 484 void ReduceLoadNamedField(HLoadNamedField* instr) {
419 // Reduce a load of the map field when it is known to be a constant. 485 // Reduce a load of the map field when it is known to be a constant.
420 if (!instr->access().IsMap()) { 486 if (!instr->access().IsMap()) {
421 // Check if we introduce field maps here. 487 // Check if we introduce field maps here.
422 MapSet maps = instr->maps(); 488 MapSet maps = instr->maps();
423 if (maps != NULL) { 489 if (maps != NULL) {
424 ASSERT_NE(0, maps->size()); 490 ASSERT_NE(0, maps->size());
425 Insert(instr, NULL, maps, HCheckTableEntry::UNCHECKED_STABLE); 491 Insert(instr, NULL, maps, HCheckTableEntry::UNCHECKED_STABLE);
426 } 492 }
427 return; 493 return;
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after
521 587
522 TRACE(("Marking redundant CompareObjectEqAndBranch #%d at B%d as false\n", 588 TRACE(("Marking redundant CompareObjectEqAndBranch #%d at B%d as false\n",
523 instr->id(), instr->block()->block_id())); 589 instr->id(), instr->block()->block_id()));
524 int succ = 1; 590 int succ = 1;
525 instr->set_known_successor_index(succ); 591 instr->set_known_successor_index(succ);
526 592
527 int unreachable_succ = 1 - succ; 593 int unreachable_succ = 1 - succ;
528 instr->block()->MarkSuccEdgeUnreachable(unreachable_succ); 594 instr->block()->MarkSuccEdgeUnreachable(unreachable_succ);
529 } 595 }
530 596
597 void ReduceIsStringAndBranch(HIsStringAndBranch* instr) {
598 HValue* value = instr->value()->ActualValue();
599 HCheckTableEntry* entry = Find(value);
600 if (entry == NULL) return;
601 EnsureChecked(entry, value, instr);
602 if (entry->maps_->IsSubset(string_maps())) {
603 TRACE(("Marking redundant IsStringAndBranch #%d at B%d as true\n",
604 instr->id(), instr->block()->block_id()));
605 int succ = 0;
606 instr->set_known_successor_index(succ);
607
608 int unreachable_succ = 1 - succ;
609 instr->block()->MarkSuccEdgeUnreachable(unreachable_succ);
610 return;
611 }
612
613 // TODO(bmeurer): Add a predicate here instead of computing the intersection
614 MapSet intersection = entry->maps_->Intersect(string_maps(), zone());
615 if (intersection->size() > 0) return;
616
617 TRACE(("Marking redundant IsStringAndBranch #%d at B%d as false\n",
618 instr->id(), instr->block()->block_id()));
619 int succ = 1;
620 instr->set_known_successor_index(succ);
621
622 int unreachable_succ = 1 - succ;
623 instr->block()->MarkSuccEdgeUnreachable(unreachable_succ);
Igor Sheludko 2014/05/30 10:00:41 I would suggest to avoid duplication of the three
Benedikt Meurer 2014/05/31 11:15:46 Done.
624 }
625
531 void ReduceTransitionElementsKind(HTransitionElementsKind* instr) { 626 void ReduceTransitionElementsKind(HTransitionElementsKind* instr) {
532 HValue* object = instr->object()->ActualValue(); 627 HValue* object = instr->object()->ActualValue();
533 HCheckTableEntry* entry = Find(object); 628 HCheckTableEntry* entry = Find(object);
534 // Can only learn more about an object that already has a known set of maps. 629 // Can only learn more about an object that already has a known set of maps.
535 if (entry == NULL) return; 630 if (entry == NULL) return;
536 EnsureChecked(entry, object, instr); 631 EnsureChecked(entry, object, instr);
537 if (entry->maps_->Contains(instr->original_map())) { 632 if (entry->maps_->Contains(instr->original_map())) {
538 // If the object has the original map, it will be transitioned. 633 // If the object has the original map, it will be transitioned.
539 UniqueSet<Map>* maps = entry->maps_->Copy(zone()); 634 UniqueSet<Map>* maps = entry->maps_->Copy(zone());
540 maps->Remove(instr->original_map()); 635 maps->Remove(instr->original_map());
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
681 entry->object_ = object; 776 entry->object_ = object;
682 entry->check_ = check; 777 entry->check_ = check;
683 entry->maps_ = maps; 778 entry->maps_ = maps;
684 entry->state_ = state; 779 entry->state_ = state;
685 // If the table becomes full, wrap around and overwrite older entries. 780 // If the table becomes full, wrap around and overwrite older entries.
686 if (cursor_ == kMaxTrackedObjects) cursor_ = 0; 781 if (cursor_ == kMaxTrackedObjects) cursor_ = 0;
687 if (size_ < kMaxTrackedObjects) size_++; 782 if (size_ < kMaxTrackedObjects) size_++;
688 } 783 }
689 784
690 Zone* zone() const { return phase_->zone(); } 785 Zone* zone() const { return phase_->zone(); }
786 MapSet string_maps() const { return phase_->string_maps(); }
691 787
692 friend class HCheckMapsEffects; 788 friend class HCheckMapsEffects;
693 friend class HCheckEliminationPhase; 789 friend class HCheckEliminationPhase;
694 790
695 HCheckEliminationPhase* phase_; 791 HCheckEliminationPhase* phase_;
696 HCheckTableEntry entries_[kMaxTrackedObjects]; 792 HCheckTableEntry entries_[kMaxTrackedObjects];
697 int16_t cursor_; // Must be <= kMaxTrackedObjects 793 int16_t cursor_; // Must be <= kMaxTrackedObjects
698 int16_t size_; // Must be <= kMaxTrackedObjects 794 int16_t size_; // Must be <= kMaxTrackedObjects
699 STATIC_ASSERT(kMaxTrackedObjects < (1 << 15)); 795 STATIC_ASSERT(kMaxTrackedObjects < (1 << 15));
700 }; 796 };
(...skipping 86 matching lines...) Expand 10 before | Expand all | Expand 10 after
787 // Are we eliminated yet? 883 // Are we eliminated yet?
788 void HCheckEliminationPhase::PrintStats() { 884 void HCheckEliminationPhase::PrintStats() {
789 #if DEBUG 885 #if DEBUG
790 #define PRINT_STAT(x) if (x##_ > 0) PrintF(" %-16s = %2d\n", #x, x##_) 886 #define PRINT_STAT(x) if (x##_ > 0) PrintF(" %-16s = %2d\n", #x, x##_)
791 #else 887 #else
792 #define PRINT_STAT(x) 888 #define PRINT_STAT(x)
793 #endif 889 #endif
794 PRINT_STAT(redundant); 890 PRINT_STAT(redundant);
795 PRINT_STAT(removed); 891 PRINT_STAT(removed);
796 PRINT_STAT(removed_cho); 892 PRINT_STAT(removed_cho);
893 PRINT_STAT(removed_cit);
797 PRINT_STAT(narrowed); 894 PRINT_STAT(narrowed);
798 PRINT_STAT(loads); 895 PRINT_STAT(loads);
799 PRINT_STAT(empty); 896 PRINT_STAT(empty);
800 PRINT_STAT(compares_true); 897 PRINT_STAT(compares_true);
801 PRINT_STAT(compares_false); 898 PRINT_STAT(compares_false);
802 PRINT_STAT(transitions); 899 PRINT_STAT(transitions);
803 } 900 }
804 901
805 } } // namespace v8::internal 902 } } // namespace v8::internal
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698