Fix for when array bounds check elimination tries to modify a phi index.
BUG= Review URL: https://chromiumcodereview.appspot.com/11486007 git-svn-id: http://v8.googlecode.com/svn/branches/bleeding_edge@13193 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
ca3ea142be
commit
ae54f9cfe0
@ -3446,7 +3446,10 @@ class BoundsCheckBbData: public ZoneObject {
|
||||
// (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,
|
||||
//
|
||||
// If the check cannot be modified because the context is unknown it
|
||||
// returns false, otherwise it returns true.
|
||||
bool CoverCheck(HBoundsCheck* new_check,
|
||||
int32_t new_offset) {
|
||||
ASSERT(new_check->index()->representation().IsInteger32());
|
||||
bool keep_new_check = false;
|
||||
@ -3457,12 +3460,13 @@ class BoundsCheckBbData: public ZoneObject {
|
||||
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);
|
||||
bool result = BuildOffsetAdd(upper_check_,
|
||||
&added_upper_index_,
|
||||
&added_upper_offset_,
|
||||
Key()->IndexBase(),
|
||||
new_check->index()->representation(),
|
||||
new_offset);
|
||||
if (!result) return false;
|
||||
upper_check_->SetOperandAt(0, added_upper_index_);
|
||||
}
|
||||
} else if (new_offset < lower_offset_) {
|
||||
@ -3471,12 +3475,13 @@ class BoundsCheckBbData: public ZoneObject {
|
||||
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);
|
||||
bool result = BuildOffsetAdd(lower_check_,
|
||||
&added_lower_index_,
|
||||
&added_lower_offset_,
|
||||
Key()->IndexBase(),
|
||||
new_check->index()->representation(),
|
||||
new_offset);
|
||||
if (!result) return false;
|
||||
lower_check_->SetOperandAt(0, added_lower_index_);
|
||||
}
|
||||
} else {
|
||||
@ -3486,6 +3491,8 @@ class BoundsCheckBbData: public ZoneObject {
|
||||
if (!keep_new_check) {
|
||||
new_check->DeleteAndReplaceWith(NULL);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void RemoveZeroOperations() {
|
||||
@ -3528,20 +3535,34 @@ class BoundsCheckBbData: public ZoneObject {
|
||||
BoundsCheckBbData* next_in_bb_;
|
||||
BoundsCheckBbData* father_in_dt_;
|
||||
|
||||
void BuildOffsetAdd(HBoundsCheck* check,
|
||||
// Given an existing add instruction and a bounds check it tries to
|
||||
// find the current context (either of the add or of the check index).
|
||||
HValue* IndexContext(HAdd* add, HBoundsCheck* check) {
|
||||
if (add != NULL) {
|
||||
return add->context();
|
||||
}
|
||||
if (check->index()->IsBinaryOperation()) {
|
||||
return HBinaryOperation::cast(check->index())->context();
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// This function returns false if it cannot build the add because the
|
||||
// current context cannot be determined.
|
||||
bool BuildOffsetAdd(HBoundsCheck* check,
|
||||
HAdd** add,
|
||||
HConstant** constant,
|
||||
HValue* original_value,
|
||||
Representation representation,
|
||||
int32_t new_offset) {
|
||||
HValue* index_context = IndexContext(*add, check);
|
||||
if (index_context == NULL) return false;
|
||||
|
||||
HConstant* new_constant = new(BasicBlock()->zone())
|
||||
HConstant(new_offset, Representation::Integer32());
|
||||
if (*add == NULL) {
|
||||
new_constant->InsertBefore(check);
|
||||
// Because of the bounds checks elimination algorithm, the index is always
|
||||
// an HAdd or an HSub here, so we can safely cast to an HBinaryOperation.
|
||||
HValue* context = HBinaryOperation::cast(check->index())->context();
|
||||
*add = new(BasicBlock()->zone()) HAdd(context,
|
||||
*add = new(BasicBlock()->zone()) HAdd(index_context,
|
||||
original_value,
|
||||
new_constant);
|
||||
(*add)->AssumeRepresentation(representation);
|
||||
@ -3551,6 +3572,7 @@ class BoundsCheckBbData: public ZoneObject {
|
||||
(*constant)->DeleteAndReplaceWith(new_constant);
|
||||
}
|
||||
*constant = new_constant;
|
||||
return true;
|
||||
}
|
||||
|
||||
void RemoveZeroAdd(HAdd** add, HConstant** constant) {
|
||||
@ -3625,9 +3647,11 @@ void HGraph::EliminateRedundantBoundsChecks(HBasicBlock* bb,
|
||||
*data_p = bb_data_list;
|
||||
} else if (data->OffsetIsCovered(offset)) {
|
||||
check->DeleteAndReplaceWith(NULL);
|
||||
} else if (data->BasicBlock() == bb) {
|
||||
data->CoverCheck(check, offset);
|
||||
} else {
|
||||
} else if (data->BasicBlock() != bb ||
|
||||
!data->CoverCheck(check, offset)) {
|
||||
// If the check is in the current BB we try to modify it by calling
|
||||
// "CoverCheck", but if also that fails we record the current offsets
|
||||
// in a new data instance because from now on they are covered.
|
||||
int32_t new_lower_offset = offset < data->LowerOffset()
|
||||
? offset
|
||||
: data->LowerOffset();
|
||||
|
@ -178,5 +178,29 @@ short_test(a, 0);
|
||||
assertTrue(%GetOptimizationStatus(short_test) != 1);
|
||||
|
||||
|
||||
// A test for when we would modify a phi index.
|
||||
var data_phi = [0, 1, 2, 3, 4, 5, 6, 7, 8];
|
||||
function test_phi(a, base, check) {
|
||||
var index;
|
||||
if (check) {
|
||||
index = base + 1;
|
||||
} else {
|
||||
index = base + 2;
|
||||
}
|
||||
var result = a[index];
|
||||
result += a[index + 1];
|
||||
result += a[index - 1];
|
||||
return result;
|
||||
}
|
||||
var result_phi = 0;
|
||||
result_phi = test_phi(data_phi, 3, true);
|
||||
assertEquals(12, result_phi);
|
||||
result_phi = test_phi(data_phi, 3, true);
|
||||
assertEquals(12, result_phi);
|
||||
%OptimizeFunctionOnNextCall(test_phi);
|
||||
result_phi = test_phi(data_phi, 3, true);
|
||||
assertEquals(12, result_phi);
|
||||
|
||||
|
||||
gc();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user