| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 3428 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3439 // range grows). | 3439 // range grows). |
| 3440 // | 3440 // |
| 3441 // The precondition is that new_check follows UpperCheck() and | 3441 // The precondition is that new_check follows UpperCheck() and |
| 3442 // LowerCheck() in the same basic block, and that new_offset is not | 3442 // LowerCheck() in the same basic block, and that new_offset is not |
| 3443 // covered (otherwise we could simply remove new_check). | 3443 // covered (otherwise we could simply remove new_check). |
| 3444 // | 3444 // |
| 3445 // If HasSingleCheck() is true then new_check is added as "second check" | 3445 // If HasSingleCheck() is true then new_check is added as "second check" |
| 3446 // (either upper or lower; note that HasSingleCheck() becomes false). | 3446 // (either upper or lower; note that HasSingleCheck() becomes false). |
| 3447 // Otherwise one of the current checks is modified so that it also covers | 3447 // Otherwise one of the current checks is modified so that it also covers |
| 3448 // new_offset, and new_check is removed. | 3448 // new_offset, and new_check is removed. |
| 3449 void CoverCheck(HBoundsCheck* new_check, | 3449 // |
| 3450 // If the check cannot be modified because the context is unknown it |
| 3451 // returns false, otherwise it returns true. |
| 3452 bool CoverCheck(HBoundsCheck* new_check, |
| 3450 int32_t new_offset) { | 3453 int32_t new_offset) { |
| 3451 ASSERT(new_check->index()->representation().IsInteger32()); | 3454 ASSERT(new_check->index()->representation().IsInteger32()); |
| 3452 bool keep_new_check = false; | 3455 bool keep_new_check = false; |
| 3453 | 3456 |
| 3454 if (new_offset > upper_offset_) { | 3457 if (new_offset > upper_offset_) { |
| 3455 upper_offset_ = new_offset; | 3458 upper_offset_ = new_offset; |
| 3456 if (HasSingleCheck()) { | 3459 if (HasSingleCheck()) { |
| 3457 keep_new_check = true; | 3460 keep_new_check = true; |
| 3458 upper_check_ = new_check; | 3461 upper_check_ = new_check; |
| 3459 } else { | 3462 } else { |
| 3460 BuildOffsetAdd(upper_check_, | 3463 bool result = BuildOffsetAdd(upper_check_, |
| 3461 &added_upper_index_, | 3464 &added_upper_index_, |
| 3462 &added_upper_offset_, | 3465 &added_upper_offset_, |
| 3463 Key()->IndexBase(), | 3466 Key()->IndexBase(), |
| 3464 new_check->index()->representation(), | 3467 new_check->index()->representation(), |
| 3465 new_offset); | 3468 new_offset); |
| 3469 if (!result) return false; |
| 3466 upper_check_->SetOperandAt(0, added_upper_index_); | 3470 upper_check_->SetOperandAt(0, added_upper_index_); |
| 3467 } | 3471 } |
| 3468 } else if (new_offset < lower_offset_) { | 3472 } else if (new_offset < lower_offset_) { |
| 3469 lower_offset_ = new_offset; | 3473 lower_offset_ = new_offset; |
| 3470 if (HasSingleCheck()) { | 3474 if (HasSingleCheck()) { |
| 3471 keep_new_check = true; | 3475 keep_new_check = true; |
| 3472 lower_check_ = new_check; | 3476 lower_check_ = new_check; |
| 3473 } else { | 3477 } else { |
| 3474 BuildOffsetAdd(lower_check_, | 3478 bool result = BuildOffsetAdd(lower_check_, |
| 3475 &added_lower_index_, | 3479 &added_lower_index_, |
| 3476 &added_lower_offset_, | 3480 &added_lower_offset_, |
| 3477 Key()->IndexBase(), | 3481 Key()->IndexBase(), |
| 3478 new_check->index()->representation(), | 3482 new_check->index()->representation(), |
| 3479 new_offset); | 3483 new_offset); |
| 3484 if (!result) return false; |
| 3480 lower_check_->SetOperandAt(0, added_lower_index_); | 3485 lower_check_->SetOperandAt(0, added_lower_index_); |
| 3481 } | 3486 } |
| 3482 } else { | 3487 } else { |
| 3483 ASSERT(false); | 3488 ASSERT(false); |
| 3484 } | 3489 } |
| 3485 | 3490 |
| 3486 if (!keep_new_check) { | 3491 if (!keep_new_check) { |
| 3487 new_check->DeleteAndReplaceWith(NULL); | 3492 new_check->DeleteAndReplaceWith(NULL); |
| 3488 } | 3493 } |
| 3494 |
| 3495 return true; |
| 3489 } | 3496 } |
| 3490 | 3497 |
| 3491 void RemoveZeroOperations() { | 3498 void RemoveZeroOperations() { |
| 3492 RemoveZeroAdd(&added_lower_index_, &added_lower_offset_); | 3499 RemoveZeroAdd(&added_lower_index_, &added_lower_offset_); |
| 3493 RemoveZeroAdd(&added_upper_index_, &added_upper_offset_); | 3500 RemoveZeroAdd(&added_upper_index_, &added_upper_offset_); |
| 3494 } | 3501 } |
| 3495 | 3502 |
| 3496 BoundsCheckBbData(BoundsCheckKey* key, | 3503 BoundsCheckBbData(BoundsCheckKey* key, |
| 3497 int32_t lower_offset, | 3504 int32_t lower_offset, |
| 3498 int32_t upper_offset, | 3505 int32_t upper_offset, |
| (...skipping 22 matching lines...) Expand all Loading... |
| 3521 HBasicBlock* basic_block_; | 3528 HBasicBlock* basic_block_; |
| 3522 HBoundsCheck* lower_check_; | 3529 HBoundsCheck* lower_check_; |
| 3523 HBoundsCheck* upper_check_; | 3530 HBoundsCheck* upper_check_; |
| 3524 HAdd* added_lower_index_; | 3531 HAdd* added_lower_index_; |
| 3525 HConstant* added_lower_offset_; | 3532 HConstant* added_lower_offset_; |
| 3526 HAdd* added_upper_index_; | 3533 HAdd* added_upper_index_; |
| 3527 HConstant* added_upper_offset_; | 3534 HConstant* added_upper_offset_; |
| 3528 BoundsCheckBbData* next_in_bb_; | 3535 BoundsCheckBbData* next_in_bb_; |
| 3529 BoundsCheckBbData* father_in_dt_; | 3536 BoundsCheckBbData* father_in_dt_; |
| 3530 | 3537 |
| 3531 void BuildOffsetAdd(HBoundsCheck* check, | 3538 // Given an existing add instruction and a bounds check it tries to |
| 3539 // find the current context (either of the add or of the check index). |
| 3540 HValue* IndexContext(HAdd* add, HBoundsCheck* check) { |
| 3541 if (add != NULL) { |
| 3542 return add->context(); |
| 3543 } |
| 3544 if (check->index()->IsBinaryOperation()) { |
| 3545 return HBinaryOperation::cast(check->index())->context(); |
| 3546 } |
| 3547 return NULL; |
| 3548 } |
| 3549 |
| 3550 // This function returns false if it cannot build the add because the |
| 3551 // current context cannot be determined. |
| 3552 bool BuildOffsetAdd(HBoundsCheck* check, |
| 3532 HAdd** add, | 3553 HAdd** add, |
| 3533 HConstant** constant, | 3554 HConstant** constant, |
| 3534 HValue* original_value, | 3555 HValue* original_value, |
| 3535 Representation representation, | 3556 Representation representation, |
| 3536 int32_t new_offset) { | 3557 int32_t new_offset) { |
| 3558 HValue* index_context = IndexContext(*add, check); |
| 3559 if (index_context == NULL) return false; |
| 3560 |
| 3537 HConstant* new_constant = new(BasicBlock()->zone()) | 3561 HConstant* new_constant = new(BasicBlock()->zone()) |
| 3538 HConstant(new_offset, Representation::Integer32()); | 3562 HConstant(new_offset, Representation::Integer32()); |
| 3539 if (*add == NULL) { | 3563 if (*add == NULL) { |
| 3540 new_constant->InsertBefore(check); | 3564 new_constant->InsertBefore(check); |
| 3541 // Because of the bounds checks elimination algorithm, the index is always | 3565 *add = new(BasicBlock()->zone()) HAdd(index_context, |
| 3542 // an HAdd or an HSub here, so we can safely cast to an HBinaryOperation. | |
| 3543 HValue* context = HBinaryOperation::cast(check->index())->context(); | |
| 3544 *add = new(BasicBlock()->zone()) HAdd(context, | |
| 3545 original_value, | 3566 original_value, |
| 3546 new_constant); | 3567 new_constant); |
| 3547 (*add)->AssumeRepresentation(representation); | 3568 (*add)->AssumeRepresentation(representation); |
| 3548 (*add)->InsertBefore(check); | 3569 (*add)->InsertBefore(check); |
| 3549 } else { | 3570 } else { |
| 3550 new_constant->InsertBefore(*add); | 3571 new_constant->InsertBefore(*add); |
| 3551 (*constant)->DeleteAndReplaceWith(new_constant); | 3572 (*constant)->DeleteAndReplaceWith(new_constant); |
| 3552 } | 3573 } |
| 3553 *constant = new_constant; | 3574 *constant = new_constant; |
| 3575 return true; |
| 3554 } | 3576 } |
| 3555 | 3577 |
| 3556 void RemoveZeroAdd(HAdd** add, HConstant** constant) { | 3578 void RemoveZeroAdd(HAdd** add, HConstant** constant) { |
| 3557 if (*add != NULL && (*constant)->Integer32Value() == 0) { | 3579 if (*add != NULL && (*constant)->Integer32Value() == 0) { |
| 3558 (*add)->DeleteAndReplaceWith((*add)->left()); | 3580 (*add)->DeleteAndReplaceWith((*add)->left()); |
| 3559 (*constant)->DeleteAndReplaceWith(NULL); | 3581 (*constant)->DeleteAndReplaceWith(NULL); |
| 3560 } | 3582 } |
| 3561 } | 3583 } |
| 3562 }; | 3584 }; |
| 3563 | 3585 |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 3618 offset, | 3640 offset, |
| 3619 offset, | 3641 offset, |
| 3620 bb, | 3642 bb, |
| 3621 check, | 3643 check, |
| 3622 check, | 3644 check, |
| 3623 bb_data_list, | 3645 bb_data_list, |
| 3624 NULL); | 3646 NULL); |
| 3625 *data_p = bb_data_list; | 3647 *data_p = bb_data_list; |
| 3626 } else if (data->OffsetIsCovered(offset)) { | 3648 } else if (data->OffsetIsCovered(offset)) { |
| 3627 check->DeleteAndReplaceWith(NULL); | 3649 check->DeleteAndReplaceWith(NULL); |
| 3628 } else if (data->BasicBlock() == bb) { | 3650 } else if (data->BasicBlock() != bb || |
| 3629 data->CoverCheck(check, offset); | 3651 !data->CoverCheck(check, offset)) { |
| 3630 } else { | 3652 // If the check is in the current BB we try to modify it by calling |
| 3653 // "CoverCheck", but if also that fails we record the current offsets |
| 3654 // in a new data instance because from now on they are covered. |
| 3631 int32_t new_lower_offset = offset < data->LowerOffset() | 3655 int32_t new_lower_offset = offset < data->LowerOffset() |
| 3632 ? offset | 3656 ? offset |
| 3633 : data->LowerOffset(); | 3657 : data->LowerOffset(); |
| 3634 int32_t new_upper_offset = offset > data->UpperOffset() | 3658 int32_t new_upper_offset = offset > data->UpperOffset() |
| 3635 ? offset | 3659 ? offset |
| 3636 : data->UpperOffset(); | 3660 : data->UpperOffset(); |
| 3637 bb_data_list = new(zone()) BoundsCheckBbData(key, | 3661 bb_data_list = new(zone()) BoundsCheckBbData(key, |
| 3638 new_lower_offset, | 3662 new_lower_offset, |
| 3639 new_upper_offset, | 3663 new_upper_offset, |
| 3640 bb, | 3664 bb, |
| (...skipping 6451 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 10092 } | 10116 } |
| 10093 } | 10117 } |
| 10094 | 10118 |
| 10095 #ifdef DEBUG | 10119 #ifdef DEBUG |
| 10096 if (graph_ != NULL) graph_->Verify(false); // No full verify. | 10120 if (graph_ != NULL) graph_->Verify(false); // No full verify. |
| 10097 if (allocator_ != NULL) allocator_->Verify(); | 10121 if (allocator_ != NULL) allocator_->Verify(); |
| 10098 #endif | 10122 #endif |
| 10099 } | 10123 } |
| 10100 | 10124 |
| 10101 } } // namespace v8::internal | 10125 } } // namespace v8::internal |
| OLD | NEW |