bug=421274 r=brendan a1.9=mtschrep

eliminating SAVE_SP_AND_PC and friends from the interpreter loop
This commit is contained in:
igor%mir2.org 2008-03-13 05:52:54 +00:00
Родитель 278fc772e8
Коммит bf5c2d0a6f
17 изменённых файлов: 440 добавлений и 571 удалений

Просмотреть файл

@ -6189,8 +6189,8 @@ nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx,
// binding a name) a new undefined property that's not already
// defined on our prototype chain. This way we can access this
// expando w/o ever getting back into XPConnect.
if ((flags & (JSRESOLVE_ASSIGNING)) && (JSOp)*cx->fp->pc != JSOP_BINDNAME &&
win->IsInnerWindow()) {
if ((flags & (JSRESOLVE_ASSIGNING)) && cx->fp->regs &&
(JSOp)*cx->fp->regs->pc != JSOP_BINDNAME && win->IsInnerWindow()) {
JSObject *realObj;
wrapper->GetJSObject(&realObj);

Просмотреть файл

@ -2480,7 +2480,8 @@ EvalInContext(JSContext *cx, JSObject *obj, uintN argc, jsval *argv,
JS_ToggleOptions(scx, JSOPTION_DONT_REPORT_UNCAUGHT);
ok = JS_EvaluateUCScript(scx, sobj, src, srclen,
fp->script->filename,
JS_PCToLineNumber(cx, fp->script, fp->pc),
JS_PCToLineNumber(cx, fp->script,
fp->regs->pc),
rval);
if (!ok) {
if (JS_GetPendingException(scx, &v))

Просмотреть файл

@ -5118,13 +5118,12 @@ JS_FRIEND_API(JSBool)
JS_IsAssigning(JSContext *cx)
{
JSStackFrame *fp;
jsbytecode *pc;
for (fp = cx->fp; fp && !fp->script; fp = fp->down)
continue;
if (!fp || !(pc = fp->pc))
if (!fp || !fp->regs)
return JS_FALSE;
return (js_CodeSpec[*pc].format & JOF_ASSIGNING) != 0;
return (js_CodeSpec[*fp->regs->pc].format & JOF_ASSIGNING) != 0;
}
JS_PUBLIC_API(void)

Просмотреть файл

@ -890,9 +890,9 @@ js_ReportOutOfMemory(JSContext *cx)
* rather than a native frame.
*/
for (fp = cx->fp; fp; fp = fp->down) {
if (fp->script && fp->pc) {
if (fp->regs) {
report.filename = fp->script->filename;
report.lineno = js_PCToLineNumber(cx, fp->script, fp->pc);
report.lineno = js_PCToLineNumber(cx, fp->script, fp->regs->pc);
break;
}
}
@ -960,9 +960,9 @@ js_ReportErrorVA(JSContext *cx, uintN flags, const char *format, va_list ap)
/* Find the top-most active script frame, for best line number blame. */
for (fp = cx->fp; fp; fp = fp->down) {
if (fp->script && fp->pc) {
if (fp->regs) {
report.filename = fp->script->filename;
report.lineno = js_PCToLineNumber(cx, fp->script, fp->pc);
report.lineno = js_PCToLineNumber(cx, fp->script, fp->regs->pc);
break;
}
}
@ -1172,9 +1172,9 @@ js_ReportErrorNumberVA(JSContext *cx, uintN flags, JSErrorCallback callback,
* see if the next frame has a script/pc combo we can use.
*/
for (fp = cx->fp; fp; fp = fp->down) {
if (fp->script && fp->pc) {
if (fp->regs) {
report.filename = fp->script->filename;
report.lineno = js_PCToLineNumber(cx, fp->script, fp->pc);
report.lineno = js_PCToLineNumber(cx, fp->script, fp->regs->pc);
break;
}
}

Просмотреть файл

@ -558,6 +558,7 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
jsval smallv[5];
jsval *argv;
JSStackFrame frame;
JSFrameRegs regs;
closure = (JSObject *) wp->closure;
clasp = OBJ_GET_CLASS(cx, closure);
@ -600,10 +601,13 @@ js_watch_set(JSContext *cx, JSObject *obj, jsval id, jsval *vp)
memset(&frame, 0, sizeof(frame));
frame.script = script;
frame.regs = NULL;
if (script) {
JS_ASSERT(script->length >= JSOP_STOP_LENGTH);
frame.pc = script->code + script->length
- JSOP_STOP_LENGTH;
regs.pc = script->code + script->length
- JSOP_STOP_LENGTH;
regs.sp = NULL;
frame.regs = &regs;
}
frame.callee = closure;
frame.fun = fun;
@ -956,7 +960,7 @@ JS_GetFrameScript(JSContext *cx, JSStackFrame *fp)
JS_PUBLIC_API(jsbytecode *)
JS_GetFramePC(JSContext *cx, JSStackFrame *fp)
{
return fp->pc;
return fp->regs ? fp->regs->pc : NULL;
}
JS_PUBLIC_API(JSStackFrame *)

Просмотреть файл

@ -332,8 +332,8 @@ InitExnPrivate(JSContext *cx, JSObject *exnObject, JSString *message,
elem->filename = NULL;
if (fp->script) {
elem->filename = fp->script->filename;
if (fp->pc)
elem->ulineno = js_PCToLineNumber(cx, fp->script, fp->pc);
if (fp->regs)
elem->ulineno = js_PCToLineNumber(cx, fp->script, fp->regs->pc);
}
++elem;
}
@ -799,7 +799,9 @@ Exception(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
} else {
if (!fp)
fp = JS_GetScriptedCaller(cx, NULL);
lineno = (fp && fp->pc) ? js_PCToLineNumber(cx, fp->script, fp->pc) : 0;
lineno = (fp && fp->regs)
? js_PCToLineNumber(cx, fp->script, fp->regs->pc)
: 0;
}
return (OBJ_GET_CLASS(cx, obj) != &js_ErrorClass) ||

Просмотреть файл

@ -2201,7 +2201,7 @@ js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags)
uintN error;
const char *name, *source;
for (fp = cx->fp; fp && !fp->spbase; fp = fp->down)
for (fp = cx->fp; fp && !fp->regs; fp = fp->down)
continue;
name = NULL;
source = NULL;
@ -2218,8 +2218,9 @@ js_ReportIsNotFunction(JSContext *cx, jsval *vp, uintN flags)
}
js_ReportValueError3(cx, error,
(fp && fp->spbase <= vp && vp < fp->sp)
? vp - fp->sp
(fp && fp->regs &&
fp->spbase <= vp && vp < fp->regs->sp)
? vp - fp->regs->sp
: (flags & JSV2F_SEARCH_STACK)
? JSDVG_SEARCH_STACK
: JSDVG_IGNORE_STACK,

Просмотреть файл

@ -2660,9 +2660,11 @@ js_TraceStackFrame(JSTracer *trc, JSStackFrame *fp)
* Don't mark what has not been pushed yet, or what has been
* popped already.
*/
nslots = (uintN) (fp->sp - fp->spbase);
JS_ASSERT(nslots <= fp->script->depth);
TRACE_JSVALS(trc, nslots, fp->spbase, "operand");
if (fp->regs) {
nslots = (uintN) (fp->regs->sp - fp->spbase);
JS_ASSERT(nslots <= fp->script->depth);
TRACE_JSVALS(trc, nslots, fp->spbase, "operand");
}
}
/* Allow for primitive this parameter due to JSFUN_THISP_* flags. */

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -49,6 +49,11 @@
JS_BEGIN_EXTERN_C
typedef struct JSFrameRegs {
jsbytecode *pc; /* program counter */
jsval *sp; /* stack pointer */
} JSFrameRegs;
/*
* JS stack frame, may be allocated on the C stack by native callers. Always
* allocated on cx->stackPool for calls from the interpreter to an interpreted
@ -60,8 +65,7 @@ JS_BEGIN_EXTERN_C
* with well-known slots, if possible.
*/
struct JSStackFrame {
jsval *sp; /* stack pointer */
jsbytecode *pc; /* program counter */
JSFrameRegs *regs;
jsval *spbase; /* operand stack base */
JSObject *callobj; /* lazily created Call object */
JSObject *argsobj; /* lazily created arguments object */
@ -91,7 +95,7 @@ struct JSStackFrame {
typedef struct JSInlineFrame {
JSStackFrame frame; /* base struct */
jsval *rvp; /* ptr to caller's return value slot */
JSFrameRegs callerRegs; /* parent's frame registers */
void *mark; /* mark before inline frame */
void *hookData; /* debugger call hook data */
JSVersion callerVersion; /* dynamic version of calling script */

Просмотреть файл

@ -791,10 +791,12 @@ js_NewGenerator(JSContext *cx, JSStackFrame *fp)
gen->frame.down = NULL;
gen->frame.annotation = NULL;
gen->frame.scopeChain = fp->scopeChain;
gen->frame.pc = fp->pc;
/* Allocate generating pc and operand stack space. */
gen->frame.spbase = gen->frame.sp = newsp;
gen->frame.spbase = newsp;
JS_ASSERT(fp->spbase == fp->regs->sp);
gen->savedRegs.sp = newsp;
gen->savedRegs.pc = fp->regs->pc;
gen->frame.regs = &gen->savedRegs;
/* Copy remaining state (XXX sharp* and xml* should be local vars). */
gen->frame.sharpDepth = 0;
@ -853,7 +855,7 @@ SendToGenerator(JSContext *cx, JSGeneratorOp op, JSObject *obj,
* Store the argument to send as the result of the yield
* expression.
*/
gen->frame.sp[-1] = arg;
gen->savedRegs.sp[-1] = arg;
}
gen->state = JSGEN_RUNNING;
break;

Просмотреть файл

@ -97,6 +97,7 @@ struct JSGenerator {
JSObject *obj;
JSGeneratorState state;
JSStackFrame frame;
JSFrameRegs savedRegs;
JSArena arena;
jsval stack[1];
};

Просмотреть файл

@ -1146,7 +1146,8 @@ js_ComputeFilename(JSContext *cx, JSStackFrame *caller,
return principals->codebase;
}
*linenop = js_PCToLineNumber(cx, caller->script, caller->pc);
*linenop = js_PCToLineNumber(cx, caller->script,
caller->regs ? caller->regs->pc : NULL);
return caller->script->filename;
}
@ -1170,8 +1171,8 @@ obj_eval(JSContext *cx, JSObject *obj, uintN argc, jsval *argv, jsval *rval)
fp = cx->fp;
caller = JS_GetScriptedCaller(cx, fp);
JS_ASSERT(!caller || caller->pc);
indirectCall = (caller && *caller->pc != JSOP_EVAL);
JS_ASSERT(!caller || caller->regs);
indirectCall = (caller && *caller->regs->pc != JSOP_EVAL);
/*
* Ban all indirect uses of eval (global.foo = eval; global.foo(...)) and
@ -1959,7 +1960,7 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
/* Block and its locals must be on the current stack for GC safety. */
JS_ASSERT((size_t) OBJ_BLOCK_DEPTH(cx, obj) <=
(size_t) (fp->sp - fp->spbase));
(size_t) (fp->regs->sp - fp->spbase));
if (normalUnwind) {
depth = OBJ_BLOCK_DEPTH(cx, obj);
@ -1969,7 +1970,7 @@ js_PutBlockObject(JSContext *cx, JSBool normalUnwind)
if (!(sprop->flags & SPROP_HAS_SHORTID))
continue;
slot = depth + (uintN) sprop->shortid;
JS_ASSERT(slot < (size_t) (fp->sp - fp->spbase));
JS_ASSERT(slot < (size_t) (fp->regs->sp - fp->spbase));
if (!js_DefineNativeProperty(cx, obj, sprop->id,
fp->spbase[slot], NULL, NULL,
JSPROP_ENUMERATE | JSPROP_PERMANENT,
@ -3269,8 +3270,8 @@ js_LookupPropertyWithFlags(JSContext *cx, JSObject *obj, jsid id, uintN flags,
if (clasp->flags & JSCLASS_NEW_RESOLVE) {
newresolve = (JSNewResolveOp)resolve;
if (!(flags & JSRESOLVE_CLASSNAME) &&
cx->fp &&
(pc = cx->fp->pc)) {
cx->fp && cx->fp->regs) {
pc = cx->fp->regs->pc;
cs = &js_CodeSpec[*pc];
format = cs->format;
if (JOF_MODE(format) != JOF_NAME)
@ -3467,10 +3468,10 @@ js_FindIdentifierBase(JSContext *cx, jsid id, JSPropCacheEntry *entry)
if (prop) {
OBJ_DROP_PROPERTY(cx, pobj, prop);
JS_ASSERT(!entry ||
entry->kpc == ((PCVCAP_TAG(entry->vcap) > 1)
? (jsbytecode *) JSID_TO_ATOM(id)
: cx->fp->pc));
JS_ASSERT_IF(entry,
entry->kpc == ((PCVCAP_TAG(entry->vcap) > 1)
? (jsbytecode *) JSID_TO_ATOM(id)
: cx->fp->regs->pc));
return obj;
}
@ -3629,10 +3630,11 @@ js_GetPropertyHelper(JSContext *cx, JSObject *obj, jsid id, jsval *vp,
* Give a strict warning if foo.bar is evaluated by a script for an
* object foo with no property named 'bar'.
*/
if (JSVAL_IS_VOID(*vp) && cx->fp && (pc = cx->fp->pc)) {
if (JSVAL_IS_VOID(*vp) && cx->fp && cx->fp->regs) {
JSOp op;
uintN flags;
pc = cx->fp->regs->pc;
op = (JSOp) *pc;
if (op == JSOP_GETXPROP) {
flags = JSREPORT_ERROR;

Просмотреть файл

@ -1787,7 +1787,7 @@ Decompile(SprintStack *ss, jsbytecode *pc, intN nb, JSOp nextop)
for (fp = cx->fp; fp && !fp->script; fp = fp->down)
continue;
format = cs->format;
if (((fp && pc == fp->pc) ||
if (((fp && fp->regs && pc == fp->regs->pc) ||
(pc == startpc && cs->nuses != 0)) &&
format & (JOF_SET|JOF_DEL|JOF_INCDEC|JOF_IMPORT|JOF_FOR|
JOF_VARPROP)) {
@ -4785,6 +4785,7 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
JSStackFrame *fp;
jsbytecode *pc;
JSScript *script;
JSFrameRegs *regs;
intN pcdepth;
jsval *sp;
char *name;
@ -4795,13 +4796,12 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
for (fp = cx->fp; fp && !fp->script; fp = fp->down)
continue;
if (!fp)
if (!fp || !fp->regs)
goto do_fallback;
pc = fp->pc;
if (!pc)
goto do_fallback;
script = fp->script;
regs = fp->regs;
pc = regs->pc;
if (pc < script->main || script->code + script->length <= pc) {
JS_NOT_REACHED("bug");
goto do_fallback;
@ -4818,7 +4818,7 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
JS_malloc(cx, script->depth * sizeof *pcstack);
if (!pcstack)
return NULL;
pcdepth = ReconstructPCStack(cx, script, fp->pc, pcstack);
pcdepth = ReconstructPCStack(cx, script, regs->pc, pcstack);
if (pcdepth < 0)
goto release_pcstack;
@ -4834,8 +4834,8 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
* calculated value matching v under assumption that it is
* it that caused exception, see bug 328664.
*/
JS_ASSERT((size_t) (fp->sp - fp->spbase) <= fp->script->depth);
sp = fp->sp;
JS_ASSERT((size_t) (regs->sp - fp->spbase) <= script->depth);
sp = regs->sp;
do {
if (sp == fp->spbase) {
pcdepth = -1;
@ -4849,7 +4849,7 @@ js_DecompileValueGenerator(JSContext *cx, intN spindex, jsval v,
* that the interpreter uses for GC roots. Assume that it is
* fp->pc that caused the exception.
*/
pc = fp->pc;
pc = regs->pc;
} else {
pc = pcstack[sp - fp->spbase];
}

Просмотреть файл

@ -1211,15 +1211,16 @@ match_or_replace(JSContext *cx,
JSStackFrame *fp;
/* Skip Function.prototype.call and .apply frames. */
for (fp = cx->fp; fp && !fp->pc; fp = fp->down)
for (fp = cx->fp; fp && !fp->regs; fp = fp->down)
JS_ASSERT(!fp->script);
/* Assume a full array result is required, then prove otherwise. */
test = JS_FALSE;
if (fp) {
JS_ASSERT(*fp->pc == JSOP_CALL || *fp->pc == JSOP_NEW);
JS_ASSERT(js_CodeSpec[*fp->pc].length == 3);
switch (fp->pc[3]) {
JS_ASSERT(*fp->regs->pc == JSOP_CALL ||
*fp->regs->pc == JSOP_NEW);
JS_ASSERT(js_CodeSpec[*fp->regs->pc].length == 3);
switch (fp->regs->pc[3]) {
case JSOP_POP:
case JSOP_IFEQ:
case JSOP_IFNE:

Просмотреть файл

@ -2002,15 +2002,15 @@ ParseXMLSource(JSContext *cx, JSString *src)
chars [offset + dstlen] = 0;
xml = NULL;
for (fp = cx->fp; fp && !fp->pc; fp = fp->down)
for (fp = cx->fp; fp && !fp->regs; fp = fp->down)
JS_ASSERT(!fp->script);
filename = NULL;
lineno = 1;
if (fp) {
op = (JSOp) *fp->pc;
op = (JSOp) *fp->regs->pc;
if (op == JSOP_TOXML || op == JSOP_TOXMLLIST) {
filename = fp->script->filename;
lineno = js_PCToLineNumber(cx, fp->script, fp->pc);
lineno = js_PCToLineNumber(cx, fp->script, fp->regs->pc);
for (endp = srcp + srclen; srcp < endp; srcp++) {
if (*srcp == '\n')
--lineno;
@ -8281,7 +8281,7 @@ js_StepXMLListFilter(JSContext *cx, JSBool initialized)
JSXML *xml, *list;
JSXMLFilter *filter;
sp = cx->fp->sp;
sp = cx->fp->regs->sp;
if (!initialized) {
/*
* We haven't iterated yet, so initialize the filter based on the

Просмотреть файл

@ -187,7 +187,6 @@ AutoPushJSContext::AutoPushJSContext(nsISupports* aSecuritySupports,
{
mFrame.fun = fun;
mFrame.script = JS_GetFunctionScript(cx, fun);
mFrame.pc = mFrame.script->code;
mFrame.callee = JS_GetFunctionObject(fun);
mFrame.scopeChain = JS_GetParent(cx, mFrame.callee);
mFrame.down = cx->fp;