From 4c62143960a9a11093e36f54fcb91877b8b63d2c Mon Sep 17 00:00:00 2001 From: Andreas Gal Date: Mon, 9 Jun 2008 14:33:40 -0700 Subject: [PATCH] Backed out extraction of code from the interpreter loop as inline method. --- js/src/jsinterp.cpp | 241 ++++++++++++++++++++------------------------ 1 file changed, 109 insertions(+), 132 deletions(-) diff --git a/js/src/jsinterp.cpp b/js/src/jsinterp.cpp index 0ed1df69184..c5930ab2df8 100644 --- a/js/src/jsinterp.cpp +++ b/js/src/jsinterp.cpp @@ -2520,7 +2520,7 @@ default_value(JSContext* cx, JSFrameRegs& regs, int n, JSType hint, } static inline bool -value_to_iter(JSContext* cx, JSFrameRegs& regs, JSStackFrame* fp, JSOp op, uintN flags) +value_to_iter(JSContext* cx, JSFrameRegs& regs, JSStackFrame *fp, JSOp op, uintN flags) { JS_ASSERT(regs.sp > fp->spbase); if (!js_ValueToIterator(cx, flags, ®s.sp[-1])) @@ -2530,105 +2530,6 @@ value_to_iter(JSContext* cx, JSFrameRegs& regs, JSStackFrame* fp, JSOp op, uintN return true; } -static inline bool -do_forinloop(JSContext* cx, JSScript* script, JSFrameRegs& regs, JSStackFrame* fp, JSAtom** atoms, JSOp op, jsid id = 0, jsint i = -1) -{ - JSObject* iterobj; - JSObject* obj; - JSObject* obj2; - jsval lval, rval; - uint32 slot; - jsval* vp; - JSProperty *prop; - - /* - * Reach under the top of stack to find our property iterator, a - * JSObject that contains the iteration state. - */ - JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[i])); - iterobj = JSVAL_TO_OBJECT(regs.sp[i]); - - if (!js_CallIteratorNext(cx, iterobj, &rval)) - return false; - if (rval == JSVAL_HOLE) { - rval = JSVAL_FALSE; - goto end_forinloop; - } - - switch (op) { - case JSOP_FORARG: - slot = GET_ARGNO(regs.pc); - JS_ASSERT(slot < fp->fun->nargs); - fp->argv[slot] = rval; - break; - - case JSOP_FORVAR: - slot = GET_VARNO(regs.pc); - JS_ASSERT(slot < fp->fun->u.i.nvars); - fp->vars[slot] = rval; - break; - - case JSOP_FORCONST: - /* Don't update the const slot. */ - break; - - case JSOP_FORLOCAL: - slot = GET_UINT16(regs.pc); - JS_ASSERT(slot < script->depth); - vp = &fp->spbase[slot]; - GC_POKE(cx, *vp); - *vp = rval; - break; - - case JSOP_FORELEM: - /* FORELEM is not a SET operation, it's more like BINDNAME. */ - prim_push_stack(regs, rval); - break; - - case JSOP_FORPROP: - /* - * We fetch object here to ensure that the iterator is called - * even if lval is null or undefined that throws in - * FETCH_OBJECT. See bug 372331. - */ - if (!fetch_object(cx, regs, -1, lval, obj)) - return false; - goto set_for_property; - - default: - JS_ASSERT(op == JSOP_FORNAME); - - /* - * We find property here after the iterator call to ensure - * that we take into account side effects of the iterator - * call. See bug 372331. - */ - - if (!js_FindProperty(cx, id, &obj, &obj2, &prop)) - return false; - if (prop) - OBJ_DROP_PROPERTY(cx, obj2, prop); - - set_for_property: - /* Set the variable obj[id] to refer to rval. */ - fp->flags |= JSFRAME_ASSIGNING; - bool ok = OBJ_SET_PROPERTY(cx, obj, id, &rval); - fp->flags &= ~JSFRAME_ASSIGNING; - if (!ok) - return false; - break; - } - - /* Push true to keep looping through properties. */ - rval = JSVAL_TRUE; - -end_forinloop: - prim_adjust_stack(regs, i + 1); - prim_push_stack(regs, rval); - - return true; -} - #define PUSH_STACK(v) prim_push_stack(regs, (v)) #define POP_STACK(v) prim_pop_stack(regs, (v)) #define STORE_STACK(n,v) prim_store_stack(regs, (n), (v)) @@ -2644,6 +2545,8 @@ end_forinloop: #define STORE_STACK_STRING(n, str) store_stack_string(regs, (n), (str)) #define STORE_STACK_OBJECT(n, obj) store_stack_object(regs, (n), (obj)) +#define VALUE_TO_ITER(flags) value_to_iter(cx, regs, fp, op, flags) + /* * Push the double d using regs from the lexical environment. Try to convert d * to a jsint that fits in a jsval, otherwise GC-alloc space for it and push a @@ -2692,14 +2595,6 @@ end_forinloop: if (!default_value(cx, regs, n, hint, v)) \ goto error; -#define VALUE_TO_ITER(op, flags) \ - if (!value_to_iter(cx, regs, fp, op, flags)) \ - goto error; - -#define DO_FORINLOOP(op, id, i) \ - if (!do_forinloop(cx, script, regs, fp, atoms, op, id, i)) \ - goto error; - /* * Quickly test if v is an int from the [-2**29, 2**29) range, that is, when * the lowest bit of v is 1 and the bits 30 and 31 are both either 0 or 1. For @@ -2821,6 +2716,7 @@ JS_INTERPRET(JSContext *cx) uint32 slot; jsval *vp, lval, rval, ltmp, rtmp; jsid id; + JSObject *iterobj; JSProperty *prop; JSScopeProperty *sprop; JSString *str, *str2; @@ -3465,12 +3361,12 @@ JS_INTERPRET(JSContext *cx) END_CASE(JSOP_IN) BEGIN_CASE(JSOP_FOREACH) - VALUE_TO_ITER(JSOP_FOREACH, JSITER_ENUMERATE | JSITER_FOREACH); + VALUE_TO_ITER(JSITER_ENUMERATE | JSITER_FOREACH); END_CASE(JSOP_FOREACH); #if JS_HAS_DESTRUCTURING BEGIN_CASE(JSOP_FOREACHKEYVAL) - VALUE_TO_ITER(JSOP_FOREACHKEYVAL, JSITER_ENUMERATE | JSITER_FOREACH | JSITER_KEYVALUE); + VALUE_TO_ITER(JSITER_ENUMERATE | JSITER_FOREACH | JSITER_KEYVALUE); END_CASE(JSOP_FOREACHKEYVAL) #endif @@ -3481,40 +3377,35 @@ JS_INTERPRET(JSContext *cx) * explicit iterator is not given via the optional __iterator__ * method. */ - VALUE_TO_ITER(JSOP_FORIN, JSITER_ENUMERATE); + VALUE_TO_ITER(JSITER_ENUMERATE); END_CASE(JSOP_FORIN) BEGIN_CASE(JSOP_FORPROP) + /* + * Handle JSOP_FORPROP first, so the cost of the goto do_forinloop + * is not paid for the more common cases. + */ LOAD_ATOM(0); - DO_FORINLOOP(JSOP_FORPROP, ATOM_TO_JSID(atom), -2); - END_CASE(JSOP_FORPROP) + id = ATOM_TO_JSID(atom); + i = -2; + goto do_forinloop; BEGIN_CASE(JSOP_FORNAME) LOAD_ATOM(0); - DO_FORINLOOP(JSOP_FORNAME, ATOM_TO_JSID(atom), -1); - END_CASE(JSOP_FORNAME) - + id = ATOM_TO_JSID(atom); + /* FALL THROUGH */ + BEGIN_CASE(JSOP_FORARG) + BEGIN_CASE(JSOP_FORVAR) + BEGIN_CASE(JSOP_FORCONST) + BEGIN_CASE(JSOP_FORLOCAL) /* * JSOP_FORARG and JSOP_FORVAR don't require any lval computation * here, because they address slots on the stack (in fp->args and * fp->vars, respectively). Same applies to JSOP_FORLOCAL, which * addresses fp->spbase. */ - DO_FORINLOOP(JSOP_FORARG, 0, -1); - END_CASE(JSOP_FORARG) - - BEGIN_CASE(JSOP_FORVAR) - DO_FORINLOOP(JSOP_FORVAR, 0, -1); - END_CASE(JSOP_FORVAR) - - BEGIN_CASE(JSOP_FORCONST) - DO_FORINLOOP(JSOP_FORCONST, 0, -1); - END_CASE(JSOP_FORCONST) - - BEGIN_CASE(JSOP_FORLOCAL) - DO_FORINLOOP(JSOP_FORLOCAL, 0, -1); - END_CASE(JSOP_FORLOCAL) + /* FALL THROUGH */ BEGIN_CASE(JSOP_FORELEM) /* @@ -3523,8 +3414,94 @@ JS_INTERPRET(JSContext *cx) * enumerator until after the next property has been acquired, via * a JSOP_ENUMELEM bytecode. */ - DO_FORINLOOP(JSOP_FORELEM, 0, -1); - END_CASE(JSOP_FORELEM) + i = -1; + + do_forinloop: + /* + * Reach under the top of stack to find our property iterator, a + * JSObject that contains the iteration state. + */ + JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[i])); + iterobj = JSVAL_TO_OBJECT(regs.sp[i]); + + if (!js_CallIteratorNext(cx, iterobj, &rval)) + goto error; + if (rval == JSVAL_HOLE) { + rval = JSVAL_FALSE; + goto end_forinloop; + } + + switch (op) { + case JSOP_FORARG: + slot = GET_ARGNO(regs.pc); + JS_ASSERT(slot < fp->fun->nargs); + fp->argv[slot] = rval; + break; + + case JSOP_FORVAR: + slot = GET_VARNO(regs.pc); + JS_ASSERT(slot < fp->fun->u.i.nvars); + fp->vars[slot] = rval; + break; + + case JSOP_FORCONST: + /* Don't update the const slot. */ + break; + + case JSOP_FORLOCAL: + slot = GET_UINT16(regs.pc); + JS_ASSERT(slot < script->depth); + vp = &fp->spbase[slot]; + GC_POKE(cx, *vp); + *vp = rval; + break; + + case JSOP_FORELEM: + /* FORELEM is not a SET operation, it's more like BINDNAME. */ + PUSH_STACK(rval); + break; + + case JSOP_FORPROP: + /* + * We fetch object here to ensure that the iterator is called + * even if lval is null or undefined that throws in + * FETCH_OBJECT. See bug 372331. + */ + FETCH_OBJECT(cx, -1, lval, obj); + goto set_for_property; + + default: + JS_ASSERT(op == JSOP_FORNAME); + + /* + * We find property here after the iterator call to ensure + * that we take into account side effects of the iterator + * call. See bug 372331. + */ + + if (!js_FindProperty(cx, id, &obj, &obj2, &prop)) + goto error; + if (prop) + OBJ_DROP_PROPERTY(cx, obj2, prop); + + set_for_property: + /* Set the variable obj[id] to refer to rval. */ + fp->flags |= JSFRAME_ASSIGNING; + ok = OBJ_SET_PROPERTY(cx, obj, id, &rval); + fp->flags &= ~JSFRAME_ASSIGNING; + if (!ok) + goto error; + break; + } + + /* Push true to keep looping through properties. */ + rval = JSVAL_TRUE; + + end_forinloop: + ADJUST_STACK(i + 1); + PUSH_STACK(rval); + len = js_CodeSpec[op].length; + DO_NEXT_OP(len); TRACE_CASE(JSOP_DUP) JS_ASSERT(regs.sp > fp->spbase);