OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/hydrogen-check-elimination.h" | 5 #include "src/hydrogen-check-elimination.h" |
6 | 6 |
7 #include "src/hydrogen-alias-analysis.h" | 7 #include "src/hydrogen-alias-analysis.h" |
8 #include "src/hydrogen-flow-engine.h" | 8 #include "src/hydrogen-flow-engine.h" |
9 | 9 |
10 #define GLOBAL 1 | 10 #define GLOBAL 1 |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
50 UNREACHABLE(); | 50 UNREACHABLE(); |
51 return NULL; | 51 return NULL; |
52 } | 52 } |
53 | 53 |
54 static State StateMerge(State state1, State state2) { | 54 static State StateMerge(State state1, State state2) { |
55 if (state1 == state2) return state1; | 55 if (state1 == state2) return state1; |
56 if ((state1 == CHECKED && state2 == CHECKED_STABLE) || | 56 if ((state1 == CHECKED && state2 == CHECKED_STABLE) || |
57 (state2 == CHECKED && state1 == CHECKED_STABLE)) { | 57 (state2 == CHECKED && state1 == CHECKED_STABLE)) { |
58 return CHECKED; | 58 return CHECKED; |
59 } | 59 } |
60 ASSERT((state1 == CHECKED_STABLE && state2 == UNCHECKED_STABLE) || | 60 DCHECK((state1 == CHECKED_STABLE && state2 == UNCHECKED_STABLE) || |
61 (state2 == CHECKED_STABLE && state1 == UNCHECKED_STABLE)); | 61 (state2 == CHECKED_STABLE && state1 == UNCHECKED_STABLE)); |
62 return UNCHECKED_STABLE; | 62 return UNCHECKED_STABLE; |
63 } | 63 } |
64 | 64 |
65 HValue* object_; // The object being approximated. NULL => invalid entry. | 65 HValue* object_; // The object being approximated. NULL => invalid entry. |
66 HInstruction* check_; // The last check instruction. | 66 HInstruction* check_; // The last check instruction. |
67 MapSet maps_; // The set of known maps for the object. | 67 MapSet maps_; // The set of known maps for the object. |
68 State state_; // The state of this entry. | 68 State state_; // The state of this entry. |
69 }; | 69 }; |
70 | 70 |
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
170 } | 170 } |
171 return state; | 171 return state; |
172 } | 172 } |
173 | 173 |
174 private: | 174 private: |
175 // Copy state to successor block. | 175 // Copy state to successor block. |
176 HCheckTable* Copy(HBasicBlock* succ, HBasicBlock* from_block, Zone* zone) { | 176 HCheckTable* Copy(HBasicBlock* succ, HBasicBlock* from_block, Zone* zone) { |
177 HCheckTable* copy = new(zone) HCheckTable(phase_); | 177 HCheckTable* copy = new(zone) HCheckTable(phase_); |
178 for (int i = 0; i < size_; i++) { | 178 for (int i = 0; i < size_; i++) { |
179 HCheckTableEntry* old_entry = &entries_[i]; | 179 HCheckTableEntry* old_entry = &entries_[i]; |
180 ASSERT(old_entry->maps_->size() > 0); | 180 DCHECK(old_entry->maps_->size() > 0); |
181 HCheckTableEntry* new_entry = ©->entries_[i]; | 181 HCheckTableEntry* new_entry = ©->entries_[i]; |
182 new_entry->object_ = old_entry->object_; | 182 new_entry->object_ = old_entry->object_; |
183 new_entry->maps_ = old_entry->maps_; | 183 new_entry->maps_ = old_entry->maps_; |
184 new_entry->state_ = old_entry->state_; | 184 new_entry->state_ = old_entry->state_; |
185 // Keep the check if the existing check's block dominates the successor. | 185 // Keep the check if the existing check's block dominates the successor. |
186 if (old_entry->check_ != NULL && | 186 if (old_entry->check_ != NULL && |
187 old_entry->check_->block()->Dominates(succ)) { | 187 old_entry->check_->block()->Dominates(succ)) { |
188 new_entry->check_ = old_entry->check_; | 188 new_entry->check_ = old_entry->check_; |
189 } else { | 189 } else { |
190 // Leave it NULL till we meet a new check instruction for this object | 190 // Leave it NULL till we meet a new check instruction for this object |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
234 entry->check_ = cmp; | 234 entry->check_ = cmp; |
235 entry->state_ = state; | 235 entry->state_ = state; |
236 } | 236 } |
237 } else { | 237 } else { |
238 // Learn on the false branch of if(CompareMap(x)). | 238 // Learn on the false branch of if(CompareMap(x)). |
239 if (entry != NULL) { | 239 if (entry != NULL) { |
240 EnsureChecked(entry, object, cmp); | 240 EnsureChecked(entry, object, cmp); |
241 UniqueSet<Map>* maps = entry->maps_->Copy(zone); | 241 UniqueSet<Map>* maps = entry->maps_->Copy(zone); |
242 maps->Remove(cmp->map()); | 242 maps->Remove(cmp->map()); |
243 entry->maps_ = maps; | 243 entry->maps_ = maps; |
244 ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, entry->state_); | 244 DCHECK_NE(HCheckTableEntry::UNCHECKED_STABLE, entry->state_); |
245 } | 245 } |
246 } | 246 } |
247 learned = true; | 247 learned = true; |
248 } else if (is_true_branch && end->IsCompareObjectEqAndBranch()) { | 248 } else if (is_true_branch && end->IsCompareObjectEqAndBranch()) { |
249 // Learn on the true branch of if(CmpObjectEq(x, y)). | 249 // Learn on the true branch of if(CmpObjectEq(x, y)). |
250 HCompareObjectEqAndBranch* cmp = | 250 HCompareObjectEqAndBranch* cmp = |
251 HCompareObjectEqAndBranch::cast(end); | 251 HCompareObjectEqAndBranch::cast(end); |
252 HValue* left = cmp->left()->ActualValue(); | 252 HValue* left = cmp->left()->ActualValue(); |
253 HValue* right = cmp->right()->ActualValue(); | 253 HValue* right = cmp->right()->ActualValue(); |
254 HCheckTableEntry* le = copy->Find(left); | 254 HCheckTableEntry* le = copy->Find(left); |
255 HCheckTableEntry* re = copy->Find(right); | 255 HCheckTableEntry* re = copy->Find(right); |
256 if (le == NULL) { | 256 if (le == NULL) { |
257 if (re != NULL) { | 257 if (re != NULL) { |
258 copy->Insert(left, NULL, re->maps_, re->state_); | 258 copy->Insert(left, NULL, re->maps_, re->state_); |
259 } | 259 } |
260 } else if (re == NULL) { | 260 } else if (re == NULL) { |
261 copy->Insert(right, NULL, le->maps_, le->state_); | 261 copy->Insert(right, NULL, le->maps_, le->state_); |
262 } else { | 262 } else { |
263 EnsureChecked(le, cmp->left(), cmp); | 263 EnsureChecked(le, cmp->left(), cmp); |
264 EnsureChecked(re, cmp->right(), cmp); | 264 EnsureChecked(re, cmp->right(), cmp); |
265 le->maps_ = re->maps_ = le->maps_->Intersect(re->maps_, zone); | 265 le->maps_ = re->maps_ = le->maps_->Intersect(re->maps_, zone); |
266 le->state_ = re->state_ = HCheckTableEntry::StateMerge( | 266 le->state_ = re->state_ = HCheckTableEntry::StateMerge( |
267 le->state_, re->state_); | 267 le->state_, re->state_); |
268 ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, le->state_); | 268 DCHECK_NE(HCheckTableEntry::UNCHECKED_STABLE, le->state_); |
269 ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, re->state_); | 269 DCHECK_NE(HCheckTableEntry::UNCHECKED_STABLE, re->state_); |
270 } | 270 } |
271 learned = true; | 271 learned = true; |
272 } else if (end->IsIsStringAndBranch()) { | 272 } else if (end->IsIsStringAndBranch()) { |
273 HIsStringAndBranch* cmp = HIsStringAndBranch::cast(end); | 273 HIsStringAndBranch* cmp = HIsStringAndBranch::cast(end); |
274 HValue* object = cmp->value()->ActualValue(); | 274 HValue* object = cmp->value()->ActualValue(); |
275 HCheckTableEntry* entry = copy->Find(object); | 275 HCheckTableEntry* entry = copy->Find(object); |
276 if (is_true_branch) { | 276 if (is_true_branch) { |
277 // Learn on the true branch of if(IsString(x)). | 277 // Learn on the true branch of if(IsString(x)). |
278 if (entry == NULL) { | 278 if (entry == NULL) { |
279 copy->Insert(object, NULL, string_maps(), | 279 copy->Insert(object, NULL, string_maps(), |
280 HCheckTableEntry::CHECKED); | 280 HCheckTableEntry::CHECKED); |
281 } else { | 281 } else { |
282 EnsureChecked(entry, object, cmp); | 282 EnsureChecked(entry, object, cmp); |
283 entry->maps_ = entry->maps_->Intersect(string_maps(), zone); | 283 entry->maps_ = entry->maps_->Intersect(string_maps(), zone); |
284 ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, entry->state_); | 284 DCHECK_NE(HCheckTableEntry::UNCHECKED_STABLE, entry->state_); |
285 } | 285 } |
286 } else { | 286 } else { |
287 // Learn on the false branch of if(IsString(x)). | 287 // Learn on the false branch of if(IsString(x)). |
288 if (entry != NULL) { | 288 if (entry != NULL) { |
289 EnsureChecked(entry, object, cmp); | 289 EnsureChecked(entry, object, cmp); |
290 entry->maps_ = entry->maps_->Subtract(string_maps(), zone); | 290 entry->maps_ = entry->maps_->Subtract(string_maps(), zone); |
291 ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, entry->state_); | 291 DCHECK_NE(HCheckTableEntry::UNCHECKED_STABLE, entry->state_); |
292 } | 292 } |
293 } | 293 } |
294 } | 294 } |
295 // Learning on false branches requires storing negative facts. | 295 // Learning on false branches requires storing negative facts. |
296 } | 296 } |
297 | 297 |
298 if (FLAG_trace_check_elimination) { | 298 if (FLAG_trace_check_elimination) { |
299 PrintF("B%d checkmaps-table %s from B%d:\n", | 299 PrintF("B%d checkmaps-table %s from B%d:\n", |
300 succ->block_id(), | 300 succ->block_id(), |
301 learned ? "learned" : "copied", | 301 learned ? "learned" : "copied", |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
337 this_entry->object_ = NULL; | 337 this_entry->object_ = NULL; |
338 compact = true; | 338 compact = true; |
339 } else { | 339 } else { |
340 this_entry->maps_ = | 340 this_entry->maps_ = |
341 this_entry->maps_->Union(that_entry->maps_, zone); | 341 this_entry->maps_->Union(that_entry->maps_, zone); |
342 this_entry->state_ = HCheckTableEntry::StateMerge( | 342 this_entry->state_ = HCheckTableEntry::StateMerge( |
343 this_entry->state_, that_entry->state_); | 343 this_entry->state_, that_entry->state_); |
344 if (this_entry->check_ != that_entry->check_) { | 344 if (this_entry->check_ != that_entry->check_) { |
345 this_entry->check_ = NULL; | 345 this_entry->check_ = NULL; |
346 } | 346 } |
347 ASSERT(this_entry->maps_->size() > 0); | 347 DCHECK(this_entry->maps_->size() > 0); |
348 } | 348 } |
349 } | 349 } |
350 if (compact) Compact(); | 350 if (compact) Compact(); |
351 } | 351 } |
352 | 352 |
353 if (FLAG_trace_check_elimination) { | 353 if (FLAG_trace_check_elimination) { |
354 PrintF("B%d checkmaps-table merged with B%d table:\n", | 354 PrintF("B%d checkmaps-table merged with B%d table:\n", |
355 succ->block_id(), pred_block->block_id()); | 355 succ->block_id(), pred_block->block_id()); |
356 Print(this); | 356 Print(this); |
357 } | 357 } |
358 return this; | 358 return this; |
359 } | 359 } |
360 | 360 |
361 void ReduceCheckMaps(HCheckMaps* instr) { | 361 void ReduceCheckMaps(HCheckMaps* instr) { |
362 HValue* object = instr->value()->ActualValue(); | 362 HValue* object = instr->value()->ActualValue(); |
363 HCheckTableEntry* entry = Find(object); | 363 HCheckTableEntry* entry = Find(object); |
364 if (entry != NULL) { | 364 if (entry != NULL) { |
365 // entry found; | 365 // entry found; |
366 HGraph* graph = instr->block()->graph(); | 366 HGraph* graph = instr->block()->graph(); |
367 if (entry->maps_->IsSubset(instr->maps())) { | 367 if (entry->maps_->IsSubset(instr->maps())) { |
368 // The first check is more strict; the second is redundant. | 368 // The first check is more strict; the second is redundant. |
369 if (entry->check_ != NULL) { | 369 if (entry->check_ != NULL) { |
370 ASSERT_NE(HCheckTableEntry::UNCHECKED_STABLE, entry->state_); | 370 DCHECK_NE(HCheckTableEntry::UNCHECKED_STABLE, entry->state_); |
371 TRACE(("Replacing redundant CheckMaps #%d at B%d with #%d\n", | 371 TRACE(("Replacing redundant CheckMaps #%d at B%d with #%d\n", |
372 instr->id(), instr->block()->block_id(), entry->check_->id())); | 372 instr->id(), instr->block()->block_id(), entry->check_->id())); |
373 instr->DeleteAndReplaceWith(entry->check_); | 373 instr->DeleteAndReplaceWith(entry->check_); |
374 INC_STAT(redundant_); | 374 INC_STAT(redundant_); |
375 } else if (entry->state_ == HCheckTableEntry::UNCHECKED_STABLE) { | 375 } else if (entry->state_ == HCheckTableEntry::UNCHECKED_STABLE) { |
376 ASSERT_EQ(NULL, entry->check_); | 376 DCHECK_EQ(NULL, entry->check_); |
377 TRACE(("Marking redundant CheckMaps #%d at B%d as stability check\n", | 377 TRACE(("Marking redundant CheckMaps #%d at B%d as stability check\n", |
378 instr->id(), instr->block()->block_id())); | 378 instr->id(), instr->block()->block_id())); |
379 instr->set_maps(entry->maps_->Copy(graph->zone())); | 379 instr->set_maps(entry->maps_->Copy(graph->zone())); |
380 instr->MarkAsStabilityCheck(); | 380 instr->MarkAsStabilityCheck(); |
381 entry->state_ = HCheckTableEntry::CHECKED_STABLE; | 381 entry->state_ = HCheckTableEntry::CHECKED_STABLE; |
382 } else if (!instr->IsStabilityCheck()) { | 382 } else if (!instr->IsStabilityCheck()) { |
383 TRACE(("Marking redundant CheckMaps #%d at B%d as dead\n", | 383 TRACE(("Marking redundant CheckMaps #%d at B%d as dead\n", |
384 instr->id(), instr->block()->block_id())); | 384 instr->id(), instr->block()->block_id())); |
385 // Mark check as dead but leave it in the graph as a checkpoint for | 385 // Mark check as dead but leave it in the graph as a checkpoint for |
386 // subsequent checks. | 386 // subsequent checks. |
(...skipping 19 matching lines...) Expand all Loading... |
406 entry->state_ = HCheckTableEntry::CHECKED_STABLE; | 406 entry->state_ = HCheckTableEntry::CHECKED_STABLE; |
407 } | 407 } |
408 if (intersection->size() != instr->maps()->size()) { | 408 if (intersection->size() != instr->maps()->size()) { |
409 // Narrow set of maps in the second check maps instruction. | 409 // Narrow set of maps in the second check maps instruction. |
410 if (entry->check_ != NULL && | 410 if (entry->check_ != NULL && |
411 entry->check_->block() == instr->block() && | 411 entry->check_->block() == instr->block() && |
412 entry->check_->IsCheckMaps()) { | 412 entry->check_->IsCheckMaps()) { |
413 // There is a check in the same block so replace it with a more | 413 // There is a check in the same block so replace it with a more |
414 // strict check and eliminate the second check entirely. | 414 // strict check and eliminate the second check entirely. |
415 HCheckMaps* check = HCheckMaps::cast(entry->check_); | 415 HCheckMaps* check = HCheckMaps::cast(entry->check_); |
416 ASSERT(!check->IsStabilityCheck()); | 416 DCHECK(!check->IsStabilityCheck()); |
417 TRACE(("CheckMaps #%d at B%d narrowed\n", check->id(), | 417 TRACE(("CheckMaps #%d at B%d narrowed\n", check->id(), |
418 check->block()->block_id())); | 418 check->block()->block_id())); |
419 // Update map set and ensure that the check is alive. | 419 // Update map set and ensure that the check is alive. |
420 check->set_maps(intersection); | 420 check->set_maps(intersection); |
421 check->ClearFlag(HValue::kIsDead); | 421 check->ClearFlag(HValue::kIsDead); |
422 TRACE(("Replacing redundant CheckMaps #%d at B%d with #%d\n", | 422 TRACE(("Replacing redundant CheckMaps #%d at B%d with #%d\n", |
423 instr->id(), instr->block()->block_id(), entry->check_->id())); | 423 instr->id(), instr->block()->block_id(), entry->check_->id())); |
424 instr->DeleteAndReplaceWith(entry->check_); | 424 instr->DeleteAndReplaceWith(entry->check_); |
425 } else { | 425 } else { |
426 TRACE(("CheckMaps #%d at B%d narrowed\n", instr->id(), | 426 TRACE(("CheckMaps #%d at B%d narrowed\n", instr->id(), |
(...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
488 } | 488 } |
489 } | 489 } |
490 } | 490 } |
491 | 491 |
492 void ReduceLoadNamedField(HLoadNamedField* instr) { | 492 void ReduceLoadNamedField(HLoadNamedField* instr) { |
493 // Reduce a load of the map field when it is known to be a constant. | 493 // Reduce a load of the map field when it is known to be a constant. |
494 if (!instr->access().IsMap()) { | 494 if (!instr->access().IsMap()) { |
495 // Check if we introduce field maps here. | 495 // Check if we introduce field maps here. |
496 MapSet maps = instr->maps(); | 496 MapSet maps = instr->maps(); |
497 if (maps != NULL) { | 497 if (maps != NULL) { |
498 ASSERT_NE(0, maps->size()); | 498 DCHECK_NE(0, maps->size()); |
499 Insert(instr, NULL, maps, HCheckTableEntry::UNCHECKED_STABLE); | 499 Insert(instr, NULL, maps, HCheckTableEntry::UNCHECKED_STABLE); |
500 } | 500 } |
501 return; | 501 return; |
502 } | 502 } |
503 | 503 |
504 HValue* object = instr->object()->ActualValue(); | 504 HValue* object = instr->object()->ActualValue(); |
505 HCheckTableEntry* entry = Find(object); | 505 HCheckTableEntry* entry = Find(object); |
506 if (entry == NULL || entry->maps_->size() != 1) return; // Not a constant. | 506 if (entry == NULL || entry->maps_->size() != 1) return; // Not a constant. |
507 | 507 |
508 EnsureChecked(entry, object, instr); | 508 EnsureChecked(entry, object, instr); |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
659 void Kill() { | 659 void Kill() { |
660 size_ = 0; | 660 size_ = 0; |
661 cursor_ = 0; | 661 cursor_ = 0; |
662 } | 662 } |
663 | 663 |
664 // Kill all unstable entries in the table. | 664 // Kill all unstable entries in the table. |
665 void KillUnstableEntries() { | 665 void KillUnstableEntries() { |
666 bool compact = false; | 666 bool compact = false; |
667 for (int i = 0; i < size_; ++i) { | 667 for (int i = 0; i < size_; ++i) { |
668 HCheckTableEntry* entry = &entries_[i]; | 668 HCheckTableEntry* entry = &entries_[i]; |
669 ASSERT_NOT_NULL(entry->object_); | 669 DCHECK_NOT_NULL(entry->object_); |
670 if (entry->state_ == HCheckTableEntry::CHECKED) { | 670 if (entry->state_ == HCheckTableEntry::CHECKED) { |
671 entry->object_ = NULL; | 671 entry->object_ = NULL; |
672 compact = true; | 672 compact = true; |
673 } else { | 673 } else { |
674 // All checked stable entries become unchecked stable. | 674 // All checked stable entries become unchecked stable. |
675 entry->state_ = HCheckTableEntry::UNCHECKED_STABLE; | 675 entry->state_ = HCheckTableEntry::UNCHECKED_STABLE; |
676 entry->check_ = NULL; | 676 entry->check_ = NULL; |
677 } | 677 } |
678 } | 678 } |
679 if (compact) Compact(); | 679 if (compact) Compact(); |
680 } | 680 } |
681 | 681 |
682 // Kill everything in the table that may alias {object}. | 682 // Kill everything in the table that may alias {object}. |
683 void Kill(HValue* object) { | 683 void Kill(HValue* object) { |
684 bool compact = false; | 684 bool compact = false; |
685 for (int i = 0; i < size_; i++) { | 685 for (int i = 0; i < size_; i++) { |
686 HCheckTableEntry* entry = &entries_[i]; | 686 HCheckTableEntry* entry = &entries_[i]; |
687 ASSERT(entry->object_ != NULL); | 687 DCHECK(entry->object_ != NULL); |
688 if (phase_->aliasing_->MayAlias(entry->object_, object)) { | 688 if (phase_->aliasing_->MayAlias(entry->object_, object)) { |
689 entry->object_ = NULL; | 689 entry->object_ = NULL; |
690 compact = true; | 690 compact = true; |
691 } | 691 } |
692 } | 692 } |
693 if (compact) Compact(); | 693 if (compact) Compact(); |
694 ASSERT(Find(object) == NULL); | 694 DCHECK(Find(object) == NULL); |
695 } | 695 } |
696 | 696 |
697 void Compact() { | 697 void Compact() { |
698 // First, compact the array in place. | 698 // First, compact the array in place. |
699 int max = size_, dest = 0, old_cursor = cursor_; | 699 int max = size_, dest = 0, old_cursor = cursor_; |
700 for (int i = 0; i < max; i++) { | 700 for (int i = 0; i < max; i++) { |
701 if (entries_[i].object_ != NULL) { | 701 if (entries_[i].object_ != NULL) { |
702 if (dest != i) entries_[dest] = entries_[i]; | 702 if (dest != i) entries_[dest] = entries_[i]; |
703 dest++; | 703 dest++; |
704 } else { | 704 } else { |
705 if (i < old_cursor) cursor_--; | 705 if (i < old_cursor) cursor_--; |
706 size_--; | 706 size_--; |
707 } | 707 } |
708 } | 708 } |
709 ASSERT(size_ == dest); | 709 DCHECK(size_ == dest); |
710 ASSERT(cursor_ <= size_); | 710 DCHECK(cursor_ <= size_); |
711 | 711 |
712 // Preserve the age of the entries by moving the older entries to the end. | 712 // Preserve the age of the entries by moving the older entries to the end. |
713 if (cursor_ == size_) return; // Cursor already points at end. | 713 if (cursor_ == size_) return; // Cursor already points at end. |
714 if (cursor_ != 0) { | 714 if (cursor_ != 0) { |
715 // | L = oldest | R = newest | | | 715 // | L = oldest | R = newest | | |
716 // ^ cursor ^ size ^ MAX | 716 // ^ cursor ^ size ^ MAX |
717 HCheckTableEntry tmp_entries[kMaxTrackedObjects]; | 717 HCheckTableEntry tmp_entries[kMaxTrackedObjects]; |
718 int L = cursor_; | 718 int L = cursor_; |
719 int R = size_ - cursor_; | 719 int R = size_ - cursor_; |
720 | 720 |
721 MemMove(&tmp_entries[0], &entries_[0], L * sizeof(HCheckTableEntry)); | 721 MemMove(&tmp_entries[0], &entries_[0], L * sizeof(HCheckTableEntry)); |
722 MemMove(&entries_[0], &entries_[L], R * sizeof(HCheckTableEntry)); | 722 MemMove(&entries_[0], &entries_[L], R * sizeof(HCheckTableEntry)); |
723 MemMove(&entries_[R], &tmp_entries[0], L * sizeof(HCheckTableEntry)); | 723 MemMove(&entries_[R], &tmp_entries[0], L * sizeof(HCheckTableEntry)); |
724 } | 724 } |
725 | 725 |
726 cursor_ = size_; // Move cursor to end. | 726 cursor_ = size_; // Move cursor to end. |
727 } | 727 } |
728 | 728 |
729 static void Print(HCheckTable* table) { | 729 static void Print(HCheckTable* table) { |
730 if (table == NULL) { | 730 if (table == NULL) { |
731 PrintF(" unreachable\n"); | 731 PrintF(" unreachable\n"); |
732 return; | 732 return; |
733 } | 733 } |
734 | 734 |
735 for (int i = 0; i < table->size_; i++) { | 735 for (int i = 0; i < table->size_; i++) { |
736 HCheckTableEntry* entry = &table->entries_[i]; | 736 HCheckTableEntry* entry = &table->entries_[i]; |
737 ASSERT(entry->object_ != NULL); | 737 DCHECK(entry->object_ != NULL); |
738 PrintF(" checkmaps-table @%d: %s #%d ", i, | 738 PrintF(" checkmaps-table @%d: %s #%d ", i, |
739 entry->object_->IsPhi() ? "phi" : "object", entry->object_->id()); | 739 entry->object_->IsPhi() ? "phi" : "object", entry->object_->id()); |
740 if (entry->check_ != NULL) { | 740 if (entry->check_ != NULL) { |
741 PrintF("check #%d ", entry->check_->id()); | 741 PrintF("check #%d ", entry->check_->id()); |
742 } | 742 } |
743 MapSet list = entry->maps_; | 743 MapSet list = entry->maps_; |
744 PrintF("%d %s maps { ", list->size(), | 744 PrintF("%d %s maps { ", list->size(), |
745 HCheckTableEntry::State2String(entry->state_)); | 745 HCheckTableEntry::State2String(entry->state_)); |
746 for (int j = 0; j < list->size(); j++) { | 746 for (int j = 0; j < list->size(); j++) { |
747 if (j > 0) PrintF(", "); | 747 if (j > 0) PrintF(", "); |
748 PrintF("%" V8PRIxPTR, list->at(j).Hashcode()); | 748 PrintF("%" V8PRIxPTR, list->at(j).Hashcode()); |
749 } | 749 } |
750 PrintF(" }\n"); | 750 PrintF(" }\n"); |
751 } | 751 } |
752 } | 752 } |
753 | 753 |
754 HCheckTableEntry* Find(HValue* object) { | 754 HCheckTableEntry* Find(HValue* object) { |
755 for (int i = size_ - 1; i >= 0; i--) { | 755 for (int i = size_ - 1; i >= 0; i--) { |
756 // Search from most-recently-inserted to least-recently-inserted. | 756 // Search from most-recently-inserted to least-recently-inserted. |
757 HCheckTableEntry* entry = &entries_[i]; | 757 HCheckTableEntry* entry = &entries_[i]; |
758 ASSERT(entry->object_ != NULL); | 758 DCHECK(entry->object_ != NULL); |
759 if (phase_->aliasing_->MustAlias(entry->object_, object)) return entry; | 759 if (phase_->aliasing_->MustAlias(entry->object_, object)) return entry; |
760 } | 760 } |
761 return NULL; | 761 return NULL; |
762 } | 762 } |
763 | 763 |
764 void Insert(HValue* object, | 764 void Insert(HValue* object, |
765 HInstruction* check, | 765 HInstruction* check, |
766 Unique<Map> map, | 766 Unique<Map> map, |
767 HCheckTableEntry::State state) { | 767 HCheckTableEntry::State state) { |
768 Insert(object, check, new(zone()) UniqueSet<Map>(map, zone()), state); | 768 Insert(object, check, new(zone()) UniqueSet<Map>(map, zone()), state); |
769 } | 769 } |
770 | 770 |
771 void Insert(HValue* object, | 771 void Insert(HValue* object, |
772 HInstruction* check, | 772 HInstruction* check, |
773 MapSet maps, | 773 MapSet maps, |
774 HCheckTableEntry::State state) { | 774 HCheckTableEntry::State state) { |
775 ASSERT(state != HCheckTableEntry::UNCHECKED_STABLE || check == NULL); | 775 DCHECK(state != HCheckTableEntry::UNCHECKED_STABLE || check == NULL); |
776 HCheckTableEntry* entry = &entries_[cursor_++]; | 776 HCheckTableEntry* entry = &entries_[cursor_++]; |
777 entry->object_ = object; | 777 entry->object_ = object; |
778 entry->check_ = check; | 778 entry->check_ = check; |
779 entry->maps_ = maps; | 779 entry->maps_ = maps; |
780 entry->state_ = state; | 780 entry->state_ = state; |
781 // If the table becomes full, wrap around and overwrite older entries. | 781 // If the table becomes full, wrap around and overwrite older entries. |
782 if (cursor_ == kMaxTrackedObjects) cursor_ = 0; | 782 if (cursor_ == kMaxTrackedObjects) cursor_ = 0; |
783 if (size_ < kMaxTrackedObjects) size_++; | 783 if (size_ < kMaxTrackedObjects) size_++; |
784 } | 784 } |
785 | 785 |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
894 PRINT_STAT(removed_cit); | 894 PRINT_STAT(removed_cit); |
895 PRINT_STAT(narrowed); | 895 PRINT_STAT(narrowed); |
896 PRINT_STAT(loads); | 896 PRINT_STAT(loads); |
897 PRINT_STAT(empty); | 897 PRINT_STAT(empty); |
898 PRINT_STAT(compares_true); | 898 PRINT_STAT(compares_true); |
899 PRINT_STAT(compares_false); | 899 PRINT_STAT(compares_false); |
900 PRINT_STAT(transitions); | 900 PRINT_STAT(transitions); |
901 } | 901 } |
902 | 902 |
903 } } // namespace v8::internal | 903 } } // namespace v8::internal |
OLD | NEW |