LCOV - code coverage report
Current view: top level - src/wasm - module-instantiate.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 536 587 91.3 %
Date: 2019-04-19 Functions: 36 38 94.7 %

          Line data    Source code
       1             : // Copyright 2019 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-instantiate.h"
       6             : 
       7             : #include "src/asmjs/asm-js.h"
       8             : #include "src/conversions-inl.h"
       9             : #include "src/counters.h"
      10             : #include "src/property-descriptor.h"
      11             : #include "src/tracing/trace-event.h"
      12             : #include "src/utils.h"
      13             : #include "src/wasm/module-compiler.h"
      14             : #include "src/wasm/wasm-external-refs.h"
      15             : #include "src/wasm/wasm-import-wrapper-cache.h"
      16             : #include "src/wasm/wasm-module.h"
      17             : #include "src/wasm/wasm-objects-inl.h"
      18             : 
      19             : #define TRACE(...)                                      \
      20             :   do {                                                  \
      21             :     if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \
      22             :   } while (false)
      23             : 
      24             : namespace v8 {
      25             : namespace internal {
      26             : namespace wasm {
      27             : 
      28             : namespace {
      29             : byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) {
      30        8402 :   return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset;
      31             : }
      32             : 
      33        3126 : uint32_t EvalUint32InitExpr(Handle<WasmInstanceObject> instance,
      34             :                             const WasmInitExpr& expr) {
      35        3126 :   switch (expr.kind) {
      36             :     case WasmInitExpr::kI32Const:
      37        2414 :       return expr.val.i32_const;
      38             :     case WasmInitExpr::kGlobalIndex: {
      39             :       uint32_t offset =
      40        2136 :           instance->module()->globals[expr.val.global_index].offset;
      41             :       auto raw_addr =
      42             :           reinterpret_cast<Address>(
      43         712 :               instance->untagged_globals_buffer()->backing_store()) +
      44         712 :           offset;
      45             :       return ReadLittleEndianValue<uint32_t>(raw_addr);
      46             :     }
      47             :     default:
      48           0 :       UNREACHABLE();
      49             :   }
      50             : }
      51             : }  // namespace
      52             : 
      53             : // A helper class to simplify instantiating a module from a module object.
      54             : // It closes over the {Isolate}, the {ErrorThrower}, etc.
      55      272988 : class InstanceBuilder {
      56             :  public:
      57             :   InstanceBuilder(Isolate* isolate, ErrorThrower* thrower,
      58             :                   Handle<WasmModuleObject> module_object,
      59             :                   MaybeHandle<JSReceiver> ffi,
      60             :                   MaybeHandle<JSArrayBuffer> memory);
      61             : 
      62             :   // Build an instance, in all of its glory.
      63             :   MaybeHandle<WasmInstanceObject> Build();
      64             :   // Run the start function, if any.
      65             :   bool ExecuteStartFunction();
      66             : 
      67             :  private:
      68             :   // A pre-evaluated value to use in import binding.
      69             :   struct SanitizedImport {
      70             :     Handle<String> module_name;
      71             :     Handle<String> import_name;
      72             :     Handle<Object> value;
      73             :   };
      74             : 
      75             :   Isolate* isolate_;
      76             :   const WasmFeatures enabled_;
      77             :   const WasmModule* const module_;
      78             :   ErrorThrower* thrower_;
      79             :   Handle<WasmModuleObject> module_object_;
      80             :   MaybeHandle<JSReceiver> ffi_;
      81             :   MaybeHandle<JSArrayBuffer> memory_;
      82             :   Handle<JSArrayBuffer> untagged_globals_;
      83             :   Handle<FixedArray> tagged_globals_;
      84             :   std::vector<Handle<WasmExceptionObject>> exception_wrappers_;
      85             :   Handle<WasmExportedFunction> start_function_;
      86             :   std::vector<SanitizedImport> sanitized_imports_;
      87             : 
      88             : // Helper routines to print out errors with imports.
      89             : #define ERROR_THROWER_WITH_MESSAGE(TYPE)                                      \
      90             :   void Report##TYPE(const char* error, uint32_t index,                        \
      91             :                     Handle<String> module_name, Handle<String> import_name) { \
      92             :     thrower_->TYPE("Import #%d module=\"%s\" function=\"%s\" error: %s",      \
      93             :                    index, module_name->ToCString().get(),                     \
      94             :                    import_name->ToCString().get(), error);                    \
      95             :   }                                                                           \
      96             :                                                                               \
      97             :   MaybeHandle<Object> Report##TYPE(const char* error, uint32_t index,         \
      98             :                                    Handle<String> module_name) {              \
      99             :     thrower_->TYPE("Import #%d module=\"%s\" error: %s", index,               \
     100             :                    module_name->ToCString().get(), error);                    \
     101             :     return MaybeHandle<Object>();                                             \
     102             :   }
     103             : 
     104       10686 :   ERROR_THROWER_WITH_MESSAGE(LinkError)
     105        1536 :   ERROR_THROWER_WITH_MESSAGE(TypeError)
     106             : 
     107             : #undef ERROR_THROWER_WITH_MESSAGE
     108             : 
     109             :   // Look up an import value in the {ffi_} object.
     110             :   MaybeHandle<Object> LookupImport(uint32_t index, Handle<String> module_name,
     111             :                                    Handle<String> import_name);
     112             : 
     113             :   // Look up an import value in the {ffi_} object specifically for linking an
     114             :   // asm.js module. This only performs non-observable lookups, which allows
     115             :   // falling back to JavaScript proper (and hence re-executing all lookups) if
     116             :   // module instantiation fails.
     117             :   MaybeHandle<Object> LookupImportAsm(uint32_t index,
     118             :                                       Handle<String> import_name);
     119             : 
     120             :   // Load data segments into the memory.
     121             :   void LoadDataSegments(Handle<WasmInstanceObject> instance);
     122             : 
     123             :   void WriteGlobalValue(const WasmGlobal& global, double value);
     124             :   void WriteGlobalValue(const WasmGlobal& global, int64_t num);
     125             :   void WriteGlobalValue(const WasmGlobal& global,
     126             :                         Handle<WasmGlobalObject> value);
     127             : 
     128             :   void WriteGlobalAnyRef(const WasmGlobal& global, Handle<Object> value);
     129             : 
     130             :   void SanitizeImports();
     131             : 
     132             :   // Find the imported memory buffer if there is one. This is used to see if we
     133             :   // need to recompile with bounds checks before creating the instance.
     134             :   MaybeHandle<JSArrayBuffer> FindImportedMemoryBuffer() const;
     135             : 
     136             :   // Processes a single imported function.
     137             :   bool ProcessImportedFunction(Handle<WasmInstanceObject> instance,
     138             :                                int import_index, int func_index,
     139             :                                Handle<String> module_name,
     140             :                                Handle<String> import_name,
     141             :                                Handle<Object> value);
     142             : 
     143             :   // Process a single imported table.
     144             :   bool ProcessImportedTable(Handle<WasmInstanceObject> instance,
     145             :                             int import_index, int table_index,
     146             :                             Handle<String> module_name,
     147             :                             Handle<String> import_name, Handle<Object> value);
     148             : 
     149             :   // Process a single imported memory.
     150             :   bool ProcessImportedMemory(Handle<WasmInstanceObject> instance,
     151             :                              int import_index, Handle<String> module_name,
     152             :                              Handle<String> import_name, Handle<Object> value);
     153             : 
     154             :   // Process a single imported global.
     155             :   bool ProcessImportedGlobal(Handle<WasmInstanceObject> instance,
     156             :                              int import_index, int global_index,
     157             :                              Handle<String> module_name,
     158             :                              Handle<String> import_name, Handle<Object> value);
     159             : 
     160             :   // Process a single imported WasmGlobalObject.
     161             :   bool ProcessImportedWasmGlobalObject(Handle<WasmInstanceObject> instance,
     162             :                                        int import_index,
     163             :                                        Handle<String> module_name,
     164             :                                        Handle<String> import_name,
     165             :                                        const WasmGlobal& global,
     166             :                                        Handle<WasmGlobalObject> global_object);
     167             : 
     168             :   // Process the imports, including functions, tables, globals, and memory, in
     169             :   // order, loading them from the {ffi_} object. Returns the number of imported
     170             :   // functions.
     171             :   int ProcessImports(Handle<WasmInstanceObject> instance);
     172             : 
     173             :   template <typename T>
     174             :   T* GetRawGlobalPtr(const WasmGlobal& global);
     175             : 
     176             :   // Process initialization of globals.
     177             :   void InitGlobals();
     178             : 
     179             :   // Allocate memory for a module instance as a new JSArrayBuffer.
     180             :   Handle<JSArrayBuffer> AllocateMemory(uint32_t initial_pages,
     181             :                                        uint32_t maximum_pages);
     182             : 
     183             :   bool NeedsWrappers() const;
     184             : 
     185             :   // Process the exports, creating wrappers for functions, tables, memories,
     186             :   // and globals.
     187             :   void ProcessExports(Handle<WasmInstanceObject> instance);
     188             : 
     189             :   void InitializeTables(Handle<WasmInstanceObject> instance);
     190             : 
     191             :   void LoadTableSegments(Handle<WasmInstanceObject> instance);
     192             : 
     193             :   // Creates new exception tags for all exceptions. Note that some tags might
     194             :   // already exist if they were imported, those tags will be re-used.
     195             :   void InitializeExceptions(Handle<WasmInstanceObject> instance);
     196             : };
     197             : 
     198      136491 : MaybeHandle<WasmInstanceObject> InstantiateToInstanceObject(
     199             :     Isolate* isolate, ErrorThrower* thrower,
     200             :     Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports,
     201             :     MaybeHandle<JSArrayBuffer> memory) {
     202      272983 :   InstanceBuilder builder(isolate, thrower, module_object, imports, memory);
     203      136496 :   auto instance = builder.Build();
     204      136491 :   if (!instance.is_null() && builder.ExecuteStartFunction()) {
     205      133704 :     return instance;
     206             :   }
     207             :   DCHECK(isolate->has_pending_exception() || thrower->error());
     208        2788 :   return {};
     209             : }
     210             : 
     211      136492 : InstanceBuilder::InstanceBuilder(Isolate* isolate, ErrorThrower* thrower,
     212             :                                  Handle<WasmModuleObject> module_object,
     213             :                                  MaybeHandle<JSReceiver> ffi,
     214             :                                  MaybeHandle<JSArrayBuffer> memory)
     215             :     : isolate_(isolate),
     216      272984 :       enabled_(module_object->native_module()->enabled_features()),
     217      272985 :       module_(module_object->module()),
     218             :       thrower_(thrower),
     219             :       module_object_(module_object),
     220             :       ffi_(ffi),
     221      545970 :       memory_(memory) {
     222      136493 :   sanitized_imports_.reserve(module_->import_table.size());
     223      136496 : }
     224             : 
     225             : // Build an instance, in all of its glory.
     226      136496 : MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
     227      409485 :   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), "InstanceBuilder::Build");
     228             :   // Check that an imports argument was provided, if the module requires it.
     229             :   // No point in continuing otherwise.
     230      257888 :   if (!module_->import_table.empty() && ffi_.is_null()) {
     231          93 :     thrower_->TypeError(
     232          93 :         "Imports argument must be present and must be an object");
     233          93 :     return {};
     234             :   }
     235             : 
     236      136403 :   SanitizeImports();
     237      136403 :   if (thrower_->error()) return {};
     238             : 
     239             :   // From here on, we expect the build pipeline to run without exiting to JS.
     240      271997 :   DisallowJavascriptExecution no_js(isolate_);
     241             :   // Record build time into correct bucket, then build instance.
     242      272002 :   TimedHistogramScope wasm_instantiate_module_time_scope(SELECT_WASM_COUNTER(
     243      136001 :       isolate_->counters(), module_->origin, wasm_instantiate, module_time));
     244      136002 :   NativeModule* native_module = module_object_->native_module();
     245             : 
     246             :   //--------------------------------------------------------------------------
     247             :   // Allocate the memory array buffer.
     248             :   //--------------------------------------------------------------------------
     249      136002 :   uint32_t initial_pages = module_->initial_pages;
     250      140866 :   auto initial_pages_counter = SELECT_WASM_COUNTER(
     251             :       isolate_->counters(), module_->origin, wasm, min_mem_pages_count);
     252      136002 :   initial_pages_counter->AddSample(initial_pages);
     253      136001 :   if (module_->has_maximum_pages) {
     254             :     DCHECK_EQ(kWasmOrigin, module_->origin);
     255             :     auto max_pages_counter =
     256        3744 :         isolate_->counters()->wasm_wasm_max_mem_pages_count();
     257        3744 :     max_pages_counter->AddSample(module_->maximum_pages);
     258             :   }
     259             :   // Asm.js has memory_ already set at this point, so we don't want to
     260             :   // overwrite it.
     261      136000 :   if (memory_.is_null()) {
     262      134760 :     memory_ = FindImportedMemoryBuffer();
     263             :   }
     264      136001 :   if (!memory_.is_null()) {
     265             :     // Set externally passed ArrayBuffer non detachable.
     266             :     Handle<JSArrayBuffer> memory = memory_.ToHandleChecked();
     267             :     memory->set_is_detachable(false);
     268             : 
     269             :     DCHECK_IMPLIES(native_module->use_trap_handler(),
     270             :                    module_->origin == kAsmJsOrigin ||
     271             :                        memory->is_wasm_memory() ||
     272             :                        memory->backing_store() == nullptr);
     273      131300 :   } else if (initial_pages > 0 || native_module->use_trap_handler()) {
     274             :     // We need to unconditionally create a guard region if using trap handlers,
     275             :     // even when the size is zero to prevent null-dereference issues
     276             :     // (e.g. https://crbug.com/769637).
     277             :     // Allocate memory if the initial size is more than 0 pages.
     278      131238 :     memory_ = AllocateMemory(initial_pages, module_->maximum_pages);
     279      131238 :     if (memory_.is_null()) {
     280             :       // failed to allocate memory
     281             :       DCHECK(isolate_->has_pending_exception() || thrower_->error());
     282          16 :       return {};
     283             :     }
     284             :   }
     285             : 
     286             :   //--------------------------------------------------------------------------
     287             :   // Create the WebAssembly.Instance object.
     288             :   //--------------------------------------------------------------------------
     289             :   TRACE("New module instantiation for %p\n", native_module);
     290             :   Handle<WasmInstanceObject> instance =
     291      135985 :       WasmInstanceObject::New(isolate_, module_object_);
     292      271961 :   NativeModuleModificationScope native_modification_scope(native_module);
     293             : 
     294             :   //--------------------------------------------------------------------------
     295             :   // Set up the globals for the new instance.
     296             :   //--------------------------------------------------------------------------
     297      135982 :   uint32_t untagged_globals_buffer_size = module_->untagged_globals_buffer_size;
     298      135982 :   if (untagged_globals_buffer_size > 0) {
     299        6534 :     void* backing_store = isolate_->array_buffer_allocator()->Allocate(
     300        6534 :         untagged_globals_buffer_size);
     301        3267 :     if (backing_store == nullptr) {
     302           0 :       thrower_->RangeError("Out of memory: wasm globals");
     303           0 :       return {};
     304             :     }
     305        3267 :     untagged_globals_ = isolate_->factory()->NewJSArrayBuffer(
     306        3267 :         SharedFlag::kNotShared, AllocationType::kOld);
     307             :     constexpr bool is_external = false;
     308             :     constexpr bool is_wasm_memory = false;
     309        3267 :     JSArrayBuffer::Setup(untagged_globals_, isolate_, is_external,
     310             :                          backing_store, untagged_globals_buffer_size,
     311        3267 :                          SharedFlag::kNotShared, is_wasm_memory);
     312        3267 :     if (untagged_globals_.is_null()) {
     313           0 :       thrower_->RangeError("Out of memory: wasm globals");
     314           0 :       return {};
     315             :     }
     316             :     instance->set_globals_start(
     317             :         reinterpret_cast<byte*>(untagged_globals_->backing_store()));
     318        3267 :     instance->set_untagged_globals_buffer(*untagged_globals_);
     319             :   }
     320             : 
     321      135982 :   uint32_t tagged_globals_buffer_size = module_->tagged_globals_buffer_size;
     322      135982 :   if (tagged_globals_buffer_size > 0) {
     323         400 :     tagged_globals_ = isolate_->factory()->NewFixedArray(
     324         800 :         static_cast<int>(tagged_globals_buffer_size));
     325         400 :     instance->set_tagged_globals_buffer(*tagged_globals_);
     326             :   }
     327             : 
     328             :   //--------------------------------------------------------------------------
     329             :   // Set up the array of references to imported globals' array buffers.
     330             :   //--------------------------------------------------------------------------
     331      135982 :   if (module_->num_imported_mutable_globals > 0) {
     332             :     // TODO(binji): This allocates one slot for each mutable global, which is
     333             :     // more than required if multiple globals are imported from the same
     334             :     // module.
     335         264 :     Handle<FixedArray> buffers_array = isolate_->factory()->NewFixedArray(
     336         528 :         module_->num_imported_mutable_globals, AllocationType::kOld);
     337         264 :     instance->set_imported_mutable_globals_buffers(*buffers_array);
     338             :   }
     339             : 
     340             :   //--------------------------------------------------------------------------
     341             :   // Set up the exception table used for exception tag checks.
     342             :   //--------------------------------------------------------------------------
     343      271964 :   int exceptions_count = static_cast<int>(module_->exceptions.size());
     344      135982 :   if (exceptions_count > 0) {
     345         616 :     Handle<FixedArray> exception_table = isolate_->factory()->NewFixedArray(
     346         616 :         exceptions_count, AllocationType::kOld);
     347         616 :     instance->set_exceptions_table(*exception_table);
     348         616 :     exception_wrappers_.resize(exceptions_count);
     349             :   }
     350             : 
     351             :   //--------------------------------------------------------------------------
     352             :   // Set up table storage space.
     353             :   //--------------------------------------------------------------------------
     354      271964 :   int table_count = static_cast<int>(module_->tables.size());
     355      135982 :   Handle<FixedArray> tables = isolate_->factory()->NewFixedArray(table_count);
     356      137350 :   for (int i = module_->num_imported_tables; i < table_count; i++) {
     357        1369 :     const WasmTable& table = module_->tables[i];
     358             :     Handle<WasmTableObject> table_obj = WasmTableObject::New(
     359        2738 :         isolate_, table.type, table.initial_size, table.has_maximum_size,
     360        4107 :         table.maximum_size, nullptr);
     361        2738 :     tables->set(i, *table_obj);
     362             :   }
     363      135981 :   instance->set_tables(*tables);
     364             : 
     365             :   //--------------------------------------------------------------------------
     366             :   // Process the imports for the module.
     367             :   //--------------------------------------------------------------------------
     368      135985 :   int num_imported_functions = ProcessImports(instance);
     369      135984 :   if (num_imported_functions < 0) return {};
     370             : 
     371             :   //--------------------------------------------------------------------------
     372             :   // Process the initialization for the module's globals.
     373             :   //--------------------------------------------------------------------------
     374      134023 :   InitGlobals();
     375             : 
     376             :   //--------------------------------------------------------------------------
     377             :   // Initialize the indirect tables.
     378             :   //--------------------------------------------------------------------------
     379      134023 :   if (table_count > 0) {
     380        2345 :     InitializeTables(instance);
     381             :   }
     382             : 
     383             :   //--------------------------------------------------------------------------
     384             :   // Initialize the exceptions table.
     385             :   //--------------------------------------------------------------------------
     386      134022 :   if (exceptions_count > 0) {
     387         576 :     InitializeExceptions(instance);
     388             :   }
     389             : 
     390             :   //--------------------------------------------------------------------------
     391             :   // Create the WebAssembly.Memory object.
     392             :   //--------------------------------------------------------------------------
     393      134022 :   if (module_->has_memory) {
     394       12608 :     if (!instance->has_memory_object()) {
     395             :       // No memory object exists. Create one.
     396             :       Handle<WasmMemoryObject> memory_object = WasmMemoryObject::New(
     397             :           isolate_, memory_,
     398        9237 :           module_->maximum_pages != 0 ? module_->maximum_pages : -1);
     399        9237 :       instance->set_memory_object(*memory_object);
     400             :     }
     401             : 
     402             :     // Add the instance object to the list of instances for this memory.
     403       12608 :     Handle<WasmMemoryObject> memory_object(instance->memory_object(), isolate_);
     404       12607 :     WasmMemoryObject::AddInstance(isolate_, memory_object, instance);
     405             : 
     406       12610 :     if (!memory_.is_null()) {
     407             :       // Double-check the {memory} array buffer matches the instance.
     408             :       Handle<JSArrayBuffer> memory = memory_.ToHandleChecked();
     409       12598 :       CHECK_EQ(instance->memory_size(), memory->byte_length());
     410       12598 :       CHECK_EQ(instance->memory_start(), memory->backing_store());
     411             :     }
     412             :   }
     413             : 
     414             :   // The bulk memory proposal changes the MVP behavior here; the segments are
     415             :   // written as if `memory.init` and `table.init` are executed directly, and
     416             :   // not bounds checked ahead of time.
     417      134024 :   if (!enabled_.bulk_memory) {
     418             :     //--------------------------------------------------------------------------
     419             :     // Check that indirect function table segments are within bounds.
     420             :     //--------------------------------------------------------------------------
     421        4851 :     for (const WasmElemSegment& elem_segment : module_->elem_segments) {
     422         101 :       if (!elem_segment.active) continue;
     423             :       DCHECK_LT(elem_segment.table_index, table_count);
     424         101 :       uint32_t base = EvalUint32InitExpr(instance, elem_segment.offset);
     425             :       // Because of imported tables, {table_size} has to come from the table
     426             :       // object itself.
     427             :       auto table_object = handle(WasmTableObject::cast(instance->tables()->get(
     428         101 :                                      elem_segment.table_index)),
     429         202 :                                  isolate_);
     430         101 :       size_t table_size = table_object->elements()->length();
     431         202 :       if (!IsInBounds(base, elem_segment.entries.size(), table_size)) {
     432           0 :         thrower_->LinkError("table initializer is out of bounds");
     433           0 :         return {};
     434             :       }
     435             :     }
     436             : 
     437             :     //--------------------------------------------------------------------------
     438             :     // Check that memory segments are within bounds.
     439             :     //--------------------------------------------------------------------------
     440        4851 :     for (const WasmDataSegment& seg : module_->data_segments) {
     441           0 :       if (!seg.active) continue;
     442           0 :       uint32_t base = EvalUint32InitExpr(instance, seg.dest_addr);
     443           0 :       if (!IsInBounds(base, seg.source.length(), instance->memory_size())) {
     444           0 :         thrower_->LinkError("data segment is out of bounds");
     445           0 :         return {};
     446             :       }
     447             :     }
     448             :   }
     449             : 
     450             :   //--------------------------------------------------------------------------
     451             :   // Set up the exports object for the new instance.
     452             :   //--------------------------------------------------------------------------
     453      134024 :   ProcessExports(instance);
     454      134019 :   if (thrower_->error()) return {};
     455             : 
     456             :   //--------------------------------------------------------------------------
     457             :   // Initialize the indirect function tables.
     458             :   //--------------------------------------------------------------------------
     459      134019 :   if (table_count > 0) {
     460        2345 :     LoadTableSegments(instance);
     461        2345 :     if (thrower_->error()) return {};
     462             :   }
     463             : 
     464             :   //--------------------------------------------------------------------------
     465             :   // Initialize the memory by loading data segments.
     466             :   //--------------------------------------------------------------------------
     467      267798 :   if (module_->data_segments.size() > 0) {
     468         724 :     LoadDataSegments(instance);
     469         724 :     if (thrower_->error()) return {};
     470             :   }
     471             : 
     472             :   //--------------------------------------------------------------------------
     473             :   // Debugging support.
     474             :   //--------------------------------------------------------------------------
     475             :   // Set all breakpoints that were set on the shared module.
     476      133771 :   WasmModuleObject::SetBreakpointsOnNewInstance(module_object_, instance);
     477             : 
     478             :   //--------------------------------------------------------------------------
     479             :   // Create a wrapper for the start function.
     480             :   //--------------------------------------------------------------------------
     481      133770 :   if (module_->start_function_index >= 0) {
     482             :     int start_index = module_->start_function_index;
     483        5027 :     auto& function = module_->functions[start_index];
     484       10054 :     Handle<Code> wrapper_code = compiler::CompileJSToWasmWrapper(
     485        5027 :                                     isolate_, function.sig, function.imported)
     486        5027 :                                     .ToHandleChecked();
     487             :     // TODO(clemensh): Don't generate an exported function for the start
     488             :     // function. Use CWasmEntry instead.
     489             :     start_function_ = WasmExportedFunction::New(
     490             :         isolate_, instance, MaybeHandle<String>(), start_index,
     491        5027 :         static_cast<int>(function.sig->parameter_count()), wrapper_code);
     492             :   }
     493             : 
     494             :   DCHECK(!isolate_->has_pending_exception());
     495             :   TRACE("Successfully built instance for module %p\n",
     496             :         module_object_->native_module());
     497      133770 :   return instance;
     498             : }
     499             : 
     500      133770 : bool InstanceBuilder::ExecuteStartFunction() {
     501      401310 :   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"),
     502             :                "InstanceBuilder::ExecuteStartFunction");
     503      133770 :   if (start_function_.is_null()) return true;  // No start function.
     504             : 
     505        5027 :   HandleScope scope(isolate_);
     506             :   // Call the JS function.
     507        5027 :   Handle<Object> undefined = isolate_->factory()->undefined_value();
     508             :   MaybeHandle<Object> retval =
     509        5027 :       Execution::Call(isolate_, start_function_, undefined, 0, nullptr);
     510             : 
     511        5027 :   if (retval.is_null()) {
     512             :     DCHECK(isolate_->has_pending_exception());
     513             :     return false;
     514             :   }
     515        4959 :   return true;
     516             : }
     517             : 
     518             : // Look up an import value in the {ffi_} object.
     519      122873 : MaybeHandle<Object> InstanceBuilder::LookupImport(uint32_t index,
     520             :                                                   Handle<String> module_name,
     521             : 
     522             :                                                   Handle<String> import_name) {
     523             :   // We pre-validated in the js-api layer that the ffi object is present, and
     524             :   // a JSObject, if the module has imports.
     525             :   DCHECK(!ffi_.is_null());
     526             :   // Look up the module first.
     527             :   MaybeHandle<Object> result = Object::GetPropertyOrElement(
     528      122873 :       isolate_, ffi_.ToHandleChecked(), module_name);
     529      122874 :   if (result.is_null()) {
     530          24 :     return ReportTypeError("module not found", index, module_name);
     531             :   }
     532             : 
     533             :   Handle<Object> module = result.ToHandleChecked();
     534             : 
     535             :   // Look up the value in the module.
     536      122850 :   if (!module->IsJSReceiver()) {
     537             :     return ReportTypeError("module is not an object or function", index,
     538         360 :                            module_name);
     539             :   }
     540             : 
     541      122490 :   result = Object::GetPropertyOrElement(isolate_, module, import_name);
     542      122494 :   if (result.is_null()) {
     543           0 :     ReportLinkError("import not found", index, module_name, import_name);
     544           0 :     return MaybeHandle<JSFunction>();
     545             :   }
     546             : 
     547      122494 :   return result;
     548             : }
     549             : 
     550             : // Look up an import value in the {ffi_} object specifically for linking an
     551             : // asm.js module. This only performs non-observable lookups, which allows
     552             : // falling back to JavaScript proper (and hence re-executing all lookups) if
     553             : // module instantiation fails.
     554        4787 : MaybeHandle<Object> InstanceBuilder::LookupImportAsm(
     555             :     uint32_t index, Handle<String> import_name) {
     556             :   // Check that a foreign function interface object was provided.
     557        4787 :   if (ffi_.is_null()) {
     558           0 :     return ReportLinkError("missing imports object", index, import_name);
     559             :   }
     560             : 
     561             :   // Perform lookup of the given {import_name} without causing any observable
     562             :   // side-effect. We only accept accesses that resolve to data properties,
     563             :   // which is indicated by the asm.js spec in section 7 ("Linking") as well.
     564             :   Handle<Object> result;
     565             :   LookupIterator it = LookupIterator::PropertyOrElement(
     566        4787 :       isolate_, ffi_.ToHandleChecked(), import_name);
     567             :   switch (it.state()) {
     568             :     case LookupIterator::ACCESS_CHECK:
     569             :     case LookupIterator::INTEGER_INDEXED_EXOTIC:
     570             :     case LookupIterator::INTERCEPTOR:
     571             :     case LookupIterator::JSPROXY:
     572             :     case LookupIterator::ACCESSOR:
     573             :     case LookupIterator::TRANSITION:
     574          18 :       return ReportLinkError("not a data property", index, import_name);
     575             :     case LookupIterator::NOT_FOUND:
     576             :       // Accepting missing properties as undefined does not cause any
     577             :       // observable difference from JavaScript semantics, we are lenient.
     578          72 :       result = isolate_->factory()->undefined_value();
     579          72 :       break;
     580             :     case LookupIterator::DATA:
     581        4697 :       result = it.GetDataValue();
     582        4697 :       break;
     583             :   }
     584             : 
     585        4769 :   return result;
     586             : }
     587             : 
     588             : // Load data segments into the memory.
     589         724 : void InstanceBuilder::LoadDataSegments(Handle<WasmInstanceObject> instance) {
     590             :   Vector<const uint8_t> wire_bytes =
     591        1448 :       module_object_->native_module()->wire_bytes();
     592         724 :   for (const WasmDataSegment& segment : module_->data_segments) {
     593             :     uint32_t size = segment.source.length();
     594             : 
     595         964 :     if (enabled_.bulk_memory) {
     596             :       // Passive segments are not copied during instantiation.
     597         964 :       if (!segment.active) continue;
     598             : 
     599         916 :       uint32_t dest_offset = EvalUint32InitExpr(instance, segment.dest_addr);
     600         916 :       bool ok = ClampToBounds(dest_offset, &size,
     601             :                               static_cast<uint32_t>(instance->memory_size()));
     602             :       Address dest_addr =
     603         916 :           reinterpret_cast<Address>(instance->memory_start()) + dest_offset;
     604         916 :       Address src_addr = reinterpret_cast<Address>(wire_bytes.start()) +
     605         916 :                          segment.source.offset();
     606         916 :       memory_copy_wrapper(dest_addr, src_addr, size);
     607         916 :       if (!ok) {
     608         128 :         thrower_->LinkError("data segment is out of bounds");
     609             :         return;
     610             :       }
     611             :     } else {
     612             :       DCHECK(segment.active);
     613             :       // Segments of size == 0 are just nops.
     614           0 :       if (size == 0) continue;
     615             : 
     616           0 :       uint32_t dest_offset = EvalUint32InitExpr(instance, segment.dest_addr);
     617             :       DCHECK(IsInBounds(dest_offset, size, instance->memory_size()));
     618           0 :       byte* dest = instance->memory_start() + dest_offset;
     619           0 :       const byte* src = wire_bytes.start() + segment.source.offset();
     620           0 :       memcpy(dest, src, size);
     621             :     }
     622             :   }
     623             : }
     624             : 
     625        2219 : void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global, double num) {
     626             :   TRACE("init [globals_start=%p + %u] = %lf, type = %s\n",
     627             :         reinterpret_cast<void*>(raw_buffer_ptr(untagged_globals_, 0)),
     628             :         global.offset, num, ValueTypes::TypeName(global.type));
     629        2219 :   switch (global.type) {
     630             :     case kWasmI32:
     631        1807 :       WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global),
     632             :                                       DoubleToInt32(num));
     633             :       break;
     634             :     case kWasmI64:
     635             :       // The Wasm-BigInt proposal currently says that i64 globals may
     636             :       // only be initialized with BigInts. See:
     637             :       // https://github.com/WebAssembly/JS-BigInt-integration/issues/12
     638           0 :       UNREACHABLE();
     639             :       break;
     640             :     case kWasmF32:
     641          40 :       WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global),
     642             :                                     DoubleToFloat32(num));
     643             :       break;
     644             :     case kWasmF64:
     645         372 :       WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global), num);
     646             :       break;
     647             :     default:
     648           0 :       UNREACHABLE();
     649             :   }
     650        2219 : }
     651             : 
     652          24 : void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global, int64_t num) {
     653             :   TRACE("init [globals_start=%p + %u] = %" PRId64 ", type = %s\n",
     654             :         reinterpret_cast<void*>(raw_buffer_ptr(untagged_globals_, 0)),
     655             :         global.offset, num, ValueTypes::TypeName(global.type));
     656             :   DCHECK_EQ(kWasmI64, global.type);
     657          24 :   WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global), num);
     658          24 : }
     659             : 
     660          40 : void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global,
     661             :                                        Handle<WasmGlobalObject> value) {
     662             :   TRACE("init [globals_start=%p + %u] = ",
     663             :         reinterpret_cast<void*>(raw_buffer_ptr(untagged_globals_, 0)),
     664             :         global.offset);
     665          40 :   switch (global.type) {
     666             :     case kWasmI32: {
     667             :       int32_t num = value->GetI32();
     668          24 :       WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global), num);
     669             :       TRACE("%d", num);
     670             :       break;
     671             :     }
     672             :     case kWasmI64: {
     673             :       int64_t num = value->GetI64();
     674           8 :       WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global), num);
     675             :       TRACE("%" PRId64, num);
     676             :       break;
     677             :     }
     678             :     case kWasmF32: {
     679             :       float num = value->GetF32();
     680           8 :       WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global), num);
     681             :       TRACE("%f", num);
     682             :       break;
     683             :     }
     684             :     case kWasmF64: {
     685             :       double num = value->GetF64();
     686           0 :       WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global), num);
     687             :       TRACE("%lf", num);
     688             :       break;
     689             :     }
     690             :     default:
     691           0 :       UNREACHABLE();
     692             :   }
     693             :   TRACE(", type = %s (from WebAssembly.Global)\n",
     694             :         ValueTypes::TypeName(global.type));
     695          40 : }
     696             : 
     697           0 : void InstanceBuilder::WriteGlobalAnyRef(const WasmGlobal& global,
     698             :                                         Handle<Object> value) {
     699         320 :   tagged_globals_->set(global.offset, *value, UPDATE_WRITE_BARRIER);
     700           0 : }
     701             : 
     702      136400 : void InstanceBuilder::SanitizeImports() {
     703             :   Vector<const uint8_t> wire_bytes =
     704      272801 :       module_object_->native_module()->wire_bytes();
     705      654591 :   for (size_t index = 0; index < module_->import_table.size(); ++index) {
     706             :     const WasmImport& import = module_->import_table[index];
     707             : 
     708             :     Handle<String> module_name;
     709             :     MaybeHandle<String> maybe_module_name =
     710             :         WasmModuleObject::ExtractUtf8StringFromModuleBytes(isolate_, wire_bytes,
     711      127663 :                                                            import.module_name);
     712      127665 :     if (!maybe_module_name.ToHandle(&module_name)) {
     713           0 :       thrower_->LinkError("Could not resolve module name for import %zu",
     714           0 :                           index);
     715           0 :       return;
     716             :     }
     717             : 
     718             :     Handle<String> import_name;
     719             :     MaybeHandle<String> maybe_import_name =
     720             :         WasmModuleObject::ExtractUtf8StringFromModuleBytes(isolate_, wire_bytes,
     721      127665 :                                                            import.field_name);
     722      127662 :     if (!maybe_import_name.ToHandle(&import_name)) {
     723           0 :       thrower_->LinkError("Could not resolve import name for import %zu",
     724           0 :                           index);
     725           0 :       return;
     726             :     }
     727             : 
     728             :     int int_index = static_cast<int>(index);
     729             :     MaybeHandle<Object> result =
     730      127662 :         module_->origin == kAsmJsOrigin
     731        4787 :             ? LookupImportAsm(int_index, import_name)
     732      132449 :             : LookupImport(int_index, module_name, import_name);
     733      127665 :     if (thrower_->error()) {
     734         402 :       thrower_->LinkError("Could not find value for import %zu", index);
     735         402 :       return;
     736             :     }
     737             :     Handle<Object> value = result.ToHandleChecked();
     738      254526 :     sanitized_imports_.push_back({module_name, import_name, value});
     739             :   }
     740             : }
     741             : 
     742      134761 : MaybeHandle<JSArrayBuffer> InstanceBuilder::FindImportedMemoryBuffer() const {
     743             :   DCHECK_EQ(module_->import_table.size(), sanitized_imports_.size());
     744      627497 :   for (size_t index = 0; index < module_->import_table.size(); index++) {
     745             :     const WasmImport& import = module_->import_table[index];
     746             : 
     747      123198 :     if (import.kind == kExternalMemory) {
     748             :       const auto& value = sanitized_imports_[index].value;
     749        3873 :       if (!value->IsWasmMemoryObject()) {
     750         412 :         return {};
     751             :       }
     752             :       auto memory = Handle<WasmMemoryObject>::cast(value);
     753        3461 :       Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate_);
     754        3461 :       return buffer;
     755             :     }
     756             :   }
     757      130888 :   return {};
     758             : }
     759             : 
     760      118437 : bool InstanceBuilder::ProcessImportedFunction(
     761             :     Handle<WasmInstanceObject> instance, int import_index, int func_index,
     762             :     Handle<String> module_name, Handle<String> import_name,
     763             :     Handle<Object> value) {
     764             :   // Function imports must be callable.
     765      118437 :   if (!value->IsCallable()) {
     766         400 :     ReportLinkError("function import requires a callable", import_index,
     767         400 :                     module_name, import_name);
     768         400 :     return false;
     769             :   }
     770      118037 :   auto js_receiver = Handle<JSReceiver>::cast(value);
     771      236074 :   FunctionSig* expected_sig = module_->functions[func_index].sig;
     772      118037 :   auto kind = compiler::GetWasmImportCallKind(js_receiver, expected_sig,
     773      236074 :                                               enabled_.bigint);
     774      118037 :   switch (kind) {
     775             :     case compiler::WasmImportCallKind::kLinkError:
     776         152 :       ReportLinkError("imported function does not match the expected type",
     777         152 :                       import_index, module_name, import_name);
     778         152 :       return false;
     779             :     case compiler::WasmImportCallKind::kWasmToWasm: {
     780             :       // The imported function is a WASM function from another instance.
     781             :       auto imported_function = Handle<WasmExportedFunction>::cast(value);
     782             :       Handle<WasmInstanceObject> imported_instance(
     783      321192 :           imported_function->instance(), isolate_);
     784             :       // The import reference is the instance object itself.
     785      107064 :       Address imported_target = imported_function->GetWasmCallTarget();
     786             :       ImportedFunctionEntry entry(instance, func_index);
     787      107064 :       entry.SetWasmToWasm(*imported_instance, imported_target);
     788             :       break;
     789             :     }
     790             :     default: {
     791             :       // The imported function is a callable.
     792       10821 :       NativeModule* native_module = instance->module_object()->native_module();
     793             :       WasmCode* wasm_code = native_module->import_wrapper_cache()->GetOrCompile(
     794       21642 :           isolate_->wasm_engine(), isolate_->counters(), kind, expected_sig);
     795             :       ImportedFunctionEntry entry(instance, func_index);
     796       10821 :       if (wasm_code->kind() == WasmCode::kWasmToJsWrapper) {
     797             :         // Wasm to JS wrappers are treated specially in the import table.
     798       10597 :         entry.SetWasmToJs(isolate_, js_receiver, wasm_code);
     799             :       } else {
     800             :         // Wasm math intrinsics are compiled as regular Wasm functions.
     801             :         DCHECK(kind >= compiler::WasmImportCallKind::kFirstMathIntrinsic &&
     802             :                kind <= compiler::WasmImportCallKind::kLastMathIntrinsic);
     803         224 :         entry.SetWasmToWasm(*instance, wasm_code->instruction_start());
     804             :       }
     805             :       break;
     806             :     }
     807             :   }
     808             :   return true;
     809             : }
     810             : 
     811        1508 : bool InstanceBuilder::ProcessImportedTable(Handle<WasmInstanceObject> instance,
     812             :                                            int import_index, int table_index,
     813             :                                            Handle<String> module_name,
     814             :                                            Handle<String> import_name,
     815             :                                            Handle<Object> value) {
     816        1508 :   if (!value->IsWasmTableObject()) {
     817         336 :     ReportLinkError("table import requires a WebAssembly.Table", import_index,
     818         336 :                     module_name, import_name);
     819         336 :     return false;
     820             :   }
     821        1172 :   const WasmTable& table = module_->tables[table_index];
     822             : 
     823        1172 :   instance->tables()->set(table_index, *value);
     824             :   auto table_object = Handle<WasmTableObject>::cast(value);
     825             : 
     826             :   int imported_table_size = table_object->elements().length();
     827        1172 :   if (imported_table_size < static_cast<int>(table.initial_size)) {
     828          40 :     thrower_->LinkError("table import %d is smaller than initial %d, got %u",
     829          40 :                         import_index, table.initial_size, imported_table_size);
     830          40 :     return false;
     831             :   }
     832             : 
     833        1132 :   if (table.has_maximum_size) {
     834        1712 :     if (table_object->maximum_length()->IsUndefined(isolate_)) {
     835          16 :       thrower_->LinkError("table import %d has no maximum length, expected %d",
     836          32 :                           import_index, table.maximum_size);
     837          16 :       return false;
     838             :     }
     839         840 :     int64_t imported_maximum_size = table_object->maximum_length()->Number();
     840         840 :     if (imported_maximum_size < 0) {
     841           0 :       thrower_->LinkError("table import %d has no maximum length, expected %d",
     842           0 :                           import_index, table.maximum_size);
     843           0 :       return false;
     844             :     }
     845         840 :     if (imported_maximum_size > table.maximum_size) {
     846          48 :       thrower_->LinkError("table import %d has a larger maximum size %" PRIx64
     847             :                           " than the module's declared maximum %u",
     848             :                           import_index, imported_maximum_size,
     849          48 :                           table.maximum_size);
     850          48 :       return false;
     851             :     }
     852             :   }
     853             : 
     854             :   // Allocate a new dispatch table.
     855        1068 :   if (!instance->has_indirect_function_table()) {
     856        1044 :     WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
     857        1044 :         instance, imported_table_size);
     858             :   }
     859             :   // Initialize the dispatch table with the (foreign) JS functions
     860             :   // that are already in the table.
     861     4220044 :   for (int i = 0; i < imported_table_size; ++i) {
     862             :     bool is_valid;
     863             :     bool is_null;
     864     2109488 :     MaybeHandle<WasmInstanceObject> maybe_target_instance;
     865             :     int function_index;
     866     2109488 :     WasmTableObject::GetFunctionTableEntry(isolate_, table_object, i, &is_valid,
     867             :                                            &is_null, &maybe_target_instance,
     868     2109488 :                                            &function_index);
     869     2109488 :     if (!is_valid) {
     870           0 :       thrower_->LinkError("table import %d[%d] is not a wasm function",
     871           0 :                           import_index, i);
     872           0 :       return false;
     873             :     }
     874     4216316 :     if (is_null) continue;
     875             : 
     876             :     Handle<WasmInstanceObject> target_instance =
     877             :         maybe_target_instance.ToHandleChecked();
     878        5320 :     FunctionSig* sig = target_instance->module_object()
     879             :                            ->module()
     880        2660 :                            ->functions[function_index]
     881        2660 :                            .sig;
     882             : 
     883             :     // Look up the signature's canonical id. If there is no canonical
     884             :     // id, then the signature does not appear at all in this module,
     885             :     // so putting {-1} in the table will cause checks to always fail.
     886             :     IndirectFunctionTableEntry(instance, i)
     887        5320 :         .Set(module_->signature_map.Find(*sig), target_instance,
     888        5320 :              function_index);
     889             :   }
     890             :   return true;
     891             : }
     892             : 
     893        3864 : bool InstanceBuilder::ProcessImportedMemory(Handle<WasmInstanceObject> instance,
     894             :                                             int import_index,
     895             :                                             Handle<String> module_name,
     896             :                                             Handle<String> import_name,
     897             :                                             Handle<Object> value) {
     898             :   // Validation should have failed if more than one memory object was
     899             :   // provided.
     900             :   DCHECK(!instance->has_memory_object());
     901        3864 :   if (!value->IsWasmMemoryObject()) {
     902         404 :     ReportLinkError("memory import must be a WebAssembly.Memory object",
     903         404 :                     import_index, module_name, import_name);
     904         404 :     return false;
     905             :   }
     906             :   auto memory = Handle<WasmMemoryObject>::cast(value);
     907        3460 :   instance->set_memory_object(*memory);
     908        3459 :   Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate_);
     909             :   // memory_ should have already been assigned in Build().
     910             :   DCHECK_EQ(*memory_.ToHandleChecked(), *buffer);
     911             :   uint32_t imported_cur_pages =
     912        3461 :       static_cast<uint32_t>(buffer->byte_length() / kWasmPageSize);
     913        3461 :   if (imported_cur_pages < module_->initial_pages) {
     914          24 :     thrower_->LinkError("memory import %d is smaller than initial %u, got %u",
     915             :                         import_index, module_->initial_pages,
     916          24 :                         imported_cur_pages);
     917          24 :     return false;
     918             :   }
     919             :   int32_t imported_maximum_pages = memory->maximum_pages();
     920        3437 :   if (module_->has_maximum_pages) {
     921        1452 :     if (imported_maximum_pages < 0) {
     922           8 :       thrower_->LinkError(
     923             :           "memory import %d has no maximum limit, expected at most %u",
     924           8 :           import_index, imported_maximum_pages);
     925           8 :       return false;
     926             :     }
     927        1444 :     if (static_cast<uint32_t>(imported_maximum_pages) >
     928        1444 :         module_->maximum_pages) {
     929          40 :       thrower_->LinkError(
     930             :           "memory import %d has a larger maximum size %u than the "
     931             :           "module's declared maximum %u",
     932          40 :           import_index, imported_maximum_pages, module_->maximum_pages);
     933          40 :       return false;
     934             :     }
     935             :   }
     936        6778 :   if (module_->has_shared_memory != buffer->is_shared()) {
     937          16 :     thrower_->LinkError(
     938             :         "mismatch in shared state of memory, declared = %d, imported = %d",
     939          16 :         module_->has_shared_memory, buffer->is_shared());
     940          16 :     return false;
     941             :   }
     942             : 
     943             :   return true;
     944             : }
     945             : 
     946         436 : bool InstanceBuilder::ProcessImportedWasmGlobalObject(
     947             :     Handle<WasmInstanceObject> instance, int import_index,
     948             :     Handle<String> module_name, Handle<String> import_name,
     949             :     const WasmGlobal& global, Handle<WasmGlobalObject> global_object) {
     950         436 :   if (global_object->type() != global.type) {
     951           8 :     ReportLinkError("imported global does not match the expected type",
     952           8 :                     import_index, module_name, import_name);
     953           8 :     return false;
     954             :   }
     955         428 :   if (global_object->is_mutable() != global.mutability) {
     956          24 :     ReportLinkError("imported global does not match the expected mutability",
     957          24 :                     import_index, module_name, import_name);
     958          24 :     return false;
     959             :   }
     960         404 :   if (global.mutability) {
     961             :     DCHECK_LT(global.index, module_->num_imported_mutable_globals);
     962             :     Handle<Object> buffer;
     963             :     Address address_or_offset;
     964         364 :     if (ValueTypes::IsReferenceType(global.type)) {
     965             :       static_assert(sizeof(global_object->offset()) <= sizeof(Address),
     966             :                     "The offset into the globals buffer does not fit into "
     967             :                     "the imported_mutable_globals array");
     968         224 :       buffer = handle(global_object->tagged_buffer(), isolate_);
     969             :       // For anyref globals we use a relative offset, not an absolute address.
     970         224 :       address_or_offset = static_cast<Address>(global_object->offset());
     971             :     } else {
     972         140 :       buffer = handle(global_object->untagged_buffer(), isolate_);
     973             :       // It is safe in this case to store the raw pointer to the buffer
     974             :       // since the backing store of the JSArrayBuffer will not be
     975             :       // relocated.
     976             :       address_or_offset = reinterpret_cast<Address>(raw_buffer_ptr(
     977         140 :           Handle<JSArrayBuffer>::cast(buffer), global_object->offset()));
     978             :     }
     979         728 :     instance->imported_mutable_globals_buffers()->set(global.index, *buffer);
     980         364 :     instance->imported_mutable_globals()[global.index] = address_or_offset;
     981             :     return true;
     982             :   }
     983             : 
     984          40 :   WriteGlobalValue(global, global_object);
     985          40 :   return true;
     986             : }
     987             : 
     988        3244 : bool InstanceBuilder::ProcessImportedGlobal(Handle<WasmInstanceObject> instance,
     989             :                                             int import_index, int global_index,
     990             :                                             Handle<String> module_name,
     991             :                                             Handle<String> import_name,
     992             :                                             Handle<Object> value) {
     993             :   // Immutable global imports are converted to numbers and written into
     994             :   // the {untagged_globals_} array buffer.
     995             :   //
     996             :   // Mutable global imports instead have their backing array buffers
     997             :   // referenced by this instance, and store the address of the imported
     998             :   // global in the {imported_mutable_globals_} array.
     999        3244 :   const WasmGlobal& global = module_->globals[global_index];
    1000             : 
    1001             :   // The mutable-global proposal allows importing i64 values, but only if
    1002             :   // they are passed as a WebAssembly.Global object.
    1003             :   //
    1004             :   // However, the bigint proposal allows importing constant i64 values,
    1005             :   // as non WebAssembly.Global object.
    1006        3292 :   if (global.type == kWasmI64 && !enabled_.bigint &&
    1007             :       !value->IsWasmGlobalObject()) {
    1008          32 :     ReportLinkError("global import cannot have type i64", import_index,
    1009          32 :                     module_name, import_name);
    1010          32 :     return false;
    1011             :   }
    1012        3212 :   if (module_->origin == kAsmJsOrigin) {
    1013             :     // Accepting {JSFunction} on top of just primitive values here is a
    1014             :     // workaround to support legacy asm.js code with broken binding. Note
    1015             :     // that using {NaN} (or Smi::kZero) here is what using the observable
    1016             :     // conversion via {ToPrimitive} would produce as well.
    1017             :     // TODO(mstarzinger): Still observable if Function.prototype.valueOf
    1018             :     // or friends are patched, we might need to check for that as well.
    1019        1208 :     if (value->IsJSFunction()) value = isolate_->factory()->nan_value();
    1020        2407 :     if (value->IsPrimitive() && !value->IsSymbol()) {
    1021        1195 :       if (global.type == kWasmI32) {
    1022         855 :         value = Object::ToInt32(isolate_, value).ToHandleChecked();
    1023             :       } else {
    1024         680 :         value = Object::ToNumber(isolate_, value).ToHandleChecked();
    1025             :       }
    1026             :     }
    1027             :   }
    1028             : 
    1029        3212 :   if (value->IsWasmGlobalObject()) {
    1030         436 :     auto global_object = Handle<WasmGlobalObject>::cast(value);
    1031             :     return ProcessImportedWasmGlobalObject(instance, import_index, module_name,
    1032         436 :                                            import_name, global, global_object);
    1033             :   }
    1034             : 
    1035        2776 :   if (global.mutability) {
    1036          16 :     ReportLinkError(
    1037             :         "imported mutable global must be a WebAssembly.Global object",
    1038          16 :         import_index, module_name, import_name);
    1039          16 :     return false;
    1040             :   }
    1041             : 
    1042        5520 :   if (ValueTypes::IsReferenceType(global.type)) {
    1043             :     // There shouldn't be any null-ref globals.
    1044             :     DCHECK_NE(ValueType::kWasmNullRef, global.type);
    1045         176 :     if (global.type == ValueType::kWasmAnyFunc) {
    1046         128 :       if (!value->IsNull(isolate_) &&
    1047          32 :           !WasmExportedFunction::IsWasmExportedFunction(*value)) {
    1048          16 :         ReportLinkError(
    1049             :             "imported anyfunc global must be null or an exported function",
    1050          16 :             import_index, module_name, import_name);
    1051          16 :         return false;
    1052             :       }
    1053             :     }
    1054             :     WriteGlobalAnyRef(global, value);
    1055         160 :     return true;
    1056             :   }
    1057             : 
    1058        2584 :   if (value->IsNumber() && global.type != kWasmI64) {
    1059        2219 :     WriteGlobalValue(global, value->Number());
    1060        2219 :     return true;
    1061             :   }
    1062             : 
    1063         365 :   if (enabled_.bigint && global.type == kWasmI64) {
    1064             :     Handle<BigInt> bigint;
    1065             : 
    1066          48 :     if (!BigInt::FromObject(isolate_, value).ToHandle(&bigint)) {
    1067             :       return false;
    1068             :     }
    1069          24 :     WriteGlobalValue(global, bigint->AsInt64());
    1070          24 :     return true;
    1071             :   }
    1072             : 
    1073         341 :   ReportLinkError("global import must be a number or WebAssembly.Global object",
    1074         341 :                   import_index, module_name, import_name);
    1075         341 :   return false;
    1076             : }
    1077             : 
    1078             : // Process the imports, including functions, tables, globals, and memory, in
    1079             : // order, loading them from the {ffi_} object. Returns the number of imported
    1080             : // functions.
    1081      135982 : int InstanceBuilder::ProcessImports(Handle<WasmInstanceObject> instance) {
    1082             :   int num_imported_functions = 0;
    1083             :   int num_imported_tables = 0;
    1084             : 
    1085             :   DCHECK_EQ(module_->import_table.size(), sanitized_imports_.size());
    1086      271964 :   int num_imports = static_cast<int>(module_->import_table.size());
    1087      386342 :   for (int index = 0; index < num_imports; ++index) {
    1088      127138 :     const WasmImport& import = module_->import_table[index];
    1089             : 
    1090      127138 :     Handle<String> module_name = sanitized_imports_[index].module_name;
    1091      127138 :     Handle<String> import_name = sanitized_imports_[index].import_name;
    1092      127138 :     Handle<Object> value = sanitized_imports_[index].value;
    1093             : 
    1094      127138 :     switch (import.kind) {
    1095             :       case kExternalFunction: {
    1096      118437 :         uint32_t func_index = import.index;
    1097             :         DCHECK_EQ(num_imported_functions, func_index);
    1098      118437 :         if (!ProcessImportedFunction(instance, index, func_index, module_name,
    1099             :                                      import_name, value)) {
    1100        1961 :           return -1;
    1101             :         }
    1102      117885 :         num_imported_functions++;
    1103      117885 :         break;
    1104             :       }
    1105             :       case kExternalTable: {
    1106        1508 :         uint32_t table_index = import.index;
    1107             :         DCHECK_EQ(table_index, num_imported_tables);
    1108        1508 :         if (!ProcessImportedTable(instance, index, table_index, module_name,
    1109             :                                   import_name, value)) {
    1110             :           return -1;
    1111             :         }
    1112             :         num_imported_tables++;
    1113             :         break;
    1114             :       }
    1115             :       case kExternalMemory: {
    1116        3861 :         if (!ProcessImportedMemory(instance, index, module_name, import_name,
    1117             :                                    value)) {
    1118             :           return -1;
    1119             :         }
    1120             :         break;
    1121             :       }
    1122             :       case kExternalGlobal: {
    1123        3244 :         if (!ProcessImportedGlobal(instance, index, import.index, module_name,
    1124             :                                    import_name, value)) {
    1125             :           return -1;
    1126             :         }
    1127             :         break;
    1128             :       }
    1129             :       case kExternalException: {
    1130          88 :         if (!value->IsWasmExceptionObject()) {
    1131          32 :           ReportLinkError("exception import requires a WebAssembly.Exception",
    1132          32 :                           index, module_name, import_name);
    1133          32 :           return -1;
    1134             :         }
    1135             :         Handle<WasmExceptionObject> imported_exception =
    1136             :             Handle<WasmExceptionObject>::cast(value);
    1137          56 :         if (!imported_exception->IsSignatureEqual(
    1138         112 :                 module_->exceptions[import.index].sig)) {
    1139           8 :           ReportLinkError("imported exception does not match the expected type",
    1140           8 :                           index, module_name, import_name);
    1141           8 :           return -1;
    1142             :         }
    1143          48 :         Object exception_tag = imported_exception->exception_tag();
    1144             :         DCHECK(instance->exceptions_table()->get(import.index)->IsUndefined());
    1145          96 :         instance->exceptions_table()->set(import.index, exception_tag);
    1146          96 :         exception_wrappers_[import.index] = imported_exception;
    1147          48 :         break;
    1148             :       }
    1149             :       default:
    1150           0 :         UNREACHABLE();
    1151             :         break;
    1152             :     }
    1153             :   }
    1154             :   return num_imported_functions;
    1155             : }
    1156             : 
    1157             : template <typename T>
    1158        8158 : T* InstanceBuilder::GetRawGlobalPtr(const WasmGlobal& global) {
    1159       16316 :   return reinterpret_cast<T*>(raw_buffer_ptr(untagged_globals_, global.offset));
    1160             : }
    1161             : 
    1162             : // Process initialization of globals.
    1163      134023 : void InstanceBuilder::InitGlobals() {
    1164      134023 :   for (auto global : module_->globals) {
    1165        9214 :     if (global.mutability && global.imported) {
    1166             :       continue;
    1167             :     }
    1168             : 
    1169        8850 :     switch (global.init.kind) {
    1170             :       case WasmInitExpr::kI32Const:
    1171        4745 :         WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global),
    1172             :                                         global.init.val.i32_const);
    1173             :         break;
    1174             :       case WasmInitExpr::kI64Const:
    1175          88 :         WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global),
    1176             :                                         global.init.val.i64_const);
    1177             :         break;
    1178             :       case WasmInitExpr::kF32Const:
    1179         188 :         WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global),
    1180             :                                       global.init.val.f32_const);
    1181             :         break;
    1182             :       case WasmInitExpr::kF64Const:
    1183         854 :         WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global),
    1184             :                                        global.init.val.f64_const);
    1185             :         break;
    1186             :       case WasmInitExpr::kRefNullConst:
    1187             :         DCHECK(enabled_.anyref || enabled_.eh);
    1188         464 :         if (global.imported) break;  // We already initialized imported globals.
    1189             : 
    1190        1392 :         tagged_globals_->set(global.offset,
    1191        1392 :                              ReadOnlyRoots(isolate_).null_value(),
    1192         464 :                              SKIP_WRITE_BARRIER);
    1193         464 :         break;
    1194             :       case WasmInitExpr::kGlobalIndex: {
    1195             :         // Initialize with another global.
    1196             :         uint32_t new_offset = global.offset;
    1197             :         uint32_t old_offset =
    1198         136 :             module_->globals[global.init.val.global_index].offset;
    1199             :         TRACE("init [globals+%u] = [globals+%d]\n", global.offset, old_offset);
    1200          68 :         if (ValueTypes::IsReferenceType(global.type)) {
    1201             :           DCHECK(enabled_.anyref || enabled_.eh);
    1202          48 :           tagged_globals_->set(new_offset, tagged_globals_->get(old_offset));
    1203             :         } else {
    1204          52 :           size_t size = (global.type == kWasmI64 || global.type == kWasmF64)
    1205             :                             ? sizeof(double)
    1206          52 :                             : sizeof(int32_t);
    1207          52 :           memcpy(raw_buffer_ptr(untagged_globals_, new_offset),
    1208          52 :                  raw_buffer_ptr(untagged_globals_, old_offset), size);
    1209             :         }
    1210             :         break;
    1211             :       }
    1212             :       case WasmInitExpr::kNone:
    1213             :         // Happens with imported globals.
    1214             :         break;
    1215             :       default:
    1216           0 :         UNREACHABLE();
    1217             :         break;
    1218             :     }
    1219             :   }
    1220      134023 : }
    1221             : 
    1222             : // Allocate memory for a module instance as a new JSArrayBuffer.
    1223      131238 : Handle<JSArrayBuffer> InstanceBuilder::AllocateMemory(uint32_t initial_pages,
    1224             :                                                       uint32_t maximum_pages) {
    1225      131238 :   if (initial_pages > max_mem_pages()) {
    1226          16 :     thrower_->RangeError("Out of memory: wasm memory too large");
    1227             :     return Handle<JSArrayBuffer>::null();
    1228             :   }
    1229      131222 :   const bool is_shared_memory = module_->has_shared_memory && enabled_.threads;
    1230             :   Handle<JSArrayBuffer> mem_buffer;
    1231      131222 :   if (is_shared_memory) {
    1232         512 :     if (!NewSharedArrayBuffer(isolate_, initial_pages * kWasmPageSize,
    1233         256 :                               maximum_pages * kWasmPageSize)
    1234             :              .ToHandle(&mem_buffer)) {
    1235           0 :       thrower_->RangeError("Out of memory: wasm shared memory");
    1236             :     }
    1237             :   } else {
    1238      261932 :     if (!NewArrayBuffer(isolate_, initial_pages * kWasmPageSize)
    1239             :              .ToHandle(&mem_buffer)) {
    1240           0 :       thrower_->RangeError("Out of memory: wasm memory");
    1241             :     }
    1242             :   }
    1243      131222 :   return mem_buffer;
    1244             : }
    1245             : 
    1246           0 : bool InstanceBuilder::NeedsWrappers() const {
    1247      134023 :   if (module_->num_exported_functions > 0) return true;
    1248        4556 :   for (auto& table : module_->tables) {
    1249         900 :     if (table.type == kWasmAnyFunc) return true;
    1250             :   }
    1251             :   return false;
    1252             : }
    1253             : 
    1254             : // Process the exports, creating wrappers for functions, tables, memories,
    1255             : // globals, and exceptions.
    1256      134021 : void InstanceBuilder::ProcessExports(Handle<WasmInstanceObject> instance) {
    1257             :   Handle<FixedArray> export_wrappers(module_object_->export_wrappers(),
    1258      134021 :                                      isolate_);
    1259      134023 :   if (NeedsWrappers()) {
    1260             :     // If an imported WebAssembly function gets exported, the exported function
    1261             :     // has to be identical to to imported function. Therefore we cache all
    1262             :     // imported WebAssembly functions in the instance.
    1263      254709 :     for (int index = 0, end = static_cast<int>(module_->import_table.size());
    1264      254709 :          index < end; ++index) {
    1265      124340 :       const WasmImport& import = module_->import_table[index];
    1266      124340 :       if (import.kind == kExternalFunction) {
    1267      117605 :         Handle<Object> value = sanitized_imports_[index].value;
    1268      117605 :         if (WasmExportedFunction::IsWasmExportedFunction(*value)) {
    1269      107024 :           WasmInstanceObject::SetWasmExportedFunction(
    1270      107024 :               isolate_, instance, import.index,
    1271      107024 :               Handle<WasmExportedFunction>::cast(value));
    1272             :         }
    1273             :       }
    1274             :     }
    1275             :   }
    1276             : 
    1277             :   Handle<JSObject> exports_object;
    1278             :   bool is_asm_js = false;
    1279      134024 :   switch (module_->origin) {
    1280             :     case kWasmOrigin: {
    1281             :       // Create the "exports" object.
    1282      129173 :       exports_object = isolate_->factory()->NewJSObjectWithNullProto();
    1283      129172 :       break;
    1284             :     }
    1285             :     case kAsmJsOrigin: {
    1286             :       Handle<JSFunction> object_function = Handle<JSFunction>(
    1287       14553 :           isolate_->native_context()->object_function(), isolate_);
    1288        4851 :       exports_object = isolate_->factory()->NewJSObject(object_function);
    1289             :       is_asm_js = true;
    1290             :       break;
    1291             :     }
    1292             :     default:
    1293           0 :       UNREACHABLE();
    1294             :   }
    1295      134023 :   instance->set_exports_object(*exports_object);
    1296             : 
    1297             :   Handle<String> single_function_name =
    1298      134021 :       isolate_->factory()->InternalizeUtf8String(AsmJs::kSingleFunctionName);
    1299             : 
    1300             :   PropertyDescriptor desc;
    1301             :   desc.set_writable(is_asm_js);
    1302             :   desc.set_enumerable(true);
    1303             :   desc.set_configurable(is_asm_js);
    1304             : 
    1305             :   // Process each export in the export table.
    1306             :   int export_index = 0;  // Index into {export_wrappers}.
    1307      134026 :   for (const WasmExport& exp : module_->export_table) {
    1308      459203 :     Handle<String> name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
    1309      229603 :                               isolate_, module_object_, exp.name)
    1310             :                               .ToHandleChecked();
    1311             :     Handle<JSObject> export_to;
    1312      237846 :     if (is_asm_js && exp.kind == kExternalFunction &&
    1313        8246 :         String::Equals(isolate_, name, single_function_name)) {
    1314             :       export_to = instance;
    1315             :     } else {
    1316             :       export_to = exports_object;
    1317             :     }
    1318             : 
    1319      229600 :     switch (exp.kind) {
    1320             :       case kExternalFunction: {
    1321             :         // Wrap and export the code as a JSFunction.
    1322             :         // TODO(wasm): reduce duplication with LoadElemSegment() further below
    1323      226472 :         const WasmFunction& function = module_->functions[exp.index];
    1324             :         MaybeHandle<WasmExportedFunction> wasm_exported_function =
    1325             :             WasmInstanceObject::GetWasmExportedFunction(isolate_, instance,
    1326      226472 :                                                         exp.index);
    1327      226474 :         if (wasm_exported_function.is_null()) {
    1328             :           // Wrap the exported code as a JSFunction.
    1329             :           Handle<Code> export_code =
    1330      452420 :               export_wrappers->GetValueChecked<Code>(isolate_, export_index);
    1331      226207 :           MaybeHandle<String> func_name;
    1332      226207 :           if (is_asm_js) {
    1333             :             // For modules arising from asm.js, honor the names section.
    1334        8226 :             WireBytesRef func_name_ref = module_->LookupFunctionName(
    1335             :                 ModuleWireBytes(module_object_->native_module()->wire_bytes()),
    1336       24678 :                 function.func_index);
    1337       16452 :             func_name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
    1338        8226 :                             isolate_, module_object_, func_name_ref)
    1339        8226 :                             .ToHandleChecked();
    1340             :           }
    1341             :           wasm_exported_function = WasmExportedFunction::New(
    1342      226207 :               isolate_, instance, func_name, function.func_index,
    1343      452414 :               static_cast<int>(function.sig->parameter_count()), export_code);
    1344      226210 :           WasmInstanceObject::SetWasmExportedFunction(
    1345      226210 :               isolate_, instance, exp.index,
    1346      226210 :               wasm_exported_function.ToHandleChecked());
    1347             :         }
    1348             :         desc.set_value(wasm_exported_function.ToHandleChecked());
    1349      226477 :         export_index++;
    1350             :         break;
    1351             :       }
    1352             :       case kExternalTable: {
    1353         540 :         desc.set_value(handle(instance->tables()->get(exp.index), isolate_));
    1354         540 :         break;
    1355             :       }
    1356             :       case kExternalMemory: {
    1357             :         // Export the memory as a WebAssembly.Memory object. A WasmMemoryObject
    1358             :         // should already be available if the module has memory, since we always
    1359             :         // create or import it when building an WasmInstanceObject.
    1360             :         DCHECK(instance->has_memory_object());
    1361        1640 :         desc.set_value(
    1362             :             Handle<WasmMemoryObject>(instance->memory_object(), isolate_));
    1363        1640 :         break;
    1364             :       }
    1365             :       case kExternalGlobal: {
    1366         836 :         const WasmGlobal& global = module_->globals[exp.index];
    1367             :         Handle<JSArrayBuffer> untagged_buffer;
    1368             :         Handle<FixedArray> tagged_buffer;
    1369             :         uint32_t offset;
    1370             : 
    1371         836 :         if (global.mutability && global.imported) {
    1372             :           Handle<FixedArray> buffers_array(
    1373         148 :               instance->imported_mutable_globals_buffers(), isolate_);
    1374         296 :           if (ValueTypes::IsReferenceType(global.type)) {
    1375             :             tagged_buffer = buffers_array->GetValueChecked<FixedArray>(
    1376         192 :                 isolate_, global.index);
    1377             :             // For anyref globals we store the relative offset in the
    1378             :             // imported_mutable_globals array instead of an absolute address.
    1379          96 :             Address addr = instance->imported_mutable_globals()[global.index];
    1380             :             DCHECK_LE(addr, static_cast<Address>(
    1381             :                                 std::numeric_limits<uint32_t>::max()));
    1382          96 :             offset = static_cast<uint32_t>(addr);
    1383             :           } else {
    1384             :             untagged_buffer = buffers_array->GetValueChecked<JSArrayBuffer>(
    1385         104 :                 isolate_, global.index);
    1386             :             Address global_addr =
    1387          52 :                 instance->imported_mutable_globals()[global.index];
    1388             : 
    1389             :             size_t buffer_size = untagged_buffer->byte_length();
    1390             :             Address backing_store =
    1391          52 :                 reinterpret_cast<Address>(untagged_buffer->backing_store());
    1392          52 :             CHECK(global_addr >= backing_store &&
    1393             :                   global_addr < backing_store + buffer_size);
    1394          52 :             offset = static_cast<uint32_t>(global_addr - backing_store);
    1395             :           }
    1396             :         } else {
    1397        1376 :           if (ValueTypes::IsReferenceType(global.type)) {
    1398         208 :             tagged_buffer = handle(instance->tagged_globals_buffer(), isolate_);
    1399             :           } else {
    1400             :             untagged_buffer =
    1401         480 :                 handle(instance->untagged_globals_buffer(), isolate_);
    1402             :           }
    1403         688 :           offset = global.offset;
    1404             :         }
    1405             : 
    1406             :         // Since the global's array untagged_buffer is always provided,
    1407             :         // allocation should never fail.
    1408             :         Handle<WasmGlobalObject> global_obj =
    1409        1672 :             WasmGlobalObject::New(isolate_, untagged_buffer, tagged_buffer,
    1410        2508 :                                   global.type, offset, global.mutability)
    1411             :                 .ToHandleChecked();
    1412             :         desc.set_value(global_obj);
    1413             :         break;
    1414             :       }
    1415             :       case kExternalException: {
    1416         112 :         const WasmException& exception = module_->exceptions[exp.index];
    1417         112 :         Handle<WasmExceptionObject> wrapper = exception_wrappers_[exp.index];
    1418         112 :         if (wrapper.is_null()) {
    1419             :           Handle<HeapObject> exception_tag(
    1420             :               HeapObject::cast(instance->exceptions_table()->get(exp.index)),
    1421          96 :               isolate_);
    1422             :           wrapper =
    1423          96 :               WasmExceptionObject::New(isolate_, exception.sig, exception_tag);
    1424         192 :           exception_wrappers_[exp.index] = wrapper;
    1425             :         }
    1426             :         desc.set_value(wrapper);
    1427             :         break;
    1428             :       }
    1429             :       default:
    1430           0 :         UNREACHABLE();
    1431             :         break;
    1432             :     }
    1433             : 
    1434             :     v8::Maybe<bool> status = JSReceiver::DefineOwnProperty(
    1435      229605 :         isolate_, export_to, name, &desc, Just(kThrowOnError));
    1436      229599 :     if (!status.IsJust()) {
    1437             :       DisallowHeapAllocation no_gc;
    1438           0 :       TruncatedUserString<> trunc_name(name->GetCharVector<uint8_t>(no_gc));
    1439           0 :       thrower_->LinkError("export of %.*s failed.", trunc_name.length(),
    1440           0 :                           trunc_name.start());
    1441             :       return;
    1442             :     }
    1443             :   }
    1444             :   DCHECK_EQ(export_index, export_wrappers->length());
    1445             : 
    1446      134022 :   if (module_->origin == kWasmOrigin) {
    1447             :     v8::Maybe<bool> success =
    1448      129171 :         JSReceiver::SetIntegrityLevel(exports_object, FROZEN, kDontThrow);
    1449             :     DCHECK(success.FromMaybe(false));
    1450             :     USE(success);
    1451             :   }
    1452             : }
    1453             : 
    1454        2345 : void InstanceBuilder::InitializeTables(Handle<WasmInstanceObject> instance) {
    1455        2345 :   size_t table_count = module_->tables.size();
    1456        7211 :   for (size_t index = 0; index < table_count; ++index) {
    1457        2433 :     const WasmTable& table = module_->tables[index];
    1458             : 
    1459        3746 :     if (!instance->has_indirect_function_table() &&
    1460        1313 :         table.type == kWasmAnyFunc) {
    1461             :       WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
    1462        1313 :           instance, table.initial_size);
    1463             :     }
    1464             :   }
    1465        2345 : }
    1466             : 
    1467        2445 : bool LoadElemSegmentImpl(Isolate* isolate, Handle<WasmInstanceObject> instance,
    1468             :                          Handle<WasmTableObject> table_object,
    1469             :                          const WasmElemSegment& elem_segment, uint32_t dst,
    1470             :                          uint32_t src, size_t count) {
    1471             :   // TODO(wasm): Move this functionality into wasm-objects, since it is used
    1472             :   // for both instantiation and in the implementation of the table.init
    1473             :   // instruction.
    1474             :   bool ok =
    1475        2445 :       ClampToBounds<size_t>(dst, &count, table_object->elements()->length());
    1476             :   // Use & instead of && so the clamp is not short-circuited.
    1477        2445 :   ok &= ClampToBounds<size_t>(src, &count, elem_segment.entries.size());
    1478             : 
    1479        2445 :   const WasmModule* module = instance->module();
    1480       22727 :   for (size_t i = 0; i < count; ++i) {
    1481       20282 :     uint32_t func_index = elem_segment.entries[src + i];
    1482       10141 :     int entry_index = static_cast<int>(dst + i);
    1483             : 
    1484       10141 :     if (func_index == WasmElemSegment::kNullIndex) {
    1485           0 :       IndirectFunctionTableEntry(instance, entry_index).clear();
    1486           0 :       WasmTableObject::Set(isolate, table_object, entry_index,
    1487           0 :                            isolate->factory()->null_value());
    1488             :       continue;
    1489             :     }
    1490             : 
    1491       10141 :     const WasmFunction* function = &module->functions[func_index];
    1492             : 
    1493             :     // Update the local dispatch table first.
    1494       20282 :     uint32_t sig_id = module->signature_ids[function->sig_index];
    1495             :     IndirectFunctionTableEntry(instance, entry_index)
    1496       20282 :         .Set(sig_id, instance, func_index);
    1497             : 
    1498             :     // Update the table object's other dispatch tables.
    1499             :     MaybeHandle<WasmExportedFunction> wasm_exported_function =
    1500             :         WasmInstanceObject::GetWasmExportedFunction(isolate, instance,
    1501       10141 :                                                     func_index);
    1502       10141 :     if (wasm_exported_function.is_null()) {
    1503             :       // No JSFunction entry yet exists for this function. Create a {Tuple2}
    1504             :       // holding the information to lazily allocate one.
    1505             :       WasmTableObject::SetFunctionTablePlaceholder(
    1506        9489 :           isolate, table_object, entry_index, instance, func_index);
    1507             :     } else {
    1508        1956 :       table_object->elements()->set(entry_index,
    1509         652 :                                     *wasm_exported_function.ToHandleChecked());
    1510             :     }
    1511             :     // UpdateDispatchTables() updates all other dispatch tables, since
    1512             :     // we have not yet added the dispatch table we are currently building.
    1513             :     WasmTableObject::UpdateDispatchTables(isolate, table_object, entry_index,
    1514       10141 :                                           function->sig, instance, func_index);
    1515             :   }
    1516        2445 :   return ok;
    1517             : }
    1518             : 
    1519        2345 : void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
    1520        2345 :   for (auto& elem_segment : module_->elem_segments) {
    1521             :     // Passive segments are not copied during instantiation.
    1522        2125 :     if (!elem_segment.active) continue;
    1523             : 
    1524        2109 :     uint32_t dst = EvalUint32InitExpr(instance, elem_segment.offset);
    1525             :     uint32_t src = 0;
    1526             :     size_t count = elem_segment.entries.size();
    1527             : 
    1528        6327 :     bool success = LoadElemSegmentImpl(
    1529             :         isolate_, instance,
    1530             :         handle(WasmTableObject::cast(
    1531        2109 :                    instance->tables()->get(elem_segment.table_index)),
    1532             :                isolate_),
    1533        2109 :         elem_segment, dst, src, count);
    1534        2109 :     if (enabled_.bulk_memory) {
    1535        2008 :       if (!success) {
    1536         120 :         thrower_->LinkError("table initializer is out of bounds");
    1537             :         // Break out instead of returning; we don't want to continue to
    1538             :         // initialize any further element segments, but still need to add
    1539             :         // dispatch tables below.
    1540         120 :         break;
    1541             :       }
    1542             :     } else {
    1543         101 :       CHECK(success);
    1544             :     }
    1545             :   }
    1546             : 
    1547        4690 :   int table_count = static_cast<int>(module_->tables.size());
    1548        7211 :   for (int index = 0; index < table_count; ++index) {
    1549        4866 :     if (module_->tables[index].type == kWasmAnyFunc) {
    1550             :       auto table_object = handle(
    1551        4834 :           WasmTableObject::cast(instance->tables()->get(index)), isolate_);
    1552             : 
    1553             :       // Add the new dispatch table at the end to avoid redundant lookups.
    1554        2417 :       WasmTableObject::AddDispatchTable(isolate_, table_object, instance,
    1555        2417 :                                         index);
    1556             :     }
    1557             :   }
    1558        2345 : }
    1559             : 
    1560         576 : void InstanceBuilder::InitializeExceptions(
    1561             :     Handle<WasmInstanceObject> instance) {
    1562         576 :   Handle<FixedArray> exceptions_table(instance->exceptions_table(), isolate_);
    1563        1984 :   for (int index = 0; index < exceptions_table->length(); ++index) {
    1564        1456 :     if (!exceptions_table->get(index)->IsUndefined(isolate_)) continue;
    1565             :     Handle<WasmExceptionTag> exception_tag =
    1566         656 :         WasmExceptionTag::New(isolate_, index);
    1567        1312 :     exceptions_table->set(index, *exception_tag);
    1568             :   }
    1569         576 : }
    1570             : 
    1571         336 : bool LoadElemSegment(Isolate* isolate, Handle<WasmInstanceObject> instance,
    1572             :                      uint32_t table_index, uint32_t segment_index, uint32_t dst,
    1573             :                      uint32_t src, uint32_t count) {
    1574        1008 :   auto& elem_segment = instance->module()->elem_segments[segment_index];
    1575         336 :   return LoadElemSegmentImpl(
    1576             :       isolate, instance,
    1577             :       handle(WasmTableObject::cast(instance->tables()->get(table_index)),
    1578             :              isolate),
    1579         336 :       elem_segment, dst, src, count);
    1580             : }
    1581             : 
    1582             : }  // namespace wasm
    1583             : }  // namespace internal
    1584      122036 : }  // namespace v8
    1585             : 
    1586             : #undef TRACE

Generated by: LCOV version 1.10