1. Fix json2.js (it crashes later, another bug) to restore a non-empty stack for a call with missing args after a nested bail-out. This involves changing js_SynthesizeFrame to return the number of stack slots it reconstructed that map to native slots. It also means not counting the missing args in the spdist uint16 pushed onto the state.rp stack (this was the root of all over-counting evil, for this bug).

2. Use if (C) { do {...} while (C); } instead of if (C) { while (C) {...} } and other style fixage.
This commit is contained in:
Brendan Eich 2008-08-18 18:36:05 -07:00
parent eee1b1202a
commit 2ac6880199

View File

@ -1243,9 +1243,9 @@ TraceRecorder::snapshot(ExitType exitType)
JSStackFrame* fp = cx->fp;
if (exitType == BRANCH_EXIT && js_IsLoopExit(cx, fp->script, fp->regs->pc))
exitType = LOOP_EXIT;
/* generate the entry map and stash it in the trace */
/* Generate the entry map and stash it in the trace. */
unsigned stackSlots = nativeStackSlots(cx, callDepth);
/* its sufficient to track the native stack use here since all stores above the
/* It's sufficient to track the native stack use here since all stores above the
stack watermark defined by guards are killed. */
trackNativeStackUse(stackSlots + 1);
/* reserve space for the type map */
@ -1259,7 +1259,7 @@ TraceRecorder::snapshot(ExitType exitType)
exit.numStackSlots = stackSlots;
exit.exitType = exitType;
exit.ip_adj = fp->regs->pc - (jsbytecode*)fragment->root->ip;
exit.sp_adj = (stackSlots*sizeof(double)) - treeInfo->nativeStackBase;
exit.sp_adj = (stackSlots * sizeof(double)) - treeInfo->nativeStackBase;
exit.rp_adj = exit.calldepth * sizeof(FrameInfo);
uint8* m = exit.typeMap = (uint8 *)data->payload();
/* Determine the type of a store by looking at the current type of the actual value the
@ -1436,7 +1436,7 @@ TraceRecorder::emitTreeCall(Fragment* inner, GuardRecord* lr)
/* Guard that we have enough stack space for the tree we are trying to call on top
of the new value for sp. */
debug_only(printf("sp_adj=%d outer=%d inner=%d\n",
sp_adj, treeInfo->nativeStackBase, ti->nativeStackBase));
sp_adj, treeInfo->nativeStackBase, ti->nativeStackBase));
LIns* sp_top = lir->ins2i(LIR_add, lirbuf->sp,
- treeInfo->nativeStackBase /* rebase sp to beginning of outer tree's stack */
+ sp_adj /* adjust for stack in outer frame inner tree can't see */
@ -1587,7 +1587,7 @@ js_TrashTree(JSContext* cx, Fragment* f)
f->releaseCode(fragmento);
}
static JSInlineFrame*
static unsigned
js_SynthesizeFrame(JSContext* cx, const FrameInfo& fi)
{
JS_ASSERT(HAS_FUNCTION_CLASS(fi.callee));
@ -1601,9 +1601,7 @@ js_SynthesizeFrame(JSContext* cx, const FrameInfo& fi)
// Assert that we have a correct sp distance from cx->fp->slots in fi.
JS_ASSERT(js_ReconstructStackDepth(cx, cx->fp->script, fi.callpc) ==
uintN(fi.s.spdist -
((fun->nargs > fi.s.argc) ? fun->nargs - fi.s.argc : 0) -
cx->fp->script->nfixed));
uintN(fi.s.spdist - cx->fp->script->nfixed));
uintN nframeslots = JS_HOWMANY(sizeof(JSInlineFrame), sizeof(jsval));
size_t nbytes = (nframeslots + script->nslots) * sizeof(jsval);
@ -1617,7 +1615,7 @@ js_SynthesizeFrame(JSContext* cx, const FrameInfo& fi)
JS_ARENA_ALLOCATE_CAST(newsp, jsval *, &cx->stackPool, nbytes);
if (!newsp) {
js_ReportOutOfScriptQuota(cx);
return NULL;
return 0;
}
}
@ -1661,7 +1659,13 @@ js_SynthesizeFrame(JSContext* cx, const FrameInfo& fi)
cx->fp->regs = &newifp->callerRegs;
cx->fp = &newifp->frame;
return newifp;
// FIXME: we must count stack slots from caller's operand stack up to (but not including)
// callee's, including missing arguments. Could we shift everything down to the caller's
// fp->slots (where vars start) and avoid some of the complexity?
return (fi.s.spdist - cx->fp->down->script->nfixed) +
((fun->nargs > cx->fp->argc) ? fun->nargs - cx->fp->argc : 0) +
script->nfixed;
}
bool
@ -1886,7 +1890,7 @@ js_ExecuteTree(JSContext* cx, Fragment** treep, uintN& inlineCallCount)
if (lr->exit->exitType == NESTED_EXIT) {
/* Unwind all frames held by nested outer trees (since the innermost tree's frame which
we restore below doesn't contain such frames. */
while (lr->exit->exitType == NESTED_EXIT) {
do {
debug_only(printf("processing tree call guard %p, calldepth=%d\n", lr, lr->calldepth);)
unsigned calldepth = lr->calldepth;
if (calldepth > 0) {
@ -1904,10 +1908,12 @@ js_ExecuteTree(JSContext* cx, Fragment** treep, uintN& inlineCallCount)
}
JS_ASSERT(lr->guard->oprnd1()->oprnd2()->isconstp());
lr = (GuardRecord*)lr->guard->oprnd1()->oprnd2()->constvalp();
}
} while (lr->exit->exitType == NESTED_EXIT);
/* We restored the nested frames, now we just need to deal with the innermost guard. */
lr = state.nestedExit;
}
/* At this point we have processed any outer frames around the innermost guard so
rp and callstack should match. */
JS_ASSERT(state.rp == callstack);
@ -1919,21 +1925,20 @@ js_ExecuteTree(JSContext* cx, Fragment** treep, uintN& inlineCallCount)
/* We already synthesized the frames around the innermost guard. Here we just deal
with additional frames inside the tree we are bailing out from. */
unsigned calldepth = lr->calldepth;
unsigned calldepth_slots = 0;
for (unsigned n = 0; n < calldepth; ++n)
js_SynthesizeFrame(cx, callstack[n]);
calldepth_slots += js_SynthesizeFrame(cx, callstack[n]);
/* Adjust sp and pc relative to the tree we exited from (not the tree we entered
into). These are our final values for sp and pc since js_SynthesizeFrame has
already taken care of all frames in between. */
SideExit* e = lr->exit;
JSStackFrame* fp = cx->fp;
/* If we are not exiting from an inlined frame the state->sp is spbase, otherwise spbase
is whatever slots frames around us consume. */
fp->regs->pc = (jsbytecode*)lr->from->root->ip + e->ip_adj;
fp->regs->sp = StackBase(fp) +
((calldepth == 0)
? (e->sp_adj/sizeof(double))
: js_ReconstructStackDepth(cx, fp->script, fp->regs->pc));
fp->regs->sp = StackBase(fp) + (e->sp_adj / sizeof(double)) - calldepth_slots;
#if defined(DEBUG) && defined(NANOJIT_IA32)
printf("leaving trace at %s:%u@%u, exitType=%d, sp=%d, ip=%p, cycles=%llu\n",
@ -3591,7 +3596,7 @@ TraceRecorder::interpretedFunctionCall(jsval& fval, JSFunction* fun, uintN argc)
FrameInfo fi = {
JSVAL_TO_OBJECT(fval),
fp->regs->pc,
fp->regs->sp + (fun->nargs - argc) - fp->slots,
fp->regs->sp - fp->slots,
argc
};
@ -3667,7 +3672,6 @@ TraceRecorder::record_JSOP_CALL()
if (FUN_INTERPRETED(fun))
return interpretedFunctionCall(fval, fun, argc);
// XXXbe need to guard this condition
if (FUN_SLOW_NATIVE(fun))
ABORT_TRACE("slow native");