Bug 1647991 - Allow wasmDis to return its result as a string. r=rhunt

This is useful for limited whitebox testing that inspects the assembly
output.  Ask me about details (s-s).

The code, adding a thread-local, is not completely pretty.  This
seemed like a better fix than adding the plumbing for a more elaborate
callback mechanism (basically we need to pass a context argument down
through the disassembly pipeline and adapt all the disassemblers),
though I'm open for discussion on this point.

Differential Revision: https://phabricator.services.mozilla.com/D80819
This commit is contained in:
Lars T Hansen 2020-06-24 19:17:40 +00:00
Родитель 6799964058
Коммит 57a5014959
3 изменённых файлов: 43 добавлений и 3 удалений

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

@ -13,6 +13,7 @@
#include "mozilla/Span.h"
#include "mozilla/Sprintf.h"
#include "mozilla/TextUtils.h"
#include "mozilla/ThreadLocal.h"
#include "mozilla/Tuple.h"
#include "mozilla/Unused.h"
@ -1008,6 +1009,21 @@ static bool WasmExtractCode(JSContext* cx, unsigned argc, Value* vp) {
return true;
}
struct DisasmBuffer {
JSStringBuilder builder;
bool oom;
explicit DisasmBuffer(JSContext* cx) : builder(cx), oom(false) {}
};
MOZ_THREAD_LOCAL(DisasmBuffer*) disasmBuf;
static void captureDisasmText(const char* text) {
DisasmBuffer* buf = disasmBuf.get();
if (!buf->builder.append(text, strlen(text)) || !buf->builder.append('\n')) {
buf->oom = true;
}
}
static bool WasmDisassemble(JSContext* cx, unsigned argc, Value* vp) {
if (!cx->options().wasm()) {
JS_ReportErrorASCII(cx, "wasm support unavailable");
@ -1046,10 +1062,27 @@ static bool WasmDisassemble(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
if (args.length() > 2 && args[2].isBoolean() && args[2].toBoolean()) {
DisasmBuffer buf(cx);
disasmBuf.set(&buf);
auto onFinish = mozilla::MakeScopeExit([&] { disasmBuf.set(nullptr); });
instance.disassembleExport(cx, funcIndex, tier, captureDisasmText);
if (buf.oom) {
ReportOutOfMemory(cx);
return false;
}
JSString* sresult = buf.builder.finishString();
if (!sresult) {
ReportOutOfMemory(cx);
return false;
}
args.rval().setString(sresult);
return true;
}
instance.disassembleExport(cx, funcIndex, tier, [](const char* text) {
fprintf(stderr, "%s\n", text);
});
return true;
}
@ -6376,10 +6409,11 @@ gc::ZealModeHelpText),
" until background compilation is complete."),
JS_FN_HELP("wasmDis", WasmDisassemble, 1, 0,
"wasmDis(function[, tier])",
"wasmDis(function[, tier [, asString]])",
" Disassembles generated machine code from an exported WebAssembly function.\n"
" The tier is a string, 'stable', 'best', 'baseline', or 'ion'; the default is\n"
" 'stable'."),
" 'stable'. If `asString` is present and is the value `true` then the output\n"
" is returned as a string; otherwise it is printed on stderr."),
JS_FN_HELP("wasmHasTier2CompilationCompleted", WasmHasTier2CompilationCompleted, 1, 0,
"wasmHasTier2CompilationCompleted(module)",
@ -6865,6 +6899,8 @@ static const JSFunctionSpecWithHelp PCCountProfilingTestingFunctions[] = {
};
// clang-format on
bool js::InitTestingFunctions() { return disasmBuf.init(); }
bool js::DefineTestingFunctions(JSContext* cx, HandleObject obj,
bool fuzzingSafe_, bool disableOOMFunctions_) {
fuzzingSafe = fuzzingSafe_;

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

@ -11,6 +11,8 @@
namespace js {
MOZ_MUST_USE bool InitTestingFunctions();
MOZ_MUST_USE bool DefineTestingFunctions(JSContext* cx, HandleObject obj,
bool fuzzingSafe,
bool disableOOMFunctions);

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

@ -15,6 +15,7 @@
#include "jstypes.h"
#include "builtin/AtomicsObject.h"
#include "builtin/TestingFunctions.h"
#include "ds/MemoryProtectionExceptionHandler.h"
#include "gc/Statistics.h"
#include "jit/AtomicOperations.h"
@ -201,6 +202,7 @@ JS_PUBLIC_API const char* JS::detail::InitWithFailureDiagnostic(
RETURN_IF_FAIL(js::CreateHelperThreadsState());
RETURN_IF_FAIL(FutexThread::initialize());
RETURN_IF_FAIL(js::gcstats::Statistics::initialize());
RETURN_IF_FAIL(js::InitTestingFunctions());
#ifdef JS_SIMULATOR
RETURN_IF_FAIL(js::jit::SimulatorProcess::initialize());