Merge.
authorBrendan Eich <brendan@mozilla.org>
Sun, 08 Jun 2008 17:05:46 -0700
changeset 17225 e72b04a575265bf06358e80c3952fee1a2fd7b1e
parent 17220 cefafc563f49ffe6d323a9525e52f957f4eac0c6 (current diff)
parent 17223 18e5bb903af37da1e38f3ad3c2bc10ef40e78e85 (diff)
child 17227 4bd428c4250c68f46c1a3077af53b0d85e915e1e
push id1452
push usershaver@mozilla.com
push dateFri, 22 Aug 2008 00:08:22 +0000
treeherderautoland@d13bb0868596 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone1.9.1a1pre
Merge.
--- a/.hgtags
+++ b/.hgtags
@@ -1,3 +1,4 @@
 df7a3c8ffeeaba229067efee5a20e21dae0dd877 MOZILLA_1_9_a4_BASE
 4209e16b58411750ac73f761023e46b76b793e2c MOZILLA_1_9_a6_BASE
 66a5c7bce7ee86a820d3c0d54fa07cb719be751c MOZILLA_1_9_a7_BASE
+d1a7596d788757799a1aa5f5d09eac32ff811831 tested
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -2514,16 +2514,126 @@ default_value(JSContext* cx, JSFrameRegs
     JSObject* obj;
     prim_jsval_to_object(v, obj);
     if (!call_obj_default_value(cx, obj, hint, &regs.sp[n])) 
         return JS_FALSE;
     prim_fetch_stack(regs, n, v);
     return JS_TRUE;
 }
 
+static inline bool
+value_to_iter(JSContext* cx, JSFrameRegs& regs, JSStackFrame* fp, JSOp op, uintN flags) 
+{
+    JS_ASSERT(regs.sp > fp->spbase);
+    if (!js_ValueToIterator(cx, flags, &regs.sp[-1]))
+        return false;
+    JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[-1]));
+    JS_ASSERT(JSOP_FORIN_LENGTH == js_CodeSpec[op].length);
+    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))
 #define FETCH_STACK(n,v) prim_fetch_stack(regs, (n), (v))
 #define ADJUST_STACK(n)  prim_adjust_stack(regs, (n))
 
 #define PUSH_STACK_CONSTANT(c)     push_stack_constant(regs, (c))
 #define PUSH_STACK_BOOLEAN(b)      push_stack_boolean(regs, (b))
@@ -2577,16 +2687,24 @@ default_value(JSContext* cx, JSFrameRegs
 #define FETCH_OBJECT(cx, n, v, obj)                                           \
     if (!fetch_object(cx, regs, n, v, obj))                                   \
         goto error;
 
 #define DEFAULT_VALUE(cx, n, hint, v)                                         \
     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
  * such v we can do increment or decrement via adding or subtracting two
  * without checking that the result overflows JSVAL_INT_MIN or JSVAL_INT_MAX.
  */
 #define CAN_DO_FAST_INC_DEC(v)     (((((v) << 1) ^ v) & 0x80000001) == 1)
 
@@ -2698,17 +2816,16 @@ JS_INTERPRET(JSContext *cx)
     jsbytecode *endpc, *pc2;
     JSOp op, op2;
     jsatomid index;
     JSAtom *atom;
     uintN argc, attrs, flags;
     uint32 slot;
     jsval *vp, lval, rval, ltmp, rtmp;
     jsid id;
-    JSObject *iterobj;
     JSProperty *prop;
     JSScopeProperty *sprop;
     JSString *str, *str2;
     jsint i, j;
     jsdouble d, d2;
     JSClass *clasp;
     JSFunction *fun;
     JSType type;
@@ -3343,164 +3460,76 @@ JS_INTERPRET(JSContext *cx)
             ADJUST_STACK(-1);
             cond = prop != NULL;
             STORE_STACK_BOOLEAN(-1, cond);
             if (prop)
                 OBJ_DROP_PROPERTY(cx, obj2, prop);
           END_CASE(JSOP_IN)
 
           BEGIN_CASE(JSOP_FOREACH)
-            flags = JSITER_ENUMERATE | JSITER_FOREACH;
-            goto value_to_iter;
+            VALUE_TO_ITER(JSOP_FOREACH, JSITER_ENUMERATE | JSITER_FOREACH);
+          END_CASE(JSOP_FOREACH);
 
 #if JS_HAS_DESTRUCTURING
           BEGIN_CASE(JSOP_FOREACHKEYVAL)
-            flags = JSITER_ENUMERATE | JSITER_FOREACH | JSITER_KEYVALUE;
-            goto value_to_iter;
+            VALUE_TO_ITER(JSOP_FOREACHKEYVAL, JSITER_ENUMERATE | JSITER_FOREACH | JSITER_KEYVALUE);
+          END_CASE(JSOP_FOREACHKEYVAL)          
 #endif
 
           BEGIN_CASE(JSOP_FORIN)
             /*
              * Set JSITER_ENUMERATE to indicate that for-in loop should use
              * the enumeration protocol's iterator for compatibility if an
              * explicit iterator is not given via the optional __iterator__
              * method.
              */
-            flags = JSITER_ENUMERATE;
-
-          value_to_iter:
-            JS_ASSERT(regs.sp > fp->spbase);
-            if (!js_ValueToIterator(cx, flags, &regs.sp[-1]))
-                goto error;
-            JS_ASSERT(!JSVAL_IS_PRIMITIVE(regs.sp[-1]));
-            JS_ASSERT(JSOP_FORIN_LENGTH == js_CodeSpec[op].length);
+            VALUE_TO_ITER(JSOP_FORIN, 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);
-            id = ATOM_TO_JSID(atom);
-            i = -2;
-            goto do_forinloop;
+            DO_FORINLOOP(JSOP_FORPROP, ATOM_TO_JSID(atom), -2);
+          END_CASE(JSOP_FORPROP)            
 
           BEGIN_CASE(JSOP_FORNAME)
             LOAD_ATOM(0);
-            id = ATOM_TO_JSID(atom);
-            /* FALL THROUGH */
-
+            DO_FORINLOOP(JSOP_FORNAME, ATOM_TO_JSID(atom), -1);
+          END_CASE(JSOP_FORNAME)
+          
           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.
              */
-            /* FALL THROUGH */
+            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)
 
           BEGIN_CASE(JSOP_FORELEM)
             /*
              * JSOP_FORELEM simply initializes or updates the iteration state
              * and leaves the index expression evaluation and assignment to the
              * enumerator until after the next property has been acquired, via
              * a JSOP_ENUMELEM bytecode.
              */
-            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);
+            DO_FORINLOOP(JSOP_FORELEM, 0, -1);
+          END_CASE(JSOP_FORELEM)
 
           TRACE_CASE(JSOP_DUP)
             JS_ASSERT(regs.sp > fp->spbase);
             FETCH_STACK(-1, rval);
             PUSH_STACK(rval);
           END_CASE(JSOP_DUP)
 
           TRACE_CASE(JSOP_DUP2)