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

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

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