Bug 781393 - JS VM stack values shouldn't always be clobbered during marking (r=bhackett)

This commit is contained in:
Bill McCloskey 2012-08-15 10:33:12 -07:00
parent 2e2b4aca5e
commit ba92c54858
4 changed files with 54 additions and 25 deletions

View File

@ -0,0 +1,14 @@
gczeal(4,1);
function check(o)
{
print(o);
assertEq(o.b, 3);
}
function f()
{
for (var i=0; i<3; i++) {
var o = {b: 3};
check(o);
}
}
f();

View File

@ -486,6 +486,15 @@ JSCompartment::discardJitCode(FreeOp *fop)
#endif /* JS_METHODJIT */ #endif /* JS_METHODJIT */
} }
bool
JSCompartment::isDiscardingJitCode(JSTracer *trc)
{
if (!IS_GC_MARKING_TRACER(trc))
return false;
return !gcPreserveCode;
}
void void
JSCompartment::sweep(FreeOp *fop, bool releaseTypes) JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
{ {

View File

@ -325,6 +325,7 @@ struct JSCompartment
void markTypes(JSTracer *trc); void markTypes(JSTracer *trc);
void discardJitCode(js::FreeOp *fop); void discardJitCode(js::FreeOp *fop);
bool isDiscardingJitCode(JSTracer *trc);
void sweep(js::FreeOp *fop, bool releaseTypes); void sweep(js::FreeOp *fop, bool releaseTypes);
void sweepCrossCompartmentWrappers(); void sweepCrossCompartmentWrappers();
void purge(); void purge();

View File

@ -648,21 +648,25 @@ StackSpace::markFrameValues(JSTracer *trc, StackFrame *fp, Value *slotsEnd, jsby
for (Value *vp = slotsBegin; vp < fixedEnd; vp++) { for (Value *vp = slotsBegin; vp < fixedEnd; vp++) {
uint32_t slot = analyze::LocalSlot(script, vp - slotsBegin); uint32_t slot = analyze::LocalSlot(script, vp - slotsBegin);
/* /* Will this slot be synced by the JIT? */
* Will this slot be synced by the JIT? If not, replace with a dummy
* value with the same type tag.
*/
if (!analysis->trackSlot(slot) || analysis->liveness(slot).live(offset)) { if (!analysis->trackSlot(slot) || analysis->liveness(slot).live(offset)) {
gc::MarkValueRoot(trc, vp, "vm_stack"); gc::MarkValueRoot(trc, vp, "vm_stack");
} else if (vp->isDouble()) { } else if (script->compartment()->isDiscardingJitCode(trc)) {
/*
* If we're throwing away analysis information, we need to replace
* non-live Values with ones that can safely be marked in later
* collections.
*/
if (vp->isDouble()) {
*vp = DoubleValue(0.0); *vp = DoubleValue(0.0);
} else { } else {
/* /*
* It's possible that *vp may not be a valid Value. For example, it * It's possible that *vp may not be a valid Value. For example,
* may be tagged as a NullValue but the low bits may be nonzero so * it may be tagged as a NullValue but the low bits may be
* that isNull() returns false. This can cause problems later on * nonzero so that isNull() returns false. This can cause
* when marking the value. Extracting the type in this way and then * problems later on when marking the value. Extracting the type
* overwriting the value circumvents the problem. * in this way and then overwriting the value circumvents the
* problem.
*/ */
JSValueType type = vp->extractNonDoubleType(); JSValueType type = vp->extractNonDoubleType();
if (type == JSVAL_TYPE_INT32) if (type == JSVAL_TYPE_INT32)
@ -679,6 +683,7 @@ StackSpace::markFrameValues(JSTracer *trc, StackFrame *fp, Value *slotsEnd, jsby
*vp = ObjectValue(fp->scopeChain()->global()); *vp = ObjectValue(fp->scopeChain()->global());
} }
} }
}
gc::MarkValueRootRange(trc, fixedEnd, slotsEnd, "vm_stack"); gc::MarkValueRootRange(trc, fixedEnd, slotsEnd, "vm_stack");
} }