[wasm] Implement extensible name section
The format of the name section changed recently. It now contains subsections of different type (currently for function names or local variable names). This CL changes our internal wasm module builders (in JS and C++) to emit this new format, and changes the decoder to understand it. We currently only parse the function name section, and ignore names of local variables. I will later extend this to parse local variable names when needed for debugging. R=ahaas@chromium.org, rossberg@chromium.org BUG=v8:6222 Change-Id: I2627160c25c9209a3f09abe0b88941ec48b24434 Reviewed-on: https://chromium-review.googlesource.com/470247 Commit-Queue: Clemens Hammacher <clemensh@chromium.org> Reviewed-by: Andreas Rossberg <rossberg@chromium.org> Cr-Commit-Position: refs/heads/master@{#44492}
This commit is contained in:
parent
ceb3f4b1a7
commit
1a73f73b3b
@ -30,7 +30,7 @@ namespace wasm {
|
||||
#define TRACE(...)
|
||||
#endif
|
||||
|
||||
const char* SectionName(WasmSectionCode code) {
|
||||
const char* SectionName(SectionCode code) {
|
||||
switch (code) {
|
||||
case kUnknownSectionCode:
|
||||
return "Unknown";
|
||||
@ -106,7 +106,7 @@ class WasmSectionIterator {
|
||||
return section_code_ != kUnknownSectionCode && decoder_.more();
|
||||
}
|
||||
|
||||
inline WasmSectionCode section_code() const { return section_code_; }
|
||||
inline SectionCode section_code() const { return section_code_; }
|
||||
|
||||
inline const byte* section_start() const { return section_start_; }
|
||||
|
||||
@ -138,7 +138,7 @@ class WasmSectionIterator {
|
||||
|
||||
private:
|
||||
Decoder& decoder_;
|
||||
WasmSectionCode section_code_;
|
||||
SectionCode section_code_;
|
||||
const byte* section_start_;
|
||||
const byte* payload_start_;
|
||||
const byte* section_end_;
|
||||
@ -184,15 +184,13 @@ class WasmSectionIterator {
|
||||
strncmp(reinterpret_cast<const char*>(section_name_start),
|
||||
kNameString, kNameStringLength) == 0) {
|
||||
section_code = kNameSectionCode;
|
||||
} else {
|
||||
section_code = kUnknownSectionCode;
|
||||
}
|
||||
} else if (!IsValidSectionCode(section_code)) {
|
||||
decoder_.errorf(decoder_.pc(), "unknown section code #0x%02x",
|
||||
section_code);
|
||||
section_code = kUnknownSectionCode;
|
||||
}
|
||||
section_code_ = static_cast<WasmSectionCode>(section_code);
|
||||
section_code_ = static_cast<SectionCode>(section_code);
|
||||
|
||||
TRACE("Section: %s\n", SectionName(section_code_));
|
||||
if (section_code_ == kUnknownSectionCode &&
|
||||
@ -651,22 +649,36 @@ class ModuleDecoder : public Decoder {
|
||||
// TODO(titzer): find a way to report name errors as warnings.
|
||||
// Use an inner decoder so that errors don't fail the outer decoder.
|
||||
Decoder inner(start_, pc_, end_);
|
||||
uint32_t functions_count = inner.consume_u32v("functions count");
|
||||
// Decode all name subsections.
|
||||
// Be lenient with their order.
|
||||
while (inner.ok() && inner.more()) {
|
||||
uint8_t name_type = inner.consume_u8("name type");
|
||||
if (name_type & 0x80) inner.error("name type if not varuint7");
|
||||
|
||||
for (uint32_t i = 0; inner.ok() && i < functions_count; ++i) {
|
||||
uint32_t function_name_length = 0;
|
||||
uint32_t name_offset =
|
||||
consume_string(inner, &function_name_length, false);
|
||||
uint32_t func_index = i;
|
||||
if (inner.ok() && func_index < module->functions.size()) {
|
||||
module->functions[func_index].name_offset = name_offset;
|
||||
module->functions[func_index].name_length = function_name_length;
|
||||
}
|
||||
uint32_t name_payload_len = inner.consume_u32v("name payload length");
|
||||
if (!inner.checkAvailable(name_payload_len)) break;
|
||||
|
||||
uint32_t local_names_count = inner.consume_u32v("local names count");
|
||||
for (uint32_t j = 0; inner.ok() && j < local_names_count; j++) {
|
||||
uint32_t length = inner.consume_u32v("string length");
|
||||
inner.consume_bytes(length, "string");
|
||||
// Decode function names, ignore the rest.
|
||||
// Local names will be decoded when needed.
|
||||
if (name_type == NameSectionType::kFunction) {
|
||||
uint32_t functions_count = inner.consume_u32v("functions count");
|
||||
|
||||
for (; inner.ok() && functions_count > 0; --functions_count) {
|
||||
uint32_t function_index = inner.consume_u32v("function index");
|
||||
uint32_t name_length = 0;
|
||||
uint32_t name_offset = consume_string(inner, &name_length, false);
|
||||
// Be lenient with errors in the name section: Ignore illegal
|
||||
// or out-of-order indexes and non-UTF8 names. You can even assign
|
||||
// to the same function multiple times (last valid one wins).
|
||||
if (inner.ok() && function_index < module->functions.size() &&
|
||||
unibrow::Utf8::Validate(inner.start() + name_offset,
|
||||
name_length)) {
|
||||
module->functions[function_index].name_offset = name_offset;
|
||||
module->functions[function_index].name_length = name_length;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
inner.consume_bytes(name_payload_len, "name subsection payload");
|
||||
}
|
||||
}
|
||||
// Skip the whole names section in the outer decoder.
|
||||
|
@ -20,7 +20,7 @@ const uint8_t kWasmFunctionTypeForm = 0x60;
|
||||
const uint8_t kWasmAnyFunctionTypeForm = 0x70;
|
||||
const uint8_t kResizableMaximumFlag = 1;
|
||||
|
||||
enum WasmSectionCode {
|
||||
enum SectionCode {
|
||||
kUnknownSectionCode = 0, // code for unknown sections
|
||||
kTypeSectionCode = 1, // Function signature declarations
|
||||
kImportSectionCode = 2, // Import declarations
|
||||
@ -36,11 +36,13 @@ enum WasmSectionCode {
|
||||
kNameSectionCode = 12, // Name section (encoded as a string)
|
||||
};
|
||||
|
||||
enum NameSectionType : uint8_t { kFunction = 1, kLocal = 2 };
|
||||
|
||||
inline bool IsValidSectionCode(uint8_t byte) {
|
||||
return kTypeSectionCode <= byte && byte <= kDataSectionCode;
|
||||
}
|
||||
|
||||
const char* SectionName(WasmSectionCode code);
|
||||
const char* SectionName(SectionCode code);
|
||||
|
||||
typedef Result<const WasmModule*> ModuleResult;
|
||||
typedef Result<WasmFunction*> FunctionResult;
|
||||
|
@ -34,7 +34,7 @@ namespace wasm {
|
||||
|
||||
// Emit a section code and the size as a padded varint that can be patched
|
||||
// later.
|
||||
size_t EmitSection(WasmSectionCode code, ZoneBuffer& buffer) {
|
||||
size_t EmitSection(SectionCode code, ZoneBuffer& buffer) {
|
||||
// Emit the section code.
|
||||
buffer.write_u8(code);
|
||||
|
||||
@ -206,8 +206,7 @@ void WasmFunctionBuilder::WriteExports(ZoneBuffer& buffer) const {
|
||||
buffer.write_size(name.size());
|
||||
buffer.write(reinterpret_cast<const byte*>(name.data()), name.size());
|
||||
buffer.write_u8(kExternalFunction);
|
||||
buffer.write_u32v(func_index_ + static_cast<uint32_t>(
|
||||
builder_->function_imports_.size()));
|
||||
buffer.write_size(func_index_ + builder_->function_imports_.size());
|
||||
}
|
||||
}
|
||||
|
||||
@ -391,14 +390,14 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
|
||||
}
|
||||
|
||||
// == Emit function signatures ===============================================
|
||||
bool has_names = false;
|
||||
uint32_t num_function_names = 0;
|
||||
if (functions_.size() > 0) {
|
||||
size_t start = EmitSection(kFunctionSectionCode, buffer);
|
||||
buffer.write_size(functions_.size());
|
||||
for (auto function : functions_) {
|
||||
function->WriteSignature(buffer);
|
||||
exports += static_cast<uint32_t>(function->exported_names_.size());
|
||||
if (function->name_.size() > 0) has_names = true;
|
||||
if (!function->name_.empty()) ++num_function_names;
|
||||
}
|
||||
FixupSection(buffer, start);
|
||||
}
|
||||
@ -507,8 +506,7 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
|
||||
// == emit start function index ==============================================
|
||||
if (start_function_index_ >= 0) {
|
||||
size_t start = EmitSection(kStartSectionCode, buffer);
|
||||
buffer.write_u32v(start_function_index_ +
|
||||
static_cast<uint32_t>(function_imports_.size()));
|
||||
buffer.write_size(start_function_index_ + function_imports_.size());
|
||||
FixupSection(buffer, start);
|
||||
}
|
||||
|
||||
@ -523,8 +521,7 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
|
||||
buffer.write_size(indirect_functions_.size()); // element count
|
||||
|
||||
for (auto index : indirect_functions_) {
|
||||
buffer.write_u32v(index +
|
||||
static_cast<uint32_t>(function_imports_.size()));
|
||||
buffer.write_size(index + function_imports_.size());
|
||||
}
|
||||
|
||||
FixupSection(buffer, start);
|
||||
@ -557,7 +554,7 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
|
||||
}
|
||||
|
||||
// == Emit names =============================================================
|
||||
if (has_names) {
|
||||
if (num_function_names > 0 || !function_imports_.empty()) {
|
||||
// Emit the section code.
|
||||
buffer.write_u8(kUnknownSectionCode);
|
||||
// Emit a placeholder for the length.
|
||||
@ -565,19 +562,37 @@ void WasmModuleBuilder::WriteTo(ZoneBuffer& buffer) const {
|
||||
// Emit the section string.
|
||||
buffer.write_size(4);
|
||||
buffer.write(reinterpret_cast<const byte*>("name"), 4);
|
||||
// Emit the names.
|
||||
size_t count = functions_.size() + function_imports_.size();
|
||||
buffer.write_size(count);
|
||||
for (size_t i = 0; i < function_imports_.size(); i++) {
|
||||
buffer.write_u8(0); // empty name for import
|
||||
buffer.write_u8(0); // no local variables
|
||||
// Emit a subsection for the function names.
|
||||
buffer.write_u8(NameSectionType::kFunction);
|
||||
// Emit a placeholder for the subsection length.
|
||||
size_t functions_start = buffer.reserve_u32v();
|
||||
// Emit the function names.
|
||||
// Imports are always named.
|
||||
uint32_t num_imports = static_cast<uint32_t>(function_imports_.size());
|
||||
buffer.write_size(num_imports + num_function_names);
|
||||
uint32_t function_index = 0;
|
||||
for (; function_index < num_imports; ++function_index) {
|
||||
const WasmFunctionImport* import = &function_imports_[function_index];
|
||||
DCHECK_NOT_NULL(import->name);
|
||||
buffer.write_u32v(function_index);
|
||||
uint32_t name_len = static_cast<uint32_t>(import->name_length);
|
||||
buffer.write_u32v(name_len);
|
||||
buffer.write(reinterpret_cast<const byte*>(import->name), name_len);
|
||||
}
|
||||
for (auto function : functions_) {
|
||||
buffer.write_size(function->name_.size());
|
||||
buffer.write(reinterpret_cast<const byte*>(function->name_.data()),
|
||||
function->name_.size());
|
||||
buffer.write_u8(0);
|
||||
if (num_function_names > 0) {
|
||||
for (auto function : functions_) {
|
||||
DCHECK_EQ(function_index,
|
||||
function->func_index() + function_imports_.size());
|
||||
if (!function->name_.empty()) {
|
||||
buffer.write_u32v(function_index);
|
||||
buffer.write_size(function->name_.size());
|
||||
buffer.write(reinterpret_cast<const byte*>(function->name_.data()),
|
||||
function->name_.size());
|
||||
}
|
||||
++function_index;
|
||||
}
|
||||
}
|
||||
FixupSection(buffer, functions_start);
|
||||
FixupSection(buffer, start);
|
||||
}
|
||||
}
|
||||
|
@ -1132,9 +1132,10 @@ MaybeHandle<String> WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
|
||||
isolate);
|
||||
DCHECK_GE(module_bytes->length(), offset);
|
||||
DCHECK_GE(module_bytes->length() - offset, size);
|
||||
Address raw = module_bytes->GetCharsAddress() + offset;
|
||||
if (!unibrow::Utf8::Validate(reinterpret_cast<const byte*>(raw), size))
|
||||
return {}; // UTF8 decoding error for name.
|
||||
// UTF8 validation happens at decode time.
|
||||
DCHECK(unibrow::Utf8::Validate(
|
||||
reinterpret_cast<const byte*>(module_bytes->GetCharsAddress() + offset),
|
||||
size));
|
||||
DCHECK_GE(kMaxInt, offset);
|
||||
DCHECK_GE(kMaxInt, size);
|
||||
return isolate->factory()->NewStringFromUtf8SubString(
|
||||
@ -1219,6 +1220,8 @@ MaybeHandle<String> WasmCompiledModule::GetFunctionNameOrNull(
|
||||
uint32_t func_index) {
|
||||
DCHECK_LT(func_index, compiled_module->module()->functions.size());
|
||||
WasmFunction& function = compiled_module->module()->functions[func_index];
|
||||
DCHECK_IMPLIES(function.name_offset == 0, function.name_length == 0);
|
||||
if (!function.name_offset) return {};
|
||||
return WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
|
||||
isolate, compiled_module, function.name_offset, function.name_length);
|
||||
}
|
||||
|
@ -308,14 +308,17 @@ class TestingModule : public ModuleEnv {
|
||||
Handle<SeqOneByteString> old_bytes(
|
||||
instance_object_->compiled_module()->module_bytes(), isolate_);
|
||||
uint32_t old_size = static_cast<uint32_t>(old_bytes->length());
|
||||
ScopedVector<byte> new_bytes(old_size + bytes.length());
|
||||
// Avoid placing strings at offset 0, this might be interpreted as "not
|
||||
// set", e.g. for function names.
|
||||
uint32_t bytes_offset = old_size ? old_size : 1;
|
||||
ScopedVector<byte> new_bytes(bytes_offset + bytes.length());
|
||||
memcpy(new_bytes.start(), old_bytes->GetChars(), old_size);
|
||||
memcpy(new_bytes.start() + old_size, bytes.start(), bytes.length());
|
||||
memcpy(new_bytes.start() + bytes_offset, bytes.start(), bytes.length());
|
||||
Handle<SeqOneByteString> new_bytes_str = Handle<SeqOneByteString>::cast(
|
||||
isolate_->factory()->NewStringFromOneByte(new_bytes).ToHandleChecked());
|
||||
instance_object_->compiled_module()->shared()->set_module_bytes(
|
||||
*new_bytes_str);
|
||||
return old_size;
|
||||
return bytes_offset;
|
||||
}
|
||||
|
||||
WasmFunction* GetFunctionAt(int index) { return &module_.functions[index]; }
|
||||
|
@ -19,8 +19,7 @@ using namespace v8::internal::wasm;
|
||||
static const char* kNameString = "name";
|
||||
static const size_t kNameStringLength = 4;
|
||||
|
||||
int fuzz_wasm_section(WasmSectionCode section, const uint8_t* data,
|
||||
size_t size) {
|
||||
int fuzz_wasm_section(SectionCode section, const uint8_t* data, size_t size) {
|
||||
v8_fuzzer::FuzzerSupport* support = v8_fuzzer::FuzzerSupport::Get();
|
||||
v8::Isolate* isolate = support->GetIsolate();
|
||||
v8::internal::Isolate* i_isolate =
|
||||
|
@ -10,7 +10,7 @@
|
||||
|
||||
#include "src/wasm/module-decoder.h"
|
||||
|
||||
int fuzz_wasm_section(v8::internal::wasm::WasmSectionCode section,
|
||||
int fuzz_wasm_section(v8::internal::wasm::SectionCode section,
|
||||
const uint8_t* data, size_t size);
|
||||
|
||||
#endif // WASM_SECTION_FUZZERS_H_
|
||||
|
@ -1,9 +1,9 @@
|
||||
Running testFunction...
|
||||
Script nr 0 parsed. URL: v8://test/setup
|
||||
Script nr 1 parsed. URL: v8://test/runTestFunction
|
||||
Script nr 2 parsed. URL: wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-0
|
||||
Script nr 2 parsed. URL: wasm://wasm/wasm-354ada0e/wasm-354ada0e-0
|
||||
This is a wasm script (nr 0).
|
||||
Script nr 3 parsed. URL: wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-1
|
||||
Script nr 3 parsed. URL: wasm://wasm/wasm-354ada0e/wasm-354ada0e-1
|
||||
This is a wasm script (nr 1).
|
||||
Querying breakable locations for all wasm scripts now...
|
||||
Requesting all breakable locations in wasm script 0
|
||||
@ -37,51 +37,51 @@ Requesting breakable locations in lines [4,6)
|
||||
[0] 4:6 || >call 0
|
||||
[1] 5:4 || >end
|
||||
Setting a breakpoint on each breakable location...
|
||||
Setting at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-0:2:2
|
||||
Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:2:2
|
||||
Success!
|
||||
Setting at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-0:3:2
|
||||
Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:3:2
|
||||
Success!
|
||||
Setting at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-0:4:2
|
||||
Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:4:2
|
||||
Success!
|
||||
Setting at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-0:5:0
|
||||
Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:5:0
|
||||
Success!
|
||||
Setting at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-1:1:2
|
||||
Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:1:2
|
||||
Success!
|
||||
Setting at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-1:2:2
|
||||
Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:2:2
|
||||
Success!
|
||||
Setting at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-1:3:4
|
||||
Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:3:4
|
||||
Success!
|
||||
Setting at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-1:4:6
|
||||
Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:4:6
|
||||
Success!
|
||||
Setting at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-1:5:4
|
||||
Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:5:4
|
||||
Success!
|
||||
Setting at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-1:6:2
|
||||
Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:6:2
|
||||
Success!
|
||||
Setting at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-1:7:0
|
||||
Setting at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:7:0
|
||||
Success!
|
||||
Running wasm code...
|
||||
Missing breakpoints: 11
|
||||
Script nr 4 parsed. URL: v8://test/runWasm
|
||||
Stopped at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-1:1:2
|
||||
Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:1:2
|
||||
Missing breakpoints: 10
|
||||
Stopped at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-1:2:2
|
||||
Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:2:2
|
||||
Missing breakpoints: 9
|
||||
Stopped at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-1:3:4
|
||||
Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:3:4
|
||||
Missing breakpoints: 8
|
||||
Stopped at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-1:4:6
|
||||
Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:4:6
|
||||
Missing breakpoints: 7
|
||||
Stopped at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-0:2:2
|
||||
Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:2:2
|
||||
Missing breakpoints: 6
|
||||
Stopped at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-0:3:2
|
||||
Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:3:2
|
||||
Missing breakpoints: 5
|
||||
Stopped at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-0:4:2
|
||||
Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:4:2
|
||||
Missing breakpoints: 4
|
||||
Stopped at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-0:5:0
|
||||
Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-0:5:0
|
||||
Missing breakpoints: 3
|
||||
Stopped at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-1:5:4
|
||||
Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:5:4
|
||||
Missing breakpoints: 2
|
||||
Stopped at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-1:6:2
|
||||
Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:6:2
|
||||
Missing breakpoints: 1
|
||||
Stopped at wasm://wasm/wasm-eb3c2032/wasm-eb3c2032-1:7:0
|
||||
Stopped at wasm://wasm/wasm-354ada0e/wasm-354ada0e-1:7:0
|
||||
Missing breakpoints: 0
|
||||
Finished!
|
||||
|
@ -1,14 +1,14 @@
|
||||
Check that inspector gets two wasm scripts at module creation time.
|
||||
Script #0 parsed. URL: v8://test/testFunction
|
||||
Script #1 parsed. URL: v8://test/runTestRunction
|
||||
Script #2 parsed. URL: wasm://wasm/wasm-4205e2ce/wasm-4205e2ce-0
|
||||
Script #3 parsed. URL: wasm://wasm/wasm-4205e2ce/wasm-4205e2ce-1
|
||||
Source for wasm://wasm/wasm-4205e2ce/wasm-4205e2ce-0:
|
||||
Script #2 parsed. URL: wasm://wasm/wasm-7b04570e/wasm-7b04570e-0
|
||||
Script #3 parsed. URL: wasm://wasm/wasm-7b04570e/wasm-7b04570e-1
|
||||
Source for wasm://wasm/wasm-7b04570e/wasm-7b04570e-0:
|
||||
func $nopFunction
|
||||
nop
|
||||
end
|
||||
|
||||
Source for wasm://wasm/wasm-4205e2ce/wasm-4205e2ce-1:
|
||||
Source for wasm://wasm/wasm-7b04570e/wasm-7b04570e-1:
|
||||
func $main
|
||||
block
|
||||
i32.const 2
|
||||
|
@ -2,10 +2,10 @@ Installing code an global variable.
|
||||
Calling instantiate function.
|
||||
Waiting for two wasm scripts to be parsed.
|
||||
Ignoring script with url v8://test/callInstantiate
|
||||
Got wasm script: wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-0
|
||||
Requesting source for wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-0...
|
||||
Got wasm script: wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1
|
||||
Requesting source for wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1...
|
||||
Got wasm script: wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0
|
||||
Requesting source for wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0...
|
||||
Got wasm script: wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1
|
||||
Requesting source for wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1...
|
||||
func $wasm_A
|
||||
nop
|
||||
nop
|
||||
@ -25,59 +25,59 @@ func $wasm_B (param i32)
|
||||
end
|
||||
end
|
||||
|
||||
Setting breakpoint on line 7 (on the setlocal before the call), url wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1
|
||||
Setting breakpoint on line 7 (on the setlocal before the call), url wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1
|
||||
{
|
||||
columnNumber : 6
|
||||
lineNumber : 7
|
||||
scriptId : <scriptId>
|
||||
}
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:7:6: >set_local 0
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:8:6: >call 0
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-0:1:2: >nop
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:1:2: >nop
|
||||
Step action: stepOver
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-0:2:2: >nop
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:2:2: >nop
|
||||
Step action: stepOut
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:9:6: >br 1
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1
|
||||
Step action: stepOut
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:7:6: >set_local 0
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0
|
||||
Step action: stepOver
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:8:6: >call 0
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0
|
||||
Step action: stepOver
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:9:6: >br 1
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1
|
||||
Step action: resume
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:7:6: >set_local 0
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:8:6: >call 0
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-0:1:2: >nop
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:1:2: >nop
|
||||
Step action: stepOut
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:9:6: >br 1
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:1:2: >loop
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:1:2: >loop
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:2:4: >get_local 0
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:2:4: >get_local 0
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:3:4: >if
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:3:4: >if
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:4:6: >get_local 0
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:4:6: >get_local 0
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:5:6: >i32.const 1
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:5:6: >i32.const 1
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:6:6: >i32.sub
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:6:6: >i32.sub
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:7:6: >set_local 0
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:7:6: >set_local 0
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:8:6: >call 0
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:8:6: >call 0
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-0:1:2: >nop
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:1:2: >nop
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-0:2:2: >nop
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:2:2: >nop
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-0:3:0: >end
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-0:3:0: >end
|
||||
Step action: stepInto
|
||||
Paused at wasm://wasm/wasm-0e9ccf72/wasm-0e9ccf72-1:9:6: >br 1
|
||||
Paused at wasm://wasm/wasm-0c10a5fe/wasm-0c10a5fe-1:9:6: >br 1
|
||||
Step action: resume
|
||||
exports.main returned!
|
||||
Finished!
|
||||
|
@ -10,7 +10,7 @@ var name = 'regression_684858';
|
||||
function patchNameLength(buffer) {
|
||||
var count = 0;
|
||||
var view = new Uint8Array(buffer);
|
||||
for (var i = 0, e = view.length - name.length; i < e; ++i) {
|
||||
for (var i = 0, e = view.length - name.length; i <= e; ++i) {
|
||||
var subs = String.fromCharCode.apply(null, view.slice(i, i + name.length));
|
||||
if (subs != name) continue;
|
||||
++count;
|
||||
|
@ -54,16 +54,16 @@ Error.prepareStackTrace = function(error, frames) {
|
||||
return frames;
|
||||
};
|
||||
|
||||
|
||||
(function testFunctionNamesAsCallSites() {
|
||||
var names = expected_names.concat(["testFunctionNamesAsCallSites", null]);
|
||||
var names = expected_names.concat(['testFunctionNamesAsCallSites', null]);
|
||||
try {
|
||||
module.exports.main();
|
||||
assertFalse("should throw");
|
||||
assertFalse('should throw');
|
||||
} catch (e) {
|
||||
assertEquals(names.length, e.stack.length);
|
||||
assertEquals(names.length, e.stack.length, 'stack length');
|
||||
for (var i = 0; i < names.length; ++i) {
|
||||
assertEquals(names[i], e.stack[i].getFunctionName());
|
||||
assertEquals(
|
||||
names[i], e.stack[i].getFunctionName(), 'function name at ' + i);
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
@ -25,7 +25,8 @@ function verifyStack(frames, expected) {
|
||||
assertContains(exp[4], frames[i].getFileName(), "["+i+"].getFileName()");
|
||||
var toString;
|
||||
if (exp[0]) {
|
||||
toString = exp[1] + " (<WASM>[" + exp[2] + "]+" + exp[3] + ")";
|
||||
var fun_str = exp[1] !== null ? exp[1] : "<WASM UNNAMED>";
|
||||
toString = fun_str + " (<WASM>[" + exp[2] + "]+" + exp[3] + ")";
|
||||
} else {
|
||||
toString = exp[4] + ":" + exp[2] + ":";
|
||||
}
|
||||
@ -70,10 +71,10 @@ var module = builder.instantiate({mod: {func: STACK}});
|
||||
(function testSimpleStack() {
|
||||
var expected_string = "Error\n" +
|
||||
// The line numbers below will change as this test gains / loses lines..
|
||||
" at STACK (stack.js:39:11)\n" + // --
|
||||
" at STACK (stack.js:40:11)\n" + // --
|
||||
" at main (<WASM>[1]+1)\n" + // --
|
||||
" at testSimpleStack (stack.js:78:18)\n" + // --
|
||||
" at stack.js:80:3"; // --
|
||||
" at testSimpleStack (stack.js:79:18)\n" + // --
|
||||
" at stack.js:81:3"; // --
|
||||
|
||||
module.exports.main();
|
||||
assertEquals(expected_string, stripPath(stack));
|
||||
@ -90,10 +91,10 @@ Error.prepareStackTrace = function(error, frames) {
|
||||
|
||||
verifyStack(stack, [
|
||||
// isWasm function line pos file
|
||||
[ false, "STACK", 39, 0, "stack.js"],
|
||||
[ false, "STACK", 40, 0, "stack.js"],
|
||||
[ true, "main", 1, 1, null],
|
||||
[ false, "testStackFrames", 89, 0, "stack.js"],
|
||||
[ false, null, 98, 0, "stack.js"]
|
||||
[ false, "testStackFrames", 90, 0, "stack.js"],
|
||||
[ false, null, 99, 0, "stack.js"]
|
||||
]);
|
||||
})();
|
||||
|
||||
@ -106,8 +107,8 @@ Error.prepareStackTrace = function(error, frames) {
|
||||
verifyStack(e.stack, [
|
||||
// isWasm function line pos file
|
||||
[ true, "exec_unreachable", 2, 1, null],
|
||||
[ false, "testWasmUnreachable", 102, 0, "stack.js"],
|
||||
[ false, null, 113, 0, "stack.js"]
|
||||
[ false, "testWasmUnreachable", 103, 0, "stack.js"],
|
||||
[ false, null, 114, 0, "stack.js"]
|
||||
]);
|
||||
}
|
||||
})();
|
||||
@ -120,10 +121,10 @@ Error.prepareStackTrace = function(error, frames) {
|
||||
assertContains("out of bounds", e.message);
|
||||
verifyStack(e.stack, [
|
||||
// isWasm function line pos file
|
||||
[ true, "", 3, 3, null],
|
||||
[ true, null, 3, 3, null],
|
||||
[ true, "call_mem_out_of_bounds", 4, 1, null],
|
||||
[ false, "testWasmMemOutOfBounds", 117, 0, "stack.js"],
|
||||
[ false, null, 129, 0, "stack.js"]
|
||||
[ false, "testWasmMemOutOfBounds", 118, 0, "stack.js"],
|
||||
[ false, null, 130, 0, "stack.js"]
|
||||
]);
|
||||
}
|
||||
})();
|
||||
|
@ -65,6 +65,10 @@ let kCodeSectionCode = 10; // Function code
|
||||
let kDataSectionCode = 11; // Data segments
|
||||
let kNameSectionCode = 12; // Name section (encoded as string)
|
||||
|
||||
// Name section types
|
||||
let kFunctionNamesCode = 1;
|
||||
let kLocalNamesCode = 2;
|
||||
|
||||
let kWasmFunctionTypeForm = 0x60;
|
||||
let kWasmAnyFunctionTypeForm = 0x70;
|
||||
|
||||
|
@ -336,15 +336,16 @@ class WasmModuleBuilder {
|
||||
}
|
||||
|
||||
// Add functions declarations
|
||||
let has_names = false;
|
||||
let num_function_names = 0;
|
||||
let names = false;
|
||||
if (wasm.functions.length > 0) {
|
||||
if (debug) print("emitting function decls @ " + binary.length);
|
||||
binary.emit_section(kFunctionSectionCode, section => {
|
||||
section.emit_u32v(wasm.functions.length);
|
||||
for (let func of wasm.functions) {
|
||||
has_names = has_names || (func.name != undefined &&
|
||||
func.name.length > 0);
|
||||
if (func.name !== undefined) {
|
||||
++num_function_names;
|
||||
}
|
||||
section.emit_u32v(func.type_index);
|
||||
}
|
||||
});
|
||||
@ -363,7 +364,7 @@ class WasmModuleBuilder {
|
||||
}
|
||||
|
||||
// Add memory section
|
||||
if (wasm.memory != undefined) {
|
||||
if (wasm.memory !== undefined) {
|
||||
if (debug) print("emitting memory @ " + binary.length);
|
||||
binary.emit_section(kMemorySectionCode, section => {
|
||||
section.emit_u8(1); // one memory entry
|
||||
@ -424,7 +425,7 @@ class WasmModuleBuilder {
|
||||
}
|
||||
|
||||
// Add export table.
|
||||
var mem_export = (wasm.memory != undefined && wasm.memory.exp);
|
||||
var mem_export = (wasm.memory !== undefined && wasm.memory.exp);
|
||||
var exports_count = wasm.exports.length + (mem_export ? 1 : 0);
|
||||
if (exports_count > 0) {
|
||||
if (debug) print("emitting exports @ " + binary.length);
|
||||
@ -444,7 +445,7 @@ class WasmModuleBuilder {
|
||||
}
|
||||
|
||||
// Add start function section.
|
||||
if (wasm.start_index != undefined) {
|
||||
if (wasm.start_index !== undefined) {
|
||||
if (debug) print("emitting start function @ " + binary.length);
|
||||
binary.emit_section(kStartSectionCode, section => {
|
||||
section.emit_u32v(wasm.start_index);
|
||||
@ -485,7 +486,7 @@ class WasmModuleBuilder {
|
||||
// Function body length will be patched later.
|
||||
let local_decls = [];
|
||||
let l = func.locals;
|
||||
if (l != undefined) {
|
||||
if (l !== undefined) {
|
||||
let local_decls_count = 0;
|
||||
if (l.i32_count > 0) {
|
||||
local_decls.push({count: l.i32_count, type: kWasmI32});
|
||||
@ -545,21 +546,18 @@ class WasmModuleBuilder {
|
||||
}
|
||||
|
||||
// Add function names.
|
||||
if (has_names) {
|
||||
if (debug) print("emitting names @ " + binary.length);
|
||||
if (num_function_names > 0) {
|
||||
if (debug) print('emitting names @ ' + binary.length);
|
||||
binary.emit_section(kUnknownSectionCode, section => {
|
||||
section.emit_string("name");
|
||||
var count = wasm.functions.length + wasm.num_imported_funcs;
|
||||
section.emit_u32v(count);
|
||||
for (var i = 0; i < wasm.num_imported_funcs; i++) {
|
||||
section.emit_u8(0); // empty string
|
||||
section.emit_u8(0); // local names count == 0
|
||||
}
|
||||
for (let func of wasm.functions) {
|
||||
var name = func.name == undefined ? "" : func.name;
|
||||
section.emit_string(name);
|
||||
section.emit_u8(0); // local names count == 0
|
||||
}
|
||||
section.emit_string('name');
|
||||
section.emit_section(kFunctionNamesCode, name_section => {
|
||||
name_section.emit_u32v(num_function_names);
|
||||
for (let func of wasm.functions) {
|
||||
if (func.name === undefined) continue;
|
||||
name_section.emit_u32v(func.index);
|
||||
name_section.emit_string(func.name);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user