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

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

Issue 180023002: 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: Restore debug code 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 24 matching lines...) Expand all
145 143
146 private: 144 private:
147 // Copy state to successor block. 145 // Copy state to successor block.
148 HCheckTable* Copy(HBasicBlock* succ, HBasicBlock* from_block, Zone* zone) { 146 HCheckTable* Copy(HBasicBlock* succ, HBasicBlock* from_block, Zone* zone) {
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 new_entry->is_stable_ = old_entry->is_stable_;
156 // 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.
157 if (old_entry->check_ != NULL && 154 if (old_entry->check_ != NULL &&
158 old_entry->check_->block()->Dominates(succ)) { 155 old_entry->check_->block()->Dominates(succ)) {
159 new_entry->check_ = old_entry->check_; 156 new_entry->check_ = old_entry->check_;
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->IsLoopHeader() && succ->phis()->length() > 0) { 167 if (!succ->IsLoopHeader() && 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 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
352 } 346 }
353 347
354 if (FLAG_trace_check_elimination) { 348 if (FLAG_trace_check_elimination) {
355 Print(); 349 Print();
356 } 350 }
357 INC_STAT(narrowed_); 351 INC_STAT(narrowed_);
358 } 352 }
359 } 353 }
360 } else { 354 } else {
361 // No entry; insert a new one. 355 // No entry; insert a new one.
362 Insert(object, instr, instr->map_set().Copy(phase_->zone()), 356 Insert(object, instr, instr->map_set().Copy(phase_->zone()));
363 instr->is_stable());
364 } 357 }
365 } 358 }
366 359
367 void ReduceCheckValue(HCheckValue* instr) { 360 void ReduceCheckValue(HCheckValue* instr) {
368 // Canonicalize HCheckValues; they might have their values load-eliminated. 361 // Canonicalize HCheckValues; they might have their values load-eliminated.
369 HValue* value = instr->Canonicalize(); 362 HValue* value = instr->Canonicalize();
370 if (value == NULL) { 363 if (value == NULL) {
371 instr->DeleteAndReplaceWith(instr->value()); 364 instr->DeleteAndReplaceWith(instr->value());
372 INC_STAT(removed_); 365 INC_STAT(removed_);
373 } else if (value != instr) { 366 } else if (value != instr) {
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after
415 INC_STAT(removed_); 408 INC_STAT(removed_);
416 } else { 409 } else {
417 // Only one map survives the check. 410 // Only one map survives the check.
418 maps->Clear(); 411 maps->Clear();
419 maps->Add(map, phase_->zone()); 412 maps->Add(map, phase_->zone());
420 entry->check_ = instr; 413 entry->check_ = instr;
421 } 414 }
422 } 415 }
423 } else { 416 } else {
424 // No prior information. 417 // No prior information.
425 // TODO(verwaest): Tag map constants with stability. 418 Insert(object, instr, map);
426 Insert(object, instr, map, false);
427 } 419 }
428 } 420 }
429 421
430 void ReduceCheckHeapObject(HCheckHeapObject* instr) { 422 void ReduceCheckHeapObject(HCheckHeapObject* instr) {
431 if (FindMaps(instr->value()->ActualValue()) != NULL) { 423 if (FindMaps(instr->value()->ActualValue()) != NULL) {
432 // If the object has known maps, it's definitely a heap object. 424 // If the object has known maps, it's definitely a heap object.
433 instr->DeleteAndReplaceWith(instr->value()); 425 instr->DeleteAndReplaceWith(instr->value());
434 INC_STAT(removed_cho_); 426 INC_STAT(removed_cho_);
435 } 427 }
436 } 428 }
437 429
438 void ReduceStoreNamedField(HStoreNamedField* instr) { 430 void ReduceStoreNamedField(HStoreNamedField* instr) {
439 HValue* object = instr->object()->ActualValue(); 431 HValue* object = instr->object()->ActualValue();
440 if (instr->has_transition()) { 432 if (instr->has_transition()) {
441 // This store transitions the object to a new map. 433 // This store transitions the object to a new map.
442 Kill(object); 434 Kill(object);
443 Insert(object, NULL, MapConstant(instr->transition()), 435 Insert(object, NULL, MapConstant(instr->transition()));
444 instr->is_stable());
445 } else if (IsMapAccess(instr->access())) { 436 } else if (IsMapAccess(instr->access())) {
446 // This is a store directly to the map field of the object. 437 // This is a store directly to the map field of the object.
447 Kill(object); 438 Kill(object);
448 if (!instr->value()->IsConstant()) return; 439 if (!instr->value()->IsConstant()) return;
449 // TODO(verwaest): Tag with stability. 440 Insert(object, NULL, MapConstant(instr->value()));
450 Insert(object, NULL, MapConstant(instr->value()), false);
451 } else { 441 } else {
452 // If the instruction changes maps, it should be handled above. 442 // If the instruction changes maps, it should be handled above.
453 CHECK(!instr->CheckChangesFlag(kMaps)); 443 CHECK(!instr->CheckChangesFlag(kMaps));
454 } 444 }
455 } 445 }
456 446
457 void ReduceCompareMap(HCompareMap* instr) { 447 void ReduceCompareMap(HCompareMap* instr) {
458 MapSet maps = FindMaps(instr->value()->ActualValue()); 448 MapSet maps = FindMaps(instr->value()->ActualValue());
459 if (maps == NULL) return; 449 if (maps == NULL) return;
460 450
(...skipping 29 matching lines...) Expand all
490 // If the object has the original map, it will be transitioned. 480 // If the object has the original map, it will be transitioned.
491 maps->Remove(instr->original_map()); 481 maps->Remove(instr->original_map());
492 maps->Add(instr->transitioned_map(), phase_->zone()); 482 maps->Add(instr->transitioned_map(), phase_->zone());
493 } else { 483 } else {
494 // Object does not have the given map, thus the transition is redundant. 484 // Object does not have the given map, thus the transition is redundant.
495 instr->DeleteAndReplaceWith(instr->object()); 485 instr->DeleteAndReplaceWith(instr->object());
496 INC_STAT(transitions_); 486 INC_STAT(transitions_);
497 } 487 }
498 } 488 }
499 489
500 // Reset the table. 490 // Kill everything in the table.
501 void Reset() { 491 void Kill() {
502 size_ = 0; 492 size_ = 0;
503 cursor_ = 0; 493 cursor_ = 0;
504 } 494 }
505 495
506 // Kill everything in the table.
507 void KillUnstableEntries() {
508 bool compact = false;
509 for (int i = 0; i < size_; i++) {
510 HCheckTableEntry* entry = &entries_[i];
511 ASSERT(entry->object_ != NULL);
512 if (!entry->is_stable_) {
513 entry->object_ = NULL;
514 compact = true;
515 }
516 }
517 if (compact) Compact();
518 }
519
520 // Kill everything in the table that may alias {object}. 496 // Kill everything in the table that may alias {object}.
521 void Kill(HValue* object) { 497 void Kill(HValue* object) {
522 bool compact = false; 498 bool compact = false;
523 for (int i = 0; i < size_; i++) { 499 for (int i = 0; i < size_; i++) {
524 HCheckTableEntry* entry = &entries_[i]; 500 HCheckTableEntry* entry = &entries_[i];
525 ASSERT(entry->object_ != NULL); 501 ASSERT(entry->object_ != NULL);
526 if (phase_->aliasing_->MayAlias(entry->object_, object)) { 502 if (phase_->aliasing_->MayAlias(entry->object_, object)) {
527 entry->object_ = NULL; 503 entry->object_ = NULL;
528 compact = true; 504 compact = true;
529 } 505 }
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after
591 if (phase_->aliasing_->MustAlias(entry->object_, object)) return entry; 567 if (phase_->aliasing_->MustAlias(entry->object_, object)) return entry;
592 } 568 }
593 return NULL; 569 return NULL;
594 } 570 }
595 571
596 MapSet FindMaps(HValue* object) { 572 MapSet FindMaps(HValue* object) {
597 HCheckTableEntry* entry = Find(object); 573 HCheckTableEntry* entry = Find(object);
598 return entry == NULL ? NULL : entry->maps_; 574 return entry == NULL ? NULL : entry->maps_;
599 } 575 }
600 576
601 void Insert(HValue* object, 577 void Insert(HValue* object, HInstruction* check, Unique<Map> map) {
602 HInstruction* check,
603 Unique<Map> map,
604 bool is_stable) {
605 MapSet list = new(phase_->zone()) UniqueSet<Map>(); 578 MapSet list = new(phase_->zone()) UniqueSet<Map>();
606 list->Add(map, phase_->zone()); 579 list->Add(map, phase_->zone());
607 Insert(object, check, list, is_stable); 580 Insert(object, check, list);
608 } 581 }
609 582
610 void Insert(HValue* object, 583 void Insert(HValue* object, HInstruction* check, MapSet maps) {
611 HInstruction* check,
612 MapSet maps,
613 bool is_stable) {
614 HCheckTableEntry* entry = &entries_[cursor_++]; 584 HCheckTableEntry* entry = &entries_[cursor_++];
615 entry->object_ = object; 585 entry->object_ = object;
616 entry->check_ = check; 586 entry->check_ = check;
617 entry->maps_ = maps; 587 entry->maps_ = maps;
618 entry->is_stable_ = is_stable;
619 // If the table becomes full, wrap around and overwrite older entries. 588 // If the table becomes full, wrap around and overwrite older entries.
620 if (cursor_ == kMaxTrackedObjects) cursor_ = 0; 589 if (cursor_ == kMaxTrackedObjects) cursor_ = 0;
621 if (size_ < kMaxTrackedObjects) size_++; 590 if (size_ < kMaxTrackedObjects) size_++;
622 } 591 }
623 592
624 bool IsMapAccess(HObjectAccess access) { 593 bool IsMapAccess(HObjectAccess access) {
625 return access.IsInobject() && access.offset() == JSObject::kMapOffset; 594 return access.IsInobject() && access.offset() == JSObject::kMapOffset;
626 } 595 }
627 596
628 Unique<Map> MapConstant(HValue* value) { 597 Unique<Map> MapConstant(HValue* value) {
629 return Unique<Map>::cast(HConstant::cast(value)->GetUnique()); 598 return Unique<Map>::cast(HConstant::cast(value)->GetUnique());
630 } 599 }
631 600
632 friend class HCheckMapsEffects; 601 friend class HCheckMapsEffects;
633 friend class HCheckEliminationPhase; 602 friend class HCheckEliminationPhase;
634 603
635 HCheckEliminationPhase* phase_; 604 HCheckEliminationPhase* phase_;
636 HCheckTableEntry entries_[kMaxTrackedObjects]; 605 HCheckTableEntry entries_[kMaxTrackedObjects];
637 int16_t cursor_; // Must be <= kMaxTrackedObjects 606 int16_t cursor_; // Must be <= kMaxTrackedObjects
638 int16_t size_; // Must be <= kMaxTrackedObjects 607 int16_t size_; // Must be <= kMaxTrackedObjects
639 // TODO(titzer): STATIC_ASSERT kMaxTrackedObjects < max(cursor_) 608 // TODO(titzer): STATIC_ASSERT kMaxTrackedObjects < max(cursor_)
640 }; 609 };
641 610
642 611
643 // Collects instructions that can cause effects that invalidate information 612 // Collects instructions that can cause effects that invalidate information
644 // needed for check elimination. 613 // needed for check elimination.
645 class HCheckMapsEffects : public ZoneObject { 614 class HCheckMapsEffects : public ZoneObject {
646 public: 615 public:
647 explicit HCheckMapsEffects(Zone* zone) 616 explicit HCheckMapsEffects(Zone* zone)
648 : stores_(5, zone) { } 617 : maps_stored_(false),
618 stores_(5, zone) { }
649 619
650 inline bool Disabled() { 620 inline bool Disabled() {
651 return false; // Effects are _not_ disabled. 621 return false; // Effects are _not_ disabled.
652 } 622 }
653 623
654 // Process a possibly side-effecting instruction. 624 // Process a possibly side-effecting instruction.
655 void Process(HInstruction* instr, Zone* zone) { 625 void Process(HInstruction* instr, Zone* zone) {
656 if (instr->IsStoreNamedField()) { 626 switch (instr->opcode()) {
657 stores_.Add(HStoreNamedField::cast(instr), zone); 627 case HValue::kStoreNamedField: {
658 } else { 628 stores_.Add(HStoreNamedField::cast(instr), zone);
659 flags_.Add(instr->ChangesFlags()); 629 break;
630 }
631 case HValue::kOsrEntry: {
632 // Kill everything. Loads must not be hoisted past the OSR entry.
633 maps_stored_ = true;
634 }
635 default: {
636 maps_stored_ |= (instr->CheckChangesFlag(kMaps) |
637 instr->CheckChangesFlag(kElementsKind));
638 }
660 } 639 }
661 } 640 }
662 641
663 // Apply these effects to the given check elimination table. 642 // Apply these effects to the given check elimination table.
664 void Apply(HCheckTable* table) { 643 void Apply(HCheckTable* table) {
665 if (flags_.Contains(kOsrEntries)) { 644 if (maps_stored_) {
666 table->Reset();
667 return;
668 }
669 if (flags_.Contains(kMaps) || flags_.Contains(kElementsKind)) {
670 // Uncontrollable map modifications; kill everything. 645 // Uncontrollable map modifications; kill everything.
671 table->KillUnstableEntries(); 646 table->Kill();
672 return; 647 return;
673 } 648 }
674 649
675 // Kill maps for each store contained in these effects. 650 // Kill maps for each store contained in these effects.
676 for (int i = 0; i < stores_.length(); i++) { 651 for (int i = 0; i < stores_.length(); i++) {
677 HStoreNamedField* s = stores_[i]; 652 HStoreNamedField* s = stores_[i];
678 if (table->IsMapAccess(s->access()) || s->has_transition()) { 653 if (table->IsMapAccess(s->access()) || s->has_transition()) {
679 table->Kill(s->object()->ActualValue()); 654 table->Kill(s->object()->ActualValue());
680 } 655 }
681 } 656 }
682 } 657 }
683 658
684 // Union these effects with the other effects. 659 // Union these effects with the other effects.
685 void Union(HCheckMapsEffects* that, Zone* zone) { 660 void Union(HCheckMapsEffects* that, Zone* zone) {
686 flags_.Add(that->flags_); 661 maps_stored_ |= that->maps_stored_;
687 for (int i = 0; i < that->stores_.length(); i++) { 662 for (int i = 0; i < that->stores_.length(); i++) {
688 stores_.Add(that->stores_[i], zone); 663 stores_.Add(that->stores_[i], zone);
689 } 664 }
690 } 665 }
691 666
692 private: 667 private:
693 GVNFlagSet flags_; 668 bool maps_stored_ : 1;
694 ZoneList<HStoreNamedField*> stores_; 669 ZoneList<HStoreNamedField*> stores_;
695 }; 670 };
696 671
697 672
698 // The main routine of the analysis phase. Use the HFlowEngine for either a 673 // The main routine of the analysis phase. Use the HFlowEngine for either a
699 // local or a global analysis. 674 // local or a global analysis.
700 void HCheckEliminationPhase::Run() { 675 void HCheckEliminationPhase::Run() {
701 HFlowEngine<HCheckTable, HCheckMapsEffects> engine(graph(), zone()); 676 HFlowEngine<HCheckTable, HCheckMapsEffects> engine(graph(), zone());
702 HCheckTable* table = new(zone()) HCheckTable(this); 677 HCheckTable* table = new(zone()) HCheckTable(this);
703 678
704 if (GLOBAL) { 679 if (GLOBAL) {
705 // Perform a global analysis. 680 // Perform a global analysis.
706 engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), table); 681 engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), table);
707 } else { 682 } else {
708 // Perform only local analysis. 683 // Perform only local analysis.
709 for (int i = 0; i < graph()->blocks()->length(); i++) { 684 for (int i = 0; i < graph()->blocks()->length(); i++) {
710 table->Reset(); 685 table->Kill();
711 engine.AnalyzeOneBlock(graph()->blocks()->at(i), table); 686 engine.AnalyzeOneBlock(graph()->blocks()->at(i), table);
712 } 687 }
713 } 688 }
714 689
715 if (FLAG_trace_check_elimination) PrintStats(); 690 if (FLAG_trace_check_elimination) PrintStats();
716 } 691 }
717 692
718 693
719 // Are we eliminated yet? 694 // Are we eliminated yet?
720 void HCheckEliminationPhase::PrintStats() { 695 void HCheckEliminationPhase::PrintStats() {
721 #if DEBUG 696 #if DEBUG
722 #define PRINT_STAT(x) if (x##_ > 0) PrintF(" %-16s = %2d\n", #x, x##_) 697 #define PRINT_STAT(x) if (x##_ > 0) PrintF(" %-16s = %2d\n", #x, x##_)
723 #else 698 #else
724 #define PRINT_STAT(x) 699 #define PRINT_STAT(x)
725 #endif 700 #endif
726 PRINT_STAT(redundant); 701 PRINT_STAT(redundant);
727 PRINT_STAT(removed); 702 PRINT_STAT(removed);
728 PRINT_STAT(removed_cho); 703 PRINT_STAT(removed_cho);
729 PRINT_STAT(narrowed); 704 PRINT_STAT(narrowed);
730 PRINT_STAT(loads); 705 PRINT_STAT(loads);
731 PRINT_STAT(empty); 706 PRINT_STAT(empty);
732 PRINT_STAT(compares_true); 707 PRINT_STAT(compares_true);
733 PRINT_STAT(compares_false); 708 PRINT_STAT(compares_false);
734 PRINT_STAT(transitions); 709 PRINT_STAT(transitions);
735 } 710 }
736 711
737 } } // namespace v8::internal 712 } } // 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