Bug 607242 - TM: inline js_Array_dense_setelem_hole. r=gal.
authorNicholas Nethercote <nnethercote@mozilla.com>
Wed, 03 Nov 2010 20:48:51 -0700
changeset 57708 71c0268fb37237ee934570e0c9f49b3a70a071ca
parent 57707 5a519584cdd3d9cb8df45043a7c8c6cf84c7f904
child 57709 b1094f628602829131cdb50d7b6e454ebd87a25a
child 57719 b38546e5b5f8fdaaa08239cd39c66982706d36c7
push id1
push usershaver@mozilla.com
push dateTue, 04 Jan 2011 17:58:04 +0000
reviewersgal
bugs607242
milestone2.0b8pre
Bug 607242 - TM: inline js_Array_dense_setelem_hole. r=gal.
js/src/jsarray.cpp
js/src/jsbuiltins.h
js/src/jstracer.cpp
js/src/tracejit/Writer.cpp
js/src/tracejit/Writer.h
--- a/js/src/jsarray.cpp
+++ b/js/src/jsarray.cpp
@@ -808,34 +808,16 @@ js_PrototypeHasIndexedProperties(JSConte
         if (!obj->isNative())
             return JS_TRUE;
         if (obj->isIndexed())
             return JS_TRUE;
     }
     return JS_FALSE;
 }
 
-#ifdef JS_TRACER
-
-JSBool FASTCALL
-js_Array_dense_setelem_hole(JSContext* cx, JSObject* obj, jsint i)
-{
-    if (js_PrototypeHasIndexedProperties(cx, obj))
-        return false;
-
-    jsuint u = jsuint(i);
-    if (u >= obj->getArrayLength())
-        obj->setArrayLength(u + 1);
-    return true;
-}
-/* storeAccSet == ACCSET_OBJ_PRIVATE: because it can set 'length'. */
-JS_DEFINE_CALLINFO_3(extern, BOOL, js_Array_dense_setelem_hole, CONTEXT, OBJECT, INT32,
-                     0, tjit::ACCSET_OBJ_PRIVATE)
-#endif
-
 static JSBool
 array_defineProperty(JSContext *cx, JSObject *obj, jsid id, const Value *value,
                      PropertyOp getter, PropertyOp setter, uintN attrs)
 {
     uint32 i = 0;       // init to shut GCC up
     JSBool isIndex;
 
     if (JSID_IS_ATOM(id, cx->runtime->atomState.lengthAtom))
--- a/js/src/jsbuiltins.h
+++ b/js/src/jsbuiltins.h
@@ -570,17 +570,16 @@ js_dmod(jsdouble a, jsdouble b);
 #define JS_DEFINE_TRCINFO_1(name, tn0)
 #define JS_DEFINE_TRCINFO_2(name, tn0, tn1)
 #define JS_DEFINE_TRCINFO_3(name, tn0, tn1, tn2)
 #define JS_DEFINE_TRCINFO_4(name, tn0, tn1, tn2, tn3)
 
 #endif /* !JS_TRACER */
 
 /* Defined in jsarray.cpp. */
-JS_DECLARE_CALLINFO(js_Array_dense_setelem_hole)
 JS_DECLARE_CALLINFO(js_NewEmptyArray)
 JS_DECLARE_CALLINFO(js_NewPreallocatedArray)
 JS_DECLARE_CALLINFO(js_InitializerArray)
 JS_DECLARE_CALLINFO(js_ArrayCompPush_tn)
 JS_DECLARE_CALLINFO(js_EnsureDenseArrayCapacity)
 
 /* Defined in jsbuiltins.cpp. */
 JS_DECLARE_CALLINFO(js_UnboxDouble)
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -12793,22 +12793,25 @@ TraceRecorder::setElem(int lval_spindex,
         LIns* isHole_ins = w.eqi(
 #if JS_BITS_PER_WORD == 32
                                  w.ldiValueTag(dslotAddr),
 #else
                                  w.q2i(w.rshuqN(w.ldq(dslotAddr), JSVAL_TAG_SHIFT)),
 #endif
                                  w.nameImmui(JSVAL_TAG_MAGIC));
         w.pauseAddingCSEValues();
-        if (MaybeBranch mbr = w.jf(isHole_ins)) {
-            LIns* args[] = { idx_ins, obj_ins, cx_ins };
-            LIns* res_ins = w.name(w.call(&js_Array_dense_setelem_hole_ci, args),
-                                    "hasNoIndexedProperties");
-            guard(false, w.eqi0(res_ins), mismatchExit);
-            w.label(mbr);
+        if (MaybeBranch mbr1 = w.jf(isHole_ins)) {
+            CHECK_STATUS_A(guardPrototypeHasNoIndexedProperties(obj, obj_ins, mismatchExit));
+            LIns* length_ins = w.lduiObjPrivate(obj_ins);
+            if (MaybeBranch mbr2 = w.jt(w.ltui(idx_ins, length_ins))) {
+                LIns* newLength_ins = w.name(w.addiN(idx_ins, 1), "newLength");
+                w.stuiObjPrivate(obj_ins, newLength_ins);
+                w.label(mbr2);
+            }
+            w.label(mbr1);
         }
         w.resumeAddingCSEValues();
 
         // Right, actually set the element.
         box_value_into(v, v_ins, dslotAddr);
     }
 
     jsbytecode* pc = cx->regs->pc;
--- a/js/src/tracejit/Writer.cpp
+++ b/js/src/tracejit/Writer.cpp
@@ -398,18 +398,19 @@ void ValidateWriter::checkAccSet(LOpcode
         break;
 
       case ACCSET_OBJ_PARENT:
         ok = OK_OBJ_FIELD(LIR_ldp, parent);
         break;
 
       case ACCSET_OBJ_PRIVATE:
         // base = <JSObject>
-        // ins  = ldp.objprivate base[offsetof(JSObject, privateData)]
-        ok = (op == LIR_ldi || op == LIR_ldp) &&
+        // ins  = {ld,st}p.objprivate base[offsetof(JSObject, privateData)]
+        ok = (op == LIR_ldi || op == LIR_ldp ||
+              op == LIR_sti || op == LIR_stp) &&
              disp == offsetof(JSObject, privateData) &&
              couldBeObjectOrString(base);
         break;
 
       case ACCSET_OBJ_CAPACITY:
         ok = OK_OBJ_FIELD(LIR_ldi, capacity);
         break;
 
--- a/js/src/tracejit/Writer.h
+++ b/js/src/tracejit/Writer.h
@@ -485,16 +485,22 @@ class Writer
     }
 
     nj::LIns *lduiObjPrivate(nj::LIns *obj) const {
         return name(lir->insLoad(nj::LIR_ldi, obj, offsetof(JSObject, privateData),
                                  ACCSET_OBJ_PRIVATE),
                     "private_uint32");
     }
 
+    nj::LIns *stuiObjPrivate(nj::LIns *obj, nj::LIns *value) const {
+        return name(lir->insStore(nj::LIR_sti, value, obj, offsetof(JSObject, privateData),
+                                  ACCSET_OBJ_PRIVATE),
+                    "private_uint32");
+    }
+
     nj::LIns *ldiDenseArrayCapacity(nj::LIns *array) const {
         return name(lir->insLoad(nj::LIR_ldi, array, offsetof(JSObject, capacity),
                                  ACCSET_OBJ_CAPACITY),
                     "capacity");
     }
 
     nj::LIns *ldpObjSlots(nj::LIns *obj) const {
         return lir->insLoad(nj::LIR_ldp, obj, offsetof(JSObject, slots), ACCSET_OBJ_SLOTS);
@@ -933,16 +939,20 @@ class Writer
     nj::LIns *negi(nj::LIns *x) const {
         return lir->ins1(nj::LIR_negi, x);
     }
 
     nj::LIns *addi(nj::LIns *x, nj::LIns *y) const {
         return lir->ins2(nj::LIR_addi, x, y);
     }
 
+    nj::LIns *addiN(nj::LIns *x, int32 imm) const {
+        return lir->ins2ImmI(nj::LIR_addi, x, imm);
+    }
+
     nj::LIns *subi(nj::LIns *x, nj::LIns *y) const {
         return lir->ins2(nj::LIR_subi, x, y);
     }
 
     nj::LIns *muli(nj::LIns *x, nj::LIns *y) const {
         return lir->ins2(nj::LIR_muli, x, y);
     }