LCOV - code coverage report
Current view: top level - src/wasm - module-instantiate.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 534 566 94.3 %
Date: 2019-02-19 Functions: 36 36 100.0 %

          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             : #include "src/asmjs/asm-js.h"
       7             : #include "src/heap/heap-inl.h"  // For CodeSpaceMemoryModificationScope.
       8             : #include "src/property-descriptor.h"
       9             : #include "src/utils.h"
      10             : #include "src/wasm/js-to-wasm-wrapper-cache-inl.h"
      11             : #include "src/wasm/module-compiler.h"
      12             : #include "src/wasm/wasm-import-wrapper-cache-inl.h"
      13             : #include "src/wasm/wasm-module.h"
      14             : #include "src/wasm/wasm-objects-inl.h"
      15             : 
      16             : #define TRACE(...)                                      \
      17             :   do {                                                  \
      18             :     if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \
      19             :   } while (false)
      20             : 
      21             : namespace v8 {
      22             : namespace internal {
      23             : namespace wasm {
      24             : 
      25             : namespace {
      26        8334 : byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) {
      27        8334 :   return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset;
      28             : }
      29             : 
      30        5398 : uint32_t EvalUint32InitExpr(Handle<WasmInstanceObject> instance,
      31             :                             const WasmInitExpr& expr) {
      32        5398 :   switch (expr.kind) {
      33             :     case WasmInitExpr::kI32Const:
      34        4030 :       return expr.val.i32_const;
      35             :     case WasmInitExpr::kGlobalIndex: {
      36             :       uint32_t offset =
      37        4104 :           instance->module()->globals[expr.val.global_index].offset;
      38             :       auto raw_addr =
      39             :           reinterpret_cast<Address>(
      40        4104 :               instance->untagged_globals_buffer()->backing_store()) +
      41        1368 :           offset;
      42             :       return ReadLittleEndianValue<uint32_t>(raw_addr);
      43             :     }
      44             :     default:
      45           0 :       UNREACHABLE();
      46             :   }
      47             : }
      48             : 
      49             : // Represents the initialized state of a table.
      50             : struct TableInstance {
      51             :   Handle<WasmTableObject> table_object;  // WebAssembly.Table instance
      52             :   Handle<FixedArray> js_functions;       // JSFunctions exported
      53             :   size_t table_size;
      54             : };
      55             : }  // namespace
      56             : 
      57             : // A helper class to simplify instantiating a module from a module object.
      58             : // It closes over the {Isolate}, the {ErrorThrower}, etc.
      59      271888 : class InstanceBuilder {
      60             :  public:
      61             :   InstanceBuilder(Isolate* isolate, ErrorThrower* thrower,
      62             :                   Handle<WasmModuleObject> module_object,
      63             :                   MaybeHandle<JSReceiver> ffi,
      64             :                   MaybeHandle<JSArrayBuffer> memory);
      65             : 
      66             :   // Build an instance, in all of its glory.
      67             :   MaybeHandle<WasmInstanceObject> Build();
      68             :   // Run the start function, if any.
      69             :   bool ExecuteStartFunction();
      70             : 
      71             :  private:
      72             :   // A pre-evaluated value to use in import binding.
      73             :   struct SanitizedImport {
      74             :     Handle<String> module_name;
      75             :     Handle<String> import_name;
      76             :     Handle<Object> value;
      77             :   };
      78             : 
      79             :   Isolate* isolate_;
      80             :   const WasmFeatures enabled_;
      81             :   const WasmModule* const module_;
      82             :   ErrorThrower* thrower_;
      83             :   Handle<WasmModuleObject> module_object_;
      84             :   MaybeHandle<JSReceiver> ffi_;
      85             :   MaybeHandle<JSArrayBuffer> memory_;
      86             :   Handle<JSArrayBuffer> untagged_globals_;
      87             :   Handle<FixedArray> tagged_globals_;
      88             :   std::vector<TableInstance> table_instances_;
      89             :   std::vector<Handle<WasmExceptionObject>> exception_wrappers_;
      90             :   Handle<WasmExportedFunction> start_function_;
      91             :   JSToWasmWrapperCache js_to_wasm_cache_;
      92             :   std::vector<SanitizedImport> sanitized_imports_;
      93             : 
      94      256800 :   UseTrapHandler use_trap_handler() const {
      95      513600 :     return module_object_->native_module()->use_trap_handler() ? kUseTrapHandler
      96      513600 :                                                                : kNoTrapHandler;
      97             :   }
      98             : 
      99             : // Helper routines to print out errors with imports.
     100             : #define ERROR_THROWER_WITH_MESSAGE(TYPE)                                      \
     101             :   void Report##TYPE(const char* error, uint32_t index,                        \
     102             :                     Handle<String> module_name, Handle<String> import_name) { \
     103             :     thrower_->TYPE("Import #%d module=\"%s\" function=\"%s\" error: %s",      \
     104             :                    index, module_name->ToCString().get(),                     \
     105             :                    import_name->ToCString().get(), error);                    \
     106             :   }                                                                           \
     107             :                                                                               \
     108             :   MaybeHandle<Object> Report##TYPE(const char* error, uint32_t index,         \
     109             :                                    Handle<String> module_name) {              \
     110             :     thrower_->TYPE("Import #%d module=\"%s\" error: %s", index,               \
     111             :                    module_name->ToCString().get(), error);                    \
     112             :     return MaybeHandle<Object>();                                             \
     113             :   }
     114             : 
     115       10758 :   ERROR_THROWER_WITH_MESSAGE(LinkError)
     116        1504 :   ERROR_THROWER_WITH_MESSAGE(TypeError)
     117             : 
     118             : #undef ERROR_THROWER_WITH_MESSAGE
     119             : 
     120             :   // Look up an import value in the {ffi_} object.
     121             :   MaybeHandle<Object> LookupImport(uint32_t index, Handle<String> module_name,
     122             :                                    Handle<String> import_name);
     123             : 
     124             :   // Look up an import value in the {ffi_} object specifically for linking an
     125             :   // asm.js module. This only performs non-observable lookups, which allows
     126             :   // falling back to JavaScript proper (and hence re-executing all lookups) if
     127             :   // module instantiation fails.
     128             :   MaybeHandle<Object> LookupImportAsm(uint32_t index,
     129             :                                       Handle<String> import_name);
     130             : 
     131             :   // Load data segments into the memory.
     132             :   void LoadDataSegments(Handle<WasmInstanceObject> instance);
     133             : 
     134             :   void WriteGlobalValue(const WasmGlobal& global, double value);
     135             :   void WriteGlobalValue(const WasmGlobal& global,
     136             :                         Handle<WasmGlobalObject> value);
     137             : 
     138             :   void WriteGlobalAnyRef(const WasmGlobal& global, Handle<Object> value);
     139             : 
     140             :   void SanitizeImports();
     141             : 
     142             :   // Find the imported memory buffer if there is one. This is used to see if we
     143             :   // need to recompile with bounds checks before creating the instance.
     144             :   MaybeHandle<JSArrayBuffer> FindImportedMemoryBuffer() const;
     145             : 
     146             :   // Processes a single imported function.
     147             :   bool ProcessImportedFunction(Handle<WasmInstanceObject> instance,
     148             :                                int import_index, int func_index,
     149             :                                Handle<String> module_name,
     150             :                                Handle<String> import_name,
     151             :                                Handle<Object> value);
     152             : 
     153             :   // Process a single imported table.
     154             :   bool ProcessImportedTable(Handle<WasmInstanceObject> instance,
     155             :                             int import_index, int table_index,
     156             :                             Handle<String> module_name,
     157             :                             Handle<String> import_name, Handle<Object> value);
     158             : 
     159             :   // Process a single imported memory.
     160             :   bool ProcessImportedMemory(Handle<WasmInstanceObject> instance,
     161             :                              int import_index, Handle<String> module_name,
     162             :                              Handle<String> import_name, Handle<Object> value);
     163             : 
     164             :   // Process a single imported global.
     165             :   bool ProcessImportedGlobal(Handle<WasmInstanceObject> instance,
     166             :                              int import_index, int global_index,
     167             :                              Handle<String> module_name,
     168             :                              Handle<String> import_name, Handle<Object> value);
     169             : 
     170             :   // Process a single imported WasmGlobalObject.
     171             :   bool ProcessImportedWasmGlobalObject(Handle<WasmInstanceObject> instance,
     172             :                                        int import_index,
     173             :                                        Handle<String> module_name,
     174             :                                        Handle<String> import_name,
     175             :                                        const WasmGlobal& global,
     176             :                                        Handle<WasmGlobalObject> global_object);
     177             : 
     178             :   // Process the imports, including functions, tables, globals, and memory, in
     179             :   // order, loading them from the {ffi_} object. Returns the number of imported
     180             :   // functions.
     181             :   int ProcessImports(Handle<WasmInstanceObject> instance);
     182             : 
     183             :   template <typename T>
     184             :   T* GetRawGlobalPtr(const WasmGlobal& global);
     185             : 
     186             :   // Process initialization of globals.
     187             :   void InitGlobals();
     188             : 
     189             :   // Allocate memory for a module instance as a new JSArrayBuffer.
     190             :   Handle<JSArrayBuffer> AllocateMemory(uint32_t num_pages);
     191             : 
     192             :   bool NeedsWrappers() const;
     193             : 
     194             :   // Process the exports, creating wrappers for functions, tables, memories,
     195             :   // and globals.
     196             :   void ProcessExports(Handle<WasmInstanceObject> instance);
     197             : 
     198             :   void InitializeTables(Handle<WasmInstanceObject> instance);
     199             : 
     200             :   void LoadTableSegments(Handle<WasmInstanceObject> instance);
     201             : 
     202             :   // Creates new exception tags for all exceptions. Note that some tags might
     203             :   // already exist if they were imported, those tags will be re-used.
     204             :   void InitializeExceptions(Handle<WasmInstanceObject> instance);
     205             : };
     206             : 
     207      135942 : MaybeHandle<WasmInstanceObject> InstantiateToInstanceObject(
     208             :     Isolate* isolate, ErrorThrower* thrower,
     209             :     Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports,
     210             :     MaybeHandle<JSArrayBuffer> memory) {
     211      135942 :   InstanceBuilder builder(isolate, thrower, module_object, imports, memory);
     212      135944 :   auto instance = builder.Build();
     213      135944 :   if (!instance.is_null() && builder.ExecuteStartFunction()) {
     214      133136 :     return instance;
     215             :   }
     216             :   DCHECK(isolate->has_pending_exception() || thrower->error());
     217        2808 :   return {};
     218             : }
     219             : 
     220      135943 : InstanceBuilder::InstanceBuilder(Isolate* isolate, ErrorThrower* thrower,
     221             :                                  Handle<WasmModuleObject> module_object,
     222             :                                  MaybeHandle<JSReceiver> ffi,
     223             :                                  MaybeHandle<JSArrayBuffer> memory)
     224             :     : isolate_(isolate),
     225      271888 :       enabled_(module_object->native_module()->enabled_features()),
     226      271888 :       module_(module_object->module()),
     227             :       thrower_(thrower),
     228             :       module_object_(module_object),
     229             :       ffi_(ffi),
     230      543775 :       memory_(memory) {
     231      271884 :   sanitized_imports_.reserve(module_->import_table.size());
     232      135944 : }
     233             : 
     234             : // Build an instance, in all of its glory.
     235      135942 : MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
     236      271884 :   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), "InstanceBuilder::Build");
     237             :   // Check that an imports argument was provided, if the module requires it.
     238             :   // No point in continuing otherwise.
     239      393505 :   if (!module_->import_table.empty() && ffi_.is_null()) {
     240             :     thrower_->TypeError(
     241      269147 :         "Imports argument must be present and must be an object");
     242          93 :     return {};
     243             :   }
     244             : 
     245      135849 :   SanitizeImports();
     246      271700 :   if (thrower_->error()) return {};
     247             : 
     248             :   // TODO(6792): No longer needed once WebAssembly code is off heap.
     249      274111 :   CodeSpaceMemoryModificationScope modification_scope(isolate_->heap());
     250             :   // From here on, we expect the build pipeline to run without exiting to JS.
     251      270913 :   DisallowJavascriptExecution no_js(isolate_);
     252             :   // Record build time into correct bucket, then build instance.
     253      270914 :   TimedHistogramScope wasm_instantiate_module_time_scope(SELECT_WASM_COUNTER(
     254      270914 :       isolate_->counters(), module_->origin, wasm_instantiate, module_time));
     255             : 
     256             :   //--------------------------------------------------------------------------
     257             :   // Allocate the memory array buffer.
     258             :   //--------------------------------------------------------------------------
     259             :   // We allocate the memory buffer before cloning or reusing the compiled module
     260             :   // so we will know whether we need to recompile with bounds checks.
     261      135457 :   uint32_t initial_pages = module_->initial_pages;
     262      270914 :   auto initial_pages_counter = SELECT_WASM_COUNTER(
     263             :       isolate_->counters(), module_->origin, wasm, min_mem_pages_count);
     264      135457 :   initial_pages_counter->AddSample(initial_pages);
     265             :   // Asm.js has memory_ already set at this point, so we don't want to
     266             :   // overwrite it.
     267      135457 :   if (memory_.is_null()) {
     268      134217 :     memory_ = FindImportedMemoryBuffer();
     269             :   }
     270      135457 :   if (!memory_.is_null()) {
     271             :     // Set externally passed ArrayBuffer non detachable.
     272             :     Handle<JSArrayBuffer> memory = memory_.ToHandleChecked();
     273             :     memory->set_is_detachable(false);
     274             : 
     275             :     DCHECK_IMPLIES(use_trap_handler(), module_->origin == kAsmJsOrigin ||
     276             :                                            memory->is_wasm_memory() ||
     277             :                                            memory->backing_store() == nullptr);
     278      130020 :   } else if (initial_pages > 0 || use_trap_handler()) {
     279             :     // We need to unconditionally create a guard region if using trap handlers,
     280             :     // even when the size is zero to prevent null-dereference issues
     281             :     // (e.g. https://crbug.com/769637).
     282             :     // Allocate memory if the initial size is more than 0 pages.
     283      129970 :     memory_ = AllocateMemory(initial_pages);
     284      129970 :     if (memory_.is_null()) {
     285             :       // failed to allocate memory
     286             :       DCHECK(isolate_->has_pending_exception() || thrower_->error());
     287          16 :       return {};
     288             :     }
     289             :   }
     290             : 
     291             :   //--------------------------------------------------------------------------
     292             :   // Recompile module if using trap handlers but could not get guarded memory
     293             :   //--------------------------------------------------------------------------
     294      135441 :   if (module_->origin == kWasmOrigin && use_trap_handler()) {
     295             :     // Make sure the memory has suitable guard regions.
     296             :     WasmMemoryTracker* const memory_tracker =
     297      261168 :         isolate_->wasm_engine()->memory_tracker();
     298             : 
     299      130584 :     if (!memory_tracker->HasFullGuardRegions(
     300      130584 :             memory_.ToHandleChecked()->backing_store())) {
     301          38 :       if (!FLAG_wasm_trap_handler_fallback) {
     302             :         thrower_->LinkError(
     303             :             "Provided memory is lacking guard regions but fallback was "
     304           0 :             "disabled.");
     305           0 :         return {};
     306             :       }
     307             : 
     308             :       TRACE("Recompiling module without bounds checks\n");
     309          38 :       ErrorThrower thrower(isolate_, "recompile");
     310          38 :       auto native_module = module_object_->native_module();
     311             :       CompileNativeModuleWithExplicitBoundsChecks(isolate_, &thrower, module_,
     312          38 :                                                   native_module);
     313          38 :       if (thrower.error()) {
     314           0 :         return {};
     315             :       }
     316          38 :       DCHECK(!native_module->use_trap_handler());
     317             :     }
     318             :   }
     319             : 
     320             :   //--------------------------------------------------------------------------
     321             :   // Create the WebAssembly.Instance object.
     322             :   //--------------------------------------------------------------------------
     323      135441 :   NativeModule* native_module = module_object_->native_module();
     324             :   TRACE("New module instantiation for %p\n", native_module);
     325             :   Handle<WasmInstanceObject> instance =
     326      135441 :       WasmInstanceObject::New(isolate_, module_object_);
     327      270878 :   NativeModuleModificationScope native_modification_scope(native_module);
     328             : 
     329             :   //--------------------------------------------------------------------------
     330             :   // Set up the globals for the new instance.
     331             :   //--------------------------------------------------------------------------
     332      135440 :   uint32_t untagged_globals_buffer_size = module_->untagged_globals_buffer_size;
     333      135440 :   if (untagged_globals_buffer_size > 0) {
     334        3199 :     void* backing_store = isolate_->array_buffer_allocator()->Allocate(
     335        3199 :         untagged_globals_buffer_size);
     336        3199 :     if (backing_store == nullptr) {
     337           0 :       thrower_->RangeError("Out of memory: wasm globals");
     338           0 :       return {};
     339             :     }
     340             :     untagged_globals_ =
     341        3199 :         isolate_->factory()->NewJSArrayBuffer(SharedFlag::kNotShared, TENURED);
     342             :     constexpr bool is_external = false;
     343             :     constexpr bool is_wasm_memory = false;
     344             :     JSArrayBuffer::Setup(untagged_globals_, isolate_, is_external,
     345             :                          backing_store, untagged_globals_buffer_size,
     346        3199 :                          SharedFlag::kNotShared, is_wasm_memory);
     347        3199 :     if (untagged_globals_.is_null()) {
     348           0 :       thrower_->RangeError("Out of memory: wasm globals");
     349           0 :       return {};
     350             :     }
     351             :     instance->set_globals_start(
     352             :         reinterpret_cast<byte*>(untagged_globals_->backing_store()));
     353        3199 :     instance->set_untagged_globals_buffer(*untagged_globals_);
     354             :   }
     355             : 
     356      135440 :   uint32_t tagged_globals_buffer_size = module_->tagged_globals_buffer_size;
     357      135440 :   if (tagged_globals_buffer_size > 0) {
     358             :     tagged_globals_ = isolate_->factory()->NewFixedArray(
     359         104 :         static_cast<int>(tagged_globals_buffer_size));
     360         104 :     instance->set_tagged_globals_buffer(*tagged_globals_);
     361             :   }
     362             : 
     363             :   //--------------------------------------------------------------------------
     364             :   // Set up the array of references to imported globals' array buffers.
     365             :   //--------------------------------------------------------------------------
     366      135440 :   if (module_->num_imported_mutable_globals > 0) {
     367             :     // TODO(binji): This allocates one slot for each mutable global, which is
     368             :     // more than required if multiple globals are imported from the same
     369             :     // module.
     370             :     Handle<FixedArray> buffers_array = isolate_->factory()->NewFixedArray(
     371         184 :         module_->num_imported_mutable_globals, TENURED);
     372         184 :     instance->set_imported_mutable_globals_buffers(*buffers_array);
     373             :   }
     374             : 
     375             :   //--------------------------------------------------------------------------
     376             :   // Set up the exception table used for exception tag checks.
     377             :   //--------------------------------------------------------------------------
     378      270880 :   int exceptions_count = static_cast<int>(module_->exceptions.size());
     379      135440 :   if (exceptions_count > 0) {
     380             :     Handle<FixedArray> exception_table =
     381         376 :         isolate_->factory()->NewFixedArray(exceptions_count, TENURED);
     382         376 :     instance->set_exceptions_table(*exception_table);
     383         376 :     exception_wrappers_.resize(exceptions_count);
     384             :   }
     385             : 
     386             :   //--------------------------------------------------------------------------
     387             :   // Set up table storage space.
     388             :   //--------------------------------------------------------------------------
     389      272137 :   int table_count = static_cast<int>(module_->tables.size());
     390      135440 :   Handle<FixedArray> tables = isolate_->factory()->NewFixedArray(table_count);
     391      136697 :   for (int i = module_->num_imported_tables; i < table_count; i++) {
     392        1257 :     const WasmTable& table = module_->tables[i];
     393             :     Handle<WasmTableObject> table_obj = WasmTableObject::New(
     394        1257 :         isolate_, table.initial_size, table.maximum_size, nullptr);
     395        2514 :     tables->set(i, *table_obj);
     396             :   }
     397      135440 :   instance->set_tables(*tables);
     398             : 
     399      137386 :   table_instances_.resize(table_count);
     400             : 
     401             :   //--------------------------------------------------------------------------
     402             :   // Process the imports for the module.
     403             :   //--------------------------------------------------------------------------
     404      135441 :   int num_imported_functions = ProcessImports(instance);
     405      135441 :   if (num_imported_functions < 0) return {};
     406             : 
     407             :   //--------------------------------------------------------------------------
     408             :   // Process the initialization for the module's globals.
     409             :   //--------------------------------------------------------------------------
     410      133468 :   InitGlobals();
     411             : 
     412             :   //--------------------------------------------------------------------------
     413             :   // Initialize the indirect tables.
     414             :   //--------------------------------------------------------------------------
     415      133468 :   if (table_count > 0) {
     416        2281 :     InitializeTables(instance);
     417             :   }
     418             : 
     419             :   //--------------------------------------------------------------------------
     420             :   // Initialize the exceptions table.
     421             :   //--------------------------------------------------------------------------
     422      133467 :   if (exceptions_count > 0) {
     423         336 :     InitializeExceptions(instance);
     424             :   }
     425             : 
     426             :   //--------------------------------------------------------------------------
     427             :   // Create the WebAssembly.Memory object.
     428             :   //--------------------------------------------------------------------------
     429      133467 :   if (module_->has_memory) {
     430       26618 :     if (!instance->has_memory_object()) {
     431             :       // No memory object exists. Create one.
     432             :       Handle<WasmMemoryObject> memory_object = WasmMemoryObject::New(
     433             :           isolate_, memory_,
     434        9208 :           module_->maximum_pages != 0 ? module_->maximum_pages : -1);
     435        9208 :       instance->set_memory_object(*memory_object);
     436             :     }
     437             : 
     438             :     // Add the instance object to the list of instances for this memory.
     439       39927 :     Handle<WasmMemoryObject> memory_object(instance->memory_object(), isolate_);
     440       13309 :     WasmMemoryObject::AddInstance(isolate_, memory_object, instance);
     441             : 
     442       13309 :     if (!memory_.is_null()) {
     443             :       // Double-check the {memory} array buffer matches the instance.
     444             :       Handle<JSArrayBuffer> memory = memory_.ToHandleChecked();
     445       13297 :       CHECK_EQ(instance->memory_size(), memory->byte_length());
     446       13297 :       CHECK_EQ(instance->memory_start(), memory->backing_store());
     447             :     }
     448             :   }
     449             : 
     450             :   //--------------------------------------------------------------------------
     451             :   // Check that indirect function table segments are within bounds.
     452             :   //--------------------------------------------------------------------------
     453      268801 :   for (const WasmElemSegment& elem_segment : module_->elem_segments) {
     454        1985 :     if (!elem_segment.active) continue;
     455             :     DCHECK(elem_segment.table_index < table_instances_.size());
     456        1945 :     uint32_t base = EvalUint32InitExpr(instance, elem_segment.offset);
     457        3890 :     size_t table_size = table_instances_[elem_segment.table_index].table_size;
     458        5835 :     if (!IsInBounds(base, elem_segment.entries.size(), table_size)) {
     459         120 :       thrower_->LinkError("table initializer is out of bounds");
     460         120 :       return {};
     461             :     }
     462             :   }
     463             : 
     464             :   //--------------------------------------------------------------------------
     465             :   // Check that memory segments are within bounds.
     466             :   //--------------------------------------------------------------------------
     467      267572 :   for (const WasmDataSegment& seg : module_->data_segments) {
     468        1020 :     if (!seg.active) continue;
     469         964 :     uint32_t base = EvalUint32InitExpr(instance, seg.dest_addr);
     470        1928 :     if (!IsInBounds(base, seg.source.length(), instance->memory_size())) {
     471         144 :       thrower_->LinkError("data segment is out of bounds");
     472         144 :       return {};
     473             :     }
     474             :   }
     475             : 
     476             :   //--------------------------------------------------------------------------
     477             :   // Set up the exports object for the new instance.
     478             :   //--------------------------------------------------------------------------
     479      133204 :   ProcessExports(instance);
     480      266408 :   if (thrower_->error()) return {};
     481             : 
     482             :   //--------------------------------------------------------------------------
     483             :   // Initialize the indirect function tables.
     484             :   //--------------------------------------------------------------------------
     485      133204 :   if (table_count > 0) {
     486        2153 :     LoadTableSegments(instance);
     487             :   }
     488             : 
     489             :   //--------------------------------------------------------------------------
     490             :   // Initialize the memory by loading data segments.
     491             :   //--------------------------------------------------------------------------
     492      266408 :   if (module_->data_segments.size() > 0) {
     493         636 :     LoadDataSegments(instance);
     494             :   }
     495             : 
     496             :   //--------------------------------------------------------------------------
     497             :   // Debugging support.
     498             :   //--------------------------------------------------------------------------
     499             :   // Set all breakpoints that were set on the shared module.
     500      133204 :   WasmModuleObject::SetBreakpointsOnNewInstance(module_object_, instance);
     501             : 
     502      133201 :   if (FLAG_wasm_interpret_all && module_->origin == kWasmOrigin) {
     503             :     Handle<WasmDebugInfo> debug_info =
     504         748 :         WasmInstanceObject::GetOrCreateDebugInfo(instance);
     505             :     std::vector<int> func_indexes;
     506        4012 :     for (int func_index = num_imported_functions,
     507        6467 :              num_wasm_functions = static_cast<int>(module_->functions.size());
     508        1632 :          func_index < num_wasm_functions; ++func_index) {
     509         884 :       func_indexes.push_back(func_index);
     510             :     }
     511         748 :     WasmDebugInfo::RedirectToInterpreter(debug_info, VectorOf(func_indexes));
     512             :   }
     513             : 
     514             :   //--------------------------------------------------------------------------
     515             :   // Create a wrapper for the start function.
     516             :   //--------------------------------------------------------------------------
     517      133201 :   if (module_->start_function_index >= 0) {
     518             :     int start_index = module_->start_function_index;
     519        4971 :     auto& function = module_->functions[start_index];
     520             :     Handle<Code> wrapper_code = js_to_wasm_cache_.GetOrCompileJSToWasmWrapper(
     521        9942 :         isolate_, function.sig, function.imported);
     522             :     // TODO(clemensh): Don't generate an exported function for the start
     523             :     // function. Use CWasmEntry instead.
     524             :     start_function_ = WasmExportedFunction::New(
     525             :         isolate_, instance, MaybeHandle<String>(), start_index,
     526        9942 :         static_cast<int>(function.sig->parameter_count()), wrapper_code);
     527             :   }
     528             : 
     529             :   DCHECK(!isolate_->has_pending_exception());
     530             :   TRACE("Successfully built instance for module %p\n",
     531             :         module_object_->native_module());
     532      269145 :   return instance;
     533             : }
     534             : 
     535      133204 : bool InstanceBuilder::ExecuteStartFunction() {
     536      266408 :   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"),
     537             :                "InstanceBuilder::ExecuteStartFunction");
     538      133204 :   if (start_function_.is_null()) return true;  // No start function.
     539             : 
     540        4971 :   HandleScope scope(isolate_);
     541             :   // Call the JS function.
     542        4971 :   Handle<Object> undefined = isolate_->factory()->undefined_value();
     543             :   MaybeHandle<Object> retval =
     544        4971 :       Execution::Call(isolate_, start_function_, undefined, 0, nullptr);
     545             : 
     546        4971 :   if (retval.is_null()) {
     547             :     DCHECK(isolate_->has_pending_exception());
     548             :     return false;
     549             :   }
     550      138107 :   return true;
     551             : }
     552             : 
     553             : // Look up an import value in the {ffi_} object.
     554      122812 : MaybeHandle<Object> InstanceBuilder::LookupImport(uint32_t index,
     555             :                                                   Handle<String> module_name,
     556             : 
     557             :                                                   Handle<String> import_name) {
     558             :   // We pre-validated in the js-api layer that the ffi object is present, and
     559             :   // a JSObject, if the module has imports.
     560             :   DCHECK(!ffi_.is_null());
     561             : 
     562             :   // Look up the module first.
     563             :   MaybeHandle<Object> result = Object::GetPropertyOrElement(
     564      122812 :       isolate_, ffi_.ToHandleChecked(), module_name);
     565      122813 :   if (result.is_null()) {
     566          16 :     return ReportTypeError("module not found", index, module_name);
     567             :   }
     568             : 
     569             :   Handle<Object> module = result.ToHandleChecked();
     570             : 
     571             :   // Look up the value in the module.
     572      245594 :   if (!module->IsJSReceiver()) {
     573             :     return ReportTypeError("module is not an object or function", index,
     574         360 :                            module_name);
     575             :   }
     576             : 
     577      122437 :   result = Object::GetPropertyOrElement(isolate_, module, import_name);
     578      122437 :   if (result.is_null()) {
     579           0 :     ReportLinkError("import not found", index, module_name, import_name);
     580           0 :     return MaybeHandle<JSFunction>();
     581             :   }
     582             : 
     583      122437 :   return result;
     584             : }
     585             : 
     586             : // Look up an import value in the {ffi_} object specifically for linking an
     587             : // asm.js module. This only performs non-observable lookups, which allows
     588             : // falling back to JavaScript proper (and hence re-executing all lookups) if
     589             : // module instantiation fails.
     590        4779 : MaybeHandle<Object> InstanceBuilder::LookupImportAsm(
     591             :     uint32_t index, Handle<String> import_name) {
     592             :   // Check that a foreign function interface object was provided.
     593        4779 :   if (ffi_.is_null()) {
     594           0 :     return ReportLinkError("missing imports object", index, import_name);
     595             :   }
     596             : 
     597             :   // Perform lookup of the given {import_name} without causing any observable
     598             :   // side-effect. We only accept accesses that resolve to data properties,
     599             :   // which is indicated by the asm.js spec in section 7 ("Linking") as well.
     600             :   Handle<Object> result;
     601             :   LookupIterator it = LookupIterator::PropertyOrElement(
     602        4779 :       isolate_, ffi_.ToHandleChecked(), import_name);
     603        4779 :   switch (it.state()) {
     604             :     case LookupIterator::ACCESS_CHECK:
     605             :     case LookupIterator::INTEGER_INDEXED_EXOTIC:
     606             :     case LookupIterator::INTERCEPTOR:
     607             :     case LookupIterator::JSPROXY:
     608             :     case LookupIterator::ACCESSOR:
     609             :     case LookupIterator::TRANSITION:
     610          18 :       return ReportLinkError("not a data property", index, import_name);
     611             :     case LookupIterator::NOT_FOUND:
     612             :       // Accepting missing properties as undefined does not cause any
     613             :       // observable difference from JavaScript semantics, we are lenient.
     614          72 :       result = isolate_->factory()->undefined_value();
     615          72 :       break;
     616             :     case LookupIterator::DATA:
     617        4689 :       result = it.GetDataValue();
     618        4689 :       break;
     619             :   }
     620             : 
     621        4761 :   return result;
     622             : }
     623             : 
     624             : // Load data segments into the memory.
     625         636 : void InstanceBuilder::LoadDataSegments(Handle<WasmInstanceObject> instance) {
     626             :   Vector<const uint8_t> wire_bytes =
     627        1272 :       module_object_->native_module()->wire_bytes();
     628        2140 :   for (const WasmDataSegment& segment : module_->data_segments) {
     629        1548 :     uint32_t source_size = segment.source.length();
     630             :     // Segments of size == 0 are just nops.
     631         868 :     if (source_size == 0) continue;
     632             :     // Passive segments are not copied during instantiation.
     633         736 :     if (!segment.active) continue;
     634         680 :     uint32_t dest_offset = EvalUint32InitExpr(instance, segment.dest_addr);
     635             :     DCHECK(IsInBounds(dest_offset, source_size, instance->memory_size()));
     636         680 :     byte* dest = instance->memory_start() + dest_offset;
     637         680 :     const byte* src = wire_bytes.start() + segment.source.offset();
     638         680 :     memcpy(dest, src, source_size);
     639             :   }
     640         636 : }
     641             : 
     642        4374 : void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global, double num) {
     643             :   TRACE("init [globals_start=%p + %u] = %lf, type = %s\n",
     644             :         reinterpret_cast<void*>(raw_buffer_ptr(untagged_globals_, 0)),
     645             :         global.offset, num, ValueTypes::TypeName(global.type));
     646        2187 :   switch (global.type) {
     647             :     case kWasmI32:
     648             :       WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global),
     649        1759 :                                       static_cast<int32_t>(num));
     650             :       break;
     651             :     case kWasmI64:
     652             :       WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global),
     653          24 :                                       static_cast<int64_t>(num));
     654             :       break;
     655             :     case kWasmF32:
     656             :       WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global),
     657          32 :                                     static_cast<float>(num));
     658             :       break;
     659             :     case kWasmF64:
     660             :       WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global),
     661             :                                      static_cast<double>(num));
     662             :       break;
     663             :     default:
     664           0 :       UNREACHABLE();
     665             :   }
     666        2187 : }
     667             : 
     668          96 : void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global,
     669             :                                        Handle<WasmGlobalObject> value) {
     670             :   TRACE("init [globals_start=%p + %u] = ",
     671             :         reinterpret_cast<void*>(raw_buffer_ptr(untagged_globals_, 0)),
     672             :         global.offset);
     673          48 :   switch (global.type) {
     674             :     case kWasmI32: {
     675          64 :       int32_t num = value->GetI32();
     676             :       WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global), num);
     677             :       TRACE("%d", num);
     678             :       break;
     679             :     }
     680             :     case kWasmI64: {
     681          16 :       int64_t num = value->GetI64();
     682             :       WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global), num);
     683             :       TRACE("%" PRId64, num);
     684             :       break;
     685             :     }
     686             :     case kWasmF32: {
     687          16 :       float num = value->GetF32();
     688             :       WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global), num);
     689             :       TRACE("%f", num);
     690             :       break;
     691             :     }
     692             :     case kWasmF64: {
     693           0 :       double num = value->GetF64();
     694             :       WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global), num);
     695             :       TRACE("%lf", num);
     696             :       break;
     697             :     }
     698             :     default:
     699           0 :       UNREACHABLE();
     700             :   }
     701             :   TRACE(", type = %s (from WebAssembly.Global)\n",
     702             :         ValueTypes::TypeName(global.type));
     703          48 : }
     704             : 
     705          48 : void InstanceBuilder::WriteGlobalAnyRef(const WasmGlobal& global,
     706             :                                         Handle<Object> value) {
     707          96 :   tagged_globals_->set(global.offset, *value, UPDATE_WRITE_BARRIER);
     708          48 : }
     709             : 
     710      135849 : void InstanceBuilder::SanitizeImports() {
     711             :   Vector<const uint8_t> wire_bytes =
     712      271699 :       module_object_->native_module()->wire_bytes();
     713      789141 :   for (size_t index = 0; index < module_->import_table.size(); ++index) {
     714      263047 :     const WasmImport& import = module_->import_table[index];
     715             : 
     716             :     Handle<String> module_name;
     717             :     MaybeHandle<String> maybe_module_name =
     718             :         WasmModuleObject::ExtractUtf8StringFromModuleBytes(isolate_, wire_bytes,
     719      127591 :                                                            import.module_name);
     720      127592 :     if (!maybe_module_name.ToHandle(&module_name)) {
     721             :       thrower_->LinkError("Could not resolve module name for import %zu",
     722      127592 :                           index);
     723           0 :       return;
     724             :     }
     725             : 
     726             :     Handle<String> import_name;
     727             :     MaybeHandle<String> maybe_import_name =
     728             :         WasmModuleObject::ExtractUtf8StringFromModuleBytes(isolate_, wire_bytes,
     729      127592 :                                                            import.field_name);
     730      127592 :     if (!maybe_import_name.ToHandle(&import_name)) {
     731             :       thrower_->LinkError("Could not resolve import name for import %zu",
     732           0 :                           index);
     733           0 :       return;
     734             :     }
     735             : 
     736             :     int int_index = static_cast<int>(index);
     737             :     MaybeHandle<Object> result =
     738      127592 :         module_->origin == kAsmJsOrigin
     739        4779 :             ? LookupImportAsm(int_index, import_name)
     740      132371 :             : LookupImport(int_index, module_name, import_name);
     741      255184 :     if (thrower_->error()) {
     742         394 :       thrower_->LinkError("Could not find value for import %zu", index);
     743         394 :       return;
     744             :     }
     745             :     Handle<Object> value = result.ToHandleChecked();
     746      254395 :     sanitized_imports_.push_back({module_name, import_name, value});
     747             :   }
     748             : }
     749             : 
     750      134217 : MaybeHandle<JSArrayBuffer> InstanceBuilder::FindImportedMemoryBuffer() const {
     751             :   DCHECK_EQ(module_->import_table.size(), sanitized_imports_.size());
     752      505476 :   for (size_t index = 0; index < module_->import_table.size(); index++) {
     753      252738 :     const WasmImport& import = module_->import_table[index];
     754             : 
     755      123134 :     if (import.kind == kExternalMemory) {
     756        9226 :       const auto& value = sanitized_imports_[index].value;
     757        9226 :       if (!value->IsWasmMemoryObject()) {
     758         416 :         return {};
     759             :       }
     760        4197 :       auto memory = Handle<WasmMemoryObject>::cast(value);
     761       12591 :       Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate_);
     762        4197 :       return buffer;
     763             :     }
     764             :   }
     765      129604 :   return {};
     766             : }
     767             : 
     768      117985 : bool InstanceBuilder::ProcessImportedFunction(
     769             :     Handle<WasmInstanceObject> instance, int import_index, int func_index,
     770             :     Handle<String> module_name, Handle<String> import_name,
     771             :     Handle<Object> value) {
     772             :   // Function imports must be callable.
     773      235970 :   if (!value->IsCallable()) {
     774             :     ReportLinkError("function import requires a callable", import_index,
     775         400 :                     module_name, import_name);
     776         400 :     return false;
     777             :   }
     778      117585 :   auto js_receiver = Handle<JSReceiver>::cast(value);
     779      235170 :   FunctionSig* expected_sig = module_->functions[func_index].sig;
     780             :   auto kind = compiler::GetWasmImportCallKind(js_receiver, expected_sig,
     781      117585 :                                               enabled_.bigint);
     782      117585 :   switch (kind) {
     783             :     case compiler::WasmImportCallKind::kLinkError:
     784             :       ReportLinkError("imported function does not match the expected type",
     785         160 :                       import_index, module_name, import_name);
     786         160 :       return false;
     787             :     case compiler::WasmImportCallKind::kWasmToWasm: {
     788             :       // The imported function is a WASM function from another instance.
     789      107128 :       auto imported_function = Handle<WasmExportedFunction>::cast(value);
     790             :       Handle<WasmInstanceObject> imported_instance(
     791      321384 :           imported_function->instance(), isolate_);
     792             :       // The import reference is the instance object itself.
     793      107128 :       Address imported_target = imported_function->GetWasmCallTarget();
     794             :       ImportedFunctionEntry entry(instance, func_index);
     795      107128 :       entry.SetWasmToWasm(*imported_instance, imported_target);
     796             :       break;
     797             :     }
     798             :     default: {
     799             :       // The imported function is a callable.
     800       10297 :       NativeModule* native_module = instance->module_object()->native_module();
     801       10297 :       WasmCode* wasm_code = native_module->import_wrapper_cache()->GetOrCompile(
     802       20594 :           isolate_->wasm_engine(), isolate_->counters(), kind, expected_sig);
     803             :       ImportedFunctionEntry entry(instance, func_index);
     804       10297 :       if (wasm_code->kind() == WasmCode::kWasmToJsWrapper) {
     805             :         // Wasm to JS wrappers are treated specially in the import table.
     806       10073 :         entry.SetWasmToJs(isolate_, js_receiver, wasm_code);
     807             :       } else {
     808             :         // Wasm math intrinsics are compiled as regular Wasm functions.
     809             :         DCHECK(kind >= compiler::WasmImportCallKind::kFirstMathIntrinsic &&
     810             :                kind <= compiler::WasmImportCallKind::kLastMathIntrinsic);
     811         224 :         entry.SetWasmToWasm(*instance, wasm_code->instruction_start());
     812             :       }
     813             :       break;
     814             :     }
     815             :   }
     816             :   return true;
     817             : }
     818             : 
     819        1480 : bool InstanceBuilder::ProcessImportedTable(Handle<WasmInstanceObject> instance,
     820             :                                            int import_index, int table_index,
     821             :                                            Handle<String> module_name,
     822             :                                            Handle<String> import_name,
     823             :                                            Handle<Object> value) {
     824        2960 :   if (!value->IsWasmTableObject()) {
     825             :     ReportLinkError("table import requires a WebAssembly.Table", import_index,
     826         344 :                     module_name, import_name);
     827         344 :     return false;
     828             :   }
     829        1136 :   const WasmTable& table = module_->tables[table_index];
     830        2168 :   TableInstance& table_instance = table_instances_[table_index];
     831        1136 :   table_instance.table_object = Handle<WasmTableObject>::cast(value);
     832        1136 :   instance->set_table_object(*table_instance.table_object);
     833             :   table_instance.js_functions =
     834        3408 :       Handle<FixedArray>(table_instance.table_object->elements(), isolate_);
     835             : 
     836             :   int imported_table_size = table_instance.js_functions->length();
     837        1136 :   if (imported_table_size < static_cast<int>(table.initial_size)) {
     838             :     thrower_->LinkError("table import %d is smaller than initial %d, got %u",
     839          40 :                         import_index, table.initial_size, imported_table_size);
     840          40 :     return false;
     841             :   }
     842             : 
     843        1096 :   if (table.has_maximum_size) {
     844             :     int64_t imported_maximum_size =
     845         808 :         table_instance.table_object->maximum_length()->Number();
     846         808 :     if (imported_maximum_size < 0) {
     847             :       thrower_->LinkError("table import %d has no maximum length, expected %d",
     848           0 :                           import_index, table.maximum_size);
     849           0 :       return false;
     850             :     }
     851         808 :     if (imported_maximum_size > table.maximum_size) {
     852             :       thrower_->LinkError("table import %d has a larger maximum size %" PRIx64
     853             :                           " than the module's declared maximum %u",
     854             :                           import_index, imported_maximum_size,
     855          64 :                           table.maximum_size);
     856          64 :       return false;
     857             :     }
     858             :   }
     859             : 
     860             :   // Allocate a new dispatch table.
     861        1032 :   if (!instance->has_indirect_function_table()) {
     862             :     WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
     863        1032 :         instance, imported_table_size);
     864        1032 :     table_instances_[table_index].table_size = imported_table_size;
     865             :   }
     866             :   // Initialize the dispatch table with the (foreign) JS functions
     867             :   // that are already in the table.
     868     2109144 :   for (int i = 0; i < imported_table_size; ++i) {
     869     2109144 :     Handle<Object> val(table_instance.js_functions->get(i), isolate_);
     870             :     // TODO(mtrofin): this is the same logic as WasmTableObject::Set:
     871             :     // insert in the local table a wrapper from the other module, and add
     872             :     // a reference to the owning instance of the other module.
     873     6324632 :     if (!val->IsJSFunction()) continue;
     874        2800 :     if (!WasmExportedFunction::IsWasmExportedFunction(*val)) {
     875             :       thrower_->LinkError("table import %d[%d] is not a wasm function",
     876           0 :                           import_index, i);
     877           0 :       return false;
     878             :     }
     879        2800 :     auto target_func = Handle<WasmExportedFunction>::cast(val);
     880             :     Handle<WasmInstanceObject> target_instance =
     881        8400 :         handle(target_func->instance(), isolate_);
     882             :     // Look up the signature's canonical id. If there is no canonical
     883             :     // id, then the signature does not appear at all in this module,
     884             :     // so putting {-1} in the table will cause checks to always fail.
     885        2800 :     FunctionSig* sig = target_func->sig();
     886             :     IndirectFunctionTableEntry(instance, i)
     887             :         .Set(module_->signature_map.Find(*sig), target_instance,
     888        5600 :              target_func->function_index());
     889             :   }
     890             :   return true;
     891             : }
     892             : 
     893        4604 : 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        9210 :   if (!value->IsWasmMemoryObject()) {
     902             :     ReportLinkError("memory import must be a WebAssembly.Memory object",
     903         408 :                     import_index, module_name, import_name);
     904         408 :     return false;
     905             :   }
     906        4197 :   auto memory = Handle<WasmMemoryObject>::cast(value);
     907        4197 :   instance->set_memory_object(*memory);
     908       12591 :   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        4197 :       static_cast<uint32_t>(buffer->byte_length() / kWasmPageSize);
     913        4197 :   if (imported_cur_pages < module_->initial_pages) {
     914             :     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        4173 :   if (module_->has_maximum_pages) {
     921        1222 :     if (imported_maximum_pages < 0) {
     922             :       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        1214 :     if (static_cast<uint32_t>(imported_maximum_pages) >
     928             :         module_->maximum_pages) {
     929             :       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        8250 :   if (module_->has_shared_memory != buffer->is_shared()) {
     937             :     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         296 : 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         296 :   if (global_object->type() != global.type) {
     951             :     ReportLinkError("imported global does not match the expected type",
     952           8 :                     import_index, module_name, import_name);
     953           8 :     return false;
     954             :   }
     955         288 :   if (global_object->is_mutable() != global.mutability) {
     956             :     ReportLinkError("imported global does not match the expected mutability",
     957          32 :                     import_index, module_name, import_name);
     958          32 :     return false;
     959             :   }
     960         256 :   if (global.mutability) {
     961             :     DCHECK_LT(global.index, module_->num_imported_mutable_globals);
     962             :     Handle<Object> buffer;
     963             :     Address address_or_offset;
     964         208 :     if (global.type == kWasmAnyRef) {
     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         216 :       buffer = handle(global_object->tagged_buffer(), isolate_);
     969             :       // For anyref globals we use a relative offset, not an absolute address.
     970          72 :       address_or_offset = static_cast<Address>(global_object->offset());
     971             :     } else {
     972         408 :       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         272 :           Handle<JSArrayBuffer>::cast(buffer), global_object->offset()));
     978             :     }
     979         416 :     instance->imported_mutable_globals_buffers()->set(global.index, *buffer);
     980         208 :     instance->imported_mutable_globals()[global.index] = address_or_offset;
     981             :     return true;
     982             :   }
     983             : 
     984          48 :   WriteGlobalValue(global, global_object);
     985          48 :   return true;
     986             : }
     987             : 
     988        2920 : 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        2920 :   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        8760 :   if (global.type == kWasmI64 && !enabled_.bigint &&
    1007        3016 :       !value->IsWasmGlobalObject()) {
    1008             :     ReportLinkError("global import cannot have type i64", import_index,
    1009          32 :                     module_name, import_name);
    1010          32 :     return false;
    1011             :   }
    1012        2888 :   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        2416 :     if (value->IsJSFunction()) value = isolate_->factory()->nan_value();
    1020        4814 :     if (value->IsPrimitive() && !value->IsSymbol()) {
    1021        1195 :       if (global.type == kWasmI32) {
    1022        1710 :         value = Object::ToInt32(isolate_, value).ToHandleChecked();
    1023             :       } else {
    1024         680 :         value = Object::ToNumber(isolate_, value).ToHandleChecked();
    1025             :       }
    1026             :     }
    1027             :   }
    1028             : 
    1029        5776 :   if (value->IsWasmGlobalObject()) {
    1030         296 :     auto global_object = Handle<WasmGlobalObject>::cast(value);
    1031             :     return ProcessImportedWasmGlobalObject(instance, import_index, module_name,
    1032         296 :                                            import_name, global, global_object);
    1033             :   }
    1034             : 
    1035        2592 :   if (global.mutability) {
    1036             :     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        2576 :   if (global.type == ValueType::kWasmAnyRef) {
    1043          48 :     WriteGlobalAnyRef(global, value);
    1044          48 :     return true;
    1045             :   }
    1046             : 
    1047        5056 :   if (value->IsNumber()) {
    1048        2163 :     WriteGlobalValue(global, value->Number());
    1049        2163 :     return true;
    1050             :   }
    1051             : 
    1052         365 :   if (enabled_.bigint && global.type == kWasmI64) {
    1053             :     Handle<BigInt> bigint;
    1054             : 
    1055          48 :     if (!BigInt::FromObject(isolate_, value).ToHandle(&bigint)) {
    1056             :       return false;
    1057             :     }
    1058          24 :     WriteGlobalValue(global, bigint->AsInt64());
    1059          24 :     return true;
    1060             :   }
    1061             : 
    1062             :   ReportLinkError("global import must be a number or WebAssembly.Global object",
    1063         341 :                   import_index, module_name, import_name);
    1064         341 :   return false;
    1065             : }
    1066             : 
    1067             : // Process the imports, including functions, tables, globals, and memory, in
    1068             : // order, loading them from the {ffi_} object. Returns the number of imported
    1069             : // functions.
    1070      135440 : int InstanceBuilder::ProcessImports(Handle<WasmInstanceObject> instance) {
    1071             :   int num_imported_functions = 0;
    1072             :   int num_imported_tables = 0;
    1073             : 
    1074             :   DCHECK_EQ(module_->import_table.size(), sanitized_imports_.size());
    1075      397957 :   int num_imports = static_cast<int>(module_->import_table.size());
    1076      521090 :   for (int index = 0; index < num_imports; ++index) {
    1077      127077 :     const WasmImport& import = module_->import_table[index];
    1078             : 
    1079      254154 :     Handle<String> module_name = sanitized_imports_[index].module_name;
    1080      127077 :     Handle<String> import_name = sanitized_imports_[index].import_name;
    1081      127077 :     Handle<Object> value = sanitized_imports_[index].value;
    1082             : 
    1083      127077 :     switch (import.kind) {
    1084             :       case kExternalFunction: {
    1085      117985 :         uint32_t func_index = import.index;
    1086             :         DCHECK_EQ(num_imported_functions, func_index);
    1087      117985 :         if (!ProcessImportedFunction(instance, index, func_index, module_name,
    1088      117985 :                                      import_name, value)) {
    1089        1973 :           return -1;
    1090             :         }
    1091      117425 :         num_imported_functions++;
    1092      117425 :         break;
    1093             :       }
    1094             :       case kExternalTable: {
    1095        1480 :         uint32_t table_index = import.index;
    1096             :         DCHECK_EQ(table_index, num_imported_tables);
    1097        1480 :         if (!ProcessImportedTable(instance, index, table_index, module_name,
    1098        1480 :                                   import_name, value)) {
    1099             :           return -1;
    1100             :         }
    1101             :         num_imported_tables++;
    1102             :         break;
    1103             :       }
    1104             :       case kExternalMemory: {
    1105        4605 :         if (!ProcessImportedMemory(instance, index, module_name, import_name,
    1106        4604 :                                    value)) {
    1107             :           return -1;
    1108             :         }
    1109             :         break;
    1110             :       }
    1111             :       case kExternalGlobal: {
    1112        2920 :         if (!ProcessImportedGlobal(instance, index, import.index, module_name,
    1113        2920 :                                    import_name, value)) {
    1114             :           return -1;
    1115             :         }
    1116             :         break;
    1117             :       }
    1118             :       case kExternalException: {
    1119         176 :         if (!value->IsWasmExceptionObject()) {
    1120             :           ReportLinkError("exception import requires a WebAssembly.Exception",
    1121          32 :                           index, module_name, import_name);
    1122          32 :           return -1;
    1123             :         }
    1124             :         Handle<WasmExceptionObject> imported_exception =
    1125          56 :             Handle<WasmExceptionObject>::cast(value);
    1126          56 :         if (!imported_exception->IsSignatureEqual(
    1127         168 :                 module_->exceptions[import.index].sig)) {
    1128             :           ReportLinkError("imported exception does not match the expected type",
    1129           8 :                           index, module_name, import_name);
    1130           8 :           return -1;
    1131             :         }
    1132          48 :         Object exception_tag = imported_exception->exception_tag();
    1133             :         DCHECK(instance->exceptions_table()->get(import.index)->IsUndefined());
    1134          96 :         instance->exceptions_table()->set(import.index, exception_tag);
    1135          96 :         exception_wrappers_[import.index] = imported_exception;
    1136          48 :         break;
    1137             :       }
    1138             :       default:
    1139           0 :         UNREACHABLE();
    1140             :         break;
    1141             :     }
    1142             :   }
    1143             :   return num_imported_functions;
    1144             : }
    1145             : 
    1146             : template <typename T>
    1147             : T* InstanceBuilder::GetRawGlobalPtr(const WasmGlobal& global) {
    1148       16172 :   return reinterpret_cast<T*>(raw_buffer_ptr(untagged_globals_, global.offset));
    1149             : }
    1150             : 
    1151             : // Process initialization of globals.
    1152      133468 : void InstanceBuilder::InitGlobals() {
    1153      275446 :   for (auto global : module_->globals) {
    1154        8510 :     if (global.mutability && global.imported) {
    1155             :       continue;
    1156             :     }
    1157             : 
    1158        8302 :     switch (global.init.kind) {
    1159             :       case WasmInitExpr::kI32Const:
    1160             :         WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global),
    1161        4729 :                                         global.init.val.i32_const);
    1162             :         break;
    1163             :       case WasmInitExpr::kI64Const:
    1164             :         WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global),
    1165          88 :                                         global.init.val.i64_const);
    1166             :         break;
    1167             :       case WasmInitExpr::kF32Const:
    1168             :         WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global),
    1169         180 :                                       global.init.val.f32_const);
    1170             :         break;
    1171             :       case WasmInitExpr::kF64Const:
    1172             :         WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global),
    1173         854 :                                        global.init.val.f64_const);
    1174             :         break;
    1175             :       case WasmInitExpr::kAnyRefConst:
    1176             :         DCHECK(enabled_.anyref);
    1177         112 :         if (global.imported) break;  // We already initialized imported globals.
    1178             : 
    1179             :         tagged_globals_->set(global.offset,
    1180         112 :                              ReadOnlyRoots(isolate_).null_value(),
    1181         224 :                              SKIP_WRITE_BARRIER);
    1182         112 :         break;
    1183             :       case WasmInitExpr::kGlobalIndex: {
    1184          56 :         if (global.type == ValueType::kWasmAnyRef) {
    1185             :           DCHECK(enabled_.anyref);
    1186             :           int other_offset =
    1187          56 :               module_->globals[global.init.val.global_index].offset;
    1188             : 
    1189             :           tagged_globals_->set(global.offset,
    1190             :                                tagged_globals_->get(other_offset),
    1191           0 :                                SKIP_WRITE_BARRIER);
    1192             :         }
    1193             :         // Initialize with another global.
    1194             :         uint32_t new_offset = global.offset;
    1195             :         uint32_t old_offset =
    1196         112 :             module_->globals[global.init.val.global_index].offset;
    1197             :         TRACE("init [globals+%u] = [globals+%d]\n", global.offset, old_offset);
    1198          56 :         size_t size = (global.type == kWasmI64 || global.type == kWasmF64)
    1199             :                           ? sizeof(double)
    1200          56 :                           : sizeof(int32_t);
    1201         168 :         memcpy(raw_buffer_ptr(untagged_globals_, new_offset),
    1202         168 :                raw_buffer_ptr(untagged_globals_, old_offset), size);
    1203          56 :         break;
    1204             :       }
    1205             :       case WasmInitExpr::kNone:
    1206             :         // Happens with imported globals.
    1207             :         break;
    1208             :       default:
    1209           0 :         UNREACHABLE();
    1210             :         break;
    1211             :     }
    1212             :   }
    1213      133468 : }
    1214             : 
    1215             : // Allocate memory for a module instance as a new JSArrayBuffer.
    1216      129970 : Handle<JSArrayBuffer> InstanceBuilder::AllocateMemory(uint32_t num_pages) {
    1217      129970 :   if (num_pages > max_mem_pages()) {
    1218          16 :     thrower_->RangeError("Out of memory: wasm memory too large");
    1219             :     return Handle<JSArrayBuffer>::null();
    1220             :   }
    1221      129954 :   const bool is_shared_memory = module_->has_shared_memory && enabled_.threads;
    1222             :   SharedFlag shared_flag =
    1223      129954 :       is_shared_memory ? SharedFlag::kShared : SharedFlag::kNotShared;
    1224             :   Handle<JSArrayBuffer> mem_buffer;
    1225      259908 :   if (!NewArrayBuffer(isolate_, num_pages * kWasmPageSize, shared_flag)
    1226      259908 :            .ToHandle(&mem_buffer)) {
    1227           0 :     thrower_->RangeError("Out of memory: wasm memory");
    1228             :   }
    1229      129954 :   return mem_buffer;
    1230             : }
    1231             : 
    1232      133203 : bool InstanceBuilder::NeedsWrappers() const {
    1233      133203 :   if (module_->num_exported_functions > 0) return true;
    1234        8768 :   for (auto& table_instance : table_instances_) {
    1235         720 :     if (!table_instance.js_functions.is_null()) return true;
    1236             :   }
    1237        7776 :   for (auto& table : module_->tables) {
    1238         352 :     if (table.exported) return true;
    1239             :   }
    1240             :   return false;
    1241             : }
    1242             : 
    1243             : // Process the exports, creating wrappers for functions, tables, memories,
    1244             : // globals, and exceptions.
    1245      133203 : void InstanceBuilder::ProcessExports(Handle<WasmInstanceObject> instance) {
    1246             :   Handle<FixedArray> export_wrappers(module_object_->export_wrappers(),
    1247      399610 :                                      isolate_);
    1248      133203 :   if (NeedsWrappers()) {
    1249             :     // If an imported WebAssembly function gets exported, the exported function
    1250             :     // has to be identical to to imported function. Therefore we cache all
    1251             :     // imported WebAssembly functions in the instance.
    1252      507608 :     for (int index = 0, end = static_cast<int>(module_->import_table.size());
    1253             :          index < end; ++index) {
    1254      124185 :       const WasmImport& import = module_->import_table[index];
    1255      124185 :       if (import.kind == kExternalFunction) {
    1256      234290 :         Handle<Object> value = sanitized_imports_[index].value;
    1257      117145 :         if (WasmExportedFunction::IsWasmExportedFunction(*value)) {
    1258             :           WasmInstanceObject::SetWasmExportedFunction(
    1259             :               isolate_, instance, import.index,
    1260      107024 :               Handle<WasmExportedFunction>::cast(value));
    1261             :         }
    1262             :       }
    1263             :     }
    1264             :   }
    1265             : 
    1266             :   Handle<JSObject> exports_object;
    1267             :   bool is_asm_js = false;
    1268      133204 :   switch (module_->origin) {
    1269             :     case kWasmOrigin: {
    1270             :       // Create the "exports" object.
    1271      128409 :       exports_object = isolate_->factory()->NewJSObjectWithNullProto();
    1272      128408 :       break;
    1273             :     }
    1274             :     case kAsmJsOrigin: {
    1275             :       Handle<JSFunction> object_function = Handle<JSFunction>(
    1276       14385 :           isolate_->native_context()->object_function(), isolate_);
    1277        4795 :       exports_object = isolate_->factory()->NewJSObject(object_function);
    1278             :       is_asm_js = true;
    1279             :       break;
    1280             :     }
    1281             :     default:
    1282           0 :       UNREACHABLE();
    1283             :   }
    1284      133202 :   instance->set_exports_object(*exports_object);
    1285             : 
    1286             :   Handle<String> single_function_name =
    1287      133204 :       isolate_->factory()->InternalizeUtf8String(AsmJs::kSingleFunctionName);
    1288             : 
    1289             :   PropertyDescriptor desc;
    1290             :   desc.set_writable(is_asm_js);
    1291             :   desc.set_enumerable(true);
    1292             :   desc.set_configurable(is_asm_js);
    1293             : 
    1294             :   // Process each export in the export table.
    1295             :   int export_index = 0;  // Index into {export_wrappers}.
    1296      494700 :   for (const WasmExport& exp : module_->export_table) {
    1297             :     Handle<String> name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
    1298      228292 :                               isolate_, module_object_, exp.name)
    1299      456584 :                               .ToHandleChecked();
    1300             :     Handle<JSObject> export_to;
    1301      236482 :     if (is_asm_js && exp.kind == kExternalFunction &&
    1302        8190 :         String::Equals(isolate_, name, single_function_name)) {
    1303             :       export_to = instance;
    1304             :     } else {
    1305             :       export_to = exports_object;
    1306             :     }
    1307             : 
    1308      228292 :     switch (exp.kind) {
    1309             :       case kExternalFunction: {
    1310             :         // Wrap and export the code as a JSFunction.
    1311             :         // TODO(wasm): reduce duplication with LoadElemSegment() further below
    1312      225488 :         const WasmFunction& function = module_->functions[exp.index];
    1313             :         MaybeHandle<WasmExportedFunction> wasm_exported_function =
    1314             :             WasmInstanceObject::GetWasmExportedFunction(isolate_, instance,
    1315      225488 :                                                         exp.index);
    1316      225488 :         if (wasm_exported_function.is_null()) {
    1317             :           // Wrap the exported code as a JSFunction.
    1318             :           Handle<Code> export_code =
    1319      450423 :               export_wrappers->GetValueChecked<Code>(isolate_, export_index);
    1320      225212 :           MaybeHandle<String> func_name;
    1321      225212 :           if (is_asm_js) {
    1322             :             // For modules arising from asm.js, honor the names section.
    1323             :             WireBytesRef func_name_ref = module_->LookupFunctionName(
    1324             :                 ModuleWireBytes(module_object_->native_module()->wire_bytes()),
    1325       24510 :                 function.func_index);
    1326             :             func_name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
    1327        8170 :                             isolate_, module_object_, func_name_ref)
    1328       16340 :                             .ToHandleChecked();
    1329             :           }
    1330             :           wasm_exported_function = WasmExportedFunction::New(
    1331             :               isolate_, instance, func_name, function.func_index,
    1332      225212 :               static_cast<int>(function.sig->parameter_count()), export_code);
    1333             :           WasmInstanceObject::SetWasmExportedFunction(
    1334             :               isolate_, instance, exp.index,
    1335      225211 :               wasm_exported_function.ToHandleChecked());
    1336             :         }
    1337             :         desc.set_value(wasm_exported_function.ToHandleChecked());
    1338      225488 :         export_index++;
    1339             :         break;
    1340             :       }
    1341             :       case kExternalTable: {
    1342             :         // Export a table as a WebAssembly.Table object.
    1343         472 :         TableInstance& table_instance = table_instances_[exp.index];
    1344         472 :         const WasmTable& table = module_->tables[exp.index];
    1345         472 :         if (table_instance.table_object.is_null()) {
    1346             :           uint32_t maximum = table.has_maximum_size ? table.maximum_size
    1347         424 :                                                     : FLAG_wasm_max_table_size;
    1348             :           table_instance.table_object =
    1349             :               WasmTableObject::New(isolate_, table.initial_size, maximum,
    1350         424 :                                    &table_instance.js_functions);
    1351             :         }
    1352         472 :         instance->set_table_object(*table_instance.table_object);
    1353             :         desc.set_value(table_instance.table_object);
    1354         472 :         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             :         desc.set_value(
    1362        4932 :             Handle<WasmMemoryObject>(instance->memory_object(), isolate_));
    1363        1644 :         break;
    1364             :       }
    1365             :       case kExternalGlobal: {
    1366         576 :         const WasmGlobal& global = module_->globals[exp.index];
    1367             :         Handle<JSArrayBuffer> untagged_buffer;
    1368             :         Handle<FixedArray> tagged_buffer;
    1369             :         uint32_t offset;
    1370             : 
    1371         576 :         if (global.mutability && global.imported) {
    1372             :           Handle<FixedArray> buffers_array(
    1373         168 :               instance->imported_mutable_globals_buffers(), isolate_);
    1374          56 :           if (global.type == kWasmAnyRef) {
    1375             :             tagged_buffer = buffers_array->GetValueChecked<FixedArray>(
    1376          48 :                 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          24 :             Address addr = instance->imported_mutable_globals()[global.index];
    1380             :             DCHECK_LE(addr, static_cast<Address>(
    1381             :                                 std::numeric_limits<uint32_t>::max()));
    1382          24 :             offset = static_cast<uint32_t>(addr);
    1383             :           } else {
    1384             :             untagged_buffer = buffers_array->GetValueChecked<JSArrayBuffer>(
    1385          64 :                 isolate_, global.index);
    1386             :             Address global_addr =
    1387          32 :                 instance->imported_mutable_globals()[global.index];
    1388             : 
    1389             :             size_t buffer_size = untagged_buffer->byte_length();
    1390             :             Address backing_store =
    1391          32 :                 reinterpret_cast<Address>(untagged_buffer->backing_store());
    1392          32 :             CHECK(global_addr >= backing_store &&
    1393             :                   global_addr < backing_store + buffer_size);
    1394          32 :             offset = static_cast<uint32_t>(global_addr - backing_store);
    1395             :           }
    1396             :         } else {
    1397         520 :           if (global.type == kWasmAnyRef) {
    1398         120 :             tagged_buffer = handle(instance->tagged_globals_buffer(), isolate_);
    1399             :           } else {
    1400             :             untagged_buffer =
    1401        1440 :                 handle(instance->untagged_globals_buffer(), isolate_);
    1402             :           }
    1403         520 :           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             :             WasmGlobalObject::New(isolate_, untagged_buffer, tagged_buffer,
    1410        1728 :                                   global.type, offset, global.mutability)
    1411        1152 :                 .ToHandleChecked();
    1412             :         desc.set_value(global_obj);
    1413             :         break;
    1414             :       }
    1415             :       case kExternalException: {
    1416         112 :         const WasmException& exception = module_->exceptions[exp.index];
    1417         320 :         Handle<WasmExceptionObject> wrapper = exception_wrappers_[exp.index];
    1418         112 :         if (wrapper.is_null()) {
    1419             :           Handle<HeapObject> exception_tag(
    1420         192 :               HeapObject::cast(instance->exceptions_table()->get(exp.index)),
    1421         288 :               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      228292 :         isolate_, export_to, name, &desc, Just(kThrowOnError));
    1436      228290 :     if (!status.IsJust()) {
    1437             :       DisallowHeapAllocation no_gc;
    1438           0 :       TruncatedUserString<> trunc_name(name->GetCharVector<uint8_t>(no_gc));
    1439             :       thrower_->LinkError("export of %.*s failed.", trunc_name.length(),
    1440           0 :                           trunc_name.start());
    1441      133203 :       return;
    1442             :     }
    1443             :   }
    1444             :   DCHECK_EQ(export_index, export_wrappers->length());
    1445             : 
    1446      133203 :   if (module_->origin == kWasmOrigin) {
    1447             :     v8::Maybe<bool> success =
    1448      128407 :         JSReceiver::SetIntegrityLevel(exports_object, FROZEN, kDontThrow);
    1449             :     DCHECK(success.FromMaybe(false));
    1450             :     USE(success);
    1451             :   }
    1452             : }
    1453             : 
    1454        2281 : void InstanceBuilder::InitializeTables(Handle<WasmInstanceObject> instance) {
    1455        4562 :   size_t table_count = module_->tables.size();
    1456        4562 :   for (size_t index = 0; index < table_count; ++index) {
    1457        2281 :     const WasmTable& table = module_->tables[index];
    1458             : 
    1459        3546 :     if (!instance->has_indirect_function_table() &&
    1460        1265 :         table.type == kWasmAnyFunc) {
    1461             :       WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
    1462        1265 :           instance, table.initial_size);
    1463        2530 :       table_instances_[index].table_size = table.initial_size;
    1464             :     }
    1465             :   }
    1466        2281 : }
    1467             : 
    1468        1993 : bool LoadElemSegmentImpl(Isolate* isolate, Handle<WasmInstanceObject> instance,
    1469             :                          const TableInstance& table_instance,
    1470             :                          JSToWasmWrapperCache* js_to_wasm_cache,
    1471             :                          const WasmElemSegment& elem_segment, uint32_t dst,
    1472             :                          uint32_t src, size_t count) {
    1473        3986 :   if (!IsInBounds(dst, count, table_instance.table_size)) return false;
    1474       15100 :   if (!IsInBounds(src, count, elem_segment.entries.size())) return false;
    1475             : 
    1476        1865 :   const WasmModule* module = instance->module();
    1477       11202 :   for (uint32_t i = 0; i < count; ++i) {
    1478       18674 :     uint32_t func_index = elem_segment.entries[src + i];
    1479        9337 :     const WasmFunction* function = &module->functions[func_index];
    1480        9337 :     int entry_index = static_cast<int>(dst + i);
    1481             : 
    1482             :     // Update the local dispatch table first.
    1483       18674 :     uint32_t sig_id = module->signature_ids[function->sig_index];
    1484             :     IndirectFunctionTableEntry(instance, entry_index)
    1485       18674 :         .Set(sig_id, instance, func_index);
    1486             : 
    1487        9337 :     if (!table_instance.table_object.is_null()) {
    1488             :       // Update the table object's other dispatch tables.
    1489             :       MaybeHandle<WasmExportedFunction> wasm_exported_function =
    1490             :           WasmInstanceObject::GetWasmExportedFunction(isolate, instance,
    1491        1832 :                                                       func_index);
    1492        1832 :       if (wasm_exported_function.is_null()) {
    1493             :         // No JSFunction entry yet exists for this function. Create one.
    1494             :         // TODO(titzer): We compile JS->wasm wrappers for functions are
    1495             :         // not exported but are in an exported table. This should be done
    1496             :         // at module compile time and cached instead.
    1497             : 
    1498             :         Handle<Code> wrapper_code =
    1499             :             js_to_wasm_cache->GetOrCompileJSToWasmWrapper(
    1500        2784 :                 isolate, function->sig, function->imported);
    1501        1392 :         MaybeHandle<String> func_name;
    1502        1392 :         if (module->origin == kAsmJsOrigin) {
    1503             :           // For modules arising from asm.js, honor the names section.
    1504             :           auto module_object =
    1505           0 :               Handle<WasmModuleObject>(instance->module_object(), isolate);
    1506             :           WireBytesRef func_name_ref = module->LookupFunctionName(
    1507             :               ModuleWireBytes(module_object->native_module()->wire_bytes()),
    1508           0 :               func_index);
    1509             :           func_name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
    1510             :                           isolate, module_object, func_name_ref)
    1511           0 :                           .ToHandleChecked();
    1512             :         }
    1513             :         wasm_exported_function = WasmExportedFunction::New(
    1514             :             isolate, instance, func_name, func_index,
    1515        2784 :             static_cast<int>(function->sig->parameter_count()), wrapper_code);
    1516             :         WasmInstanceObject::SetWasmExportedFunction(
    1517             :             isolate, instance, func_index,
    1518        1392 :             wasm_exported_function.ToHandleChecked());
    1519             :       }
    1520             :       table_instance.js_functions->set(
    1521        3664 :           entry_index, *wasm_exported_function.ToHandleChecked());
    1522             :       // UpdateDispatchTables() updates all other dispatch tables, since
    1523             :       // we have not yet added the dispatch table we are currently building.
    1524             :       WasmTableObject::UpdateDispatchTables(
    1525             :           isolate, table_instance.table_object, entry_index, function->sig,
    1526        1832 :           instance, func_index);
    1527             :     }
    1528             :   }
    1529             :   return true;
    1530             : }
    1531             : 
    1532        2153 : void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
    1533        6155 :   for (auto& elem_segment : module_->elem_segments) {
    1534             :     // Passive segments are not copied during instantiation.
    1535        1849 :     if (!elem_segment.active) continue;
    1536             : 
    1537        1809 :     uint32_t dst = EvalUint32InitExpr(instance, elem_segment.offset);
    1538             :     uint32_t src = 0;
    1539        1809 :     size_t count = elem_segment.entries.size();
    1540             : 
    1541             :     bool success = LoadElemSegmentImpl(
    1542        3962 :         isolate_, instance, table_instances_[elem_segment.table_index],
    1543        3618 :         &js_to_wasm_cache_, elem_segment, dst, src, count);
    1544        1809 :     CHECK(success);
    1545             :   }
    1546             : 
    1547        4306 :   int table_count = static_cast<int>(module_->tables.size());
    1548        4306 :   for (int index = 0; index < table_count; ++index) {
    1549        2153 :     TableInstance& table_instance = table_instances_[index];
    1550             : 
    1551             :     // Add the new dispatch table at the end to avoid redundant lookups.
    1552        2153 :     if (!table_instance.table_object.is_null()) {
    1553             :       WasmTableObject::AddDispatchTable(isolate_, table_instance.table_object,
    1554        1392 :                                         instance, index);
    1555             :     }
    1556             :   }
    1557        2153 : }
    1558             : 
    1559         336 : void InstanceBuilder::InitializeExceptions(
    1560             :     Handle<WasmInstanceObject> instance) {
    1561        1008 :   Handle<FixedArray> exceptions_table(instance->exceptions_table(), isolate_);
    1562        1520 :   for (int index = 0; index < exceptions_table->length(); ++index) {
    1563        1320 :     if (!exceptions_table->get(index)->IsUndefined(isolate_)) continue;
    1564             :     Handle<WasmExceptionTag> exception_tag =
    1565         376 :         WasmExceptionTag::New(isolate_, index);
    1566         752 :     exceptions_table->set(index, *exception_tag);
    1567             :   }
    1568         336 : }
    1569             : 
    1570         184 : bool LoadElemSegment(Isolate* isolate, Handle<WasmInstanceObject> instance,
    1571             :                      uint32_t table_index, uint32_t segment_index, uint32_t dst,
    1572             :                      uint32_t src, uint32_t count) {
    1573             :   JSToWasmWrapperCache js_to_wasm_cache;
    1574             : 
    1575             :   Handle<WasmTableObject> table_object;
    1576             :   Handle<FixedArray> js_functions;
    1577         368 :   if (instance->has_table_object()) {
    1578         368 :     table_object = Handle<WasmTableObject>(instance->table_object(), isolate);
    1579         368 :     js_functions = Handle<FixedArray>(table_object->elements(), isolate);
    1580             :   }
    1581             : 
    1582             :   TableInstance table_instance = {table_object, js_functions,
    1583         368 :                                   instance->indirect_function_table_size()};
    1584             : 
    1585         552 :   auto& elem_segment = instance->module()->elem_segments[segment_index];
    1586             :   return LoadElemSegmentImpl(isolate, instance, table_instance,
    1587         368 :                              &js_to_wasm_cache, elem_segment, dst, src, count);
    1588             : }
    1589             : 
    1590             : }  // namespace wasm
    1591             : }  // namespace internal
    1592      178779 : }  // namespace v8
    1593             : 
    1594             : #undef TRACE

Generated by: LCOV version 1.10