| 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 |