Bug 1147403 part 2 - IonMonkey: Use GenericPrinter& instead of FILE* for *::dump functions. r=h4writer

This commit is contained in:
Nicolas B. Pierron 2015-05-28 19:26:55 +02:00
parent 2c0982f451
commit a9838faded
24 changed files with 570 additions and 520 deletions

View File

@ -14,6 +14,8 @@
#include "jit/MIR.h"
#include "jit/MIRGraph.h"
#include "vm/Printer.h"
using namespace js;
using namespace js::jit;
@ -128,11 +130,12 @@ IonSpewDependency(MInstruction* load, MInstruction* store, const char* verb, con
if (!JitSpewEnabled(JitSpew_Alias))
return;
fprintf(JitSpewFile, "Load ");
load->printName(JitSpewFile);
fprintf(JitSpewFile, " %s on store ", verb);
store->printName(JitSpewFile);
fprintf(JitSpewFile, " (%s)\n", reason);
Fprinter& out = JitSpewPrinter();
out.printf("Load ");
load->printName(out);
out.printf(" %s on store ", verb);
store->printName(out);
out.printf(" (%s)\n", reason);
}
static void
@ -141,9 +144,10 @@ IonSpewAliasInfo(const char* pre, MInstruction* ins, const char* post)
if (!JitSpewEnabled(JitSpew_Alias))
return;
fprintf(JitSpewFile, "%s ", pre);
ins->printName(JitSpewFile);
fprintf(JitSpewFile, " %s\n", post);
Fprinter& out = JitSpewPrinter();
out.printf("%s ", pre);
ins->printName(out);
out.printf(" %s\n", post);
}
// This pass annotates every load instruction with the last store instruction
@ -208,9 +212,10 @@ AliasAnalysis::analyze()
}
if (JitSpewEnabled(JitSpew_Alias)) {
fprintf(JitSpewFile, "Processing store ");
def->printName(JitSpewFile);
fprintf(JitSpewFile, " (flags %x)\n", set.flags());
Fprinter& out = JitSpewPrinter();
out.printf("Processing store ");
def->printName(out);
out.printf(" (flags %x)\n", set.flags());
}
} else {
// Find the most recent store on which this instruction depends.

View File

@ -16,66 +16,67 @@
#include "jit/LIR.h"
#include "jit/MIRGraph.h"
#include "vm/Printer.h"
using namespace js;
using namespace js::jit;
bool
C1Spewer::init(const char* path)
{
spewout_ = fopen(path, "w");
return spewout_ != nullptr;
return out_.init(path);
}
void
C1Spewer::beginFunction(MIRGraph* graph, HandleScript script)
{
if (!spewout_)
if (!out_.isInitialized())
return;
this->graph = graph;
fprintf(spewout_, "begin_compilation\n");
out_.printf("begin_compilation\n");
if (script) {
fprintf(spewout_, " name \"%s:%" PRIuSIZE "\"\n", script->filename(), script->lineno());
fprintf(spewout_, " method \"%s:%" PRIuSIZE "\"\n", script->filename(), script->lineno());
out_.printf(" name \"%s:%" PRIuSIZE "\"\n", script->filename(), script->lineno());
out_.printf(" method \"%s:%" PRIuSIZE "\"\n", script->filename(), script->lineno());
} else {
fprintf(spewout_, " name \"asm.js compilation\"\n");
fprintf(spewout_, " method \"asm.js compilation\"\n");
out_.printf(" name \"asm.js compilation\"\n");
out_.printf(" method \"asm.js compilation\"\n");
}
fprintf(spewout_, " date %d\n", (int)time(nullptr));
fprintf(spewout_, "end_compilation\n");
out_.printf(" date %d\n", (int)time(nullptr));
out_.printf("end_compilation\n");
}
void
C1Spewer::spewPass(const char* pass)
{
if (!spewout_)
if (!out_.isInitialized())
return;
fprintf(spewout_, "begin_cfg\n");
fprintf(spewout_, " name \"%s\"\n", pass);
out_.printf("begin_cfg\n");
out_.printf(" name \"%s\"\n", pass);
for (MBasicBlockIterator block(graph->begin()); block != graph->end(); block++)
spewPass(spewout_, *block);
spewPass(out_, *block);
fprintf(spewout_, "end_cfg\n");
fflush(spewout_);
out_.printf("end_cfg\n");
out_.flush();
}
void
C1Spewer::spewRanges(const char* pass, BacktrackingAllocator* regalloc)
{
if (!spewout_)
if (!out_.isInitialized())
return;
fprintf(spewout_, "begin_ranges\n");
fprintf(spewout_, " name \"%s\"\n", pass);
out_.printf("begin_ranges\n");
out_.printf(" name \"%s\"\n", pass);
for (MBasicBlockIterator block(graph->begin()); block != graph->end(); block++)
spewRanges(spewout_, *block, regalloc);
spewRanges(out_, *block, regalloc);
fprintf(spewout_, "end_ranges\n");
fflush(spewout_);
out_.printf("end_ranges\n");
out_.flush();
}
void
@ -86,32 +87,32 @@ C1Spewer::endFunction()
void
C1Spewer::finish()
{
if (spewout_)
fclose(spewout_);
if (out_.isInitialized())
out_.finish();
}
static void
DumpDefinition(FILE* fp, MDefinition* def)
DumpDefinition(GenericPrinter& out, MDefinition* def)
{
fprintf(fp, " ");
fprintf(fp, "%u %u ", def->id(), unsigned(def->useCount()));
def->printName(fp);
fprintf(fp, " ");
def->printOpcode(fp);
fprintf(fp, " <|@\n");
out.printf(" ");
out.printf("%u %u ", def->id(), unsigned(def->useCount()));
def->printName(out);
out.printf(" ");
def->printOpcode(out);
out.printf(" <|@\n");
}
static void
DumpLIR(FILE* fp, LNode* ins)
DumpLIR(GenericPrinter& out, LNode* ins)
{
fprintf(fp, " ");
fprintf(fp, "%d ", ins->id());
ins->dump(fp);
fprintf(fp, " <|@\n");
out.printf(" ");
out.printf("%d ", ins->id());
ins->dump(out);
out.printf(" <|@\n");
}
void
C1Spewer::spewRanges(FILE* fp, BacktrackingAllocator* regalloc, LNode* ins)
C1Spewer::spewRanges(GenericPrinter& out, BacktrackingAllocator* regalloc, LNode* ins)
{
for (size_t k = 0; k < ins->numDefs(); k++) {
uint32_t id = ins->getDef(k)->virtualRegister();
@ -119,98 +120,98 @@ C1Spewer::spewRanges(FILE* fp, BacktrackingAllocator* regalloc, LNode* ins)
for (LiveRange::RegisterLinkIterator iter = vreg->rangesBegin(); iter; iter++) {
LiveRange* range = LiveRange::get(*iter);
fprintf(fp, "%d object \"", id);
fprintf(fp, "%s", range->bundle()->allocation().toString());
fprintf(fp, "\" %d -1", id);
fprintf(fp, " [%u, %u[", range->from().bits(), range->to().bits());
out.printf("%d object \"", id);
out.printf("%s", range->bundle()->allocation().toString());
out.printf("\" %d -1", id);
out.printf(" [%u, %u[", range->from().bits(), range->to().bits());
for (UsePositionIterator usePos(range->usesBegin()); usePos; usePos++)
fprintf(fp, " %u M", usePos->pos.bits());
fprintf(fp, " \"\"\n");
out.printf(" %u M", usePos->pos.bits());
out.printf(" \"\"\n");
}
}
}
void
C1Spewer::spewRanges(FILE* fp, MBasicBlock* block, BacktrackingAllocator* regalloc)
C1Spewer::spewRanges(GenericPrinter& out, MBasicBlock* block, BacktrackingAllocator* regalloc)
{
LBlock* lir = block->lir();
if (!lir)
return;
for (size_t i = 0; i < lir->numPhis(); i++)
spewRanges(fp, regalloc, lir->getPhi(i));
spewRanges(out, regalloc, lir->getPhi(i));
for (LInstructionIterator ins = lir->begin(); ins != lir->end(); ins++)
spewRanges(fp, regalloc, *ins);
spewRanges(out, regalloc, *ins);
}
void
C1Spewer::spewPass(FILE* fp, MBasicBlock* block)
C1Spewer::spewPass(GenericPrinter& out, MBasicBlock* block)
{
fprintf(fp, " begin_block\n");
fprintf(fp, " name \"B%d\"\n", block->id());
fprintf(fp, " from_bci -1\n");
fprintf(fp, " to_bci -1\n");
out.printf(" begin_block\n");
out.printf(" name \"B%d\"\n", block->id());
out.printf(" from_bci -1\n");
out.printf(" to_bci -1\n");
fprintf(fp, " predecessors");
out.printf(" predecessors");
for (uint32_t i = 0; i < block->numPredecessors(); i++) {
MBasicBlock* pred = block->getPredecessor(i);
fprintf(fp, " \"B%d\"", pred->id());
out.printf(" \"B%d\"", pred->id());
}
fprintf(fp, "\n");
out.printf("\n");
fprintf(fp, " successors");
out.printf(" successors");
for (uint32_t i = 0; i < block->numSuccessors(); i++) {
MBasicBlock* successor = block->getSuccessor(i);
fprintf(fp, " \"B%d\"", successor->id());
out.printf(" \"B%d\"", successor->id());
}
fprintf(fp, "\n");
out.printf("\n");
fprintf(fp, " xhandlers\n");
fprintf(fp, " flags\n");
out.printf(" xhandlers\n");
out.printf(" flags\n");
if (block->lir() && block->lir()->begin() != block->lir()->end()) {
fprintf(fp, " first_lir_id %d\n", block->lir()->firstId());
fprintf(fp, " last_lir_id %d\n", block->lir()->lastId());
out.printf(" first_lir_id %d\n", block->lir()->firstId());
out.printf(" last_lir_id %d\n", block->lir()->lastId());
}
fprintf(fp, " begin_states\n");
out.printf(" begin_states\n");
if (block->entryResumePoint()) {
fprintf(fp, " begin_locals\n");
fprintf(fp, " size %d\n", (int)block->numEntrySlots());
fprintf(fp, " method \"None\"\n");
out.printf(" begin_locals\n");
out.printf(" size %d\n", (int)block->numEntrySlots());
out.printf(" method \"None\"\n");
for (uint32_t i = 0; i < block->numEntrySlots(); i++) {
MDefinition* ins = block->getEntrySlot(i);
fprintf(fp, " ");
fprintf(fp, "%d ", i);
out.printf(" ");
out.printf("%d ", i);
if (ins->isUnused())
fprintf(fp, "unused");
out.printf("unused");
else
ins->printName(fp);
fprintf(fp, "\n");
ins->printName(out);
out.printf("\n");
}
fprintf(fp, " end_locals\n");
out.printf(" end_locals\n");
}
fprintf(fp, " end_states\n");
out.printf(" end_states\n");
fprintf(fp, " begin_HIR\n");
out.printf(" begin_HIR\n");
for (MPhiIterator phi(block->phisBegin()); phi != block->phisEnd(); phi++)
DumpDefinition(fp, *phi);
DumpDefinition(out, *phi);
for (MInstructionIterator i(block->begin()); i != block->end(); i++)
DumpDefinition(fp, *i);
fprintf(fp, " end_HIR\n");
DumpDefinition(out, *i);
out.printf(" end_HIR\n");
if (block->lir()) {
fprintf(fp, " begin_LIR\n");
out.printf(" begin_LIR\n");
for (size_t i = 0; i < block->lir()->numPhis(); i++)
DumpLIR(fp, block->lir()->getPhi(i));
DumpLIR(out, block->lir()->getPhi(i));
for (LInstructionIterator i(block->lir()->begin()); i != block->lir()->end(); i++)
DumpLIR(fp, *i);
fprintf(fp, " end_LIR\n");
DumpLIR(out, *i);
out.printf(" end_LIR\n");
}
fprintf(fp, " end_block\n");
out.printf(" end_block\n");
}
#endif /* DEBUG */

View File

@ -12,6 +12,7 @@
#include "NamespaceImports.h"
#include "js/RootingAPI.h"
#include "vm/Printer.h"
namespace js {
namespace jit {
@ -24,11 +25,11 @@ class LNode;
class C1Spewer
{
MIRGraph* graph;
FILE* spewout_;
Fprinter out_;
public:
C1Spewer()
: graph(nullptr), spewout_(nullptr)
: graph(nullptr), out_()
{ }
bool init(const char* path);
@ -39,9 +40,9 @@ class C1Spewer
void finish();
private:
void spewPass(FILE* fp, MBasicBlock* block);
void spewRanges(FILE* fp, BacktrackingAllocator* regalloc, LNode* ins);
void spewRanges(FILE* fp, MBasicBlock* block, BacktrackingAllocator* regalloc);
void spewPass(GenericPrinter& out, MBasicBlock* block);
void spewRanges(GenericPrinter& out, BacktrackingAllocator* regalloc, LNode* ins);
void spewRanges(GenericPrinter& out, MBasicBlock* block, BacktrackingAllocator* regalloc);
};
} // namespace jit

View File

@ -2932,7 +2932,7 @@ LinearSum::add(int32_t constant)
}
void
LinearSum::print(Sprinter& sp) const
LinearSum::dump(GenericPrinter& out) const
{
for (size_t i = 0; i < terms_.length(); i++) {
int32_t scale = terms_[i].scale;
@ -2940,36 +2940,29 @@ LinearSum::print(Sprinter& sp) const
MOZ_ASSERT(scale);
if (scale > 0) {
if (i)
sp.printf("+");
out.printf("+");
if (scale == 1)
sp.printf("#%d", id);
out.printf("#%d", id);
else
sp.printf("%d*#%d", scale, id);
out.printf("%d*#%d", scale, id);
} else if (scale == -1) {
sp.printf("-#%d", id);
out.printf("-#%d", id);
} else {
sp.printf("%d*#%d", scale, id);
out.printf("%d*#%d", scale, id);
}
}
if (constant_ > 0)
sp.printf("+%d", constant_);
out.printf("+%d", constant_);
else if (constant_ < 0)
sp.printf("%d", constant_);
}
void
LinearSum::dump(FILE* fp) const
{
Sprinter sp(GetJitContext()->cx);
sp.init();
print(sp);
fprintf(fp, "%s\n", sp.string());
out.printf("%d", constant_);
}
void
LinearSum::dump() const
{
dump(stderr);
Fprinter out(stderr);
dump(out);
out.finish();
}
MDefinition*

View File

@ -151,8 +151,7 @@ class LinearSum
LinearTerm term(size_t i) const { return terms_[i]; }
void replaceTerm(size_t i, MDefinition* def) { terms_[i].term = def; }
void print(Sprinter& sp) const;
void dump(FILE*) const;
void dump(GenericPrinter& out) const;
void dump() const;
private:

View File

@ -19,45 +19,45 @@ using namespace js::jit;
JSONSpewer::~JSONSpewer()
{
if (fp_)
fclose(fp_);
if (out_.isInitialized())
out_.finish();
}
void
JSONSpewer::indent()
{
if (!fp_)
if (!out_.isInitialized())
return;
MOZ_ASSERT(indentLevel_ >= 0);
fprintf(fp_, "\n");
out_.printf("\n");
for (int i = 0; i < indentLevel_; i++)
fprintf(fp_, " ");
out_.printf(" ");
}
void
JSONSpewer::property(const char* name)
{
if (!fp_)
if (!out_.isInitialized())
return;
if (!first_)
fprintf(fp_, ",");
out_.printf(",");
indent();
fprintf(fp_, "\"%s\":", name);
out_.printf("\"%s\":", name);
first_ = false;
}
void
JSONSpewer::beginObject()
{
if (!fp_)
if (!out_.isInitialized())
return;
if (!first_) {
fprintf(fp_, ",");
out_.printf(",");
indent();
}
fprintf(fp_, "{");
out_.printf("{");
indentLevel_++;
first_ = true;
}
@ -65,11 +65,11 @@ JSONSpewer::beginObject()
void
JSONSpewer::beginObjectProperty(const char* name)
{
if (!fp_)
if (!out_.isInitialized())
return;
property(name);
fprintf(fp_, "{");
out_.printf("{");
indentLevel_++;
first_ = true;
}
@ -77,27 +77,27 @@ JSONSpewer::beginObjectProperty(const char* name)
void
JSONSpewer::beginListProperty(const char* name)
{
if (!fp_)
if (!out_.isInitialized())
return;
property(name);
fprintf(fp_, "[");
out_.printf("[");
first_ = true;
}
void
JSONSpewer::stringProperty(const char* name, const char* format, ...)
{
if (!fp_)
if (!out_.isInitialized())
return;
va_list ap;
va_start(ap, format);
property(name);
fprintf(fp_, "\"");
vfprintf(fp_, format, ap);
fprintf(fp_, "\"");
out_.printf("\"");
out_.vprintf(format, ap);
out_.printf("\"");
va_end(ap);
}
@ -105,17 +105,17 @@ JSONSpewer::stringProperty(const char* name, const char* format, ...)
void
JSONSpewer::stringValue(const char* format, ...)
{
if (!fp_)
if (!out_.isInitialized())
return;
va_list ap;
va_start(ap, format);
if (!first_)
fprintf(fp_, ",");
fprintf(fp_, "\"");
vfprintf(fp_, format, ap);
fprintf(fp_, "\"");
out_.printf(",");
out_.printf("\"");
out_.vprintf(format, ap);
out_.printf("\"");
va_end(ap);
first_ = false;
@ -124,52 +124,51 @@ JSONSpewer::stringValue(const char* format, ...)
void
JSONSpewer::integerProperty(const char* name, int value)
{
if (!fp_)
if (!out_.isInitialized())
return;
property(name);
fprintf(fp_, "%d", value);
out_.printf("%d", value);
}
void
JSONSpewer::integerValue(int value)
{
if (!fp_)
if (!out_.isInitialized())
return;
if (!first_)
fprintf(fp_, ",");
fprintf(fp_, "%d", value);
out_.printf(",");
out_.printf("%d", value);
first_ = false;
}
void
JSONSpewer::endObject()
{
if (!fp_)
if (!out_.isInitialized())
return;
indentLevel_--;
indent();
fprintf(fp_, "}");
out_.printf("}");
first_ = false;
}
void
JSONSpewer::endList()
{
if (!fp_)
if (!out_.isInitialized())
return;
fprintf(fp_, "]");
out_.printf("]");
first_ = false;
}
bool
JSONSpewer::init(const char* path)
{
fp_ = fopen(path, "w");
if (!fp_)
if (out_.init(path))
return false;
beginObject();
@ -214,13 +213,13 @@ JSONSpewer::spewMResumePoint(MResumePoint* rp)
property("mode");
switch (rp->mode()) {
case MResumePoint::ResumeAt:
fprintf(fp_, "\"At\"");
out_.printf("\"At\"");
break;
case MResumePoint::ResumeAfter:
fprintf(fp_, "\"After\"");
out_.printf("\"After\"");
break;
case MResumePoint::Outer:
fprintf(fp_, "\"Outer\"");
out_.printf("\"Outer\"");
break;
}
@ -244,9 +243,9 @@ JSONSpewer::spewMDef(MDefinition* def)
integerProperty("id", def->id());
property("opcode");
fprintf(fp_, "\"");
def->printOpcode(fp_);
fprintf(fp_, "\"");
out_.printf("\"");
def->printOpcode(out_);
out_.printf("\"");
beginListProperty("attributes");
#define OUTPUT_ATTRIBUTE(X) do{ if(def->is##X()) stringValue(#X); } while(0);
@ -278,7 +277,7 @@ JSONSpewer::spewMDef(MDefinition* def)
if (def->type() != MIRType_None && def->range()) {
Sprinter sp(GetJitContext()->cx);
sp.init();
def->range()->print(sp);
def->range()->dump(sp);
stringProperty("type", "%s : %s%s", sp.string(), StringFromMIRType(def->type()), (isTruncated ? " (t)" : ""));
} else {
stringProperty("type", "%s%s", StringFromMIRType(def->type()), (isTruncated ? " (t)" : ""));
@ -295,7 +294,7 @@ JSONSpewer::spewMDef(MDefinition* def)
void
JSONSpewer::spewMIR(MIRGraph* mir)
{
if (!fp_)
if (!out_.isInitialized())
return;
beginObjectProperty("mir");
@ -344,7 +343,7 @@ JSONSpewer::spewMIR(MIRGraph* mir)
void
JSONSpewer::spewLIns(LNode* ins)
{
if (!fp_)
if (!out_.isInitialized())
return;
beginObject();
@ -352,9 +351,9 @@ JSONSpewer::spewLIns(LNode* ins)
integerProperty("id", ins->id());
property("opcode");
fprintf(fp_, "\"");
ins->dump(fp_);
fprintf(fp_, "\"");
out_.printf("\"");
ins->dump(out_);
out_.printf("\"");
beginListProperty("defs");
for (size_t i = 0; i < ins->numDefs(); i++)
@ -367,7 +366,7 @@ JSONSpewer::spewLIns(LNode* ins)
void
JSONSpewer::spewLIR(MIRGraph* mir)
{
if (!fp_)
if (!out_.isInitialized())
return;
beginObjectProperty("lir");
@ -398,7 +397,7 @@ JSONSpewer::spewLIR(MIRGraph* mir)
void
JSONSpewer::spewRanges(BacktrackingAllocator* regalloc)
{
if (!fp_)
if (!out_.isInitialized())
return;
beginObjectProperty("ranges");
@ -424,7 +423,7 @@ JSONSpewer::spewRanges(BacktrackingAllocator* regalloc)
beginObject();
property("allocation");
fprintf(fp_, "\"%s\"", range->bundle()->allocation().toString());
out_.printf("\"%s\"", range->bundle()->allocation().toString());
integerProperty("start", range->from().bits());
integerProperty("end", range->to().bits());
endObject();
@ -447,7 +446,7 @@ void
JSONSpewer::endPass()
{
endObject();
fflush(fp_);
out_.flush();
}
void
@ -456,14 +455,14 @@ JSONSpewer::endFunction()
MOZ_ASSERT(inFunction_);
endList();
endObject();
fflush(fp_);
out_.flush();
inFunction_ = false;
}
void
JSONSpewer::finish()
{
if (!fp_)
if (!out_.isInitialized())
return;
if (inFunction_)
@ -471,9 +470,8 @@ JSONSpewer::finish()
endList();
endObject();
fprintf(fp_, "\n");
out_.printf("\n");
fclose(fp_);
fp_ = nullptr;
out_.finish();
}

View File

@ -11,6 +11,8 @@
#include "js/TypeDecls.h"
#include "vm/Printer.h"
namespace js {
namespace jit {
@ -29,7 +31,7 @@ class JSONSpewer
int indentLevel_;
bool first_;
FILE* fp_;
Fprinter out_;
void indent();
@ -49,7 +51,7 @@ class JSONSpewer
: inFunction_(false),
indentLevel_(0),
first_(true),
fp_(nullptr)
out_()
{ }
~JSONSpewer();

View File

@ -203,7 +203,13 @@ IonSpewer::endFunction()
}
FILE* jit::JitSpewFile = nullptr;
Fprinter&
jit::JitSpewPrinter()
{
static Fprinter out;
return out;
}
static bool
ContainsFlag(const char* str, const char* flag)
@ -348,7 +354,7 @@ jit::CheckLogging()
EnableChannel(JitSpew_BaselineDebugModeOSR);
}
JitSpewFile = stderr;
JitSpewPrinter().init(stderr);
}
void
@ -402,9 +408,10 @@ jit::JitSpewDef(JitSpewChannel channel, const char* str, MDefinition* def)
return;
JitSpewHeader(channel);
fprintf(JitSpewFile, "%s", str);
def->dump(JitSpewFile);
def->dumpLocation(JitSpewFile);
Fprinter& out = JitSpewPrinter();
out.put(str);
def->dump(out);
def->dumpLocation(out);
}
void

View File

@ -140,7 +140,7 @@ void IonSpewPass(const char* pass, BacktrackingAllocator* ra);
void IonSpewEndFunction();
void CheckLogging();
extern FILE* JitSpewFile;
Fprinter& JitSpewPrinter();
void JitSpew(JitSpewChannel channel, const char* fmt, ...);
void JitSpewStart(JitSpewChannel channel, const char* fmt, ...);
void JitSpewCont(JitSpewChannel channel, const char* fmt, ...);
@ -169,7 +169,10 @@ static inline void IonSpewEndFunction()
static inline void CheckLogging()
{ }
static FILE* const JitSpewFile = nullptr;
static inline Fprinter& JitSpewPrinter()
{
MOZ_CRASH("No empty backend for JitSpewPrinter");
}
static inline void JitSpew(JitSpewChannel, const char* fmt, ...)
{ }
static inline void JitSpewStart(JitSpewChannel channel, const char* fmt, ...)

View File

@ -100,7 +100,7 @@ class LMoveGroup : public LInstructionHelper<0, 0, 0>
return new(alloc) LMoveGroup(alloc);
}
void printOperands(FILE* fp);
void printOperands(GenericPrinter& out);
// Add a move which takes place simultaneously with all others in the group.
bool add(LAllocation from, LAllocation to, LDefinition::Type type);

View File

@ -57,18 +57,20 @@ LIRGraph::noteNeedsSafepoint(LInstruction* ins)
}
void
LIRGraph::dump(FILE* fp)
LIRGraph::dump(GenericPrinter& out)
{
for (size_t i = 0; i < numBlocks(); i++) {
getBlock(i)->dump(fp);
fprintf(fp, "\n");
getBlock(i)->dump(out);
out.printf("\n");
}
}
void
LIRGraph::dump()
{
dump(stderr);
Fprinter out(stderr);
dump(out);
out.finish();
}
LBlock::LBlock(MBasicBlock* from)
@ -149,23 +151,25 @@ LBlock::getExitMoveGroup(TempAllocator& alloc)
}
void
LBlock::dump(FILE* fp)
LBlock::dump(GenericPrinter& out)
{
fprintf(fp, "block%u:\n", mir()->id());
out.printf("block%u:\n", mir()->id());
for (size_t i = 0; i < numPhis(); ++i) {
getPhi(i)->dump(fp);
fprintf(fp, "\n");
getPhi(i)->dump(out);
out.printf("\n");
}
for (LInstructionIterator iter = begin(); iter != end(); iter++) {
iter->dump(fp);
fprintf(fp, "\n");
iter->dump(out);
out.printf("\n");
}
}
void
LBlock::dump()
{
dump(stderr);
Fprinter out(stderr);
dump(out);
out.finish();
}
static size_t
@ -308,7 +312,7 @@ LSnapshot::rewriteRecoveredInput(LUse input)
}
void
LNode::printName(FILE* fp, Opcode op)
LNode::printName(GenericPrinter& out, Opcode op)
{
static const char * const names[] =
{
@ -319,13 +323,13 @@ LNode::printName(FILE* fp, Opcode op)
const char* name = names[op];
size_t len = strlen(name);
for (size_t i = 0; i < len; i++)
fprintf(fp, "%c", tolower(name[i]));
out.printf("%c", tolower(name[i]));
}
void
LNode::printName(FILE* fp)
LNode::printName(GenericPrinter& out)
{
printName(fp, op());
printName(out, op());
}
bool
@ -455,12 +459,12 @@ LDefinition::dump() const
}
void
LNode::printOperands(FILE* fp)
LNode::printOperands(GenericPrinter& out)
{
for (size_t i = 0, e = numOperands(); i < e; i++) {
fprintf(fp, " (%s)", getOperand(i)->toString());
out.printf(" (%s)", getOperand(i)->toString());
if (i != numOperands() - 1)
fprintf(fp, ",");
out.printf(",");
}
}
@ -473,56 +477,59 @@ LInstruction::assignSnapshot(LSnapshot* snapshot)
#ifdef DEBUG
if (JitSpewEnabled(JitSpew_IonSnapshots)) {
JitSpewHeader(JitSpew_IonSnapshots);
fprintf(JitSpewFile, "Assigning snapshot %p to instruction %p (",
(void*)snapshot, (void*)this);
printName(JitSpewFile);
fprintf(JitSpewFile, ")\n");
Fprinter& out = JitSpewPrinter();
out.printf("Assigning snapshot %p to instruction %p (",
(void*)snapshot, (void*)this);
printName(out);
out.printf(")\n");
}
#endif
}
void
LNode::dump(FILE* fp)
LNode::dump(GenericPrinter& out)
{
if (numDefs() != 0) {
fprintf(fp, "{");
out.printf("{");
for (size_t i = 0; i < numDefs(); i++) {
fprintf(fp, "%s", getDef(i)->toString());
out.printf("%s", getDef(i)->toString());
if (i != numDefs() - 1)
fprintf(fp, ", ");
out.printf(", ");
}
fprintf(fp, "} <- ");
out.printf("} <- ");
}
printName(fp);
printOperands(fp);
printName(out);
printOperands(out);
if (numTemps()) {
fprintf(fp, " t=(");
out.printf(" t=(");
for (size_t i = 0; i < numTemps(); i++) {
fprintf(fp, "%s", getTemp(i)->toString());
out.printf("%s", getTemp(i)->toString());
if (i != numTemps() - 1)
fprintf(fp, ", ");
out.printf(", ");
}
fprintf(fp, ")");
out.printf(")");
}
if (numSuccessors()) {
fprintf(fp, " s=(");
out.printf(" s=(");
for (size_t i = 0; i < numSuccessors(); i++) {
fprintf(fp, "block%u", getSuccessor(i)->id());
out.printf("block%u", getSuccessor(i)->id());
if (i != numSuccessors() - 1)
fprintf(fp, ", ");
out.printf(", ");
}
fprintf(fp, ")");
out.printf(")");
}
}
void
LNode::dump()
{
dump(stderr);
fprintf(stderr, "\n");
Fprinter out(stderr);
dump(out);
out.printf("\n");
out.finish();
}
void
@ -590,18 +597,18 @@ LMoveGroup::addAfter(LAllocation from, LAllocation to, LDefinition::Type type)
}
void
LMoveGroup::printOperands(FILE* fp)
LMoveGroup::printOperands(GenericPrinter& out)
{
for (size_t i = 0; i < numMoves(); i++) {
const LMove& move = getMove(i);
// Use two printfs, as LAllocation::toString is not reentrant.
fprintf(fp, " [%s", move.from().toString());
fprintf(fp, " -> %s", move.to().toString());
out.printf(" [%s", move.from().toString());
out.printf(" -> %s", move.to().toString());
#ifdef DEBUG
fprintf(fp, ", %s", TypeChars[move.type()]);
out.printf(", %s", TypeChars[move.type()]);
#endif
fprintf(fp, "]");
out.printf("]");
if (i != numMoves() - 1)
fprintf(fp, ",");
out.printf(",");
}
}

View File

@ -702,11 +702,11 @@ class LNode
return false;
}
virtual void dump(FILE* fp);
virtual void dump(GenericPrinter& out);
void dump();
static void printName(FILE* fp, Opcode op);
virtual void printName(FILE* fp);
virtual void printOperands(FILE* fp);
static void printName(GenericPrinter& out, Opcode op);
virtual void printName(GenericPrinter& out);
virtual void printOperands(GenericPrinter& out);
public:
// Opcode testing and casts.
@ -986,7 +986,7 @@ class LBlock
return begin()->isGoto() && !mir()->isLoopHeader();
}
void dump(FILE* fp);
void dump(GenericPrinter& out);
void dump();
};
@ -1799,7 +1799,7 @@ class LIRGraph
return safepoints_[i];
}
void dump(FILE* fp);
void dump(GenericPrinter& out);
void dump();
};

View File

@ -4181,27 +4181,28 @@ LIRGenerator::visitNurseryObject(MNurseryObject* ins)
static void
SpewResumePoint(MBasicBlock* block, MInstruction* ins, MResumePoint* resumePoint)
{
fprintf(JitSpewFile, "Current resume point %p details:\n", (void*)resumePoint);
fprintf(JitSpewFile, " frame count: %u\n", resumePoint->frameCount());
Fprinter& out = JitSpewPrinter();
out.printf("Current resume point %p details:\n", (void*)resumePoint);
out.printf(" frame count: %u\n", resumePoint->frameCount());
if (ins) {
fprintf(JitSpewFile, " taken after: ");
ins->printName(JitSpewFile);
out.printf(" taken after: ");
ins->printName(out);
} else {
fprintf(JitSpewFile, " taken at block %d entry", block->id());
out.printf(" taken at block %d entry", block->id());
}
fprintf(JitSpewFile, "\n");
out.printf("\n");
fprintf(JitSpewFile, " pc: %p (script: %p, offset: %d)\n",
out.printf(" pc: %p (script: %p, offset: %d)\n",
(void*)resumePoint->pc(),
(void*)resumePoint->block()->info().script(),
int(resumePoint->block()->info().script()->pcToOffset(resumePoint->pc())));
for (size_t i = 0, e = resumePoint->numOperands(); i < e; i++) {
MDefinition* in = resumePoint->getOperand(i);
fprintf(JitSpewFile, " slot%u: ", (unsigned)i);
in->printName(JitSpewFile);
fprintf(JitSpewFile, "\n");
out.printf(" slot%u: ", (unsigned)i);
in->printName(out);
out.printf("\n");
}
}

View File

@ -61,7 +61,7 @@ CheckUsesAreFloat32Consumers(MInstruction* ins)
}
void
MDefinition::PrintOpcodeName(FILE* fp, MDefinition::Opcode op)
MDefinition::PrintOpcodeName(GenericPrinter& out, MDefinition::Opcode op)
{
static const char * const names[] =
{
@ -72,7 +72,7 @@ MDefinition::PrintOpcodeName(FILE* fp, MDefinition::Opcode op)
const char* name = names[op];
size_t len = strlen(name);
for (size_t i = 0; i < len; i++)
fprintf(fp, "%c", tolower(name[i]));
out.printf("%c", tolower(name[i]));
}
const Value&
@ -209,10 +209,10 @@ EvaluateExactReciprocal(TempAllocator& alloc, MDiv* ins)
}
void
MDefinition::printName(FILE* fp) const
MDefinition::printName(GenericPrinter& out) const
{
PrintOpcodeName(fp, op());
fprintf(fp, "%u", id());
PrintOpcodeName(out, op());
out.printf("%u", id());
}
HashNumber
@ -439,40 +439,42 @@ MTest::filtersUndefinedOrNull(bool trueBranch, MDefinition** subject, bool* filt
}
void
MDefinition::printOpcode(FILE* fp) const
MDefinition::printOpcode(GenericPrinter& out) const
{
PrintOpcodeName(fp, op());
PrintOpcodeName(out, op());
for (size_t j = 0, e = numOperands(); j < e; j++) {
fprintf(fp, " ");
out.printf(" ");
if (getUseFor(j)->hasProducer())
getOperand(j)->printName(fp);
getOperand(j)->printName(out);
else
fprintf(fp, "(null)");
out.printf("(null)");
}
}
void
MDefinition::dump(FILE* fp) const
MDefinition::dump(GenericPrinter& out) const
{
printName(fp);
fprintf(fp, " = ");
printOpcode(fp);
fprintf(fp, "\n");
printName(out);
out.printf(" = ");
printOpcode(out);
out.printf("\n");
if (isInstruction()) {
if (MResumePoint* resume = toInstruction()->resumePoint())
resume->dump(fp);
resume->dump(out);
}
}
void
MDefinition::dump() const
{
dump(stderr);
Fprinter out(stderr);
dump(out);
out.finish();
}
void
MDefinition::dumpLocation(FILE* fp) const
MDefinition::dumpLocation(GenericPrinter& out) const
{
MResumePoint* rp = nullptr;
const char* linkWord = nullptr;
@ -487,7 +489,7 @@ MDefinition::dumpLocation(FILE* fp) const
while (rp) {
JSScript* script = rp->block()->info().script();
uint32_t lineno = PCToLineNumber(rp->block()->info().script(), rp->pc());
fprintf(fp, " %s %s:%d\n", linkWord, script->filename(), lineno);
out.printf(" %s %s:%d\n", linkWord, script->filename(), lineno);
rp = rp->caller();
linkWord = "in";
}
@ -496,7 +498,9 @@ MDefinition::dumpLocation(FILE* fp) const
void
MDefinition::dumpLocation() const
{
dumpLocation(stderr);
Fprinter out(stderr);
dumpLocation(out);
out.finish();
}
#ifdef DEBUG
@ -753,72 +757,72 @@ MConstant::congruentTo(const MDefinition* ins) const
}
void
MConstant::printOpcode(FILE* fp) const
MConstant::printOpcode(GenericPrinter& out) const
{
PrintOpcodeName(fp, op());
fprintf(fp, " ");
PrintOpcodeName(out, op());
out.printf(" ");
switch (type()) {
case MIRType_Undefined:
fprintf(fp, "undefined");
out.printf("undefined");
break;
case MIRType_Null:
fprintf(fp, "null");
out.printf("null");
break;
case MIRType_Boolean:
fprintf(fp, value().toBoolean() ? "true" : "false");
out.printf(value().toBoolean() ? "true" : "false");
break;
case MIRType_Int32:
fprintf(fp, "0x%x", value().toInt32());
out.printf("0x%x", value().toInt32());
break;
case MIRType_Double:
fprintf(fp, "%f", value().toDouble());
out.printf("%f", value().toDouble());
break;
case MIRType_Float32:
{
float val = value().toDouble();
fprintf(fp, "%f", val);
out.printf("%f", val);
break;
}
case MIRType_Object:
if (value().toObject().is<JSFunction>()) {
JSFunction* fun = &value().toObject().as<JSFunction>();
if (fun->displayAtom()) {
fputs("function ", fp);
FileEscapedString(fp, fun->displayAtom(), 0);
out.put("function ");
EscapedStringPrinter(out, fun->displayAtom(), 0);
} else {
fputs("unnamed function", fp);
out.put("unnamed function");
}
if (fun->hasScript()) {
JSScript* script = fun->nonLazyScript();
fprintf(fp, " (%s:%" PRIuSIZE ")",
out.printf(" (%s:%" PRIuSIZE ")",
script->filename() ? script->filename() : "", script->lineno());
}
fprintf(fp, " at %p", (void*) fun);
out.printf(" at %p", (void*) fun);
break;
}
fprintf(fp, "object %p (%s)", (void*)&value().toObject(),
out.printf("object %p (%s)", (void*)&value().toObject(),
value().toObject().getClass()->name);
break;
case MIRType_Symbol:
fprintf(fp, "symbol at %p", (void*)value().toSymbol());
out.printf("symbol at %p", (void*)value().toSymbol());
break;
case MIRType_String:
fprintf(fp, "string %p", (void*)value().toString());
out.printf("string %p", (void*)value().toString());
break;
case MIRType_MagicOptimizedArguments:
fprintf(fp, "magic lazyargs");
out.printf("magic lazyargs");
break;
case MIRType_MagicHole:
fprintf(fp, "magic hole");
out.printf("magic hole");
break;
case MIRType_MagicIsConstructing:
fprintf(fp, "magic is-constructing");
out.printf("magic is-constructing");
break;
case MIRType_MagicOptimizedOut:
fprintf(fp, "magic optimized-out");
out.printf("magic optimized-out");
break;
case MIRType_MagicUninitializedLexical:
fprintf(fp, "magic uninitialized-lexical");
out.printf("magic uninitialized-lexical");
break;
default:
MOZ_CRASH("unexpected type");
@ -1001,43 +1005,43 @@ MSimdGeneralShuffle::foldsTo(TempAllocator& alloc)
template <typename T>
static void
PrintOpcodeOperation(T* mir, FILE* fp)
PrintOpcodeOperation(T* mir, GenericPrinter& out)
{
mir->MDefinition::printOpcode(fp);
fprintf(fp, " (%s)", T::OperationName(mir->operation()));
mir->MDefinition::printOpcode(out);
out.printf(" (%s)", T::OperationName(mir->operation()));
}
void
MSimdBinaryArith::printOpcode(FILE* fp) const
MSimdBinaryArith::printOpcode(GenericPrinter& out) const
{
PrintOpcodeOperation(this, fp);
PrintOpcodeOperation(this, out);
}
void
MSimdBinaryBitwise::printOpcode(FILE* fp) const
MSimdBinaryBitwise::printOpcode(GenericPrinter& out) const
{
PrintOpcodeOperation(this, fp);
PrintOpcodeOperation(this, out);
}
void
MSimdUnaryArith::printOpcode(FILE* fp) const
MSimdUnaryArith::printOpcode(GenericPrinter& out) const
{
PrintOpcodeOperation(this, fp);
PrintOpcodeOperation(this, out);
}
void
MSimdBinaryComp::printOpcode(FILE* fp) const
MSimdBinaryComp::printOpcode(GenericPrinter& out) const
{
PrintOpcodeOperation(this, fp);
PrintOpcodeOperation(this, out);
}
void
MSimdShift::printOpcode(FILE* fp) const
MSimdShift::printOpcode(GenericPrinter& out) const
{
PrintOpcodeOperation(this, fp);
PrintOpcodeOperation(this, out);
}
void
MSimdInsertElement::printOpcode(FILE* fp) const
MSimdInsertElement::printOpcode(GenericPrinter& out) const
{
MDefinition::printOpcode(fp);
fprintf(fp, " (%s)", MSimdInsertElement::LaneName(lane()));
MDefinition::printOpcode(out);
out.printf(" (%s)", MSimdInsertElement::LaneName(lane()));
}
MCloneLiteral*
@ -1047,42 +1051,42 @@ MCloneLiteral::New(TempAllocator& alloc, MDefinition* obj)
}
void
MControlInstruction::printOpcode(FILE* fp) const
MControlInstruction::printOpcode(GenericPrinter& out) const
{
MDefinition::printOpcode(fp);
MDefinition::printOpcode(out);
for (size_t j = 0; j < numSuccessors(); j++)
fprintf(fp, " block%u", getSuccessor(j)->id());
out.printf(" block%u", getSuccessor(j)->id());
}
void
MCompare::printOpcode(FILE* fp) const
MCompare::printOpcode(GenericPrinter& out) const
{
MDefinition::printOpcode(fp);
fprintf(fp, " %s", js_CodeName[jsop()]);
MDefinition::printOpcode(out);
out.printf(" %s", js_CodeName[jsop()]);
}
void
MConstantElements::printOpcode(FILE* fp) const
MConstantElements::printOpcode(GenericPrinter& out) const
{
PrintOpcodeName(fp, op());
fprintf(fp, " %p", value());
PrintOpcodeName(out, op());
out.printf(" %p", value());
}
void
MLoadUnboxedScalar::printOpcode(FILE* fp) const
MLoadUnboxedScalar::printOpcode(GenericPrinter& out) const
{
MDefinition::printOpcode(fp);
fprintf(fp, " %s", ScalarTypeDescr::typeName(indexType()));
MDefinition::printOpcode(out);
out.printf(" %s", ScalarTypeDescr::typeName(indexType()));
}
void
MAssertRange::printOpcode(FILE* fp) const
MAssertRange::printOpcode(GenericPrinter& out) const
{
MDefinition::printOpcode(fp);
MDefinition::printOpcode(out);
Sprinter sp(GetJitContext()->cx);
sp.init();
assertedRange()->print(sp);
fprintf(fp, " %s", sp.string());
assertedRange()->dump(sp);
out.printf(" %s", sp.string());
}
const char*
@ -1119,10 +1123,10 @@ MMathFunction::FunctionName(Function function)
}
void
MMathFunction::printOpcode(FILE* fp) const
MMathFunction::printOpcode(GenericPrinter& out) const
{
MDefinition::printOpcode(fp);
fprintf(fp, " %s", FunctionName(function()));
MDefinition::printOpcode(out);
out.printf(" %s", FunctionName(function()));
}
MDefinition*
@ -1227,13 +1231,13 @@ MParameter::New(TempAllocator& alloc, int32_t index, TemporaryTypeSet* types)
}
void
MParameter::printOpcode(FILE* fp) const
MParameter::printOpcode(GenericPrinter& out) const
{
PrintOpcodeName(fp, op());
PrintOpcodeName(out, op());
if (index() == THIS_SLOT)
fprintf(fp, " THIS_SLOT");
out.printf(" THIS_SLOT");
else
fprintf(fp, " %d", index());
out.printf(" %d", index());
}
HashNumber
@ -1485,37 +1489,37 @@ MGoto::New(TempAllocator& alloc, MBasicBlock* target)
}
void
MUnbox::printOpcode(FILE* fp) const
MUnbox::printOpcode(GenericPrinter& out) const
{
PrintOpcodeName(fp, op());
fprintf(fp, " ");
getOperand(0)->printName(fp);
fprintf(fp, " ");
PrintOpcodeName(out, op());
out.printf(" ");
getOperand(0)->printName(out);
out.printf(" ");
switch (type()) {
case MIRType_Int32: fprintf(fp, "to Int32"); break;
case MIRType_Double: fprintf(fp, "to Double"); break;
case MIRType_Boolean: fprintf(fp, "to Boolean"); break;
case MIRType_String: fprintf(fp, "to String"); break;
case MIRType_Symbol: fprintf(fp, "to Symbol"); break;
case MIRType_Object: fprintf(fp, "to Object"); break;
case MIRType_Int32: out.printf("to Int32"); break;
case MIRType_Double: out.printf("to Double"); break;
case MIRType_Boolean: out.printf("to Boolean"); break;
case MIRType_String: out.printf("to String"); break;
case MIRType_Symbol: out.printf("to Symbol"); break;
case MIRType_Object: out.printf("to Object"); break;
default: break;
}
switch (mode()) {
case Fallible: fprintf(fp, " (fallible)"); break;
case Infallible: fprintf(fp, " (infallible)"); break;
case TypeBarrier: fprintf(fp, " (typebarrier)"); break;
case Fallible: out.printf(" (fallible)"); break;
case Infallible: out.printf(" (infallible)"); break;
case TypeBarrier: out.printf(" (typebarrier)"); break;
default: break;
}
}
void
MTypeBarrier::printOpcode(FILE* fp) const
MTypeBarrier::printOpcode(GenericPrinter& out) const
{
PrintOpcodeName(fp, op());
fprintf(fp, " ");
getOperand(0)->printName(fp);
PrintOpcodeName(out, op());
out.printf(" ");
getOperand(0)->printName(out);
}
bool
@ -3225,39 +3229,41 @@ MResumePoint::addStore(TempAllocator& alloc, MDefinition* store, const MResumePo
}
void
MResumePoint::dump(FILE* fp) const
MResumePoint::dump(GenericPrinter& out) const
{
fprintf(fp, "resumepoint mode=");
out.printf("resumepoint mode=");
switch (mode()) {
case MResumePoint::ResumeAt:
fprintf(fp, "At");
out.printf("At");
break;
case MResumePoint::ResumeAfter:
fprintf(fp, "After");
out.printf("After");
break;
case MResumePoint::Outer:
fprintf(fp, "Outer");
out.printf("Outer");
break;
}
if (MResumePoint* c = caller())
fprintf(fp, " (caller in block%u)", c->block()->id());
out.printf(" (caller in block%u)", c->block()->id());
for (size_t i = 0; i < numOperands(); i++) {
fprintf(fp, " ");
out.printf(" ");
if (operands_[i].hasProducer())
getOperand(i)->printName(fp);
getOperand(i)->printName(out);
else
fprintf(fp, "(null)");
out.printf("(null)");
}
fprintf(fp, "\n");
out.printf("\n");
}
void
MResumePoint::dump() const
{
dump(stderr);
Fprinter out(stderr);
dump(out);
out.finish();
}
bool
@ -3900,18 +3906,12 @@ MNot::trySpecializeFloat32(TempAllocator& alloc)
}
void
MBeta::printOpcode(FILE* fp) const
MBeta::printOpcode(GenericPrinter& out) const
{
MDefinition::printOpcode(fp);
MDefinition::printOpcode(out);
if (JitContext* context = MaybeGetJitContext()) {
Sprinter sp(context->cx);
sp.init();
comparison_->print(sp);
fprintf(fp, " %s", sp.string());
} else {
fprintf(fp, " ???");
}
out.printf(" ");
comparison_->dump(out);
}
bool

View File

@ -281,7 +281,7 @@ class MNode : public TempObject
virtual bool writeRecoverData(CompactBufferWriter& writer) const;
virtual void dump(FILE* fp) const = 0;
virtual void dump(GenericPrinter& out) const = 0;
virtual void dump() const = 0;
protected:
@ -448,12 +448,12 @@ class MDefinition : public MNode
virtual const char* opName() const = 0;
virtual void accept(MDefinitionVisitor* visitor) = 0;
void printName(FILE* fp) const;
static void PrintOpcodeName(FILE* fp, Opcode op);
virtual void printOpcode(FILE* fp) const;
void dump(FILE* fp) const override;
void printName(GenericPrinter& out) const;
static void PrintOpcodeName(GenericPrinter& out, Opcode op);
virtual void printOpcode(GenericPrinter& out) const;
void dump(GenericPrinter& out) const override;
void dump() const override;
void dumpLocation(FILE* fp) const;
void dumpLocation(GenericPrinter& out) const;
void dumpLocation() const;
// For LICM.
@ -1334,7 +1334,7 @@ class MConstant : public MNullaryInstruction
return ToBoolean(HandleValue::fromMarkedLocation(&value_));
}
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
HashNumber valueHash() const override;
bool congruentTo(const MDefinition* ins) const override;
@ -1725,7 +1725,7 @@ class MSimdInsertElement
return binaryCongruentTo(ins) && lane_ == ins->toSimdInsertElement()->lane();
}
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
ALLOW_CLONE(MSimdInsertElement)
};
@ -2051,7 +2051,7 @@ class MSimdUnaryArith
return congruentIfOperandsEqual(ins) && ins->toSimdUnaryArith()->operation() == operation();
}
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
ALLOW_CLONE(MSimdUnaryArith);
};
@ -2138,7 +2138,7 @@ class MSimdBinaryComp
operation_ == other->operation();
}
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
ALLOW_CLONE(MSimdBinaryComp)
};
@ -2207,7 +2207,7 @@ class MSimdBinaryArith
return operation_ == ins->toSimdBinaryArith()->operation();
}
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
ALLOW_CLONE(MSimdBinaryArith)
};
@ -2272,7 +2272,7 @@ class MSimdBinaryBitwise
return operation_ == ins->toSimdBinaryBitwise()->operation();
}
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
ALLOW_CLONE(MSimdBinaryBitwise)
};
@ -2329,7 +2329,7 @@ class MSimdShift
MOZ_CRASH("unexpected operation");
}
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
bool congruentTo(const MDefinition* ins) const override {
if (!binaryCongruentTo(ins))
@ -2432,7 +2432,7 @@ class MParameter : public MNullaryInstruction
int32_t index() const {
return index_;
}
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
HashNumber valueHash() const override;
bool congruentTo(const MDefinition* ins) const override;
@ -2498,7 +2498,7 @@ class MControlInstruction : public MInstruction
return true;
}
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
};
class MTableSwitch final
@ -4268,7 +4268,7 @@ class MCompare
return AliasSet::None();
}
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
void collectRangeInfoPreTrunc() override;
void trySpecializeFloat32(TempAllocator& alloc) override;
@ -4447,7 +4447,7 @@ class MUnbox final : public MUnaryInstruction, public BoxInputsPolicy::Data
AliasSet getAliasSet() const override {
return AliasSet::None();
}
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
void makeInfallible() {
// Should only be called if we're already Infallible or TypeBarrier
MOZ_ASSERT(mode() != Fallible);
@ -4559,7 +4559,7 @@ class MAssertRange
return AliasSet::None();
}
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
};
// Caller-side allocation of |this| for |new|:
@ -6093,7 +6093,7 @@ class MMathFunction
MDefinition* foldsTo(TempAllocator& alloc) override;
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
static const char* FunctionName(Function function);
@ -6913,7 +6913,7 @@ class MBeta
public:
INSTRUCTION_HEADER(Beta)
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
static MBeta* New(TempAllocator& alloc, MDefinition* val, const Range* comp)
{
return new(alloc) MBeta(val, comp);
@ -7664,7 +7664,7 @@ class MConstantElements : public MNullaryInstruction
return value_;
}
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
HashNumber valueHash() const override {
return (HashNumber)(size_t) value_;
@ -9303,7 +9303,7 @@ class MLoadUnboxedScalar
return congruentIfOperandsEqual(other);
}
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
void computeRange(TempAllocator& alloc) override;
@ -12119,7 +12119,7 @@ class MTypeBarrier
return new(alloc) MTypeBarrier(def, types, kind);
}
void printOpcode(FILE* fp) const override;
void printOpcode(GenericPrinter& out) const override;
bool congruentTo(const MDefinition* def) const override;
AliasSet getAliasSet() const override {
@ -12505,7 +12505,7 @@ class MResumePoint final :
return stores_.end();
}
virtual void dump(FILE* fp) const override;
virtual void dump(GenericPrinter& out) const override;
virtual void dump() const override;
};

View File

@ -1516,19 +1516,6 @@ MBasicBlock::specializePhis()
return true;
}
void
MBasicBlock::dumpStack(FILE* fp)
{
#ifdef DEBUG
fprintf(fp, " %-3s %-16s %-6s %-10s\n", "#", "name", "copyOf", "first/next");
fprintf(fp, "-------------------------------------------\n");
for (uint32_t i = 0; i < stackPosition_; i++) {
fprintf(fp, " %-3d", i);
fprintf(fp, " %-16p\n", (void*)slots_[i]);
}
#endif
}
MTest*
MBasicBlock::immediateDominatorBranch(BranchDirection* pdirection)
{
@ -1558,12 +1545,33 @@ MBasicBlock::immediateDominatorBranch(BranchDirection* pdirection)
}
void
MIRGraph::dump(FILE* fp)
MBasicBlock::dumpStack(GenericPrinter& out)
{
#ifdef DEBUG
out.printf(" %-3s %-16s %-6s %-10s\n", "#", "name", "copyOf", "first/next");
out.printf("-------------------------------------------\n");
for (uint32_t i = 0; i < stackPosition_; i++) {
out.printf(" %-3d", i);
out.printf(" %-16p\n", (void*)slots_[i]);
}
#endif
}
void
MBasicBlock::dumpStack()
{
Fprinter out(stderr);
dumpStack(out);
out.finish();
}
void
MIRGraph::dump(GenericPrinter& out)
{
#ifdef DEBUG
for (MBasicBlockIterator iter(begin()); iter != end(); iter++) {
iter->dump(fp);
fprintf(fp, "\n");
iter->dump(out);
out.printf("\n");
}
#endif
}
@ -1571,31 +1579,32 @@ MIRGraph::dump(FILE* fp)
void
MIRGraph::dump()
{
dump(stderr);
Fprinter out(stderr);
dump(out);
out.finish();
}
void
MBasicBlock::dump(FILE* fp)
MBasicBlock::dump(GenericPrinter& out)
{
#ifdef DEBUG
fprintf(fp, "block%u:%s%s%s\n", id(),
isLoopHeader() ? " (loop header)" : "",
unreachable() ? " (unreachable)" : "",
isMarked() ? " (marked)" : "");
if (MResumePoint* resume = entryResumePoint()) {
resume->dump();
}
for (MPhiIterator iter(phisBegin()); iter != phisEnd(); iter++) {
iter->dump(fp);
}
for (MInstructionIterator iter(begin()); iter != end(); iter++) {
iter->dump(fp);
}
out.printf("block%u:%s%s%s\n", id(),
isLoopHeader() ? " (loop header)" : "",
unreachable() ? " (unreachable)" : "",
isMarked() ? " (marked)" : "");
if (MResumePoint* resume = entryResumePoint())
resume->dump(out);
for (MPhiIterator iter(phisBegin()); iter != phisEnd(); iter++)
iter->dump(out);
for (MInstructionIterator iter(begin()); iter != end(); iter++)
iter->dump(out);
#endif
}
void
MBasicBlock::dump()
{
dump(stderr);
Fprinter out(stderr);
dump(out);
out.finish();
}

View File

@ -599,9 +599,10 @@ class MBasicBlock : public TempObject, public InlineListNode<MBasicBlock>
return info_.script()->strict();
}
void dumpStack(FILE* fp);
void dumpStack(GenericPrinter& out);
void dumpStack();
void dump(FILE* fp);
void dump(GenericPrinter& out);
void dump();
// Track bailouts by storing the current pc in MIR instruction added at
@ -809,7 +810,7 @@ class MIRGraph
hasTryBlock_ = true;
}
void dump(FILE* fp);
void dump(GenericPrinter& out);
void dump();
};

View File

@ -115,9 +115,10 @@ SpewRange(MDefinition* def)
#ifdef DEBUG
if (JitSpewEnabled(JitSpew_Range) && def->type() != MIRType_None && def->range()) {
JitSpewHeader(JitSpew_Range);
def->printName(JitSpewFile);
fprintf(JitSpewFile, " has range ");
def->range()->dump(JitSpewFile);
Fprinter& out = JitSpewPrinter();
def->printName(out);
out.printf(" has range ");
def->range()->dump(out);
}
#endif
}
@ -281,8 +282,9 @@ RangeAnalysis::addBetaNodes()
if (JitSpewEnabled(JitSpew_Range)) {
JitSpewHeader(JitSpew_Range);
fprintf(JitSpewFile, "Adding beta node for %d with range ", val->id());
comp.dump(JitSpewFile);
Fprinter& out = JitSpewPrinter();
out.printf("Adding beta node for %d with range ", val->id());
comp.dump(out);
}
MBeta* beta = MBeta::New(alloc(), val, new(alloc()) Range(comp));
@ -320,20 +322,20 @@ RangeAnalysis::removeBetaNodes()
}
void
SymbolicBound::print(Sprinter& sp) const
SymbolicBound::dump(GenericPrinter& out) const
{
if (loop)
sp.printf("[loop] ");
sum.print(sp);
out.printf("[loop] ");
sum.dump(out);
}
void
SymbolicBound::dump() const
{
Sprinter sp(GetJitContext()->cx);
sp.init();
print(sp);
fprintf(stderr, "%s\n", sp.string());
Fprinter out(stderr);
dump(out);
out.printf("\n");
out.finish();
}
// Test whether the given range's exponent tells us anything that its lower
@ -356,41 +358,41 @@ IsExponentInteresting(const Range* r)
}
void
Range::print(Sprinter& sp) const
Range::dump(GenericPrinter& out) const
{
assertInvariants();
// Floating-point or Integer subset.
if (canHaveFractionalPart_)
sp.printf("F");
out.printf("F");
else
sp.printf("I");
out.printf("I");
sp.printf("[");
out.printf("[");
if (!hasInt32LowerBound_)
sp.printf("?");
out.printf("?");
else
sp.printf("%d", lower_);
out.printf("%d", lower_);
if (symbolicLower_) {
sp.printf(" {");
symbolicLower_->print(sp);
sp.printf("}");
out.printf(" {");
symbolicLower_->dump(out);
out.printf("}");
}
sp.printf(", ");
out.printf(", ");
if (!hasInt32UpperBound_)
sp.printf("?");
out.printf("?");
else
sp.printf("%d", upper_);
out.printf("%d", upper_);
if (symbolicUpper_) {
sp.printf(" {");
symbolicUpper_->print(sp);
sp.printf("}");
out.printf(" {");
symbolicUpper_->dump(out);
out.printf("}");
}
sp.printf("]");
out.printf("]");
bool includesNaN = max_exponent_ == IncludesInfinityAndNaN;
bool includesNegativeInfinity = max_exponent_ >= IncludesInfinity && !hasInt32LowerBound_;
@ -402,55 +404,49 @@ Range::print(Sprinter& sp) const
includesPositiveInfinity ||
includesNegativeZero)
{
sp.printf(" (");
out.printf(" (");
bool first = true;
if (includesNaN) {
if (first)
first = false;
else
sp.printf(" ");
sp.printf("U NaN");
out.printf(" ");
out.printf("U NaN");
}
if (includesNegativeInfinity) {
if (first)
first = false;
else
sp.printf(" ");
sp.printf("U -Infinity");
out.printf(" ");
out.printf("U -Infinity");
}
if (includesPositiveInfinity) {
if (first)
first = false;
else
sp.printf(" ");
sp.printf("U Infinity");
out.printf(" ");
out.printf("U Infinity");
}
if (includesNegativeZero) {
if (first)
first = false;
else
sp.printf(" ");
sp.printf("U -0");
out.printf(" ");
out.printf("U -0");
}
sp.printf(")");
out.printf(")");
}
if (max_exponent_ < IncludesInfinity && IsExponentInteresting(this))
sp.printf(" (< pow(2, %d+1))", max_exponent_);
}
void
Range::dump(FILE* fp) const
{
Sprinter sp(GetJitContext()->cx);
sp.init();
print(sp);
fprintf(fp, "%s\n", sp.string());
out.printf(" (< pow(2, %d+1))", max_exponent_);
}
void
Range::dump() const
{
dump(stderr);
Fprinter out(stderr);
dump(out);
out.printf("\n");
out.finish();
}
Range*
@ -1871,7 +1867,7 @@ RangeAnalysis::analyzeLoop(MBasicBlock* header)
if (JitSpewEnabled(JitSpew_Range)) {
Sprinter sp(GetJitContext()->cx);
sp.init();
iterationBound->boundSum.print(sp);
iterationBound->boundSum.dump(sp);
JitSpew(JitSpew_Range, "computed symbolic bound on backedges: %s",
sp.string());
}

View File

@ -81,7 +81,7 @@ struct SymbolicBound : public TempObject
// Computed symbolic bound, see above.
LinearSum sum;
void print(Sprinter& sp) const;
void dump(GenericPrinter& out) const;
void dump() const;
};
@ -450,8 +450,7 @@ class Range : public TempObject {
return r;
}
void print(Sprinter& sp) const;
void dump(FILE* fp) const;
void dump(GenericPrinter& out) const;
void dump() const;
bool update(const Range* other);

View File

@ -205,12 +205,13 @@ SafepointWriter::writeValueSlots(LSafepoint* safepoint)
static void
DumpNunboxPart(const LAllocation& a)
{
Fprinter& out = JitSpewPrinter();
if (a.isStackSlot()) {
fprintf(JitSpewFile, "stack %d", a.toStackSlot()->slot());
out.printf("stack %d", a.toStackSlot()->slot());
} else if (a.isArgument()) {
fprintf(JitSpewFile, "arg %d", a.toArgument()->index());
out.printf("arg %d", a.toArgument()->index());
} else {
fprintf(JitSpewFile, "reg %s", a.toGeneralReg()->reg().name());
out.printf("reg %s", a.toGeneralReg()->reg().name());
}
}
#endif // DEBUG
@ -295,11 +296,12 @@ SafepointWriter::writeNunboxParts(LSafepoint* safepoint)
if (entry.type.isUse() || entry.payload.isUse())
continue;
JitSpewHeader(JitSpew_Safepoints);
fprintf(JitSpewFile, " nunbox (type in ");
Fprinter& out = JitSpewPrinter();
out.printf(" nunbox (type in ");
DumpNunboxPart(entry.type);
fprintf(JitSpewFile, ", payload in ");
out.printf(", payload in ");
DumpNunboxPart(entry.payload);
fprintf(JitSpewFile, ")\n");
out.printf(")\n");
}
}
# endif

View File

@ -16,6 +16,8 @@
#include "jit/MIR.h"
#include "jit/Recover.h"
#include "vm/Printer.h"
using namespace js;
using namespace js::jit;
@ -419,43 +421,43 @@ ValTypeToString(JSValueType type)
}
void
RValueAllocation::dumpPayload(FILE* fp, PayloadType type, Payload p)
RValueAllocation::dumpPayload(GenericPrinter& out, PayloadType type, Payload p)
{
switch (type) {
case PAYLOAD_NONE:
break;
case PAYLOAD_INDEX:
fprintf(fp, "index %u", p.index);
out.printf("index %u", p.index);
break;
case PAYLOAD_STACK_OFFSET:
fprintf(fp, "stack %d", p.stackOffset);
out.printf("stack %d", p.stackOffset);
break;
case PAYLOAD_GPR:
fprintf(fp, "reg %s", p.gpr.name());
out.printf("reg %s", p.gpr.name());
break;
case PAYLOAD_FPU:
fprintf(fp, "reg %s", p.fpu.name());
out.printf("reg %s", p.fpu.name());
break;
case PAYLOAD_PACKED_TAG:
fprintf(fp, "%s", ValTypeToString(p.type));
out.printf("%s", ValTypeToString(p.type));
break;
}
}
void
RValueAllocation::dump(FILE* fp) const
RValueAllocation::dump(GenericPrinter& out) const
{
const Layout& layout = layoutFromMode(mode());
fprintf(fp, "%s", layout.name);
out.printf("%s", layout.name);
if (layout.type1 != PAYLOAD_NONE)
fprintf(fp, " (");
dumpPayload(fp, layout.type1, arg1_);
out.printf(" (");
dumpPayload(out, layout.type1, arg1_);
if (layout.type2 != PAYLOAD_NONE)
fprintf(fp, ", ");
dumpPayload(fp, layout.type2, arg2_);
out.printf(", ");
dumpPayload(out, layout.type2, arg2_);
if (layout.type1 != PAYLOAD_NONE)
fprintf(fp, ")");
out.printf(")");
}
bool
@ -548,12 +550,13 @@ SnapshotReader::spewBailingFrom() const
{
if (JitSpewEnabled(JitSpew_IonBailouts)) {
JitSpewHeader(JitSpew_IonBailouts);
fprintf(JitSpewFile, " bailing from bytecode: %s, MIR: ", js_CodeName[pcOpcode_]);
MDefinition::PrintOpcodeName(JitSpewFile, MDefinition::Opcode(mirOpcode_));
fprintf(JitSpewFile, " [%u], LIR: ", mirId_);
LInstruction::printName(JitSpewFile, LInstruction::Opcode(lirOpcode_));
fprintf(JitSpewFile, " [%u]", lirId_);
fprintf(JitSpewFile, "\n");
Fprinter& out = JitSpewPrinter();
out.printf(" bailing from bytecode: %s, MIR: ", js_CodeName[pcOpcode_]);
MDefinition::PrintOpcodeName(out, MDefinition::Opcode(mirOpcode_));
out.printf(" [%u], LIR: ", mirId_);
LInstruction::printName(out, LInstruction::Opcode(lirOpcode_));
out.printf(" [%u]", lirId_);
out.printf("\n");
}
}
#endif
@ -666,9 +669,10 @@ SnapshotWriter::add(const RValueAllocation& alloc)
if (JitSpewEnabled(JitSpew_IonSnapshots)) {
JitSpewHeader(JitSpew_IonSnapshots);
fprintf(JitSpewFile, " slot %u (%d): ", allocWritten_, offset);
alloc.dump(JitSpewFile);
fprintf(JitSpewFile, "\n");
Fprinter& out = JitSpewPrinter();
out.printf(" slot %u (%d): ", allocWritten_, offset);
alloc.dump(out);
out.printf("\n");
}
allocWritten_++;

View File

@ -19,6 +19,8 @@
#include "js/HashTable.h"
namespace js {
class GenericPrinter;
namespace jit {
class RValueAllocation;
@ -165,7 +167,7 @@ class RValueAllocation
static void writePayload(CompactBufferWriter& writer, PayloadType t,
Payload p);
static void writePadding(CompactBufferWriter& writer);
static void dumpPayload(FILE* fp, PayloadType t, Payload p);
static void dumpPayload(GenericPrinter& out, PayloadType t, Payload p);
static bool equalPayloads(PayloadType t, Payload lhs, Payload rhs);
RValueAllocation(Mode mode, Payload a1, Payload a2)
@ -334,7 +336,7 @@ class RValueAllocation
}
public:
void dump(FILE* fp) const;
void dump(GenericPrinter& out) const;
public:
bool operator==(const RValueAllocation& rhs) const {

View File

@ -5046,19 +5046,19 @@ js::OneUcs4ToUtf8Char(uint8_t* utf8Buffer, uint32_t ucs4Char)
}
size_t
js::PutEscapedStringImpl(char* buffer, size_t bufferSize, FILE* fp, JSLinearString* str,
js::PutEscapedStringImpl(char* buffer, size_t bufferSize, GenericPrinter* out, JSLinearString* str,
uint32_t quote)
{
size_t len = str->length();
AutoCheckCannotGC nogc;
return str->hasLatin1Chars()
? PutEscapedStringImpl(buffer, bufferSize, fp, str->latin1Chars(nogc), len, quote)
: PutEscapedStringImpl(buffer, bufferSize, fp, str->twoByteChars(nogc), len, quote);
? PutEscapedStringImpl(buffer, bufferSize, out, str->latin1Chars(nogc), len, quote)
: PutEscapedStringImpl(buffer, bufferSize, out, str->twoByteChars(nogc), len, quote);
}
template <typename CharT>
size_t
js::PutEscapedStringImpl(char* buffer, size_t bufferSize, FILE* fp, const CharT* chars,
js::PutEscapedStringImpl(char* buffer, size_t bufferSize, GenericPrinter* out, const CharT* chars,
size_t length, uint32_t quote)
{
enum {
@ -5067,7 +5067,7 @@ js::PutEscapedStringImpl(char* buffer, size_t bufferSize, FILE* fp, const CharT*
MOZ_ASSERT(quote == 0 || quote == '\'' || quote == '"');
MOZ_ASSERT_IF(!buffer, bufferSize == 0);
MOZ_ASSERT_IF(fp, !buffer);
MOZ_ASSERT_IF(out, !buffer);
if (bufferSize == 0)
buffer = nullptr;
@ -5156,8 +5156,8 @@ js::PutEscapedStringImpl(char* buffer, size_t bufferSize, FILE* fp, const CharT*
buffer[n] = '\0';
buffer = nullptr;
}
} else if (fp) {
if (fputc(c, fp) < 0)
} else if (out) {
if (out->put(&c, 1) < 0)
return size_t(-1);
}
n++;
@ -5169,15 +5169,15 @@ js::PutEscapedStringImpl(char* buffer, size_t bufferSize, FILE* fp, const CharT*
}
template size_t
js::PutEscapedStringImpl(char* buffer, size_t bufferSize, FILE* fp, const Latin1Char* chars,
js::PutEscapedStringImpl(char* buffer, size_t bufferSize, GenericPrinter* out, const Latin1Char* chars,
size_t length, uint32_t quote);
template size_t
js::PutEscapedStringImpl(char* buffer, size_t bufferSize, FILE* fp, const char* chars,
js::PutEscapedStringImpl(char* buffer, size_t bufferSize, GenericPrinter* out, const char* chars,
size_t length, uint32_t quote);
template size_t
js::PutEscapedStringImpl(char* buffer, size_t bufferSize, FILE* fp, const char16_t* chars,
js::PutEscapedStringImpl(char* buffer, size_t bufferSize, GenericPrinter* out, const char16_t* chars,
size_t length, uint32_t quote);
template size_t

View File

@ -16,6 +16,7 @@
#include "gc/Rooting.h"
#include "js/RootingAPI.h"
#include "vm/Printer.h"
#include "vm/Unicode.h"
class JSAutoByteString;
@ -342,11 +343,12 @@ extern int
OneUcs4ToUtf8Char(uint8_t* utf8Buffer, uint32_t ucs4Char);
extern size_t
PutEscapedStringImpl(char* buffer, size_t size, FILE* fp, JSLinearString* str, uint32_t quote);
PutEscapedStringImpl(char* buffer, size_t size, GenericPrinter* out, JSLinearString* str,
uint32_t quote);
template <typename CharT>
extern size_t
PutEscapedStringImpl(char* buffer, size_t bufferSize, FILE* fp, const CharT* chars,
PutEscapedStringImpl(char* buffer, size_t bufferSize, GenericPrinter* out, const CharT* chars,
size_t length, uint32_t quote);
/*
@ -379,6 +381,18 @@ PutEscapedString(char* buffer, size_t bufferSize, const CharT* chars, size_t len
return n;
}
inline bool
EscapedStringPrinter(GenericPrinter& out, JSLinearString* str, uint32_t quote)
{
return PutEscapedStringImpl(nullptr, 0, &out, str, quote) != size_t(-1);
}
inline bool
EscapedStringPrinter(GenericPrinter& out, const char* chars, size_t length, uint32_t quote)
{
return PutEscapedStringImpl(nullptr, 0, &out, chars, length, quote) != size_t(-1);
}
/*
* Write str into file escaping any non-printable or non-ASCII character.
* If quote is not 0, it must be a single or double quote character that
@ -387,13 +401,19 @@ PutEscapedString(char* buffer, size_t bufferSize, const CharT* chars, size_t len
inline bool
FileEscapedString(FILE* fp, JSLinearString* str, uint32_t quote)
{
return PutEscapedStringImpl(nullptr, 0, fp, str, quote) != size_t(-1);
Fprinter out(fp);
bool res = EscapedStringPrinter(out, str, quote);
out.finish();
return res;
}
inline bool
FileEscapedString(FILE* fp, const char* chars, size_t length, uint32_t quote)
{
return PutEscapedStringImpl(nullptr, 0, fp, chars, length, quote) != size_t(-1);
Fprinter out(fp);
bool res = EscapedStringPrinter(out, chars, length, quote);
out.finish();
return res;
}
bool