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 703efdec92
commit 6ffc6f7672
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 */
}
bool
JSCompartment::isDiscardingJitCode(JSTracer *trc)
{
if (!IS_GC_MARKING_TRACER(trc))
return false;
return !gcPreserveCode;
}
void
JSCompartment::sweep(FreeOp *fop, bool releaseTypes)
{

View File

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

View File

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