Bug 516062: detect overridden arguments.length on trace for JSOP_ARGCNT, r=dvander

This commit is contained in:
David Mandelin 2009-09-17 18:00:01 -07:00
parent 836a74cc80
commit 38779e6762
2 changed files with 35 additions and 4 deletions

View File

@ -12704,11 +12704,28 @@ TraceRecorder::record_JSOP_ARGSUB()
JS_REQUIRES_STACK JSRecordingStatus JS_REQUIRES_STACK JSRecordingStatus
TraceRecorder::record_JSOP_ARGCNT() TraceRecorder::record_JSOP_ARGCNT()
{ {
if (!(cx->fp->fun->flags & JSFUN_HEAVYWEIGHT)) { if (cx->fp->fun->flags & JSFUN_HEAVYWEIGHT)
stack(0, lir->insImmf(cx->fp->argc)); ABORT_TRACE("can't trace heavyweight JSOP_ARGCNT");
return JSRS_CONTINUE;
// argc is fixed on trace, so ideally we would simply generate LIR for
// constant argc. But the user can mutate arguments.length in the
// interpreter, so we have to check for that in the trace entry frame.
LIns *a_ins = get(&cx->fp->argsobj);
if (callDepth == 0) {
LIns *br = lir->insBranch(LIR_jt, lir->ins_peq0(a_ins), NULL);
// The following implements IsOverriddenArgsLength on trace.
// The '2' bit is set set if length was overridden.
const uint32 JSSLOT_ARGS_LENGTH = JSSLOT_PRIVATE + 1;
LIns *len_ins = stobj_get_fslot(a_ins, JSSLOT_ARGS_LENGTH);
LIns *ovr_ins = lir->ins2(LIR_piand, len_ins, INS_CONSTWORD(2));
guard(true, lir->ins_peq0(ovr_ins), snapshot(BRANCH_EXIT));
LIns *label = lir->ins0(LIR_label);
br->setTarget(label);
} }
ABORT_TRACE("can't trace heavyweight JSOP_ARGCNT"); stack(0, lir->insImmf(cx->fp->argc));
return JSRS_CONTINUE;
} }
JS_REQUIRES_STACK JSRecordingStatus JS_REQUIRES_STACK JSRecordingStatus

View File

@ -0,0 +1,14 @@
var count = 0;
function f() {
arguments.length--;
for (var i = 0; i < arguments.length; ++i) {
++count;
}
}
f(1, 2);
f(1, 2);
f(2, 2);
assertEq(count, 3);