Bug 723773 - Liveness analysis makes mistakes when analyzing try/catch (r=bhackett)

This commit is contained in:
Bill McCloskey 2012-02-10 18:32:03 -08:00
parent 2817419f26
commit 48692f96aa

View File

@ -940,12 +940,15 @@ ScriptAnalysis::killVariable(JSContext *cx, LifetimeVariable &var, unsigned offs
/* /*
* The variable is live even before the write, due to an enclosing try * The variable is live even before the write, due to an enclosing try
* block. We need to split the lifetime to indicate there was a write. * block. We need to split the lifetime to indicate there was a write.
* We set the new interval's savedEnd to 0, since it will always be
* adjacent to the old interval, so it never needs to be extended.
*/ */
var.lifetime = cx->typeLifoAlloc().new_<Lifetime>(start, offset, var.lifetime); var.lifetime = cx->typeLifoAlloc().new_<Lifetime>(start, 0, var.lifetime);
if (!var.lifetime) { if (!var.lifetime) {
setOOM(cx); setOOM(cx);
return; return;
} }
var.lifetime->end = offset;
} else { } else {
var.saved = var.lifetime; var.saved = var.lifetime;
var.savedEnd = 0; var.savedEnd = 0;
@ -973,25 +976,43 @@ ScriptAnalysis::extendVariable(JSContext *cx, LifetimeVariable &var,
var.lifetime->start = start; var.lifetime->start = start;
/* /*
* When walking backwards through loop bodies, we don't know which vars * Consider this code:
* are live at the loop's backedge. We save the endpoints for lifetime
* segments which we *would* use if the variables were live at the backedge
* and extend the variable with new lifetimes if we find the variable is
* indeed live at the head of the loop.
* *
* while (...) { * while (...) { (#1)
* if (x #1) { ... } * use x; (#2)
* ... * ...
* if (... #2) { x = 0; #3} * x = ...; (#3)
* } * ...
* } (#4)
* *
* If x is not live after the loop, we treat it as dead in the walk and * Just before analyzing the while statement, there would be a live range
* make a point lifetime for the write at #3. At the beginning of that * from #1..#2 and a "point range" at #3. The job of extendVariable is to
* basic block (#2), we save the loop endpoint; if we knew x was live in * create a new live range from #3..#4.
* the next iteration then a new lifetime would be made here. At #1 we *
* mark x live again, make a segment between the head of the loop and #1, * However, more extensions may be required if the definition of x is
* and then extend x with loop tail lifetimes from #1 to #2, and from #3 * conditional. Consider the following.
* to the back edge. *
* while (...) { (#1)
* use x; (#2)
* ...
* if (...) (#5)
* x = ...; (#3)
* ...
* } (#4)
*
* Assume that x is not used after the loop. Then, before extendVariable is
* run, the live ranges would be the same as before (#1..#2 and #3..#3). We
* still need to create a range from #3..#4. But, since the assignment at #3
* may never run, we also need to create a range from #2..#3. This is done
* as follows.
*
* Each time we create a Lifetime, we store the start of the most recently
* seen sequence of conditional code in the Lifetime's savedEnd field. So,
* when creating the Lifetime at #2, we set the Lifetime's savedEnd to
* #5. (The start of the most recent conditional is cached in each
* variable's savedEnd field.) Consequently, extendVariable is able to
* create a new interval from #2..#5 using the savedEnd field of the
* existing #1..#2 interval.
*/ */
Lifetime *segment = var.lifetime; Lifetime *segment = var.lifetime;