Bug 1322560 - Refactor js::jit::JSONPrinter -> js::JSONPrinter, r=jonco
☠☠ backed out by 1805d0a9e85b ☠ ☠
authorSteve Fink <sfink@mozilla.com>
Tue, 25 Apr 2017 13:46:04 -0700
changeset 355586 9c91d92a0215701ed9388f149c8ac7c879510060
parent 355585 3b458dc06af44ee788cb86dee6611b66ce0ebe5b
child 355587 a8668eecdab4e6cbc89999f95fd13bf66155cf89
push id89703
push usersfink@mozilla.com
push dateFri, 28 Apr 2017 18:04:28 +0000
treeherdermozilla-inbound@2cd1662bcc5b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersjonco
bugs1322560
milestone55.0a1
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 1322560 - Refactor js::jit::JSONPrinter -> js::JSONPrinter, r=jonco
js/src/jit/CacheIRSpewer.cpp
js/src/jit/CacheIRSpewer.h
js/src/jit/JSONPrinter.cpp
js/src/jit/JSONPrinter.h
js/src/jit/JSONSpewer.cpp
js/src/jit/JSONSpewer.h
js/src/moz.build
js/src/vm/JSONPrinter.cpp
js/src/vm/JSONPrinter.h
js/src/vm/Printer.cpp
js/src/vm/Printer.h
--- a/js/src/jit/CacheIRSpewer.cpp
+++ b/js/src/jit/CacheIRSpewer.cpp
@@ -76,24 +76,24 @@ CacheIRSpewer::init()
 
 void
 CacheIRSpewer::beginCache(LockGuard<Mutex>&, const IRGenerator& gen)
 {
     MOZ_ASSERT(enabled());
     JSONPrinter& j = json.ref();
 
     j.beginObject();
-    j.stringProperty("name", "%s", CacheKindNames[uint8_t(gen.cacheKind_)]);
-    j.stringProperty("file", "%s", gen.script_->filename());
-    j.integerProperty("mode", int(gen.mode_));
+    j.property("name", "%s", CacheKindNames[uint8_t(gen.cacheKind_)]);
+    j.property("file", "%s", gen.script_->filename());
+    j.property("mode", int(gen.mode_));
     if (jsbytecode* pc = gen.pc_) {
         unsigned column;
-        j.integerProperty("line", PCToLineNumber(gen.script_, pc, &column));
-        j.integerProperty("column", column);
-        j.stringProperty("pc", "%p", pc);
+        j.property("line", PCToLineNumber(gen.script_, pc, &column));
+        j.property("column", column);
+        j.property("pc", "%p", pc);
     }
 }
 
 template <typename CharT>
 static void
 QuoteString(GenericPrinter& out, const CharT* s, size_t length)
 {
     const CharT* end = s + length;
@@ -128,42 +128,42 @@ CacheIRSpewer::valueProperty(LockGuard<M
     MOZ_ASSERT(enabled());
     JSONPrinter& j = json.ref();
 
     j.beginObjectProperty(name);
 
     const char* type = InformalValueTypeName(v);
     if (v.isInt32())
         type = "int32";
-    j.stringProperty("type", "%s", type);
+    j.property("type", "%s", type);
 
     if (v.isInt32()) {
-        j.integerProperty("value", v.toInt32());
+        j.property("value", v.toInt32());
     } else if (v.isDouble()) {
-        j.doubleProperty("value", v.toDouble());
+        j.property("value", v.toDouble());
     } else if (v.isString() || v.isSymbol()) {
         JSString* str = v.isString() ? v.toString() : v.toSymbol()->description();
         if (str && str->isLinear()) {
             j.beginStringProperty("value");
             QuoteString(output, &str->asLinear());
             j.endStringProperty();
         }
     } else if (v.isObject()) {
-        j.stringProperty("value", "%p (shape: %p)", &v.toObject(),
+        j.property("value", "%p (shape: %p)", &v.toObject(),
                          v.toObject().maybeShape());
     }
 
     j.endObject();
 }
 
 void
 CacheIRSpewer::attached(LockGuard<Mutex>&, const char* name)
 {
     MOZ_ASSERT(enabled());
-    json.ref().stringProperty("attached", "%s", name);
+    json.ref().property("attached", "%s", name);
 }
 
 void
 CacheIRSpewer::endCache(LockGuard<Mutex>&)
 {
     MOZ_ASSERT(enabled());
     json.ref().endObject();
 }
--- a/js/src/jit/CacheIRSpewer.h
+++ b/js/src/jit/CacheIRSpewer.h
@@ -7,19 +7,19 @@
 #ifndef jit_CacheIRSpewer_h
 #define jit_CacheIRSpewer_h
 
 #ifdef JS_CACHEIR_SPEW
 
 #include "mozilla/Maybe.h"
 
 #include "jit/CacheIR.h"
-#include "jit/JSONPrinter.h"
 #include "js/TypeDecls.h"
 #include "threading/LockGuard.h"
+#include "vm/JSONPrinter.h"
 #include "vm/MutexIDs.h"
 
 namespace js {
 namespace jit {
 
 class CacheIRSpewer
 {
     Mutex outputLock;
--- a/js/src/jit/JSONSpewer.cpp
+++ b/js/src/jit/JSONSpewer.cpp
@@ -21,110 +21,110 @@
 using namespace js;
 using namespace js::jit;
 
 void
 JSONSpewer::beginFunction(JSScript* script)
 {
     beginObject();
     if (script)
-        stringProperty("name", "%s:%" PRIuSIZE, script->filename(), script->lineno());
+        property("name", "%s:%" PRIuSIZE, script->filename(), script->lineno());
     else
-        stringProperty("name", "wasm compilation");
+        property("name", "wasm compilation");
     beginListProperty("passes");
 }
 
 void
 JSONSpewer::beginPass(const char* pass)
 {
     beginObject();
-    stringProperty("name", "%s", pass);
+    property("name", "%s", pass);
 }
 
 void
 JSONSpewer::spewMResumePoint(MResumePoint* rp)
 {
     if (!rp)
         return;
 
     beginObjectProperty("resumePoint");
 
     if (rp->caller())
-        integerProperty("caller", rp->caller()->block()->id());
+        property("caller", rp->caller()->block()->id());
 
     switch (rp->mode()) {
       case MResumePoint::ResumeAt:
-        stringProperty("mode", "%s", "At");
+        property("mode", "%s", "At");
         break;
       case MResumePoint::ResumeAfter:
-        stringProperty("mode", "%s", "After");
+        property("mode", "%s", "After");
         break;
       case MResumePoint::Outer:
-        stringProperty("mode", "%s", "Outer");
+        property("mode", "%s", "Outer");
         break;
     }
 
     beginListProperty("operands");
     for (MResumePoint* iter = rp; iter; iter = iter->caller()) {
         for (int i = iter->numOperands() - 1; i >= 0; i--)
-            integerValue(iter->getOperand(i)->id());
+            value(iter->getOperand(i)->id());
         if (iter->caller())
-            stringValue("|");
+            value("|");
     }
     endList();
 
     endObject();
 }
 
 void
 JSONSpewer::spewMDef(MDefinition* def)
 {
     beginObject();
 
-    integerProperty("id", def->id());
+    property("id", def->id());
 
-    property("opcode");
+    propertyName("opcode");
     out_.printf("\"");
     def->printOpcode(out_);
     out_.printf("\"");
 
     beginListProperty("attributes");
-#define OUTPUT_ATTRIBUTE(X) do{ if(def->is##X()) stringValue(#X); } while(0);
+#define OUTPUT_ATTRIBUTE(X) do{ if(def->is##X()) value(#X); } while(0);
     MIR_FLAG_LIST(OUTPUT_ATTRIBUTE);
 #undef OUTPUT_ATTRIBUTE
     endList();
 
     beginListProperty("inputs");
     for (size_t i = 0, e = def->numOperands(); i < e; i++)
-        integerValue(def->getOperand(i)->id());
+        value(def->getOperand(i)->id());
     endList();
 
     beginListProperty("uses");
     for (MUseDefIterator use(def); use; use++)
-        integerValue(use.def()->id());
+        value(use.def()->id());
     endList();
 
     if (!def->isLowered()) {
         beginListProperty("memInputs");
         if (def->dependency())
-            integerValue(def->dependency()->id());
+            value(def->dependency()->id());
         endList();
     }
 
     bool isTruncated = false;
     if (def->isAdd() || def->isSub() || def->isMod() || def->isMul() || def->isDiv())
         isTruncated = static_cast<MBinaryArithInstruction*>(def)->isTruncated();
 
     if (def->type() != MIRType::None && def->range()) {
         beginStringProperty("type");
         def->range()->dump(out_);
         out_.printf(" : %s%s", StringFromMIRType(def->type()), (isTruncated ? " (t)" : ""));
         endStringProperty();
     } else {
-        stringProperty("type", "%s%s", StringFromMIRType(def->type()), (isTruncated ? " (t)" : ""));
+        property("type", "%s%s", StringFromMIRType(def->type()), (isTruncated ? " (t)" : ""));
     }
 
     if (def->isInstruction()) {
         if (MResumePoint* rp = def->toInstruction()->resumePoint())
             spewMResumePoint(rp);
     }
 
     endObject();
@@ -134,40 +134,40 @@ void
 JSONSpewer::spewMIR(MIRGraph* mir)
 {
     beginObjectProperty("mir");
     beginListProperty("blocks");
 
     for (MBasicBlockIterator block(mir->begin()); block != mir->end(); block++) {
         beginObject();
 
-        integerProperty("number", block->id());
+        property("number", block->id());
         if (block->getHitState() == MBasicBlock::HitState::Count)
-            integerProperty("count", block->getHitCount());
+            property("count", block->getHitCount());
 
         beginListProperty("attributes");
         if (block->hasLastIns()) {
             if (block->isLoopBackedge())
-                stringValue("backedge");
+                value("backedge");
             if (block->isLoopHeader())
-                stringValue("loopheader");
+                value("loopheader");
             if (block->isSplitEdge())
-                stringValue("splitedge");
+                value("splitedge");
         }
         endList();
 
         beginListProperty("predecessors");
         for (size_t i = 0; i < block->numPredecessors(); i++)
-            integerValue(block->getPredecessor(i)->id());
+            value(block->getPredecessor(i)->id());
         endList();
 
         beginListProperty("successors");
         if (block->hasLastIns()) {
             for (size_t i = 0; i < block->numSuccessors(); i++)
-                integerValue(block->getSuccessor(i)->id());
+                value(block->getSuccessor(i)->id());
         }
         endList();
 
         beginListProperty("instructions");
         for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd(); phi++)
             spewMDef(*phi);
         for (MInstructionIterator i(block->begin()); i != block->end(); i++)
             spewMDef(*i);
@@ -182,26 +182,26 @@ JSONSpewer::spewMIR(MIRGraph* mir)
     endObject();
 }
 
 void
 JSONSpewer::spewLIns(LNode* ins)
 {
     beginObject();
 
-    integerProperty("id", ins->id());
+    property("id", ins->id());
 
-    property("opcode");
+    propertyName("opcode");
     out_.printf("\"");
     ins->dump(out_);
     out_.printf("\"");
 
     beginListProperty("defs");
     for (size_t i = 0; i < ins->numDefs(); i++)
-        integerValue(ins->getDef(i)->virtualRegister());
+        value(ins->getDef(i)->virtualRegister());
     endList();
 
     endObject();
 }
 
 void
 JSONSpewer::spewLIR(MIRGraph* mir)
 {
@@ -209,17 +209,17 @@ JSONSpewer::spewLIR(MIRGraph* mir)
     beginListProperty("blocks");
 
     for (MBasicBlockIterator i(mir->begin()); i != mir->end(); i++) {
         LBlock* block = i->lir();
         if (!block)
             continue;
 
         beginObject();
-        integerProperty("number", i->id());
+        property("number", i->id());
 
         beginListProperty("instructions");
         for (size_t p = 0; p < block->numPhis(); p++)
             spewLIns(block->getPhi(p));
         for (LInstructionIterator ins(block->begin()); ins != block->end(); ins++)
             spewLIns(*ins);
         endList();
 
@@ -233,36 +233,36 @@ JSONSpewer::spewLIR(MIRGraph* mir)
 void
 JSONSpewer::spewRanges(BacktrackingAllocator* regalloc)
 {
     beginObjectProperty("ranges");
     beginListProperty("blocks");
 
     for (size_t bno = 0; bno < regalloc->graph.numBlocks(); bno++) {
         beginObject();
-        integerProperty("number", bno);
+        property("number", bno);
         beginListProperty("vregs");
 
         LBlock* lir = regalloc->graph.getBlock(bno);
         for (LInstructionIterator ins = lir->begin(); ins != lir->end(); ins++) {
             for (size_t k = 0; k < ins->numDefs(); k++) {
                 uint32_t id = ins->getDef(k)->virtualRegister();
                 VirtualRegister* vreg = &regalloc->vregs[id];
 
                 beginObject();
-                integerProperty("vreg", id);
+                property("vreg", id);
                 beginListProperty("ranges");
 
                 for (LiveRange::RegisterLinkIterator iter = vreg->rangesBegin(); iter; iter++) {
                     LiveRange* range = LiveRange::get(*iter);
 
                     beginObject();
-                    stringProperty("allocation", "%s", range->bundle()->allocation().toString().get());
-                    integerProperty("start", range->from().bits());
-                    integerProperty("end", range->to().bits());
+                    property("allocation", "%s", range->bundle()->allocation().toString().get());
+                    property("start", range->from().bits());
+                    property("end", range->to().bits());
                     endObject();
                 }
 
                 endList();
                 endObject();
             }
         }
 
--- a/js/src/jit/JSONSpewer.h
+++ b/js/src/jit/JSONSpewer.h
@@ -6,18 +6,18 @@
 
 #ifndef jit_JSONSpewer_h
 #define jit_JSONSpewer_h
 
 #ifdef JS_JITSPEW
 
 #include <stdio.h>
 
-#include "jit/JSONPrinter.h"
 #include "js/TypeDecls.h"
+#include "vm/JSONPrinter.h"
 
 namespace js {
 namespace jit {
 
 class BacktrackingAllocator;
 class MDefinition;
 class MIRGraph;
 class MResumePoint;
--- a/js/src/moz.build
+++ b/js/src/moz.build
@@ -233,17 +233,16 @@ UNIFIED_SOURCES += [
     'jit/IonCaches.cpp',
     'jit/IonControlFlow.cpp',
     'jit/IonIC.cpp',
     'jit/IonOptimizationLevels.cpp',
     'jit/JitcodeMap.cpp',
     'jit/JitFrames.cpp',
     'jit/JitOptions.cpp',
     'jit/JitSpewer.cpp',
-    'jit/JSONPrinter.cpp',
     'jit/JSONSpewer.cpp',
     'jit/LICM.cpp',
     'jit/Linker.cpp',
     'jit/LIR.cpp',
     'jit/LoopUnroller.cpp',
     'jit/Lowering.cpp',
     'jit/MacroAssembler.cpp',
     'jit/MCallOptimize.cpp',
@@ -321,16 +320,17 @@ UNIFIED_SOURCES += [
     'vm/ErrorReporting.cpp',
     'vm/ForOfIterator.cpp',
     'vm/GeckoProfiler.cpp',
     'vm/GeneratorObject.cpp',
     'vm/GlobalObject.cpp',
     'vm/HelperThreads.cpp',
     'vm/Id.cpp',
     'vm/JSONParser.cpp',
+    'vm/JSONPrinter.cpp',
     'vm/MemoryMetrics.cpp',
     'vm/NativeObject.cpp',
     'vm/ObjectGroup.cpp',
     'vm/PIC.cpp',
     'vm/Printer.cpp',
     'vm/Probes.cpp',
     'vm/ProxyObject.cpp',
     'vm/Realm.cpp',
rename from js/src/jit/JSONPrinter.cpp
rename to js/src/vm/JSONPrinter.cpp
--- a/js/src/jit/JSONPrinter.cpp
+++ b/js/src/vm/JSONPrinter.cpp
@@ -1,36 +1,35 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#include "jit/JSONPrinter.h"
+#include "vm/JSONPrinter.h"
 
 #include "mozilla/Assertions.h"
 #include "mozilla/FloatingPoint.h"
 #include "mozilla/SizePrintfMacros.h"
 
 #include <stdarg.h>
 
 using namespace js;
-using namespace js::jit;
 
 void
 JSONPrinter::indent()
 {
     MOZ_ASSERT(indentLevel_ >= 0);
     out_.printf("\n");
     for (int i = 0; i < indentLevel_; i++)
         out_.printf("  ");
 }
 
 void
-JSONPrinter::property(const char* name)
+JSONPrinter::propertyName(const char* name)
 {
     if (!first_)
         out_.printf(",");
     indent();
     out_.printf("\"%s\":", name);
     first_ = false;
 }
 
@@ -44,92 +43,106 @@ JSONPrinter::beginObject()
     out_.printf("{");
     indentLevel_++;
     first_ = true;
 }
 
 void
 JSONPrinter::beginObjectProperty(const char* name)
 {
-    property(name);
+    propertyName(name);
     out_.printf("{");
     indentLevel_++;
     first_ = true;
 }
 
 void
 JSONPrinter::beginListProperty(const char* name)
 {
-    property(name);
+    propertyName(name);
     out_.printf("[");
     first_ = true;
 }
 
 void
 JSONPrinter::beginStringProperty(const char* name)
 {
-    property(name);
+    propertyName(name);
     out_.printf("\"");
 }
 
 void
 JSONPrinter::endStringProperty()
 {
     out_.printf("\"");
 }
 
 void
-JSONPrinter::stringProperty(const char* name, const char* format, ...)
+JSONPrinter::property(const char* name, const char* format, ...)
 {
     va_list ap;
     va_start(ap, format);
 
     beginStringProperty(name);
     out_.vprintf(format, ap);
     endStringProperty();
 
     va_end(ap);
 }
 
 void
-JSONPrinter::stringValue(const char* format, ...)
+JSONPrinter::value(const char* format, ...)
 {
     va_list ap;
     va_start(ap, format);
 
     if (!first_)
         out_.printf(",");
     out_.printf("\"");
     out_.vprintf(format, ap);
     out_.printf("\"");
 
     va_end(ap);
     first_ = false;
 }
 
 void
-JSONPrinter::integerProperty(const char* name, int value)
+JSONPrinter::property(const char* name, int value)
 {
-    property(name);
+    propertyName(name);
     out_.printf("%d", value);
 }
 
 void
-JSONPrinter::integerValue(int value)
+JSONPrinter::value(int val)
 {
     if (!first_)
         out_.printf(",");
-    out_.printf("%d", value);
+    out_.printf("%d", val);
     first_ = false;
 }
 
 void
-JSONPrinter::doubleProperty(const char* name, double value)
+JSONPrinter::property(const char* name, uint32_t value)
+{
+    propertyName(name);
+    out_.printf("%u", value);
+}
+
+void
+JSONPrinter::property(const char* name, uint64_t value)
 {
-    property(name);
+    propertyName(name);
+    out_.printf("%" PRIu64, value);
+}
+
+void
+JSONPrinter::property(const char* name, double value)
+{
+    propertyName(name);
     if (mozilla::IsFinite(value))
         out_.printf("%f", value);
     else
         out_.printf("null");
 }
 
 void
 JSONPrinter::endObject()
rename from js/src/jit/JSONPrinter.h
rename to js/src/vm/JSONPrinter.h
--- a/js/src/jit/JSONPrinter.h
+++ b/js/src/vm/JSONPrinter.h
@@ -1,24 +1,23 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
  * vim: set ts=8 sts=4 et sw=4 tw=99:
  * This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
-#ifndef jit_JSONPrinter_h
-#define jit_JSONPrinter_h
+#ifndef vm_JSONPrinter_h
+#define vm_JSONPrinter_h
 
 #include <stdio.h>
 
 #include "js/TypeDecls.h"
 #include "vm/Printer.h"
 
 namespace js {
-namespace jit {
 
 class JSONPrinter
 {
   protected:
     int indentLevel_;
     bool first_;
     GenericPrinter& out_;
 
@@ -26,27 +25,34 @@ class JSONPrinter
 
   public:
     explicit JSONPrinter(GenericPrinter& out)
       : indentLevel_(0),
         first_(true),
         out_(out)
     { }
 
-    void property(const char* name);
     void beginObject();
     void beginObjectProperty(const char* name);
     void beginListProperty(const char* name);
-    void stringValue(const char* format, ...) MOZ_FORMAT_PRINTF(2, 3);
-    void stringProperty(const char* name, const char* format, ...) MOZ_FORMAT_PRINTF(3, 4);
+
+    void value(const char* format, ...) MOZ_FORMAT_PRINTF(2, 3);
+    void value(int value);
+
+    void property(const char* name, const char* format, ...) MOZ_FORMAT_PRINTF(3, 4);
+    void property(const char* name, int value);
+    void property(const char* name, uint32_t value);
+    void property(const char* name, uint64_t value);
+    void property(const char* name, double value);
+
     void beginStringProperty(const char* name);
     void endStringProperty();
-    void integerValue(int value);
-    void integerProperty(const char* name, int value);
-    void doubleProperty(const char* name, double value);
+
     void endObject();
     void endList();
+
+  protected:
+    void propertyName(const char* name);
 };
 
-} // namespace jit
 } // namespace js
 
-#endif /* jit_JSONPrinter_h */
+#endif /* vm_JSONPrinter_h */
--- a/js/src/vm/Printer.cpp
+++ b/js/src/vm/Printer.cpp
@@ -544,23 +544,9 @@ LSprinter::put(const char* s, size_t len
         MOZ_ASSERT(unused_ >= overflow);
         unused_ -= overflow;
     }
 
     MOZ_ASSERT(len <= INT_MAX);
     return true;
 }
 
-void
-LSprinter::reportOutOfMemory()
-{
-    if (hadOOM_)
-        return;
-    hadOOM_ = true;
-}
-
-bool
-LSprinter::hadOutOfMemory() const
-{
-    return hadOOM_;
-}
-
 } // namespace js
--- a/js/src/vm/Printer.h
+++ b/js/src/vm/Printer.h
@@ -42,19 +42,17 @@ class GenericPrinter
     inline bool put(const char* s) {
         return put(s, strlen(s));
     }
 
     // Prints a formatted string into the buffer.
     bool printf(const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3);
     bool vprintf(const char* fmt, va_list ap);
 
-    // Report that a string operation failed to get the memory it requested. The
-    // first call to this function calls JS_ReportOutOfMemory, and sets this
-    // Sprinter's outOfMemory flag; subsequent calls do nothing.
+    // Report that a string operation failed to get the memory it requested.
     virtual void reportOutOfMemory();
 
     // Return true if this Sprinter ran out of memory.
     virtual bool hadOutOfMemory() const;
 };
 
 // Sprintf, but with unlimited and automatically allocated buffering.
 class Sprinter final : public GenericPrinter
@@ -190,24 +188,16 @@ class LSprinter final : public GenericPr
 
     // Drop the current string, and let them be free with the LifoAlloc.
     void clear();
 
     // Puts |len| characters from |s| at the current position and
     // return true on success, false on failure.
     virtual bool put(const char* s, size_t len) override;
     using GenericPrinter::put; // pick up |inline bool put(const char* s);|
-
-    // Report that a string operation failed to get the memory it requested. The
-    // first call to this function calls JS_ReportOutOfMemory, and sets this
-    // Sprinter's outOfMemory flag; subsequent calls do nothing.
-    virtual void reportOutOfMemory() override;
-
-    // Return true if this Sprinter ran out of memory.
-    virtual bool hadOutOfMemory() const override;
 };
 
 // Map escaped code to the letter/symbol escaped with a backslash.
 extern const char       js_EscapeMap[];
 
 // Return a GC'ed string containing the chars in str, with any non-printing
 // chars or quotes (' or " as specified by the quote argument) escaped, and
 // with the quote character at the beginning and end of the result string.