diff --git a/js/src/jsgc.c b/js/src/jsgc.c index 78a494cf07a..0b71dd57478 100644 --- a/js/src/jsgc.c +++ b/js/src/jsgc.c @@ -1944,6 +1944,7 @@ void js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp) { uintN depth, nslots, minargs; + jsval *vp; if (fp->callobj) JS_CALL_OBJECT_TRACER(trc, fp->callobj, "call"); @@ -1976,6 +1977,7 @@ js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp) JS_CALL_OBJECT_TRACER(trc, fp->callee, "callee"); if (fp->argv) { + /* Trace argv including callee and thisp slots. */ nslots = fp->argc; if (fp->fun) { minargs = FUN_MINARGS(fp->fun); @@ -1984,7 +1986,23 @@ js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp) if (!FUN_INTERPRETED(fp->fun)) nslots += fp->fun->u.n.extra; } - TRACE_JSVALS(trc, nslots + 2, fp->argv - 2, "arg"); + nslots += 2; + vp = fp->argv - 2; + if (fp->down && fp->down->spbase) { + /* + * Avoid unnecessary tracing in the common case when args overlaps + * with the stack segment of the previous frame. That segment is + * traced via the above spbase code and, when sp > spbase + depth, + * during tracing of the stack headers in js_TraceContext. + */ + if (JS_UPTRDIFF(vp, fp->down->spbase) < + JS_UPTRDIFF(fp->down->sp, fp->down->spbase)) { + JS_ASSERT((size_t)nslots >= (size_t)(fp->down->sp - vp)); + nslots -= (uintN)(fp->down->sp - vp); + vp = fp->down->sp; + } + } + TRACE_JSVALS(trc, nslots, vp, "arg"); } JS_CALL_VALUE_TRACER(trc, fp->rval, "rval"); if (fp->vars) diff --git a/js/src/jsiter.c b/js/src/jsiter.c index e4fa53943c3..b75b48a6722 100644 --- a/js/src/jsiter.c +++ b/js/src/jsiter.c @@ -679,8 +679,11 @@ generator_trace(JSTracer *trc, JSObject *obj) JSGenerator *gen; gen = (JSGenerator *) JS_GetPrivate(trc->context, obj); - if (gen) + if (gen) { + /* js_TraceStackFrame does not trace recursively the down chain. */ + JS_ASSERT(!gen->frame.down); js_TraceStackFrame(trc, &gen->frame); + } } JSClass js_GeneratorClass = {