Merge V8 5.3.332.45.  DO NOT MERGE

Test: Manual

FPIIM-449

Change-Id: Id3254828b068abdea3cb10442e0172a8c9a98e03
(cherry picked from commit 13e2dadd00298019ed862f2b2fc5068bba730bcf)
diff --git a/src/wasm/module-decoder.cc b/src/wasm/module-decoder.cc
index f7d26a5..c356eb8 100644
--- a/src/wasm/module-decoder.cc
+++ b/src/wasm/module-decoder.cc
@@ -25,6 +25,8 @@
 #define TRACE(...)
 #endif
 
+namespace {
+
 // The main logic for decoding the bytes of a module.
 class ModuleDecoder : public Decoder {
  public:
@@ -108,9 +110,7 @@
       pos = pc_;
 
       // Read the section name.
-      int string_leb_length = 0;
-      uint32_t string_length =
-          consume_u32v(&string_leb_length, "section name length");
+      uint32_t string_length = consume_u32v("section name length");
       const byte* section_name_start = pc_;
       consume_bytes(string_length);
       if (failed()) {
@@ -118,13 +118,15 @@
         break;
       }
 
+      TRACE("  +%d  section name        : \"%.*s\"\n",
+            static_cast<int>(section_name_start - start_),
+            string_length < 20 ? string_length : 20, section_name_start);
+
       WasmSection::Code section =
           WasmSection::lookup(section_name_start, string_length);
 
       // Read and check the section size.
-      int section_leb_length = 0;
-      uint32_t section_length =
-          consume_u32v(&section_leb_length, "section length");
+      uint32_t section_length = consume_u32v("section length");
       if (!checkAvailable(section_length)) {
         // The section would extend beyond the end of the module.
         break;
@@ -140,18 +142,16 @@
           limit_ = pc_;
           break;
         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->min_mem_pages = consume_u32v("min memory");
+          module->max_mem_pages = consume_u32v("max memory");
           module->mem_export = consume_u8("export memory") != 0;
           break;
         }
         case WasmSection::Code::Signatures: {
-          int length;
-          uint32_t signatures_count = consume_u32v(&length, "signatures count");
+          uint32_t signatures_count = consume_u32v("signatures count");
           module->signatures.reserve(SafeReserve(signatures_count));
           // Decode signatures.
-          for (uint32_t i = 0; i < signatures_count; i++) {
+          for (uint32_t i = 0; i < signatures_count; ++i) {
             if (failed()) break;
             TRACE("DecodeSignature[%d] module+%d\n", i,
                   static_cast<int>(pc_ - start_));
@@ -161,37 +161,33 @@
           break;
         }
         case WasmSection::Code::FunctionSignatures: {
-          int length;
-          uint32_t functions_count = consume_u32v(&length, "functions count");
+          uint32_t functions_count = consume_u32v("functions count");
           module->functions.reserve(SafeReserve(functions_count));
-          for (uint32_t i = 0; i < functions_count; i++) {
+          for (uint32_t i = 0; i < functions_count; ++i) {
             module->functions.push_back({nullptr,  // sig
                                          i,        // func_index
                                          0,        // sig_index
                                          0,        // name_offset
                                          0,        // name_length
                                          0,        // code_start_offset
-                                         0,        // code_end_offset
-                                         false});  // exported
+                                         0});      // code_end_offset
             WasmFunction* function = &module->functions.back();
             function->sig_index = consume_sig_index(module, &function->sig);
           }
           break;
         }
         case WasmSection::Code::FunctionBodies: {
-          int length;
           const byte* pos = pc_;
-          uint32_t functions_count = consume_u32v(&length, "functions count");
+          uint32_t functions_count = consume_u32v("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++) {
+          for (uint32_t i = 0; i < functions_count; ++i) {
             WasmFunction* function = &module->functions[i];
-            int length;
-            uint32_t size = consume_u32v(&length, "body size");
+            uint32_t size = consume_u32v("body size");
             function->code_start_offset = pc_offset();
             function->code_end_offset = pc_offset() + size;
 
@@ -204,48 +200,9 @@
           }
           break;
         }
-        case WasmSection::Code::OldFunctions: {
-          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.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({nullptr,  // sig
-                                         i,        // func_index
-                                         0,        // sig_index
-                                         0,        // name_offset
-                                         0,        // name_length
-                                         0,        // code_start_offset
-                                         0,        // code_end_offset
-                                         false});  // exported
-            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[i];
-              VerifyFunctionBody(i, &menv, function);
-              if (result_.failed()) {
-                error(result_.error_pc, result_.error_msg.get());
-              }
-            }
-          }
-          break;
-        }
         case WasmSection::Code::Names: {
-          int length;
           const byte* pos = pc_;
-          uint32_t functions_count = consume_u32v(&length, "functions count");
+          uint32_t functions_count = consume_u32v("functions count");
           if (functions_count != module->functions.size()) {
             error(pos, pos, "function name count %u mismatch (%u expected)",
                   functions_count,
@@ -253,13 +210,12 @@
             break;
           }
 
-          for (uint32_t i = 0; i < functions_count; i++) {
+          for (uint32_t i = 0; i < functions_count; ++i) {
             WasmFunction* function = &module->functions[i];
             function->name_offset =
                 consume_string(&function->name_length, false);
 
-            uint32_t local_names_count =
-                consume_u32v(&length, "local names count");
+            uint32_t local_names_count = consume_u32v("local names count");
             for (uint32_t j = 0; j < local_names_count; j++) {
               uint32_t unused = 0;
               uint32_t offset = consume_string(&unused, false);
@@ -270,11 +226,10 @@
           break;
         }
         case WasmSection::Code::Globals: {
-          int length;
-          uint32_t globals_count = consume_u32v(&length, "globals count");
+          uint32_t globals_count = consume_u32v("globals count");
           module->globals.reserve(SafeReserve(globals_count));
           // Decode globals.
-          for (uint32_t i = 0; i < globals_count; i++) {
+          for (uint32_t i = 0; i < globals_count; ++i) {
             if (failed()) break;
             TRACE("DecodeGlobal[%d] module+%d\n", i,
                   static_cast<int>(pc_ - start_));
@@ -285,12 +240,10 @@
           break;
         }
         case WasmSection::Code::DataSegments: {
-          int length;
-          uint32_t data_segments_count =
-              consume_u32v(&length, "data segments count");
+          uint32_t data_segments_count = consume_u32v("data segments count");
           module->data_segments.reserve(SafeReserve(data_segments_count));
           // Decode data segments.
-          for (uint32_t i = 0; i < data_segments_count; i++) {
+          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_));
@@ -303,25 +256,39 @@
           }
           break;
         }
+        case WasmSection::Code::FunctionTablePad: {
+          if (!FLAG_wasm_jit_prototype) {
+            error("FunctionTablePad section without jiting enabled");
+          }
+          // An indirect function table requires functions first.
+          module->indirect_table_size = consume_u32v("indirect entry count");
+          if (module->indirect_table_size > 0 &&
+              module->indirect_table_size < module->function_table.size()) {
+            error("more predefined indirect entries than table can hold");
+          }
+          break;
+        }
         case WasmSection::Code::FunctionTable: {
           // An indirect function table requires functions first.
           CheckForFunctions(module, section);
-          int length;
-          uint32_t function_table_count =
-              consume_u32v(&length, "function table count");
+          uint32_t function_table_count = consume_u32v("function table count");
           module->function_table.reserve(SafeReserve(function_table_count));
           // Decode function table.
-          for (uint32_t i = 0; i < function_table_count; i++) {
+          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_u32v(&length);
+            uint16_t index = consume_u32v();
             if (index >= module->functions.size()) {
               error(pc_ - 2, "invalid function index");
               break;
             }
             module->function_table.push_back(index);
           }
+          if (module->indirect_table_size > 0 &&
+              module->indirect_table_size < module->function_table.size()) {
+            error("more predefined indirect entries than table can hold");
+          }
           break;
         }
         case WasmSection::Code::StartFunction: {
@@ -341,12 +308,10 @@
           break;
         }
         case WasmSection::Code::ImportTable: {
-          int length;
-          uint32_t import_table_count =
-              consume_u32v(&length, "import table count");
+          uint32_t import_table_count = consume_u32v("import table count");
           module->import_table.reserve(SafeReserve(import_table_count));
           // Decode import table.
-          for (uint32_t i = 0; i < import_table_count; i++) {
+          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_));
@@ -374,12 +339,10 @@
         case WasmSection::Code::ExportTable: {
           // Declares an export table.
           CheckForFunctions(module, section);
-          int length;
-          uint32_t export_table_count =
-              consume_u32v(&length, "export table count");
+          uint32_t export_table_count = consume_u32v("export table count");
           module->export_table.reserve(SafeReserve(export_table_count));
           // Decode export table.
-          for (uint32_t i = 0; i < export_table_count; i++) {
+          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_));
@@ -393,6 +356,32 @@
             exp->func_index = consume_func_index(module, &func);
             exp->name_offset = consume_string(&exp->name_length, true);
           }
+          // Check for duplicate exports.
+          if (ok() && module->export_table.size() > 1) {
+            std::vector<WasmExport> sorted_exports(module->export_table);
+            const byte* base = start_;
+            auto cmp_less = [base](const WasmExport& a, const WasmExport& b) {
+              // Return true if a < b.
+              uint32_t len = a.name_length;
+              if (len != b.name_length) return len < b.name_length;
+              return memcmp(base + a.name_offset, base + b.name_offset, len) <
+                     0;
+            };
+            std::stable_sort(sorted_exports.begin(), sorted_exports.end(),
+                             cmp_less);
+            auto it = sorted_exports.begin();
+            WasmExport* last = &*it++;
+            for (auto end = sorted_exports.end(); it != end; last = &*it++) {
+              DCHECK(!cmp_less(*it, *last));  // Vector must be sorted.
+              if (!cmp_less(*last, *it)) {
+                const byte* pc = start_ + it->name_offset;
+                error(pc, pc,
+                      "Duplicate export name '%.*s' for functions %d and %d",
+                      it->name_length, pc, last->func_index, it->func_index);
+                break;
+              }
+            }
+          }
           break;
         }
         case WasmSection::Code::Max:
@@ -419,7 +408,9 @@
     }
 
   done:
-    ModuleResult result = toResult(module);
+    if (ok()) CalculateGlobalsOffsets(module);
+    const WasmModule* finished_module = module;
+    ModuleResult result = toResult(finished_module);
     if (FLAG_dump_wasm_module) {
       DumpModule(module, result);
     }
@@ -462,7 +453,6 @@
     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
 
     if (ok()) VerifyFunctionBody(0, module_env, function);
 
@@ -489,53 +479,15 @@
   // Decodes a single global entry inside a module starting at {pc_}.
   void DecodeGlobalInModule(WasmGlobal* global) {
     global->name_offset = consume_string(&global->name_length, false);
-    DCHECK(unibrow::Utf8::Validate(start_ + global->name_offset,
-                                   global->name_length));
+    if (!unibrow::Utf8::Validate(start_ + global->name_offset,
+                                 global->name_length)) {
+      error("global name is not valid utf8");
+    }
     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");
-
-    const byte* sigpos = pc_;
-    function->sig_index = consume_u16("signature index");
-
-    if (function->sig_index >= module->signatures.size()) {
-      return error(sigpos, "invalid signature index");
-    } else {
-      function->sig = module->signatures[function->sig_index];
-    }
-
-    TRACE("  +%d  <function attributes:%s%s>\n", static_cast<int>(pc_ - start_),
-          decl_bits & kDeclFunctionName ? " name" : "",
-          decl_bits & kDeclFunctionExport ? " exported" : "");
-
-    function->exported = decl_bits & kDeclFunctionExport;
-
-    if (decl_bits & kDeclFunctionName) {
-      function->name_offset =
-          consume_string(&function->name_length, function->exported);
-    }
-
-    uint16_t size = consume_u16("body size");
-    if (ok()) {
-      if ((pc_ + size) > limit_) {
-        return error(pc_, limit_,
-                     "expected %d bytes for function body, fell off end", size);
-      }
-      function->code_start_offset = static_cast<uint32_t>(pc_ - start_);
-      function->code_end_offset = function->code_start_offset + size;
-      TRACE("  +%d  %-20s: (%d bytes)\n", static_cast<int>(pc_ - start_),
-            "function body", size);
-      pc_ += size;
-    }
-  }
-
   bool IsWithinLimit(uint32_t limit, uint32_t offset, uint32_t size) {
     if (offset > limit) return false;
     if ((offset + size) < offset) return false;  // overflow
@@ -545,9 +497,8 @@
   // Decodes a single data segment entry inside a module starting at {pc_}.
   void DecodeDataSegmentInModule(WasmModule* module, WasmDataSegment* segment) {
     const byte* start = pc_;
-    int length;
-    segment->dest_addr = consume_u32v(&length, "destination");
-    segment->source_size = consume_u32v(&length, "source size");
+    segment->dest_addr = consume_u32v("destination");
+    segment->source_size = consume_u32v("source size");
     segment->source_offset = static_cast<uint32_t>(pc_ - start_);
     segment->init = true;
 
@@ -570,6 +521,22 @@
     consume_bytes(segment->source_size);
   }
 
+  // Calculate individual global offsets and total size of globals table.
+  void CalculateGlobalsOffsets(WasmModule* module) {
+    uint32_t offset = 0;
+    if (module->globals.size() == 0) {
+      module->globals_size = 0;
+      return;
+    }
+    for (WasmGlobal& global : module->globals) {
+      byte size = WasmOpcodes::MemSize(global.type);
+      offset = (offset + size - 1) & ~(size - 1);  // align
+      global.offset = offset;
+      offset += size;
+    }
+    module->globals_size = offset;
+  }
+
   // Verifies the body (code) of a given function.
   void VerifyFunctionBody(uint32_t func_num, ModuleEnv* menv,
                           WasmFunction* function) {
@@ -613,8 +580,7 @@
   // 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, bool validate_utf8) {
-    int varint_length;
-    *length = consume_u32v(&varint_length, "string length");
+    *length = consume_u32v("string length");
     uint32_t offset = pc_offset();
     TRACE("  +%u  %-20s: (%u bytes)\n", offset, "string", *length);
     if (validate_utf8 && !unibrow::Utf8::Validate(pc_, *length)) {
@@ -626,8 +592,7 @@
 
   uint32_t consume_sig_index(WasmModule* module, FunctionSig** sig) {
     const byte* pos = pc_;
-    int length;
-    uint32_t sig_index = consume_u32v(&length, "signature index");
+    uint32_t sig_index = consume_u32v("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()));
@@ -640,8 +605,7 @@
 
   uint32_t consume_func_index(WasmModule* module, WasmFunction** func) {
     const byte* pos = pc_;
-    int length;
-    uint32_t func_index = consume_u32v(&length, "function index");
+    uint32_t func_index = consume_u32v("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()));
@@ -698,6 +662,8 @@
         return MachineType::Float32();
       case kMemF64:
         return MachineType::Float64();
+      case kMemS128:
+        return MachineType::Simd128();
       default:
         error(pc_ - 1, "invalid memory type");
         return MachineType::None();
@@ -713,11 +679,10 @@
             kWasmFunctionTypeForm, form);
       return nullptr;
     }
-    int length;
     // parse parameter types
-    uint32_t param_count = consume_u32v(&length, "param count");
+    uint32_t param_count = consume_u32v("param count");
     std::vector<LocalType> params;
-    for (uint32_t i = 0; i < param_count; i++) {
+    for (uint32_t i = 0; i < param_count; ++i) {
       LocalType param = consume_local_type();
       if (param == kAstStmt) error(pc_ - 1, "invalid void parameter type");
       params.push_back(param);
@@ -725,14 +690,14 @@
 
     // parse return types
     const byte* pt = pc_;
-    uint32_t return_count = consume_u32v(&length, "return count");
+    uint32_t return_count = consume_u32v("return count");
     if (return_count > kMaxReturnCount) {
       error(pt, pt, "return count of %u exceeds maximum of %u", return_count,
             kMaxReturnCount);
       return nullptr;
     }
     std::vector<LocalType> returns;
-    for (uint32_t i = 0; i < return_count; i++) {
+    for (uint32_t i = 0; i < return_count; ++i) {
       LocalType ret = consume_local_type();
       if (ret == kAstStmt) error(pc_ - 1, "invalid void return type");
       returns.push_back(ret);
@@ -742,8 +707,8 @@
     LocalType* buffer =
         module_zone->NewArray<LocalType>(param_count + return_count);
     uint32_t b = 0;
-    for (uint32_t i = 0; i < return_count; i++) buffer[b++] = returns[i];
-    for (uint32_t i = 0; i < param_count; i++) buffer[b++] = params[i];
+    for (uint32_t i = 0; i < return_count; ++i) buffer[b++] = returns[i];
+    for (uint32_t i = 0; i < param_count; ++i) buffer[b++] = params[i];
 
     return new (module_zone) FunctionSig(return_count, param_count, buffer);
   }
@@ -775,6 +740,41 @@
   }
 };
 
+Vector<const byte> FindSection(const byte* module_start, const byte* module_end,
+                               WasmSection::Code code) {
+  Decoder decoder(module_start, module_end);
+
+  uint32_t magic_word = decoder.consume_u32("wasm magic");
+  if (magic_word != kWasmMagic) decoder.error("wrong magic word");
+
+  uint32_t magic_version = decoder.consume_u32("wasm version");
+  if (magic_version != kWasmVersion) decoder.error("wrong wasm version");
+
+  while (decoder.more() && decoder.ok()) {
+    // Read the section name.
+    uint32_t string_length = decoder.consume_u32v("section name length");
+    const byte* section_name_start = decoder.pc();
+    decoder.consume_bytes(string_length);
+    if (decoder.failed()) break;
+
+    WasmSection::Code section =
+        WasmSection::lookup(section_name_start, string_length);
+
+    // Read and check the section size.
+    uint32_t section_length = decoder.consume_u32v("section length");
+
+    const byte* section_start = decoder.pc();
+    decoder.consume_bytes(section_length);
+    if (section == code && decoder.ok()) {
+      return Vector<const uint8_t>(section_start, section_length);
+    }
+  }
+
+  return Vector<const uint8_t>();
+}
+
+}  // namespace
+
 ModuleResult DecodeWasmModule(Isolate* isolate, Zone* zone,
                               const byte* module_start, const byte* module_end,
                               bool verify_functions, ModuleOrigin origin) {
@@ -818,6 +818,33 @@
   ModuleDecoder decoder(zone, function_start, function_end, kWasmOrigin);
   return decoder.DecodeSingleFunction(module_env, function);
 }
+
+FunctionOffsetsResult DecodeWasmFunctionOffsets(const byte* module_start,
+                                                const byte* module_end) {
+  Vector<const byte> code_section =
+      FindSection(module_start, module_end, WasmSection::Code::FunctionBodies);
+  Decoder decoder(code_section.start(), code_section.end());
+  if (!code_section.start()) decoder.error("no code section");
+
+  uint32_t functions_count = decoder.consume_u32v("functions count");
+  FunctionOffsets table;
+  // Take care of invalid input here.
+  if (functions_count < static_cast<unsigned>(code_section.length()) / 2)
+    table.reserve(functions_count);
+  int section_offset = static_cast<int>(code_section.start() - module_start);
+  DCHECK_LE(0, section_offset);
+  for (uint32_t i = 0; i < functions_count && decoder.ok(); ++i) {
+    uint32_t size = decoder.consume_u32v("body size");
+    int offset = static_cast<int>(section_offset + decoder.pc_offset());
+    table.push_back(std::make_pair(offset, static_cast<int>(size)));
+    DCHECK(table.back().first >= 0 && table.back().second >= 0);
+    decoder.consume_bytes(size);
+  }
+  if (decoder.more()) decoder.error("unexpected additional bytes");
+
+  return decoder.toResult(std::move(table));
+}
+
 }  // namespace wasm
 }  // namespace internal
 }  // namespace v8