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

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

Issue 153823003: 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
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();
109 } else if (instr->CheckChangesFlag(kMaps)) {
108 Kill(); 110 Kill();
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
119 // Global analysis: Copy state to successor block. 121 // Global analysis: Copy state to successor block.
120 HCheckTable* Copy(HBasicBlock* succ, HBasicBlock* from_block, Zone* zone) { 122 HCheckTable* Copy(HBasicBlock* succ, HBasicBlock* from_block, Zone* zone) {
121 HCheckTable* copy = new(phase_->zone()) HCheckTable(phase_); 123 HCheckTable* copy = new(phase_->zone()) HCheckTable(phase_);
122 for (int i = 0; i < size_; i++) { 124 for (int i = 0; i < size_; i++) {
123 HCheckTableEntry* old_entry = &entries_[i]; 125 HCheckTableEntry* old_entry = &entries_[i];
124 HCheckTableEntry* new_entry = &copy->entries_[i]; 126 HCheckTableEntry* new_entry = &copy->entries_[i];
125 // TODO(titzer): keep the check if this block dominates the successor? 127 // TODO(titzer): keep the check if this block dominates the successor?
126 new_entry->object_ = old_entry->object_; 128 new_entry->object_ = old_entry->object_;
127 new_entry->check_ = NULL; 129 new_entry->check_ = NULL;
128 new_entry->maps_ = old_entry->maps_->Copy(phase_->zone()); 130 new_entry->maps_ = old_entry->maps_->Copy(phase_->zone());
131 new_entry->is_stable_ = old_entry->is_stable_;
129 } 132 }
130 copy->cursor_ = cursor_; 133 copy->cursor_ = cursor_;
131 copy->size_ = size_; 134 copy->size_ = size_;
132 135
133 // Create entries for succ block's phis. 136 // Create entries for succ block's phis.
134 if (succ->phis()->length() > 0) { 137 if (succ->phis()->length() > 0) {
135 int pred_index = succ->PredecessorIndexOf(from_block); 138 int pred_index = succ->PredecessorIndexOf(from_block);
136 for (int phi_index = 0; 139 for (int phi_index = 0;
137 phi_index < succ->phis()->length(); 140 phi_index < succ->phis()->length();
138 ++phi_index) { 141 ++phi_index) {
139 HPhi* phi = succ->phis()->at(phi_index); 142 HPhi* phi = succ->phis()->at(phi_index);
140 HValue* phi_operand = phi->OperandAt(pred_index); 143 HValue* phi_operand = phi->OperandAt(pred_index);
141 144
142 HCheckTableEntry* pred_entry = copy->Find(phi_operand); 145 HCheckTableEntry* pred_entry = copy->Find(phi_operand);
143 if (pred_entry != NULL) { 146 if (pred_entry != NULL) {
144 // Create an entry for a phi in the table. 147 // Create an entry for a phi in the table.
145 copy->Insert(phi, NULL, pred_entry->maps_->Copy(phase_->zone())); 148 copy->Insert(phi, NULL, pred_entry->maps_->Copy(phase_->zone()),
149 pred_entry->is_stable_);
146 } 150 }
147 } 151 }
148 } 152 }
149 153
150 // Branch-sensitive analysis for certain comparisons may add more facts 154 // Branch-sensitive analysis for certain comparisons may add more facts
151 // to the state for the successor on the true branch. 155 // to the state for the successor on the true branch.
152 bool learned = false; 156 bool learned = false;
153 HControlInstruction* end = succ->predecessors()->at(0)->end(); 157 HControlInstruction* end = succ->predecessors()->at(0)->end();
154 if (succ->predecessors()->length() == 1 && end->SuccessorAt(0) == succ) { 158 if (succ->predecessors()->length() == 1 && end->SuccessorAt(0) == succ) {
155 if (end->IsCompareMap()) { 159 if (end->IsCompareMap()) {
156 // Learn on the true branch of if(CompareMap(x)). 160 // Learn on the true branch of if(CompareMap(x)).
157 HCompareMap* cmp = HCompareMap::cast(end); 161 HCompareMap* cmp = HCompareMap::cast(end);
158 HValue* object = cmp->value()->ActualValue(); 162 HValue* object = cmp->value()->ActualValue();
159 HCheckTableEntry* entry = copy->Find(object); 163 HCheckTableEntry* entry = copy->Find(object);
160 if (entry == NULL) { 164 if (entry == NULL) {
161 copy->Insert(object, cmp->map()); 165 copy->Insert(object, cmp->map(), cmp->is_stable());
162 } else { 166 } else {
163 MapSet list = new(phase_->zone()) UniqueSet<Map>(); 167 MapSet list = new(phase_->zone()) UniqueSet<Map>();
164 list->Add(cmp->map(), phase_->zone()); 168 list->Add(cmp->map(), phase_->zone());
165 entry->maps_ = list; 169 entry->maps_ = list;
166 } 170 }
167 learned = true; 171 learned = true;
168 } else if (end->IsCompareObjectEqAndBranch()) { 172 } else if (end->IsCompareObjectEqAndBranch()) {
169 // Learn on the true branch of if(CmpObjectEq(x, y)). 173 // Learn on the true branch of if(CmpObjectEq(x, y)).
170 HCompareObjectEqAndBranch* cmp = 174 HCompareObjectEqAndBranch* cmp =
171 HCompareObjectEqAndBranch::cast(end); 175 HCompareObjectEqAndBranch::cast(end);
172 HValue* left = cmp->left()->ActualValue(); 176 HValue* left = cmp->left()->ActualValue();
173 HValue* right = cmp->right()->ActualValue(); 177 HValue* right = cmp->right()->ActualValue();
174 HCheckTableEntry* le = copy->Find(left); 178 HCheckTableEntry* le = copy->Find(left);
175 HCheckTableEntry* re = copy->Find(right); 179 HCheckTableEntry* re = copy->Find(right);
176 if (le == NULL) { 180 if (le == NULL) {
177 if (re != NULL) { 181 if (re != NULL) {
178 copy->Insert(left, NULL, re->maps_->Copy(zone)); 182 copy->Insert(left, NULL, re->maps_->Copy(zone), re->is_stable_);
179 } 183 }
180 } else if (re == NULL) { 184 } else if (re == NULL) {
181 copy->Insert(right, NULL, le->maps_->Copy(zone)); 185 copy->Insert(right, NULL, le->maps_->Copy(zone), le->is_stable_);
182 } else { 186 } else {
183 MapSet intersect = le->maps_->Intersect(re->maps_, zone); 187 MapSet intersect = le->maps_->Intersect(re->maps_, zone);
184 le->maps_ = intersect; 188 le->maps_ = intersect;
185 re->maps_ = intersect->Copy(zone); 189 re->maps_ = intersect->Copy(zone);
186 } 190 }
187 learned = true; 191 learned = true;
188 } 192 }
189 // Learning on false branches requires storing negative facts. 193 // Learning on false branches requires storing negative facts.
190 } 194 }
191 195
192 if (FLAG_trace_check_elimination) { 196 if (FLAG_trace_check_elimination) {
193 PrintF("B%d checkmaps-table %s from B%d:\n", 197 PrintF("B%d checkmaps-table %s from B%d:\n",
194 succ->block_id(), 198 succ->block_id(),
195 learned ? "learned" : "copied", 199 learned ? "learned" : "copied",
196 from_block->block_id()); 200 from_block->block_id());
197 copy->Print(); 201 copy->Print();
198 } 202 }
199 203
200 return copy; 204 return copy;
201 } 205 }
202 206
203 // Global analysis: Merge this state with the other incoming state. 207 // Global analysis: Merge this state with the other incoming state.
204 HCheckTable* Merge(HBasicBlock* succ, HCheckTable* that, 208 HCheckTable* Merge(HBasicBlock* succ, HCheckTable* that,
205 HBasicBlock* pred_block, Zone* zone) { 209 HBasicBlock* pred_block, Zone* zone) {
206 if (pred_block->IsReachable()) { 210 if (pred_block->IsReachable()) {
207 if (that->size_ == 0) { 211 if (that->size_ == 0) {
208 // If the other state is empty, simply reset. 212 // If the other state is empty, simply reset.
Igor Sheludko 2014/02/12 12:58:20 Reset();
Toon Verwaest 2014/02/12 14:53:34 Done.
209 size_ = 0; 213 size_ = 0;
210 cursor_ = 0; 214 cursor_ = 0;
211 } else { 215 } else {
212 int pred_index = succ->PredecessorIndexOf(pred_block); 216 int pred_index = succ->PredecessorIndexOf(pred_block);
213 bool compact = false; 217 bool compact = false;
214 for (int i = 0; i < size_; i++) { 218 for (int i = 0; i < size_; i++) {
215 HCheckTableEntry* this_entry = &entries_[i]; 219 HCheckTableEntry* this_entry = &entries_[i];
216 HCheckTableEntry* that_entry; 220 HCheckTableEntry* that_entry;
217 if (this_entry->object_->IsPhi() && 221 if (this_entry->object_->IsPhi() &&
218 this_entry->object_->block() == succ) { 222 this_entry->object_->block() == succ) {
219 HPhi* phi = HPhi::cast(this_entry->object_); 223 HPhi* phi = HPhi::cast(this_entry->object_);
220 HValue* phi_operand = phi->OperandAt(pred_index); 224 HValue* phi_operand = phi->OperandAt(pred_index);
221 that_entry = that->Find(phi_operand); 225 that_entry = that->Find(phi_operand);
222 226
223 } else { 227 } else {
224 that_entry = that->Find(this_entry->object_); 228 that_entry = that->Find(this_entry->object_);
225 } 229 }
226 230
227 if (that_entry == NULL) { 231 if (that_entry == NULL) {
228 this_entry->object_ = NULL; 232 this_entry->object_ = NULL;
229 compact = true; 233 compact = true;
230 } else { 234 } else {
231 this_entry->maps_ = 235 this_entry->maps_ =
232 this_entry->maps_->Union(that_entry->maps_, phase_->zone()); 236 this_entry->maps_->Union(that_entry->maps_, phase_->zone());
237 this_entry->is_stable_ =
238 this_entry->is_stable_ && that_entry->is_stable_;
233 if (this_entry->check_ != that_entry->check_) { 239 if (this_entry->check_ != that_entry->check_) {
234 this_entry->check_ = NULL; 240 this_entry->check_ = NULL;
235 } 241 }
236 ASSERT(this_entry->maps_->size() > 0); 242 ASSERT(this_entry->maps_->size() > 0);
237 } 243 }
238 } 244 }
239 if (compact) Compact(); 245 if (compact) Compact();
240 } 246 }
241 } 247 }
242 if (FLAG_trace_check_elimination) { 248 if (FLAG_trace_check_elimination) {
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
303 } 309 }
304 310
305 if (FLAG_trace_check_elimination) { 311 if (FLAG_trace_check_elimination) {
306 Print(); 312 Print();
307 } 313 }
308 INC_STAT(narrowed_); 314 INC_STAT(narrowed_);
309 } 315 }
310 } 316 }
311 } else { 317 } else {
312 // No entry; insert a new one. 318 // No entry; insert a new one.
313 Insert(object, instr, instr->map_set().Copy(phase_->zone())); 319 Insert(object, instr, instr->map_set().Copy(phase_->zone()),
320 instr->is_stable());
314 } 321 }
315 } 322 }
316 323
317 void ReduceCheckValue(HCheckValue* instr) { 324 void ReduceCheckValue(HCheckValue* instr) {
318 // Canonicalize HCheckValues; they might have their values load-eliminated. 325 // Canonicalize HCheckValues; they might have their values load-eliminated.
319 HValue* value = instr->Canonicalize(); 326 HValue* value = instr->Canonicalize();
320 if (value == NULL) { 327 if (value == NULL) {
321 instr->DeleteAndReplaceWith(instr->value()); 328 instr->DeleteAndReplaceWith(instr->value());
322 INC_STAT(removed_); 329 INC_STAT(removed_);
323 } else if (value != instr) { 330 } else if (value != instr) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 instr->DeleteAndReplaceWith(NULL); 362 instr->DeleteAndReplaceWith(NULL);
356 INC_STAT(removed_); 363 INC_STAT(removed_);
357 } else { 364 } else {
358 // Only one map survives the check. 365 // Only one map survives the check.
359 maps->Clear(); 366 maps->Clear();
360 maps->Add(map, phase_->zone()); 367 maps->Add(map, phase_->zone());
361 } 368 }
362 } 369 }
363 } else { 370 } else {
364 // No prior information. 371 // No prior information.
365 Insert(object, map); 372 // TODO(verwaest): Tag map constants with stability.
373 Insert(object, map, false);
366 } 374 }
367 } 375 }
368 376
369 void ReduceCheckHeapObject(HCheckHeapObject* instr) { 377 void ReduceCheckHeapObject(HCheckHeapObject* instr) {
370 if (FindMaps(instr->value()->ActualValue()) != NULL) { 378 if (FindMaps(instr->value()->ActualValue()) != NULL) {
371 // If the object has known maps, it's definitely a heap object. 379 // If the object has known maps, it's definitely a heap object.
372 instr->DeleteAndReplaceWith(instr->value()); 380 instr->DeleteAndReplaceWith(instr->value());
373 INC_STAT(removed_cho_); 381 INC_STAT(removed_cho_);
374 } 382 }
375 } 383 }
376 384
377 void ReduceStoreNamedField(HStoreNamedField* instr) { 385 void ReduceStoreNamedField(HStoreNamedField* instr) {
378 HValue* object = instr->object()->ActualValue(); 386 HValue* object = instr->object()->ActualValue();
379 if (instr->has_transition()) { 387 if (instr->has_transition()) {
380 // This store transitions the object to a new map. 388 // This store transitions the object to a new map.
381 Kill(object); 389 Kill(object);
382 Insert(object, MapConstant(instr->transition())); 390 Insert(object, MapConstant(instr->transition()), instr->is_stable());
383 } else if (IsMapAccess(instr->access())) { 391 } else if (IsMapAccess(instr->access())) {
384 // This is a store directly to the map field of the object. 392 // This is a store directly to the map field of the object.
385 Kill(object); 393 Kill(object);
386 if (!instr->value()->IsConstant()) return; 394 if (!instr->value()->IsConstant()) return;
387 Insert(object, MapConstant(instr->value())); 395 // TODO(verwaest): Tag with stability.
396 Insert(object, MapConstant(instr->value()), false);
388 } else { 397 } else {
389 // If the instruction changes maps, it should be handled above. 398 // If the instruction changes maps, it should be handled above.
390 CHECK(!instr->CheckChangesFlag(kMaps)); 399 CHECK(!instr->CheckChangesFlag(kMaps));
391 } 400 }
392 } 401 }
393 402
394 void ReduceCompareMap(HCompareMap* instr) { 403 void ReduceCompareMap(HCompareMap* instr) {
395 MapSet maps = FindMaps(instr->value()->ActualValue()); 404 MapSet maps = FindMaps(instr->value()->ActualValue());
396 if (maps == NULL) return; 405 if (maps == NULL) return;
397 if (maps->Contains(instr->map())) { 406 if (maps->Contains(instr->map())) {
(...skipping 19 matching lines...) Expand all
417 // If the object has the original map, it will be transitioned. 426 // If the object has the original map, it will be transitioned.
418 maps->Remove(instr->original_map()); 427 maps->Remove(instr->original_map());
419 maps->Add(instr->transitioned_map(), phase_->zone()); 428 maps->Add(instr->transitioned_map(), phase_->zone());
420 } else { 429 } else {
421 // Object does not have the given map, thus the transition is redundant. 430 // Object does not have the given map, thus the transition is redundant.
422 instr->DeleteAndReplaceWith(instr->object()); 431 instr->DeleteAndReplaceWith(instr->object());
423 INC_STAT(transitions_); 432 INC_STAT(transitions_);
424 } 433 }
425 } 434 }
426 435
436 // Reset the table.
437 void Reset() {
438 size_ = 0;
439 cursor_ = 0;
440 }
441
427 // Kill everything in the table. 442 // Kill everything in the table.
428 void Kill() { 443 void Kill() {
Igor Sheludko 2014/02/12 12:58:20 KillNonStableEntries(); ?
Toon Verwaest 2014/02/12 14:53:34 Done.
429 size_ = 0; 444 bool compact = false;
430 cursor_ = 0; 445 for (int i = 0; i < size_; i++) {
446 HCheckTableEntry* entry = &entries_[i];
447 ASSERT(entry->object_ != NULL);
448 if (!entry->is_stable_) {
449 entry->object_ = NULL;
450 compact = true;
451 }
452 }
453 if (compact) Compact();
431 } 454 }
432 455
433 // Kill everything in the table that may alias {object}. 456 // Kill everything in the table that may alias {object}.
434 void Kill(HValue* object) { 457 void Kill(HValue* object) {
435 bool compact = false; 458 bool compact = false;
436 for (int i = 0; i < size_; i++) { 459 for (int i = 0; i < size_; i++) {
437 HCheckTableEntry* entry = &entries_[i]; 460 HCheckTableEntry* entry = &entries_[i];
438 ASSERT(entry->object_ != NULL); 461 ASSERT(entry->object_ != NULL);
439 if (phase_->aliasing_->MayAlias(entry->object_, object)) { 462 if (phase_->aliasing_->MayAlias(entry->object_, object)) {
440 entry->object_ = NULL; 463 entry->object_ = NULL;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
506 if (phase_->aliasing_->MustAlias(entry->object_, object)) return entry; 529 if (phase_->aliasing_->MustAlias(entry->object_, object)) return entry;
507 } 530 }
508 return NULL; 531 return NULL;
509 } 532 }
510 533
511 MapSet FindMaps(HValue* object) { 534 MapSet FindMaps(HValue* object) {
512 HCheckTableEntry* entry = Find(object); 535 HCheckTableEntry* entry = Find(object);
513 return entry == NULL ? NULL : entry->maps_; 536 return entry == NULL ? NULL : entry->maps_;
514 } 537 }
515 538
516 void Insert(HValue* object, Unique<Map> map) { 539 void Insert(HValue* object, Unique<Map> map, bool is_stable) {
517 MapSet list = new(phase_->zone()) UniqueSet<Map>(); 540 MapSet list = new(phase_->zone()) UniqueSet<Map>();
518 list->Add(map, phase_->zone()); 541 list->Add(map, phase_->zone());
519 Insert(object, NULL, list); 542 Insert(object, NULL, list, is_stable);
520 } 543 }
521 544
522 void Insert(HValue* object, HCheckMaps* check, MapSet maps) { 545 void Insert(HValue* object, HCheckMaps* check, MapSet maps, bool is_stable) {
523 HCheckTableEntry* entry = &entries_[cursor_++]; 546 HCheckTableEntry* entry = &entries_[cursor_++];
524 entry->object_ = object; 547 entry->object_ = object;
525 entry->check_ = check; 548 entry->check_ = check;
526 entry->maps_ = maps; 549 entry->maps_ = maps;
550 entry->is_stable_ = is_stable;
527 // If the table becomes full, wrap around and overwrite older entries. 551 // If the table becomes full, wrap around and overwrite older entries.
528 if (cursor_ == kMaxTrackedObjects) cursor_ = 0; 552 if (cursor_ == kMaxTrackedObjects) cursor_ = 0;
529 if (size_ < kMaxTrackedObjects) size_++; 553 if (size_ < kMaxTrackedObjects) size_++;
530 } 554 }
531 555
532 bool IsMapAccess(HObjectAccess access) { 556 bool IsMapAccess(HObjectAccess access) {
533 return access.IsInobject() && access.offset() == JSObject::kMapOffset; 557 return access.IsInobject() && access.offset() == JSObject::kMapOffset;
534 } 558 }
535 559
536 Unique<Map> MapConstant(HValue* value) { 560 Unique<Map> MapConstant(HValue* value) {
537 return Unique<Map>::cast(HConstant::cast(value)->GetUnique()); 561 return Unique<Map>::cast(HConstant::cast(value)->GetUnique());
538 } 562 }
539 563
540 friend class HCheckMapsEffects; 564 friend class HCheckMapsEffects;
541 565
542 HCheckEliminationPhase* phase_; 566 HCheckEliminationPhase* phase_;
543 HCheckTableEntry entries_[kMaxTrackedObjects]; 567 HCheckTableEntry entries_[kMaxTrackedObjects];
544 int16_t cursor_; // Must be <= kMaxTrackedObjects 568 int16_t cursor_; // Must be <= kMaxTrackedObjects
545 int16_t size_; // Must be <= kMaxTrackedObjects 569 int16_t size_; // Must be <= kMaxTrackedObjects
546 // TODO(titzer): STATIC_ASSERT kMaxTrackedObjects < max(cursor_) 570 // TODO(titzer): STATIC_ASSERT kMaxTrackedObjects < max(cursor_)
547 }; 571 };
548 572
549 573
550 // Collects instructions that can cause effects that invalidate information 574 // Collects instructions that can cause effects that invalidate information
551 // needed for check elimination. 575 // needed for check elimination.
552 class HCheckMapsEffects : public ZoneObject { 576 class HCheckMapsEffects : public ZoneObject {
553 public: 577 public:
554 explicit HCheckMapsEffects(Zone* zone) 578 explicit HCheckMapsEffects(Zone* zone)
555 : maps_stored_(false), 579 : maps_stored_(false),
580 requires_reset_(false),
556 stores_(5, zone) { } 581 stores_(5, zone) { }
557 582
558 inline bool Disabled() { 583 inline bool Disabled() {
559 return false; // Effects are _not_ disabled. 584 return false; // Effects are _not_ disabled.
560 } 585 }
561 586
562 // Process a possibly side-effecting instruction. 587 // Process a possibly side-effecting instruction.
563 void Process(HInstruction* instr, Zone* zone) { 588 void Process(HInstruction* instr, Zone* zone) {
564 switch (instr->opcode()) { 589 switch (instr->opcode()) {
565 case HValue::kStoreNamedField: { 590 case HValue::kStoreNamedField: {
566 stores_.Add(HStoreNamedField::cast(instr), zone); 591 stores_.Add(HStoreNamedField::cast(instr), zone);
567 break; 592 break;
568 } 593 }
569 case HValue::kOsrEntry: { 594 case HValue::kOsrEntry: {
570 // Kill everything. Loads must not be hoisted past the OSR entry. 595 // Kill everything. Loads must not be hoisted past the OSR entry.
571 maps_stored_ = true; 596 requires_reset_ = true;
597 break;
572 } 598 }
573 default: { 599 default: {
574 maps_stored_ |= (instr->CheckChangesFlag(kMaps) | 600 maps_stored_ |= (instr->CheckChangesFlag(kMaps) |
575 instr->CheckChangesFlag(kElementsKind)); 601 instr->CheckChangesFlag(kElementsKind));
576 } 602 }
577 } 603 }
578 } 604 }
579 605
580 // Apply these effects to the given check elimination table. 606 // Apply these effects to the given check elimination table.
581 void Apply(HCheckTable* table) { 607 void Apply(HCheckTable* table) {
608 if (requires_reset_) {
609 table->Reset();
610 return;
611 }
582 if (maps_stored_) { 612 if (maps_stored_) {
583 // Uncontrollable map modifications; kill everything. 613 // Uncontrollable map modifications; kill everything.
584 table->Kill(); 614 table->Kill();
585 return; 615 return;
586 } 616 }
587 617
588 // Kill maps for each store contained in these effects. 618 // Kill maps for each store contained in these effects.
589 for (int i = 0; i < stores_.length(); i++) { 619 for (int i = 0; i < stores_.length(); i++) {
590 HStoreNamedField* s = stores_[i]; 620 HStoreNamedField* s = stores_[i];
591 if (table->IsMapAccess(s->access()) || s->has_transition()) { 621 if (table->IsMapAccess(s->access()) || s->has_transition()) {
592 table->Kill(s->object()->ActualValue()); 622 table->Kill(s->object()->ActualValue());
593 } 623 }
594 } 624 }
595 } 625 }
596 626
597 // Union these effects with the other effects. 627 // Union these effects with the other effects.
598 void Union(HCheckMapsEffects* that, Zone* zone) { 628 void Union(HCheckMapsEffects* that, Zone* zone) {
629 requires_reset_ |= that->requires_reset_;
599 maps_stored_ |= that->maps_stored_; 630 maps_stored_ |= that->maps_stored_;
600 for (int i = 0; i < that->stores_.length(); i++) { 631 for (int i = 0; i < that->stores_.length(); i++) {
601 stores_.Add(that->stores_[i], zone); 632 stores_.Add(that->stores_[i], zone);
602 } 633 }
603 } 634 }
604 635
605 private: 636 private:
606 bool maps_stored_ : 1; 637 bool maps_stored_ : 1;
638 bool requires_reset_ : 1;
Igor Sheludko 2014/02/12 12:58:20 Consider replacing these flags with GVNFlagSet as
Toon Verwaest 2014/02/12 14:53:34 Done.
607 ZoneList<HStoreNamedField*> stores_; 639 ZoneList<HStoreNamedField*> stores_;
608 }; 640 };
609 641
610 642
611 // The main routine of the analysis phase. Use the HFlowEngine for either a 643 // The main routine of the analysis phase. Use the HFlowEngine for either a
612 // local or a global analysis. 644 // local or a global analysis.
613 void HCheckEliminationPhase::Run() { 645 void HCheckEliminationPhase::Run() {
614 HFlowEngine<HCheckTable, HCheckMapsEffects> engine(graph(), zone()); 646 HFlowEngine<HCheckTable, HCheckMapsEffects> engine(graph(), zone());
615 HCheckTable* table = new(zone()) HCheckTable(this); 647 HCheckTable* table = new(zone()) HCheckTable(this);
616 648
617 if (GLOBAL) { 649 if (GLOBAL) {
618 // Perform a global analysis. 650 // Perform a global analysis.
619 engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), table); 651 engine.AnalyzeDominatedBlocks(graph()->blocks()->at(0), table);
620 } else { 652 } else {
621 // Perform only local analysis. 653 // Perform only local analysis.
622 for (int i = 0; i < graph()->blocks()->length(); i++) { 654 for (int i = 0; i < graph()->blocks()->length(); i++) {
623 table->Kill(); 655 table->Reset();
624 engine.AnalyzeOneBlock(graph()->blocks()->at(i), table); 656 engine.AnalyzeOneBlock(graph()->blocks()->at(i), table);
625 } 657 }
626 } 658 }
627 659
628 if (FLAG_trace_check_elimination) PrintStats(); 660 if (FLAG_trace_check_elimination) PrintStats();
629 } 661 }
630 662
631 663
632 // Are we eliminated yet? 664 // Are we eliminated yet?
633 void HCheckEliminationPhase::PrintStats() { 665 void HCheckEliminationPhase::PrintStats() {
634 #if DEBUG 666 #if DEBUG
635 #define PRINT_STAT(x) if (x##_ > 0) PrintF(" %-16s = %2d\n", #x, x##_) 667 #define PRINT_STAT(x) if (x##_ > 0) PrintF(" %-16s = %2d\n", #x, x##_)
636 #else 668 #else
637 #define PRINT_STAT(x) 669 #define PRINT_STAT(x)
638 #endif 670 #endif
639 PRINT_STAT(redundant); 671 PRINT_STAT(redundant);
640 PRINT_STAT(removed); 672 PRINT_STAT(removed);
641 PRINT_STAT(removed_cho); 673 PRINT_STAT(removed_cho);
642 PRINT_STAT(narrowed); 674 PRINT_STAT(narrowed);
643 PRINT_STAT(loads); 675 PRINT_STAT(loads);
644 PRINT_STAT(empty); 676 PRINT_STAT(empty);
645 PRINT_STAT(compares_true); 677 PRINT_STAT(compares_true);
646 PRINT_STAT(compares_false); 678 PRINT_STAT(compares_false);
647 PRINT_STAT(transitions); 679 PRINT_STAT(transitions);
648 } 680 }
649 681
650 } } // namespace v8::internal 682 } } // namespace v8::internal
OLDNEW
« no previous file with comments | « src/hydrogen.cc ('k') | src/hydrogen-instructions.h » ('j') | src/hydrogen-instructions.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698