Backed out changeset d737bf8f1ca2 (bug 1692462) for bustages in check_vanilla_allocations.py. CLOSED TREE

This commit is contained in:
Brindusan Cristian 2021-03-02 10:22:57 +02:00
Родитель 65745dbb4a
Коммит 85f0d3073f
10 изменённых файлов: 60 добавлений и 289 удалений

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

@ -23,7 +23,6 @@
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <functional>
#include <initializer_list>
#include <iterator>
#include <utility>
@ -1256,79 +1255,6 @@ static bool DisassembleNative(JSContext* cx, unsigned argc, Value* vp) {
return true;
}
static bool ComputeTier(JSContext* cx, const wasm::Code& code,
HandleValue tierSelection, wasm::Tier* tier) {
*tier = code.stableTier();
if (!tierSelection.isUndefined() &&
!ConvertToTier(cx, tierSelection, code, tier)) {
JS_ReportErrorASCII(cx, "invalid tier");
return false;
}
if (!code.hasTier(*tier)) {
JS_ReportErrorASCII(cx, "function missing selected tier");
return false;
}
return true;
}
static bool DisassembleIt(
JSContext* cx, bool asString, MutableHandleValue rval,
const std::function<void(void (*)(const char* text))>& disassembleIt) {
if (asString) {
DisasmBuffer buf(cx);
disasmBuf.set(&buf);
auto onFinish = mozilla::MakeScopeExit([&] { disasmBuf.set(nullptr); });
disassembleIt(captureDisasmText);
if (buf.oom) {
ReportOutOfMemory(cx);
return false;
}
JSString* sresult = buf.builder.finishString();
if (!sresult) {
ReportOutOfMemory(cx);
return false;
}
rval.setString(sresult);
return true;
}
disassembleIt([](const char* text) { fprintf(stderr, "%s\n", text); });
return true;
}
static bool WasmDisassembleFunction(JSContext* cx, const HandleFunction& func,
HandleValue tierSelection, bool asString,
MutableHandleValue rval) {
wasm::Instance& instance = wasm::ExportedFunctionToInstance(func);
uint32_t funcIndex = wasm::ExportedFunctionToFuncIndex(func);
wasm::Tier tier;
if (!ComputeTier(cx, instance.code(), tierSelection, &tier)) {
return false;
}
return DisassembleIt(
cx, asString, rval, [&](void (*captureText)(const char*)) {
instance.disassembleExport(cx, funcIndex, tier, captureText);
});
}
static bool WasmDisassembleCode(JSContext* cx, const wasm::Code& code,
HandleValue tierSelection, int kindSelection,
bool asString, MutableHandleValue rval) {
wasm::Tier tier;
if (!ComputeTier(cx, code, tierSelection, &tier)) {
return false;
}
return DisassembleIt(cx, asString, rval,
[&](void (*captureText)(const char*)) {
code.disassemble(cx, tier, kindSelection, captureText);
});
}
static bool WasmDisassemble(JSContext* cx, unsigned argc, Value* vp) {
if (!cx->options().wasm()) {
JS_ReportErrorASCII(cx, "wasm support unavailable");
@ -1344,87 +1270,51 @@ static bool WasmDisassemble(JSContext* cx, unsigned argc, Value* vp) {
return false;
}
bool asString = false;
RootedValue tierSelection(cx);
int kindSelection = (1 << wasm::CodeRange::Function);
if (args.length() > 1 && args[1].isObject()) {
RootedObject options(cx, &args[1].toObject());
RootedValue val(cx);
if (!JS_GetProperty(cx, options, "asString", &val)) {
return false;
}
asString = val.isBoolean() && val.toBoolean();
if (!JS_GetProperty(cx, options, "tier", &tierSelection)) {
return false;
}
if (!JS_GetProperty(cx, options, "kinds", &val)) {
return false;
}
if (val.isString() && val.toString()->hasLatin1Chars()) {
AutoStableStringChars stable(cx);
if (!stable.init(cx, val.toString())) {
return false;
}
const char* p = (const char*)(stable.latin1Chars());
const char* end = p + val.toString()->length();
int selection = 0;
for (;;) {
if (strncmp(p, "Function", 8) == 0) {
selection |= (1 << wasm::CodeRange::Function);
p += 8;
} else if (strncmp(p, "InterpEntry", 11) == 0) {
selection |= (1 << wasm::CodeRange::InterpEntry);
p += 11;
} else if (strncmp(p, "JitEntry", 8) == 0) {
selection |= (1 << wasm::CodeRange::JitEntry);
p += 8;
} else if (strncmp(p, "ImportInterpExit", 16) == 0) {
selection |= (1 << wasm::CodeRange::ImportInterpExit);
p += 16;
} else if (strncmp(p, "ImportJitExit", 13) == 0) {
selection |= (1 << wasm::CodeRange::ImportJitExit);
p += 13;
} else if (strncmp(p, "all", 3) == 0) {
selection = ~0;
p += 3;
} else {
break;
}
if (p == end || *p != ',') {
break;
}
p++;
}
if (p == end) {
kindSelection = selection;
} else {
JS_ReportErrorASCII(cx, "argument object has invalid `kinds`");
return false;
}
}
}
RootedFunction func(cx, args[0].toObject().maybeUnwrapIf<JSFunction>());
if (func && wasm::IsWasmExportedFunction(func)) {
return WasmDisassembleFunction(cx, func, tierSelection, asString,
args.rval());
if (!func || !wasm::IsWasmExportedFunction(func)) {
JS_ReportErrorASCII(cx, "argument is not an exported wasm function");
return false;
}
if (args[0].toObject().is<WasmModuleObject>()) {
return WasmDisassembleCode(
cx, args[0].toObject().as<WasmModuleObject>().module().code(),
tierSelection, kindSelection, asString, args.rval());
wasm::Instance& instance = wasm::ExportedFunctionToInstance(func);
uint32_t funcIndex = wasm::ExportedFunctionToFuncIndex(func);
wasm::Tier tier = instance.code().stableTier();
if (args.length() > 1 &&
!ConvertToTier(cx, args[1], instance.code(), &tier)) {
JS_ReportErrorASCII(cx, "invalid tier");
return false;
}
if (args[0].toObject().is<WasmInstanceObject>()) {
return WasmDisassembleCode(
cx, args[0].toObject().as<WasmInstanceObject>().instance().code(),
tierSelection, kindSelection, asString, args.rval());
if (!instance.code().hasTier(tier)) {
JS_ReportErrorASCII(cx, "function missing selected tier");
return false;
}
JS_ReportErrorASCII(
cx, "argument is not an exported wasm function or a wasm module");
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;
}
enum class Flag { Tier2Complete, Deserialized };
@ -6989,22 +6879,11 @@ gc::ZealModeHelpText),
" until background compilation is complete."),
JS_FN_HELP("wasmDis", WasmDisassemble, 1, 0,
"wasmDis(wasmObject[, options])\n",
" Disassembles generated machine code from an exported WebAssembly function,\n"
" or from all the functions defined in the module or instance, exported and not.\n"
" The `options` is an object with the following optional keys:\n"
" asString: boolean - if true, return a string rather than printing on stderr,\n"
" the default is false.\n"
" tier: string - one of 'stable', 'best', 'baseline', or 'ion'; the default is\n"
" 'stable'.\n"
" kinds: string - if set, and the wasmObject is a module or instance, a\n"
" comma-separated list of the following keys, the default is `Function`:\n"
" Function - functions defined in the module\n"
" InterpEntry - C++-to-wasm stubs\n"
" JitEntry - jitted-js-to-wasm stubs\n"
" ImportInterpExit - wasm-to-C++ stubs\n"
" ImportJitExit - wasm-to-jitted-JS stubs\n"
" all - all kinds, including obscure ones\n"),
"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'. 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)",

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

@ -147,7 +147,7 @@ function codegenTestX64_adhoc(module_text, export_name, expected, options = {})
let ins = wasmEvalText(module_text, {}, options.features);
if (options.instanceBox)
options.instanceBox.value = ins;
let output = wasmDis(ins.exports[export_name], {tier:"ion", asString:true});
let output = wasmDis(ins.exports[export_name], "ion", true);
if (!options.no_prefix)
expected = x64_prefix + '\n' + expected;
if (!options.no_suffix)

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

@ -49,7 +49,7 @@ function codegenTestX86_adhoc(module_text, export_name, expected, options = {})
assertEq(hasDisassembler(), true);
let ins = wasmEvalText(module_text);
let output = wasmDis(ins.exports[export_name], {tier:"ion", asString:true});
let output = wasmDis(ins.exports[export_name], "ion", true);
if (!options.no_prefix)
expected = x86_prefix + '\n' + expected;
if (!options.no_suffix)

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

@ -1,43 +0,0 @@
// |jit-test| skip-if: !hasDisassembler()
// Test that the disassembler is reasonably sane.
var mod = new WebAssembly.Module(wasmTextToBinary(`
(module
(func $hum (import "m" "hum") (param i32) (result f64))
(memory 1)
(func $hi (export "f") (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (param i32) (result i32)
(i32.add (i32.load (local.get 5)) (i32.load (local.get 6))))
(func $ho (param i32) (result i32) (i32.const 37))
)
`));
// The following capture the disassembly as a string. We can't really check
// that no other output is produced.
var s = wasmDis(mod, {tier:'best', asString:true});
assertEq(typeof s, "string")
assertEq(s.match(/Kind = Function/g).length, 3)
var ins = new WebAssembly.Instance(mod, {m:{hum:(x) => x+0.5}});
var s = wasmDis(ins, {tier:'best', asString:true});
assertEq(typeof s, "string")
assertEq(s.match(/Kind = Function/g).length, 3)
var s = wasmDis(ins.exports.f, {tier:'best', asString:true})
assertEq(typeof s, "string")
var s = wasmDis(ins, {asString:true, kinds:"InterpEntry,ImportInterpExit,Function"})
assertEq(typeof s, "string")
assertEq(s.match(/Kind = Function/g).length, 3)
assertEq(s.match(/Kind = InterpEntry/g).length, 1)
assertEq(s.match(/Kind = ImportInterpExit/g).length, 1)
assertEq(s.match(/name = hi/g).length, 2)
assertEq(s.match(/name = ho/g).length, 1)
assertEq(s.match(/name = hum/g).length, 2)
// This one prints to stderr, we can't check the output but we can check that a
// string is not returned.
var s = wasmDis(ins, {tier:'best'})
assertEq(typeof s, "undefined")

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

@ -86,7 +86,7 @@ ${suffix}
(v128.store (i32.const 0) (call $f)))
(func $f (export "f") (result v128)
(v128.const ${bits})))`);
let output = wasmDis(ins.exports.f, {tier:"baseline", asString:true});
let output = wasmDis(ins.exports.f, "baseline", true);
assertEq(output.match(new RegExp(expected)) != null, true);
let mem = new Int8Array(ins.exports.mem.buffer);
set(mem, 0, iota(16).map(x => -1-x));

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

@ -23,16 +23,16 @@ var ins = wasmEvalText(`
switch (wasmCompileMode()) {
case "ion":
assertEq(wasmDis(ins.exports.wasm2wasm, {tier:'stable', asString:true}).match(/call.*\n.*mov %eax, %eax/).length, 1);
assertEq(wasmDis(ins.exports.wasm2import, {tier:'stable', asString:true}).match(/call.*\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1);
assertEq(wasmDis(ins.exports.wasmIndirect, {tier:'stable', asString:true}).match(/call.*\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1);
assertEq(wasmDis(ins.exports.instanceCall, {tier:'stable', asString:true}).match(/call.*\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1);
assertEq(wasmDis(ins.exports.wasm2wasm, 'stable', true).match(/call.*\n.*mov %eax, %eax/).length, 1);
assertEq(wasmDis(ins.exports.wasm2import, 'stable', true).match(/call.*\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1);
assertEq(wasmDis(ins.exports.wasmIndirect, 'stable', true).match(/call.*\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1);
assertEq(wasmDis(ins.exports.instanceCall, 'stable', true).match(/call.*\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1);
break;
case "baseline":
assertEq(wasmDis(ins.exports.wasm2wasm, {tier:'stable', asString:true}).match(/call.*\n.*add.*%rsp\n.*mov %eax, %eax/).length, 1);
assertEq(wasmDis(ins.exports.wasm2import, {tier:'stable', asString:true}).match(/call.*\n.*add.*%rsp\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1);
assertEq(wasmDis(ins.exports.wasmIndirect, {tier:'stable', asString:true}).match(/call.*\n.*add.*%rsp\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1);
assertEq(wasmDis(ins.exports.instanceCall, {tier:'stable', asString:true}).match(/call.*\n.*add.*%rsp\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1);
assertEq(wasmDis(ins.exports.wasm2wasm, 'stable', true).match(/call.*\n.*add.*%rsp\n.*mov %eax, %eax/).length, 1);
assertEq(wasmDis(ins.exports.wasm2import, 'stable', true).match(/call.*\n.*add.*%rsp\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1);
assertEq(wasmDis(ins.exports.wasmIndirect, 'stable', true).match(/call.*\n.*add.*%rsp\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1);
assertEq(wasmDis(ins.exports.instanceCall, 'stable', true).match(/call.*\n.*add.*%rsp\n(?:.*movq.*\n)*.*mov %eax, %eax/).length, 1);
break;
default:
throw "Unexpected compile mode";

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

@ -25,7 +25,6 @@
#include "jsnum.h"
#include "jit/Disassemble.h"
#include "jit/ExecutableAllocator.h"
#ifdef JS_ION_PERF
# include "jit/PerfSpewer.h"
@ -1537,65 +1536,6 @@ uint8_t* Code::serialize(uint8_t* cursor, const LinkData& linkData) const {
return cursor;
}
void Code::disassemble(JSContext* cx, Tier tier, int kindSelection,
PrintCallback printString) const {
const MetadataTier& metadataTier = metadata(tier);
const CodeTier& codeTier = this->codeTier(tier);
const ModuleSegment& segment = codeTier.segment();
for (const CodeRange& range : metadataTier.codeRanges) {
if (kindSelection & (1 << range.kind())) {
MOZ_ASSERT(range.begin() < segment.length());
MOZ_ASSERT(range.end() < segment.length());
const char* kind;
char kindbuf[128];
switch (range.kind()) {
case CodeRange::Function:
kind = "Function";
break;
case CodeRange::InterpEntry:
kind = "InterpEntry";
break;
case CodeRange::JitEntry:
kind = "JitEntry";
break;
case CodeRange::ImportInterpExit:
kind = "ImportInterpExit";
break;
case CodeRange::ImportJitExit:
kind = "ImportJitExit";
break;
default:
SprintfLiteral(kindbuf, "CodeRange::Kind(%d)", range.kind());
kind = kindbuf;
break;
}
const char* separator =
"\n--------------------------------------------------\n";
// The buffer is quite large in order to accomodate mangled C++ names;
// lengths over 3500 have been observed in the wild.
char buf[4096];
if (range.hasFuncIndex()) {
const char* funcName = "(unknown)";
UTF8Bytes namebuf;
if (metadata().getFuncNameStandalone(range.funcIndex(), &namebuf) &&
namebuf.append('\0')) {
funcName = namebuf.begin();
}
SprintfLiteral(buf, "%sKind = %s, index = %d, name = %s:\n", separator,
kind, range.funcIndex(), funcName);
} else {
SprintfLiteral(buf, "%sKind = %s\n", separator, kind);
}
printString(buf);
uint8_t* theCode = segment.base() + range.begin();
jit::Disassemble(theCode, range.end() - range.begin(), printString);
}
}
}
void wasm::PatchDebugSymbolicAccesses(uint8_t* codeBase, MacroAssembler& masm) {
#ifdef WASM_CODEGEN_DEBUG
for (auto& access : masm.symbolicAccesses()) {

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

@ -748,11 +748,6 @@ class Code : public ShareableBase<Code> {
void ensureProfilingLabels(bool profilingEnabled) const;
const char* profilingLabel(uint32_t funcIndex) const;
// Wasm disassembly support
void disassemble(JSContext* cx, Tier tier, int kindSelection,
PrintCallback printString) const;
// about:memory reporting:
void addSizeOfMiscIfNotSeen(MallocSizeOf mallocSizeOf,

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

@ -2123,7 +2123,7 @@ void Instance::destroyBreakpointSite(JSFreeOp* fop, uint32_t offset) {
}
void Instance::disassembleExport(JSContext* cx, uint32_t funcIndex, Tier tier,
PrintCallback printString) const {
PrintCallback callback) const {
const MetadataTier& metadataTier = metadata(tier);
const FuncExport& funcExport = metadataTier.lookupFuncExport(funcIndex);
const CodeRange& range = metadataTier.codeRange(funcExport);
@ -2134,7 +2134,7 @@ void Instance::disassembleExport(JSContext* cx, uint32_t funcIndex, Tier tier,
MOZ_ASSERT(range.end() < segment.length());
uint8_t* functionCode = segment.base() + range.begin();
jit::Disassemble(functionCode, range.end() - range.begin(), printString);
jit::Disassemble(functionCode, range.end() - range.begin(), callback);
}
void Instance::addSizeOfMisc(MallocSizeOf mallocSizeOf,

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

@ -175,7 +175,7 @@ class Instance {
// Wasm disassembly support
void disassembleExport(JSContext* cx, uint32_t funcIndex, Tier tier,
PrintCallback printString) const;
PrintCallback callback) const;
public:
// Functions to be called directly from wasm code.