Bug 572029: fully specialize for unboxing most numbers
authorDavid Mandelin <dmandelin@mozilla.com>
Mon, 14 Jun 2010 17:26:59 -0700
changeset 52866 182abff03d37db9c0f1bab6a513a6777a4a243a5
parent 52865 55fa327f247b9bc6a07217eb14a230715951da68
child 52867 40d06608165491740251b71ebcf125ee11d2214a
push id1
push userroot
push dateTue, 26 Apr 2011 22:38:44 +0000
treeherdermozilla-beta@bfdb6e623a36 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs572029
milestone1.9.3a5pre
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 572029: fully specialize for unboxing most numbers
js/src/jsrecursion.cpp
js/src/jstracer.cpp
js/src/jstracer.h
--- a/js/src/jsrecursion.cpp
+++ b/js/src/jsrecursion.cpp
@@ -726,43 +726,27 @@ TraceRecorder::downRecursion()
     return closeLoop(exit);
 }
 
 JS_REQUIRES_STACK LIns*
 TraceRecorder::slurpInt32Slot(LIns* addr_ins, ptrdiff_t offset, Value* vp, VMSideExit* exit)
 {
     LIns *mask_ins = lir->insLoad(LIR_ldi, addr_ins, offset + offsetof(jsval_layout, s.u.mask32), 
                                   ACC_OTHER);
-    guard(false,
-          lir->insEqI_0(lir->ins2(LIR_ori,
-                                  lir->ins2(LIR_eqi, mask_ins, INS_CONST(JSVAL_MASK32_INT32)),
-                                  lir->ins2(LIR_ltui, mask_ins, INS_CONST(JSVAL_MASK32_CLEAR)))),
-          exit);
-    LIns* space = lir->insAlloc(sizeof(int32));
-    LIns* args[] = { space, lir->ins2(LIR_addp, addr_ins, INS_CONST(offset)) };
-    LIns* result = lir->insCall(&js_TryUnboxInt32_ci, args);
-    guard(false, lir->insEqI_0(result), exit);
-    LIns* int32_ins = lir->insLoad(LIR_ldi, space, 0, ACC_OTHER);
-    return int32_ins;
+    guard(true, lir->ins2(LIR_eqi, mask_ins, INS_CONST(JSVAL_MASK32_INT32)), exit);
+    return lir->insLoad(LIR_ldi, addr_ins, offset + offsetof(jsval_layout, s.payload), ACC_OTHER);
 }
 
 JS_REQUIRES_STACK LIns*
 TraceRecorder::slurpDoubleSlot(LIns* addr_ins, ptrdiff_t offset, Value* vp, VMSideExit* exit)
 {
     LIns *mask_ins = lir->insLoad(LIR_ldi, addr_ins, offset + offsetof(jsval_layout, s.u.mask32), 
                                   ACC_OTHER);
-    guard(false,
-          lir->insEqI_0(lir->ins2(LIR_ori,
-                                  lir->ins2(LIR_eqi, mask_ins, INS_CONST(JSVAL_MASK32_INT32)),
-                                  lir->ins2(LIR_ltui, mask_ins, INS_CONST(JSVAL_MASK32_CLEAR)))),
-          exit);
-    LIns *val_ins = lir->insLoad(LIR_ldi, addr_ins, offset + offsetof(jsval_layout, s.payload),
-                                     ACC_OTHER);
-    LIns* args[] = { val_ins, mask_ins };
-    return lir->insCall(&js_UnboxDouble_ci, args);
+    guard(true, lir->ins2(LIR_ltui, mask_ins, INS_CONST(JSVAL_MASK32_CLEAR)), exit);
+    return lir->insLoad(LIR_ldd, addr_ins, offset + offsetof(jsval_layout, s.payload), ACC_OTHER);
 }
 
 JS_REQUIRES_STACK LIns*
 TraceRecorder::slurpTypedSlot(LIns* addr_ins, ptrdiff_t offset, Value* vp, uint32 mask, VMSideExit* exit)
 {
     LIns *mask_ins = lir->insLoad(LIR_ldi, addr_ins, offset + offsetof(jsval_layout, s.u.mask32), 
                                   ACC_OTHER);
     guard(true, lir->ins2(LIR_eqi, mask_ins, INS_CONST(mask)), exit);
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -9352,35 +9352,45 @@ LIns*
 TraceRecorder::stobj_get_slot(LIns* obj_ins, unsigned slot, LIns*& dslots_ins)
 {
     if (slot < JS_INITIAL_NSLOTS)
         return stobj_get_fslot(obj_ins, slot);
     return stobj_get_dslot(obj_ins, slot - JS_INITIAL_NSLOTS, dslots_ins);
 }
 
 JS_REQUIRES_STACK LIns*
-TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, VMSideExit *exit)
+TraceRecorder::unbox_value(const Value &v, LIns *vaddr_ins, ptrdiff_t offset, VMSideExit *exit,
+                           bool force_double)
 {
     AccSet accSet = vaddr_ins == lirbuf->sp ? ACC_STACK : ACC_OTHER;
     LIns *mask_ins = lir->insLoad(LIR_ldi, vaddr_ins, offset + offsetof(jsval_layout, s.u.mask32), 
                                   accSet);
-    if (v.isNumber()) {
+    if (v.isNumber() && force_double) {
         guard(false,
               lir->insEqI_0(lir->ins2(LIR_ori,
                                       lir->ins2(LIR_eqi, mask_ins, INS_CONST(JSVAL_MASK32_INT32)),
                                       lir->ins2(LIR_ltui, mask_ins, INS_CONST(JSVAL_MASK32_CLEAR)))),
               exit);
         LIns *val_ins = lir->insLoad(LIR_ldi, vaddr_ins, offset + offsetof(jsval_layout, s.payload),
                                      accSet);
         LIns* args[] = { val_ins, mask_ins };
         return lir->insCall(&js_UnboxDouble_ci, args);
     }
 
-    LIns *val_ins = lir->insLoad(LIR_ldi, vaddr_ins, offset + offsetof(jsval_layout, s.payload),
-                                 accSet);
+    if (v.isInt32()) {
+        guard(true, lir->ins2(LIR_eqi, mask_ins, INS_CONST(JSVAL_MASK32_INT32)), exit);
+        return i2d(lir->insLoad(LIR_ldi, vaddr_ins, offset + offsetof(jsval_layout, s.payload), accSet));
+    }
+
+    if (v.isDouble()) {
+        guard(true, lir->ins2(LIR_ltui, mask_ins, INS_CONST(JSVAL_MASK32_CLEAR)), exit);
+        return lir->insLoad(LIR_ldd, vaddr_ins, offset + offsetof(jsval_layout, s.payload), accSet);
+    }
+
+    LIns *val_ins = NULL;
     uint32 mask;
     if (v.isUndefined()) {
         mask = JSVAL_MASK32_UNDEFINED;
         val_ins = INS_VOID();
     } else if (v.isMagic()) {
         mask = JSVAL_MASK32_MAGIC;
         val_ins = INS_HOLE();
     } else if (v.isBoolean()) {
@@ -9391,16 +9401,19 @@ TraceRecorder::unbox_value(const Value &
         mask = JSVAL_MASK32_NONFUNOBJ;
     } else if (v.isFunObj()) {
         mask = JSVAL_MASK32_FUNOBJ;
     } else if (v.isString()) {
         mask = JSVAL_MASK32_STRING;
     } else {
         JS_NOT_REACHED("bad type");
     }
+    if (!val_ins)
+        val_ins = lir->insLoad(LIR_ldi, vaddr_ins, offset + offsetof(jsval_layout, s.payload), 
+                               accSet);
     
     guard(true, lir->ins2(LIR_eqi, mask_ins, INS_CONST(mask)), exit);
     return val_ins;
 }
 
 JS_REQUIRES_STACK LIns*
 TraceRecorder::unbox_value_load(const Value &v, LIns *vload_ins, VMSideExit *exit)
 {
@@ -13245,17 +13258,17 @@ TraceRecorder::denseArrayElement(Value& 
           lir->ins2(LIR_ltup, pidx_ins, minLenCap),
           exit);
 
     /* Load the value and guard on its type to unbox it. */
     vp = &obj->dslots[jsuint(idx)];
 	JS_ASSERT(sizeof(Value) == 8); // The |3| in the following statement requires this.
     addr_ins = lir->ins2(LIR_addp, dslots_ins,
                          lir->ins2ImmI(LIR_lshp, pidx_ins, 3));
-    v_ins = unbox_value(*vp, addr_ins, 0, exit);
+    v_ins = unbox_value(*vp, addr_ins, 0, exit, true);
 
     /* Don't let the hole value escape. Turn it into an undefined. */
     if (vp->isMagic()) {
         CHECK_STATUS(guardPrototypeHasNoIndexedProperties(obj, obj_ins, MISMATCH_EXIT));
         v_ins = INS_VOID();
     }
     return RECORD_CONTINUE;
 }
--- a/js/src/jstracer.h
+++ b/js/src/jstracer.h
@@ -1323,17 +1323,18 @@ class TraceRecorder
                                                                 bool init);
     JS_REQUIRES_STACK RecordingStatus initOrSetPropertyByIndex(nanojit::LIns* obj_ins,
                                                                  nanojit::LIns* index_ins,
                                                                  Value* rvalp, bool init);
     JS_REQUIRES_STACK AbortableRecordingStatus setElem(int lval_spindex, int idx_spindex,
                                                        int v_spindex);
 
     JS_REQUIRES_STACK nanojit::LIns* unbox_value(const Value &v, nanojit::LIns *vaddr_ins, 
-                                                 ptrdiff_t offset, VMSideExit *exit);
+                                                 ptrdiff_t offset, VMSideExit *exit,
+                                                 bool force_double=false);
     JS_REQUIRES_STACK nanojit::LIns* unbox_value_load(const Value &v, nanojit::LIns *vload_ins,
                                                       VMSideExit *exit);
     JS_REQUIRES_STACK nanojit::LIns* unbox_int(const Value &v, nanojit::LIns *vaddr_ins, 
                                                   ptrdiff_t offset);
     JS_REQUIRES_STACK nanojit::LIns* unbox_string(const Value &v, nanojit::LIns *vaddr_ins, 
                                                   ptrdiff_t offset);
     JS_REQUIRES_STACK nanojit::LIns* unbox_object(nanojit::LIns *vaddr_ins, ptrdiff_t offset);
     JS_REQUIRES_STACK nanojit::LIns* is_boxed_int(nanojit::LIns *vaddr_ins);