[INFER] Don't hoist accesses that could underflow the array, bug 649775.

This commit is contained in:
Brian Hackett 2011-04-13 15:18:15 -07:00
parent 42fa6e5949
commit 0ae73e12fa
3 changed files with 49 additions and 0 deletions

View File

@ -0,0 +1,17 @@
var x = [, ];
var n = [, ];
var np = 18229;
sa = Array;
function copy_(x, y) {
var i;
var k = x < y ? x.length : y.length;
for (i = 0; i < k; i--) {
x[i];
if (i == -100)
return;
}
}
function mont_(x, y, n, np) {
copy_(x, sa);
}
mont_(x, x, n, np);

View File

@ -494,6 +494,24 @@ struct LifetimeVariable
return uint32(-1);
}
/* Return true if the variable cannot decrease during the body of a loop. */
bool nonDecreasing(JSScript *script, LifetimeLoop *loop) {
Lifetime *segment = lifetime ? lifetime : saved;
while (segment && segment->start <= loop->backedge) {
if (segment->start >= loop->head && segment->write) {
switch (JSOp(script->code[segment->start])) {
case JSOP_INCLOCAL:
case JSOP_LOCALINC:
break;
default:
return false;
}
}
segment = segment->next;
}
return true;
}
/*
* If the variable is only written once in the body of a loop, offset of
* that write. -1 otherwise.
@ -562,6 +580,11 @@ class LifetimeScript
return lifetimes[slot].firstWrite(loop);
}
bool nonDecreasing(uint32 slot, LifetimeLoop *loop) {
JS_ASSERT(slot < nLifetimes);
return lifetimes[slot].nonDecreasing(script, loop);
}
uint32 onlyWrite(uint32 slot, LifetimeLoop *loop) {
JS_ASSERT(slot < nLifetimes);
return lifetimes[slot].onlyWrite(loop);

View File

@ -393,6 +393,15 @@ LoopState::hoistArrayLengthCheck(const FrameEntry *obj, const FrameEntry *index)
uint32 rhs = lifetime->testRHS;
int32 constant = lifetime->testConstant;
/*
* If the LHS can decrease in the loop, it could become negative and
* underflow the array.
*/
if (!liveness->nonDecreasing(lifetime->testLHS, lifetime)) {
JaegerSpew(JSpew_Analysis, "Index may decrease in future iterations\n");
return false;
}
uint32 write = liveness->firstWrite(lifetime->testLHS, lifetime);
JS_ASSERT(write != LifetimeLoop::UNASSIGNED);
if (write < uint32(PC - script->code)) {