Cleanup the native frame -> interpreter frame boxing code. We sometimes end up with numbers on our stack in double format that are really ints. We have to detect those and properly store them as in on the interpreter stack.
authorAndreas Gal <gal@mozilla.com>
Mon, 07 Jul 2008 01:37:40 -0700
changeset 17483 1aa7e11366a29c3fe26fed7639e140ead5ab5902
parent 17482 d88a5e56ec9382799f89b9a87d8b4f9a561ff1af
child 17484 5b4529458a560d4fabcb625f3eaadd23bb151c39
child 17485 23d317c80d00330484a91f6bbc5afbc95fe3a588
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
Cleanup the native frame -> interpreter frame boxing code. We sometimes end up with numbers on our stack in double format that are really ints. We have to detect those and properly store them as in on the interpreter stack.
js/src/jstracer.cpp
--- a/js/src/jstracer.cpp
+++ b/js/src/jstracer.cpp
@@ -538,17 +538,17 @@ TraceRecorder::trackNativeFrameUse(unsig
 {
     if (slots > fragmentInfo->maxNativeFrameSlots)
         fragmentInfo->maxNativeFrameSlots = slots;
 }
 
 /* Unbox a jsval into a slot. Slots are wide enough to hold double values
    directly (instead of storing a pointer to them). */
 static bool
-unbox_jsval(jsval v, int t, double* slot)
+unbox_jsval(jsval v, uint8 t, double* slot)
 {
     jsuint type = TYPEMAP_GET_TYPE(t);
     if (type == JSVAL_INT) {
         jsint i;
         if (JSVAL_IS_INT(v))
             *(jsint*)slot = JSVAL_TO_INT(v);
         else if (JSDOUBLE_IS_INT(*JSVAL_TO_DOUBLE(v), i))
             *(jsint*)slot = i;
@@ -582,34 +582,38 @@ unbox_jsval(jsval v, int t, double* slot
     }
     return true;
 }
 
 /* Box a value from the native stack back into the jsval format. Integers
    that are too large to fit into a jsval are automatically boxed into
    heap-allocated doubles. */
 static bool
-box_jsval(JSContext* cx, jsval* vp, int t, double* slot)
+box_jsval(JSContext* cx, jsval* vp, uint8 t, double* slot)
 {
+    jsint i;
     jsdouble d;
     switch (t) {
       case JSVAL_BOOLEAN:
         *vp = BOOLEAN_TO_JSVAL(*(bool*)slot);
         break;
       case JSVAL_INT:
-        jsint i = *(jsint*)slot;
+        i = *(jsint*)slot;
+      store_int:
         if (INT_FITS_IN_JSVAL(i)) {
             *vp = INT_TO_JSVAL(i);
             break;
         }
         d = (jsdouble)i;
-        goto allocate_double;
+        goto store_double;
       case JSVAL_DOUBLE:
         d = *slot;
-     allocate_double:
+        if (JSDOUBLE_IS_INT(d, i))
+            goto store_int;
+      store_double:
         /* GC is not allowed to hit as we come out of the native frame. We have to teach
            the GC how to scan native frames to avoid this race condition. */
         JS_ASSERT(cx->doubleFreeList != NULL);
         return js_NewDoubleInRootedValue(cx, d, vp);
       case JSVAL_STRING:
         *vp = STRING_TO_JSVAL(*(JSString**)slot);
         break;
       default:
@@ -622,41 +626,41 @@ box_jsval(JSContext* cx, jsval* vp, int 
 
 /* Attempt to unbox the given JS frame into a native frame, checking along the way that the 
    supplied typemap holds. */
 static bool
 unbox(JSStackFrame* fp, JSFrameRegs& regs, uint8* m, double* native)
 {
     jsval* vp;
     for (vp = fp->argv; vp < fp->argv + fp->argc; ++vp)
-        if (!unbox_jsval(*vp, (JSType)*m++, native++))
+        if (!unbox_jsval(*vp, *m++, native++))
             return false;
     for (vp = fp->vars; vp < fp->vars + fp->nvars; ++vp)
-        if (!unbox_jsval(*vp, (JSType)*m++, native++))
+        if (!unbox_jsval(*vp, *m++, native++))
             return false;
     for (vp = fp->spbase; vp < regs.sp; ++vp)
-        if (!unbox_jsval(*vp, (JSType)*m++, native++))
+        if (!unbox_jsval(*vp, *m++, native++))
             return false;
     return true;
 }
 
 /* Box the given native frame into a JS frame. This only fails due to a hard error 
    (out of memory for example). */
 static bool
 box(JSContext* cx, JSStackFrame* fp, JSFrameRegs& regs, uint8* m, double* native)
 {
     jsval* vp;
     for (vp = fp->argv; vp < fp->argv + fp->argc; ++vp)
-        if (!box_jsval(cx, vp, (JSType)*m++, native++))
+        if (!box_jsval(cx, vp, *m++, native++))
             return false;
     for (vp = fp->vars; vp < fp->vars + fp->nvars; ++vp)
-        if (!box_jsval(cx, vp, (JSType)*m++, native++))
+        if (!box_jsval(cx, vp, *m++, native++))
             return false;
     for (vp = fp->spbase; vp < regs.sp; ++vp)
-        if (!box_jsval(cx, vp, (JSType)*m++, native++))
+        if (!box_jsval(cx, vp, *m++, native++))
             return false;
     return true;
 }
 
 /* Emit load instructions onto the trace that read the initial stack state. */
 void
 TraceRecorder::import(jsval* p, uint8& t, char *prefix, int index)
 {