Bug 1839396 part 13 - Convert GenericPrinter::put to be infallible. r=mgaudet

Remove the boolean returned value of printing functions of the GenericPrinter
and all descendant classes.

The goal being that error checking is the responsibility of the wrapping
function in charge of the GenericPrinter, and that functions in charge of
providing content should assume that everything is always written successfully.

This patch only look at the GenericPrinter methods, consumers of these functions
would be updated in subsequent patches.

Differential Revision: https://phabricator.services.mozilla.com/D181498
This commit is contained in:
Nicolas B. Pierron 2023-09-20 17:00:08 +00:00
Родитель f9ec219ed5
Коммит 13454e29f9
12 изменённых файлов: 304 добавлений и 600 удалений

Просмотреть файл

@ -35,27 +35,36 @@ class JS_PUBLIC_API GenericPrinter {
constexpr GenericPrinter() : hadOOM_(false) {}
public:
// 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) = 0;
inline bool put(const char* s) { return put(s, strlen(s)); }
inline bool putChar(const char c) { return put(&c, 1); }
// Puts |len| characters from |s| at the current position. This function might
// silently fail and the error can be tested using `hadOutOfMemory()`. Calling
// this function or any other printing functions after a failures is accepted,
// but the outcome would still remain incorrect and `hadOutOfMemory()` would
// still report any of the previous errors.
virtual void put(const char* s, size_t len) = 0;
inline void put(const char* s) { put(s, strlen(s)); }
inline void putChar(const char c) { put(&c, 1); }
virtual bool putAsciiPrintable(mozilla::Span<const JS::Latin1Char> str);
virtual bool putAsciiPrintable(mozilla::Span<const char16_t> str);
virtual void putAsciiPrintable(mozilla::Span<const JS::Latin1Char> str);
virtual void putAsciiPrintable(mozilla::Span<const char16_t> str);
inline bool putAsciiPrintable(const char c) {
inline void putAsciiPrintable(const char c) {
MOZ_ASSERT(IsAsciiPrintable(c));
return putChar(c);
putChar(c);
}
inline bool putAsciiPrintable(const char16_t c) {
inline void putAsciiPrintable(const char16_t c) {
MOZ_ASSERT(IsAsciiPrintable(c));
return putChar(char(c));
putChar(char(c));
}
// 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) MOZ_FORMAT_PRINTF(2, 0);
void printf(const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3);
void vprintf(const char* fmt, va_list ap) MOZ_FORMAT_PRINTF(2, 0);
virtual bool canPutFromIndex() const { return false; }
virtual void putFromIndex(size_t index, size_t length) {
MOZ_CRASH("Calls to putFromIndex should be guarded by canPutFromIndex.");
}
virtual size_t index() const { return 0; }
// In some printers, this ensure that the content is fully written.
virtual void flush() { /* Do nothing */
@ -123,15 +132,23 @@ class JS_PUBLIC_API Sprinter final : public GenericPrinter {
// 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;
virtual void put(const char* s, size_t len) override;
using GenericPrinter::put; // pick up |inline bool put(const char* s);|
virtual bool canPutFromIndex() const override { return true; }
virtual void putFromIndex(size_t index, size_t length) override {
MOZ_ASSERT(index <= this->index());
MOZ_ASSERT(index + length <= this->index());
put(base + index, length);
}
virtual size_t index() const override { return length(); }
// Format the given format/arguments as if by JS_vsmprintf, then put it.
// Return true on success, else return false and report an error (typically
// OOM).
[[nodiscard]] bool jsprintf(const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3);
void jsprintf(const char* fmt, ...) MOZ_FORMAT_PRINTF(2, 3);
bool putString(JSString* str);
void putString(JSString* str);
size_t length() const;
@ -167,7 +184,7 @@ class JS_PUBLIC_API Fprinter final : public GenericPrinter {
// 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;
virtual void put(const char* s, size_t len) override;
using GenericPrinter::put; // pick up |inline bool put(const char* s);|
};
@ -203,7 +220,7 @@ class JS_PUBLIC_API LSprinter final : public GenericPrinter {
// 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;
virtual void put(const char* s, size_t len) override;
using GenericPrinter::put; // pick up |inline bool put(const char* s);|
};

Просмотреть файл

@ -1729,12 +1729,11 @@ static bool DisassembleNative(JSContext* cx, unsigned argc, Value* vp) {
uint8_t* jit_end = nullptr;
if (fun->isAsmJSNative() || fun->isWasmWithJitEntry()) {
if (fun->isAsmJSNative() && !sprinter.jsprintf("; backend=asmjs\n")) {
return false;
}
if (!sprinter.jsprintf("; backend=wasm\n")) {
if (fun->isAsmJSNative()) {
return false;
}
sprinter.jsprintf("; backend=asmjs\n");
sprinter.jsprintf("; backend=wasm\n");
js::wasm::Instance& inst = fun->wasmInstance();
const js::wasm::Code& code = inst.code();
@ -1760,17 +1759,11 @@ static bool DisassembleNative(JSContext* cx, unsigned argc, Value* vp) {
js::jit::BaselineScript* baseline =
script->hasBaselineScript() ? script->baselineScript() : nullptr;
if (ion && ion->method()) {
if (!sprinter.jsprintf("; backend=ion\n")) {
return false;
}
sprinter.jsprintf("; backend=ion\n");
jit_begin = ion->method()->raw();
jit_end = ion->method()->rawEnd();
} else if (baseline) {
if (!sprinter.jsprintf("; backend=baseline\n")) {
return false;
}
sprinter.jsprintf("; backend=baseline\n");
jit_begin = baseline->method()->raw();
jit_end = baseline->method()->rawEnd();
}

Просмотреть файл

@ -909,9 +909,10 @@ void js::Nursery::printCollectionProfile(JS::GCReason reason,
stats().maybePrintProfileHeaders();
Sprinter sprinter;
if (!sprinter.init() || !sprinter.put(gcstats::MinorGCProfilePrefix)) {
if (!sprinter.init()) {
return;
}
sprinter.put(gcstats::MinorGCProfilePrefix);
size_t pid = getpid();
JSRuntime* runtime = gc->rt;
@ -923,9 +924,8 @@ void js::Nursery::printCollectionProfile(JS::GCReason reason,
size_t dedupCount = stats().getStat(gcstats::STAT_STRINGS_DEDUPLICATED);
#define PRINT_FIELD_VALUE(_1, _2, format, value) \
if (!sprinter.jsprintf(" " format, value)) { \
return; \
}
sprinter.jsprintf(" " format, value);
FOR_EACH_NURSERY_PROFILE_METADATA(PRINT_FIELD_VALUE)
#undef PRINT_FIELD_VALUE
@ -940,27 +940,24 @@ void js::Nursery::printCollectionProfile(JS::GCReason reason,
void js::Nursery::printProfileHeader() {
Sprinter sprinter;
if (!sprinter.init() || !sprinter.put(gcstats::MinorGCProfilePrefix)) {
if (!sprinter.init()) {
return;
}
sprinter.put(gcstats::MinorGCProfilePrefix);
#define PRINT_FIELD_NAME(name, width, _1, _2) \
sprinter.jsprintf(" %-*s", width, name);
#define PRINT_FIELD_NAME(name, width, _1, _2) \
if (!sprinter.jsprintf(" %-*s", width, name)) { \
return; \
}
FOR_EACH_NURSERY_PROFILE_METADATA(PRINT_FIELD_NAME)
#undef PRINT_FIELD_NAME
#define PRINT_PROFILE_NAME(_1, text) \
if (!sprinter.jsprintf(" %-6.6s", text)) { \
return; \
}
#define PRINT_PROFILE_NAME(_1, text) \
sprinter.jsprintf(" %-6.6s", text);
FOR_EACH_NURSERY_PROFILE_TIME(PRINT_PROFILE_NAME)
#undef PRINT_PROFILE_NAME
if (!sprinter.put("\n")) {
return;
}
sprinter.put("\n");
JS::UniqueChars str = sprinter.release();
if (!str) {
@ -974,12 +971,11 @@ bool js::Nursery::printProfileDurations(const ProfileDurations& times,
Sprinter& sprinter) {
for (auto time : times) {
int64_t micros = int64_t(time.ToMicroseconds());
if (!sprinter.jsprintf(" %6" PRIi64, micros)) {
return false;
}
sprinter.jsprintf(" %6" PRIi64, micros);
}
return sprinter.put("\n");
sprinter.put("\n");
return true;
}
static constexpr size_t NurserySliceMetadataFormatWidth() {
@ -1004,9 +1000,10 @@ void js::Nursery::printTotalProfileTimes() {
}
Sprinter sprinter;
if (!sprinter.init() || !sprinter.put(gcstats::MinorGCProfilePrefix)) {
if (!sprinter.init()) {
return;
}
sprinter.put(gcstats::MinorGCProfilePrefix);
size_t pid = getpid();
JSRuntime* runtime = gc->rt;
@ -1017,18 +1014,15 @@ void js::Nursery::printTotalProfileTimes() {
MOZ_ASSERT(r > 0 && r < int(sizeof(collections)));
#define PRINT_FIELD_VALUE(_1, _2, format, value) \
if (!sprinter.jsprintf(" " format, value)) { \
return; \
}
sprinter.jsprintf(" " format, value);
FOR_EACH_NURSERY_PROFILE_COMMON_METADATA(PRINT_FIELD_VALUE)
#undef PRINT_FIELD_VALUE
// Use whole width of per-slice metadata to print total slices so the profile
// totals that follow line up.
size_t width = NurserySliceMetadataFormatWidth();
if (!sprinter.jsprintf(" %-*s", int(width), collections)) {
return;
}
sprinter.jsprintf(" %-*s", int(width), collections);
if (!printProfileDurations(totalDurations_, sprinter)) {
return;

Просмотреть файл

@ -1640,27 +1640,24 @@ void Statistics::printProfileHeader() {
}
Sprinter sprinter;
if (!sprinter.init() || !sprinter.put(MajorGCProfilePrefix)) {
if (!sprinter.init()) {
return;
}
sprinter.put(MajorGCProfilePrefix);
#define PRINT_METADATA_NAME(name, width, _1, _2) \
if (!sprinter.jsprintf(" %-*s", width, name)) { \
return; \
}
sprinter.jsprintf(" %-*s", width, name);
FOR_EACH_GC_PROFILE_METADATA(PRINT_METADATA_NAME)
#undef PRINT_METADATA_NAME
#define PRINT_PROFILE_NAME(_1, text, _2) \
if (!sprinter.jsprintf(" %-6.6s", text)) { \
return; \
}
sprinter.jsprintf(" %-6.6s", text);
FOR_EACH_GC_PROFILE_TIME(PRINT_PROFILE_NAME)
#undef PRINT_PROFILE_NAME
if (!sprinter.put("\n")) {
return;
}
sprinter.put("\n");
JS::UniqueChars str = sprinter.release();
if (!str) {
@ -1685,9 +1682,10 @@ void Statistics::printSliceProfile() {
updateTotalProfileTimes(times);
Sprinter sprinter;
if (!sprinter.init() || !sprinter.put(MajorGCProfilePrefix)) {
if (!sprinter.init()) {
return;
}
sprinter.put(MajorGCProfilePrefix);
size_t pid = getpid();
JSRuntime* runtime = gc->rt;
@ -1699,9 +1697,8 @@ void Statistics::printSliceProfile() {
size_t realmCount = zoneStats.realmCount;
#define PRINT_FIELD_VALUE(_1, _2, format, value) \
if (!sprinter.jsprintf(" " format, value)) { \
return; \
}
sprinter.jsprintf(" " format, value);
FOR_EACH_GC_PROFILE_METADATA(PRINT_FIELD_VALUE)
#undef PRINT_FIELD_VALUE
@ -1782,12 +1779,11 @@ bool Statistics::printProfileTimes(const ProfileDurations& times,
Sprinter& sprinter) {
for (auto time : times) {
int64_t millis = int64_t(time.ToMilliseconds());
if (!sprinter.jsprintf(" %6" PRIi64, millis)) {
return false;
}
sprinter.jsprintf(" %6" PRIi64, millis);
}
return sprinter.put("\n");
sprinter.put("\n");
return true;
}
constexpr size_t SliceMetadataFormatWidth() {
@ -1812,26 +1808,24 @@ void Statistics::printTotalProfileTimes() {
}
Sprinter sprinter;
if (!sprinter.init() || !sprinter.put(MajorGCProfilePrefix)) {
if (!sprinter.init()) {
return;
}
sprinter.put(MajorGCProfilePrefix);
size_t pid = getpid();
JSRuntime* runtime = gc->rt;
#define PRINT_FIELD_VALUE(_1, _2, format, value) \
if (!sprinter.jsprintf(" " format, value)) { \
return; \
}
sprinter.jsprintf(" " format, value);
FOR_EACH_GC_PROFILE_COMMON_METADATA(PRINT_FIELD_VALUE)
#undef PRINT_FIELD_VALUE
// Use whole width of per-slice metadata to print total slices so the profile
// totals that follow line up.
size_t width = SliceMetadataFormatWidth();
if (!sprinter.jsprintf(" %-*s", int(width), formatTotalSlices())) {
return;
}
sprinter.jsprintf(" %-*s", int(width), formatTotalSlices());
if (!printProfileTimes(totalTimes_, sprinter)) {
return;

Просмотреть файл

@ -495,7 +495,7 @@ void IonPerfSpewer::recordInstruction(MacroAssembler& masm, LInstruction* ins) {
if (PerfIROpsEnabled()) {
Sprinter buf;
CHECK_RETURN(buf.init());
CHECK_RETURN(buf.put(LIRCodeName(op)));
buf.put(LIRCodeName(op));
ins->printOperands(buf);
opcodeStr = buf.release();
}
@ -516,46 +516,46 @@ static void PrintStackValue(StackValue* stackVal, CompilerFrameInfo& frame,
case StackValue::Constant: {
js::Value constantVal = stackVal->constant();
if (constantVal.isInt32()) {
CHECK_RETURN(buf.jsprintf("%d", constantVal.toInt32()));
buf.jsprintf("%d", constantVal.toInt32());
} else if (constantVal.isObjectOrNull()) {
CHECK_RETURN(buf.jsprintf("obj:%p", constantVal.toObjectOrNull()));
buf.jsprintf("obj:%p", constantVal.toObjectOrNull());
} else if (constantVal.isString()) {
CHECK_RETURN(buf.put("str:"));
CHECK_RETURN(buf.putString(constantVal.toString()));
buf.put("str:");
buf.putString(constantVal.toString());
} else if (constantVal.isNumber()) {
CHECK_RETURN(buf.jsprintf("num:%f", constantVal.toNumber()));
buf.jsprintf("num:%f", constantVal.toNumber());
} else if (constantVal.isSymbol()) {
CHECK_RETURN(buf.put("sym:"));
buf.put("sym:");
constantVal.toSymbol()->dump(buf);
} else {
CHECK_RETURN(buf.jsprintf("raw:%" PRIx64, constantVal.asRawBits()));
buf.jsprintf("raw:%" PRIx64, constantVal.asRawBits());
}
} break;
/****** Register ******/
case StackValue::Register: {
Register reg = stackVal->reg().payloadOrValueReg();
CHECK_RETURN(buf.put(reg.name()));
buf.put(reg.name());
} break;
/****** Stack ******/
case StackValue::Stack:
CHECK_RETURN(buf.put("stack"));
buf.put("stack");
break;
/****** ThisSlot ******/
case StackValue::ThisSlot: {
# ifdef JS_HAS_HIDDEN_SP
CHECK_RETURN(buf.put("this"));
buf.put("this");
# else
Address addr = frame.addressOfThis();
CHECK_RETURN(buf.jsprintf("this:%s(%d)", addr.base.name(), addr.offset));
buf.jsprintf("this:%s(%d)", addr.base.name(), addr.offset);
# endif
} break;
/****** LocalSlot ******/
case StackValue::LocalSlot:
CHECK_RETURN(buf.jsprintf("local:%u", stackVal->localSlot()));
buf.jsprintf("local:%u", stackVal->localSlot());
break;
/****** ArgSlot ******/
case StackValue::ArgSlot:
CHECK_RETURN(buf.jsprintf("arg:%u", stackVal->argSlot()));
buf.jsprintf("arg:%u", stackVal->argSlot());
break;
default:
@ -582,7 +582,7 @@ void BaselinePerfSpewer::recordInstruction(JSContext* cx, MacroAssembler& masm,
Sprinter buf(cx);
CHECK_RETURN(buf.init());
CHECK_RETURN(buf.put(js::CodeName(op)));
buf.put(js::CodeName(op));
switch (op) {
case JSOp::SetName:
@ -593,8 +593,8 @@ void BaselinePerfSpewer::recordInstruction(JSContext* cx, MacroAssembler& masm,
case JSOp::GetGName: {
// Emit the name used for these ops
Rooted<PropertyName*> name(cx, script->getName(pc));
CHECK_RETURN(buf.put(" "));
CHECK_RETURN(buf.putString(name));
buf.put(" ");
buf.putString(name);
} break;
default:
break;
@ -602,14 +602,14 @@ void BaselinePerfSpewer::recordInstruction(JSContext* cx, MacroAssembler& masm,
// Output should be "JSOp (operand1), (operand2), ..."
for (unsigned i = 1; i <= numOperands; i++) {
CHECK_RETURN(buf.put(" ("));
buf.put(" (");
StackValue* stackVal = frame.peek(-int(i));
PrintStackValue(stackVal, frame, buf);
if (i < numOperands) {
CHECK_RETURN(buf.put("),"));
buf.put("),");
} else {
CHECK_RETURN(buf.put(")"));
buf.put(")");
}
}
opcodeStr = buf.release();

Просмотреть файл

@ -3655,15 +3655,11 @@ static bool DisassWithSrc(JSContext* cx, unsigned argc, Value* vp) {
if (line2 < line1) {
if (bupline != line2) {
bupline = line2;
if (!sprinter.jsprintf("%s %3u: BACKUP\n", sep, line2)) {
return false;
}
sprinter.jsprintf("%s %3u: BACKUP\n", sep, line2);
}
} else {
if (bupline && line1 == line2) {
if (!sprinter.jsprintf("%s %3u: RESTORE\n", sep, line2)) {
return false;
}
sprinter.jsprintf("%s %3u: RESTORE\n", sep, line2);
}
bupline = 0;
while (line1 < line2) {
@ -3673,9 +3669,7 @@ static bool DisassWithSrc(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
line1++;
if (!sprinter.jsprintf("%s %3u: %s", sep, line1, linebuf)) {
return false;
}
sprinter.jsprintf("%s %3u: %s", sep, line1, linebuf);
}
}

Просмотреть файл

@ -285,17 +285,11 @@ static bool FormatFrame(JSContext* cx, const FrameIter& iter, Sprinter& sp,
if (!funbytes) {
return false;
}
if (!sp.printf("%d %s(", num, funbytes.get())) {
return false;
}
sp.printf("%d %s(", num, funbytes.get());
} else if (fun) {
if (!sp.printf("%d anonymous(", num)) {
return false;
}
sp.printf("%d anonymous(", num);
} else {
if (!sp.printf("%d <TOP LEVEL>", num)) {
return false;
}
sp.printf("%d <TOP LEVEL>", num);
}
if (showArgs && iter.hasArgs()) {
@ -346,28 +340,22 @@ static bool FormatFrame(JSContext* cx, const FrameIter& iter, Sprinter& sp,
}
if (value) {
if (!sp.printf("%s%s%s%s%s%s", !first ? ", " : "", name ? name : "",
name ? " = " : "", arg.isString() ? "\"" : "", value,
arg.isString() ? "\"" : "")) {
return false;
}
sp.printf("%s%s%s%s%s%s", !first ? ", " : "", name ? name : "",
name ? " = " : "", arg.isString() ? "\"" : "", value,
arg.isString() ? "\"" : "");
first = false;
} else {
if (!sp.put(" <Failed to get argument while inspecting stack "
"frame>\n")) {
return false;
}
sp.put(" <Failed to get argument while inspecting stack "
"frame>\n");
}
}
}
// print filename, line number and column
if (!sp.printf("%s [\"%s\":%u:%u]\n", fun ? ")" : "",
filename ? filename : "<unknown>", lineno,
column.zeroOriginValue())) {
return false;
}
sp.printf("%s [\"%s\":%u:%u]\n", fun ? ")" : "",
filename ? filename : "<unknown>", lineno,
column.zeroOriginValue());
// Note: Right now we don't dump the local variables anymore, because
// that is hard to support across all the JITs etc.
@ -387,13 +375,9 @@ static bool FormatFrame(JSContext* cx, const FrameIter& iter, Sprinter& sp,
if (!thisValBytes) {
return false;
}
if (!sp.printf(" this = %s\n", thisValBytes.get())) {
return false;
}
sp.printf(" this = %s\n", thisValBytes.get());
} else {
if (!sp.put(" <failed to get 'this' value>\n")) {
return false;
}
sp.put(" <failed to get 'this' value>\n");
}
}
}
@ -419,10 +403,8 @@ static bool FormatFrame(JSContext* cx, const FrameIter& iter, Sprinter& sp,
return false;
}
cx->clearPendingException();
if (!sp.put(" <Failed to fetch property while inspecting stack "
"frame>\n")) {
return false;
}
sp.put(" <Failed to fetch property while inspecting stack "
"frame>\n");
continue;
}
@ -445,15 +427,11 @@ static bool FormatFrame(JSContext* cx, const FrameIter& iter, Sprinter& sp,
}
if (name && value) {
if (!sp.printf(" this.%s = %s%s%s\n", name, v.isString() ? "\"" : "",
value, v.isString() ? "\"" : "")) {
return false;
}
sp.printf(" this.%s = %s%s%s\n", name, v.isString() ? "\"" : "",
value, v.isString() ? "\"" : "");
} else {
if (!sp.put(" <Failed to format values while inspecting stack "
"frame>\n")) {
return false;
}
sp.put(" <Failed to format values while inspecting stack "
"frame>\n");
}
}
}
@ -472,15 +450,10 @@ static bool FormatWasmFrame(JSContext* cx, const FrameIter& iter, Sprinter& sp,
}
}
if (!sp.printf("%d %s()", num, nameStr ? nameStr.get() : "<wasm-function>")) {
return false;
}
if (!sp.printf(" [\"%s\":wasm-function[%u]:0x%x]\n",
iter.filename() ? iter.filename() : "<unknown>",
iter.wasmFuncIndex(), iter.wasmBytecodeOffset())) {
return false;
}
sp.printf("%d %s()", num, nameStr ? nameStr.get() : "<wasm-function>");
sp.printf(" [\"%s\":wasm-function[%u]:0x%x]\n",
iter.filename() ? iter.filename() : "<unknown>",
iter.wasmFuncIndex(), iter.wasmBytecodeOffset());
MOZ_ASSERT(!cx->isExceptionPending());
return true;
@ -506,9 +479,7 @@ JS::UniqueChars JS::FormatStackDump(JSContext* cx, bool showArgs,
}
if (num == 0) {
if (!sp.put("JavaScript stack is empty\n")) {
return nullptr;
}
sp.put("JavaScript stack is empty\n");
}
return sp.release();

Просмотреть файл

@ -368,9 +368,7 @@ size_t js::PutEscapedStringImpl(char* buffer, size_t bufferSize,
buffer = nullptr;
}
} else if (out) {
if (!out->put(&c, 1)) {
return size_t(-1);
}
out->put(&c, 1);
}
n++;
}

Просмотреть файл

@ -104,9 +104,7 @@ static bool DecompileArgumentFromStack(JSContext* cx, int formalIndex,
[[nodiscard]] static bool DumpIonScriptCounts(Sprinter* sp, HandleScript script,
jit::IonScriptCounts* ionCounts) {
if (!sp->jsprintf("IonScript [%zu blocks]:\n", ionCounts->numBlocks())) {
return false;
}
sp->jsprintf("IonScript [%zu blocks]:\n", ionCounts->numBlocks());
for (size_t i = 0; i < ionCounts->numBlocks(); i++) {
const jit::IonBlockCounts& block = ionCounts->block(i);
@ -114,27 +112,16 @@ static bool DecompileArgumentFromStack(JSContext* cx, int formalIndex,
JS::LimitedColumnNumberZeroOrigin columnNumber;
lineNumber = PCToLineNumber(script, script->offsetToPC(block.offset()),
&columnNumber);
if (!sp->jsprintf("BB #%" PRIu32 " [%05u,%u,%u]", block.id(),
block.offset(), lineNumber,
columnNumber.zeroOriginValue())) {
return false;
}
sp->jsprintf("BB #%" PRIu32 " [%05u,%u,%u]", block.id(), block.offset(),
lineNumber, columnNumber.zeroOriginValue());
if (block.description()) {
if (!sp->jsprintf(" [inlined %s]", block.description())) {
return false;
}
sp->jsprintf(" [inlined %s]", block.description());
}
for (size_t j = 0; j < block.numSuccessors(); j++) {
if (!sp->jsprintf(" -> #%" PRIu32, block.successor(j))) {
return false;
}
}
if (!sp->jsprintf(" :: %" PRIu64 " hits\n", block.hitCount())) {
return false;
}
if (!sp->jsprintf("%s\n", block.code())) {
return false;
sp->jsprintf(" -> #%" PRIu32, block.successor(j));
}
sp->jsprintf(" :: %" PRIu64 " hits\n", block.hitCount());
sp->jsprintf("%s\n", block.code());
}
return true;
@ -156,19 +143,13 @@ static bool DecompileArgumentFromStack(JSContext* cx, int formalIndex,
return false;
}
if (!sp->put(" {")) {
return false;
}
sp->put(" {");
PCCounts* counts = script->maybeGetPCCounts(pc);
if (double val = counts ? counts->numExec() : 0.0) {
if (!sp->jsprintf("\"%s\": %.0f", PCCounts::numExecName, val)) {
return false;
}
}
if (!sp->put("}\n")) {
return false;
sp->jsprintf("\"%s\": %.0f", PCCounts::numExecName, val);
}
sp->put("}\n");
pc = next;
}
@ -1023,78 +1004,48 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
}
if (showAll) {
if (!sp->jsprintf("%s:%u\n", script->filename(),
unsigned(script->lineno()))) {
return false;
}
sp->jsprintf("%s:%u\n", script->filename(),
unsigned(script->lineno()));
}
if (pc != nullptr) {
if (!sp->put(" ")) {
return false;
}
sp->put(" ");
}
if (showAll) {
if (!sp->put("sn stack ")) {
return false;
}
}
if (!sp->put("loc ")) {
return false;
sp->put("sn stack ");
}
sp->put("loc ");
if (lines) {
if (!sp->put("line")) {
return false;
}
}
if (!sp->put(" op\n")) {
return false;
sp->put("line");
}
sp->put(" op\n");
if (pc != nullptr) {
if (!sp->put(" ")) {
return false;
}
sp->put(" ");
}
if (showAll) {
if (!sp->put("-- ----- ")) {
return false;
}
}
if (!sp->put("----- ")) {
return false;
sp->put("-- ----- ");
}
sp->put("----- ");
if (lines) {
if (!sp->put("----")) {
return false;
}
}
if (!sp->put(" --\n")) {
return false;
sp->put("----");
}
sp->put(" --\n");
jsbytecode* next = script->code();
jsbytecode* end = script->codeEnd();
while (next < end) {
if (next == script->main()) {
if (!sp->put("main:\n")) {
return false;
}
sp->put("main:\n");
}
if (pc != nullptr) {
if (!sp->put(pc == next ? "--> " : " ")) {
return false;
}
sp->put(pc == next ? "--> " : " ");
}
if (showAll) {
if (parser && parser->isReachable(next)) {
if (!sp->jsprintf("%05u ", parser->stackDepthAtPC(next))) {
return false;
}
sp->jsprintf("%05u ", parser->stackDepthAtPC(next));
} else {
if (!sp->put(" ")) {
return false;
}
sp->put(" ");
}
}
unsigned len = Disassemble1(cx, script, next, script->pcToOffset(next),
@ -1271,13 +1222,9 @@ static bool DumpJumpOrigins(HandleScript script, jsbytecode* pc,
BytecodeParser::JumpKind kind) {
if (!called) {
called = true;
if (!sp->put("\n# ")) {
return false;
}
sp->put("\n# ");
} else {
if (!sp->put(", ")) {
return false;
}
sp->put(", ");
}
switch (kind) {
@ -1285,34 +1232,24 @@ static bool DumpJumpOrigins(HandleScript script, jsbytecode* pc,
break;
case BytecodeParser::JumpKind::SwitchCase:
if (!sp->put("switch-case ")) {
return false;
}
sp->put("switch-case ");
break;
case BytecodeParser::JumpKind::SwitchDefault:
if (!sp->put("switch-default ")) {
return false;
}
sp->put("switch-default ");
break;
case BytecodeParser::JumpKind::TryCatch:
if (!sp->put("try-catch ")) {
return false;
}
sp->put("try-catch ");
break;
case BytecodeParser::JumpKind::TryFinally:
if (!sp->put("try-finally ")) {
return false;
}
sp->put("try-finally ");
break;
}
if (!sp->jsprintf("from %s @ %05u", CodeName(JSOp(*pc)),
unsigned(script->pcToOffset(pc)))) {
return false;
}
sp->jsprintf("from %s @ %05u", CodeName(JSOp(*pc)),
unsigned(script->pcToOffset(pc)));
return true;
};
@ -1320,9 +1257,7 @@ static bool DumpJumpOrigins(HandleScript script, jsbytecode* pc,
return false;
}
if (called) {
if (!sp->put("\n")) {
return false;
}
sp->put("\n");
}
return true;
@ -1343,9 +1278,7 @@ static bool PrintShapeProperties(JSContext* cx, Sprinter* sp,
}
}
if (!sp->put("{")) {
return false;
}
sp->put("{");
for (size_t i = props.length(); i > 0; i--) {
PropertyKey key = props[i - 1];
@ -1355,17 +1288,14 @@ static bool PrintShapeProperties(JSContext* cx, Sprinter* sp,
ReportOutOfMemory(cx);
return false;
}
if (!sp->putString(str)) {
return false;
}
sp->putString(str);
if (i > 1) {
if (!sp->put(", ")) {
return false;
}
sp->put(", ");
}
}
return sp->put("}");
sp->put("}");
return true;
}
static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
@ -1393,27 +1323,19 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
static const size_t stack_column = 40;
for (size_t i = after - before; i < stack_column - 1; i++) {
if (!sp->put(" ")) {
return false;
}
sp->put(" ");
}
if (!sp->put(" # ")) {
return false;
}
sp->put(" # ");
if (!parser->isReachable(pc)) {
if (!sp->put("!!! UNREACHABLE !!!")) {
return false;
}
sp->put("!!! UNREACHABLE !!!");
} else {
uint32_t depth = parser->stackDepthAfterPC(pc);
for (uint32_t i = 0; i < depth; i++) {
if (i) {
if (!sp->put(" ")) {
return false;
}
sp->put(" ");
}
const OffsetAndDefIndex& offsetAndDefIndex =
@ -1441,17 +1363,11 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
JSOp op = JSOp(*pc);
const JSCodeSpec& cs = CodeSpec(op);
const unsigned len = cs.length;
if (!sp->jsprintf("%05u:", loc)) {
return 0;
}
sp->jsprintf("%05u:", loc);
if (lines) {
if (!sp->jsprintf("%4u", PCToLineNumber(script, pc))) {
return 0;
}
}
if (!sp->jsprintf(" %s", CodeName(op))) {
return 0;
sp->jsprintf("%4u", PCToLineNumber(script, pc));
}
sp->jsprintf(" %s", CodeName(op));
int i;
switch (JOF_TYPE(cs.format)) {
@ -1460,9 +1376,7 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
case JOF_JUMP: {
ptrdiff_t off = GET_JUMP_OFFSET(pc);
if (!sp->jsprintf(" %u (%+d)", unsigned(loc + int(off)), int(off))) {
return 0;
}
sp->jsprintf(" %u (%+d)", unsigned(loc + int(off)), int(off));
break;
}
@ -1472,9 +1386,7 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
if (!ToDisassemblySource(cx, scope, &bytes)) {
return 0;
}
if (!sp->jsprintf(" %s", bytes.get())) {
return 0;
}
sp->jsprintf(" %s", bytes.get());
break;
}
@ -1485,17 +1397,12 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
return 0;
}
EnvironmentCoordinate ec(pc);
if (!sp->jsprintf(" %s (hops = %u, slot = %u)", bytes.get(), ec.hops(),
ec.slot())) {
return 0;
}
sp->jsprintf(" %s (hops = %u, slot = %u)", bytes.get(), ec.hops(), ec.slot());
break;
}
case JOF_DEBUGCOORD: {
EnvironmentCoordinate ec(pc);
if (!sp->jsprintf("(hops = %u, slot = %u)", ec.hops(), ec.slot())) {
return 0;
}
sp->jsprintf("(hops = %u, slot = %u)", ec.hops(), ec.slot());
break;
}
case JOF_ATOM: {
@ -1504,9 +1411,7 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
if (!bytes) {
return 0;
}
if (!sp->jsprintf(" %s", bytes.get())) {
return 0;
}
sp->jsprintf(" %s", bytes.get());
break;
}
case JOF_STRING: {
@ -1515,17 +1420,13 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
if (!bytes) {
return 0;
}
if (!sp->jsprintf(" %s", bytes.get())) {
return 0;
}
sp->jsprintf(" %s", bytes.get());
break;
}
case JOF_DOUBLE: {
double d = GET_INLINE_VALUE(pc).toDouble();
if (!sp->jsprintf(" %lf", d)) {
return 0;
}
sp->jsprintf(" %lf", d);
break;
}
@ -1535,9 +1436,7 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
if (!bytes) {
return 0;
}
if (!sp->jsprintf(" %s", bytes.get())) {
return 0;
}
sp->jsprintf(" %s", bytes.get());
break;
}
@ -1549,18 +1448,14 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
if (!bytes) {
return 0;
}
if (!sp->jsprintf(" %s", bytes.get())) {
return 0;
}
sp->jsprintf(" %s", bytes.get());
}
break;
}
case JOF_SHAPE: {
SharedShape* shape = script->getShape(pc);
if (!sp->put(" ")) {
return 0;
}
sp->put(" ");
if (!PrintShapeProperties(cx, sp, shape)) {
return 0;
}
@ -1574,9 +1469,7 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
if (!bytes) {
return 0;
}
if (!sp->jsprintf(" %s", bytes.get())) {
return 0;
}
sp->jsprintf(" %s", bytes.get());
break;
}
@ -1589,10 +1482,7 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
pc2 += JUMP_OFFSET_LEN;
high = GET_JUMP_OFFSET(pc2);
pc2 += JUMP_OFFSET_LEN;
if (!sp->jsprintf(" defaultOffset %d low %d high %d", int(off), low,
high)) {
return 0;
}
sp->jsprintf(" defaultOffset %d low %d high %d", int(off), low, high);
// Display stack dump before diplaying the offsets for each case.
if (!dumpStack()) {
@ -1602,60 +1492,42 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
for (i = low; i <= high; i++) {
off =
script->tableSwitchCaseOffset(pc, i - low) - script->pcToOffset(pc);
if (!sp->jsprintf("\n\t%d: %d", i, int(off))) {
return 0;
}
sp->jsprintf("\n\t%d: %d", i, int(off));
}
break;
}
case JOF_QARG:
if (!sp->jsprintf(" %u", GET_ARGNO(pc))) {
return 0;
}
sp->jsprintf(" %u", GET_ARGNO(pc));
break;
case JOF_LOCAL:
if (!sp->jsprintf(" %u", GET_LOCALNO(pc))) {
return 0;
}
sp->jsprintf(" %u", GET_LOCALNO(pc));
break;
case JOF_GCTHING:
if (!sp->jsprintf(" %u", unsigned(GET_GCTHING_INDEX(pc)))) {
return 0;
}
sp->jsprintf(" %u", unsigned(GET_GCTHING_INDEX(pc)));
break;
case JOF_UINT32:
if (!sp->jsprintf(" %u", GET_UINT32(pc))) {
return 0;
}
sp->jsprintf(" %u", GET_UINT32(pc));
break;
case JOF_ICINDEX:
if (!sp->jsprintf(" (ic: %u)", GET_ICINDEX(pc))) {
return 0;
}
sp->jsprintf(" (ic: %u)", GET_ICINDEX(pc));
break;
case JOF_LOOPHEAD:
if (!sp->jsprintf(" (ic: %u, depthHint: %u)", GET_ICINDEX(pc),
LoopHeadDepthHint(pc))) {
return 0;
}
sp->jsprintf(" (ic: %u, depthHint: %u)", GET_ICINDEX(pc),
LoopHeadDepthHint(pc));
break;
case JOF_TWO_UINT8: {
int one = (int)GET_UINT8(pc);
int two = (int)GET_UINT8(pc + 1);
if (!sp->jsprintf(" %d", one)) {
return 0;
}
if (!sp->jsprintf(" %d", two)) {
return 0;
}
sp->jsprintf(" %d", one);
sp->jsprintf(" %d", two);
break;
}
@ -1682,9 +1554,7 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
MOZ_ASSERT(op == JSOp::Int32);
i = GET_INT32(pc);
print_int:
if (!sp->jsprintf(" %d", i)) {
return 0;
}
sp->jsprintf(" %d", i);
break;
default: {
@ -1700,9 +1570,7 @@ static unsigned Disassemble1(JSContext* cx, HandleScript script, jsbytecode* pc,
return 0;
}
if (!sp->put("\n")) {
return 0;
}
sp->put("\n");
return len;
}
@ -1930,7 +1798,8 @@ bool ExpressionDecompiler::decompilePC(jsbytecode* pc, uint8_t defIndex) {
case JSOp::Uint16:
case JSOp::Uint24:
case JSOp::Int32:
return sprinter.printf("%d", GetBytecodeInteger(pc));
sprinter.printf("%d", GetBytecodeInteger(pc));
return true;
case JSOp::String:
return quote(loadString(pc), '"');
case JSOp::Symbol: {
@ -2086,7 +1955,8 @@ bool ExpressionDecompiler::decompilePC(jsbytecode* pc, uint8_t defIndex) {
return write("arguments.length");
case JSOp::GetFrameArg:
return sprinter.printf("arguments[%u]", GET_ARGNO(pc));
sprinter.printf("arguments[%u]", GET_ARGNO(pc));
return true;
case JSOp::GetActualArg:
return write("arguments[") && decompilePCForStackOperand(pc, -1) &&
@ -2109,7 +1979,8 @@ bool ExpressionDecompiler::decompilePC(jsbytecode* pc, uint8_t defIndex) {
return write("OBJ");
case JSOp::Double:
return sprinter.printf("%lf", GET_INLINE_VALUE(pc).toDouble());
sprinter.printf("%lf", GET_INLINE_VALUE(pc).toDouble());
return true;
case JSOp::Exception:
return write("EXCEPTION");
@ -2294,7 +2165,10 @@ bool ExpressionDecompiler::init() {
return sprinter.init();
}
bool ExpressionDecompiler::write(const char* s) { return sprinter.put(s); }
bool ExpressionDecompiler::write(const char* s) {
sprinter.put(s);
return true;
}
bool ExpressionDecompiler::write(JSString* str) {
if (str == cx->names().dot_this_) {
@ -2303,7 +2177,8 @@ bool ExpressionDecompiler::write(JSString* str) {
if (str == cx->names().dot_newTarget_) {
return write("new.target");
}
return sprinter.putString(str);
sprinter.putString(str);
return true;
}
bool ExpressionDecompiler::quote(JSString* s, char quote) {
@ -2372,7 +2247,8 @@ static bool DecompileAtPCForStackDump(
return false;
}
return sp->put(result.get());
sp->put(result.get());
return true;
}
#endif /* defined(DEBUG) || defined(JS_JITSPEW) */

Просмотреть файл

@ -3399,9 +3399,7 @@ bool JSScript::dump(JSContext* cx, JS::Handle<JSScript*> script,
return false;
}
if (!sp->put("\n")) {
return false;
}
sp->put("\n");
if (!Disassemble(cx, script, /* lines = */ true, sp)) {
return false;
@ -3427,9 +3425,7 @@ bool JSScript::dump(JSContext* cx, JS::Handle<JSScript*> script,
JSObject* obj = &gcThing.as<JSObject>();
if (obj->is<JSFunction>()) {
if (!sp->put("\n")) {
return false;
}
sp->put("\n");
JS::Rooted<JSFunction*> fun(cx, &obj->as<JSFunction>());
if (fun->isInterpreted()) {
@ -3442,9 +3438,7 @@ bool JSScript::dump(JSContext* cx, JS::Handle<JSScript*> script,
return false;
}
} else {
if (!sp->put("[native code]\n")) {
return false;
}
sp->put("[native code]\n");
}
}
}
@ -3456,12 +3450,10 @@ bool JSScript::dump(JSContext* cx, JS::Handle<JSScript*> script,
/* static */
bool JSScript::dumpSrcNotes(JSContext* cx, JS::Handle<JSScript*> script,
js::Sprinter* sp) {
if (!sp->put("\nSource notes:\n") ||
!sp->jsprintf("%4s %4s %6s %5s %6s %-16s %s\n", "ofs", "line", "column",
"pc", "delta", "desc", "args") ||
!sp->put("---- ---- ------ ----- ------ ---------------- ------\n")) {
return false;
}
sp->put("\nSource notes:\n");
sp->jsprintf("%4s %4s %6s %5s %6s %-16s %s\n", "ofs", "line", "column",
"pc", "delta", "desc", "args");
sp->put("---- ---- ------ ----- ------ ---------------- ------\n");
unsigned offset = 0;
unsigned lineno = script->lineno();
@ -3475,10 +3467,8 @@ bool JSScript::dumpSrcNotes(JSContext* cx, JS::Handle<JSScript*> script,
offset += delta;
SrcNoteType type = sn->type();
const char* name = sn->name();
if (!sp->jsprintf("%3u: %4u %6u %5u [%4u] %-16s", unsigned(sn - notes),
lineno, column.zeroOriginValue(), offset, delta, name)) {
return false;
}
sp->jsprintf("%3u: %4u %6u %5u [%4u] %-16s", unsigned(sn - notes),
lineno, column.zeroOriginValue(), offset, delta, name);
switch (type) {
case SrcNoteType::Breakpoint:
@ -3488,28 +3478,21 @@ bool JSScript::dumpSrcNotes(JSContext* cx, JS::Handle<JSScript*> script,
case SrcNoteType::ColSpan: {
JS::ColumnNumberOffset colspan = SrcNote::ColSpan::getSpan(sn);
if (!sp->jsprintf(" colspan %u", colspan.value())) {
return false;
}
sp->jsprintf(" colspan %u", colspan.value());
column += colspan;
break;
}
case SrcNoteType::SetLine:
lineno = SrcNote::SetLine::getLine(sn, script->lineno());
if (!sp->jsprintf(" lineno %u", lineno)) {
return false;
}
sp->jsprintf(" lineno %u", lineno);
column = JS::LimitedColumnNumberZeroOrigin::zero();
break;
case SrcNoteType::SetLineColumn:
lineno = SrcNote::SetLineColumn::getLine(sn, script->lineno());
column = SrcNote::SetLineColumn::getColumn(sn);
if (!sp->jsprintf(" lineno %u column %u", lineno,
column.zeroOriginValue())) {
return false;
}
sp->jsprintf(" lineno %u column %u", lineno, column.zeroOriginValue());
break;
case SrcNoteType::NewLine:
@ -3519,19 +3502,14 @@ bool JSScript::dumpSrcNotes(JSContext* cx, JS::Handle<JSScript*> script,
case SrcNoteType::NewLineColumn:
column = SrcNote::NewLineColumn::getColumn(sn);
if (!sp->jsprintf(" column %u", column.zeroOriginValue())) {
return false;
}
sp->jsprintf(" column %u", column.zeroOriginValue());
++lineno;
break;
default:
MOZ_ASSERT_UNREACHABLE("unrecognized srcnote");
}
if (!sp->put("\n")) {
return false;
}
sp->put("\n");
}
return true;
@ -3561,16 +3539,11 @@ static const char* TryNoteName(TryNoteKind kind) {
/* static */
bool JSScript::dumpTryNotes(JSContext* cx, JS::Handle<JSScript*> script,
js::Sprinter* sp) {
if (!sp->put(
"\nException table:\nkind stack start end\n")) {
return false;
}
sp->put("\nException table:\nkind stack start end\n");
for (const js::TryNote& tn : script->trynotes()) {
if (!sp->jsprintf(" %-16s %6u %8u %8u\n", TryNoteName(tn.kind()),
tn.stackDepth, tn.start, tn.start + tn.length)) {
return false;
}
sp->jsprintf(" %-16s %6u %8u %8u\n", TryNoteName(tn.kind()),
tn.stackDepth, tn.start, tn.start + tn.length);
}
return true;
}
@ -3578,32 +3551,20 @@ bool JSScript::dumpTryNotes(JSContext* cx, JS::Handle<JSScript*> script,
/* static */
bool JSScript::dumpScopeNotes(JSContext* cx, JS::Handle<JSScript*> script,
js::Sprinter* sp) {
if (!sp->put("\nScope notes:\n index parent start end\n")) {
return false;
}
sp->put("\nScope notes:\n index parent start end\n");
for (const ScopeNote& note : script->scopeNotes()) {
if (note.index == ScopeNote::NoScopeIndex) {
if (!sp->jsprintf("%8s ", "(none)")) {
return false;
}
sp->jsprintf("%8s ", "(none)");
} else {
if (!sp->jsprintf("%8u ", note.index.index)) {
return false;
}
sp->jsprintf("%8u ", note.index.index);
}
if (note.parent == ScopeNote::NoScopeIndex) {
if (!sp->jsprintf("%8s ", "(none)")) {
return false;
}
sp->jsprintf("%8s ", "(none)");
} else {
if (!sp->jsprintf("%8u ", note.parent)) {
return false;
}
}
if (!sp->jsprintf("%8u %8u\n", note.start, note.start + note.length)) {
return false;
sp->jsprintf("%8u ", note.parent);
}
sp->jsprintf("%8u %8u\n", note.start, note.start + note.length);
}
return true;
}
@ -3611,41 +3572,27 @@ bool JSScript::dumpScopeNotes(JSContext* cx, JS::Handle<JSScript*> script,
/* static */
bool JSScript::dumpGCThings(JSContext* cx, JS::Handle<JSScript*> script,
js::Sprinter* sp) {
if (!sp->put("\nGC things:\n index type value\n")) {
return false;
}
sp->put("\nGC things:\n index type value\n");
size_t i = 0;
for (JS::GCCellPtr gcThing : script->gcthings()) {
if (!sp->jsprintf("%8zu ", i)) {
return false;
}
sp->jsprintf("%8zu ", i);
if (gcThing.is<JS::BigInt>()) {
if (!sp->put("BigInt ")) {
return false;
}
sp->put("BigInt ");
gcThing.as<JS::BigInt>().dump(*sp);
if (!sp->put("\n")) {
return false;
}
sp->put("\n");
} else if (gcThing.is<Scope>()) {
if (!sp->put("Scope ")) {
return false;
}
sp->put("Scope ");
JS::Rooted<Scope*> scope(cx, &gcThing.as<Scope>());
if (!Scope::dumpForDisassemble(cx, scope, *sp,
" ")) {
return false;
}
if (!sp->put("\n")) {
return false;
}
sp->put("\n");
} else if (gcThing.is<JSObject>()) {
JSObject* obj = &gcThing.as<JSObject>();
if (obj->is<JSFunction>()) {
if (!sp->put("Function ")) {
return false;
}
sp->put("Function ");
JS::Rooted<JSFunction*> fun(cx, &obj->as<JSFunction>());
if (fun->displayAtom()) {
JS::Rooted<JSAtom*> name(cx, fun->displayAtom());
@ -3653,35 +3600,23 @@ bool JSScript::dumpGCThings(JSContext* cx, JS::Handle<JSScript*> script,
if (!utf8chars) {
return false;
}
if (!sp->put(utf8chars.get())) {
return false;
}
sp->put(utf8chars.get());
} else {
if (!sp->put("(anonymous)")) {
return false;
}
sp->put("(anonymous)");
}
if (fun->hasBaseScript()) {
BaseScript* script = fun->baseScript();
if (!sp->jsprintf(" @ %u:%u\n", script->lineno(),
script->column().zeroOriginValue())) {
return false;
}
sp->jsprintf(" @ %u:%u\n", script->lineno(),
script->column().zeroOriginValue());
} else {
if (!sp->put(" (no script)\n")) {
return false;
}
sp->put(" (no script)\n");
}
} else {
if (obj->is<RegExpObject>()) {
if (!sp->put("RegExp ")) {
return false;
}
sp->put("RegExp ");
} else {
if (!sp->put("Object ")) {
return false;
}
sp->put("Object ");
}
JS::Rooted<JS::Value> objValue(cx, ObjectValue(*obj));
@ -3693,39 +3628,24 @@ bool JSScript::dumpGCThings(JSContext* cx, JS::Handle<JSScript*> script,
if (!utf8chars) {
return false;
}
if (!sp->put(utf8chars.get())) {
return false;
}
if (!sp->put("\n")) {
return false;
}
sp->put(utf8chars.get());
sp->put("\n");
}
} else if (gcThing.is<JSString>()) {
JS::Rooted<JSString*> str(cx, &gcThing.as<JSString>());
if (str->isAtom()) {
if (!sp->put("Atom ")) {
return false;
}
sp->put("Atom ");
} else {
if (!sp->put("String ")) {
return false;
}
sp->put("String ");
}
JS::UniqueChars chars = QuoteString(cx, str, '"');
if (!chars) {
return false;
}
if (!sp->put(chars.get())) {
return false;
}
if (!sp->put("\n")) {
return false;
}
sp->put(chars.get());
sp->put("\n");
} else {
if (!sp->put("Unknown\n")) {
return false;
}
sp->put("Unknown\n");
}
i++;
}

Просмотреть файл

@ -29,7 +29,8 @@ class GenericPrinterPrintfTarget : public mozilla::PrintfTarget {
explicit GenericPrinterPrintfTarget(js::GenericPrinter& p) : printer(p) {}
bool append(const char* sp, size_t len) override {
return printer.put(sp, len);
printer.put(sp, len);
return true;
}
private:
@ -47,40 +48,36 @@ void GenericPrinter::reportOutOfMemory() {
hadOOM_ = true;
}
bool GenericPrinter::putAsciiPrintable(mozilla::Span<const JS::Latin1Char> str) {
void GenericPrinter::putAsciiPrintable(mozilla::Span<const JS::Latin1Char> str) {
#ifdef DEBUG
for (char c: str) {
MOZ_ASSERT(IsAsciiPrintable(c));
}
#endif
return put(reinterpret_cast<const char*>(&str[0]), str.Length());
put(reinterpret_cast<const char*>(&str[0]), str.Length());
}
bool GenericPrinter::putAsciiPrintable(mozilla::Span<const char16_t> str) {
void GenericPrinter::putAsciiPrintable(mozilla::Span<const char16_t> str) {
for (char16_t c: str) {
if (!putAsciiPrintable(c)) {
return false;
}
putAsciiPrintable(c);
}
return true;
}
bool GenericPrinter::printf(const char* fmt, ...) {
void GenericPrinter::printf(const char* fmt, ...) {
va_list va;
va_start(va, fmt);
bool r = vprintf(fmt, va);
vprintf(fmt, va);
va_end(va);
return r;
}
bool GenericPrinter::vprintf(const char* fmt, va_list ap) {
void GenericPrinter::vprintf(const char* fmt, va_list ap) {
// Simple shortcut to avoid allocating strings.
if (strchr(fmt, '%') == nullptr) {
return put(fmt);
put(fmt);
}
GenericPrinterPrintfTarget printer(*this);
return printer.vprint(fmt, ap);
(void) printer.vprint(fmt, ap);
}
const size_t Sprinter::DefaultSize = 64;
@ -228,7 +225,7 @@ char* Sprinter::reserve(size_t len) {
return sb;
}
bool Sprinter::put(const char* s, size_t len) {
void Sprinter::put(const char* s, size_t len) {
InvariantChecker ic(this);
const char* oldBase = base;
@ -236,7 +233,7 @@ bool Sprinter::put(const char* s, size_t len) {
char* bp = reserve(len);
if (!bp) {
return true;
return;
}
// s is within the buffer already
@ -250,23 +247,22 @@ bool Sprinter::put(const char* s, size_t len) {
}
bp[len] = '\0';
return true;
}
bool Sprinter::putString(JSString* s) {
void Sprinter::putString(JSString* s) {
MOZ_ASSERT(maybeCx);
InvariantChecker ic(this);
JSLinearString* linear = s->ensureLinear(maybeCx);
if (!linear) {
return true;
return;
}
size_t length = JS::GetDeflatedUTF8StringLength(linear);
char* buffer = reserve(length);
if (!buffer) {
return true;
return;
}
mozilla::DebugOnly<size_t> written =
@ -274,7 +270,6 @@ bool Sprinter::putString(JSString* s) {
MOZ_ASSERT(written == length);
buffer[length] = '\0';
return true;
}
size_t Sprinter::length() const { return size_t(offset); }
@ -286,14 +281,11 @@ void Sprinter::forwardOutOfMemory() {
}
}
bool Sprinter::jsprintf(const char* format, ...) {
void Sprinter::jsprintf(const char* format, ...) {
va_list ap;
va_start(ap, format);
bool r = vprintf(format, ap);
vprintf(format, ap);
va_end(ap);
return r;
}
const char js_EscapeMap[] = {
@ -333,12 +325,10 @@ JS_PUBLIC_API bool QuoteString(Sprinter* sp,
using CharPtr = mozilla::RangedPtr<const CharT>;
const char* escapeMap =
(target == QuoteTarget::String) ? js_EscapeMap : JSONEscapeMap;
(target == QuoteTarget::String) ? js::js_EscapeMap : JSONEscapeMap;
if (quote) {
if (!sp->putChar(quote)) {
return false;
}
sp->putChar(quote);
}
const CharPtr end = chars.end();
@ -367,9 +357,7 @@ JS_PUBLIC_API bool QuoteString(Sprinter* sp,
}
mozilla::Span<const CharT> span(s.get(), t - s);
if (!sp->putAsciiPrintable(span)) {
return false;
}
sp->putAsciiPrintable(span);
if (t == end) {
break;
@ -379,26 +367,20 @@ JS_PUBLIC_API bool QuoteString(Sprinter* sp,
const char* escape;
if (!(c >> 8) && c != 0 &&
(escape = strchr(escapeMap, int(c))) != nullptr) {
if (!sp->jsprintf("\\%c", escape[1])) {
return false;
}
sp->jsprintf("\\%c", escape[1]);
} else {
/*
* Use \x only if the high byte is 0 and we're in a quoted string,
* because ECMA-262 allows only \u, not \x, in Unicode identifiers
* (see bug 621814).
*/
if (!sp->jsprintf((quote && !(c >> 8)) ? "\\x%02X" : "\\u%04X", c)) {
return false;
}
sp->jsprintf((quote && !(c >> 8)) ? "\\x%02X" : "\\u%04X", c);
}
}
/* Sprint the closing quote and return the quoted string. */
if (quote) {
if (!sp->putChar(quote)) {
return false;
}
sp->putChar(quote);
}
return true;
@ -492,28 +474,27 @@ void Fprinter::finish() {
file_ = nullptr;
}
bool Fprinter::put(const char* s, size_t len) {
void Fprinter::put(const char* s, size_t len) {
if (hadOutOfMemory()) {
return true;
return;
}
MOZ_ASSERT(file_);
int i = fwrite(s, /*size=*/1, /*nitems=*/len, file_);
if (size_t(i) != len) {
reportOutOfMemory();
return false;
return;
}
#ifdef XP_WIN
if ((file_ == stderr) && (IsDebuggerPresent())) {
UniqueChars buf = DuplicateString(s, len);
if (!buf) {
reportOutOfMemory();
return false;
return;
}
OutputDebugStringA(buf.get());
}
#endif
return true;
}
LSprinter::LSprinter(LifoAlloc* lifoAlloc)
@ -542,9 +523,9 @@ void LSprinter::clear() {
hadOOM_ = false;
}
bool LSprinter::put(const char* s, size_t len) {
void LSprinter::put(const char* s, size_t len) {
if (hadOutOfMemory()) {
return true;
return;
}
// Compute how much data will fit in the current chunk.
@ -566,7 +547,7 @@ bool LSprinter::put(const char* s, size_t len) {
last = reinterpret_cast<Chunk*>(alloc_->alloc(allocLength));
if (!last) {
reportOutOfMemory();
return false;
return;
}
}
@ -610,7 +591,6 @@ bool LSprinter::put(const char* s, size_t len) {
}
MOZ_ASSERT(len <= INT_MAX);
return true;
}
} // namespace js

Просмотреть файл

@ -392,88 +392,55 @@ void Scope::dump() {
/* static */
bool Scope::dumpForDisassemble(JSContext* cx, JS::Handle<Scope*> scope,
GenericPrinter& out, const char* indent) {
if (!out.put(ScopeKindString(scope->kind()))) {
return false;
}
if (!out.put(" {")) {
return false;
}
out.put(ScopeKindString(scope->kind()));
out.put(" {");
size_t i = 0;
for (Rooted<BindingIter> bi(cx, BindingIter(scope)); bi; bi++, i++) {
if (i == 0) {
if (!out.put("\n")) {
return false;
}
out.put("\n");
}
UniqueChars bytes = AtomToPrintableString(cx, bi.name());
if (!bytes) {
return false;
}
if (!out.put(indent)) {
return false;
}
if (!out.printf(" %2zu: %s %s ", i, BindingKindString(bi.kind()),
bytes.get())) {
return false;
}
out.put(indent);
out.printf(" %2zu: %s %s ", i, BindingKindString(bi.kind()), bytes.get());
switch (bi.location().kind()) {
case BindingLocation::Kind::Global:
if (bi.isTopLevelFunction()) {
if (!out.put("(global function)\n")) {
return false;
}
out.put("(global function)\n");
} else {
if (!out.put("(global)\n")) {
return false;
}
out.put("(global)\n");
}
break;
case BindingLocation::Kind::Argument:
if (!out.printf("(arg slot %u)\n", bi.location().argumentSlot())) {
return false;
}
out.printf("(arg slot %u)\n", bi.location().argumentSlot());
break;
case BindingLocation::Kind::Frame:
if (!out.printf("(frame slot %u)\n", bi.location().slot())) {
return false;
}
out.printf("(frame slot %u)\n", bi.location().slot());
break;
case BindingLocation::Kind::Environment:
if (!out.printf("(env slot %u)\n", bi.location().slot())) {
return false;
}
out.printf("(env slot %u)\n", bi.location().slot());
break;
case BindingLocation::Kind::NamedLambdaCallee:
if (!out.put("(named lambda callee)\n")) {
return false;
}
out.put("(named lambda callee)\n");
break;
case BindingLocation::Kind::Import:
if (!out.put("(import)\n")) {
return false;
}
out.put("(import)\n");
break;
}
}
if (i > 0) {
if (!out.put(indent)) {
return false;
}
}
if (!out.put("}")) {
return false;
out.put(indent);
}
out.put("}");
ScopeIter si(scope);
si++;
for (; si; si++) {
if (!out.put(" -> ")) {
return false;
}
if (!out.put(ScopeKindString(si.kind()))) {
return false;
}
out.put(" -> ");
out.put(ScopeKindString(si.kind()));
}
return true;
}