[wasm] Remove disassembly support

This was used for debugging only. The DevTools frontend now receives the
raw wasm bytes, and disassembles the functions it needed. The inspector
change was done in https://crrev.com/c/1991481.
This CL removes all code which is now dead in v8.

R=ahaas@chromium.org, bmeurer@chromium.org

Change-Id: I2d433613f1270a1ddac9af0bae8d990ef190712a
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2005072
Reviewed-by: Benedikt Meurer <bmeurer@chromium.org>
Reviewed-by: Andreas Haas <ahaas@chromium.org>
Commit-Queue: Clemens Backes <clemensb@chromium.org>
Cr-Commit-Position: refs/heads/master@{#65831}
This commit is contained in:
Clemens Backes 2020-01-16 21:24:32 +01:00 committed by Commit Bot
parent 90db2b7482
commit f66ffd544c
12 changed files with 59 additions and 832 deletions

238
BUILD.gn
View File

@ -830,15 +830,9 @@ template("asm_to_inline_asm") {
assert(emit_builtins_as_inline_asm)
script = "tools/snapshot/asm_to_inline_asm.py"
deps = [
":run_mksnapshot_" + name,
]
sources = [
"$target_gen_dir/embedded${suffix}.S",
]
outputs = [
"$target_gen_dir/embedded${suffix}.cc",
]
deps = [ ":run_mksnapshot_" + name ]
sources = [ "$target_gen_dir/embedded${suffix}.S" ]
outputs = [ "$target_gen_dir/embedded${suffix}.cc" ]
args = invoker.args
args += [
rebase_path("$target_gen_dir/embedded${suffix}.S", root_build_dir),
@ -852,9 +846,7 @@ if (is_android && enable_java_templates) {
if (v8_use_external_startup_data) {
# We don't support side-by-side snapshots on Android within Chromium.
assert(!v8_use_multi_snapshots)
deps = [
"//v8",
]
deps = [ "//v8" ]
renaming_sources = [ "$root_out_dir/snapshot_blob.bin" ]
if (current_cpu == "arm" || current_cpu == "x86" ||
current_cpu == "mipsel") {
@ -938,16 +930,12 @@ action("postmortem-metadata") {
"$target_gen_dir/torque-generated/instance-types-tq.h",
]
outputs = [
"$target_gen_dir/debug-support.cc",
]
outputs = [ "$target_gen_dir/debug-support.cc" ]
args = rebase_path(outputs, root_build_dir) +
rebase_path(sources, root_build_dir)
deps = [
":run_torque",
]
deps = [ ":run_torque" ]
}
torque_files = [
@ -1120,9 +1108,7 @@ action("run_torque") {
"test/cctest/:*",
]
deps = [
":torque($v8_generator_toolchain)",
]
deps = [ ":torque($v8_generator_toolchain)" ]
script = "tools/run.py"
@ -1171,9 +1157,7 @@ action("run_torque") {
group("v8_maybe_icu") {
if (v8_enable_i18n_support) {
public_deps = [
"//third_party/icu",
]
public_deps = [ "//third_party/icu" ]
}
}
@ -1185,9 +1169,7 @@ v8_source_set("torque_generated_initializers") {
":run_torque",
]
public_deps = [
":v8_maybe_icu",
]
public_deps = [ ":v8_maybe_icu" ]
sources = [
"$target_gen_dir/torque-generated/csa-types-tq.h",
@ -1215,9 +1197,7 @@ v8_source_set("torque_generated_definitions") {
":run_torque",
]
public_deps = [
":v8_maybe_icu",
]
public_deps = [ ":v8_maybe_icu" ]
sources = [
"$target_gen_dir/torque-generated/class-definitions-tq.cc",
@ -1231,12 +1211,8 @@ v8_source_set("torque_generated_definitions") {
action("generate_bytecode_builtins_list") {
script = "tools/run.py"
outputs = [
"$target_gen_dir/builtins-generated/bytecodes-builtins-list.h",
]
deps = [
":bytecode_builtins_list_generator($v8_generator_toolchain)",
]
outputs = [ "$target_gen_dir/builtins-generated/bytecodes-builtins-list.h" ]
deps = [ ":bytecode_builtins_list_generator($v8_generator_toolchain)" ]
args = [
"./" + rebase_path(
get_label_info(
@ -1268,9 +1244,7 @@ template("run_mksnapshot") {
action("run_mksnapshot_" + name) {
visibility = [ ":*" ] # Only targets in this file can depend on this.
deps = [
":mksnapshot($v8_snapshot_toolchain)",
]
deps = [ ":mksnapshot($v8_snapshot_toolchain)" ]
script = "tools/run.py"
@ -1401,9 +1375,7 @@ if (v8_use_multi_snapshots) {
action("v8_dump_build_config") {
script = "tools/testrunner/utils/dump_build_config.py"
outputs = [
"$root_out_dir/v8_build_config.json",
]
outputs = [ "$root_out_dir/v8_build_config.json" ]
is_gcov_coverage = v8_code_coverage && !is_clang
is_full_debug = v8_enable_debugging_features && !v8_optimized_debug
args = [
@ -1457,9 +1429,7 @@ v8_source_set("v8_snapshot") {
# Do not publicize any header to remove build dependency.
public = []
sources = [
"src/init/setup-isolate-deserialize.cc",
]
sources = [ "src/init/setup-isolate-deserialize.cc" ]
if (emit_builtins_as_inline_asm) {
deps += [ ":asm_to_inline_asm_default" ]
sources += [ "$target_gen_dir/embedded.cc" ]
@ -1499,9 +1469,7 @@ v8_source_set("v8_initializers") {
"test/cctest:*",
]
deps = [
":torque_generated_initializers",
]
deps = [ ":torque_generated_initializers" ]
sources = [
### gcmole(all) ###
@ -1624,18 +1592,14 @@ v8_source_set("v8_initializers") {
v8_source_set("v8_init") {
visibility = [ ":*" ] # Only targets in this file can depend on this.
deps = [
":v8_initializers",
]
deps = [ ":v8_initializers" ]
sources = [
### gcmole(all) ###
"src/init/setup-isolate-full.cc",
]
public_deps = [
":v8_maybe_icu",
]
public_deps = [ ":v8_maybe_icu" ]
configs = [ ":internal_config" ]
}
@ -1672,9 +1636,7 @@ v8_header_set("v8_headers") {
"include/v8-wasm-trap-handler-win.h",
]
deps = [
":v8_version",
]
deps = [ ":v8_version" ]
}
# This is split out to share basic headers with Torque.
@ -1682,13 +1644,9 @@ v8_header_set("v8_shared_internal_headers") {
visibility = [ ":*" ] # Only targets in this file can depend on this.
configs = [ ":internal_config" ]
sources = [
"src/common/globals.h",
]
sources = [ "src/common/globals.h" ]
deps = [
":v8_headers",
]
deps = [ ":v8_headers" ]
}
v8_compiler_sources = [
@ -1969,13 +1927,9 @@ v8_source_set("v8_compiler") {
group("v8_compiler_for_mksnapshot") {
if (is_debug && !v8_optimized_debug && v8_enable_fast_mksnapshot) {
deps = [
":v8_compiler_opt",
]
deps = [ ":v8_compiler_opt" ]
} else {
deps = [
":v8_compiler",
]
deps = [ ":v8_compiler" ]
}
}
@ -2978,8 +2932,6 @@ v8_source_set("v8_base_without_compiler") {
"src/wasm/wasm-result.h",
"src/wasm/wasm-serialization.cc",
"src/wasm/wasm-serialization.h",
"src/wasm/wasm-text.cc",
"src/wasm/wasm-text.h",
"src/wasm/wasm-tier.h",
"src/wasm/wasm-value.h",
"src/zone/accounting-allocator.cc",
@ -3428,13 +3380,9 @@ v8_source_set("torque_base") {
"src/torque/utils.h",
]
deps = [
":v8_shared_internal_headers",
]
deps = [ ":v8_shared_internal_headers" ]
public_deps = [
":v8_libbase",
]
public_deps = [ ":v8_libbase" ]
# The use of exceptions for Torque in violation of the Chromium style-guide
# is justified by the fact that it is only used from the non-essential
@ -3477,9 +3425,7 @@ v8_source_set("torque_ls_base") {
"src/torque/ls/message.h",
]
public_deps = [
":torque_base",
]
public_deps = [ ":torque_base" ]
# The use of exceptions for Torque in violation of the Chromium style-guide
# is justified by the fact that it is only used from the non-essential
@ -3580,9 +3526,7 @@ v8_component("v8_libbase") {
public_configs = [ ":libbase_config" ]
deps = [
":v8_headers",
]
deps = [ ":v8_headers" ]
public_deps = []
@ -3768,9 +3712,7 @@ v8_source_set("v8_libsampler") {
public_configs = [ ":libsampler_config" ]
deps = [
":v8_libbase",
]
deps = [ ":v8_libbase" ]
}
v8_source_set("fuzzer_support") {
@ -3783,9 +3725,7 @@ v8_source_set("fuzzer_support") {
configs = [ ":internal_config_base" ]
deps = [
":v8",
]
deps = [ ":v8" ]
public_deps = [
":v8_libbase",
@ -3907,9 +3847,7 @@ if (current_toolchain == v8_snapshot_toolchain) {
v8_executable("torque") {
visibility = [ ":*" ] # Only targets in this file can depend on this.
sources = [
"src/torque/torque.cc",
]
sources = [ "src/torque/torque.cc" ]
deps = [
":torque_base",
@ -3939,9 +3877,7 @@ if (current_toolchain == v8_snapshot_toolchain) {
v8_executable("torque-language-server") {
visibility = [ ":*" ] # Only targets in this file can depend on this.
sources = [
"src/torque/ls/torque-language-server.cc",
]
sources = [ "src/torque/ls/torque-language-server.cc" ]
deps = [
":torque_base",
@ -3973,9 +3909,7 @@ if (v8_enable_i18n_support) {
v8_executable("gen-regexp-special-case") {
visibility = [ ":*" ] # Only targets in this file can depend on this.
sources = [
"src/regexp/gen-regexp-special-case.cc",
]
sources = [ "src/regexp/gen-regexp-special-case.cc" ]
deps = [
":v8_libbase",
@ -3992,15 +3926,11 @@ if (v8_enable_i18n_support) {
script = "tools/run.py"
deps = [
":gen-regexp-special-case($v8_generator_toolchain)",
]
deps = [ ":gen-regexp-special-case($v8_generator_toolchain)" ]
output_file = "$target_gen_dir/src/regexp/special-case.cc"
outputs = [
output_file,
]
outputs = [ output_file ]
args = [
"./" + rebase_path(
@ -4046,17 +3976,13 @@ group("gn_all") {
}
group("v8_python_base") {
data = [
".vpython",
]
data = [ ".vpython" ]
}
group("v8_clusterfuzz") {
testonly = true
deps = [
":d8",
]
deps = [ ":d8" ]
if (v8_multi_arch_build) {
deps += [
@ -4072,9 +3998,7 @@ group("v8_clusterfuzz") {
group("v8_archive") {
testonly = true
deps = [
":d8",
]
deps = [ ":d8" ]
if (!is_win) {
# On windows, cctest doesn't link with v8_static_library.
@ -4117,9 +4041,7 @@ group("v8_fuzzers") {
if (is_component_build) {
v8_component("v8") {
sources = [
"src/utils/v8dll-main.cc",
]
sources = [ "src/utils/v8dll-main.cc" ]
public_deps = [
":v8_base",
@ -4134,9 +4056,7 @@ if (is_component_build) {
v8_component("v8_for_testing") {
testonly = true
sources = [
"src/utils/v8dll-main.cc",
]
sources = [ "src/utils/v8dll-main.cc" ]
public_deps = [
":torque_base",
@ -4225,9 +4145,7 @@ v8_executable("d8") {
}
v8_executable("v8_hello_world") {
sources = [
"samples/hello-world.cc",
]
sources = [ "samples/hello-world.cc" ]
configs = [
# Note: don't use :internal_config here because this target will get
@ -4245,9 +4163,7 @@ v8_executable("v8_hello_world") {
}
v8_executable("v8_sample_process") {
sources = [
"samples/process.cc",
]
sources = [ "samples/process.cc" ]
configs = [
# Note: don't use :internal_config here because this target will get
@ -4266,9 +4182,7 @@ v8_executable("v8_sample_process") {
if (want_v8_shell) {
v8_executable("v8_shell") {
sources = [
"samples/shell.cc",
]
sources = [ "samples/shell.cc" ]
configs = [
# Note: don't use :internal_config here because this target will get
@ -4295,22 +4209,16 @@ template("v8_fuzzer") {
"//build/win:default_exe_manifest",
]
sources = [
"test/fuzzer/fuzzer.cc",
]
sources = [ "test/fuzzer/fuzzer.cc" ]
configs = [ ":external_config" ]
}
}
v8_source_set("json_fuzzer") {
sources = [
"test/fuzzer/json.cc",
]
sources = [ "test/fuzzer/json.cc" ]
deps = [
":fuzzer_support",
]
deps = [ ":fuzzer_support" ]
configs = [
":external_config",
@ -4322,13 +4230,9 @@ v8_fuzzer("json_fuzzer") {
}
v8_source_set("multi_return_fuzzer") {
sources = [
"test/fuzzer/multi-return.cc",
]
sources = [ "test/fuzzer/multi-return.cc" ]
deps = [
":fuzzer_support",
]
deps = [ ":fuzzer_support" ]
configs = [
":external_config",
@ -4340,13 +4244,9 @@ v8_fuzzer("multi_return_fuzzer") {
}
v8_source_set("parser_fuzzer") {
sources = [
"test/fuzzer/parser.cc",
]
sources = [ "test/fuzzer/parser.cc" ]
deps = [
":fuzzer_support",
]
deps = [ ":fuzzer_support" ]
configs = [
":external_config",
@ -4363,9 +4263,7 @@ v8_source_set("regexp_builtins_fuzzer") {
"test/fuzzer/regexp_builtins/mjsunit.js.h",
]
deps = [
":fuzzer_support",
]
deps = [ ":fuzzer_support" ]
configs = [
":external_config",
@ -4377,13 +4275,9 @@ v8_fuzzer("regexp_builtins_fuzzer") {
}
v8_source_set("regexp_fuzzer") {
sources = [
"test/fuzzer/regexp.cc",
]
sources = [ "test/fuzzer/regexp.cc" ]
deps = [
":fuzzer_support",
]
deps = [ ":fuzzer_support" ]
configs = [
":external_config",
@ -4405,9 +4299,7 @@ v8_source_set("wasm_module_runner") {
":run_torque",
]
public_deps = [
":v8_maybe_icu",
]
public_deps = [ ":v8_maybe_icu" ]
configs = [
":external_config",
@ -4416,9 +4308,7 @@ v8_source_set("wasm_module_runner") {
}
v8_source_set("wasm_fuzzer") {
sources = [
"test/fuzzer/wasm.cc",
]
sources = [ "test/fuzzer/wasm.cc" ]
deps = [
":fuzzer_support",
@ -4436,9 +4326,7 @@ v8_fuzzer("wasm_fuzzer") {
}
v8_source_set("wasm_async_fuzzer") {
sources = [
"test/fuzzer/wasm-async.cc",
]
sources = [ "test/fuzzer/wasm-async.cc" ]
deps = [
":fuzzer_support",
@ -4487,9 +4375,7 @@ v8_source_set("lib_wasm_fuzzer_common") {
":run_torque",
]
public_deps = [
":v8_maybe_icu",
]
public_deps = [ ":v8_maybe_icu" ]
configs = [
":external_config",
@ -4614,9 +4500,7 @@ if (!build_with_chromium && v8_use_perfetto) {
# This target should be used only by the protoc compiler and by test targets.
source_set("protobuf_full") {
deps = [
":protobuf_lite",
]
deps = [ ":protobuf_lite" ]
sources = [
"third_party/protobuf/src/google/protobuf/any.cc",
"third_party/protobuf/src/google/protobuf/any.pb.cc",
@ -4686,9 +4570,7 @@ if (!build_with_chromium && v8_use_perfetto) {
if (current_toolchain == host_toolchain) {
source_set("protoc_lib") {
deps = [
":protobuf_full",
]
deps = [ ":protobuf_full" ]
sources = [
"third_party/protobuf/src/google/protobuf/compiler/code_generator.cc",
"third_party/protobuf/src/google/protobuf/compiler/command_line_interface.cc",
@ -4727,9 +4609,7 @@ if (!build_with_chromium && v8_use_perfetto) {
":protoc_lib",
"//build/win:default_exe_manifest",
]
sources = [
"src/protobuf/protobuf-compiler-main.cc",
]
sources = [ "src/protobuf/protobuf-compiler-main.cc" ]
configs -= [ "//build/config/compiler:chromium_code" ]
configs += [ "//build/config/compiler:no_chromium_code" ]
}

View File

@ -9717,17 +9717,6 @@ uint32_t debug::WasmScript::GetFunctionHash(int function_index) {
function_bytes.length(), 0);
}
debug::WasmDisassembly debug::WasmScript::DisassembleFunction(
int function_index) const {
i::DisallowHeapAllocation no_gc;
i::Handle<i::Script> script = Utils::OpenHandle(this);
DCHECK_EQ(i::Script::TYPE_WASM, script->type());
i::wasm::NativeModule* native_module = script->wasm_native_module();
const i::wasm::WasmModule* module = native_module->module();
i::wasm::ModuleWireBytes wire_bytes(native_module->wire_bytes());
return DisassembleWasmFunction(module, wire_bytes, function_index);
}
debug::Location::Location(int line_number, int column_number)
: line_number_(line_number),
column_number_(column_number),

View File

@ -55,7 +55,6 @@
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-text.h"
namespace v8 {
namespace internal {

View File

@ -173,7 +173,6 @@ class WasmScript : public Script {
std::pair<int, int> GetFunctionRange(int function_index) const;
int GetContainingFunction(int byte_offset) const;
debug::WasmDisassembly DisassembleFunction(int function_index) const;
uint32_t GetFunctionHash(int function_index);
};

View File

@ -42,33 +42,6 @@ class V8_EXPORT_PRIVATE Location {
bool is_empty_;
};
/**
* The result of disassembling a wasm function.
* Consists of the disassembly string and an offset table mapping wasm byte
* offsets to line and column in the disassembly.
* The offset table entries are ordered by the byte_offset.
* All numbers are 0-based.
*/
struct WasmDisassemblyOffsetTableEntry {
WasmDisassemblyOffsetTableEntry(uint32_t byte_offset, int line, int column)
: byte_offset(byte_offset), line(line), column(column) {}
uint32_t byte_offset;
int line;
int column;
};
struct WasmDisassembly {
using OffsetTable = std::vector<WasmDisassemblyOffsetTableEntry>;
WasmDisassembly() = default;
WasmDisassembly(std::string disassembly, OffsetTable offset_table)
: disassembly(std::move(disassembly)),
offset_table(std::move(offset_table)) {}
std::string disassembly;
OffsetTable offset_table;
};
enum DebugAsyncActionType {
kDebugPromiseThen,
kDebugPromiseCatch,

View File

@ -22,7 +22,6 @@
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-objects-inl.h"
#include "src/wasm/wasm-result.h"
#include "src/wasm/wasm-text.h"
namespace v8 {
namespace internal {
@ -103,23 +102,6 @@ int GetContainingWasmFunction(const WasmModule* module, uint32_t byte_offset) {
return func_index;
}
// static
v8::debug::WasmDisassembly DisassembleWasmFunction(
const WasmModule* module, const ModuleWireBytes& wire_bytes,
int func_index) {
if (func_index < 0 ||
static_cast<uint32_t>(func_index) >= module->functions.size())
return {};
std::ostringstream disassembly_os;
v8::debug::WasmDisassembly::OffsetTable offset_table;
PrintWasmText(module, wire_bytes, static_cast<uint32_t>(func_index),
disassembly_os, &offset_table);
return {disassembly_os.str(), std::move(offset_table)};
}
void DecodedFunctionNames::AddForTesting(int function_index,
WireBytesRef name) {
base::MutexGuard lock(&mutex_);

View File

@ -17,10 +17,6 @@
namespace v8 {
namespace debug {
struct WasmDisassembly;
}
namespace internal {
class WasmModuleObject;
@ -268,15 +264,6 @@ int GetContainingWasmFunction(const WasmModule* module, uint32_t byte_offset);
// contained within a function.
int GetNearestWasmFunction(const WasmModule* module, uint32_t byte_offset);
// Compute the disassembly of a wasm function.
// 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.
V8_EXPORT_PRIVATE debug::WasmDisassembly DisassembleWasmFunction(
const WasmModule* module, const ModuleWireBytes& wire_bytes,
int func_index);
// Interface to the storage (wire bytes) of a wasm module.
// It is illegal for anyone receiving a ModuleWireBytes to store pointers based
// on module_bytes, as this storage is only guaranteed to be alive as long as

View File

@ -1,381 +0,0 @@
// 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.
#include "src/wasm/wasm-text.h"
#include "src/debug/interface-types.h"
#include "src/utils/ostreams.h"
#include "src/utils/vector.h"
#include "src/objects/objects-inl.h"
#include "src/wasm/function-body-decoder-impl.h"
#include "src/wasm/function-body-decoder.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/zone/zone.h"
namespace v8 {
namespace internal {
namespace wasm {
namespace {
bool IsValidFunctionName(const Vector<const char> &name) {
if (name.empty()) return false;
const char *special_chars = "_.+-*/\\^~=<>!?@#$%&|:'`";
for (char c : name) {
bool valid_char = (c >= '0' && c <= '9') || (c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') || strchr(special_chars, c);
if (!valid_char) return false;
}
return true;
}
} // namespace
void PrintWasmText(const WasmModule* module, const ModuleWireBytes& wire_bytes,
uint32_t func_index, std::ostream& os,
debug::WasmDisassembly::OffsetTable* offset_table) {
DCHECK_NOT_NULL(module);
DCHECK_GT(module->functions.size(), func_index);
const WasmFunction *fun = &module->functions[func_index];
AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
int line_nr = 0;
int control_depth = 1;
// Print the function signature.
os << "func";
WasmName fun_name = wire_bytes.GetNameOrNull(fun, module);
if (IsValidFunctionName(fun_name)) {
os << " $";
os.write(fun_name.begin(), fun_name.length());
}
if (fun->sig->parameter_count()) {
os << " (param";
for (auto param : fun->sig->parameters())
os << ' ' << ValueTypes::TypeName(param);
os << ')';
}
if (fun->sig->return_count()) {
os << " (result";
for (auto ret : fun->sig->returns()) os << ' ' << ValueTypes::TypeName(ret);
os << ')';
}
os << "\n";
++line_nr;
// Print the local declarations.
BodyLocalDecls decls(&zone);
Vector<const byte> func_bytes = wire_bytes.GetFunctionBytes(fun);
BytecodeIterator i(func_bytes.begin(), func_bytes.end(), &decls);
DCHECK_LT(func_bytes.begin(), i.pc());
if (!decls.type_list.empty()) {
os << "(local";
for (const ValueType &v : decls.type_list) {
os << ' ' << ValueTypes::TypeName(v);
}
os << ")\n";
++line_nr;
}
for (; i.has_next(); i.next()) {
WasmOpcode opcode = i.current();
if (opcode == kExprElse || opcode == kExprCatch || opcode == kExprEnd) {
--control_depth;
}
DCHECK_LE(0, control_depth);
const int kMaxIndentation = 64;
int indentation = std::min(kMaxIndentation, 2 * control_depth);
if (offset_table) {
offset_table->emplace_back(i.pc_offset(), line_nr, indentation);
}
// 64 whitespaces
const char padding[kMaxIndentation + 1] =
" ";
os.write(padding, indentation);
switch (opcode) {
case kExprLoop:
case kExprIf:
case kExprBlock:
case kExprTry: {
BlockTypeImmediate<Decoder::kNoValidate> imm(WasmFeatures::All(), &i,
i.pc());
os << WasmOpcodes::OpcodeName(opcode);
if (imm.type == kWasmBottom) {
os << " (type " << imm.sig_index << ")";
} else if (imm.out_arity() > 0) {
os << " " << ValueTypes::TypeName(imm.out_type(0));
}
control_depth++;
break;
}
case kExprBr:
case kExprBrIf: {
BranchDepthImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.depth;
break;
}
case kExprBrOnExn: {
BranchOnExceptionImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.depth.depth << ' '
<< imm.index.index;
break;
}
case kExprElse:
case kExprCatch:
os << WasmOpcodes::OpcodeName(opcode);
control_depth++;
break;
case kExprEnd:
os << "end";
break;
case kExprBrTable: {
BranchTableImmediate<Decoder::kNoValidate> imm(&i, i.pc());
BranchTableIterator<Decoder::kNoValidate> iterator(&i, imm);
os << "br_table";
while (iterator.has_next()) os << ' ' << iterator.next();
break;
}
case kExprCallIndirect:
case kExprReturnCallIndirect: {
CallIndirectImmediate<Decoder::kNoValidate> imm(WasmFeatures::All(), &i,
i.pc());
DCHECK_EQ(0, imm.table_index);
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.sig_index;
break;
}
case kExprCallFunction:
case kExprReturnCall: {
CallFunctionImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.index;
break;
}
case kExprLocalGet:
case kExprLocalSet:
case kExprLocalTee: {
LocalIndexImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.index;
break;
}
case kExprThrow: {
ExceptionIndexImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.index;
break;
}
case kExprGlobalGet:
case kExprGlobalSet: {
GlobalIndexImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.index;
break;
}
case kExprTableGet:
case kExprTableSet: {
TableIndexImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.index;
break;
}
case kExprSelectWithType: {
SelectTypeImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' '
<< ValueTypes::TypeName(imm.type);
break;
}
#define CASE_CONST(type, str, cast_type) \
case kExpr##type##Const: { \
Imm##type##Immediate<Decoder::kNoValidate> imm(&i, i.pc()); \
os << #str ".const " << static_cast<cast_type>(imm.value); \
break; \
}
CASE_CONST(I32, i32, int32_t)
CASE_CONST(I64, i64, int64_t)
CASE_CONST(F32, f32, float)
CASE_CONST(F64, f64, double)
#undef CASE_CONST
case kExprRefFunc: {
FunctionIndexImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.index;
break;
}
#define CASE_OPCODE(opcode, _, __) case kExpr##opcode:
FOREACH_LOAD_MEM_OPCODE(CASE_OPCODE)
FOREACH_STORE_MEM_OPCODE(CASE_OPCODE) {
MemoryAccessImmediate<Decoder::kNoValidate> imm(&i, i.pc(),
kMaxUInt32);
os << WasmOpcodes::OpcodeName(opcode) << " offset=" << imm.offset
<< " align=" << (1ULL << imm.alignment);
break;
}
FOREACH_SIMPLE_OPCODE(CASE_OPCODE)
FOREACH_SIMPLE_PROTOTYPE_OPCODE(CASE_OPCODE)
case kExprUnreachable:
case kExprNop:
case kExprReturn:
case kExprMemorySize:
case kExprMemoryGrow:
case kExprDrop:
case kExprSelect:
case kExprRethrow:
case kExprRefNull:
os << WasmOpcodes::OpcodeName(opcode);
break;
case kNumericPrefix: {
WasmOpcode numeric_opcode = i.prefixed_opcode();
switch (numeric_opcode) {
case kExprI32SConvertSatF32:
case kExprI32UConvertSatF32:
case kExprI32SConvertSatF64:
case kExprI32UConvertSatF64:
case kExprI64SConvertSatF32:
case kExprI64UConvertSatF32:
case kExprI64SConvertSatF64:
case kExprI64UConvertSatF64:
case kExprMemoryCopy:
case kExprMemoryFill:
os << WasmOpcodes::OpcodeName(opcode);
break;
case kExprMemoryInit: {
MemoryInitImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' '
<< imm.data_segment_index;
break;
}
case kExprDataDrop: {
DataDropImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.index;
break;
}
case kExprTableInit: {
TableInitImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' '
<< imm.elem_segment_index << ' ' << imm.table.index;
break;
}
case kExprElemDrop: {
ElemDropImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.index;
break;
}
case kExprTableCopy: {
TableCopyImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.table_src.index
<< ' ' << imm.table_dst.index;
break;
}
case kExprTableGrow:
case kExprTableSize:
case kExprTableFill: {
TableIndexImmediate<Decoder::kNoValidate> imm(&i, i.pc() + 1);
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.index;
break;
}
default:
UNREACHABLE();
break;
}
break;
}
case kSimdPrefix: {
WasmOpcode simd_opcode = i.prefixed_opcode();
switch (simd_opcode) {
case kExprS128LoadMem:
case kExprS128StoreMem: {
MemoryAccessImmediate<Decoder::kNoValidate> imm(&i, i.pc(),
kMaxUInt32);
os << WasmOpcodes::OpcodeName(opcode) << " offset=" << imm.offset
<< " align=" << (1ULL << imm.alignment);
break;
}
case kExprS8x16Shuffle: {
Simd8x16ShuffleImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode);
for (uint8_t v : imm.shuffle) {
os << ' ' << v;
}
break;
}
case kExprI8x16ExtractLaneS:
case kExprI8x16ExtractLaneU:
case kExprI16x8ExtractLaneS:
case kExprI16x8ExtractLaneU:
case kExprI32x4ExtractLane:
case kExprI64x2ExtractLane:
case kExprF32x4ExtractLane:
case kExprF64x2ExtractLane:
case kExprI8x16ReplaceLane:
case kExprI16x8ReplaceLane:
case kExprI32x4ReplaceLane:
case kExprI64x2ReplaceLane:
case kExprF32x4ReplaceLane:
case kExprF64x2ReplaceLane: {
SimdLaneImmediate<Decoder::kNoValidate> imm(&i, i.pc());
os << WasmOpcodes::OpcodeName(opcode) << ' ' << imm.lane;
break;
}
FOREACH_SIMD_0_OPERAND_OPCODE(CASE_OPCODE) {
os << WasmOpcodes::OpcodeName(opcode);
break;
}
default:
UNREACHABLE();
break;
}
break;
}
case kAtomicPrefix: {
WasmOpcode atomic_opcode = i.prefixed_opcode();
switch (atomic_opcode) {
FOREACH_ATOMIC_OPCODE(CASE_OPCODE) {
MemoryAccessImmediate<Decoder::kNoValidate> imm(&i, i.pc() + 1,
kMaxUInt32);
os << WasmOpcodes::OpcodeName(atomic_opcode)
<< " offset=" << imm.offset
<< " align=" << (1ULL << imm.alignment);
break;
}
FOREACH_ATOMIC_0_OPERAND_OPCODE(CASE_OPCODE) {
os << WasmOpcodes::OpcodeName(atomic_opcode);
break;
}
default:
UNREACHABLE();
break;
}
break;
}
// This group is just printed by their internal opcode name, as they
// should never be shown to end-users.
FOREACH_ASMJS_COMPAT_OPCODE(CASE_OPCODE) {
os << WasmOpcodes::OpcodeName(opcode);
}
break;
#undef CASE_OPCODE
default:
UNREACHABLE();
break;
}
os << '\n';
++line_nr;
}
DCHECK_EQ(0, control_depth);
DCHECK(i.ok());
}
} // namespace wasm
} // namespace internal
} // namespace v8

View File

@ -1,39 +0,0 @@
// 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_WASM_TEXT_H_
#define V8_WASM_WASM_TEXT_H_
#include <cstdint>
#include <ostream>
#include <vector>
#include "src/common/globals.h"
namespace v8 {
namespace debug {
struct WasmDisassemblyOffsetTableEntry;
} // namespace debug
namespace internal {
namespace wasm {
// Forward declaration.
struct WasmModule;
struct ModuleWireBytes;
// 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.
V8_EXPORT_PRIVATE void PrintWasmText(
const WasmModule* module, const ModuleWireBytes& wire_bytes,
uint32_t func_index, std::ostream& os,
std::vector<debug::WasmDisassemblyOffsetTableEntry>* offset_table);
} // namespace wasm
} // namespace internal
} // namespace v8
#endif // V8_WASM_WASM_TEXT_H_

View File

@ -942,46 +942,6 @@ TEST(MemoryWithOOBEmptyDataSegment) {
Cleanup();
}
TEST(AtomicOpDisassembly) {
{
EXPERIMENTAL_FLAG_SCOPE(threads);
TestSignatures sigs;
Isolate* isolate = CcTest::InitIsolateOnce();
v8::internal::AccountingAllocator allocator;
Zone zone(&allocator, ZONE_NAME);
WasmModuleBuilder* builder = new (&zone) WasmModuleBuilder(&zone);
builder->SetHasSharedMemory();
builder->SetMaxMemorySize(16);
WasmFunctionBuilder* f = builder->AddFunction(sigs.i_i());
ExportAsMain(f);
byte code[] = {
WASM_ATOMICS_STORE_OP(kExprI32AtomicStore, WASM_ZERO, WASM_GET_LOCAL(0),
MachineRepresentation::kWord32),
WASM_ATOMICS_LOAD_OP(kExprI32AtomicLoad, WASM_ZERO,
MachineRepresentation::kWord32)};
EMIT_CODE_WITH_END(f, code);
HandleScope scope(isolate);
ZoneBuffer buffer(&zone);
builder->WriteTo(&buffer);
testing::SetupIsolateForWasmModule(isolate);
ErrorThrower thrower(isolate, "Test");
auto enabled_features = WasmFeatures::FromIsolate(isolate);
Handle<WasmModuleObject> module_object =
isolate->wasm_engine()
->SyncCompile(isolate, enabled_features, &thrower,
ModuleWireBytes(buffer.begin(), buffer.end()))
.ToHandleChecked();
NativeModule* native_module = module_object->native_module();
ModuleWireBytes wire_bytes(native_module->wire_bytes());
DisassembleWasmFunction(native_module->module(), wire_bytes, 0);
}
Cleanup();
}
#undef EMIT_CODE_WITH_END
} // namespace test_run_wasm_module

View File

@ -245,7 +245,6 @@ v8_source_set("unittests_sources") {
"wasm/wasm-module-builder-unittest.cc",
"wasm/wasm-module-sourcemap-unittest.cc",
"wasm/wasm-opcodes-unittest.cc",
"wasm/wasm-text-unittest.cc",
"zone/zone-allocator-unittest.cc",
"zone/zone-chunk-list-unittest.cc",
"zone/zone-unittest.cc",

View File

@ -1,121 +0,0 @@
// Copyright 2019 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.
#include <sstream>
#include "test/unittests/test-utils.h"
#include "src/wasm/module-decoder.h"
#include "src/wasm/wasm-module-builder.h"
#include "src/wasm/wasm-module.h"
#include "src/wasm/wasm-opcodes.h"
#include "src/wasm/wasm-text.h"
#include "test/common/wasm/test-signatures.h"
namespace v8 {
namespace internal {
namespace wasm {
class WasmTextTest : public TestWithIsolateAndZone {
public:
TestSignatures sigs;
WasmFeatures enabled_features_;
void TestInstruction(const byte* func_start, size_t func_size) {
WasmModuleBuilder mb(zone());
auto* fb = mb.AddFunction(sigs.v_v());
fb->EmitCode(func_start, static_cast<uint32_t>(func_size));
fb->Emit(kExprEnd);
ZoneBuffer buffer(zone());
mb.WriteTo(&buffer);
ModuleWireBytes wire_bytes(
Vector<const byte>(buffer.begin(), buffer.size()));
ModuleResult result = DecodeWasmModule(
enabled_features_, buffer.begin(), buffer.end(), false, kWasmOrigin,
isolate()->counters(), isolate()->wasm_engine()->allocator());
EXPECT_TRUE(result.ok());
std::stringstream ss;
PrintWasmText(result.value().get(), wire_bytes, 0, ss, nullptr);
}
};
TEST_F(WasmTextTest, EveryOpcodeCanBeDecoded) {
static const struct {
WasmOpcode opcode;
const char* debug_name;
} kValues[] = {
#define DECLARE_ELEMENT(name, opcode, sig) {kExpr##name, "kExpr" #name},
FOREACH_OPCODE(DECLARE_ELEMENT)};
#undef DECLARE_ELEMENT
for (const auto& value : kValues) {
// Pad with 0 for any immediate values. If they're not needed, they'll be
// interpreted as unreachable.
byte data[20] = {0};
printf("%s\n", value.debug_name);
switch (value.opcode) {
// Instructions that have a special case because they affect the control
// depth.
case kExprBlock:
case kExprLoop:
case kExprIf:
case kExprTry:
data[0] = value.opcode;
data[1] = kLocalVoid;
data[2] = kExprEnd;
break;
case kExprElse:
data[0] = kExprIf;
data[1] = value.opcode;
data[2] = kExprEnd;
break;
case kExprCatch:
data[0] = kExprTry;
data[1] = value.opcode;
data[2] = kExprEnd;
break;
case kExprEnd:
break;
// Instructions with special requirements for immediates.
case kExprSelectWithType:
data[0] = kExprSelectWithType;
data[1] = 1;
data[2] = kLocalI32;
break;
default: {
if (value.opcode >= 0x100) {
data[0] = value.opcode >> 8; // Prefix byte.
byte opcode = value.opcode & 0xff; // Actual opcode.
if (opcode >= 0x80) {
// Opcode with prefix, and needs to be LEB encoded (3 bytes).
// For now, this can only be in the range [0x80, 0xff], which means
// that the third byte is always 1.
data[1] = (opcode & 0x7f) | 0x80;
data[2] = 1;
} else {
// Opcode with prefix (2 bytes).
data[1] = opcode;
}
} else {
// Single-byte opcode.
data[0] = value.opcode;
}
break;
}
}
TestInstruction(data, arraysize(data));
}
}
} // namespace wasm
} // namespace internal
} // namespace v8