--- 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);