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

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

Issue 137863005: Revert "Use stability to only conditionally flush information from the CheckMaps table." (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Created 6 years, 10 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.cc ('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 // Redistribution and use in source and binary forms, with or without 2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are 3 // modification, are permitted provided that the following conditions are
4 // met: 4 // met:
5 // 5 //
6 // * Redistributions of source code must retain the above copyright 6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer. 7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above 8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following 9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided 10 // disclaimer in the documentation and/or other materials provided
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
43 43
44 namespace v8 { 44 namespace v8 {
45 namespace internal { 45 namespace internal {
46 46
47 typedef UniqueSet<Map>* MapSet; 47 typedef UniqueSet<Map>* MapSet;
48 48
49 struct HCheckTableEntry { 49 struct HCheckTableEntry {
50 HValue* object_; // The object being approximated. NULL => invalid entry. 50 HValue* object_; // The object being approximated. NULL => invalid entry.
51 HInstruction* check_; // The last check instruction. 51 HInstruction* check_; // The last check instruction.
52 MapSet maps_; // The set of known maps for the object. 52 MapSet maps_; // The set of known maps for the object.
53 bool is_stable_;
54 }; 53 };
55 54
56 55
57 // The main data structure used during check elimination, which stores a 56 // The main data structure used during check elimination, which stores a
58 // set of known maps for each object. 57 // set of known maps for each object.
59 class HCheckTable : public ZoneObject { 58 class HCheckTable : public ZoneObject {
60 public: 59 public:
61 static const int kMaxTrackedObjects = 10; 60 static const int kMaxTrackedObjects = 10;
62 61
63 explicit HCheckTable(HCheckEliminationPhase* phase) 62 explicit HCheckTable(HCheckEliminationPhase* phase)
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
97 case HValue::kCheckMapValue: { 96 case HValue::kCheckMapValue: {
98 ReduceCheckMapValue(HCheckMapValue::cast(instr)); 97 ReduceCheckMapValue(HCheckMapValue::cast(instr));
99 break; 98 break;
100 } 99 }
101 case HValue::kCheckHeapObject: { 100 case HValue::kCheckHeapObject: {
102 ReduceCheckHeapObject(HCheckHeapObject::cast(instr)); 101 ReduceCheckHeapObject(HCheckHeapObject::cast(instr));
103 break; 102 break;
104 } 103 }
105 default: { 104 default: {
106 // If the instruction changes maps uncontrollably, drop everything. 105 // If the instruction changes maps uncontrollably, drop everything.
107 if (instr->CheckChangesFlag(kOsrEntries)) { 106 if (instr->CheckChangesFlag(kMaps) ||
108 Reset(); 107 instr->CheckChangesFlag(kOsrEntries)) {
109 } else if (instr->CheckChangesFlag(kMaps)) { 108 Kill();
110 KillUnstableEntries();
111 } 109 }
112 } 110 }
113 // Improvements possible: 111 // Improvements possible:
114 // - eliminate redundant HCheckSmi, HCheckInstanceType instructions 112 // - eliminate redundant HCheckSmi, HCheckInstanceType instructions
115 // - track which values have been HCheckHeapObject'd 113 // - track which values have been HCheckHeapObject'd
116 } 114 }
117 115
118 return this; 116 return this;
119 } 117 }
120 118
(...skipping 28 matching lines...) Expand all
149 HCheckTable* copy = new(phase_->zone()) HCheckTable(phase_); 147 HCheckTable* copy = new(phase_->zone()) HCheckTable(phase_);
150 for (int i = 0; i < size_; i++) { 148 for (int i = 0; i < size_; i++) {
151 HCheckTableEntry* old_entry = &entries_[i]; 149 HCheckTableEntry* old_entry = &entries_[i];
152 HCheckTableEntry* new_entry = &copy->entries_[i]; 150 HCheckTableEntry* new_entry = &copy->entries_[i];
153 new_entry->object_ = old_entry->object_; 151 new_entry->object_ = old_entry->object_;
154 new_entry->maps_ = old_entry->maps_->Copy(phase_->zone()); 152 new_entry->maps_ = old_entry->maps_->Copy(phase_->zone());
155 // Keep the check if the existing check's block dominates the successor. 153 // Keep the check if the existing check's block dominates the successor.
156 if (old_entry->check_ != NULL && 154 if (old_entry->check_ != NULL &&
157 old_entry->check_->block()->Dominates(succ)) { 155 old_entry->check_->block()->Dominates(succ)) {
158 new_entry->check_ = old_entry->check_; 156 new_entry->check_ = old_entry->check_;
159 new_entry->is_stable_ = old_entry->is_stable_;
160 } else { 157 } else {
161 // Leave it NULL till we meet a new check instruction for this object 158 // Leave it NULL till we meet a new check instruction for this object
162 // in the control flow. 159 // in the control flow.
163 new_entry->check_ = NULL; 160 new_entry->check_ = NULL;
164 } 161 }
165 } 162 }
166 copy->cursor_ = cursor_; 163 copy->cursor_ = cursor_;
167 copy->size_ = size_; 164 copy->size_ = size_;
168 165
169 // Create entries for succ block's phis. 166 // Create entries for succ block's phis.
170 if (succ->phis()->length() > 0) { 167 if (succ->phis()->length() > 0) {
171 int pred_index = succ->PredecessorIndexOf(from_block); 168 int pred_index = succ->PredecessorIndexOf(from_block);
172 for (int phi_index = 0; 169 for (int phi_index = 0;
173 phi_index < succ->phis()->length(); 170 phi_index < succ->phis()->length();
174 ++phi_index) { 171 ++phi_index) {
175 HPhi* phi = succ->phis()->at(phi_index); 172 HPhi* phi = succ->phis()->at(phi_index);
176 HValue* phi_operand = phi->OperandAt(pred_index); 173 HValue* phi_operand = phi->OperandAt(pred_index);
177 174
178 HCheckTableEntry* pred_entry = copy->Find(phi_operand); 175 HCheckTableEntry* pred_entry = copy->Find(phi_operand);
179 if (pred_entry != NULL) { 176 if (pred_entry != NULL) {
180 // Create an entry for a phi in the table. 177 // Create an entry for a phi in the table.
181 copy->Insert(phi, NULL, pred_entry->maps_->Copy(phase_->zone()), 178 copy->Insert(phi, NULL, pred_entry->maps_->Copy(phase_->zone()));
182 pred_entry->is_stable_);
183 } 179 }
184 } 180 }
185 } 181 }
186 182
187 // Branch-sensitive analysis for certain comparisons may add more facts 183 // Branch-sensitive analysis for certain comparisons may add more facts
188 // to the state for the successor on the true branch. 184 // to the state for the successor on the true branch.
189 bool learned = false; 185 bool learned = false;
190 if (succ->predecessors()->length() == 1) { 186 if (succ->predecessors()->length() == 1) {
191 HControlInstruction* end = succ->predecessors()->at(0)->end(); 187 HControlInstruction* end = succ->predecessors()->at(0)->end();
192 bool is_true_branch = end->SuccessorAt(0) == succ; 188 bool is_true_branch = end->SuccessorAt(0) == succ;
193 if (end->IsCompareMap()) { 189 if (end->IsCompareMap()) {
194 HCompareMap* cmp = HCompareMap::cast(end); 190 HCompareMap* cmp = HCompareMap::cast(end);
195 HValue* object = cmp->value()->ActualValue(); 191 HValue* object = cmp->value()->ActualValue();
196 HCheckTableEntry* entry = copy->Find(object); 192 HCheckTableEntry* entry = copy->Find(object);
197 if (is_true_branch) { 193 if (is_true_branch) {
198 // Learn on the true branch of if(CompareMap(x)). 194 // Learn on the true branch of if(CompareMap(x)).
199 if (entry == NULL) { 195 if (entry == NULL) {
200 copy->Insert(object, cmp, cmp->map(), cmp->is_stable()); 196 copy->Insert(object, cmp, cmp->map());
201 } else { 197 } else {
202 MapSet list = new(phase_->zone()) UniqueSet<Map>(); 198 MapSet list = new(phase_->zone()) UniqueSet<Map>();
203 list->Add(cmp->map(), phase_->zone()); 199 list->Add(cmp->map(), phase_->zone());
204 entry->maps_ = list; 200 entry->maps_ = list;
205 entry->check_ = cmp; 201 entry->check_ = cmp;
206 entry->is_stable_ = cmp->is_stable();
207 } 202 }
208 } else { 203 } else {
209 // Learn on the false branch of if(CompareMap(x)). 204 // Learn on the false branch of if(CompareMap(x)).
210 if (entry != NULL) { 205 if (entry != NULL) {
211 entry->maps_->Remove(cmp->map()); 206 entry->maps_->Remove(cmp->map());
212 } 207 }
213 } 208 }
214 learned = true; 209 learned = true;
215 } else if (is_true_branch && end->IsCompareObjectEqAndBranch()) { 210 } else if (is_true_branch && end->IsCompareObjectEqAndBranch()) {
216 // Learn on the true branch of if(CmpObjectEq(x, y)). 211 // Learn on the true branch of if(CmpObjectEq(x, y)).
217 HCompareObjectEqAndBranch* cmp = 212 HCompareObjectEqAndBranch* cmp =
218 HCompareObjectEqAndBranch::cast(end); 213 HCompareObjectEqAndBranch::cast(end);
219 HValue* left = cmp->left()->ActualValue(); 214 HValue* left = cmp->left()->ActualValue();
220 HValue* right = cmp->right()->ActualValue(); 215 HValue* right = cmp->right()->ActualValue();
221 HCheckTableEntry* le = copy->Find(left); 216 HCheckTableEntry* le = copy->Find(left);
222 HCheckTableEntry* re = copy->Find(right); 217 HCheckTableEntry* re = copy->Find(right);
223 if (le == NULL) { 218 if (le == NULL) {
224 if (re != NULL) { 219 if (re != NULL) {
225 copy->Insert(left, NULL, re->maps_->Copy(zone), re->is_stable_); 220 copy->Insert(left, NULL, re->maps_->Copy(zone));
226 } 221 }
227 } else if (re == NULL) { 222 } else if (re == NULL) {
228 copy->Insert(right, NULL, le->maps_->Copy(zone), le->is_stable_); 223 copy->Insert(right, NULL, le->maps_->Copy(zone));
229 } else { 224 } else {
230 MapSet intersect = le->maps_->Intersect(re->maps_, zone); 225 MapSet intersect = le->maps_->Intersect(re->maps_, zone);
231 le->maps_ = intersect; 226 le->maps_ = intersect;
232 re->maps_ = intersect->Copy(zone); 227 re->maps_ = intersect->Copy(zone);
233 } 228 }
234 learned = true; 229 learned = true;
235 } 230 }
236 // Learning on false branches requires storing negative facts. 231 // Learning on false branches requires storing negative facts.
237 } 232 }
238 233
239 if (FLAG_trace_check_elimination) { 234 if (FLAG_trace_check_elimination) {
240 PrintF("B%d checkmaps-table %s from B%d:\n", 235 PrintF("B%d checkmaps-table %s from B%d:\n",
241 succ->block_id(), 236 succ->block_id(),
242 learned ? "learned" : "copied", 237 learned ? "learned" : "copied",
243 from_block->block_id()); 238 from_block->block_id());
244 copy->Print(); 239 copy->Print();
245 } 240 }
246 241
247 return copy; 242 return copy;
248 } 243 }
249 244
250 // Merge this state with the other incoming state. 245 // Merge this state with the other incoming state.
251 HCheckTable* Merge(HBasicBlock* succ, HCheckTable* that, 246 HCheckTable* Merge(HBasicBlock* succ, HCheckTable* that,
252 HBasicBlock* pred_block, Zone* zone) { 247 HBasicBlock* pred_block, Zone* zone) {
253 if (that->size_ == 0) { 248 if (that->size_ == 0) {
254 // If the other state is empty, simply reset. 249 // If the other state is empty, simply reset.
255 Reset(); 250 size_ = 0;
251 cursor_ = 0;
256 } else { 252 } else {
257 int pred_index = succ->PredecessorIndexOf(pred_block); 253 int pred_index = succ->PredecessorIndexOf(pred_block);
258 bool compact = false; 254 bool compact = false;
259 for (int i = 0; i < size_; i++) { 255 for (int i = 0; i < size_; i++) {
260 HCheckTableEntry* this_entry = &entries_[i]; 256 HCheckTableEntry* this_entry = &entries_[i];
261 HCheckTableEntry* that_entry; 257 HCheckTableEntry* that_entry;
262 if (this_entry->object_->IsPhi() && 258 if (this_entry->object_->IsPhi() &&
263 this_entry->object_->block() == succ) { 259 this_entry->object_->block() == succ) {
264 HPhi* phi = HPhi::cast(this_entry->object_); 260 HPhi* phi = HPhi::cast(this_entry->object_);
265 HValue* phi_operand = phi->OperandAt(pred_index); 261 HValue* phi_operand = phi->OperandAt(pred_index);
266 that_entry = that->Find(phi_operand); 262 that_entry = that->Find(phi_operand);
267 263
268 } else { 264 } else {
269 that_entry = that->Find(this_entry->object_); 265 that_entry = that->Find(this_entry->object_);
270 } 266 }
271 267
272 if (that_entry == NULL) { 268 if (that_entry == NULL) {
273 this_entry->object_ = NULL; 269 this_entry->object_ = NULL;
274 compact = true; 270 compact = true;
275 } else { 271 } else {
276 this_entry->maps_ = 272 this_entry->maps_ =
277 this_entry->maps_->Union(that_entry->maps_, phase_->zone()); 273 this_entry->maps_->Union(that_entry->maps_, phase_->zone());
278 this_entry->is_stable_ =
279 this_entry->is_stable_ && that_entry->is_stable_;
280 if (this_entry->check_ != that_entry->check_) { 274 if (this_entry->check_ != that_entry->check_) {
281 this_entry->check_ = NULL; 275 this_entry->check_ = NULL;
282 } 276 }
283 ASSERT(this_entry->maps_->size() > 0); 277 ASSERT(this_entry->maps_->size() > 0);
284 } 278 }
285 } 279 }
286 if (compact) Compact(); 280 if (compact) Compact();
287 } 281 }
288 282
289 if (FLAG_trace_check_elimination) { 283 if (FLAG_trace_check_elimination) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
350 } 344 }
351 345
352 if (FLAG_trace_check_elimination) { 346 if (FLAG_trace_check_elimination) {
353 Print(); 347 Print();
354 } 348 }
355 INC_STAT(narrowed_); 349 INC_STAT(narrowed_);
356 } 350 }
357 } 351 }
358 } else { 352 } else {
359 // No entry; insert a new one. 353 // No entry; insert a new one.
360 Insert(object, instr, instr->map_set().Copy(phase_->zone()), 354 Insert(object, instr, instr->map_set().Copy(phase_->zone()));
361 instr->is_stable());
362 } 355 }
363 } 356 }
364 357
365 void ReduceCheckValue(HCheckValue* instr) { 358 void ReduceCheckValue(HCheckValue* instr) {
366 // Canonicalize HCheckValues; they might have their values load-eliminated. 359 // Canonicalize HCheckValues; they might have their values load-eliminated.
367 HValue* value = instr->Canonicalize(); 360 HValue* value = instr->Canonicalize();
368 if (value == NULL) { 361 if (value == NULL) {
369 instr->DeleteAndReplaceWith(instr->value()); 362 instr->DeleteAndReplaceWith(instr->value());
370 INC_STAT(removed_); 363 INC_STAT(removed_);
371 } else if (value != instr) { 364 } else if (value != instr) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
413 INC_STAT(removed_); 406 INC_STAT(removed_);
414 } else { 407 } else {
415 // Only one map survives the check. 408 // Only one map survives the check.
416 maps->Clear(); 409 maps->Clear();
417 maps->Add(map, phase_->zone()); 410 maps->Add(map, phase_->zone());
418 entry->check_ = instr; 411 entry->check_ = instr;
419 } 412 }
420 } 413 }
421 } else { 414 } else {
422 // No prior information. 415 // No prior information.
423 // TODO(verwaest): Tag map constants with stability. 416 Insert(object, instr, map);
424 Insert(object, instr, map, false);
425 } 417 }
426 } 418 }
427 419
428 void ReduceCheckHeapObject(HCheckHeapObject* instr) { 420 void ReduceCheckHeapObject(HCheckHeapObject* instr) {
429 if (FindMaps(instr->value()->ActualValue()) != NULL) { 421 if (FindMaps(instr->value()->ActualValue()) != NULL) {
430 // If the object has known maps, it's definitely a heap object. 422 // If the object has known maps, it's definitely a heap object.
431 instr->DeleteAndReplaceWith(instr->value()); 423 instr->DeleteAndReplaceWith(instr->value());
432 INC_STAT(removed_cho_); 424 INC_STAT(removed_cho_);
433 } 425 }
434 } 426 }
435 427
436 void ReduceStoreNamedField(HStoreNamedField* instr) { 428 void ReduceStoreNamedField(HStoreNamedField* instr) {
437 HValue* object = instr->object()->ActualValue(); 429 HValue* object = instr->object()->ActualValue();
438 if (instr->has_transition()) { 430 if (instr->has_transition()) {
439 // This store transitions the object to a new map. 431 // This store transitions the object to a new map.
440 Kill(object); 432 Kill(object);
441 Insert(object, NULL, MapConstant(instr->transition()), 433 Insert(object, NULL, MapConstant(instr->transition()));
442 instr->is_stable());
443 } else if (IsMapAccess(instr->access())) { 434 } else if (IsMapAccess(instr->access())) {
444 // This is a store directly to the map field of the object. 435 // This is a store directly to the map field of the object.
445 Kill(object); 436 Kill(object);
446 if (!instr->value()->IsConstant()) return; 437 if (!instr->value()->IsConstant()) return;
447 // TODO(verwaest): Tag with stability. 438 Insert(object, NULL, MapConstant(instr->value()));
448 Insert(object, NULL, MapConstant(instr->value()), false);
449 } else { 439 } else {
450 // If the instruction changes maps, it should be handled above. 440 // If the instruction changes maps, it should be handled above.
451 CHECK(!instr->CheckChangesFlag(kMaps)); 441 CHECK(!instr->CheckChangesFlag(kMaps));
452 } 442 }
453 } 443 }
454 444
455 void ReduceCompareMap(HCompareMap* instr) { 445 void ReduceCompareMap(HCompareMap* instr) {
456 MapSet maps = FindMaps(instr->value()->ActualValue()); 446 MapSet maps = FindMaps(instr->value()->ActualValue());
457 if (maps == NULL) return; 447 if (maps == NULL) return;
458 448
(...skipping 29 matching lines...) Expand all
488 // If the object has the original map, it will be transitioned. 478 // If the object has the original map, it will be transitioned.
489 maps->Remove(instr->original_map()); 479 maps->Remove(instr->original_map());
490 maps->Add(instr->transitioned_map(), phase_->zone()); 480 maps->Add(instr->transitioned_map(), phase_->zone());
491 } else { 481 } else {
492 // Object does not have the given map, thus the transition is redundant. 482 // Object does not have the given map, thus the transition is redundant.
493 instr->DeleteAndReplaceWith(instr->object()); 483 instr->DeleteAndReplaceWith(instr->object());
494 INC_STAT(transitions_); 484 INC_STAT(transitions_);
495 } 485 }
496 } 486 }
497 487
498 // Reset the table. 488 // Kill everything in the table.
499 void Reset() { 489 void Kill() {
500 size_ = 0; 490 size_ = 0;
501 cursor_ = 0; 491 cursor_ = 0;
502 } 492 }
503 493
504 // Kill everything in the table.
505 void KillUnstableEntries() {
506 bool compact = false;
507 for (int i = 0; i < size_; i++) {
508 HCheckTableEntry* entry = &entries_[i];
509 ASSERT(entry->object_ != NULL);
510 if (!entry->is_stable_) {
511 entry->object_ = NULL;
512 compact = true;
513 }
514 }
515 if (compact) Compact();
516 }
517
518 // Kill everything in the table that may alias {object}. 494 // Kill everything in the table that may alias {object}.
519 void Kill(HValue* object) { 495 void Kill(HValue* object) {
520 bool compact = false; 496 bool compact = false;
521 for (int i = 0; i < size_; i++) { 497 for (int i = 0; i < size_; i++) {
522 HCheckTableEntry* entry = &entries_[i]; 498 HCheckTableEntry* entry = &entries_[i];
523 ASSERT(entry->object_ != NULL); 499 ASSERT(entry->object_ != NULL);
524 if (phase_->aliasing_->MayAlias(entry->object_, object)) { 500 if (phase_->aliasing_->MayAlias(entry->object_, object)) {
525 entry->object_ = NULL; 501 entry->object_ = NULL;
526 compact = true; 502 compact = true;
527 } 503 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
589 if (phase_->aliasing_->MustAlias(entry->object_, object)) return entry; 565 if (phase_->aliasing_->MustAlias(entry->object_, object)) return entry;
590 } 566 }
591 return NULL; 567 return NULL;
592 } 568 }
593 569
594 MapSet FindMaps(HValue* object) { 570 MapSet FindMaps(HValue* object) {
595 HCheckTableEntry* entry = Find(object); 571 HCheckTableEntry* entry = Find(object);
596 return entry == NULL ? NULL : entry->maps_; 572 return entry == NULL ? NULL : entry->maps_;
597 } 573 }
598 574
599 void Insert(HValue* object, 575 void Insert(HValue* object, HInstruction* check, Unique<Map> map) {
600 HInstruction* check,
601 Unique<Map> map,
602 bool is_stable) {
603 MapSet list = new(phase_->zone()) UniqueSet<Map>(); 576 MapSet list = new(phase_->zone()) UniqueSet<Map>();
604 list->Add(map, phase_->zone()); 577 list->Add(map, phase_->zone());
605 Insert(object, check, list, is_stable); 578 Insert(object, check, list);
606 } 579 }
607 580
608 void Insert(HValue* object, 581 void Insert(HValue* object, HInstruction* check, MapSet maps) {
609 HInstruction* check,
610 MapSet maps,
611 bool is_stable) {
612 HCheckTableEntry* entry = &entries_[cursor_++]; 582 HCheckTableEntry* entry = &entries_[cursor_++];
613 entry->object_ = object; 583 entry->object_ = object;
614 entry->check_ = check; 584 entry->check_ = check;
615 entry->maps_ = maps; 585 entry->maps_ = maps;
616 entry->is_stable_ = is_stable;
617 // If the table becomes full, wrap around and overwrite older entries. 586 // If the table becomes full, wrap around and overwrite older entries.
618 if (cursor_ == kMaxTrackedObjects) cursor_ = 0; 587 if (cursor_ == kMaxTrackedObjects) cursor_ = 0;
619 if (size_ < kMaxTrackedObjects) size_++; 588 if (size_ < kMaxTrackedObjects) size_++;
620 } 589 }
621 590
622 bool IsMapAccess(HObjectAccess access) { 591 bool IsMapAccess(HObjectAccess access) {
623 return access.IsInobject() && access.offset() == JSObject::kMapOffset; 592 return access.IsInobject() && access.offset() == JSObject::kMapOffset;
624 } 593 }
625 594
626 Unique<Map> MapConstant(HValue* value) { 595 Unique<Map> MapConstant(HValue* value) {
627 return Unique<Map>::cast(HConstant::cast(value)->GetUnique()); 596 return Unique<Map>::cast(HConstant::cast(value)->GetUnique());
628 } 597 }
629 598
630 friend class HCheckMapsEffects; 599 friend class HCheckMapsEffects;
631 friend class HCheckEliminationPhase; 600 friend class HCheckEliminationPhase;
632 601
633 HCheckEliminationPhase* phase_; 602 HCheckEliminationPhase* phase_;
634 HCheckTableEntry entries_[kMaxTrackedObjects]; 603 HCheckTableEntry entries_[kMaxTrackedObjects];
635 int16_t cursor_; // Must be <= kMaxTrackedObjects 604 int16_t cursor_; // Must be <= kMaxTrackedObjects
636 int16_t size_; // Must be <= kMaxTrackedObjects 605 int16_t size_; // Must be <= kMaxTrackedObjects
637 // TODO(titzer): STATIC_ASSERT kMaxTrackedObjects < max(cursor_) 606 // TODO(titzer): STATIC_ASSERT kMaxTrackedObjects < max(cursor_)
638 }; 607 };
639 608
640 609
641 // Collects instructions that can cause effects that invalidate information 610 // Collects instructions that can cause effects that invalidate information
642 // needed for check elimination. 611 // needed for check elimination.
643 class HCheckMapsEffects : public ZoneObject { 612 class HCheckMapsEffects : public ZoneObject {
644 public: 613 public:
645 explicit HCheckMapsEffects(Zone* zone) 614 explicit HCheckMapsEffects(Zone* zone)
646 : stores_(5, zone) { } 615 : maps_stored_(false),
616 stores_(5, zone) { }
647 617
648 inline bool Disabled() { 618 inline bool Disabled() {
649 return false; // Effects are _not_ disabled. 619 return false; // Effects are _not_ disabled.
650 } 620 }
651 621
652 // Process a possibly side-effecting instruction. 622 // Process a possibly side-effecting instruction.
653 void Process(HInstruction* instr, Zone* zone) { 623 void Process(HInstruction* instr, Zone* zone) {
654 if (instr->IsStoreNamedField()) { 624 switch (instr->opcode()) {
655 stores_.Add(HStoreNamedField::cast(instr), zone); 625 case HValue::kStoreNamedField: {
656 } else { 626 stores_.Add(HStoreNamedField::cast(instr), zone);
657 flags_.Add(instr->ChangesFlags()); 627 break;
628 }
629 case HValue::kOsrEntry: {
630 // Kill everything. Loads must not be hoisted past the OSR entry.
631 maps_stored_ = true;
632 }
633 default: {
634 maps_stored_ |= (instr->CheckChangesFlag(kMaps) |
635 instr->CheckChangesFlag(kElementsKind));
636 }
658 } 637 }
659 } 638 }
660 639
661 // Apply these effects to the given check elimination table. 640 // Apply these effects to the given check elimination table.
662 void Apply(HCheckTable* table) { 641 void Apply(HCheckTable* table) {
663 if (flags_.Contains(kOsrEntries)) { 642 if (maps_stored_) {
664 table->Reset();
665 return;
666 }
667 if (flags_.Contains(kMaps) || flags_.Contains(kElementsKind)) {
668 // Uncontrollable map modifications; kill everything. 643 // Uncontrollable map modifications; kill everything.
669 table->KillUnstableEntries(); 644 table->Kill();
670 return; 645 return;
671 } 646 }
672 647
673 // Kill maps for each store contained in these effects. 648 // Kill maps for each store contained in these effects.
674 for (int i = 0; i < stores_.length(); i++) { 649 for (int i = 0; i < stores_.length(); i++) {
675 HStoreNamedField* s = stores_[i]; 650 HStoreNamedField* s = stores_[i];
676 if (table->IsMapAccess(s->access()) || s->has_transition()) { 651 if (table->IsMapAccess(s->access()) || s->has_transition()) {
677 table->Kill(s->object()->ActualValue()); 652 table->Kill(s->object()->ActualValue());
678 } 653 }
679 } 654 }
680 } 655 }
681 656
682 // Union these effects with the other effects. 657 // Union these effects with the other effects.
683 void Union(HCheckMapsEffects* that, Zone* zone) { 658 void Union(HCheckMapsEffects* that, Zone* zone) {
684 flags_.Add(that->flags_); 659 maps_stored_ |= that->maps_stored_;
685 for (int i = 0; i < that->stores_.length(); i++) { 660 for (int i = 0; i < that->stores_.length(); i++) {
686 stores_.Add(that->stores_[i], zone); 661 stores_.Add(that->stores_[i], zone);
687 } 662 }
688 } 663 }
689 664
690 private: 665 private:
691 GVNFlagSet flags_; 666 bool maps_stored_ : 1;
692 ZoneList<HStoreNamedField*> stores_; 667 ZoneList<HStoreNamedField*> stores_;
693 }; 668 };
694 669
695 670
696 // The main routine of the analysis phase. Use the HFlowEngine for either a 671 // The main routine of the analysis phase. Use the HFlowEngine for either a
697 // local or a global analysis. 672 // local or a global analysis.
698 void HCheckEliminationPhase::Run() { 673 void HCheckEliminationPhase::Run() {
699 HFlowEngine<HCheckTable, HCheckMapsEffects> engine(graph(), zone()); 674 HFlowEngine<HCheckTable, HCheckMapsEffects> engine(graph(), zone());
700 HCheckTable* table = new(zone()) HCheckTable(this); 675 HCheckTable* table = new(zone()) HCheckTable(this);
701 676
702 if (GLOBAL) { 677 if (GLOBAL) {
703 // Perform a global analysis. 678 // Perform a global analysis.
704 engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), table); 679 engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), table);
705 } else { 680 } else {
706 // Perform only local analysis. 681 // Perform only local analysis.
707 for (int i = 0; i < graph()->blocks()->length(); i++) { 682 for (int i = 0; i < graph()->blocks()->length(); i++) {
708 table->Reset(); 683 table->Kill();
709 engine.AnalyzeOneBlock(graph()->blocks()->at(i), table); 684 engine.AnalyzeOneBlock(graph()->blocks()->at(i), table);
710 } 685 }
711 } 686 }
712 687
713 if (FLAG_trace_check_elimination) PrintStats(); 688 if (FLAG_trace_check_elimination) PrintStats();
714 } 689 }
715 690
716 691
717 // Are we eliminated yet? 692 // Are we eliminated yet?
718 void HCheckEliminationPhase::PrintStats() { 693 void HCheckEliminationPhase::PrintStats() {
719 #if DEBUG 694 #if DEBUG
720 #define PRINT_STAT(x) if (x##_ > 0) PrintF(" %-16s = %2d\n", #x, x##_) 695 #define PRINT_STAT(x) if (x##_ > 0) PrintF(" %-16s = %2d\n", #x, x##_)
721 #else 696 #else
722 #define PRINT_STAT(x) 697 #define PRINT_STAT(x)
723 #endif 698 #endif
724 PRINT_STAT(redundant); 699 PRINT_STAT(redundant);
725 PRINT_STAT(removed); 700 PRINT_STAT(removed);
726 PRINT_STAT(removed_cho); 701 PRINT_STAT(removed_cho);
727 PRINT_STAT(narrowed); 702 PRINT_STAT(narrowed);
728 PRINT_STAT(loads); 703 PRINT_STAT(loads);
729 PRINT_STAT(empty); 704 PRINT_STAT(empty);
730 PRINT_STAT(compares_true); 705 PRINT_STAT(compares_true);
731 PRINT_STAT(compares_false); 706 PRINT_STAT(compares_false);
732 PRINT_STAT(transitions); 707 PRINT_STAT(transitions);
733 } 708 }
734 709
735 } } // namespace v8::internal 710 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.cc ('k') | src/hydrogen-instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698