Bug 725765 - More Sprinter cleanups (adding a put method rather than having SprintCString and friends). r=jwalden
authorAdam <adam@sigterm.info>
Wed, 15 Feb 2012 16:15:57 -0800
changeset 89838 ad596e4e1c79edef95d96c6bedf6cc07948593c8
parent 89837 b6ba04315303eafa314d2715cf3321f7ba226306
child 89839 3c017b5fd4a52e49c90a57566db8e38e90b6f645
push idunknown
push userunknown
push dateunknown
reviewersjwalden
bugs725765
milestone13.0a1
Bug 725765 - More Sprinter cleanups (adding a put method rather than having SprintCString and friends). r=jwalden
js/src/jsopcode.cpp
js/src/jsopcode.h
--- a/js/src/jsopcode.cpp
+++ b/js/src/jsopcode.cpp
@@ -379,35 +379,35 @@ js_DumpPCCounts(JSContext *cx, JSScript 
  * If counts != NULL, include a counter of the number of times each op was executed.
  */
 JS_FRIEND_API(JSBool)
 js_DisassembleAtPC(JSContext *cx, JSScript *script, JSBool lines, jsbytecode *pc, Sprinter *sp)
 {
     jsbytecode *next, *end;
     uintN len;
 
-    SprintCString(sp, "loc   ");
+    sp->put("loc   ");
     if (lines)
-        SprintCString(sp, "line");
-    SprintCString(sp, "  op\n");
-    SprintCString(sp, "----- ");
+        sp->put("line");
+    sp->put("  op\n");
+    sp->put("----- ");
     if (lines)
-        SprintCString(sp, "----");
-    SprintCString(sp, "  --\n");
+        sp->put("----");
+    sp->put("  --\n");
 
     next = script->code;
     end = next + script->length;
     while (next < end) {
         if (next == script->main())
-            SprintCString(sp, "main:\n");
+            sp->put("main:\n");
         if (pc != NULL) {
             if (pc == next)
-                SprintCString(sp, "--> ");
+                sp->put("--> ");
             else
-                SprintCString(sp, "    ");
+                sp->put("    ");
         }
         len = js_Disassemble1(cx, script, next, next - script->code, lines, sp);
         if (!len)
             return JS_FALSE;
         next += len;
     }
     return JS_TRUE;
 }
@@ -711,17 +711,17 @@ js_Disassemble1(JSContext *cx, JSScript 
       default: {
         char numBuf[12];
         JS_snprintf(numBuf, sizeof numBuf, "%lx", (unsigned long) cs->format);
         JS_ReportErrorNumber(cx, js_GetErrorMessage, NULL,
                              JSMSG_UNKNOWN_FORMAT, numBuf);
         return 0;
       }
     }
-    SprintCString(sp, "\n");
+    sp->put("\n");
     return len;
 }
 
 #endif /* DEBUG */
 
 /************************************************************************/
 
 const size_t Sprinter::DefaultSize = 64;
@@ -859,16 +859,22 @@ Sprinter::put(const char *s, size_t len)
         js_memcpy(bp, s, len);
     }
 
     bp[len] = 0;
     return oldOffset;
 }
 
 ptrdiff_t
+Sprinter::put(const char *s)
+{
+    return put(s, strlen(s));
+}
+
+ptrdiff_t
 Sprinter::putString(JSString *s)
 {
     InvariantChecker ic(this);
 
     size_t length = s->length();
     const jschar *chars = s->getChars(context);
     if (!chars)
         return -1;
@@ -930,48 +936,30 @@ Sprinter::getOffset() const
 ptrdiff_t
 Sprinter::getOffsetOf(const char *string) const
 {
     JS_ASSERT(string >= base && string < base + size);
     return string - base;
 }
 
 ptrdiff_t
-js::SprintPut(Sprinter *sp, const char *s, size_t len)
-{
-    return sp->put(s, len);
-}
-
-ptrdiff_t
-js::SprintCString(Sprinter *sp, const char *s)
-{
-    return SprintPut(sp, s, strlen(s));
-}
-
-ptrdiff_t
-js::SprintString(Sprinter *sp, JSString *str)
-{
-    return sp->putString(str);
-}
-
-ptrdiff_t
 js::Sprint(Sprinter *sp, const char *format, ...)
 {
     va_list ap;
     char *bp;
     ptrdiff_t offset;
 
     va_start(ap, format);
     bp = JS_vsmprintf(format, ap);      /* XXX vsaprintf */
     va_end(ap);
     if (!bp) {
         JS_ReportOutOfMemory(sp->context);
         return -1;
     }
-    offset = SprintCString(sp, bp);
+    offset = sp->put(bp);
     sp->context->free_(bp);
     return offset;
 }
 
 const char js_EscapeMap[] = {
     '\b', 'b',
     '\f', 'f',
     '\n', 'n',
@@ -1237,28 +1225,28 @@ js_printf(JSPrinter *jp, const char *for
     }
     if (!bp) {
         JS_ReportOutOfMemory(jp->sprinter.context);
         va_end(ap);
         return -1;
     }
 
     cc = strlen(bp);
-    if (SprintPut(&jp->sprinter, bp, (size_t)cc) < 0)
+    if (jp->sprinter.put(bp, (size_t)cc) < 0)
         cc = -1;
     jp->sprinter.context->free_(bp);
 
     va_end(ap);
     return cc;
 }
 
 JSBool
 js_puts(JSPrinter *jp, const char *s)
 {
-    return SprintCString(&jp->sprinter, s) >= 0;
+    return jp->sprinter.put(s) >= 0;
 }
 
 /************************************************************************/
 
 struct SprintStack
 {
     Sprinter    sprinter;       /* sprinter for postfix to infix buffering */
     ptrdiff_t   *offsets;       /* stack of postfix string offsets */
@@ -1337,17 +1325,17 @@ SprintOpcode(SprintStack *ss, const char
              jsbytecode *parentpc, ptrdiff_t startOffset)
 {
     if (startOffset < 0) {
         JS_ASSERT(ss->sprinter.context->isExceptionPending());
         return;
     }
     ptrdiff_t offset = ss->sprinter.getOffset();
     UpdateDecompiledParent(ss->printer, pc, parentpc, offset - startOffset);
-    SprintCString(&ss->sprinter, str);
+    ss->sprinter.put(str);
 }
 
 /*
  * Copy the decompiled text for an opcode to all other ops which it was
  * decomposed into.
  */
 static inline void
 CopyDecompiledTextForDecomposedOp(JSPrinter *jp, jsbytecode *pc)
@@ -1420,17 +1408,17 @@ GetOff(SprintStack *ss, uintN i)
     JS_ASSERT(ss->printer->pcstack);
     if (off <= -2 && ss->printer->pcstack) {
         pc = ss->printer->pcstack[-2 - off];
         bytes = DecompileExpression(ss->sprinter.context, ss->printer->script,
                                     ss->printer->fun, pc);
         if (!bytes)
             return 0;
         if (bytes != FAILED_EXPRESSION_DECOMPILER) {
-            off = SprintCString(&ss->sprinter, bytes);
+            off = ss->sprinter.put(bytes);
             if (off < 0)
                 off = 0;
             ss->offsets[i] = off;
             ss->sprinter.context->free_(bytes);
             return off;
         }
 
         if (!*ss->sprinter.string()) {
@@ -1486,17 +1474,17 @@ PushOff(SprintStack *ss, ptrdiff_t off, 
 
     AddParenSlop(ss);
     return JS_TRUE;
 }
 
 static bool
 PushStr(SprintStack *ss, const char *str, JSOp op)
 {
-    ptrdiff_t off = SprintCString(&ss->sprinter, str);
+    ptrdiff_t off = ss->sprinter.put(str);
     if (off < 0)
         return false;
     return PushOff(ss, off, op);
 }
 
 static ptrdiff_t
 PopOffPrec(SprintStack *ss, uint8_t prec, jsbytecode **ppc = NULL)
 {
@@ -1610,26 +1598,25 @@ SprintDoubleValue(Sprinter *sp, jsval v,
 {
     jsdouble d;
     ptrdiff_t todo;
     char *s;
 
     JS_ASSERT(JSVAL_IS_DOUBLE(v));
     d = JSVAL_TO_DOUBLE(v);
     if (JSDOUBLE_IS_NEGZERO(d)) {
-        todo = SprintCString(sp, "-0");
+        todo = sp->put("-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");
+        /* Don't use Infinity and NaN, as local variables may shadow them. */
+        todo = sp->put(JSDOUBLE_IS_NaN(d)
+                       ? "0 / 0"
+                       : (d < 0)
+                       ? "1 / -0"
+                       : "1 / 0");
         *opp = JSOP_DIV;
     } else {
         ToCStringBuf cbuf;
         s = NumberToCString(sp->context, &cbuf, d);
         if (!s) {
             JS_ReportOutOfMemory(sp->context);
             return -1;
         }
@@ -1945,17 +1932,17 @@ DecompileDestructuringLHS(SprintStack *s
 
     *hole = JS_FALSE;
     jp = ss->printer;
     LOAD_OP_DATA(pc);
 
     switch (op) {
       case JSOP_POP:
         *hole = JS_TRUE;
-        if (SprintPut(&ss->sprinter, ", ", 2) < 0)
+        if (ss->sprinter.put(", ", 2) < 0)
             return NULL;
         break;
 
       case JSOP_PICK:
         /*
          * For 'let ([x, y] = y)', the emitter generates
          *
          *     push evaluation of y
@@ -1989,17 +1976,17 @@ DecompileDestructuringLHS(SprintStack *s
         LOAD_OP_DATA(pc);
 
         /*
          * By its post-condition, DecompileDestructuring pushed one string
          * containing the whole decompiled lhs. Our post-condition is to sprint
          * in-place so pop/concat this pushed string.
          */
         lval = PopStr(ss, JSOP_NOP);
-        if (SprintCString(&ss->sprinter, lval) < 0)
+        if (ss->sprinter.put(lval) < 0)
             return NULL;
 
         LOCAL_ASSERT(*pc == JSOP_POP);
 
         /*
          * To put block slots in the right place, the emitter follows a
          * compound lhs with a pick (if at least one slot was pushed). The pick
          * is not part of the compound lhs so DecompileDestructuring did not
@@ -2029,17 +2016,17 @@ DecompileDestructuringLHS(SprintStack *s
                 return NULL;
         } else if (IsVarSlot(jp, pc, &i)) {
             atom = GetArgOrVarAtom(jp, i);
             LOCAL_ASSERT(atom);
             if (!QuoteString(&ss->sprinter, atom, 0))
                 return NULL;
         } else {
             lval = GetLocal(ss, i);
-            if (!lval || SprintCString(&ss->sprinter, lval) < 0)
+            if (!lval || ss->sprinter.put(lval) < 0)
                 return NULL;
         }
         if (op != JSOP_SETLOCALPOP) {
             pc += oplen;
             if (pc == endpc)
                 return pc;
             LOAD_OP_DATA(pc);
             if (op == JSOP_POPN)
@@ -2066,20 +2053,20 @@ DecompileDestructuringLHS(SprintStack *s
             return pc;
         LOAD_OP_DATA(pc);
         LOCAL_ASSERT(op == JSOP_ENUMELEM || op == JSOP_ENUMCONSTELEM);
         xval = PopStr(ss, JSOP_NOP);
         lval = PopStr(ss, JSOP_GETPROP);
         ss->sprinter.setOffset(todo);
         if (*lval == '\0') {
             /* lval is from JSOP_BINDNAME, so just print xval. */
-            todo = SprintCString(&ss->sprinter, xval);
+            todo = ss->sprinter.put(xval);
         } else if (*xval == '\0') {
             /* xval is from JSOP_SETCALL or JSOP_BINDXMLNAME, print lval. */
-            todo = SprintCString(&ss->sprinter, lval);
+            todo = ss->sprinter.put(lval);
         } else {
             todo = Sprint(&ss->sprinter,
                           (JOF_OPMODE(ss->opcodes[ss->top+1]) == JOF_XMLNAME)
                           ? "%s.%s"
                           : "%s[%s]",
                           lval, xval);
         }
         if (todo < 0)
@@ -2112,17 +2099,17 @@ DecompileDestructuring(SprintStack *ss, 
     JSPrinter *jp = ss->printer;
     jsbytecode *startpc = pc;
 
     /*
      * Set head so we can rewrite '[' to '{' as needed.  Back up PAREN_SLOP
      * chars so the destructuring decompilation accumulates contiguously in
      * ss->sprinter starting with "[".
      */
-    ptrdiff_t head = SprintPut(&ss->sprinter, "[", 1);
+    ptrdiff_t head = ss->sprinter.put("[", 1);
     if (head < 0 || !PushOff(ss, head, JSOP_NOP))
         return NULL;
     ss->sprinter.setOffset(ss->sprinter.getOffset() - PAREN_SLOP);
     LOCAL_ASSERT(head == ss->sprinter.getOffset() - 1);
     LOCAL_ASSERT(ss->sprinter[head] == '[');
 
     int lasti = -1;
 
@@ -2173,17 +2160,17 @@ DecompileDestructuring(SprintStack *ss, 
                 if (Sprint(&ss->sprinter, "%g: ", d) < 0)
                     return NULL;
             } else {
                 /* Sanity check for the gnarly control flow above. */
                 LOCAL_ASSERT(i == d);
 
                 /* Fill in any holes (holes at the end don't matter). */
                 while (++lasti < i) {
-                    if (SprintPut(&ss->sprinter, ", ", 2) < 0)
+                    if (ss->sprinter.put(", ", 2) < 0)
                         return NULL;
                 }
             }
             break;
           }
 
           case JSOP_GETPROP:
           case JSOP_LENGTH:
@@ -2191,17 +2178,17 @@ DecompileDestructuring(SprintStack *ss, 
             JSAtom *atom;
             LOAD_ATOM(0);
             ss->sprinter[head] = '{';
 #if JS_HAS_DESTRUCTURING_SHORTHAND
             nameoff = ss->sprinter.getOffset();
 #endif
             if (!QuoteString(&ss->sprinter, atom, IsIdentifier(atom) ? 0 : (jschar)'\''))
                 return NULL;
-            if (SprintPut(&ss->sprinter, ": ", 2) < 0)
+            if (ss->sprinter.put(": ", 2) < 0)
                 return NULL;
             break;
           }
 
           default:
             LOCAL_ASSERT(0);
         }
 
@@ -2263,25 +2250,25 @@ DecompileDestructuring(SprintStack *ss, 
         jssrcnote *sn = js_GetSrcNote(jp->script, pc);
         if (!sn)
             break;
         if (SN_TYPE(sn) != SRC_CONTINUE) {
             LOCAL_ASSERT(SN_TYPE(sn) == SRC_DESTRUCT || SN_TYPE(sn) == SRC_DESTRUCTLET);
             break;
         }
 
-        if (!hole && SprintPut(&ss->sprinter, ", ", 2) < 0)
+        if (!hole && ss->sprinter.put(", ", 2) < 0)
             return NULL;
 
         pc += JSOP_DUP_LENGTH;
     }
 
 out:
     const char *lval = ss->sprinter.stringAt(head);
-    if (SprintPut(&ss->sprinter, (*lval == '[') ? "]" : "}", 1) < 0)
+    if (ss->sprinter.put((*lval == '[') ? "]" : "}", 1) < 0)
         return NULL;
     return pc;
 }
 
 static jsbytecode *
 DecompileGroupAssignment(SprintStack *ss, jsbytecode *pc, jsbytecode *endpc,
                          jssrcnote *sn, ptrdiff_t *todop)
 {
@@ -2307,36 +2294,36 @@ DecompileGroupAssignment(SprintStack *ss
         pc = DecompileDestructuringLHS(ss, pc, endpc, &hole);
         if (!pc)
             return NULL;
         if (pc == endpc)
             return pc;
         LOAD_OP_DATA(pc);
         if (op != JSOP_GETLOCAL)
             break;
-        if (!hole && SprintPut(&ss->sprinter, ", ", 2) < 0)
+        if (!hole && ss->sprinter.put(", ", 2) < 0)
             return NULL;
     }
 
     LOCAL_ASSERT(op == JSOP_POPN);
-    if (SprintPut(&ss->sprinter, "] = [", 5) < 0)
+    if (ss->sprinter.put("] = [", 5) < 0)
         return NULL;
 
     end = ss->top - 1;
     start = end - GET_UINT16(pc);
     for (i = start; i < end; i++) {
         rval = GetStr(ss, i);
         if (Sprint(&ss->sprinter,
                    (i == start) ? "%s" : ", %s",
                    (i == end - 1 && *rval == '\0') ? ", " : rval) < 0) {
             return NULL;
         }
     }
 
-    if (SprintPut(&ss->sprinter, "]", 1) < 0)
+    if (ss->sprinter.put("]", 1) < 0)
         return NULL;
     ss->sprinter.setOffset(ss->offsets[i]);
     ss->top = start;
     *todop = todo;
     return pc;
 }
 
 #undef LOCAL_ASSERT
@@ -2862,17 +2849,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                      * expansion: x = x op y (replace y by z = w to see the
                      * problem).
                      */
                     op = (JSOp) pc[oplen];
                     rval = PopStr(ss, op, &lastrvalpc);
                     (void)PopStr(ss, op, &lastlvalpc);
 
                     /* Print only the right operand of the assignment-op. */
-                    todo = SprintCString(&ss->sprinter, rval);
+                    todo = ss->sprinter.put(rval);
                 } else if (!inXML) {
                     rval = PopStrPrecDupe(ss, cs->prec + !!(cs->format & JOF_LEFTASSOC), &rvalpc);
                     lval = PopStrPrec(ss, cs->prec + !(cs->format & JOF_LEFTASSOC), &lvalpc);
                     todo = ss->sprinter.getOffset();
                     SprintOpcode(ss, lval, lvalpc, pc, todo);
                     Sprint(&ss->sprinter, " %s ", token);
                     SprintOpcode(ss, rval, rvalpc, pc, todo);
                 } else {
@@ -2881,28 +2868,28 @@ Decompile(SprintStack *ss, jsbytecode *p
                     rval = POP_STR();
                     lval = POP_STR();
                     todo = Sprint(&ss->sprinter, ss_format, lval, rval);
                 }
                 break;
 
               case 1:
                 rval = PopStrDupe(ss, op, &rvalpc);
-                todo = SprintCString(&ss->sprinter, token);
+                todo = ss->sprinter.put(token);
                 SprintOpcode(ss, rval, rvalpc, pc, todo);
                 break;
 
               case 0:
                 sn = js_GetSrcNote(jp->script, pc);
                 if (sn && SN_TYPE(sn) == SRC_CONTINUE) {
                     /* Hoisted let decl (e.g. 'y' in 'let (x) { let y; }'). */
-                    todo = SprintCString(&ss->sprinter, SkipString);
+                    todo = ss->sprinter.put(SkipString);
                     break;
                 }
-                todo = SprintCString(&ss->sprinter, token);
+                todo = ss->sprinter.put(token);
                 break;
 
               default:
                 todo = -2;
                 break;
             }
         } else {
             switch (op) {
@@ -3079,17 +3066,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                         rval = ss->sprinter.stringAt(ss->offsets[i]);
                         if (Sprint(&ss->sprinter, ss_format,
                                    (i == newtop) ? "" : ", ",
                                    (i == oldtop - 1 && *rval == '\0')
                                    ? ", " : rval) < 0) {
                             return NULL;
                         }
                     }
-                    if (SprintPut(&ss->sprinter, "]", 1) < 0)
+                    if (ss->sprinter.put("]", 1) < 0)
                         return NULL;
 
                     /*
                      * If this is an empty group assignment, we have no stack
                      * budget into which we can push our result string. Adjust
                      * ss->sprinter.offset so that our consumer can find the
                      * empty group assignment decompilation.
                      */
@@ -3112,17 +3099,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                      * Thread directly to the next opcode if we can, to handle
                      * the special cases of a group assignment in the first or
                      * last part of a for(;;) loop head, or in a let block or
                      * expression head.
                      *
                      * NB: todo at this point indexes space in ss->sprinter
                      * that is liable to be overwritten.  The code below knows
                      * exactly how long rval lives, or else copies it down via
-                     * SprintCString.
+                     * Sprinter::put.
                      */
                     rval = ss->sprinter.stringAt(todo);
                     rvalpc = NULL;
                     todo = -2;
                     pc2 = pc + oplen;
 
                     if (*pc2 == JSOP_NOP) {
                         sn = js_GetSrcNote(jp->script, pc2);
@@ -3139,17 +3126,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                              * third part of for(;;) loop head. If the POPN's
                              * immediate operand is 0, then we may have no slot
                              * on the sprint-stack in which to push our result
                              * string. In this case the result can be recovered
                              * at ss->sprinter.base + ss->sprinter.offset.
                              */
                             if (GET_UINT16(pc) == 0)
                                 break;
-                            todo = SprintCString(&ss->sprinter, rval);
+                            todo = ss->sprinter.put(rval);
                             saveop = JSOP_NOP;
                         }
                     }
 
                     /*
                      * If control flow reaches this point with todo still -2,
                      * just print rval as an expression statement.
                      */
@@ -3209,17 +3196,17 @@ Decompile(SprintStack *ss, jsbytecode *p
 
                     if (!Decompile(ss, done, pc - done))
                         return NULL;
 
                     /* Pop Decompile result and print comma expression. */
                     rval = PopStrDupe(ss, op, &rvalpc);
                     todo = ss->sprinter.getOffset();
                     SprintOpcode(ss, lval, lvalpc, pushpc, todo);
-                    SprintCString(&ss->sprinter, ", ");
+                    ss->sprinter.put(", ");
                     SprintOpcode(ss, rval, rvalpc, pushpc, todo);
                     break;
 
                   case SRC_HIDDEN:
                     /* Hide this pop, it's from a goto in a with or for/in. */
                     todo = -2;
                     break;
 
@@ -3418,17 +3405,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                 }
                 top = ss->top;
                 depth = GET_UINT16(pc);
                 LOCAL_ASSERT(top >= depth);
                 top -= depth;
                 ss->top = top;
                 ss->sprinter.setOffset(GetOff(ss, top));
                 if (op == JSOP_LEAVEBLOCKEXPR)
-                    todo = SprintCString(&ss->sprinter, rval);
+                    todo = ss->sprinter.put(rval);
                 break;
               }
 
               case JSOP_ENTERLET0:
               {
                 obj = jp->script->getObject(GET_UINT32_INDEX(pc));
                 StaticBlockObject &blockObj = obj->asStaticBlock();
 
@@ -3479,20 +3466,20 @@ Decompile(SprintStack *ss, jsbytecode *p
                     const char *rhs = rhsExprs[i];
                     if (!strcmp(rhs, SkipString))
                         continue;
 
                     if (i && Sprint(&ss->sprinter, ", ") < 0)
                         return NULL;
 
                     if (groupAssign) {
-                        if (SprintCString(&ss->sprinter, rhs) < 0)
+                        if (ss->sprinter.put(rhs) < 0)
                             return NULL;
                     } else if (!strncmp(rhs, DestructuredString, DestructuredStringLength)) {
-                        if (SprintCString(&ss->sprinter, rhs + DestructuredStringLength) < 0)
+                        if (ss->sprinter.put(rhs + DestructuredStringLength) < 0)
                             return NULL;
                     } else {
                         JS_ASSERT(atoms[i] != cx->runtime->atomState.emptyAtom);
                         if (!QuoteString(&ss->sprinter, atoms[i], 0))
                             return NULL;
                         if (*rhs) {
                             uint8_t prec = js_CodeSpec[ss->opcodes[letDepth + i]].prec;
                             const char *fmt = prec && prec < js_CodeSpec[JSOP_SETLOCAL].prec
@@ -3740,17 +3727,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                     rval = POP_STR();
                     todo = (*rval != '\0')
                            ? Sprint(&ss->sprinter,
                                     (strncmp(rval, js_yield_str, 5) == 0 &&
                                      (rval[5] == ' ' || rval[5] == '\0'))
                                     ? "%s (%s)"
                                     : "%s %s",
                                     js_yield_str, rval)
-                           : SprintCString(&ss->sprinter, js_yield_str);
+                           : ss->sprinter.put(js_yield_str);
                     break;
                 }
 
 #if JS_HAS_GENERATOR_EXPRS
                 LOCAL_ASSERT(SN_TYPE(sn) == SRC_HIDDEN);
                 /* FALL THROUGH */
 #endif
 
@@ -4103,19 +4090,19 @@ Decompile(SprintStack *ss, jsbytecode *p
                     pc += len;
                     LOCAL_ASSERT(*pc == JSOP_GOTO);
                     oplen = js_CodeSpec[*pc].length;
                     len = GET_JUMP_OFFSET(pc);
                     DECOMPILE_CODE(pc + oplen, len - oplen);
                     rval = PopStrDupe(ss, op, &rvalpc);
                     todo = ss->sprinter.getOffset();
                     SprintOpcode(ss, xval, xvalpc, pushpc, todo);
-                    SprintCString(&ss->sprinter, " ? ");
+                    ss->sprinter.put(" ? ");
                     SprintOpcode(ss, lval, lvalpc, pushpc, todo);
-                    SprintCString(&ss->sprinter, " : ");
+                    ss->sprinter.put(" : ");
                     SprintOpcode(ss, rval, rvalpc, pushpc, todo);
                     break;
 
                   default:
                     break;
                 }
                 break;
               }
@@ -4170,34 +4157,34 @@ Decompile(SprintStack *ss, jsbytecode *p
                 op = JSOP_NOP;          /* turn off parens around xval */
                 xval = POP_STR();
                 op = JSOP_GETELEM;      /* lval must have high precedence */
                 lval = POP_STR();
                 op = saveop;
                 rval = POP_STR();
                 LOCAL_ASSERT(strcmp(rval, forelem_cookie) == 0);
                 if (*xval == '\0') {
-                    todo = SprintCString(&ss->sprinter, lval);
+                    todo = ss->sprinter.put(lval);
                 } else {
                     todo = Sprint(&ss->sprinter,
                                   (JOF_OPMODE(lastop) == JOF_XMLNAME)
                                   ? dot_format
                                   : index_format,
                                   lval, xval);
                 }
                 break;
 
               case JSOP_GETTER:
               case JSOP_SETTER:
                 todo = -2;
                 break;
 
               case JSOP_DUP2:
                 rval = GetStr(ss, ss->top-2);
-                todo = SprintCString(&ss->sprinter, rval);
+                todo = ss->sprinter.put(rval);
                 if (todo < 0 || !PushOff(ss, todo,
                                          (JSOp) ss->opcodes[ss->top-2])) {
                     return NULL;
                 }
                 /* FALL THROUGH */
 
               case JSOP_DUP:
 #if JS_HAS_DESTRUCTURING
@@ -4306,17 +4293,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                         todo = -2;
                     }
                     break;
                 }
 #endif
 
                 rval = GetStr(ss, ss->top-1);
                 saveop = (JSOp) ss->opcodes[ss->top-1];
-                todo = SprintCString(&ss->sprinter, rval);
+                todo = ss->sprinter.put(rval);
                 break;
 
               case JSOP_SWAP:
                 Swap(ss->offsets[ss->top-1], ss->offsets[ss->top-2]);
                 Swap(ss->opcodes[ss->top-1], ss->opcodes[ss->top-2]);
                 Swap(ss->bytecodes[ss->top-1], ss->bytecodes[ss->top-2]);
                 todo = -2;
                 break;
@@ -4412,24 +4399,24 @@ Decompile(SprintStack *ss, jsbytecode *p
                 lval = "(", rval = ")";
                 todo = ss->sprinter.getOffset();
                 if (op == JSOP_NEW) {
                     if (argc == 0)
                         lval = rval = "";
                     Sprint(&ss->sprinter, "%s ", js_new_str);
                 }
                 SprintOpcode(ss, argv[0], lvalpc, pc, todo);
-                SprintCString(&ss->sprinter, lval);
+                ss->sprinter.put(lval);
 
                 for (i = 1; i <= argc; i++) {
                     SprintOpcode(ss, argv[i], argbytecodes[i], pc, todo);
                     if (i < argc)
-                        SprintCString(&ss->sprinter, ", ");
+                        ss->sprinter.put(", ");
                 }
-                SprintCString(&ss->sprinter, rval);
+                ss->sprinter.put(rval);
 
                 cx->free_(argv);
                 cx->free_(argbytecodes);
 
                 break;
               }
 
               case JSOP_SETCALL:
@@ -4661,19 +4648,19 @@ Decompile(SprintStack *ss, jsbytecode *p
                 xval = PopStrDupe(ss, op, &xvalpc);
                 op = saveop;
                 PROPAGATE_CALLNESS();
                 lval = PopStr(ss, op, &lvalpc);
                 todo = ss->sprinter.getOffset();
                 SprintOpcode(ss, lval, lvalpc, pc, todo);
                 if (*xval != '\0') {
                     bool xml = (JOF_OPMODE(lastop) == JOF_XMLNAME);
-                    SprintCString(&ss->sprinter, xml ? "." : "[");
+                    ss->sprinter.put(xml ? "." : "[");
                     SprintOpcode(ss, xval, xvalpc, pc, todo);
-                    SprintCString(&ss->sprinter, xml ? "" : "]");
+                    ss->sprinter.put(xml ? "" : "]");
                 }
                 break;
 
               case JSOP_SETELEM:
               {
                 rval = PopStrDupe(ss, op, &rvalpc);
                 op = JSOP_NOP;          /* turn off parens */
                 xval = PopStrDupe(ss, op, &xvalpc);
@@ -4685,19 +4672,19 @@ Decompile(SprintStack *ss, jsbytecode *p
                     goto do_setlval;
                 sn = js_GetSrcNote(jp->script, pc - 1);
                 bool xml = (JOF_MODE(cs->format) == JOF_XMLNAME);
                 const char *token =
                     GetTokenForAssignment(jp, sn, lastop, pc, rvalpc,
                                           &lastlvalpc, &lastrvalpc);
                 todo = ss->sprinter.getOffset();
                 SprintOpcode(ss, lval, lvalpc, pc, todo);
-                SprintCString(&ss->sprinter, xml ? "." : "[");
+                ss->sprinter.put(xml ? "." : "[");
                 SprintOpcode(ss, xval, xvalpc, pc, todo);
-                SprintCString(&ss->sprinter, xml ? "" : "]");
+                ss->sprinter.put(xml ? "" : "]");
                 Sprint(&ss->sprinter, " %s= ", token);
                 SprintOpcode(ss, rval, rvalpc, pc, todo);
                 break;
               }
 
               case JSOP_CALLARG:
               case JSOP_GETARG:
                 i = GET_ARGNO(pc);
@@ -4892,17 +4879,17 @@ Decompile(SprintStack *ss, jsbytecode *p
                      * Alas, we have to malloc a copy of the result left on the
                      * top of ss2 because both ss and ss2 arena-allocate from
                      * cx's tempLifoAlloc
                      */
                     rval = JS_strdup(cx, PopStr(&ss2, op));
                     las.releaseEarly();
                     if (!rval)
                         return NULL;
-                    todo = SprintCString(&ss->sprinter, rval);
+                    todo = ss->sprinter.put(rval);
                     cx->free_((void *)rval);
                     break;
                 }
 #endif /* JS_HAS_GENERATOR_EXPRS */
                 /* FALL THROUGH */
 
                 fun = jp->script->getFunction(GET_UINT32_INDEX(pc));
                 {
@@ -4916,22 +4903,22 @@ Decompile(SprintStack *ss, jsbytecode *p
                     bool strict = jp->script->strictModeCode;
                     str = js_DecompileToString(cx, "lambda", fun, 0, 
                                                false, grouped, strict,
                                                js_DecompileFunction);
                     if (!str)
                         return NULL;
                 }
               sprint_string:
-                todo = SprintString(&ss->sprinter, str);
+                todo = ss->sprinter.putString(str);
                 break;
 
               case JSOP_CALLEE:
                 JS_ASSERT(jp->fun && jp->fun->atom);
-                todo = SprintString(&ss->sprinter, jp->fun->atom);
+                todo = ss->sprinter.putString(jp->fun->atom);
                 break;
 
               case JSOP_OBJECT:
                 obj = jp->script->getObject(GET_UINT32_INDEX(pc));
                 str = js_ValueToSource(cx, ObjectValue(*obj));
                 if (!str)
                     return NULL;
                 goto sprint_string;
@@ -5133,49 +5120,49 @@ Decompile(SprintStack *ss, jsbytecode *p
               }
 
               case JSOP_DEFFUN:
                 fun = jp->script->getFunction(GET_UINT32_INDEX(pc));
                 todo = -2;
                 goto do_function;
 
               case JSOP_HOLE:
-                todo = SprintPut(&ss->sprinter, "", 0);
+                todo = ss->sprinter.put("", 0);
                 break;
 
               case JSOP_NEWINIT:
               {
                 i = GET_UINT8(pc);
                 LOCAL_ASSERT(i == JSProto_Array || i == JSProto_Object);
 
                 todo = ss->sprinter.getOffset();
                 if (i == JSProto_Array) {
                     ++ss->inArrayInit;
-                    if (SprintCString(&ss->sprinter, "[") < 0)
+                    if (ss->sprinter.put("[") < 0)
                         return NULL;
                 } else {
-                    if (SprintCString(&ss->sprinter, "{") < 0)
+                    if (ss->sprinter.put("{") < 0)
                         return NULL;
                 }
                 break;
               }
 
               case JSOP_NEWARRAY:
               {
                 todo = ss->sprinter.getOffset();
                 ++ss->inArrayInit;
-                if (SprintCString(&ss->sprinter, "[") < 0)
+                if (ss->sprinter.put("[") < 0)
                     return NULL;
                 break;
               }
 
               case JSOP_NEWOBJECT:
               {
                 todo = ss->sprinter.getOffset();
-                if (SprintCString(&ss->sprinter, "{") < 0)
+                if (ss->sprinter.put("{") < 0)
                     return NULL;
                 break;
               }
 
               case JSOP_ENDINIT:
               {
                 JSBool inArray;
 
@@ -5276,19 +5263,19 @@ Decompile(SprintStack *ss, jsbytecode *p
                 js_printf(jp, "\t%s %s %s = %s;\n",
                           js_default_str, js_xml_str, js_namespace_str, rval);
                 todo = -2;
                 break;
 
               case JSOP_ANYNAME:
                 if (pc[JSOP_ANYNAME_LENGTH] == JSOP_TOATTRNAME) {
                     len += JSOP_TOATTRNAME_LENGTH;
-                    todo = SprintPut(&ss->sprinter, "@*", 2);
+                    todo = ss->sprinter.put("@*", 2);
                 } else {
-                    todo = SprintPut(&ss->sprinter, "*", 1);
+                    todo = ss->sprinter.put("*", 1);
                 }
                 break;
 
               case JSOP_QNAMEPART:
                 LOAD_ATOM(0);
                 if (pc[JSOP_QNAMEPART_LENGTH] == JSOP_TOATTRNAME) {
                     saveop = JSOP_TOATTRNAME;
                     len += JSOP_TOATTRNAME_LENGTH;
@@ -5386,48 +5373,48 @@ Decompile(SprintStack *ss, jsbytecode *p
                 rval = POP_STR();
                 PROPAGATE_CALLNESS();
                 lval = POP_STR();
                 todo = Sprint(&ss->sprinter, "%s..%s", lval, rval);
                 break;
 
               case JSOP_XMLCDATA:
                 LOAD_ATOM(0);
-                todo = SprintPut(&ss->sprinter, "<![CDATA[", 9);
+                todo = ss->sprinter.put("<![CDATA[", 9);
                 if (!QuoteString(&ss->sprinter, atom, DONT_ESCAPE))
                     return NULL;
-                SprintPut(&ss->sprinter, "]]>", 3);
+                ss->sprinter.put("]]>", 3);
                 break;
 
               case JSOP_XMLCOMMENT:
                 LOAD_ATOM(0);
-                todo = SprintPut(&ss->sprinter, "<!--", 4);
+                todo = ss->sprinter.put("<!--", 4);
                 if (!QuoteString(&ss->sprinter, atom, DONT_ESCAPE))
                     return NULL;
-                SprintPut(&ss->sprinter, "-->", 3);
+                ss->sprinter.put("-->", 3);
                 break;
 
               case JSOP_XMLPI:
                 LOAD_ATOM(0);
                 rval = JS_strdup(cx, POP_STR());
                 if (!rval)
                     return NULL;
-                todo = SprintPut(&ss->sprinter, "<?", 2);
+                todo = ss->sprinter.put("<?", 2);
                 ok = QuoteString(&ss->sprinter, atom, 0) &&
                      (*rval == '\0' ||
-                      (SprintPut(&ss->sprinter, " ", 1) >= 0 &&
-                       SprintCString(&ss->sprinter, rval)));
+                      (ss->sprinter.put(" ", 1) >= 0 &&
+                       ss->sprinter.put(rval)));
                 cx->free_((char *)rval);
                 if (!ok)
                     return NULL;
-                SprintPut(&ss->sprinter, "?>", 2);
+                ss->sprinter.put("?>", 2);
                 break;
 
               case JSOP_GETFUNNS:
-                todo = SprintPut(&ss->sprinter, js_function_str, 8);
+                todo = ss->sprinter.put(js_function_str, 8);
                 break;
 #endif /* JS_HAS_XML_SUPPORT */
 
               default:
                 todo = -2;
                 break;
             }
         }
@@ -5666,17 +5653,17 @@ js_DecompileFunction(JSPrinter *jp)
                 pc = DecompileDestructuring(&ss, pc, endpc);
                 if (!pc) {
                     ok = JS_FALSE;
                     break;
                 }
                 LOCAL_ASSERT(*pc == JSOP_POP);
                 pc += JSOP_POP_LENGTH;
                 lval = PopStr(&ss, JSOP_NOP);
-                todo = SprintCString(&jp->sprinter, lval);
+                todo = jp->sprinter.put(lval);
                 if (todo < 0) {
                     ok = JS_FALSE;
                     break;
                 }
                 continue;
             }
 
 #undef LOCAL_ASSERT
--- a/js/src/jsopcode.h
+++ b/js/src/jsopcode.h
@@ -499,40 +499,32 @@ class Sprinter
     /* Like reserve, but memory is initialized to 0 */
     char *reserveAndClear(size_t len);
 
     /*
      * Puts |len| characters from |s| at the current position and return an offset to
      * the beginning of this new data
      */
     ptrdiff_t put(const char *s, size_t len);
+    ptrdiff_t put(const char *s);
     ptrdiff_t putString(JSString *str);
 
     /* Prints a formatted string into the buffer */
     int printf(const char *fmt, ...);
 
     /* Change the offset */
     void setOffset(const char *end);
     void setOffset(ptrdiff_t off);
 
     /* Get the offset */
     ptrdiff_t getOffset() const;
     ptrdiff_t getOffsetOf(const char *string) const;
 };
 
 extern ptrdiff_t
-SprintPut(Sprinter *sp, const char *s, size_t len);
-
-extern ptrdiff_t
-SprintCString(Sprinter *sp, const char *s);
-
-extern ptrdiff_t
-SprintString(Sprinter *sp, JSString *str);
-
-extern ptrdiff_t
 Sprint(Sprinter *sp, const char *format, ...);
 
 extern bool
 CallResultEscapes(jsbytecode *pc);
 
 static inline uintN
 GetDecomposeLength(jsbytecode *pc, size_t len)
 {