Upgrade V8 to 5.1.281.57 DO NOT MERGE
FPIIM-449
Change-Id: Id981b686b4d587ac31697662eb98bb34be42ad90
(cherry picked from commit 3b9bc31999c9787eb726ecdbfd5796bfdec32a18)
diff --git a/src/wasm/module-decoder.cc b/src/wasm/module-decoder.cc
index 62b000d..3e85a1b 100644
--- a/src/wasm/module-decoder.cc
+++ b/src/wasm/module-decoder.cc
@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "src/wasm/module-decoder.h"
+
+#include "src/base/functional.h"
+#include "src/base/platform/platform.h"
#include "src/macro-assembler.h"
#include "src/objects.h"
#include "src/v8.h"
#include "src/wasm/decoder.h"
-#include "src/wasm/module-decoder.h"
namespace v8 {
namespace internal {
@@ -27,8 +30,8 @@
class ModuleDecoder : public Decoder {
public:
ModuleDecoder(Zone* zone, const byte* module_start, const byte* module_end,
- bool asm_js)
- : Decoder(module_start, module_end), module_zone(zone), asm_js_(asm_js) {
+ ModuleOrigin origin)
+ : Decoder(module_start, module_end), module_zone(zone), origin_(origin) {
result_.start = start_;
if (limit_ < start_) {
error(start_, "end is less than start");
@@ -40,86 +43,196 @@
pc_ = limit_; // On error, terminate section decoding loop.
}
+ static void DumpModule(WasmModule* module, ModuleResult result) {
+ std::string path;
+ if (FLAG_dump_wasm_module_path) {
+ path = FLAG_dump_wasm_module_path;
+ if (path.size() &&
+ !base::OS::isDirectorySeparator(path[path.size() - 1])) {
+ path += base::OS::DirectorySeparator();
+ }
+ }
+ // File are named `HASH.{ok,failed}.wasm`.
+ size_t hash = base::hash_range(module->module_start, module->module_end);
+ char buf[32] = {'\0'};
+#if V8_OS_WIN && _MSC_VER < 1900
+#define snprintf sprintf_s
+#endif
+ snprintf(buf, sizeof(buf) - 1, "%016zx.%s.wasm", hash,
+ result.ok() ? "ok" : "failed");
+ std::string name(buf);
+ if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(), "wb")) {
+ fwrite(module->module_start, module->module_end - module->module_start, 1,
+ wasm_file);
+ fclose(wasm_file);
+ }
+ }
+
// Decodes an entire module.
ModuleResult DecodeModule(WasmModule* module, bool verify_functions = true) {
pc_ = start_;
module->module_start = start_;
module->module_end = limit_;
- module->min_mem_size_log2 = 0;
- module->max_mem_size_log2 = 0;
+ module->min_mem_pages = 0;
+ module->max_mem_pages = 0;
module->mem_export = false;
module->mem_external = false;
- module->globals = new std::vector<WasmGlobal>();
- module->signatures = new std::vector<FunctionSig*>();
- module->functions = new std::vector<WasmFunction>();
- module->data_segments = new std::vector<WasmDataSegment>();
- module->function_table = new std::vector<uint16_t>();
- module->import_table = new std::vector<WasmImport>();
+ module->origin = origin_;
- bool sections[kMaxModuleSectionCode];
- memset(sections, 0, sizeof(sections));
+ bool sections[(size_t)WasmSection::Code::Max] = {false};
+
+ const byte* pos = pc_;
+ uint32_t magic_word = consume_u32("wasm magic");
+#define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff
+ if (magic_word != kWasmMagic) {
+ error(pos, pos,
+ "expected magic word %02x %02x %02x %02x, "
+ "found %02x %02x %02x %02x",
+ BYTES(kWasmMagic), BYTES(magic_word));
+ goto done;
+ }
+
+ pos = pc_;
+ {
+ uint32_t magic_version = consume_u32("wasm version");
+ if (magic_version != kWasmVersion) {
+ error(pos, pos,
+ "expected version %02x %02x %02x %02x, "
+ "found %02x %02x %02x %02x",
+ BYTES(kWasmVersion), BYTES(magic_version));
+ goto done;
+ }
+ }
// Decode the module sections.
while (pc_ < limit_) {
TRACE("DecodeSection\n");
- WasmSectionDeclCode section =
- static_cast<WasmSectionDeclCode>(consume_u8("section"));
- // Each section should appear at most once.
- if (section < kMaxModuleSectionCode) {
- CheckForPreviousSection(sections, section, false);
- sections[section] = true;
+ pos = pc_;
+
+ int length;
+ uint32_t section_length = consume_u32v(&length, "section size");
+
+ int section_string_leb_length = 0;
+ uint32_t section_string_length = 0;
+ WasmSection::Code section = consume_section_name(
+ §ion_string_leb_length, §ion_string_length);
+ uint32_t string_and_leb_length =
+ section_string_leb_length + section_string_length;
+ if (string_and_leb_length > section_length) {
+ error(pos, pos,
+ "section string of size %u longer than total section bytes %u",
+ string_and_leb_length, section_length);
+ break;
}
+ if (section == WasmSection::Code::Max) {
+ // Skip unknown section.
+ uint32_t skip = section_length - string_and_leb_length;
+ TRACE("skipping %u bytes from unknown section\n", skip);
+ consume_bytes(skip);
+ continue;
+ }
+
+ // Each section should appear at most once.
+ CheckForPreviousSection(sections, section, false);
+ sections[(size_t)section] = true;
+
switch (section) {
- case kDeclEnd:
+ case WasmSection::Code::End:
// Terminate section decoding.
limit_ = pc_;
break;
- case kDeclMemory:
- module->min_mem_size_log2 = consume_u8("min memory");
- module->max_mem_size_log2 = consume_u8("max memory");
+ case WasmSection::Code::Memory:
+ int length;
+ module->min_mem_pages = consume_u32v(&length, "min memory");
+ module->max_mem_pages = consume_u32v(&length, "max memory");
module->mem_export = consume_u8("export memory") != 0;
break;
- case kDeclSignatures: {
+ case WasmSection::Code::Signatures: {
int length;
uint32_t signatures_count = consume_u32v(&length, "signatures count");
- module->signatures->reserve(SafeReserve(signatures_count));
+ module->signatures.reserve(SafeReserve(signatures_count));
// Decode signatures.
for (uint32_t i = 0; i < signatures_count; i++) {
if (failed()) break;
TRACE("DecodeSignature[%d] module+%d\n", i,
static_cast<int>(pc_ - start_));
FunctionSig* s = consume_sig(); // read function sig.
- module->signatures->push_back(s);
+ module->signatures.push_back(s);
}
break;
}
- case kDeclFunctions: {
+ case WasmSection::Code::FunctionSignatures: {
// Functions require a signature table first.
- CheckForPreviousSection(sections, kDeclSignatures, true);
+ CheckForPreviousSection(sections, WasmSection::Code::Signatures,
+ true);
int length;
uint32_t functions_count = consume_u32v(&length, "functions count");
- module->functions->reserve(SafeReserve(functions_count));
+ module->functions.reserve(SafeReserve(functions_count));
+ for (uint32_t i = 0; i < functions_count; i++) {
+ module->functions.push_back(
+ {nullptr, i, 0, 0, 0, 0, 0, 0, false, false});
+ WasmFunction* function = &module->functions.back();
+ function->sig_index = consume_sig_index(module, &function->sig);
+ }
+ break;
+ }
+ case WasmSection::Code::FunctionBodies: {
+ // Function bodies should follow signatures.
+ CheckForPreviousSection(sections,
+ WasmSection::Code::FunctionSignatures, true);
+ int length;
+ const byte* pos = pc_;
+ uint32_t functions_count = consume_u32v(&length, "functions count");
+ if (functions_count != module->functions.size()) {
+ error(pos, pos, "function body count %u mismatch (%u expected)",
+ functions_count,
+ static_cast<uint32_t>(module->functions.size()));
+ break;
+ }
+ for (uint32_t i = 0; i < functions_count; i++) {
+ WasmFunction* function = &module->functions[i];
+ int length;
+ uint32_t size = consume_u32v(&length, "body size");
+ function->code_start_offset = pc_offset();
+ function->code_end_offset = pc_offset() + size;
+
+ TRACE(" +%d %-20s: (%d bytes)\n", pc_offset(), "function body",
+ size);
+ pc_ += size;
+ if (pc_ > limit_) {
+ error(pc_, "function body extends beyond end of file");
+ }
+ }
+ break;
+ }
+ case WasmSection::Code::Functions: {
+ // Functions require a signature table first.
+ CheckForPreviousSection(sections, WasmSection::Code::Signatures,
+ true);
+ int length;
+ uint32_t functions_count = consume_u32v(&length, "functions count");
+ module->functions.reserve(SafeReserve(functions_count));
// Set up module environment for verification.
ModuleEnv menv;
menv.module = module;
menv.instance = nullptr;
- menv.asm_js = asm_js_;
+ menv.origin = origin_;
// Decode functions.
for (uint32_t i = 0; i < functions_count; i++) {
if (failed()) break;
TRACE("DecodeFunction[%d] module+%d\n", i,
static_cast<int>(pc_ - start_));
- module->functions->push_back(
+ module->functions.push_back(
{nullptr, i, 0, 0, 0, 0, 0, 0, false, false});
- WasmFunction* function = &module->functions->back();
+ WasmFunction* function = &module->functions.back();
DecodeFunctionInModule(module, function, false);
}
if (ok() && verify_functions) {
for (uint32_t i = 0; i < functions_count; i++) {
if (failed()) break;
- WasmFunction* function = &module->functions->at(i);
+ WasmFunction* function = &module->functions[i];
if (!function->external) {
VerifyFunctionBody(i, &menv, function);
if (result_.failed())
@@ -129,132 +242,166 @@
}
break;
}
- case kDeclGlobals: {
+ case WasmSection::Code::Names: {
+ // Names correspond to functions.
+ CheckForPreviousSection(sections,
+ WasmSection::Code::FunctionSignatures, true);
+ int length;
+ const byte* pos = pc_;
+ uint32_t functions_count = consume_u32v(&length, "functions count");
+ if (functions_count != module->functions.size()) {
+ error(pos, pos, "function name count %u mismatch (%u expected)",
+ functions_count,
+ static_cast<uint32_t>(module->functions.size()));
+ break;
+ }
+
+ for (uint32_t i = 0; i < functions_count; i++) {
+ WasmFunction* function = &module->functions[i];
+ function->name_offset =
+ consume_string(&function->name_length, "function name");
+
+ uint32_t local_names_count =
+ consume_u32v(&length, "local names count");
+ for (uint32_t j = 0; j < local_names_count; j++) {
+ uint32_t unused = 0;
+ uint32_t offset = consume_string(&unused, "local name");
+ USE(unused);
+ USE(offset);
+ }
+ }
+ break;
+ }
+ case WasmSection::Code::Globals: {
int length;
uint32_t globals_count = consume_u32v(&length, "globals count");
- module->globals->reserve(SafeReserve(globals_count));
+ module->globals.reserve(SafeReserve(globals_count));
// Decode globals.
for (uint32_t i = 0; i < globals_count; i++) {
if (failed()) break;
TRACE("DecodeGlobal[%d] module+%d\n", i,
static_cast<int>(pc_ - start_));
- module->globals->push_back({0, MachineType::Int32(), 0, false});
- WasmGlobal* global = &module->globals->back();
+ module->globals.push_back({0, 0, MachineType::Int32(), 0, false});
+ WasmGlobal* global = &module->globals.back();
DecodeGlobalInModule(global);
}
break;
}
- case kDeclDataSegments: {
+ case WasmSection::Code::DataSegments: {
int length;
uint32_t data_segments_count =
consume_u32v(&length, "data segments count");
- module->data_segments->reserve(SafeReserve(data_segments_count));
+ module->data_segments.reserve(SafeReserve(data_segments_count));
// Decode data segments.
for (uint32_t i = 0; i < data_segments_count; i++) {
if (failed()) break;
TRACE("DecodeDataSegment[%d] module+%d\n", i,
static_cast<int>(pc_ - start_));
- module->data_segments->push_back({0, 0, 0});
- WasmDataSegment* segment = &module->data_segments->back();
+ module->data_segments.push_back({0, 0, 0});
+ WasmDataSegment* segment = &module->data_segments.back();
DecodeDataSegmentInModule(module, segment);
}
break;
}
- case kDeclFunctionTable: {
+ case WasmSection::Code::FunctionTable: {
// An indirect function table requires functions first.
- CheckForPreviousSection(sections, kDeclFunctions, true);
+ CheckForFunctions(module, section);
int length;
uint32_t function_table_count =
consume_u32v(&length, "function table count");
- module->function_table->reserve(SafeReserve(function_table_count));
+ module->function_table.reserve(SafeReserve(function_table_count));
// Decode function table.
for (uint32_t i = 0; i < function_table_count; i++) {
if (failed()) break;
TRACE("DecodeFunctionTable[%d] module+%d\n", i,
static_cast<int>(pc_ - start_));
- uint16_t index = consume_u16();
- if (index >= module->functions->size()) {
+ uint16_t index = consume_u32v(&length);
+ if (index >= module->functions.size()) {
error(pc_ - 2, "invalid function index");
break;
}
- module->function_table->push_back(index);
+ module->function_table.push_back(index);
}
break;
}
- case kDeclStartFunction: {
+ case WasmSection::Code::StartFunction: {
// Declares a start function for a module.
- CheckForPreviousSection(sections, kDeclFunctions, true);
+ CheckForFunctions(module, section);
if (module->start_function_index >= 0) {
error("start function already declared");
break;
}
- int length;
- const byte* before = pc_;
- uint32_t index = consume_u32v(&length, "start function index");
- if (index >= module->functions->size()) {
- error(before, "invalid start function index");
- break;
- }
- module->start_function_index = static_cast<int>(index);
- FunctionSig* sig =
- module->signatures->at(module->functions->at(index).sig_index);
- if (sig->parameter_count() > 0) {
- error(before, "invalid start function: non-zero parameter count");
+ WasmFunction* func;
+ const byte* pos = pc_;
+ module->start_function_index = consume_func_index(module, &func);
+ if (func && func->sig->parameter_count() > 0) {
+ error(pos, "invalid start function: non-zero parameter count");
break;
}
break;
}
- case kDeclImportTable: {
+ case WasmSection::Code::ImportTable: {
// Declares an import table.
- CheckForPreviousSection(sections, kDeclSignatures, true);
+ CheckForPreviousSection(sections, WasmSection::Code::Signatures,
+ true);
int length;
uint32_t import_table_count =
consume_u32v(&length, "import table count");
- module->import_table->reserve(SafeReserve(import_table_count));
+ module->import_table.reserve(SafeReserve(import_table_count));
// Decode import table.
for (uint32_t i = 0; i < import_table_count; i++) {
if (failed()) break;
TRACE("DecodeImportTable[%d] module+%d\n", i,
static_cast<int>(pc_ - start_));
- module->import_table->push_back({nullptr, 0, 0});
- WasmImport* import = &module->import_table->back();
+ module->import_table.push_back({nullptr, 0, 0});
+ WasmImport* import = &module->import_table.back();
- const byte* sigpos = pc_;
- import->sig_index = consume_u16("signature index");
-
- if (import->sig_index >= module->signatures->size()) {
- error(sigpos, "invalid signature index");
- } else {
- import->sig = module->signatures->at(import->sig_index);
+ import->sig_index = consume_sig_index(module, &import->sig);
+ const byte* pos = pc_;
+ import->module_name_offset = consume_string(
+ &import->module_name_length, "import module name");
+ if (import->module_name_length == 0) {
+ error(pos, "import module name cannot be NULL");
}
- import->module_name_offset = consume_string("import module name");
- import->function_name_offset =
- consume_string("import function name");
+ import->function_name_offset = consume_string(
+ &import->function_name_length, "import function name");
}
break;
}
- case kDeclWLL: {
- // Reserved for experimentation by the Web Low-level Language project
- // which is augmenting the binary encoding with source code meta
- // information. This section does not affect the semantics of the code
- // and can be ignored by the runtime. https://github.com/JSStats/wll
- int length = 0;
- uint32_t section_size = consume_u32v(&length, "section size");
- if (pc_ + section_size > limit_ || pc_ + section_size < pc_) {
- error(pc_ - length, "invalid section size");
- break;
+ case WasmSection::Code::ExportTable: {
+ // Declares an export table.
+ CheckForFunctions(module, section);
+ int length;
+ uint32_t export_table_count =
+ consume_u32v(&length, "export table count");
+ module->export_table.reserve(SafeReserve(export_table_count));
+ // Decode export table.
+ for (uint32_t i = 0; i < export_table_count; i++) {
+ if (failed()) break;
+ TRACE("DecodeExportTable[%d] module+%d\n", i,
+ static_cast<int>(pc_ - start_));
+
+ module->export_table.push_back({0, 0});
+ WasmExport* exp = &module->export_table.back();
+
+ WasmFunction* func;
+ exp->func_index = consume_func_index(module, &func);
+ exp->name_offset = consume_string(&exp->name_length, "export name");
}
- pc_ += section_size;
break;
}
- default:
- error(pc_ - 1, nullptr, "unrecognized section 0x%02x", section);
- break;
+ case WasmSection::Code::Max:
+ UNREACHABLE(); // Already skipped unknown sections.
}
}
- return toResult(module);
+ done:
+ ModuleResult result = toResult(module);
+ if (FLAG_dump_wasm_module) {
+ DumpModule(module, result);
+ }
+ return result;
}
uint32_t SafeReserve(uint32_t count) {
@@ -263,38 +410,23 @@
return count < kMaxReserve ? count : kMaxReserve;
}
- void CheckForPreviousSection(bool* sections, WasmSectionDeclCode section,
- bool present) {
- if (section >= kMaxModuleSectionCode) return;
- if (sections[section] == present) return;
- const char* name = "";
- switch (section) {
- case kDeclMemory:
- name = "memory";
- break;
- case kDeclSignatures:
- name = "signatures";
- break;
- case kDeclFunctions:
- name = "function declaration";
- break;
- case kDeclGlobals:
- name = "global variable";
- break;
- case kDeclDataSegments:
- name = "data segment";
- break;
- case kDeclFunctionTable:
- name = "function table";
- break;
- default:
- name = "";
- break;
+ void CheckForFunctions(WasmModule* module, WasmSection::Code section) {
+ if (module->functions.size() == 0) {
+ error(pc_ - 1, nullptr, "functions must appear before section %s",
+ WasmSection::getName(section));
}
+ }
+
+ void CheckForPreviousSection(bool* sections, WasmSection::Code section,
+ bool present) {
+ if (section >= WasmSection::Code::Max) return;
+ if (sections[(size_t)section] == present) return;
if (present) {
- error(pc_ - 1, nullptr, "required %s section missing", name);
+ error(pc_ - 1, nullptr, "required %s section missing",
+ WasmSection::getName(section));
} else {
- error(pc_ - 1, nullptr, "%s section already present", name);
+ error(pc_ - 1, nullptr, "%s section already present",
+ WasmSection::getName(section));
}
}
@@ -302,16 +434,13 @@
FunctionResult DecodeSingleFunction(ModuleEnv* module_env,
WasmFunction* function) {
pc_ = start_;
- function->sig = consume_sig(); // read signature
- function->name_offset = 0; // ---- name
- function->code_start_offset = off(pc_ + 8); // ---- code start
- function->code_end_offset = off(limit_); // ---- code end
- function->local_i32_count = consume_u16(); // read u16
- function->local_i64_count = consume_u16(); // read u16
- function->local_f32_count = consume_u16(); // read u16
- function->local_f64_count = consume_u16(); // read u16
- function->exported = false; // ---- exported
- function->external = false; // ---- external
+ function->sig = consume_sig(); // read signature
+ function->name_offset = 0; // ---- name
+ function->name_length = 0; // ---- name length
+ function->code_start_offset = off(pc_); // ---- code start
+ function->code_end_offset = off(limit_); // ---- code end
+ function->exported = false; // ---- exported
+ function->external = false; // ---- external
if (ok()) VerifyFunctionBody(0, module_env, function);
@@ -331,19 +460,20 @@
private:
Zone* module_zone;
ModuleResult result_;
- bool asm_js_;
+ ModuleOrigin origin_;
uint32_t off(const byte* ptr) { return static_cast<uint32_t>(ptr - start_); }
// Decodes a single global entry inside a module starting at {pc_}.
void DecodeGlobalInModule(WasmGlobal* global) {
- global->name_offset = consume_string("global name");
+ global->name_offset = consume_string(&global->name_length, "global name");
global->type = mem_type();
global->offset = 0;
global->exported = consume_u8("exported") != 0;
}
// Decodes a single function entry inside a module starting at {pc_}.
+ // TODO(titzer): legacy function body; remove
void DecodeFunctionInModule(WasmModule* module, WasmFunction* function,
bool verify_body = true) {
byte decl_bits = consume_u8("function decl");
@@ -351,10 +481,10 @@
const byte* sigpos = pc_;
function->sig_index = consume_u16("signature index");
- if (function->sig_index >= module->signatures->size()) {
+ if (function->sig_index >= module->signatures.size()) {
return error(sigpos, "invalid signature index");
} else {
- function->sig = module->signatures->at(function->sig_index);
+ function->sig = module->signatures[function->sig_index];
}
TRACE(" +%d <function attributes:%s%s%s%s%s>\n",
@@ -366,7 +496,8 @@
(decl_bits & kDeclFunctionImport) == 0 ? " body" : "");
if (decl_bits & kDeclFunctionName) {
- function->name_offset = consume_string("function name");
+ function->name_offset =
+ consume_string(&function->name_length, "function name");
}
function->exported = decl_bits & kDeclFunctionExport;
@@ -406,25 +537,30 @@
// Decodes a single data segment entry inside a module starting at {pc_}.
void DecodeDataSegmentInModule(WasmModule* module, WasmDataSegment* segment) {
- segment->dest_addr = consume_u32("destination");
- segment->source_offset = consume_offset("source offset");
- segment->source_size = consume_u32("source size");
- segment->init = consume_u8("init");
+ const byte* start = pc_;
+ int length;
+ segment->dest_addr = consume_u32v(&length, "destination");
+ segment->source_size = consume_u32v(&length, "source size");
+ segment->source_offset = static_cast<uint32_t>(pc_ - start_);
+ segment->init = true;
// Validate the data is in the module.
uint32_t module_limit = static_cast<uint32_t>(limit_ - start_);
if (!IsWithinLimit(module_limit, segment->source_offset,
segment->source_size)) {
- error(pc_ - sizeof(uint32_t), "segment out of bounds of module");
+ error(start, "segment out of bounds of module");
}
// Validate that the segment will fit into the (minimum) memory.
uint32_t memory_limit =
- 1 << (module ? module->min_mem_size_log2 : WasmModule::kMaxMemSize);
+ WasmModule::kPageSize * (module ? module->min_mem_pages
+ : WasmModule::kMaxMemPages);
if (!IsWithinLimit(memory_limit, segment->dest_addr,
segment->source_size)) {
- error(pc_ - sizeof(uint32_t), "segment out of bounds of memory");
+ error(start, "segment out of bounds of memory");
}
+
+ consume_bytes(segment->source_size);
}
// Verifies the body (code) of a given function.
@@ -436,18 +572,10 @@
<< std::endl;
os << std::endl;
}
- FunctionEnv fenv;
- fenv.module = menv;
- fenv.sig = function->sig;
- fenv.local_i32_count = function->local_i32_count;
- fenv.local_i64_count = function->local_i64_count;
- fenv.local_f32_count = function->local_f32_count;
- fenv.local_f64_count = function->local_f64_count;
- fenv.SumLocals();
-
- TreeResult result =
- VerifyWasmCode(&fenv, start_, start_ + function->code_start_offset,
- start_ + function->code_end_offset);
+ FunctionBody body = {menv, function->sig, start_,
+ start_ + function->code_start_offset,
+ start_ + function->code_end_offset};
+ TreeResult result = VerifyWasmCode(module_zone->allocator(), body);
if (result.failed()) {
// Wrap the error message from the function decoder.
std::ostringstream str;
@@ -476,11 +604,67 @@
return offset;
}
- // Reads a single 32-bit unsigned integer interpreted as an offset into the
- // data and validating the string there and advances.
- uint32_t consume_string(const char* name = nullptr) {
- // TODO(titzer): validate string
- return consume_offset(name ? name : "string");
+ // Reads a length-prefixed string, checking that it is within bounds. Returns
+ // the offset of the string, and the length as an out parameter.
+ uint32_t consume_string(uint32_t* length, const char* name = nullptr) {
+ int varint_length;
+ *length = consume_u32v(&varint_length, "string length");
+ uint32_t offset = pc_offset();
+ TRACE(" +%u %-20s: (%u bytes)\n", offset, "string", *length);
+ consume_bytes(*length);
+ return offset;
+ }
+
+ uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
+ const byte* pos = pc_;
+ int length;
+ uint32_t sig_index = consume_u32v(&length, "signature index");
+ if (sig_index >= module->signatures.size()) {
+ error(pos, pos, "signature index %u out of bounds (%d signatures)",
+ sig_index, static_cast<int>(module->signatures.size()));
+ *sig = nullptr;
+ return 0;
+ }
+ *sig = module->signatures[sig_index];
+ return sig_index;
+ }
+
+ uint32_t consume_func_index(WasmModule* module, WasmFunction** func) {
+ const byte* pos = pc_;
+ int length;
+ uint32_t func_index = consume_u32v(&length, "function index");
+ if (func_index >= module->functions.size()) {
+ error(pos, pos, "function index %u out of bounds (%d functions)",
+ func_index, static_cast<int>(module->functions.size()));
+ *func = nullptr;
+ return 0;
+ }
+ *func = &module->functions[func_index];
+ return func_index;
+ }
+
+ // Reads a section name.
+ WasmSection::Code consume_section_name(int* string_leb_length,
+ uint32_t* string_length) {
+ *string_length = consume_u32v(string_leb_length, "name length");
+ const byte* start = pc_;
+ consume_bytes(*string_length);
+ if (failed()) {
+ TRACE("Section name of length %u couldn't be read\n", *string_length);
+ return WasmSection::Code::Max;
+ }
+ // TODO(jfb) Linear search, it may be better to do a common-prefix search.
+ for (WasmSection::Code i = WasmSection::begin(); i != WasmSection::end();
+ i = WasmSection::next(i)) {
+ if (WasmSection::getNameLength(i) == *string_length &&
+ 0 == memcmp(WasmSection::getName(i), start, *string_length)) {
+ return i;
+ }
+ }
+ TRACE("Unknown section: '");
+ for (uint32_t i = 0; i != *string_length; ++i) TRACE("%c", *(start + i));
+ TRACE("'\n");
+ return WasmSection::Code::Max;
}
// Reads a single 8-bit integer, interpreting it as a local type.
@@ -537,7 +721,8 @@
// Parses an inline function signature.
FunctionSig* consume_sig() {
- byte count = consume_u8("param count");
+ int length;
+ byte count = consume_u32v(&length, "param count");
LocalType ret = consume_local_type();
FunctionSig::Builder builder(module_zone, ret == kAstStmt ? 0 : 1, count);
if (ret != kAstStmt) builder.AddReturn(ret);
@@ -579,22 +764,21 @@
}
};
-
ModuleResult DecodeWasmModule(Isolate* isolate, Zone* zone,
const byte* module_start, const byte* module_end,
- bool verify_functions, bool asm_js) {
+ bool verify_functions, ModuleOrigin origin) {
size_t size = module_end - module_start;
if (module_start > module_end) return ModuleError("start > end");
if (size >= kMaxModuleSize) return ModuleError("size > maximum module size");
WasmModule* module = new WasmModule();
- ModuleDecoder decoder(zone, module_start, module_end, asm_js);
+ ModuleDecoder decoder(zone, module_start, module_end, origin);
return decoder.DecodeModule(module, verify_functions);
}
FunctionSig* DecodeWasmSignatureForTesting(Zone* zone, const byte* start,
const byte* end) {
- ModuleDecoder decoder(zone, start, end, false);
+ ModuleDecoder decoder(zone, start, end, kWasmOrigin);
return decoder.DecodeFunctionSignature(start);
}
@@ -608,7 +792,7 @@
if (size > kMaxFunctionSize)
return FunctionError("size > maximum function size");
WasmFunction* function = new WasmFunction();
- ModuleDecoder decoder(zone, function_start, function_end, false);
+ ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin);
return decoder.DecodeSingleFunction(module_env, function);
}
} // namespace wasm