Commit 172f5012 authored by clemensh's avatar clemensh Committed by Commit bot

[wasm] Implement official wasm text format

When disassembling functions for the inspector, we used an internal
text representation before. This CL implements the official text
format like it is understood by the spec interpreter.

Example output:
func $main (param i32) (result i32)
block i32
  get_local 0
  i32.const 2
  i32.lt_u
  if
    i32.const -2
    return
  end
  get_local 0
  call_indirect 0
end

R=rossberg@chromium.org, titzer@chromium.org
BUG=chromium:659715

Review-Url: https://codereview.chromium.org/2520943002
Cr-Commit-Position: refs/heads/master@{#41172}
parent ffe2fbf8
......@@ -1756,6 +1756,8 @@ v8_source_set("v8_base") {
"src/wasm/wasm-opcodes.h",
"src/wasm/wasm-result.cc",
"src/wasm/wasm-result.h",
"src/wasm/wasm-text.cc",
"src/wasm/wasm-text.h",
"src/zone/accounting-allocator.cc",
"src/zone/accounting-allocator.h",
"src/zone/zone-allocator.h",
......
......@@ -36,6 +36,7 @@
#include "src/wasm/ast-decoder.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-text.h"
// TODO(titzer): pull WASM_64 up to a common header.
#if !V8_TARGET_ARCH_32_BIT || V8_TARGET_ARCH_X64
......@@ -3359,6 +3360,10 @@ SourcePositionTable* WasmCompilationUnit::BuildGraphForWasmFunction(
OFStream os(stdout);
PrintAst(isolate_->allocator(), body, os, nullptr);
}
if (index >= FLAG_trace_wasm_text_start && index < FLAG_trace_wasm_text_end) {
OFStream os(stdout);
PrintWasmText(module_env_->module, function_->func_index, os, nullptr);
}
if (FLAG_trace_wasm_decode_time) {
*decode_ms = decode_timer.Elapsed().InMillisecondsF();
}
......
......@@ -498,6 +498,10 @@ DEFINE_BOOL(trace_wasm_interpreter, false, "trace interpretation of wasm code")
DEFINE_INT(trace_wasm_ast_start, 0,
"start function for WASM AST trace (inclusive)")
DEFINE_INT(trace_wasm_ast_end, 0, "end function for WASM AST trace (exclusive)")
DEFINE_INT(trace_wasm_text_start, 0,
"start function for WASM text generation (inclusive)")
DEFINE_INT(trace_wasm_text_end, 0,
"end function for WASM text generation (exclusive)")
DEFINE_INT(skip_compiling_wasm_funcs, 0, "start compiling at function N")
DEFINE_BOOL(wasm_break_on_decoder_error, false,
"debug break when wasm decoder encounters an error")
......
......@@ -1294,6 +1294,8 @@
'wasm/wasm-opcodes.h',
'wasm/wasm-result.cc',
'wasm/wasm-result.h',
'wasm/wasm-text.cc',
'wasm/wasm-text.h',
'zone/accounting-allocator.cc',
'zone/accounting-allocator.h',
'zone/zone-segment.cc',
......
......@@ -243,10 +243,6 @@ struct BranchTableOperand {
}
table = pc + 1 + len1;
}
inline uint32_t read_entry(Decoder* decoder, unsigned i) {
DCHECK(i <= table_count);
return table ? decoder->read_u32(table + i * sizeof(uint32_t)) : 0;
}
};
// A helper to iterate over a branch table.
......
......@@ -20,6 +20,7 @@
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects.h"
#include "src/wasm/wasm-result.h"
#include "src/wasm/wasm-text.h"
#include "src/compiler/wasm-compiler.h"
......@@ -634,15 +635,6 @@ std::pair<int, int> GetFunctionOffsetAndLength(
static_cast<int>(func.code_end_offset - func.code_start_offset)};
}
Vector<const uint8_t> GetFunctionBytes(
Handle<WasmCompiledModule> compiled_module, int func_index) {
int offset, length;
std::tie(offset, length) =
GetFunctionOffsetAndLength(compiled_module, func_index);
return Vector<const uint8_t>(
compiled_module->module_bytes()->GetChars() + offset, length);
}
} // namespace
Handle<JSArrayBuffer> wasm::NewArrayBuffer(Isolate* isolate, size_t size,
......@@ -1977,19 +1969,16 @@ Handle<Script> wasm::GetScript(Handle<JSObject> instance) {
std::pair<std::string, std::vector<std::tuple<uint32_t, int, int>>>
wasm::DisassembleFunction(Handle<WasmCompiledModule> compiled_module,
int func_index) {
if (func_index < 0 ||
static_cast<uint32_t>(func_index) >=
compiled_module->module()->functions.size())
return {};
std::ostringstream disassembly_os;
std::vector<std::tuple<uint32_t, int, int>> offset_table;
Vector<const uint8_t> func_bytes =
GetFunctionBytes(compiled_module, func_index);
DisallowHeapAllocation no_gc;
if (func_bytes.is_empty()) return {};
AccountingAllocator allocator;
bool ok = PrintAst(
&allocator, FunctionBodyForTesting(func_bytes.start(), func_bytes.end()),
disassembly_os, &offset_table);
CHECK(ok);
PrintWasmText(compiled_module->module(), static_cast<uint32_t>(func_index),
disassembly_os, &offset_table);
return {disassembly_os.str(), std::move(offset_table)};
}
......@@ -2030,6 +2019,7 @@ MaybeHandle<WasmModuleObject> wasm::CreateModuleObjectFromBytes(
thrower->CompileFailed("Wasm decoding failed", result);
return nothing;
}
// The {module_wrapper} will take ownership of the {WasmModule} object,
// and it will be destroyed when the GC reclaims the wrapper object.
Handle<WasmModuleWrapper> module_wrapper =
......
......@@ -390,6 +390,7 @@ Handle<Script> GetScript(Handle<JSObject> instance);
// Returns the disassembly string and a list of <byte_offset, line, column>
// entries, mapping wasm byte offsets to line and column in the disassembly.
// The list is guaranteed to be ordered by the byte_offset.
// Returns an empty string and empty vector if the function index is invalid.
std::pair<std::string, std::vector<std::tuple<uint32_t, int, int>>>
DisassembleFunction(Handle<WasmCompiledModule> compiled_module, int func_index);
......
This diff is collapsed.
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef V8_WASM_S_EXPR_H_
#define V8_WASM_S_EXPR_H_
#include <cstdint>
#include <ostream>
#include <tuple>
#include <vector>
namespace v8 {
namespace internal {
namespace wasm {
// Forward declaration.
struct WasmModule;
// Generate disassembly according to official text format.
// Output disassembly to the given output stream, and optionally return an
// offset table of <byte offset, line, column> via the given pointer.
void PrintWasmText(const WasmModule *module, uint32_t func_index,
std::ostream &os,
std::vector<std::tuple<uint32_t, int, int>> *offset_table);
} // namespace wasm
} // namespace internal
} // namespace v8
#endif // V8_WASM_S_EXPR_H_
......@@ -2,8 +2,8 @@ Check that inspector gets disassembled wasm code
Paused on debugger!
Number of frames: 5
[0] debugger;
[1] kExprCallFunction, 0x00, // function #0
[2] kExprCallIndirect, 0x02, 0x00, // sig #2
[1] call 0
[2] call_indirect 2
[3] instance.exports.main();
[4] testFunction(module_bytes)
Finished.
......@@ -2,8 +2,8 @@ Running testFunction with generated WASM bytes...
Paused on 'debugger;'
Number of frames: 5
- [0] {"functionName":"call_debugger","function_lineNumber":1,"function_columnNumber":24,"lineNumber":2,"columnNumber":4}
- [1] {"functionName":"call_func","lineNumber":3,"columnNumber":0}
- [2] {"functionName":"main","lineNumber":4,"columnNumber":2}
- [1] {"functionName":"call_func","lineNumber":1,"columnNumber":0}
- [2] {"functionName":"main","lineNumber":2,"columnNumber":2}
- [3] {"functionName":"testFunction","function_lineNumber":0,"function_columnNumber":21,"lineNumber":14,"columnNumber":19}
- [4] {"functionName":"","function_lineNumber":0,"function_columnNumber":0,"lineNumber":0,"columnNumber":0}
Getting v8-generated stack trace...
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment