Index: src/hydrogen.cc |
diff --git a/src/hydrogen.cc b/src/hydrogen.cc |
index 539b48aafcf79caf13af88043bfd82f1947b1431..3ce76c1ef19a2a2be7b70dac589a5ee5761a9fea 100644 |
--- a/src/hydrogen.cc |
+++ b/src/hydrogen.cc |
@@ -3266,7 +3266,8 @@ class BoundsCheckBbData: public ZoneObject { |
int32_t LowerOffset() const { return lower_offset_; } |
int32_t UpperOffset() const { return upper_offset_; } |
HBasicBlock* BasicBlock() const { return basic_block_; } |
- HBoundsCheck* Check() const { return check_; } |
+ HBoundsCheck* LowerCheck() const { return lower_check_; } |
+ HBoundsCheck* UpperCheck() const { return upper_check_; } |
BoundsCheckBbData* NextInBasicBlock() const { return next_in_bb_; } |
BoundsCheckBbData* FatherInDominatorTree() const { return father_in_dt_; } |
@@ -3274,76 +3275,85 @@ class BoundsCheckBbData: public ZoneObject { |
return offset >= LowerOffset() && offset <= UpperOffset(); |
} |
- // This method removes new_check and modifies the current check so that it |
- // also "covers" what new_check covered. |
- // The obvious precondition is that new_check follows Check() in the |
- // same basic block, and that new_offset is not covered (otherwise we |
- // could simply remove new_check). |
- // As a consequence LowerOffset() or UpperOffset() change (the covered |
+ bool HasSingleCheck() { return lower_check_ == upper_check_; } |
+ |
+ // The goal of this method is to modify either upper_offset_ or |
+ // lower_offset_ so that also new_offset is covered (the covered |
// range grows). |
// |
- // In the general case the check covering the current range should be like |
- // these two checks: |
- // 0 <= Key()->IndexBase() + LowerOffset() |
- // Key()->IndexBase() + UpperOffset() < Key()->Length() |
- // |
- // We can transform the second check like this: |
- // Key()->IndexBase() + LowerOffset() < |
- // Key()->Length() + (LowerOffset() - UpperOffset()) |
- // so we can handle both checks with a single unsigned comparison. |
+ // The precondition is that new_check follows UpperCheck() and |
+ // LowerCheck() in the same basic block, and that new_offset is not |
+ // covered (otherwise we could simply remove new_check). |
// |
- // The bulk of this method changes Check()->index() and Check()->length() |
- // replacing them with new HAdd instructions to perform the transformation |
- // described above. |
+ // If HasSingleCheck() is true then new_check is added as "second check" |
+ // (either upper or lower; note that HasSingleCheck() becomes false). |
+ // Otherwise one of the current checks is modified so that it also covers |
+ // new_offset, and new_check is removed. |
void CoverCheck(HBoundsCheck* new_check, |
int32_t new_offset) { |
ASSERT(new_check->index()->representation().IsInteger32()); |
+ bool keep_new_check = false; |
if (new_offset > upper_offset_) { |
upper_offset_ = new_offset; |
+ if (HasSingleCheck()) { |
+ keep_new_check = true; |
+ upper_check_ = new_check; |
+ } else { |
+ BuildOffsetAdd(upper_check_, |
+ &added_upper_index_, |
+ &added_upper_offset_, |
+ Key()->IndexBase(), |
+ new_check->index()->representation(), |
+ new_offset); |
+ upper_check_->SetOperandAt(0, added_upper_index_); |
+ } |
} else if (new_offset < lower_offset_) { |
lower_offset_ = new_offset; |
+ if (HasSingleCheck()) { |
+ keep_new_check = true; |
+ lower_check_ = new_check; |
+ } else { |
+ BuildOffsetAdd(lower_check_, |
+ &added_lower_index_, |
+ &added_lower_offset_, |
+ Key()->IndexBase(), |
+ new_check->index()->representation(), |
+ new_offset); |
+ lower_check_->SetOperandAt(0, added_lower_index_); |
+ } |
} else { |
ASSERT(false); |
} |
- BuildOffsetAdd(&added_index_, |
- &added_index_offset_, |
- Key()->IndexBase(), |
- new_check->index()->representation(), |
- lower_offset_); |
- Check()->SetOperandAt(0, added_index_); |
- BuildOffsetAdd(&added_length_, |
- &added_length_offset_, |
- Key()->Length(), |
- new_check->length()->representation(), |
- lower_offset_ - upper_offset_); |
- Check()->SetOperandAt(1, added_length_); |
- |
- new_check->DeleteAndReplaceWith(NULL); |
+ if (!keep_new_check) { |
+ new_check->DeleteAndReplaceWith(NULL); |
+ } |
} |
void RemoveZeroOperations() { |
- RemoveZeroAdd(&added_index_, &added_index_offset_); |
- RemoveZeroAdd(&added_length_, &added_length_offset_); |
+ RemoveZeroAdd(&added_lower_index_, &added_lower_offset_); |
+ RemoveZeroAdd(&added_upper_index_, &added_upper_offset_); |
} |
BoundsCheckBbData(BoundsCheckKey* key, |
int32_t lower_offset, |
int32_t upper_offset, |
HBasicBlock* bb, |
- HBoundsCheck* check, |
+ HBoundsCheck* lower_check, |
+ HBoundsCheck* upper_check, |
BoundsCheckBbData* next_in_bb, |
BoundsCheckBbData* father_in_dt) |
: key_(key), |
lower_offset_(lower_offset), |
upper_offset_(upper_offset), |
basic_block_(bb), |
- check_(check), |
- added_index_offset_(NULL), |
- added_index_(NULL), |
- added_length_offset_(NULL), |
- added_length_(NULL), |
+ lower_check_(lower_check), |
+ upper_check_(upper_check), |
+ added_lower_index_(NULL), |
+ added_lower_offset_(NULL), |
+ added_upper_index_(NULL), |
+ added_upper_offset_(NULL), |
next_in_bb_(next_in_bb), |
father_in_dt_(father_in_dt) { } |
@@ -3352,15 +3362,17 @@ class BoundsCheckBbData: public ZoneObject { |
int32_t lower_offset_; |
int32_t upper_offset_; |
HBasicBlock* basic_block_; |
- HBoundsCheck* check_; |
- HConstant* added_index_offset_; |
- HAdd* added_index_; |
- HConstant* added_length_offset_; |
- HAdd* added_length_; |
+ HBoundsCheck* lower_check_; |
+ HBoundsCheck* upper_check_; |
+ HAdd* added_lower_index_; |
+ HConstant* added_lower_offset_; |
+ HAdd* added_upper_index_; |
+ HConstant* added_upper_offset_; |
BoundsCheckBbData* next_in_bb_; |
BoundsCheckBbData* father_in_dt_; |
- void BuildOffsetAdd(HAdd** add, |
+ void BuildOffsetAdd(HBoundsCheck* check, |
+ HAdd** add, |
HConstant** constant, |
HValue* original_value, |
Representation representation, |
@@ -3369,12 +3381,12 @@ class BoundsCheckBbData: public ZoneObject { |
HConstant(Handle<Object>(Smi::FromInt(new_offset)), |
Representation::Integer32()); |
if (*add == NULL) { |
- new_constant->InsertBefore(Check()); |
+ new_constant->InsertBefore(check); |
*add = new(BasicBlock()->zone()) HAdd(NULL, |
original_value, |
new_constant); |
(*add)->AssumeRepresentation(representation); |
- (*add)->InsertBefore(Check()); |
+ (*add)->InsertBefore(check); |
} else { |
new_constant->InsertBefore(*add); |
(*constant)->DeleteAndReplaceWith(new_constant); |
@@ -3447,6 +3459,7 @@ void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb, |
offset, |
bb, |
check, |
+ check, |
bb_data_list, |
NULL); |
*data_p = bb_data_list; |
@@ -3465,7 +3478,8 @@ void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb, |
new_lower_offset, |
new_upper_offset, |
bb, |
- check, |
+ data->LowerCheck(), |
+ data->UpperCheck(), |
bb_data_list, |
data); |
table->Insert(key, bb_data_list, zone()); |