Unify double sprinting to handle non-finite and negative zero cases (375882, r=mrbkap).
authorbrendan@mozilla.org
Sun, 01 Apr 2007 19:01:50 -0700
changeset 259 0d5531f3a6112a027bf219d9a923428638cf8e14
parent 258 4433c926292c5fe6ec844dc2699b763da3312bff
child 260 f654d0d8013a74247d345743e8bdc174e96de065
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)
reviewersmrbkap
bugs375882
milestone1.9a4pre
Unify double sprinting to handle non-finite and negative zero cases (375882, r=mrbkap).
js/src/jsopcode.c
--- a/js/src/jsopcode.c
+++ b/js/src/jsopcode.c
@@ -936,27 +936,63 @@ CompareOffsets(void *arg, const void *v1
 
     offset_diff = te1->offset - te2->offset;
     *result = (offset_diff == 0 ? te1->order - te2->order
                : offset_diff < 0 ? -1
                : 1);
     return JS_TRUE;
 }
 
+static ptrdiff_t
+SprintDoubleValue(Sprinter *sp, jsval v, JSOp *opp)
+{
+    jsdouble d;
+    ptrdiff_t todo;
+    char *s, buf[DTOSTR_STANDARD_BUFFER_SIZE];
+
+    JS_ASSERT(JSVAL_IS_DOUBLE(v));
+    d = *JSVAL_TO_DOUBLE(v);
+    if (JSDOUBLE_IS_NEGZERO(d)) {
+        todo = SprintCString(sp, "-0");
+        *opp = JSOP_NEG;
+    } else if (!JSDOUBLE_IS_FINITE(d)) {
+        /* Don't use Infinity and NaN, they're mutable. */
+        todo = SprintCString(sp,
+                             JSDOUBLE_IS_NaN(d)
+                             ? "0 / 0"
+                             : (d < 0)
+                             ? "1 / -0"
+                             : "1 / 0");
+        *opp = JSOP_DIV;
+    } else {
+        s = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD, 0, d);
+        if (!s) {
+            JS_ReportOutOfMemory(sp->context);
+            return -1;
+        }
+        JS_ASSERT(strcmp(s, js_Infinity_str) &&
+                  (*s != '-' ||
+                   strcmp(s + 1, js_Infinity_str)) &&
+                  strcmp(s, js_NaN_str));
+        todo = Sprint(sp, s);
+    }
+    return todo;
+}
+
 static jsbytecode *
 Decompile(SprintStack *ss, jsbytecode *pc, intN nb);
 
 static JSBool
 DecompileSwitch(SprintStack *ss, TableEntry *table, uintN tableLength,
                 jsbytecode *pc, ptrdiff_t switchLength,
                 ptrdiff_t defaultOffset, JSBool isCondSwitch)
 {
     JSContext *cx;
     JSPrinter *jp;
-    ptrdiff_t off, off2, diff, caseExprOff;
+    ptrdiff_t off, off2, diff, caseExprOff, todo;
     char *lval, *rval;
     uintN i;
     jsval key;
     JSString *str;
 
     cx = ss->sprinter.context;
     jp = ss->printer;
 
@@ -1007,28 +1043,38 @@ DecompileSwitch(SprintStack *ss, TableEn
                 /*
                  * key comes from an atom, not the decompiler, so we need to
                  * quote it if it's a string literal.  But if table[i].label
                  * is non-null, key was constant-propagated and label is the
                  * name of the const we should show as the case label.  We set
                  * key to undefined so this identifier is escaped, if required
                  * by non-ASCII characters, but not quoted, by QuoteString.
                  */
+                todo = -1;
                 if (table[i].label) {
                     str = ATOM_TO_STRING(table[i].label);
                     key = JSVAL_VOID;
+                } else if (JSVAL_IS_DOUBLE(key)) {
+                    JSOp junk;
+
+                    todo = SprintDoubleValue(&ss->sprinter, key, &junk);
+                    str = NULL;
                 } else {
                     str = js_ValueToString(cx, key);
                     if (!str)
                         return JS_FALSE;
                 }
-                rval = QuoteString(&ss->sprinter, str,
-                                   (jschar)(JSVAL_IS_STRING(key) ? '"' : 0));
-                if (!rval)
-                    return JS_FALSE;
+                if (todo >= 0) {
+                    rval = OFF2STR(&ss->sprinter, todo);
+                } else {
+                    rval = QuoteString(&ss->sprinter, str, (jschar)
+                                       (JSVAL_IS_STRING(key) ? '"' : 0));
+                    if (!rval)
+                        return JS_FALSE;
+                }
                 RETRACT(&ss->sprinter, rval);
                 jp->indent += 2;
                 js_printf(jp, "\tcase %s:\n", rval);
             }
 
             jp->indent += 2;
             if (off <= defaultOffset && defaultOffset < off2) {
                 diff = defaultOffset - off;
@@ -3481,50 +3527,19 @@ Decompile(SprintStack *ss, jsbytecode *p
               case JSOP_UINT24:
                 i = (jsint) GET_UINT24(pc);
               do_sprint_int:
                 todo = Sprint(&ss->sprinter, "%u", (unsigned) i);
                 break;
 
               BEGIN_LITOPX_CASE(JSOP_NUMBER, 0)
                 val = ATOM_KEY(atom);
-                if (JSVAL_IS_INT(val)) {
-                    long ival = (long)JSVAL_TO_INT(val);
-                    todo = Sprint(&ss->sprinter, "%ld", ival);
-                } else {
-                    jsdouble d;
-                    char *numStr, buf[DTOSTR_STANDARD_BUFFER_SIZE];
-                   
-                    d = *JSVAL_TO_DOUBLE(val);
-                    if (JSDOUBLE_IS_NEGZERO(d)) {
-                        todo = SprintCString(&ss->sprinter, "-0");
-                        saveop = JSOP_NEG;
-                    } else if (!JSDOUBLE_IS_FINITE(d)) {
-                        /* Don't use Infinity, it's mutable. */
-                        todo = SprintCString(&ss->sprinter,
-                                             JSDOUBLE_IS_NaN(d)
-                                             ? "0 / 0"
-                                             : (d < 0)
-                                             ? "1 / -0"
-                                             : "1 / 0");
-                        saveop = JSOP_DIV;
-                    } else {
-                        numStr = JS_dtostr(buf, sizeof buf, DTOSTR_STANDARD,
-                                           0, d);
-                        if (!numStr) {
-                            JS_ReportOutOfMemory(cx);
-                            return NULL;
-                        }
-                        JS_ASSERT(strcmp(numStr, js_Infinity_str) &&
-                                  (*numStr != '-' ||
-                                   strcmp(numStr + 1, js_Infinity_str)) &&
-                                  strcmp(numStr, js_NaN_str));
-                        todo = Sprint(&ss->sprinter, numStr);
-                    }
-                }
+                todo = JSVAL_IS_INT(val)
+                       ? Sprint(&ss->sprinter, "%ld", (long) JSVAL_TO_INT(val))
+                       : SprintDoubleValue(&ss->sprinter, val, &saveop);
               END_LITOPX_CASE
 
               BEGIN_LITOPX_CASE(JSOP_STRING, 0)
                 rval = QuoteString(&ss->sprinter, ATOM_TO_STRING(atom),
                                    inXML ? DONT_ESCAPE : '"');
                 if (!rval)
                     return NULL;
                 todo = STR2OFF(&ss->sprinter, rval);