LCOV - code coverage report
Current view: top level - src/wasm - module-decoder.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 496 540 91.9 %
Date: 2017-04-26 Functions: 32 35 91.4 %

          Line data    Source code
       1             : // Copyright 2015 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/wasm/module-decoder.h"
       6             : #include "src/wasm/function-body-decoder-impl.h"
       7             : 
       8             : #include "src/base/functional.h"
       9             : #include "src/base/platform/platform.h"
      10             : #include "src/counters.h"
      11             : #include "src/flags.h"
      12             : #include "src/macro-assembler.h"
      13             : #include "src/objects-inl.h"
      14             : #include "src/ostreams.h"
      15             : #include "src/v8.h"
      16             : 
      17             : #include "src/wasm/decoder.h"
      18             : #include "src/wasm/wasm-limits.h"
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : namespace wasm {
      23             : 
      24             : #if DEBUG
      25             : #define TRACE(...)                                    \
      26             :   do {                                                \
      27             :     if (FLAG_trace_wasm_decoder) PrintF(__VA_ARGS__); \
      28             :   } while (false)
      29             : #else
      30             : #define TRACE(...)
      31             : #endif
      32             : 
      33           0 : const char* SectionName(SectionCode code) {
      34           0 :   switch (code) {
      35             :     case kUnknownSectionCode:
      36             :       return "Unknown";
      37             :     case kTypeSectionCode:
      38             :       return "Type";
      39             :     case kImportSectionCode:
      40             :       return "Import";
      41             :     case kFunctionSectionCode:
      42             :       return "Function";
      43             :     case kTableSectionCode:
      44             :       return "Table";
      45             :     case kMemorySectionCode:
      46             :       return "Memory";
      47             :     case kGlobalSectionCode:
      48             :       return "Global";
      49             :     case kExportSectionCode:
      50             :       return "Export";
      51             :     case kStartSectionCode:
      52             :       return "Start";
      53             :     case kCodeSectionCode:
      54             :       return "Code";
      55             :     case kElementSectionCode:
      56             :       return "Element";
      57             :     case kDataSectionCode:
      58             :       return "Data";
      59             :     case kNameSectionCode:
      60             :       return "Name";
      61             :     default:
      62             :       return "<unknown>";
      63             :   }
      64             : }
      65             : 
      66             : namespace {
      67             : 
      68             : const char* kNameString = "name";
      69             : const size_t kNameStringLength = 4;
      70             : 
      71      446987 : ValueType TypeOf(const WasmModule* module, const WasmInitExpr& expr) {
      72      446987 :   switch (expr.kind) {
      73             :     case WasmInitExpr::kNone:
      74             :       return kWasmStmt;
      75             :     case WasmInitExpr::kGlobalIndex:
      76         146 :       return expr.val.global_index < module->globals.size()
      77             :                  ? module->globals[expr.val.global_index].type
      78         292 :                  : kWasmStmt;
      79             :     case WasmInitExpr::kI32Const:
      80             :       return kWasmI32;
      81             :     case WasmInitExpr::kI64Const:
      82             :       return kWasmI64;
      83             :     case WasmInitExpr::kF32Const:
      84             :       return kWasmF32;
      85             :     case WasmInitExpr::kF64Const:
      86             :       return kWasmF64;
      87             :     default:
      88           0 :       UNREACHABLE();
      89             :       return kWasmStmt;
      90             :   }
      91             : }
      92             : 
      93             : // Reads a length-prefixed string, checking that it is within bounds. Returns
      94             : // the offset of the string, and the length as an out parameter.
      95      262632 : uint32_t consume_string(Decoder& decoder, uint32_t* length, bool validate_utf8,
      96             :                         const char* name) {
      97      131316 :   *length = decoder.consume_u32v("string length");
      98             :   uint32_t offset = decoder.pc_offset();
      99             :   const byte* string_start = decoder.pc();
     100             :   // Consume bytes before validation to guarantee that the string is not oob.
     101      131316 :   if (*length > 0) {
     102      128236 :     decoder.consume_bytes(*length, name);
     103      206472 :     if (decoder.ok() && validate_utf8 &&
     104       78236 :         !unibrow::Utf8::Validate(string_start, *length)) {
     105         242 :       decoder.errorf(string_start, "%s: no valid UTF-8 string", name);
     106             :     }
     107             :   }
     108      131316 :   return offset;
     109             : }
     110             : 
     111             : // An iterator over the sections in a WASM binary module.
     112             : // Automatically skips all unknown sections.
     113             : class WasmSectionIterator {
     114             :  public:
     115       19586 :   explicit WasmSectionIterator(Decoder& decoder)
     116             :       : decoder_(decoder),
     117             :         section_code_(kUnknownSectionCode),
     118             :         section_start_(decoder.pc()),
     119       39172 :         section_end_(decoder.pc()) {
     120       19586 :     next();
     121             :   }
     122             : 
     123             :   inline bool more() const {
     124       19586 :     return section_code_ != kUnknownSectionCode && decoder_.more();
     125             :   }
     126             : 
     127             :   inline SectionCode section_code() const { return section_code_; }
     128             : 
     129             :   inline const byte* section_start() const { return section_start_; }
     130             : 
     131             :   inline uint32_t section_length() const {
     132         381 :     return static_cast<uint32_t>(section_end_ - section_start_);
     133             :   }
     134             : 
     135             :   inline const byte* payload_start() const { return payload_start_; }
     136             : 
     137             :   inline uint32_t payload_length() const {
     138       15400 :     return static_cast<uint32_t>(section_end_ - payload_start_);
     139             :   }
     140             : 
     141             :   inline const byte* section_end() const { return section_end_; }
     142             : 
     143             :   // Advances to the next section, checking that decoding the current section
     144             :   // stopped at {section_end_}.
     145      106081 :   void advance() {
     146      106081 :     if (decoder_.pc() != section_end_) {
     147         381 :       const char* msg = decoder_.pc() < section_end_ ? "shorter" : "longer";
     148             :       decoder_.errorf(decoder_.pc(),
     149             :                       "section was %s than expected size "
     150             :                       "(%u bytes expected, %zu decoded)",
     151             :                       msg, section_length(),
     152         762 :                       static_cast<size_t>(decoder_.pc() - section_start_));
     153             :     }
     154      106081 :     next();
     155      106080 :   }
     156             : 
     157             :  private:
     158             :   Decoder& decoder_;
     159             :   SectionCode section_code_;
     160             :   const byte* section_start_;
     161             :   const byte* payload_start_;
     162             :   const byte* section_end_;
     163             : 
     164             :   // Reads the section code/name at the current position and sets up
     165             :   // the embedder fields.
     166      125667 :   void next() {
     167             :     while (true) {
     168      279844 :       if (!decoder_.more()) {
     169       19395 :         section_code_ = kUnknownSectionCode;
     170       19395 :         return;
     171             :       }
     172             :       uint8_t section_code = decoder_.consume_u8("section code");
     173             :       // Read and check the section size.
     174      106495 :       uint32_t section_length = decoder_.consume_u32v("section length");
     175      212990 :       section_start_ = decoder_.pc();
     176      106495 :       payload_start_ = section_start_;
     177      106495 :       if (decoder_.checkAvailable(section_length)) {
     178             :         // Get the limit of the section within the module.
     179      106347 :         section_end_ = section_start_ + section_length;
     180             :       } else {
     181             :         // The section would extend beyond the end of the module.
     182         148 :         section_end_ = section_start_;
     183             :       }
     184             : 
     185      106495 :       if (section_code == kUnknownSectionCode) {
     186             :         // Check for the known "name" section.
     187             :         uint32_t string_length;
     188             :         uint32_t string_offset = wasm::consume_string(decoder_, &string_length,
     189       15621 :                                                       true, "section name");
     190       46859 :         if (decoder_.failed() || decoder_.pc() > section_end_) {
     191           7 :           section_code_ = kUnknownSectionCode;
     192           7 :           return;
     193             :         }
     194       15614 :         const byte* section_name_start = decoder_.start() + string_offset;
     195       15614 :         payload_start_ = decoder_.pc();
     196             : 
     197             :         TRACE("  +%d  section name        : \"%.*s\"\n",
     198             :               static_cast<int>(section_name_start - decoder_.start()),
     199             :               string_length < 20 ? string_length : 20, section_name_start);
     200             : 
     201       31031 :         if (string_length == kNameStringLength &&
     202             :             strncmp(reinterpret_cast<const char*>(section_name_start),
     203       15417 :                     kNameString, kNameStringLength) == 0) {
     204             :           section_code = kNameSectionCode;
     205             :         }
     206       90874 :       } else if (!IsValidSectionCode(section_code)) {
     207             :         decoder_.errorf(decoder_.pc(), "unknown section code #0x%02x",
     208           0 :                         section_code);
     209             :         section_code = kUnknownSectionCode;
     210             :       }
     211      106487 :       section_code_ = decoder_.failed()
     212             :                           ? kUnknownSectionCode
     213      106487 :                           : static_cast<SectionCode>(section_code);
     214             : 
     215             :       TRACE("Section: %s\n", SectionName(section_code_));
     216      106878 :       if (section_code_ == kUnknownSectionCode &&
     217         391 :           section_end_ > decoder_.pc()) {
     218             :         // skip to the end of the unknown section.
     219             :         uint32_t remaining =
     220         446 :             static_cast<uint32_t>(section_end_ - decoder_.pc());
     221         223 :         decoder_.consume_bytes(remaining, "section payload");
     222             :         // fall through and continue to the next section.
     223             :       } else {
     224             :         return;
     225             :       }
     226         223 :     }
     227             :   }
     228             : };
     229             : 
     230             : // The main logic for decoding the bytes of a module.
     231       39556 : class ModuleDecoder : public Decoder {
     232             :  public:
     233       19778 :   ModuleDecoder(Zone* zone, const byte* module_start, const byte* module_end,
     234             :                 ModuleOrigin origin)
     235             :       : Decoder(module_start, module_end),
     236             :         module_zone_(zone),
     237       39556 :         origin_(FLAG_assume_asmjs_origin ? kAsmJsOrigin : origin) {
     238       19778 :     if (end_ < start_) {
     239           0 :       error(start_, "end is less than start");
     240           0 :       end_ = start_;
     241             :     }
     242       19778 :   }
     243             : 
     244        1022 :   virtual void onFirstError() {
     245        1022 :     pc_ = end_;  // On error, terminate section decoding loop.
     246        1022 :   }
     247             : 
     248           0 :   void DumpModule(const ModuleResult& result) {
     249             :     std::string path;
     250           0 :     if (FLAG_dump_wasm_module_path) {
     251             :       path = FLAG_dump_wasm_module_path;
     252           0 :       if (path.size() &&
     253           0 :           !base::OS::isDirectorySeparator(path[path.size() - 1])) {
     254           0 :         path += base::OS::DirectorySeparator();
     255             :       }
     256             :     }
     257             :     // File are named `HASH.{ok,failed}.wasm`.
     258           0 :     size_t hash = base::hash_range(start_, end_);
     259           0 :     char buf[32] = {'\0'};
     260             : #if V8_OS_WIN && _MSC_VER < 1900
     261             : #define snprintf sprintf_s
     262             : #endif
     263             :     snprintf(buf, sizeof(buf) - 1, "%016zx.%s.wasm", hash,
     264           0 :              result.ok() ? "ok" : "failed");
     265           0 :     std::string name(buf);
     266           0 :     if (FILE* wasm_file = base::OS::FOpen((path + name).c_str(), "wb")) {
     267           0 :       fwrite(start_, end_ - start_, 1, wasm_file);
     268           0 :       fclose(wasm_file);
     269             :     }
     270           0 :   }
     271             : 
     272             :   // Decodes an entire module.
     273       19586 :   ModuleResult DecodeModule(bool verify_functions = true) {
     274       19586 :     pc_ = start_;
     275       19586 :     WasmModule* module = new WasmModule(module_zone_);
     276       19586 :     module->min_mem_pages = 0;
     277       19586 :     module->max_mem_pages = 0;
     278       19586 :     module->mem_export = false;
     279       19586 :     module->set_origin(origin_);
     280             : 
     281       19586 :     const byte* pos = pc_;
     282      124623 :     uint32_t magic_word = consume_u32("wasm magic");
     283             : #define BYTES(x) (x & 0xff), (x >> 8) & 0xff, (x >> 16) & 0xff, (x >> 24) & 0xff
     284       19586 :     if (magic_word != kWasmMagic) {
     285             :       errorf(pos,
     286             :              "expected magic word %02x %02x %02x %02x, "
     287             :              "found %02x %02x %02x %02x",
     288         136 :              BYTES(kWasmMagic), BYTES(magic_word));
     289             :     }
     290             : 
     291       19586 :     pos = pc_;
     292             :     {
     293             :       uint32_t magic_version = consume_u32("wasm version");
     294       19586 :       if (magic_version != kWasmVersion) {
     295             :         errorf(pos,
     296             :                "expected version %02x %02x %02x %02x, "
     297             :                "found %02x %02x %02x %02x",
     298         200 :                BYTES(kWasmVersion), BYTES(magic_version));
     299             :       }
     300             :     }
     301             : 
     302             :     WasmSectionIterator section_iter(*this);
     303             : 
     304             :     // ===== Type section ====================================================
     305       19586 :     if (section_iter.section_code() == kTypeSectionCode) {
     306       17735 :       uint32_t signatures_count = consume_count("types count", kV8MaxWasmTypes);
     307       17735 :       module->signatures.reserve(signatures_count);
     308      139382 :       for (uint32_t i = 0; ok() && i < signatures_count; ++i) {
     309             :         TRACE("DecodeSignature[%d] module+%d\n", i,
     310             :               static_cast<int>(pc_ - start_));
     311       51956 :         FunctionSig* s = consume_sig();
     312       51956 :         module->signatures.push_back(s);
     313             :       }
     314       17735 :       section_iter.advance();
     315             :     }
     316             : 
     317             :     // ===== Import section ==================================================
     318       19586 :     if (section_iter.section_code() == kImportSectionCode) {
     319             :       uint32_t import_table_count =
     320        8162 :           consume_count("imports count", kV8MaxWasmImports);
     321        8162 :       module->import_table.reserve(import_table_count);
     322       36436 :       for (uint32_t i = 0; ok() && i < import_table_count; ++i) {
     323             :         TRACE("DecodeImportTable[%d] module+%d\n", i,
     324             :               static_cast<int>(pc_ - start_));
     325             : 
     326             :         module->import_table.push_back({
     327             :             0,                  // module_name_length
     328             :             0,                  // module_name_offset
     329             :             0,                  // field_name_offset
     330             :             0,                  // field_name_length
     331             :             kExternalFunction,  // kind
     332             :             0                   // index
     333       20112 :         });
     334             :         WasmImport* import = &module->import_table.back();
     335       10056 :         const byte* pos = pc_;
     336             :         import->module_name_offset =
     337       20112 :             consume_string(&import->module_name_length, true, "module name");
     338             :         import->field_name_offset =
     339       20112 :             consume_string(&import->field_name_length, true, "field name");
     340             : 
     341       10056 :         import->kind = static_cast<WasmExternalKind>(consume_u8("import kind"));
     342       10056 :         switch (import->kind) {
     343             :           case kExternalFunction: {
     344             :             // ===== Imported function =======================================
     345      234081 :             import->index = static_cast<uint32_t>(module->functions.size());
     346        7620 :             module->num_imported_functions++;
     347             :             module->functions.push_back({nullptr,        // sig
     348             :                                          import->index,  // func_index
     349             :                                          0,              // sig_index
     350             :                                          0,              // name_offset
     351             :                                          0,              // name_length
     352             :                                          0,              // code_start_offset
     353             :                                          0,              // code_end_offset
     354             :                                          true,           // imported
     355       15240 :                                          false});        // exported
     356             :             WasmFunction* function = &module->functions.back();
     357        7620 :             function->sig_index = consume_sig_index(module, &function->sig);
     358        7620 :             break;
     359             :           }
     360             :           case kExternalTable: {
     361             :             // ===== Imported table ==========================================
     362         525 :             if (!AddTable(module)) break;
     363             :             import->index =
     364        1595 :                 static_cast<uint32_t>(module->function_tables.size());
     365             :             module->function_tables.push_back({0, 0, false,
     366             :                                                std::vector<int32_t>(), true,
     367        2100 :                                                false, SignatureMap()});
     368         525 :             expect_u8("element type", kWasmAnyFunctionTypeForm);
     369             :             WasmIndirectFunctionTable* table = &module->function_tables.back();
     370             :             consume_resizable_limits("element count", "elements",
     371             :                                      FLAG_wasm_max_table_size, &table->min_size,
     372             :                                      &table->has_max, FLAG_wasm_max_table_size,
     373         525 :                                      &table->max_size);
     374         525 :             break;
     375             :           }
     376             :           case kExternalMemory: {
     377             :             // ===== Imported memory =========================================
     378        1258 :             if (!AddMemory(module)) break;
     379             :             consume_resizable_limits(
     380             :                 "memory", "pages", FLAG_wasm_max_mem_pages,
     381             :                 &module->min_mem_pages, &module->has_max_mem,
     382        1227 :                 kSpecMaxWasmMemoryPages, &module->max_mem_pages);
     383        1227 :             break;
     384             :           }
     385             :           case kExternalGlobal: {
     386             :             // ===== Imported global =========================================
     387        2959 :             import->index = static_cast<uint32_t>(module->globals.size());
     388             :             module->globals.push_back(
     389        1959 :                 {kWasmStmt, false, WasmInitExpr(), 0, true, false});
     390             :             WasmGlobal* global = &module->globals.back();
     391         653 :             global->type = consume_value_type();
     392         653 :             global->mutability = consume_mutability();
     393         653 :             if (global->mutability) {
     394             :               error("mutable globals cannot be imported");
     395             :             }
     396             :             break;
     397             :           }
     398             :           default:
     399           0 :             errorf(pos, "unknown import kind 0x%02x", import->kind);
     400           0 :             break;
     401             :         }
     402             :       }
     403        8162 :       section_iter.advance();
     404             :     }
     405             : 
     406             :     // ===== Function section ================================================
     407       19586 :     if (section_iter.section_code() == kFunctionSectionCode) {
     408             :       uint32_t functions_count =
     409       17004 :           consume_count("functions count", kV8MaxWasmFunctions);
     410       17004 :       module->functions.reserve(functions_count);
     411       17004 :       module->num_declared_functions = functions_count;
     412      152818 :       for (uint32_t i = 0; ok() && i < functions_count; ++i) {
     413       59405 :         uint32_t func_index = static_cast<uint32_t>(module->functions.size());
     414             :         module->functions.push_back({nullptr,     // sig
     415             :                                      func_index,  // func_index
     416             :                                      0,           // sig_index
     417             :                                      0,           // name_offset
     418             :                                      0,           // name_length
     419             :                                      0,           // code_start_offset
     420             :                                      0,           // code_end_offset
     421             :                                      false,       // imported
     422      118810 :                                      false});     // exported
     423             :         WasmFunction* function = &module->functions.back();
     424       59405 :         function->sig_index = consume_sig_index(module, &function->sig);
     425             :       }
     426       17004 :       section_iter.advance();
     427             :     }
     428             : 
     429             :     // ===== Table section ===================================================
     430       19586 :     if (section_iter.section_code() == kTableSectionCode) {
     431         633 :       uint32_t table_count = consume_count("table count", kV8MaxWasmTables);
     432             : 
     433        2532 :       for (uint32_t i = 0; ok() && i < table_count; i++) {
     434         633 :         if (!AddTable(module)) break;
     435             :         module->function_tables.push_back({0, 0, false, std::vector<int32_t>(),
     436        2532 :                                            false, false, SignatureMap()});
     437             :         WasmIndirectFunctionTable* table = &module->function_tables.back();
     438         633 :         expect_u8("table type", kWasmAnyFunctionTypeForm);
     439             :         consume_resizable_limits("table elements", "elements",
     440             :                                  FLAG_wasm_max_table_size, &table->min_size,
     441             :                                  &table->has_max, FLAG_wasm_max_table_size,
     442         633 :                                  &table->max_size);
     443             :       }
     444         633 :       section_iter.advance();
     445             :     }
     446             : 
     447             :     // ===== Memory section ==================================================
     448       19586 :     if (section_iter.section_code() == kMemorySectionCode) {
     449        7020 :       uint32_t memory_count = consume_count("memory count", kV8MaxWasmMemories);
     450             : 
     451       28016 :       for (uint32_t i = 0; ok() && i < memory_count; i++) {
     452        7019 :         if (!AddMemory(module)) break;
     453             :         consume_resizable_limits("memory", "pages", FLAG_wasm_max_mem_pages,
     454             :                                  &module->min_mem_pages, &module->has_max_mem,
     455             :                                  kSpecMaxWasmMemoryPages,
     456        6988 :                                  &module->max_mem_pages);
     457             :       }
     458        7020 :       section_iter.advance();
     459             :     }
     460             : 
     461             :     // ===== Global section ==================================================
     462       19586 :     if (section_iter.section_code() == kGlobalSectionCode) {
     463             :       uint32_t globals_count =
     464        1653 :           consume_count("globals count", kV8MaxWasmGlobals);
     465        1653 :       uint32_t imported_globals = static_cast<uint32_t>(module->globals.size());
     466        1653 :       module->globals.reserve(imported_globals + globals_count);
     467      895920 :       for (uint32_t i = 0; ok() && i < globals_count; ++i) {
     468             :         TRACE("DecodeGlobal[%d] module+%d\n", i,
     469             :               static_cast<int>(pc_ - start_));
     470             :         // Add an uninitialized global and pass a pointer to it.
     471             :         module->globals.push_back(
     472     1338921 :             {kWasmStmt, false, WasmInitExpr(), 0, false, false});
     473      446307 :         WasmGlobal* global = &module->globals.back();
     474      446307 :         DecodeGlobalInModule(module, i + imported_globals, global);
     475             :       }
     476        1653 :       section_iter.advance();
     477             :     }
     478             : 
     479             :     // ===== Export section ==================================================
     480       19586 :     if (section_iter.section_code() == kExportSectionCode) {
     481             :       uint32_t export_table_count =
     482       15987 :           consume_count("exports count", kV8MaxWasmImports);
     483       27965 :       module->export_table.reserve(export_table_count);
     484      122644 :       for (uint32_t i = 0; ok() && i < export_table_count; ++i) {
     485             :         TRACE("DecodeExportTable[%d] module+%d\n", i,
     486             :               static_cast<int>(pc_ - start_));
     487             : 
     488             :         module->export_table.push_back({
     489             :             0,                  // name_length
     490             :             0,                  // name_offset
     491             :             kExternalFunction,  // kind
     492             :             0                   // index
     493       90670 :         });
     494             :         WasmExport* exp = &module->export_table.back();
     495             : 
     496             :         exp->name_offset =
     497       90670 :             consume_string(&exp->name_length, true, "field name");
     498             :         const byte* pos = pc();
     499       45335 :         exp->kind = static_cast<WasmExternalKind>(consume_u8("export kind"));
     500       45335 :         switch (exp->kind) {
     501             :           case kExternalFunction: {
     502       44190 :             WasmFunction* func = nullptr;
     503       44190 :             exp->index = consume_func_index(module, &func);
     504       44190 :             module->num_exported_functions++;
     505       44190 :             if (func) func->exported = true;
     506             :             break;
     507             :           }
     508             :           case kExternalTable: {
     509         256 :             WasmIndirectFunctionTable* table = nullptr;
     510         256 :             exp->index = consume_table_index(module, &table);
     511         256 :             if (table) table->exported = true;
     512             :             break;
     513             :           }
     514             :           case kExternalMemory: {
     515             :             uint32_t index = consume_u32v("memory index");
     516             :             // TODO(titzer): This should become more regular
     517             :             // once we support multiple memories.
     518         734 :             if (!module->has_memory || index != 0) {
     519             :               error("invalid memory index != 0");
     520             :             }
     521         734 :             module->mem_export = true;
     522         734 :             break;
     523             :           }
     524             :           case kExternalGlobal: {
     525         155 :             WasmGlobal* global = nullptr;
     526         155 :             exp->index = consume_global_index(module, &global);
     527         155 :             if (global) {
     528         155 :               if (global->mutability) {
     529             :                 error("mutable globals cannot be exported");
     530             :               }
     531         155 :               global->exported = true;
     532             :             }
     533             :             break;
     534             :           }
     535             :           default:
     536           0 :             errorf(pos, "invalid export kind 0x%02x", exp->kind);
     537           0 :             break;
     538             :         }
     539             :       }
     540             :       // Check for duplicate exports (except for asm.js).
     541       27965 :       if (ok() && origin_ != kAsmJsOrigin && module->export_table.size() > 1) {
     542        2574 :         std::vector<WasmExport> sorted_exports(module->export_table);
     543        2574 :         const byte* base = start_;
     544      150876 :         auto cmp_less = [base](const WasmExport& a, const WasmExport& b) {
     545             :           // Return true if a < b.
     546      150876 :           if (a.name_length != b.name_length) {
     547       18691 :             return a.name_length < b.name_length;
     548             :           }
     549      264370 :           return memcmp(base + a.name_offset, base + b.name_offset,
     550      396555 :                         a.name_length) < 0;
     551        2574 :         };
     552             :         std::stable_sort(sorted_exports.begin(), sorted_exports.end(),
     553        2574 :                          cmp_less);
     554             :         auto it = sorted_exports.begin();
     555       24129 :         WasmExport* last = &*it++;
     556       29260 :         for (auto end = sorted_exports.end(); it != end; last = &*it++) {
     557             :           DCHECK(!cmp_less(*it, *last));  // Vector must be sorted.
     558       24129 :           if (!cmp_less(*last, *it)) {
     559          17 :             const byte* pc = start_ + it->name_offset;
     560             :             errorf(pc, "Duplicate export name '%.*s' for functions %d and %d",
     561          17 :                    it->name_length, pc, last->index, it->index);
     562          17 :             break;
     563             :           }
     564             :         }
     565             :       }
     566       15987 :       section_iter.advance();
     567             :     }
     568             : 
     569             :     // ===== Start section ===================================================
     570       19586 :     if (section_iter.section_code() == kStartSectionCode) {
     571             :       WasmFunction* func;
     572        4928 :       const byte* pos = pc_;
     573        4928 :       module->start_function_index = consume_func_index(module, &func);
     574       14752 :       if (func &&
     575        9744 :           (func->sig->parameter_count() > 0 || func->sig->return_count() > 0)) {
     576             :         error(pos,
     577             :               "invalid start function: non-zero parameter or return count");
     578             :       }
     579        4928 :       section_iter.advance();
     580             :     }
     581             : 
     582             :     // ===== Elements section ================================================
     583       19586 :     if (section_iter.section_code() == kElementSectionCode) {
     584             :       uint32_t element_count =
     585         545 :           consume_count("element count", FLAG_wasm_max_table_size);
     586        2180 :       for (uint32_t i = 0; ok() && i < element_count; ++i) {
     587             :         const byte* pos = pc();
     588             :         uint32_t table_index = consume_u32v("table index");
     589         545 :         if (table_index != 0) {
     590           0 :           errorf(pos, "illegal table index %u != 0", table_index);
     591             :         }
     592             :         WasmIndirectFunctionTable* table = nullptr;
     593        1090 :         if (table_index >= module->function_tables.size()) {
     594           0 :           errorf(pos, "out of bounds table index %u", table_index);
     595           0 :           break;
     596             :         }
     597             :         table = &module->function_tables[table_index];
     598         545 :         WasmInitExpr offset = consume_init_expr(module, kWasmI32);
     599             :         uint32_t num_elem =
     600         545 :             consume_count("number of elements", kV8MaxWasmTableEntries);
     601             :         std::vector<uint32_t> vector;
     602        1090 :         module->table_inits.push_back({table_index, offset, vector});
     603             :         WasmTableInit* init = &module->table_inits.back();
     604        9286 :         for (uint32_t j = 0; ok() && j < num_elem; j++) {
     605        4098 :           WasmFunction* func = nullptr;
     606        4098 :           uint32_t index = consume_func_index(module, &func);
     607             :           DCHECK_EQ(func != nullptr, ok());
     608        4098 :           if (!func) break;
     609             :           DCHECK_EQ(index, func->func_index);
     610        4098 :           init->entries.push_back(index);
     611             :           // Canonicalize signature indices during decoding.
     612        4098 :           table->map.FindOrInsert(func->sig);
     613             :         }
     614             :       }
     615             : 
     616         545 :       section_iter.advance();
     617             :     }
     618             : 
     619             :     // ===== Code section ====================================================
     620       19586 :     if (section_iter.section_code() == kCodeSectionCode) {
     621       16787 :       const byte* pos = pc_;
     622             :       uint32_t functions_count = consume_u32v("functions count");
     623       16787 :       if (functions_count != module->num_declared_functions) {
     624             :         errorf(pos, "function body count %u mismatch (%u expected)",
     625           4 :                functions_count, module->num_declared_functions);
     626             :       }
     627      135069 :       for (uint32_t i = 0; ok() && i < functions_count; ++i) {
     628             :         WasmFunction* function =
     629       59141 :             &module->functions[i + module->num_imported_functions];
     630             :         uint32_t size = consume_u32v("body size");
     631       59141 :         function->code_start_offset = pc_offset();
     632       59141 :         function->code_end_offset = pc_offset() + size;
     633       59141 :         if (verify_functions) {
     634             :           ModuleBytesEnv module_env(module, nullptr,
     635        1172 :                                     ModuleWireBytes(start_, end_));
     636             :           VerifyFunctionBody(i + module->num_imported_functions, &module_env,
     637        1172 :                              function);
     638             :         }
     639       59141 :         consume_bytes(size, "function body");
     640             :       }
     641       16787 :       section_iter.advance();
     642             :     }
     643             : 
     644             :     // ===== Data section ====================================================
     645       19586 :     if (section_iter.section_code() == kDataSectionCode) {
     646             :       uint32_t data_segments_count =
     647         227 :           consume_count("data segments count", kV8MaxWasmDataSegments);
     648         227 :       module->data_segments.reserve(data_segments_count);
     649         908 :       for (uint32_t i = 0; ok() && i < data_segments_count; ++i) {
     650         229 :         if (!module->has_memory) {
     651             :           error("cannot load data without memory");
     652             :           break;
     653             :         }
     654             :         TRACE("DecodeDataSegment[%d] module+%d\n", i,
     655             :               static_cast<int>(pc_ - start_));
     656             :         module->data_segments.push_back({
     657             :             WasmInitExpr(),  // dest_addr
     658             :             0,               // source_offset
     659             :             0                // source_size
     660         454 :         });
     661         227 :         WasmDataSegment* segment = &module->data_segments.back();
     662         227 :         DecodeDataSegmentInModule(module, segment);
     663             :       }
     664         227 :       section_iter.advance();
     665             :     }
     666             : 
     667             :     // ===== Name section ====================================================
     668       19586 :     if (section_iter.section_code() == kNameSectionCode) {
     669             :       // TODO(titzer): find a way to report name errors as warnings.
     670             :       // Use an inner decoder so that errors don't fail the outer decoder.
     671       15400 :       Decoder inner(start_, pc_, end_);
     672             :       // Decode all name subsections.
     673             :       // Be lenient with their order.
     674       30770 :       while (inner.ok() && inner.more()) {
     675             :         uint8_t name_type = inner.consume_u8("name type");
     676       15405 :         if (name_type & 0x80) inner.error("name type if not varuint7");
     677             : 
     678             :         uint32_t name_payload_len = inner.consume_u32v("name payload length");
     679       15405 :         if (!inner.checkAvailable(name_payload_len)) break;
     680             : 
     681             :         // Decode function names, ignore the rest.
     682             :         // Local names will be decoded when needed.
     683       15370 :         if (name_type == NameSectionType::kFunction) {
     684             :           uint32_t functions_count = inner.consume_u32v("functions count");
     685             : 
     686      131148 :           for (; inner.ok() && functions_count > 0; --functions_count) {
     687             :             uint32_t function_index = inner.consume_u32v("function index");
     688       50248 :             uint32_t name_length = 0;
     689             :             uint32_t name_offset = wasm::consume_string(inner, &name_length,
     690       50248 :                                                         false, "function name");
     691             :             // Be lenient with errors in the name section: Ignore illegal
     692             :             // or out-of-order indexes and non-UTF8 names. You can even assign
     693             :             // to the same function multiple times (last valid one wins).
     694      150640 :             if (inner.ok() && function_index < module->functions.size() &&
     695       50196 :                 unibrow::Utf8::Validate(inner.start() + name_offset,
     696      100392 :                                         name_length)) {
     697      100198 :               module->functions[function_index].name_offset = name_offset;
     698       50099 :               module->functions[function_index].name_length = name_length;
     699             :             }
     700             :           }
     701             :         } else {
     702          44 :           inner.consume_bytes(name_payload_len, "name subsection payload");
     703             :         }
     704             :       }
     705             :       // Skip the whole names section in the outer decoder.
     706       30800 :       consume_bytes(section_iter.payload_length(), nullptr);
     707       15400 :       section_iter.advance();
     708             :     }
     709             : 
     710             :     // ===== Remaining sections ==============================================
     711       39188 :     if (section_iter.more() && ok()) {
     712             :       errorf(pc(), "unexpected section: %s",
     713          16 :              SectionName(section_iter.section_code()));
     714             :     }
     715             : 
     716             :     if (ok()) {
     717       18698 :       CalculateGlobalOffsets(module);
     718             :     }
     719             :     const WasmModule* finished_module = module;
     720       19586 :     ModuleResult result = toResult(finished_module);
     721       21463 :     if (verify_functions && result.ok()) {
     722             :       // Copy error code and location.
     723        1802 :       result.MoveErrorFrom(intermediate_result_);
     724             :     }
     725       19586 :     if (FLAG_dump_wasm_module) DumpModule(result);
     726       19586 :     return result;
     727             :   }
     728             : 
     729             :   // Decodes a single anonymous function starting at {start_}.
     730           1 :   FunctionResult DecodeSingleFunction(ModuleBytesEnv* module_env,
     731           1 :                                       WasmFunction* function) {
     732           1 :     pc_ = start_;
     733           1 :     function->sig = consume_sig();            // read signature
     734           1 :     function->name_offset = 0;                // ---- name
     735           1 :     function->name_length = 0;                // ---- name length
     736           2 :     function->code_start_offset = off(pc_);   // ---- code start
     737           2 :     function->code_end_offset = off(end_);    // ---- code end
     738             : 
     739           1 :     if (ok()) VerifyFunctionBody(0, module_env, function);
     740             : 
     741             :     FunctionResult result;
     742             :     // Copy error code and location.
     743           1 :     result.MoveErrorFrom(intermediate_result_);
     744           1 :     result.val = function;
     745           1 :     return result;
     746             :   }
     747             : 
     748             :   // Decodes a single function signature at {start}.
     749             :   FunctionSig* DecodeFunctionSignature(const byte* start) {
     750         170 :     pc_ = start;
     751         170 :     FunctionSig* result = consume_sig();
     752         170 :     return ok() ? result : nullptr;
     753             :   }
     754             : 
     755             :   WasmInitExpr DecodeInitExpr(const byte* start) {
     756          21 :     pc_ = start;
     757          21 :     return consume_init_expr(nullptr, kWasmStmt);
     758             :   }
     759             : 
     760             :  private:
     761             :   Zone* module_zone_;
     762             :   Result<bool> intermediate_result_;
     763             :   ModuleOrigin origin_;
     764             : 
     765           2 :   uint32_t off(const byte* ptr) { return static_cast<uint32_t>(ptr - start_); }
     766             : 
     767        1158 :   bool AddTable(WasmModule* module) {
     768        2316 :     if (module->function_tables.size() > 0) {
     769           0 :       error("At most one table is supported");
     770           0 :       return false;
     771             :     } else {
     772             :       return true;
     773             :     }
     774             :   }
     775             : 
     776             :   bool AddMemory(WasmModule* module) {
     777        8277 :     if (module->has_memory) {
     778             :       error("At most one memory is supported");
     779             :       return false;
     780             :     } else {
     781        8215 :       module->has_memory = true;
     782             :       return true;
     783             :     }
     784             :   }
     785             : 
     786             :   // Decodes a single global entry inside a module starting at {pc_}.
     787      446307 :   void DecodeGlobalInModule(WasmModule* module, uint32_t index,
     788             :                             WasmGlobal* global) {
     789      446307 :     global->type = consume_value_type();
     790      446307 :     global->mutability = consume_mutability();
     791      446307 :     const byte* pos = pc();
     792      446307 :     global->init = consume_init_expr(module, kWasmStmt);
     793      446307 :     switch (global->init.kind) {
     794             :       case WasmInitExpr::kGlobalIndex: {
     795          96 :         uint32_t other_index = global->init.val.global_index;
     796          96 :         if (other_index >= index) {
     797             :           errorf(pos,
     798             :                  "invalid global index in init expression, "
     799             :                  "index %u, other_index %u",
     800           0 :                  index, other_index);
     801         192 :         } else if (module->globals[other_index].type != global->type) {
     802             :           errorf(pos,
     803             :                  "type mismatch in global initialization "
     804             :                  "(from global #%u), expected %s, got %s",
     805             :                  other_index, WasmOpcodes::TypeName(global->type),
     806           0 :                  WasmOpcodes::TypeName(module->globals[other_index].type));
     807             :         }
     808             :         break;
     809             :       }
     810             :       default:
     811      446211 :         if (global->type != TypeOf(module, global->init)) {
     812             :           errorf(pos,
     813             :                  "type error in global initialization, expected %s, got %s",
     814             :                  WasmOpcodes::TypeName(global->type),
     815           0 :                  WasmOpcodes::TypeName(TypeOf(module, global->init)));
     816             :         }
     817             :     }
     818      446307 :   }
     819             : 
     820             :   bool IsWithinLimit(uint32_t limit, uint32_t offset, uint32_t size) {
     821         227 :     if (offset > limit) return false;
     822         227 :     if ((offset + size) < offset) return false;  // overflow
     823         227 :     return (offset + size) <= limit;
     824             :   }
     825             : 
     826             :   // Decodes a single data segment entry inside a module starting at {pc_}.
     827         227 :   void DecodeDataSegmentInModule(WasmModule* module, WasmDataSegment* segment) {
     828         227 :     const byte* start = pc_;
     829         227 :     expect_u8("linear memory index", 0);
     830         227 :     segment->dest_addr = consume_init_expr(module, kWasmI32);
     831         454 :     segment->source_size = consume_u32v("source size");
     832         227 :     segment->source_offset = static_cast<uint32_t>(pc_ - start_);
     833             : 
     834             :     // Validate the data is in the module.
     835         227 :     uint32_t module_limit = static_cast<uint32_t>(end_ - start_);
     836         227 :     if (!IsWithinLimit(module_limit, segment->source_offset,
     837             :                        segment->source_size)) {
     838             :       error(start, "segment out of bounds of module");
     839             :     }
     840             : 
     841         227 :     consume_bytes(segment->source_size, "segment data");
     842         227 :   }
     843             : 
     844             :   // Calculate individual global offsets and total size of globals table.
     845       18698 :   void CalculateGlobalOffsets(WasmModule* module) {
     846             :     uint32_t offset = 0;
     847       37396 :     if (module->globals.size() == 0) {
     848       16730 :       module->globals_size = 0;
     849       18698 :       return;
     850             :     }
     851      448915 :     for (WasmGlobal& global : module->globals) {
     852             :       byte size =
     853      446947 :           WasmOpcodes::MemSize(WasmOpcodes::MachineTypeFor(global.type));
     854      446947 :       offset = (offset + size - 1) & ~(size - 1);  // align
     855      446947 :       global.offset = offset;
     856      446947 :       offset += size;
     857             :     }
     858        1968 :     module->globals_size = offset;
     859             :   }
     860             : 
     861             :   // Verifies the body (code) of a given function.
     862        1173 :   void VerifyFunctionBody(uint32_t func_num, ModuleBytesEnv* menv,
     863        1173 :                           WasmFunction* function) {
     864             :     WasmFunctionName func_name(function,
     865        1173 :                                menv->wire_bytes.GetNameOrNull(function));
     866        1173 :     if (FLAG_trace_wasm_decoder || FLAG_trace_wasm_decode_time) {
     867           0 :       OFStream os(stdout);
     868           0 :       os << "Verifying WASM function " << func_name << std::endl;
     869             :     }
     870             :     FunctionBody body = {function->sig, start_,
     871        1173 :                          start_ + function->code_start_offset,
     872        2346 :                          start_ + function->code_end_offset};
     873             :     DecodeResult result = VerifyWasmCode(
     874             :         module_zone_->allocator(),
     875        2346 :         menv == nullptr ? nullptr : menv->module_env.module, body);
     876        1173 :     if (result.failed()) {
     877             :       // Wrap the error message from the function decoder.
     878         466 :       std::ostringstream str;
     879         466 :       str << "in function " << func_name << ": " << result.error_msg;
     880             : 
     881             :       // Set error code and location, if this is the first error.
     882         466 :       if (intermediate_result_.ok()) {
     883         466 :         intermediate_result_.MoveErrorFrom(result);
     884         466 :       }
     885             :     }
     886        1173 :   }
     887             : 
     888             :   uint32_t consume_string(uint32_t* length, bool validate_utf8,
     889             :                           const char* name) {
     890       65447 :     return wasm::consume_string(*this, length, validate_utf8, name);
     891             :   }
     892             : 
     893       67025 :   uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
     894       67025 :     const byte* pos = pc_;
     895       67025 :     uint32_t sig_index = consume_u32v("signature index");
     896      134050 :     if (sig_index >= module->signatures.size()) {
     897             :       errorf(pos, "signature index %u out of bounds (%d signatures)", sig_index,
     898          19 :              static_cast<int>(module->signatures.size()));
     899          19 :       *sig = nullptr;
     900          19 :       return 0;
     901             :     }
     902       67006 :     *sig = module->signatures[sig_index];
     903       67006 :     return sig_index;
     904             :   }
     905             : 
     906      173529 :   uint32_t consume_count(const char* name, size_t maximum) {
     907      173529 :     const byte* p = pc_;
     908      173529 :     uint32_t count = consume_u32v(name);
     909      173529 :     if (count > maximum) {
     910           4 :       errorf(p, "%s of %u exceeds internal limit of %zu", name, count, maximum);
     911           4 :       return static_cast<uint32_t>(maximum);
     912             :     }
     913             :     return count;
     914             :   }
     915             : 
     916             :   uint32_t consume_func_index(WasmModule* module, WasmFunction** func) {
     917       53216 :     return consume_index("function index", module->functions, func);
     918             :   }
     919             : 
     920             :   uint32_t consume_global_index(WasmModule* module, WasmGlobal** global) {
     921         155 :     return consume_index("global index", module->globals, global);
     922             :   }
     923             : 
     924             :   uint32_t consume_table_index(WasmModule* module,
     925             :                                WasmIndirectFunctionTable** table) {
     926         256 :     return consume_index("table index", module->function_tables, table);
     927             :   }
     928             : 
     929             :   template <typename T>
     930      107254 :   uint32_t consume_index(const char* name, std::vector<T>& vector, T** ptr) {
     931       53627 :     const byte* pos = pc_;
     932       53627 :     uint32_t index = consume_u32v(name);
     933      107254 :     if (index >= vector.size()) {
     934          38 :       errorf(pos, "%s %u out of bounds (%d entr%s)", name, index,
     935             :              static_cast<int>(vector.size()), vector.size() == 1 ? "y" : "ies");
     936          38 :       *ptr = nullptr;
     937          38 :       return 0;
     938             :     }
     939       53589 :     *ptr = &vector[index];
     940       53589 :     return index;
     941             :   }
     942             : 
     943        9373 :   void consume_resizable_limits(const char* name, const char* units,
     944             :                                 uint32_t max_initial, uint32_t* initial,
     945             :                                 bool* has_max, uint32_t max_maximum,
     946             :                                 uint32_t* maximum) {
     947       26774 :     uint32_t flags = consume_u32v("resizable limits flags");
     948             :     const byte* pos = pc();
     949        9373 :     *initial = consume_u32v("initial size");
     950        9373 :     *has_max = false;
     951        9373 :     if (*initial > max_initial) {
     952             :       errorf(pos,
     953             :              "initial %s size (%u %s) is larger than implementation limit (%u)",
     954           0 :              name, *initial, units, max_initial);
     955             :     }
     956        9373 :     if (flags & 1) {
     957        8028 :       *has_max = true;
     958             :       pos = pc();
     959        8028 :       *maximum = consume_u32v("maximum size");
     960        8028 :       if (*maximum > max_maximum) {
     961             :         errorf(
     962             :             pos,
     963             :             "maximum %s size (%u %s) is larger than implementation limit (%u)",
     964           2 :             name, *maximum, units, max_maximum);
     965             :       }
     966        8028 :       if (*maximum < *initial) {
     967             :         errorf(pos, "maximum %s size (%u %s) is less than initial (%u %s)",
     968           0 :                name, *maximum, units, *initial, units);
     969             :       }
     970             :     } else {
     971        1345 :       *has_max = false;
     972        1345 :       *maximum = max_initial;
     973             :     }
     974        9373 :   }
     975             : 
     976      500612 :   bool expect_u8(const char* name, uint8_t expected) {
     977      500612 :     const byte* pos = pc();
     978      500612 :     uint8_t value = consume_u8(name);
     979      500612 :     if (value != expected) {
     980         132 :       errorf(pos, "expected %s 0x%02x, got 0x%02x", name, expected, value);
     981         132 :       return false;
     982             :     }
     983             :     return true;
     984             :   }
     985             : 
     986      447100 :   WasmInitExpr consume_init_expr(WasmModule* module, ValueType expected) {
     987      894196 :     const byte* pos = pc();
     988      447100 :     uint8_t opcode = consume_u8("opcode");
     989             :     WasmInitExpr expr;
     990             :     unsigned len = 0;
     991      447100 :     switch (opcode) {
     992             :       case kExprGetGlobal: {
     993             :         GlobalIndexOperand<true> operand(this, pc() - 1);
     994         488 :         if (module->globals.size() <= operand.index) {
     995             :           error("global index is out of bounds");
     996             :           expr.kind = WasmInitExpr::kNone;
     997           0 :           expr.val.i32_const = 0;
     998           0 :           break;
     999             :         }
    1000             :         WasmGlobal* global = &module->globals[operand.index];
    1001         244 :         if (global->mutability || !global->imported) {
    1002             :           error(
    1003             :               "only immutable imported globals can be used in initializer "
    1004             :               "expressions");
    1005             :           expr.kind = WasmInitExpr::kNone;
    1006           2 :           expr.val.i32_const = 0;
    1007           2 :           break;
    1008             :         }
    1009         242 :         expr.kind = WasmInitExpr::kGlobalIndex;
    1010         242 :         expr.val.global_index = operand.index;
    1011         242 :         len = operand.length;
    1012         242 :         break;
    1013             :       }
    1014             :       case kExprI32Const: {
    1015             :         ImmI32Operand<true> operand(this, pc() - 1);
    1016        5158 :         expr.kind = WasmInitExpr::kI32Const;
    1017        5158 :         expr.val.i32_const = operand.value;
    1018        5158 :         len = operand.length;
    1019             :         break;
    1020             :       }
    1021             :       case kExprF32Const: {
    1022      441148 :         ImmF32Operand<true> operand(this, pc() - 1);
    1023      441148 :         expr.kind = WasmInitExpr::kF32Const;
    1024      441148 :         expr.val.f32_const = operand.value;
    1025      441148 :         len = operand.length;
    1026             :         break;
    1027             :       }
    1028             :       case kExprI64Const: {
    1029             :         ImmI64Operand<true> operand(this, pc() - 1);
    1030          38 :         expr.kind = WasmInitExpr::kI64Const;
    1031          38 :         expr.val.i64_const = operand.value;
    1032          38 :         len = operand.length;
    1033             :         break;
    1034             :       }
    1035             :       case kExprF64Const: {
    1036         508 :         ImmF64Operand<true> operand(this, pc() - 1);
    1037         508 :         expr.kind = WasmInitExpr::kF64Const;
    1038         508 :         expr.val.f64_const = operand.value;
    1039         508 :         len = operand.length;
    1040             :         break;
    1041             :       }
    1042             :       default: {
    1043             :         error("invalid opcode in initialization expression");
    1044             :         expr.kind = WasmInitExpr::kNone;
    1045           4 :         expr.val.i32_const = 0;
    1046             :       }
    1047             :     }
    1048      447100 :     consume_bytes(len, "init code");
    1049      447100 :     if (!expect_u8("end opcode", kExprEnd)) {
    1050          10 :       expr.kind = WasmInitExpr::kNone;
    1051             :     }
    1052      447100 :     if (expected != kWasmStmt && TypeOf(module, expr) != kWasmI32) {
    1053             :       errorf(pos, "type error in init expression, expected %s, got %s",
    1054             :              WasmOpcodes::TypeName(expected),
    1055           4 :              WasmOpcodes::TypeName(TypeOf(module, expr)));
    1056             :     }
    1057      447100 :     return expr;
    1058             :   }
    1059             : 
    1060             :   // Read a mutability flag
    1061      446960 :   bool consume_mutability() {
    1062      446960 :     byte val = consume_u8("mutability");
    1063      446960 :     if (val > 1) error(pc_ - 1, "invalid mutability");
    1064      446960 :     return val != 0;
    1065             :   }
    1066             : 
    1067             :   // Reads a single 8-bit integer, interpreting it as a local type.
    1068      545628 :   ValueType consume_value_type() {
    1069      545628 :     byte val = consume_u8("value type");
    1070             :     ValueTypeCode t = static_cast<ValueTypeCode>(val);
    1071      545628 :     switch (t) {
    1072             :       case kLocalI32:
    1073             :         return kWasmI32;
    1074             :       case kLocalI64:
    1075         328 :         return kWasmI64;
    1076             :       case kLocalF32:
    1077      445748 :         return kWasmF32;
    1078             :       case kLocalF64:
    1079        8464 :         return kWasmF64;
    1080             :       default:
    1081          27 :         if (origin_ != kAsmJsOrigin && FLAG_wasm_simd_prototype) {
    1082           0 :           switch (t) {
    1083             :             case kLocalS128:
    1084             :               return kWasmS128;
    1085             :             case kLocalS1x4:
    1086           0 :               return kWasmS1x4;
    1087             :             case kLocalS1x8:
    1088           0 :               return kWasmS1x8;
    1089             :             case kLocalS1x16:
    1090           0 :               return kWasmS1x16;
    1091             :             default:
    1092             :               break;
    1093             :           }
    1094             :         }
    1095          27 :         error(pc_ - 1, "invalid local type");
    1096          27 :         return kWasmStmt;
    1097             :     }
    1098             :   }
    1099             : 
    1100             :   // Parses a type entry, which is currently limited to functions only.
    1101       52127 :   FunctionSig* consume_sig() {
    1102       52127 :     if (!expect_u8("type form", kWasmFunctionTypeForm)) return nullptr;
    1103             :     // parse parameter types
    1104             :     uint32_t param_count =
    1105       52009 :         consume_count("param count", kV8MaxWasmFunctionParams);
    1106       52009 :     if (failed()) return nullptr;
    1107             :     std::vector<ValueType> params;
    1108      217416 :     for (uint32_t i = 0; ok() && i < param_count; ++i) {
    1109       56699 :       ValueType param = consume_value_type();
    1110       56699 :       params.push_back(param);
    1111             :     }
    1112             : 
    1113             :     // parse return types
    1114             :     const size_t max_return_count = FLAG_wasm_mv_prototype
    1115             :                                         ? kV8MaxWasmFunctionMultiReturns
    1116       52009 :                                         : kV8MaxWasmFunctionReturns;
    1117       52009 :     uint32_t return_count = consume_count("return count", max_return_count);
    1118       52009 :     if (failed()) return nullptr;
    1119             :     std::vector<ValueType> returns;
    1120      187940 :     for (uint32_t i = 0; ok() && i < return_count; ++i) {
    1121       41969 :       ValueType ret = consume_value_type();
    1122       41969 :       returns.push_back(ret);
    1123             :     }
    1124             : 
    1125       52001 :     if (failed()) return nullptr;
    1126             : 
    1127             :     // FunctionSig stores the return types first.
    1128             :     ValueType* buffer =
    1129       51983 :         module_zone_->NewArray<ValueType>(param_count + return_count);
    1130             :     uint32_t b = 0;
    1131       93934 :     for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i];
    1132      113368 :     for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i];
    1133             : 
    1134      155949 :     return new (module_zone_) FunctionSig(return_count, param_count, buffer);
    1135             :   }
    1136             : };
    1137             : 
    1138             : }  // namespace
    1139             : 
    1140       97929 : ModuleResult DecodeWasmModule(Isolate* isolate, const byte* module_start,
    1141             :                               const byte* module_end, bool verify_functions,
    1142             :                               ModuleOrigin origin) {
    1143             :   HistogramTimerScope wasm_decode_module_time_scope(
    1144             :       IsWasm(origin) ? isolate->counters()->wasm_decode_wasm_module_time()
    1145       39172 :                      : isolate->counters()->wasm_decode_asm_module_time());
    1146       19585 :   size_t size = module_end - module_start;
    1147       19585 :   if (module_start > module_end) return ModuleResult::Error("start > end");
    1148       19585 :   if (size >= kV8MaxWasmModuleSize)
    1149           0 :     return ModuleResult::Error("size > maximum module size: %zu", size);
    1150             :   // TODO(bradnelson): Improve histogram handling of size_t.
    1151             :   (IsWasm(origin) ? isolate->counters()->wasm_wasm_module_size_bytes()
    1152             :                   : isolate->counters()->wasm_asm_module_size_bytes())
    1153       39170 :       ->AddSample(static_cast<int>(size));
    1154             :   // Signatures are stored in zone memory, which have the same lifetime
    1155             :   // as the {module}.
    1156       39172 :   Zone* zone = new Zone(isolate->allocator(), ZONE_NAME);
    1157       39172 :   ModuleDecoder decoder(zone, module_start, module_end, origin);
    1158       39172 :   ModuleResult result = decoder.DecodeModule(verify_functions);
    1159             :   // TODO(bradnelson): Improve histogram handling of size_t.
    1160             :   // TODO(titzer): this isn't accurate, since it doesn't count the data
    1161             :   // allocated on the C++ heap.
    1162             :   // https://bugs.chromium.org/p/chromium/issues/detail?id=657320
    1163             :   (IsWasm(origin)
    1164             :        ? isolate->counters()->wasm_decode_wasm_module_peak_memory_bytes()
    1165             :        : isolate->counters()->wasm_decode_asm_module_peak_memory_bytes())
    1166       39172 :       ->AddSample(static_cast<int>(zone->allocation_size()));
    1167             :   return result;
    1168             : }
    1169             : 
    1170         170 : FunctionSig* DecodeWasmSignatureForTesting(Zone* zone, const byte* start,
    1171             :                                            const byte* end) {
    1172         170 :   ModuleDecoder decoder(zone, start, end, kWasmOrigin);
    1173         170 :   return decoder.DecodeFunctionSignature(start);
    1174             : }
    1175             : 
    1176          21 : WasmInitExpr DecodeWasmInitExprForTesting(const byte* start, const byte* end) {
    1177          21 :   AccountingAllocator allocator;
    1178          42 :   Zone zone(&allocator, ZONE_NAME);
    1179          42 :   ModuleDecoder decoder(&zone, start, end, kWasmOrigin);
    1180          21 :   return decoder.DecodeInitExpr(start);
    1181             : }
    1182             : 
    1183           3 : FunctionResult DecodeWasmFunction(Isolate* isolate, Zone* zone,
    1184             :                                   ModuleBytesEnv* module_env,
    1185             :                                   const byte* function_start,
    1186             :                                   const byte* function_end) {
    1187           1 :   bool is_wasm = module_env->module_env.is_wasm();
    1188             :   HistogramTimerScope wasm_decode_function_time_scope(
    1189             :       is_wasm ? isolate->counters()->wasm_decode_wasm_function_time()
    1190           2 :               : isolate->counters()->wasm_decode_asm_function_time());
    1191           1 :   size_t size = function_end - function_start;
    1192           1 :   if (function_start > function_end)
    1193           0 :     return FunctionResult::Error("start > end");
    1194           1 :   if (size > kV8MaxWasmFunctionSize)
    1195           0 :     return FunctionResult::Error("size > maximum function size: %zu", size);
    1196             :   (is_wasm ? isolate->counters()->wasm_wasm_function_size_bytes()
    1197             :            : isolate->counters()->wasm_asm_function_size_bytes())
    1198           2 :       ->AddSample(static_cast<int>(size));
    1199           1 :   WasmFunction* function = new WasmFunction();
    1200           2 :   ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin);
    1201           2 :   return decoder.DecodeSingleFunction(module_env, function);
    1202             : }
    1203             : 
    1204          78 : AsmJsOffsetsResult DecodeAsmJsOffsets(const byte* tables_start,
    1205             :                                       const byte* tables_end) {
    1206             :   AsmJsOffsets table;
    1207             : 
    1208             :   Decoder decoder(tables_start, tables_end);
    1209             :   uint32_t functions_count = decoder.consume_u32v("functions count");
    1210             :   // Reserve space for the entries, taking care of invalid input.
    1211          78 :   if (functions_count < static_cast<unsigned>(tables_end - tables_start)) {
    1212          78 :     table.reserve(functions_count);
    1213             :   }
    1214             : 
    1215         512 :   for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
    1216             :     uint32_t size = decoder.consume_u32v("table size");
    1217         256 :     if (size == 0) {
    1218          78 :       table.emplace_back();
    1219          78 :       continue;
    1220             :     }
    1221         178 :     if (!decoder.checkAvailable(size)) {
    1222             :       decoder.error("illegal asm function offset table size");
    1223             :     }
    1224         178 :     const byte* table_end = decoder.pc() + size;
    1225             :     uint32_t locals_size = decoder.consume_u32v("locals size");
    1226         178 :     int function_start_position = decoder.consume_u32v("function start pos");
    1227         178 :     int last_byte_offset = locals_size;
    1228             :     int last_asm_position = function_start_position;
    1229             :     std::vector<AsmJsOffsetEntry> func_asm_offsets;
    1230         178 :     func_asm_offsets.reserve(size / 4);  // conservative estimation
    1231             :     // Add an entry for the stack check, associated with position 0.
    1232             :     func_asm_offsets.push_back(
    1233         356 :         {0, function_start_position, function_start_position});
    1234         495 :     while (decoder.ok() && decoder.pc() < table_end) {
    1235         139 :       last_byte_offset += decoder.consume_u32v("byte offset delta");
    1236             :       int call_position =
    1237         139 :           last_asm_position + decoder.consume_i32v("call position delta");
    1238             :       int to_number_position =
    1239         139 :           call_position + decoder.consume_i32v("to_number position delta");
    1240             :       last_asm_position = to_number_position;
    1241             :       func_asm_offsets.push_back(
    1242         278 :           {last_byte_offset, call_position, to_number_position});
    1243             :     }
    1244         178 :     if (decoder.pc() != table_end) {
    1245             :       decoder.error("broken asm offset table");
    1246             :     }
    1247             :     table.push_back(std::move(func_asm_offsets));
    1248             :   }
    1249          78 :   if (decoder.more()) decoder.error("unexpected additional bytes");
    1250             : 
    1251         234 :   return decoder.toResult(std::move(table));
    1252             : }
    1253             : 
    1254          62 : std::vector<CustomSectionOffset> DecodeCustomSections(const byte* start,
    1255             :                                                       const byte* end) {
    1256             :   Decoder decoder(start, end);
    1257          62 :   decoder.consume_bytes(4, "wasm magic");
    1258          62 :   decoder.consume_bytes(4, "wasm version");
    1259             : 
    1260             :   std::vector<CustomSectionOffset> result;
    1261             : 
    1262         249 :   while (decoder.more()) {
    1263             :     byte section_code = decoder.consume_u8("section code");
    1264             :     uint32_t section_length = decoder.consume_u32v("section length");
    1265         187 :     uint32_t section_start = decoder.pc_offset();
    1266         187 :     if (section_code != 0) {
    1267             :       // Skip known sections.
    1268           2 :       decoder.consume_bytes(section_length, "section bytes");
    1269           2 :       continue;
    1270             :     }
    1271             :     uint32_t name_length = decoder.consume_u32v("name length");
    1272         185 :     uint32_t name_offset = decoder.pc_offset();
    1273         185 :     decoder.consume_bytes(name_length, "section name");
    1274         185 :     uint32_t payload_offset = decoder.pc_offset();
    1275         185 :     uint32_t payload_length = section_length - (payload_offset - section_start);
    1276         185 :     decoder.consume_bytes(payload_length);
    1277             :     result.push_back({section_start, name_offset, name_length, payload_offset,
    1278         370 :                       payload_length, section_length});
    1279             :   }
    1280             : 
    1281          62 :   return result;
    1282             : }
    1283             : 
    1284             : }  // namespace wasm
    1285             : }  // namespace internal
    1286             : }  // namespace v8

Generated by: LCOV version 1.10