Bug 821707 - Refactor INITELEM code in the interpreter. r=jorendorff
authorJan de Mooij <jdemooij@mozilla.com>
Sat, 15 Dec 2012 12:12:46 +0100
changeset 125243 90558474eee0287e2891ab975eca5201077b5bef
parent 125242 7c43da37e53fe26f4d67b719b8ca9ca8d97198f0
child 125244 4d0ebb80d228d2e9e4092f9b3322000773fed77a
push id2151
push userlsblakk@mozilla.com
push dateTue, 19 Feb 2013 18:06:57 +0000
treeherdermozilla-beta@4952e88741ec [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjorendorff
bugs821707
milestone20.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 821707 - Refactor INITELEM code in the interpreter. r=jorendorff
js/src/jsinterp.cpp
js/src/jsinterpinlines.h
--- a/js/src/jsinterp.cpp
+++ b/js/src/jsinterp.cpp
@@ -3068,63 +3068,30 @@ BEGIN_CASE(JSOP_INITPROP)
 
     regs.sp--;
 }
 END_CASE(JSOP_INITPROP);
 
 BEGIN_CASE(JSOP_INITELEM_INC)
 BEGIN_CASE(JSOP_INITELEM)
 {
-    /* Pop the element's value into rval. */
     JS_ASSERT(regs.stackDepth() >= 3);
-    HandleValue rref = HandleValue::fromMarkedLocation(&regs.sp[-1]);
+    HandleValue val = HandleValue::fromMarkedLocation(&regs.sp[-1]);
+    MutableHandleValue id = MutableHandleValue::fromMarkedLocation(&regs.sp[-2]);
 
     RootedObject &obj = rootObject0;
-
-    /* Find the object being initialized at top of stack. */
-    const Value &lref = regs.sp[-3];
-    JS_ASSERT(lref.isObject());
-    obj = &lref.toObject();
-
-    /* Fetch id now that we have obj. */
-    RootedId &id = rootId0;
-    FETCH_ELEMENT_ID(obj, -2, id);
-
-    /*
-     * If rref is a hole, do not call JSObject::defineProperty. In this case,
-     * obj must be an array, so if the current op is the last element
-     * initialiser, set the array length to one greater than id.
-     */
-    if (rref.isMagic(JS_ARRAY_HOLE)) {
-        JS_ASSERT(obj->isArray());
-        JS_ASSERT(JSID_IS_INT(id));
-        JS_ASSERT(uint32_t(JSID_TO_INT(id)) < StackSpace::ARGS_LENGTH_MAX);
-        JSOp next = JSOp(*(regs.pc + GetBytecodeLength(regs.pc)));
-        if ((next == JSOP_ENDINIT && op == JSOP_INITELEM) ||
-            (next == JSOP_POP && op == JSOP_INITELEM_INC))
-        {
-            if (!SetLengthProperty(cx, obj, (uint32_t) (JSID_TO_INT(id) + 1)))
-                goto error;
-        }
-    } else {
-        if (!JSObject::defineGeneric(cx, obj, id, rref, NULL, NULL, JSPROP_ENUMERATE))
-            goto error;
-    }
-    if (op == JSOP_INITELEM_INC) {
-        JS_ASSERT(obj->isArray());
-        if (JSID_TO_INT(id) == INT32_MAX) {
-            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
-                                 JSMSG_SPREAD_TOO_LARGE);
-            goto error;
-        }
-        regs.sp[-2].setInt32(JSID_TO_INT(id) + 1);
+    obj = &regs.sp[-3].toObject();
+
+    if (!InitElemOperation(cx, regs.pc, obj, id, val))
+        goto error;
+
+    if (JSOp(*regs.pc) == JSOP_INITELEM)
+        regs.sp -= 2;
+    else
         regs.sp--;
-    } else {
-        regs.sp -= 2;
-    }
 }
 END_CASE(JSOP_INITELEM)
 
 BEGIN_CASE(JSOP_SPREAD)
 {
     int32_t count = regs.sp[-2].toInt32();
     RootedObject arr(cx, &regs.sp[-3].toObject());
     const Value iterable = regs.sp[-1];
--- a/js/src/jsinterpinlines.h
+++ b/js/src/jsinterpinlines.h
@@ -874,16 +874,62 @@ SetObjectElementOperation(JSContext *cx,
 
 static JS_ALWAYS_INLINE JSString *
 TypeOfOperation(JSContext *cx, HandleValue v)
 {
     JSType type = JS_TypeOfValue(cx, v);
     return TypeName(type, cx);
 }
 
+static JS_ALWAYS_INLINE bool
+InitElemOperation(JSContext *cx, jsbytecode *pc, HandleObject obj, MutableHandleValue idval,
+                  HandleValue val)
+{
+    JSOp op = JSOp(*pc);
+    JS_ASSERT(op == JSOP_INITELEM || op == JSOP_INITELEM_INC);
+
+    RootedId id(cx);
+    if (!FetchElementId(cx, obj, idval, id.address(), idval))
+        return false;
+
+    /*
+     * If val is a hole, do not call JSObject::defineProperty. In this case,
+     * obj must be an array, so if the current op is the last element
+     * initialiser, set the array length to one greater than id.
+     */
+    if (val.isMagic(JS_ARRAY_HOLE)) {
+        JS_ASSERT(obj->isArray());
+        JS_ASSERT(JSID_IS_INT(id));
+        JS_ASSERT(uint32_t(JSID_TO_INT(id)) < StackSpace::ARGS_LENGTH_MAX);
+
+        JSOp next = JSOp(*GetNextPc(pc));
+        if ((op == JSOP_INITELEM && next == JSOP_ENDINIT) ||
+            (op == JSOP_INITELEM_INC && next == JSOP_POP))
+        {
+            if (!SetLengthProperty(cx, obj, uint32_t(JSID_TO_INT(id) + 1)))
+                return false;
+        }
+    } else {
+        if (!JSObject::defineGeneric(cx, obj, id, val, NULL, NULL, JSPROP_ENUMERATE))
+            return false;
+    }
+
+    if (op == JSOP_INITELEM_INC) {
+        JS_ASSERT(obj->isArray());
+        if (JSID_TO_INT(id) == INT32_MAX) {
+            JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
+                                 JSMSG_SPREAD_TOO_LARGE);
+            return false;
+        }
+        idval.setInt32(JSID_TO_INT(id) + 1);
+    }
+
+    return true;
+}
+
 #define RELATIONAL_OP(OP)                                                     \
     JS_BEGIN_MACRO                                                            \
         RootedValue lvalRoot(cx, lhs), rvalRoot(cx, rhs);                     \
         Value &lval = lvalRoot.get();                                         \
         Value &rval = rvalRoot.get();                                         \
         /* Optimize for two int-tagged operands (typical loop control). */    \
         if (lval.isInt32() && rval.isInt32()) {                               \
             *res = lval.toInt32() OP rval.toInt32();                          \