LCOV - code coverage report
Current view: top level - src/wasm - module-instantiate.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 517 549 94.2 %
Date: 2019-01-20 Functions: 34 34 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/property-descriptor.h"
       8             : #include "src/utils.h"
       9             : #include "src/wasm/js-to-wasm-wrapper-cache-inl.h"
      10             : #include "src/wasm/module-compiler.h"
      11             : #include "src/wasm/wasm-import-wrapper-cache-inl.h"
      12             : #include "src/wasm/wasm-module.h"
      13             : #include "src/wasm/wasm-objects-inl.h"
      14             : 
      15             : #define TRACE(...)                                      \
      16             :   do {                                                  \
      17             :     if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \
      18             :   } while (false)
      19             : 
      20             : namespace v8 {
      21             : namespace internal {
      22             : namespace wasm {
      23             : 
      24             : namespace {
      25       10946 : byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) {
      26       10946 :   return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset;
      27             : }
      28             : }  // namespace
      29             : 
      30             : // A helper class to simplify instantiating a module from a module object.
      31             : // It closes over the {Isolate}, the {ErrorThrower}, etc.
      32      305208 : class InstanceBuilder {
      33             :  public:
      34             :   InstanceBuilder(Isolate* isolate, ErrorThrower* thrower,
      35             :                   Handle<WasmModuleObject> module_object,
      36             :                   MaybeHandle<JSReceiver> ffi,
      37             :                   MaybeHandle<JSArrayBuffer> memory);
      38             : 
      39             :   // Build an instance, in all of its glory.
      40             :   MaybeHandle<WasmInstanceObject> Build();
      41             :   // Run the start function, if any.
      42             :   bool ExecuteStartFunction();
      43             : 
      44             :  private:
      45             :   // Represents the initialized state of a table.
      46             :   struct TableInstance {
      47             :     Handle<WasmTableObject> table_object;  // WebAssembly.Table instance
      48             :     Handle<FixedArray> js_wrappers;        // JSFunctions exported
      49             :     size_t table_size;
      50             :   };
      51             : 
      52             :   // A pre-evaluated value to use in import binding.
      53             :   struct SanitizedImport {
      54             :     Handle<String> module_name;
      55             :     Handle<String> import_name;
      56             :     Handle<Object> value;
      57             :   };
      58             : 
      59             :   Isolate* isolate_;
      60             :   const WasmFeatures enabled_;
      61             :   const WasmModule* const module_;
      62             :   ErrorThrower* thrower_;
      63             :   Handle<WasmModuleObject> module_object_;
      64             :   MaybeHandle<JSReceiver> ffi_;
      65             :   MaybeHandle<JSArrayBuffer> memory_;
      66             :   Handle<JSArrayBuffer> untagged_globals_;
      67             :   Handle<FixedArray> tagged_globals_;
      68             :   std::vector<TableInstance> table_instances_;
      69             :   std::vector<Handle<JSFunction>> js_wrappers_;
      70             :   std::vector<Handle<WasmExceptionObject>> exception_wrappers_;
      71             :   Handle<WasmExportedFunction> start_function_;
      72             :   JSToWasmWrapperCache js_to_wasm_cache_;
      73             :   std::vector<SanitizedImport> sanitized_imports_;
      74             : 
      75      288249 :   UseTrapHandler use_trap_handler() const {
      76      576498 :     return module_object_->native_module()->use_trap_handler() ? kUseTrapHandler
      77      576498 :                                                                : kNoTrapHandler;
      78             :   }
      79             : 
      80             : // Helper routines to print out errors with imports.
      81             : #define ERROR_THROWER_WITH_MESSAGE(TYPE)                                      \
      82             :   void Report##TYPE(const char* error, uint32_t index,                        \
      83             :                     Handle<String> module_name, Handle<String> import_name) { \
      84             :     thrower_->TYPE("Import #%d module=\"%s\" function=\"%s\" error: %s",      \
      85             :                    index, module_name->ToCString().get(),                     \
      86             :                    import_name->ToCString().get(), error);                    \
      87             :   }                                                                           \
      88             :                                                                               \
      89             :   MaybeHandle<Object> Report##TYPE(const char* error, uint32_t index,         \
      90             :                                    Handle<String> module_name) {              \
      91             :     thrower_->TYPE("Import #%d module=\"%s\" error: %s", index,               \
      92             :                    module_name->ToCString().get(), error);                    \
      93             :     return MaybeHandle<Object>();                                             \
      94             :   }
      95             : 
      96       11740 :   ERROR_THROWER_WITH_MESSAGE(LinkError)
      97        1584 :   ERROR_THROWER_WITH_MESSAGE(TypeError)
      98             : 
      99             : #undef ERROR_THROWER_WITH_MESSAGE
     100             : 
     101             :   // Look up an import value in the {ffi_} object.
     102             :   MaybeHandle<Object> LookupImport(uint32_t index, Handle<String> module_name,
     103             :                                    Handle<String> import_name);
     104             : 
     105             :   // Look up an import value in the {ffi_} object specifically for linking an
     106             :   // asm.js module. This only performs non-observable lookups, which allows
     107             :   // falling back to JavaScript proper (and hence re-executing all lookups) if
     108             :   // module instantiation fails.
     109             :   MaybeHandle<Object> LookupImportAsm(uint32_t index,
     110             :                                       Handle<String> import_name);
     111             : 
     112             :   uint32_t EvalUint32InitExpr(const WasmInitExpr& expr);
     113             : 
     114             :   // Load data segments into the memory.
     115             :   void LoadDataSegments(Handle<WasmInstanceObject> instance);
     116             : 
     117             :   void WriteGlobalValue(const WasmGlobal& global, double value);
     118             :   void WriteGlobalValue(const WasmGlobal& global,
     119             :                         Handle<WasmGlobalObject> value);
     120             : 
     121             :   void WriteGlobalAnyRef(const WasmGlobal& global, Handle<Object> value);
     122             : 
     123             :   void SanitizeImports();
     124             : 
     125             :   // Find the imported memory buffer if there is one. This is used to see if we
     126             :   // need to recompile with bounds checks before creating the instance.
     127             :   MaybeHandle<JSArrayBuffer> FindImportedMemoryBuffer() const;
     128             : 
     129             :   // Processes a single imported function.
     130             :   bool ProcessImportedFunction(Handle<WasmInstanceObject> instance,
     131             :                                int import_index, int func_index,
     132             :                                Handle<String> module_name,
     133             :                                Handle<String> import_name,
     134             :                                Handle<Object> value);
     135             : 
     136             :   // Process a single imported table.
     137             :   bool ProcessImportedTable(Handle<WasmInstanceObject> instance,
     138             :                             int import_index, int table_index,
     139             :                             Handle<String> module_name,
     140             :                             Handle<String> import_name, Handle<Object> value);
     141             : 
     142             :   // Process a single imported memory.
     143             :   bool ProcessImportedMemory(Handle<WasmInstanceObject> instance,
     144             :                              int import_index, Handle<String> module_name,
     145             :                              Handle<String> import_name, Handle<Object> value);
     146             : 
     147             :   // Process a single imported global.
     148             :   bool ProcessImportedGlobal(Handle<WasmInstanceObject> instance,
     149             :                              int import_index, int global_index,
     150             :                              Handle<String> module_name,
     151             :                              Handle<String> import_name, Handle<Object> value);
     152             : 
     153             :   // Process a single imported WasmGlobalObject.
     154             :   bool ProcessImportedWasmGlobalObject(Handle<WasmInstanceObject> instance,
     155             :                                        int import_index,
     156             :                                        Handle<String> module_name,
     157             :                                        Handle<String> import_name,
     158             :                                        const WasmGlobal& global,
     159             :                                        Handle<WasmGlobalObject> global_object);
     160             : 
     161             :   // Process the imports, including functions, tables, globals, and memory, in
     162             :   // order, loading them from the {ffi_} object. Returns the number of imported
     163             :   // functions.
     164             :   int ProcessImports(Handle<WasmInstanceObject> instance);
     165             : 
     166             :   template <typename T>
     167             :   T* GetRawGlobalPtr(const WasmGlobal& global);
     168             : 
     169             :   // Process initialization of globals.
     170             :   void InitGlobals();
     171             : 
     172             :   // Allocate memory for a module instance as a new JSArrayBuffer.
     173             :   Handle<JSArrayBuffer> AllocateMemory(uint32_t num_pages);
     174             : 
     175             :   bool NeedsWrappers() const;
     176             : 
     177             :   // Process the exports, creating wrappers for functions, tables, memories,
     178             :   // and globals.
     179             :   void ProcessExports(Handle<WasmInstanceObject> instance);
     180             : 
     181             :   void InitializeTables(Handle<WasmInstanceObject> instance);
     182             : 
     183             :   void LoadTableSegments(Handle<WasmInstanceObject> instance);
     184             : 
     185             :   // Creates new exception tags for all exceptions. Note that some tags might
     186             :   // already exist if they were imported, those tags will be re-used.
     187             :   void InitializeExceptions(Handle<WasmInstanceObject> instance);
     188             : };
     189             : 
     190      152589 : MaybeHandle<WasmInstanceObject> InstantiateToInstanceObject(
     191             :     Isolate* isolate, ErrorThrower* thrower,
     192             :     Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports,
     193             :     MaybeHandle<JSArrayBuffer> memory) {
     194      152589 :   InstanceBuilder builder(isolate, thrower, module_object, imports, memory);
     195      152604 :   auto instance = builder.Build();
     196      152604 :   if (!instance.is_null() && builder.ExecuteStartFunction()) {
     197      149520 :     return instance;
     198             :   }
     199             :   DCHECK(isolate->has_pending_exception() || thrower->error());
     200        3084 :   return {};
     201             : }
     202             : 
     203      152589 : InstanceBuilder::InstanceBuilder(Isolate* isolate, ErrorThrower* thrower,
     204             :                                  Handle<WasmModuleObject> module_object,
     205             :                                  MaybeHandle<JSReceiver> ffi,
     206             :                                  MaybeHandle<JSArrayBuffer> memory)
     207             :     : isolate_(isolate),
     208      305196 :       enabled_(module_object->native_module()->enabled_features()),
     209      305201 :       module_(module_object->module()),
     210             :       thrower_(thrower),
     211             :       module_object_(module_object),
     212             :       ffi_(ffi),
     213      610389 :       memory_(memory) {
     214      305198 :   sanitized_imports_.reserve(module_->import_table.size());
     215      152604 : }
     216             : 
     217             : // Build an instance, in all of its glory.
     218      152592 : MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
     219      305184 :   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), "InstanceBuilder::Build");
     220             :   // Check that an imports argument was provided, if the module requires it.
     221             :   // No point in continuing otherwise.
     222      441758 :   if (!module_->import_table.empty() && ffi_.is_null()) {
     223             :     thrower_->TypeError(
     224      302203 :         "Imports argument must be present and must be an object");
     225         106 :     return {};
     226             :   }
     227             : 
     228      152486 :   SanitizeImports();
     229      304996 :   if (thrower_->error()) return {};
     230             : 
     231             :   // TODO(6792): No longer needed once WebAssembly code is off heap.
     232      307749 :   CodeSpaceMemoryModificationScope modification_scope(isolate_->heap());
     233             :   // From here on, we expect the build pipeline to run without exiting to JS.
     234      304158 :   DisallowJavascriptExecution no_js(isolate_);
     235             :   // Record build time into correct bucket, then build instance.
     236      304160 :   TimedHistogramScope wasm_instantiate_module_time_scope(SELECT_WASM_COUNTER(
     237      304160 :       isolate_->counters(), module_->origin, wasm_instantiate, module_time));
     238             : 
     239             :   //--------------------------------------------------------------------------
     240             :   // Allocate the memory array buffer.
     241             :   //--------------------------------------------------------------------------
     242             :   // We allocate the memory buffer before cloning or reusing the compiled module
     243             :   // so we will know whether we need to recompile with bounds checks.
     244      152080 :   uint32_t initial_pages = module_->initial_pages;
     245      304160 :   auto initial_pages_counter = SELECT_WASM_COUNTER(
     246             :       isolate_->counters(), module_->origin, wasm, min_mem_pages_count);
     247      152080 :   initial_pages_counter->AddSample(initial_pages);
     248             :   // Asm.js has memory_ already set at this point, so we don't want to
     249             :   // overwrite it.
     250      152080 :   if (memory_.is_null()) {
     251      150689 :     memory_ = FindImportedMemoryBuffer();
     252             :   }
     253      152080 :   if (!memory_.is_null()) {
     254             :     // Set externally passed ArrayBuffer non detachable.
     255             :     Handle<JSArrayBuffer> memory = memory_.ToHandleChecked();
     256             :     memory->set_is_detachable(false);
     257             : 
     258             :     DCHECK_IMPLIES(use_trap_handler(), module_->origin == kAsmJsOrigin ||
     259             :                                            memory->is_wasm_memory() ||
     260             :                                            memory->backing_store() == nullptr);
     261      145972 :   } else if (initial_pages > 0 || use_trap_handler()) {
     262             :     // We need to unconditionally create a guard region if using trap handlers,
     263             :     // even when the size is zero to prevent null-dereference issues
     264             :     // (e.g. https://crbug.com/769637).
     265             :     // Allocate memory if the initial size is more than 0 pages.
     266      145910 :     memory_ = AllocateMemory(initial_pages);
     267      145910 :     if (memory_.is_null()) {
     268             :       // failed to allocate memory
     269             :       DCHECK(isolate_->has_pending_exception() || thrower_->error());
     270          18 :       return {};
     271             :     }
     272             :   }
     273             : 
     274             :   //--------------------------------------------------------------------------
     275             :   // Recompile module if using trap handlers but could not get guarded memory
     276             :   //--------------------------------------------------------------------------
     277      152062 :   if (module_->origin == kWasmOrigin && use_trap_handler()) {
     278             :     // Make sure the memory has suitable guard regions.
     279             :     WasmMemoryTracker* const memory_tracker =
     280      293104 :         isolate_->wasm_engine()->memory_tracker();
     281             : 
     282      146552 :     if (!memory_tracker->HasFullGuardRegions(
     283      146552 :             memory_.ToHandleChecked()->backing_store())) {
     284          43 :       if (!FLAG_wasm_trap_handler_fallback) {
     285             :         thrower_->LinkError(
     286             :             "Provided memory is lacking guard regions but fallback was "
     287           0 :             "disabled.");
     288           0 :         return {};
     289             :       }
     290             : 
     291             :       TRACE("Recompiling module without bounds checks\n");
     292          43 :       ErrorThrower thrower(isolate_, "recompile");
     293          43 :       auto native_module = module_object_->native_module();
     294             :       CompileNativeModuleWithExplicitBoundsChecks(isolate_, &thrower, module_,
     295          43 :                                                   native_module);
     296          43 :       if (thrower.error()) {
     297           0 :         return {};
     298             :       }
     299          43 :       DCHECK(!native_module->use_trap_handler());
     300             :     }
     301             :   }
     302             : 
     303             :   //--------------------------------------------------------------------------
     304             :   // Create the WebAssembly.Instance object.
     305             :   //--------------------------------------------------------------------------
     306      152062 :   NativeModule* native_module = module_object_->native_module();
     307             :   TRACE("New module instantiation for %p\n", native_module);
     308             :   Handle<WasmInstanceObject> instance =
     309      152062 :       WasmInstanceObject::New(isolate_, module_object_);
     310      304109 :   NativeModuleModificationScope native_modification_scope(native_module);
     311             : 
     312             :   //--------------------------------------------------------------------------
     313             :   // Set up the globals for the new instance.
     314             :   //--------------------------------------------------------------------------
     315      152058 :   uint32_t untagged_globals_buffer_size = module_->untagged_globals_buffer_size;
     316      152058 :   if (untagged_globals_buffer_size > 0) {
     317        3590 :     void* backing_store = isolate_->array_buffer_allocator()->Allocate(
     318        3590 :         untagged_globals_buffer_size);
     319        3590 :     if (backing_store == nullptr) {
     320           0 :       thrower_->RangeError("Out of memory: wasm globals");
     321           0 :       return {};
     322             :     }
     323             :     untagged_globals_ =
     324        3590 :         isolate_->factory()->NewJSArrayBuffer(SharedFlag::kNotShared, TENURED);
     325             :     constexpr bool is_external = false;
     326             :     constexpr bool is_wasm_memory = false;
     327             :     JSArrayBuffer::Setup(untagged_globals_, isolate_, is_external,
     328             :                          backing_store, untagged_globals_buffer_size,
     329        3590 :                          SharedFlag::kNotShared, is_wasm_memory);
     330        3590 :     if (untagged_globals_.is_null()) {
     331           0 :       thrower_->RangeError("Out of memory: wasm globals");
     332           0 :       return {};
     333             :     }
     334             :     instance->set_globals_start(
     335             :         reinterpret_cast<byte*>(untagged_globals_->backing_store()));
     336        3590 :     instance->set_untagged_globals_buffer(*untagged_globals_);
     337             :   }
     338             : 
     339      152058 :   uint32_t tagged_globals_buffer_size = module_->tagged_globals_buffer_size;
     340      152058 :   if (tagged_globals_buffer_size > 0) {
     341             :     tagged_globals_ = isolate_->factory()->NewFixedArray(
     342         117 :         static_cast<int>(tagged_globals_buffer_size));
     343         117 :     instance->set_tagged_globals_buffer(*tagged_globals_);
     344             :   }
     345             : 
     346             :   //--------------------------------------------------------------------------
     347             :   // Set up the array of references to imported globals' array buffers.
     348             :   //--------------------------------------------------------------------------
     349      152058 :   if (module_->num_imported_mutable_globals > 0) {
     350             :     // TODO(binji): This allocates one slot for each mutable global, which is
     351             :     // more than required if multiple globals are imported from the same
     352             :     // module.
     353             :     Handle<FixedArray> buffers_array = isolate_->factory()->NewFixedArray(
     354         207 :         module_->num_imported_mutable_globals, TENURED);
     355         207 :     instance->set_imported_mutable_globals_buffers(*buffers_array);
     356             :   }
     357             : 
     358             :   //--------------------------------------------------------------------------
     359             :   // Set up the exception table used for exception tag checks.
     360             :   //--------------------------------------------------------------------------
     361      304116 :   int exceptions_count = static_cast<int>(module_->exceptions.size());
     362      152058 :   if (exceptions_count > 0) {
     363             :     Handle<FixedArray> exception_table =
     364         423 :         isolate_->factory()->NewFixedArray(exceptions_count, TENURED);
     365         423 :     instance->set_exceptions_table(*exception_table);
     366         423 :     exception_wrappers_.resize(exceptions_count);
     367             :   }
     368             : 
     369             :   //--------------------------------------------------------------------------
     370             :   // Reserve the metadata for indirect function tables.
     371             :   //--------------------------------------------------------------------------
     372      304116 :   int table_count = static_cast<int>(module_->tables.size());
     373      154264 :   table_instances_.resize(table_count);
     374             : 
     375             :   //--------------------------------------------------------------------------
     376             :   // Process the imports for the module.
     377             :   //--------------------------------------------------------------------------
     378      152058 :   int num_imported_functions = ProcessImports(instance);
     379      152061 :   if (num_imported_functions < 0) return {};
     380             : 
     381             :   //--------------------------------------------------------------------------
     382             :   // Process the initialization for the module's globals.
     383             :   //--------------------------------------------------------------------------
     384      149903 :   InitGlobals();
     385             : 
     386             :   //--------------------------------------------------------------------------
     387             :   // Initialize the indirect tables.
     388             :   //--------------------------------------------------------------------------
     389      149900 :   if (table_count > 0) {
     390        2557 :     InitializeTables(instance);
     391             :   }
     392             : 
     393             :   //--------------------------------------------------------------------------
     394             :   // Initialize the exceptions table.
     395             :   //--------------------------------------------------------------------------
     396      149898 :   if (exceptions_count > 0) {
     397         378 :     InitializeExceptions(instance);
     398             :   }
     399             : 
     400             :   //--------------------------------------------------------------------------
     401             :   // Create the WebAssembly.Memory object.
     402             :   //--------------------------------------------------------------------------
     403      149898 :   if (module_->has_memory) {
     404       30039 :     if (!instance->has_memory_object()) {
     405             :       // No memory object exists. Create one.
     406             :       Handle<WasmMemoryObject> memory_object = WasmMemoryObject::New(
     407             :           isolate_, memory_,
     408       10409 :           module_->maximum_pages != 0 ? module_->maximum_pages : -1);
     409       10409 :       instance->set_memory_object(*memory_object);
     410             :     }
     411             : 
     412             :     // Add the instance object to the list of instances for this memory.
     413       45057 :     Handle<WasmMemoryObject> memory_object(instance->memory_object(), isolate_);
     414       15018 :     WasmMemoryObject::AddInstance(isolate_, memory_object, instance);
     415             : 
     416       15014 :     if (!memory_.is_null()) {
     417             :       // Double-check the {memory} array buffer matches the instance.
     418             :       Handle<JSArrayBuffer> memory = memory_.ToHandleChecked();
     419       15002 :       CHECK_EQ(instance->memory_size(), memory->byte_length());
     420       15003 :       CHECK_EQ(instance->memory_start(), memory->backing_store());
     421             :     }
     422             :   }
     423             : 
     424             :   //--------------------------------------------------------------------------
     425             :   // Check that indirect function table segments are within bounds.
     426             :   //--------------------------------------------------------------------------
     427      301902 :   for (const WasmElemSegment& elem_segment : module_->elem_segments) {
     428        2233 :     if (!elem_segment.active) continue;
     429             :     DCHECK(elem_segment.table_index < table_instances_.size());
     430        2206 :     uint32_t base = EvalUint32InitExpr(elem_segment.offset);
     431        4412 :     size_t table_size = table_instances_[elem_segment.table_index].table_size;
     432        6618 :     if (!IsInBounds(base, elem_segment.entries.size(), table_size)) {
     433         135 :       thrower_->LinkError("table initializer is out of bounds");
     434         135 :       return {};
     435             :     }
     436             :   }
     437             : 
     438             :   //--------------------------------------------------------------------------
     439             :   // Check that memory segments are within bounds.
     440             :   //--------------------------------------------------------------------------
     441      300521 :   for (const WasmDataSegment& seg : module_->data_segments) {
     442        1150 :     if (!seg.active) continue;
     443        1087 :     uint32_t base = EvalUint32InitExpr(seg.dest_addr);
     444        2174 :     if (!IsInBounds(base, seg.source.length(), instance->memory_size())) {
     445         163 :       thrower_->LinkError("data segment is out of bounds");
     446         163 :       return {};
     447             :     }
     448             :   }
     449             : 
     450             :   //--------------------------------------------------------------------------
     451             :   // Set up the exports object for the new instance.
     452             :   //--------------------------------------------------------------------------
     453      149604 :   ProcessExports(instance);
     454      299198 :   if (thrower_->error()) return {};
     455             : 
     456             :   //--------------------------------------------------------------------------
     457             :   // Initialize the indirect function tables.
     458             :   //--------------------------------------------------------------------------
     459      149599 :   if (table_count > 0) {
     460        2413 :     LoadTableSegments(instance);
     461             :   }
     462             : 
     463             :   //--------------------------------------------------------------------------
     464             :   // Initialize the memory by loading data segments.
     465             :   //--------------------------------------------------------------------------
     466      299200 :   if (module_->data_segments.size() > 0) {
     467         717 :     LoadDataSegments(instance);
     468             :   }
     469             : 
     470             :   //--------------------------------------------------------------------------
     471             :   // Debugging support.
     472             :   //--------------------------------------------------------------------------
     473             :   // Set all breakpoints that were set on the shared module.
     474      149600 :   WasmModuleObject::SetBreakpointsOnNewInstance(module_object_, instance);
     475             : 
     476      149593 :   if (FLAG_wasm_interpret_all && module_->origin == kWasmOrigin) {
     477             :     Handle<WasmDebugInfo> debug_info =
     478         842 :         WasmInstanceObject::GetOrCreateDebugInfo(instance);
     479             :     std::vector<int> func_indexes;
     480        4520 :     for (int func_index = num_imported_functions,
     481        7326 :              num_wasm_functions = static_cast<int>(module_->functions.size());
     482        1839 :          func_index < num_wasm_functions; ++func_index) {
     483         997 :       func_indexes.push_back(func_index);
     484             :     }
     485         842 :     WasmDebugInfo::RedirectToInterpreter(debug_info, VectorOf(func_indexes));
     486             :   }
     487             : 
     488             :   //--------------------------------------------------------------------------
     489             :   // Create a wrapper for the start function.
     490             :   //--------------------------------------------------------------------------
     491      149593 :   if (module_->start_function_index >= 0) {
     492             :     int start_index = module_->start_function_index;
     493        5642 :     auto& function = module_->functions[start_index];
     494             :     Handle<Code> wrapper_code = js_to_wasm_cache_.GetOrCompileJSToWasmWrapper(
     495       11284 :         isolate_, function.sig, function.imported);
     496             :     // TODO(clemensh): Don't generate an exported function for the start
     497             :     // function. Use CWasmEntry instead.
     498             :     start_function_ = WasmExportedFunction::New(
     499             :         isolate_, instance, MaybeHandle<String>(), start_index,
     500       11284 :         static_cast<int>(function.sig->parameter_count()), wrapper_code);
     501             :   }
     502             : 
     503             :   DCHECK(!isolate_->has_pending_exception());
     504             :   TRACE("Successfully built instance for module %p\n",
     505             :         module_object_->native_module());
     506      302197 :   return instance;
     507             : }
     508             : 
     509      149606 : bool InstanceBuilder::ExecuteStartFunction() {
     510      299212 :   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"),
     511             :                "InstanceBuilder::ExecuteStartFunction");
     512      149606 :   if (start_function_.is_null()) return true;  // No start function.
     513             : 
     514        5642 :   HandleScope scope(isolate_);
     515             :   // Call the JS function.
     516        5642 :   Handle<Object> undefined = isolate_->factory()->undefined_value();
     517             :   MaybeHandle<Object> retval =
     518        5642 :       Execution::Call(isolate_, start_function_, undefined, 0, nullptr);
     519             : 
     520        5642 :   if (retval.is_null()) {
     521             :     DCHECK(isolate_->has_pending_exception());
     522             :     return false;
     523             :   }
     524      155162 :   return true;
     525             : }
     526             : 
     527             : // Look up an import value in the {ffi_} object.
     528      137754 : MaybeHandle<Object> InstanceBuilder::LookupImport(uint32_t index,
     529             :                                                   Handle<String> module_name,
     530             : 
     531             :                                                   Handle<String> import_name) {
     532             :   // We pre-validated in the js-api layer that the ffi object is present, and
     533             :   // a JSObject, if the module has imports.
     534             :   DCHECK(!ffi_.is_null());
     535             : 
     536             :   // Look up the module first.
     537             :   MaybeHandle<Object> result = Object::GetPropertyOrElement(
     538      137754 :       isolate_, ffi_.ToHandleChecked(), module_name);
     539      137760 :   if (result.is_null()) {
     540          18 :     return ReportTypeError("module not found", index, module_name);
     541             :   }
     542             : 
     543             :   Handle<Object> module = result.ToHandleChecked();
     544             : 
     545             :   // Look up the value in the module.
     546      275480 :   if (!module->IsJSReceiver()) {
     547             :     return ReportTypeError("module is not an object or function", index,
     548         378 :                            module_name);
     549             :   }
     550             : 
     551      137358 :   result = Object::GetPropertyOrElement(isolate_, module, import_name);
     552      137369 :   if (result.is_null()) {
     553           0 :     ReportLinkError("import not found", index, module_name, import_name);
     554           0 :     return MaybeHandle<JSFunction>();
     555             :   }
     556             : 
     557      137369 :   return result;
     558             : }
     559             : 
     560             : // Look up an import value in the {ffi_} object specifically for linking an
     561             : // asm.js module. This only performs non-observable lookups, which allows
     562             : // falling back to JavaScript proper (and hence re-executing all lookups) if
     563             : // module instantiation fails.
     564        5307 : MaybeHandle<Object> InstanceBuilder::LookupImportAsm(
     565             :     uint32_t index, Handle<String> import_name) {
     566             :   // Check that a foreign function interface object was provided.
     567        5307 :   if (ffi_.is_null()) {
     568           0 :     return ReportLinkError("missing imports object", index, import_name);
     569             :   }
     570             : 
     571             :   // Perform lookup of the given {import_name} without causing any observable
     572             :   // side-effect. We only accept accesses that resolve to data properties,
     573             :   // which is indicated by the asm.js spec in section 7 ("Linking") as well.
     574             :   Handle<Object> result;
     575             :   LookupIterator it = LookupIterator::PropertyOrElement(
     576        5307 :       isolate_, ffi_.ToHandleChecked(), import_name);
     577        5307 :   switch (it.state()) {
     578             :     case LookupIterator::ACCESS_CHECK:
     579             :     case LookupIterator::INTEGER_INDEXED_EXOTIC:
     580             :     case LookupIterator::INTERCEPTOR:
     581             :     case LookupIterator::JSPROXY:
     582             :     case LookupIterator::ACCESSOR:
     583             :     case LookupIterator::TRANSITION:
     584          22 :       return ReportLinkError("not a data property", index, import_name);
     585             :     case LookupIterator::NOT_FOUND:
     586             :       // Accepting missing properties as undefined does not cause any
     587             :       // observable difference from JavaScript semantics, we are lenient.
     588          81 :       result = isolate_->factory()->undefined_value();
     589          81 :       break;
     590             :     case LookupIterator::DATA:
     591        5204 :       result = it.GetDataValue();
     592        5204 :       break;
     593             :   }
     594             : 
     595        5285 :   return result;
     596             : }
     597             : 
     598        6112 : uint32_t InstanceBuilder::EvalUint32InitExpr(const WasmInitExpr& expr) {
     599        6112 :   switch (expr.kind) {
     600             :     case WasmInitExpr::kI32Const:
     601        4573 :       return expr.val.i32_const;
     602             :     case WasmInitExpr::kGlobalIndex: {
     603        3078 :       uint32_t offset = module_->globals[expr.val.global_index].offset;
     604             :       return ReadLittleEndianValue<uint32_t>(
     605        4617 :           reinterpret_cast<Address>(raw_buffer_ptr(untagged_globals_, offset)));
     606             :     }
     607             :     default:
     608           0 :       UNREACHABLE();
     609             :   }
     610             : }
     611             : 
     612             : // Load data segments into the memory.
     613         717 : void InstanceBuilder::LoadDataSegments(Handle<WasmInstanceObject> instance) {
     614             :   Vector<const uint8_t> wire_bytes =
     615        1434 :       module_object_->native_module()->wire_bytes();
     616        2412 :   for (const WasmDataSegment& segment : module_->data_segments) {
     617        1744 :     uint32_t source_size = segment.source.length();
     618             :     // Segments of size == 0 are just nops.
     619         978 :     if (source_size == 0) continue;
     620             :     // Passive segments are not copied during instantiation.
     621         829 :     if (!segment.active) continue;
     622         766 :     uint32_t dest_offset = EvalUint32InitExpr(segment.dest_addr);
     623             :     DCHECK(IsInBounds(dest_offset, source_size, instance->memory_size()));
     624         766 :     byte* dest = instance->memory_start() + dest_offset;
     625         766 :     const byte* src = wire_bytes.start() + segment.source.offset();
     626         766 :     memcpy(dest, src, source_size);
     627             :   }
     628         717 : }
     629             : 
     630        4902 : void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global, double num) {
     631             :   TRACE("init [globals_start=%p + %u] = %lf, type = %s\n",
     632             :         reinterpret_cast<void*>(raw_buffer_ptr(untagged_globals_, 0)),
     633             :         global.offset, num, ValueTypes::TypeName(global.type));
     634        2451 :   switch (global.type) {
     635             :     case kWasmI32:
     636             :       WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global),
     637        1972 :                                       static_cast<int32_t>(num));
     638             :       break;
     639             :     case kWasmI64:
     640             :       WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global),
     641          27 :                                       static_cast<int64_t>(num));
     642             :       break;
     643             :     case kWasmF32:
     644             :       WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global),
     645          36 :                                     static_cast<float>(num));
     646             :       break;
     647             :     case kWasmF64:
     648             :       WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global),
     649             :                                      static_cast<double>(num));
     650             :       break;
     651             :     default:
     652           0 :       UNREACHABLE();
     653             :   }
     654        2451 : }
     655             : 
     656         108 : void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global,
     657             :                                        Handle<WasmGlobalObject> value) {
     658             :   TRACE("init [globals_start=%p + %u] = ",
     659             :         reinterpret_cast<void*>(raw_buffer_ptr(untagged_globals_, 0)),
     660             :         global.offset);
     661          54 :   switch (global.type) {
     662             :     case kWasmI32: {
     663          72 :       int32_t num = value->GetI32();
     664             :       WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global), num);
     665             :       TRACE("%d", num);
     666             :       break;
     667             :     }
     668             :     case kWasmI64: {
     669          18 :       int64_t num = value->GetI64();
     670             :       WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global), num);
     671             :       TRACE("%" PRId64, num);
     672             :       break;
     673             :     }
     674             :     case kWasmF32: {
     675          18 :       float num = value->GetF32();
     676             :       WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global), num);
     677             :       TRACE("%f", num);
     678             :       break;
     679             :     }
     680             :     case kWasmF64: {
     681           0 :       double num = value->GetF64();
     682             :       WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global), num);
     683             :       TRACE("%lf", num);
     684             :       break;
     685             :     }
     686             :     default:
     687           0 :       UNREACHABLE();
     688             :   }
     689             :   TRACE(", type = %s (from WebAssembly.Global)\n",
     690             :         ValueTypes::TypeName(global.type));
     691          54 : }
     692             : 
     693          54 : void InstanceBuilder::WriteGlobalAnyRef(const WasmGlobal& global,
     694             :                                         Handle<Object> value) {
     695         108 :   tagged_globals_->set(global.offset, *value, UPDATE_WRITE_BARRIER);
     696          54 : }
     697             : 
     698      152483 : void InstanceBuilder::SanitizeImports() {
     699             :   Vector<const uint8_t> wire_bytes =
     700      304969 :       module_object_->native_module()->wire_bytes();
     701      885414 :   for (size_t index = 0; index < module_->import_table.size(); ++index) {
     702      295138 :     const WasmImport& import = module_->import_table[index];
     703             : 
     704             :     Handle<String> module_name;
     705             :     MaybeHandle<String> maybe_module_name =
     706             :         WasmModuleObject::ExtractUtf8StringFromModuleBytes(isolate_, wire_bytes,
     707      143059 :                                                            import.module_name);
     708      143071 :     if (!maybe_module_name.ToHandle(&module_name)) {
     709             :       thrower_->LinkError("Could not resolve module name for import %zu",
     710      143072 :                           index);
     711           0 :       return;
     712             :     }
     713             : 
     714             :     Handle<String> import_name;
     715             :     MaybeHandle<String> maybe_import_name =
     716             :         WasmModuleObject::ExtractUtf8StringFromModuleBytes(isolate_, wire_bytes,
     717      143071 :                                                            import.field_name);
     718      143070 :     if (!maybe_import_name.ToHandle(&import_name)) {
     719             :       thrower_->LinkError("Could not resolve import name for import %zu",
     720           0 :                           index);
     721           0 :       return;
     722             :     }
     723             : 
     724             :     int int_index = static_cast<int>(index);
     725             :     MaybeHandle<Object> result =
     726      143070 :         module_->origin == kAsmJsOrigin
     727        5307 :             ? LookupImportAsm(int_index, import_name)
     728      148377 :             : LookupImport(int_index, module_name, import_name);
     729      286144 :     if (thrower_->error()) {
     730         418 :       thrower_->LinkError("Could not find value for import %zu", index);
     731         418 :       return;
     732             :     }
     733             :     Handle<Object> value = result.ToHandleChecked();
     734      285307 :     sanitized_imports_.push_back({module_name, import_name, value});
     735             :   }
     736             : }
     737             : 
     738      150689 : MaybeHandle<JSArrayBuffer> InstanceBuilder::FindImportedMemoryBuffer() const {
     739             :   DCHECK_EQ(module_->import_table.size(), sanitized_imports_.size());
     740      567356 :   for (size_t index = 0; index < module_->import_table.size(); index++) {
     741      283678 :     const WasmImport& import = module_->import_table[index];
     742             : 
     743      138156 :     if (import.kind == kExternalMemory) {
     744       10334 :       const auto& value = sanitized_imports_[index].value;
     745       10334 :       if (!value->IsWasmMemoryObject()) {
     746         450 :         return {};
     747             :       }
     748        4717 :       auto memory = Handle<WasmMemoryObject>::cast(value);
     749       14151 :       Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate_);
     750        4717 :       return buffer;
     751             :     }
     752             :   }
     753      145522 :   return {};
     754             : }
     755             : 
     756      132347 : bool InstanceBuilder::ProcessImportedFunction(
     757             :     Handle<WasmInstanceObject> instance, int import_index, int func_index,
     758             :     Handle<String> module_name, Handle<String> import_name,
     759             :     Handle<Object> value) {
     760             :   // Function imports must be callable.
     761      264694 :   if (!value->IsCallable()) {
     762             :     ReportLinkError("function import requires a callable", import_index,
     763         432 :                     module_name, import_name);
     764         432 :     return false;
     765             :   }
     766      131915 :   auto js_receiver = Handle<JSReceiver>::cast(value);
     767      263830 :   FunctionSig* expected_sig = module_->functions[func_index].sig;
     768             :   auto kind = compiler::GetWasmImportCallKind(js_receiver, expected_sig,
     769      131915 :                                               enabled_.bigint);
     770      131915 :   switch (kind) {
     771             :     case compiler::WasmImportCallKind::kLinkError:
     772             :       ReportLinkError("imported function does not match the expected type",
     773         180 :                       import_index, module_name, import_name);
     774         180 :       return false;
     775             :     case compiler::WasmImportCallKind::kWasmToWasm: {
     776             :       // The imported function is a WASM function from another instance.
     777      120519 :       auto imported_function = Handle<WasmExportedFunction>::cast(value);
     778             :       Handle<WasmInstanceObject> imported_instance(
     779      361557 :           imported_function->instance(), isolate_);
     780             :       // The import reference is the instance object itself.
     781      120519 :       Address imported_target = imported_function->GetWasmCallTarget();
     782             :       ImportedFunctionEntry entry(instance, func_index);
     783      120519 :       entry.SetWasmToWasm(*imported_instance, imported_target);
     784             :       break;
     785             :     }
     786             :     default: {
     787             :       // The imported function is a callable.
     788       11216 :       NativeModule* native_module = instance->module_object()->native_module();
     789       11216 :       WasmCode* wasm_code = native_module->import_wrapper_cache()->GetOrCompile(
     790       22432 :           isolate_->wasm_engine(), isolate_->counters(), kind, expected_sig);
     791             :       ImportedFunctionEntry entry(instance, func_index);
     792       11216 :       if (wasm_code->kind() == WasmCode::kWasmToJsWrapper) {
     793             :         // Wasm to JS wrappers are treated specially in the import table.
     794       10964 :         entry.SetWasmToJs(isolate_, js_receiver, wasm_code);
     795             :       } else {
     796             :         // Wasm math intrinsics are compiled as regular Wasm functions.
     797             :         DCHECK(kind >= compiler::WasmImportCallKind::kFirstMathIntrinsic &&
     798             :                kind <= compiler::WasmImportCallKind::kLastMathIntrinsic);
     799         252 :         entry.SetWasmToWasm(*instance, wasm_code->instruction_start());
     800             :       }
     801             :       break;
     802             :     }
     803             :   }
     804             :   return true;
     805             : }
     806             : 
     807        1665 : bool InstanceBuilder::ProcessImportedTable(Handle<WasmInstanceObject> instance,
     808             :                                            int import_index, int table_index,
     809             :                                            Handle<String> module_name,
     810             :                                            Handle<String> import_name,
     811             :                                            Handle<Object> value) {
     812        3330 :   if (!value->IsWasmTableObject()) {
     813             :     ReportLinkError("table import requires a WebAssembly.Table", import_index,
     814         387 :                     module_name, import_name);
     815         387 :     return false;
     816             :   }
     817        1278 :   const WasmTable& table = module_->tables[table_index];
     818        2439 :   TableInstance& table_instance = table_instances_[table_index];
     819        1278 :   table_instance.table_object = Handle<WasmTableObject>::cast(value);
     820        1278 :   instance->set_table_object(*table_instance.table_object);
     821             :   table_instance.js_wrappers =
     822        3834 :       Handle<FixedArray>(table_instance.table_object->functions(), isolate_);
     823             : 
     824             :   int imported_table_size = table_instance.js_wrappers->length();
     825        1278 :   if (imported_table_size < static_cast<int>(table.initial_size)) {
     826             :     thrower_->LinkError("table import %d is smaller than initial %d, got %u",
     827          45 :                         import_index, table.initial_size, imported_table_size);
     828          45 :     return false;
     829             :   }
     830             : 
     831        1233 :   if (table.has_maximum_size) {
     832             :     int64_t imported_maximum_size =
     833         909 :         table_instance.table_object->maximum_length()->Number();
     834         909 :     if (imported_maximum_size < 0) {
     835             :       thrower_->LinkError("table import %d has no maximum length, expected %d",
     836           0 :                           import_index, table.maximum_size);
     837           0 :       return false;
     838             :     }
     839         909 :     if (imported_maximum_size > table.maximum_size) {
     840             :       thrower_->LinkError("table import %d has a larger maximum size %" PRIx64
     841             :                           " than the module's declared maximum %u",
     842             :                           import_index, imported_maximum_size,
     843          72 :                           table.maximum_size);
     844          72 :       return false;
     845             :     }
     846             :   }
     847             : 
     848             :   // Allocate a new dispatch table.
     849        1161 :   if (!instance->has_indirect_function_table()) {
     850             :     WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
     851        1161 :         instance, imported_table_size);
     852        1161 :     table_instances_[table_index].table_size = imported_table_size;
     853             :   }
     854             :   // Initialize the dispatch table with the (foreign) JS functions
     855             :   // that are already in the table.
     856     2372787 :   for (int i = 0; i < imported_table_size; ++i) {
     857     2372787 :     Handle<Object> val(table_instance.js_wrappers->get(i), isolate_);
     858             :     // TODO(mtrofin): this is the same logic as WasmTableObject::Set:
     859             :     // insert in the local table a wrapper from the other module, and add
     860             :     // a reference to the owning instance of the other module.
     861     7115211 :     if (!val->IsJSFunction()) continue;
     862        3150 :     if (!WasmExportedFunction::IsWasmExportedFunction(*val)) {
     863             :       thrower_->LinkError("table import %d[%d] is not a wasm function",
     864           0 :                           import_index, i);
     865           0 :       return false;
     866             :     }
     867        3150 :     auto target_func = Handle<WasmExportedFunction>::cast(val);
     868             :     Handle<WasmInstanceObject> target_instance =
     869        9450 :         handle(target_func->instance(), isolate_);
     870             :     // Look up the signature's canonical id. If there is no canonical
     871             :     // id, then the signature does not appear at all in this module,
     872             :     // so putting {-1} in the table will cause checks to always fail.
     873        3150 :     FunctionSig* sig = target_func->sig();
     874             :     IndirectFunctionTableEntry(instance, i)
     875             :         .Set(module_->signature_map.Find(*sig), target_instance,
     876        6300 :              target_func->function_index());
     877             :   }
     878             :   return true;
     879             : }
     880             : 
     881        5150 : bool InstanceBuilder::ProcessImportedMemory(Handle<WasmInstanceObject> instance,
     882             :                                             int import_index,
     883             :                                             Handle<String> module_name,
     884             :                                             Handle<String> import_name,
     885             :                                             Handle<Object> value) {
     886             :   // Validation should have failed if more than one memory object was
     887             :   // provided.
     888             :   DCHECK(!instance->has_memory_object());
     889       10310 :   if (!value->IsWasmMemoryObject()) {
     890             :     ReportLinkError("memory import must be a WebAssembly.Memory object",
     891         441 :                     import_index, module_name, import_name);
     892         441 :     return false;
     893             :   }
     894        4717 :   auto memory = Handle<WasmMemoryObject>::cast(value);
     895        4717 :   instance->set_memory_object(*memory);
     896       14147 :   Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate_);
     897             :   // memory_ should have already been assigned in Build().
     898             :   DCHECK_EQ(*memory_.ToHandleChecked(), *buffer);
     899             :   uint32_t imported_cur_pages =
     900        4717 :       static_cast<uint32_t>(buffer->byte_length() / kWasmPageSize);
     901        4717 :   if (imported_cur_pages < module_->initial_pages) {
     902             :     thrower_->LinkError("memory import %d is smaller than initial %u, got %u",
     903             :                         import_index, module_->initial_pages,
     904          27 :                         imported_cur_pages);
     905          27 :     return false;
     906             :   }
     907             :   int32_t imported_maximum_pages = memory->maximum_pages();
     908        4690 :   if (module_->has_maximum_pages) {
     909        1370 :     if (imported_maximum_pages < 0) {
     910             :       thrower_->LinkError(
     911             :           "memory import %d has no maximum limit, expected at most %u",
     912           9 :           import_index, imported_maximum_pages);
     913           9 :       return false;
     914             :     }
     915        1361 :     if (static_cast<uint32_t>(imported_maximum_pages) >
     916             :         module_->maximum_pages) {
     917             :       thrower_->LinkError(
     918             :           "memory import %d has a larger maximum size %u than the "
     919             :           "module's declared maximum %u",
     920          45 :           import_index, imported_maximum_pages, module_->maximum_pages);
     921          45 :       return false;
     922             :     }
     923             :   }
     924        9272 :   if (module_->has_shared_memory != buffer->is_shared()) {
     925             :     thrower_->LinkError(
     926             :         "mismatch in shared state of memory, declared = %d, imported = %d",
     927          18 :         module_->has_shared_memory, buffer->is_shared());
     928          18 :     return false;
     929             :   }
     930             : 
     931             :   return true;
     932             : }
     933             : 
     934         333 : bool InstanceBuilder::ProcessImportedWasmGlobalObject(
     935             :     Handle<WasmInstanceObject> instance, int import_index,
     936             :     Handle<String> module_name, Handle<String> import_name,
     937             :     const WasmGlobal& global, Handle<WasmGlobalObject> global_object) {
     938         333 :   if (global_object->type() != global.type) {
     939             :     ReportLinkError("imported global does not match the expected type",
     940           9 :                     import_index, module_name, import_name);
     941           9 :     return false;
     942             :   }
     943         324 :   if (global_object->is_mutable() != global.mutability) {
     944             :     ReportLinkError("imported global does not match the expected mutability",
     945          36 :                     import_index, module_name, import_name);
     946          36 :     return false;
     947             :   }
     948         288 :   if (global.mutability) {
     949             :     DCHECK_LT(global.index, module_->num_imported_mutable_globals);
     950             :     Handle<Object> buffer;
     951             :     Address address_or_offset;
     952         234 :     if (global.type == kWasmAnyRef) {
     953             :       static_assert(sizeof(global_object->offset()) <= sizeof(Address),
     954             :                     "The offset into the globals buffer does not fit into "
     955             :                     "the imported_mutable_globals array");
     956         243 :       buffer = handle(global_object->tagged_buffer(), isolate_);
     957             :       // For anyref globals we use a relative offset, not an absolute address.
     958          81 :       address_or_offset = static_cast<Address>(global_object->offset());
     959             :     } else {
     960         459 :       buffer = handle(global_object->untagged_buffer(), isolate_);
     961             :       // It is safe in this case to store the raw pointer to the buffer
     962             :       // since the backing store of the JSArrayBuffer will not be
     963             :       // relocated.
     964             :       address_or_offset = reinterpret_cast<Address>(raw_buffer_ptr(
     965         306 :           Handle<JSArrayBuffer>::cast(buffer), global_object->offset()));
     966             :     }
     967         468 :     instance->imported_mutable_globals_buffers()->set(global.index, *buffer);
     968         234 :     instance->imported_mutable_globals()[global.index] = address_or_offset;
     969             :     return true;
     970             :   }
     971             : 
     972          54 :   WriteGlobalValue(global, global_object);
     973          54 :   return true;
     974             : }
     975             : 
     976        3250 : bool InstanceBuilder::ProcessImportedGlobal(Handle<WasmInstanceObject> instance,
     977             :                                             int import_index, int global_index,
     978             :                                             Handle<String> module_name,
     979             :                                             Handle<String> import_name,
     980             :                                             Handle<Object> value) {
     981             :   // Immutable global imports are converted to numbers and written into
     982             :   // the {untagged_globals_} array buffer.
     983             :   //
     984             :   // Mutable global imports instead have their backing array buffers
     985             :   // referenced by this instance, and store the address of the imported
     986             :   // global in the {imported_mutable_globals_} array.
     987        3250 :   const WasmGlobal& global = module_->globals[global_index];
     988             : 
     989             :   // The mutable-global proposal allows importing i64 values, but only if
     990             :   // they are passed as a WebAssembly.Global object.
     991             :   //
     992             :   // However, the bigint proposal allows importing constant i64 values,
     993             :   // as non WebAssembly.Global object.
     994        9750 :   if (global.type == kWasmI64 && !enabled_.bigint &&
     995        3358 :       !value->IsWasmGlobalObject()) {
     996             :     ReportLinkError("global import cannot have type i64", import_index,
     997          36 :                     module_name, import_name);
     998          36 :     return false;
     999             :   }
    1000        3214 :   if (module_->origin == kAsmJsOrigin) {
    1001             :     // Accepting {JSFunction} on top of just primitive values here is a
    1002             :     // workaround to support legacy asm.js code with broken binding. Note
    1003             :     // that using {NaN} (or Smi::kZero) here is what using the observable
    1004             :     // conversion via {ToPrimitive} would produce as well.
    1005             :     // TODO(mstarzinger): Still observable if Function.prototype.valueOf
    1006             :     // or friends are patched, we might need to check for that as well.
    1007        2702 :     if (value->IsJSFunction()) value = isolate_->factory()->nan_value();
    1008        5382 :     if (value->IsPrimitive() && !value->IsSymbol()) {
    1009        1335 :       if (global.type == kWasmI32) {
    1010        1910 :         value = Object::ToInt32(isolate_, value).ToHandleChecked();
    1011             :       } else {
    1012         760 :         value = Object::ToNumber(isolate_, value).ToHandleChecked();
    1013             :       }
    1014             :     }
    1015             :   }
    1016             : 
    1017        6428 :   if (value->IsWasmGlobalObject()) {
    1018         333 :     auto global_object = Handle<WasmGlobalObject>::cast(value);
    1019             :     return ProcessImportedWasmGlobalObject(instance, import_index, module_name,
    1020         333 :                                            import_name, global, global_object);
    1021             :   }
    1022             : 
    1023        2881 :   if (global.mutability) {
    1024             :     ReportLinkError(
    1025             :         "imported mutable global must be a WebAssembly.Global object",
    1026          18 :         import_index, module_name, import_name);
    1027          18 :     return false;
    1028             :   }
    1029             : 
    1030        2863 :   if (global.type == ValueType::kWasmAnyRef) {
    1031          54 :     WriteGlobalAnyRef(global, value);
    1032          54 :     return true;
    1033             :   }
    1034             : 
    1035        5618 :   if (value->IsNumber()) {
    1036        2424 :     WriteGlobalValue(global, value->Number());
    1037        2424 :     return true;
    1038             :   }
    1039             : 
    1040         385 :   if (enabled_.bigint && global.type == kWasmI64) {
    1041             :     Handle<BigInt> bigint;
    1042             : 
    1043          54 :     if (!BigInt::FromObject(isolate_, value).ToHandle(&bigint)) {
    1044             :       return false;
    1045             :     }
    1046          27 :     WriteGlobalValue(global, bigint->AsInt64());
    1047          27 :     return true;
    1048             :   }
    1049             : 
    1050             :   ReportLinkError("global import must be a number or WebAssembly.Global object",
    1051         358 :                   import_index, module_name, import_name);
    1052         358 :   return false;
    1053             : }
    1054             : 
    1055             : // Process the imports, including functions, tables, globals, and memory, in
    1056             : // order, loading them from the {ffi_} object. Returns the number of imported
    1057             : // functions.
    1058      152055 : int InstanceBuilder::ProcessImports(Handle<WasmInstanceObject> instance) {
    1059             :   int num_imported_functions = 0;
    1060             :   int num_imported_tables = 0;
    1061             : 
    1062             :   DCHECK_EQ(module_->import_table.size(), sanitized_imports_.size());
    1063      446622 :   int num_imports = static_cast<int>(module_->import_table.size());
    1064      584832 :   for (int index = 0; index < num_imports; ++index) {
    1065      142512 :     const WasmImport& import = module_->import_table[index];
    1066             : 
    1067      285024 :     Handle<String> module_name = sanitized_imports_[index].module_name;
    1068      142512 :     Handle<String> import_name = sanitized_imports_[index].import_name;
    1069      142512 :     Handle<Object> value = sanitized_imports_[index].value;
    1070             : 
    1071      142512 :     switch (import.kind) {
    1072             :       case kExternalFunction: {
    1073      132347 :         uint32_t func_index = import.index;
    1074             :         DCHECK_EQ(num_imported_functions, func_index);
    1075      132347 :         if (!ProcessImportedFunction(instance, index, func_index, module_name,
    1076      132347 :                                      import_name, value)) {
    1077        2158 :           return -1;
    1078             :         }
    1079      131735 :         num_imported_functions++;
    1080      131735 :         break;
    1081             :       }
    1082             :       case kExternalTable: {
    1083        1665 :         uint32_t table_index = import.index;
    1084             :         DCHECK_EQ(table_index, num_imported_tables);
    1085        1665 :         if (!ProcessImportedTable(instance, index, table_index, module_name,
    1086        1665 :                                   import_name, value)) {
    1087             :           return -1;
    1088             :         }
    1089             :         num_imported_tables++;
    1090             :         break;
    1091             :       }
    1092             :       case kExternalMemory: {
    1093        5158 :         if (!ProcessImportedMemory(instance, index, module_name, import_name,
    1094        5151 :                                    value)) {
    1095             :           return -1;
    1096             :         }
    1097             :         break;
    1098             :       }
    1099             :       case kExternalGlobal: {
    1100        3250 :         if (!ProcessImportedGlobal(instance, index, import.index, module_name,
    1101        3250 :                                    import_name, value)) {
    1102             :           return -1;
    1103             :         }
    1104             :         break;
    1105             :       }
    1106             :       case kExternalException: {
    1107         198 :         if (!value->IsWasmExceptionObject()) {
    1108             :           ReportLinkError("exception import requires a WebAssembly.Exception",
    1109          36 :                           index, module_name, import_name);
    1110          36 :           return -1;
    1111             :         }
    1112             :         Handle<WasmExceptionObject> imported_exception =
    1113          63 :             Handle<WasmExceptionObject>::cast(value);
    1114          63 :         if (!imported_exception->IsSignatureEqual(
    1115         189 :                 module_->exceptions[import.index].sig)) {
    1116             :           ReportLinkError("imported exception does not match the expected type",
    1117           9 :                           index, module_name, import_name);
    1118           9 :           return -1;
    1119             :         }
    1120          54 :         Object exception_tag = imported_exception->exception_tag();
    1121             :         DCHECK(instance->exceptions_table()->get(import.index)->IsUndefined());
    1122         108 :         instance->exceptions_table()->set(import.index, exception_tag);
    1123         108 :         exception_wrappers_[import.index] = imported_exception;
    1124          54 :         break;
    1125             :       }
    1126             :       default:
    1127           0 :         UNREACHABLE();
    1128             :         break;
    1129             :     }
    1130             :   }
    1131             :   return num_imported_functions;
    1132             : }
    1133             : 
    1134             : template <typename T>
    1135             : T* InstanceBuilder::GetRawGlobalPtr(const WasmGlobal& global) {
    1136       18256 :   return reinterpret_cast<T*>(raw_buffer_ptr(untagged_globals_, global.offset));
    1137             : }
    1138             : 
    1139             : // Process initialization of globals.
    1140      149900 : void InstanceBuilder::InitGlobals() {
    1141      309405 :   for (auto global : module_->globals) {
    1142        9605 :     if (global.mutability && global.imported) {
    1143             :       continue;
    1144             :     }
    1145             : 
    1146        9371 :     switch (global.init.kind) {
    1147             :       case WasmInitExpr::kI32Const:
    1148             :         WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global),
    1149        5355 :                                         global.init.val.i32_const);
    1150             :         break;
    1151             :       case WasmInitExpr::kI64Const:
    1152             :         WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global),
    1153          99 :                                         global.init.val.i64_const);
    1154             :         break;
    1155             :       case WasmInitExpr::kF32Const:
    1156             :         WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global),
    1157         208 :                                       global.init.val.f32_const);
    1158             :         break;
    1159             :       case WasmInitExpr::kF64Const:
    1160             :         WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global),
    1161         961 :                                        global.init.val.f64_const);
    1162             :         break;
    1163             :       case WasmInitExpr::kAnyRefConst:
    1164             :         DCHECK(enabled_.anyref);
    1165         126 :         if (global.imported) break;  // We already initialized imported globals.
    1166             : 
    1167             :         tagged_globals_->set(global.offset,
    1168         126 :                              ReadOnlyRoots(isolate_).null_value(),
    1169         252 :                              SKIP_WRITE_BARRIER);
    1170         126 :         break;
    1171             :       case WasmInitExpr::kGlobalIndex: {
    1172          63 :         if (global.type == ValueType::kWasmAnyRef) {
    1173             :           DCHECK(enabled_.anyref);
    1174             :           int other_offset =
    1175          63 :               module_->globals[global.init.val.global_index].offset;
    1176             : 
    1177             :           tagged_globals_->set(global.offset,
    1178             :                                tagged_globals_->get(other_offset),
    1179           0 :                                SKIP_WRITE_BARRIER);
    1180             :         }
    1181             :         // Initialize with another global.
    1182             :         uint32_t new_offset = global.offset;
    1183             :         uint32_t old_offset =
    1184         126 :             module_->globals[global.init.val.global_index].offset;
    1185             :         TRACE("init [globals+%u] = [globals+%d]\n", global.offset, old_offset);
    1186          63 :         size_t size = (global.type == kWasmI64 || global.type == kWasmF64)
    1187             :                           ? sizeof(double)
    1188          63 :                           : sizeof(int32_t);
    1189         189 :         memcpy(raw_buffer_ptr(untagged_globals_, new_offset),
    1190         189 :                raw_buffer_ptr(untagged_globals_, old_offset), size);
    1191          63 :         break;
    1192             :       }
    1193             :       case WasmInitExpr::kNone:
    1194             :         // Happens with imported globals.
    1195             :         break;
    1196             :       default:
    1197           0 :         UNREACHABLE();
    1198             :         break;
    1199             :     }
    1200             :   }
    1201      149900 : }
    1202             : 
    1203             : // Allocate memory for a module instance as a new JSArrayBuffer.
    1204      145910 : Handle<JSArrayBuffer> InstanceBuilder::AllocateMemory(uint32_t num_pages) {
    1205      145910 :   if (num_pages > max_mem_pages()) {
    1206          18 :     thrower_->RangeError("Out of memory: wasm memory too large");
    1207             :     return Handle<JSArrayBuffer>::null();
    1208             :   }
    1209      145892 :   const bool is_shared_memory = module_->has_shared_memory && enabled_.threads;
    1210             :   SharedFlag shared_flag =
    1211      145892 :       is_shared_memory ? SharedFlag::kShared : SharedFlag::kNotShared;
    1212             :   Handle<JSArrayBuffer> mem_buffer;
    1213      291784 :   if (!NewArrayBuffer(isolate_, num_pages * kWasmPageSize, shared_flag)
    1214      291784 :            .ToHandle(&mem_buffer)) {
    1215           0 :     thrower_->RangeError("Out of memory: wasm memory");
    1216             :   }
    1217      145892 :   return mem_buffer;
    1218             : }
    1219             : 
    1220      149595 : bool InstanceBuilder::NeedsWrappers() const {
    1221      149595 :   if (module_->num_exported_functions > 0) return true;
    1222        9794 :   for (auto& table_instance : table_instances_) {
    1223         810 :     if (!table_instance.js_wrappers.is_null()) return true;
    1224             :   }
    1225        8678 :   for (auto& table : module_->tables) {
    1226         396 :     if (table.exported) return true;
    1227             :   }
    1228             :   return false;
    1229             : }
    1230             : 
    1231             : // Process the exports, creating wrappers for functions, tables, memories,
    1232             : // globals, and exceptions.
    1233      149598 : void InstanceBuilder::ProcessExports(Handle<WasmInstanceObject> instance) {
    1234             :   Handle<FixedArray> export_wrappers(module_object_->export_wrappers(),
    1235      448801 :                                      isolate_);
    1236      149599 :   if (NeedsWrappers()) {
    1237             :     // Fill the table to cache the exported JSFunction wrappers.
    1238             :     js_wrappers_.insert(js_wrappers_.begin(), module_->functions.size(),
    1239     1315480 :                         Handle<JSFunction>::null());
    1240             : 
    1241             :     // If an imported WebAssembly function gets exported, the exported function
    1242             :     // has to be identical to to imported function. Therefore we put all
    1243             :     // imported WebAssembly functions into the js_wrappers_ list.
    1244      569863 :     for (int index = 0, end = static_cast<int>(module_->import_table.size());
    1245             :          index < end; ++index) {
    1246      139322 :       const WasmImport& import = module_->import_table[index];
    1247      139322 :       if (import.kind == kExternalFunction) {
    1248      262840 :         Handle<Object> value = sanitized_imports_[index].value;
    1249      131420 :         if (WasmExportedFunction::IsWasmExportedFunction(*value)) {
    1250      240804 :           js_wrappers_[import.index] = Handle<JSFunction>::cast(value);
    1251             :         }
    1252             :       }
    1253             :     }
    1254             :   }
    1255             : 
    1256             :   Handle<JSObject> exports_object;
    1257             :   bool is_asm_js = false;
    1258      149600 :   switch (module_->origin) {
    1259             :     case kWasmOrigin: {
    1260             :       // Create the "exports" object.
    1261      144165 :       exports_object = isolate_->factory()->NewJSObjectWithNullProto();
    1262      144167 :       break;
    1263             :     }
    1264             :     case kAsmJsOrigin: {
    1265             :       Handle<JSFunction> object_function = Handle<JSFunction>(
    1266       16305 :           isolate_->native_context()->object_function(), isolate_);
    1267        5435 :       exports_object = isolate_->factory()->NewJSObject(object_function);
    1268             :       is_asm_js = true;
    1269             :       break;
    1270             :     }
    1271             :     default:
    1272           0 :       UNREACHABLE();
    1273             :   }
    1274      149603 :   instance->set_exports_object(*exports_object);
    1275             : 
    1276             :   Handle<String> single_function_name =
    1277      149604 :       isolate_->factory()->InternalizeUtf8String(AsmJs::kSingleFunctionName);
    1278             : 
    1279             :   PropertyDescriptor desc;
    1280             :   desc.set_writable(is_asm_js);
    1281             :   desc.set_enumerable(true);
    1282             :   desc.set_configurable(is_asm_js);
    1283             : 
    1284             :   // Process each export in the export table.
    1285             :   int export_index = 0;  // Index into {export_wrappers}.
    1286      555134 :   for (const WasmExport& exp : module_->export_table) {
    1287             :     Handle<String> name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
    1288      255943 :                               isolate_, module_object_, exp.name)
    1289      511882 :                               .ToHandleChecked();
    1290             :     Handle<JSObject> export_to;
    1291      265164 :     if (is_asm_js && exp.kind == kExternalFunction &&
    1292        9225 :         String::Equals(isolate_, name, single_function_name)) {
    1293             :       export_to = instance;
    1294             :     } else {
    1295             :       export_to = exports_object;
    1296             :     }
    1297             : 
    1298      255939 :     switch (exp.kind) {
    1299             :       case kExternalFunction: {
    1300             :         // Wrap and export the code as a JSFunction.
    1301      252858 :         const WasmFunction& function = module_->functions[exp.index];
    1302      252858 :         Handle<JSFunction> js_function = js_wrappers_[exp.index];
    1303      252858 :         if (js_function.is_null()) {
    1304             :           // Wrap the exported code as a JSFunction.
    1305             :           Handle<Code> export_code =
    1306      505090 :               export_wrappers->GetValueChecked<Code>(isolate_, export_index);
    1307      252552 :           MaybeHandle<String> func_name;
    1308      252552 :           if (is_asm_js) {
    1309             :             // For modules arising from asm.js, honor the names section.
    1310             :             WireBytesRef func_name_ref = module_->LookupFunctionName(
    1311             :                 ModuleWireBytes(module_object_->native_module()->wire_bytes()),
    1312       27603 :                 function.func_index);
    1313             :             func_name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
    1314        9201 :                             isolate_, module_object_, func_name_ref)
    1315       18402 :                             .ToHandleChecked();
    1316             :           }
    1317             :           js_function = WasmExportedFunction::New(
    1318             :               isolate_, instance, func_name, function.func_index,
    1319      252552 :               static_cast<int>(function.sig->parameter_count()), export_code);
    1320      505106 :           js_wrappers_[exp.index] = js_function;
    1321             :         }
    1322             :         desc.set_value(js_function);
    1323      252865 :         export_index++;
    1324             :         break;
    1325             :       }
    1326             :       case kExternalTable: {
    1327             :         // Export a table as a WebAssembly.Table object.
    1328         513 :         TableInstance& table_instance = table_instances_[exp.index];
    1329         513 :         const WasmTable& table = module_->tables[exp.index];
    1330         513 :         if (table_instance.table_object.is_null()) {
    1331             :           uint32_t maximum = table.has_maximum_size ? table.maximum_size
    1332         459 :                                                     : FLAG_wasm_max_table_size;
    1333             :           table_instance.table_object =
    1334             :               WasmTableObject::New(isolate_, table.initial_size, maximum,
    1335         459 :                                    &table_instance.js_wrappers);
    1336             :         }
    1337         513 :         instance->set_table_object(*table_instance.table_object);
    1338             :         desc.set_value(table_instance.table_object);
    1339         513 :         break;
    1340             :       }
    1341             :       case kExternalMemory: {
    1342             :         // Export the memory as a WebAssembly.Memory object. A WasmMemoryObject
    1343             :         // should already be available if the module has memory, since we always
    1344             :         // create or import it when building an WasmInstanceObject.
    1345             :         DCHECK(instance->has_memory_object());
    1346             :         desc.set_value(
    1347        5382 :             Handle<WasmMemoryObject>(instance->memory_object(), isolate_));
    1348        1794 :         break;
    1349             :       }
    1350             :       case kExternalGlobal: {
    1351         648 :         const WasmGlobal& global = module_->globals[exp.index];
    1352             :         Handle<JSArrayBuffer> untagged_buffer;
    1353             :         Handle<FixedArray> tagged_buffer;
    1354             :         uint32_t offset;
    1355             : 
    1356         648 :         if (global.mutability && global.imported) {
    1357             :           Handle<FixedArray> buffers_array(
    1358         189 :               instance->imported_mutable_globals_buffers(), isolate_);
    1359          63 :           if (global.type == kWasmAnyRef) {
    1360             :             tagged_buffer = buffers_array->GetValueChecked<FixedArray>(
    1361          54 :                 isolate_, global.index);
    1362             :             // For anyref globals we store the relative offset in the
    1363             :             // imported_mutable_globals array instead of an absolute address.
    1364          27 :             Address addr = instance->imported_mutable_globals()[global.index];
    1365             :             DCHECK_LE(addr, static_cast<Address>(
    1366             :                                 std::numeric_limits<uint32_t>::max()));
    1367          27 :             offset = static_cast<uint32_t>(addr);
    1368             :           } else {
    1369             :             untagged_buffer = buffers_array->GetValueChecked<JSArrayBuffer>(
    1370          72 :                 isolate_, global.index);
    1371             :             Address global_addr =
    1372          36 :                 instance->imported_mutable_globals()[global.index];
    1373             : 
    1374             :             size_t buffer_size = untagged_buffer->byte_length();
    1375             :             Address backing_store =
    1376          36 :                 reinterpret_cast<Address>(untagged_buffer->backing_store());
    1377          36 :             CHECK(global_addr >= backing_store &&
    1378             :                   global_addr < backing_store + buffer_size);
    1379          36 :             offset = static_cast<uint32_t>(global_addr - backing_store);
    1380             :           }
    1381             :         } else {
    1382         585 :           if (global.type == kWasmAnyRef) {
    1383         135 :             tagged_buffer = handle(instance->tagged_globals_buffer(), isolate_);
    1384             :           } else {
    1385             :             untagged_buffer =
    1386        1620 :                 handle(instance->untagged_globals_buffer(), isolate_);
    1387             :           }
    1388         585 :           offset = global.offset;
    1389             :         }
    1390             : 
    1391             :         // Since the global's array untagged_buffer is always provided,
    1392             :         // allocation should never fail.
    1393             :         Handle<WasmGlobalObject> global_obj =
    1394             :             WasmGlobalObject::New(isolate_, untagged_buffer, tagged_buffer,
    1395        1944 :                                   global.type, offset, global.mutability)
    1396        1296 :                 .ToHandleChecked();
    1397             :         desc.set_value(global_obj);
    1398             :         break;
    1399             :       }
    1400             :       case kExternalException: {
    1401         126 :         const WasmException& exception = module_->exceptions[exp.index];
    1402         360 :         Handle<WasmExceptionObject> wrapper = exception_wrappers_[exp.index];
    1403         126 :         if (wrapper.is_null()) {
    1404             :           Handle<HeapObject> exception_tag(
    1405         216 :               HeapObject::cast(instance->exceptions_table()->get(exp.index)),
    1406         324 :               isolate_);
    1407             :           wrapper =
    1408         108 :               WasmExceptionObject::New(isolate_, exception.sig, exception_tag);
    1409         216 :           exception_wrappers_[exp.index] = wrapper;
    1410             :         }
    1411             :         desc.set_value(wrapper);
    1412             :         break;
    1413             :       }
    1414             :       default:
    1415           0 :         UNREACHABLE();
    1416             :         break;
    1417             :     }
    1418             : 
    1419             :     v8::Maybe<bool> status = JSReceiver::DefineOwnProperty(
    1420      255946 :         isolate_, export_to, name, &desc, kThrowOnError);
    1421      255934 :     if (!status.IsJust()) {
    1422             :       DisallowHeapAllocation no_gc;
    1423           0 :       TruncatedUserString<> trunc_name(name->GetCharVector<uint8_t>(no_gc));
    1424             :       thrower_->LinkError("export of %.*s failed.", trunc_name.length(),
    1425           0 :                           trunc_name.start());
    1426      149597 :       return;
    1427             :     }
    1428             :   }
    1429             :   DCHECK_EQ(export_index, export_wrappers->length());
    1430             : 
    1431      149591 :   if (module_->origin == kWasmOrigin) {
    1432             :     v8::Maybe<bool> success =
    1433      144156 :         JSReceiver::SetIntegrityLevel(exports_object, FROZEN, kDontThrow);
    1434             :     DCHECK(success.FromMaybe(false));
    1435             :     USE(success);
    1436             :   }
    1437             : }
    1438             : 
    1439        2557 : void InstanceBuilder::InitializeTables(Handle<WasmInstanceObject> instance) {
    1440        5114 :   size_t table_count = module_->tables.size();
    1441        5114 :   for (size_t index = 0; index < table_count; ++index) {
    1442        2557 :     const WasmTable& table = module_->tables[index];
    1443        2557 :     TableInstance& table_instance = table_instances_[index];
    1444             : 
    1445        3971 :     if (!instance->has_indirect_function_table() &&
    1446        1414 :         table.type == kWasmAnyFunc) {
    1447             :       WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
    1448        1414 :           instance, table.initial_size);
    1449        1414 :       table_instance.table_size = table.initial_size;
    1450             :     }
    1451             :   }
    1452        2557 : }
    1453             : 
    1454        2413 : void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
    1455        2413 :   NativeModule* native_module = module_object_->native_module();
    1456        6906 :   for (auto& elem_segment : module_->elem_segments) {
    1457             :     // Passive segments are not copied during instantiation.
    1458        2080 :     if (!elem_segment.active) continue;
    1459             : 
    1460        2053 :     uint32_t base = EvalUint32InitExpr(elem_segment.offset);
    1461       14175 :     uint32_t num_entries = static_cast<uint32_t>(elem_segment.entries.size());
    1462        2053 :     uint32_t index = elem_segment.table_index;
    1463        4466 :     TableInstance& table_instance = table_instances_[index];
    1464             :     DCHECK(IsInBounds(base, num_entries, table_instance.table_size));
    1465       12122 :     for (uint32_t i = 0; i < num_entries; ++i) {
    1466       20138 :       uint32_t func_index = elem_segment.entries[i];
    1467       10069 :       const WasmFunction* function = &module_->functions[func_index];
    1468       10069 :       int table_index = static_cast<int>(i + base);
    1469             : 
    1470             :       // Update the local dispatch table first.
    1471       20138 :       uint32_t sig_id = module_->signature_ids[function->sig_index];
    1472             :       IndirectFunctionTableEntry(instance, table_index)
    1473       20138 :           .Set(sig_id, instance, func_index);
    1474             : 
    1475       10069 :       if (!table_instance.table_object.is_null()) {
    1476             :         // Update the table object's other dispatch tables.
    1477        7371 :         if (js_wrappers_[func_index].is_null()) {
    1478             :           // No JSFunction entry yet exists for this function. Create one.
    1479             :           // TODO(titzer): We compile JS->wasm wrappers for functions are
    1480             :           // not exported but are in an exported table. This should be done
    1481             :           // at module compile time and cached instead.
    1482             : 
    1483             :           Handle<Code> wrapper_code =
    1484             :               js_to_wasm_cache_.GetOrCompileJSToWasmWrapper(
    1485        3132 :                   isolate_, function->sig, function->imported);
    1486        1566 :           MaybeHandle<String> func_name;
    1487        1566 :           if (module_->origin == kAsmJsOrigin) {
    1488             :             // For modules arising from asm.js, honor the names section.
    1489             :             WireBytesRef func_name_ref = module_->LookupFunctionName(
    1490           0 :                 ModuleWireBytes(native_module->wire_bytes()), func_index);
    1491             :             func_name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
    1492           0 :                             isolate_, module_object_, func_name_ref)
    1493           0 :                             .ToHandleChecked();
    1494             :           }
    1495             :           Handle<WasmExportedFunction> js_function = WasmExportedFunction::New(
    1496             :               isolate_, instance, func_name, func_index,
    1497        3132 :               static_cast<int>(function->sig->parameter_count()), wrapper_code);
    1498        1566 :           js_wrappers_[func_index] = js_function;
    1499             :         }
    1500        3870 :         table_instance.js_wrappers->set(table_index, *js_wrappers_[func_index]);
    1501             :         // UpdateDispatchTables() updates all other dispatch tables, since
    1502             :         // we have not yet added the dispatch table we are currently building.
    1503             :         WasmTableObject::UpdateDispatchTables(
    1504             :             isolate_, table_instance.table_object, table_index, function->sig,
    1505        1935 :             instance, func_index);
    1506             :       }
    1507             :     }
    1508             :   }
    1509             : 
    1510        4826 :   int table_count = static_cast<int>(module_->tables.size());
    1511        4826 :   for (int index = 0; index < table_count; ++index) {
    1512        2413 :     TableInstance& table_instance = table_instances_[index];
    1513             : 
    1514             :     // Add the new dispatch table at the end to avoid redundant lookups.
    1515        2413 :     if (!table_instance.table_object.is_null()) {
    1516             :       WasmTableObject::AddDispatchTable(isolate_, table_instance.table_object,
    1517        1548 :                                         instance, index);
    1518             :     }
    1519             :   }
    1520        2413 : }
    1521             : 
    1522         378 : void InstanceBuilder::InitializeExceptions(
    1523             :     Handle<WasmInstanceObject> instance) {
    1524        1134 :   Handle<FixedArray> exceptions_table(instance->exceptions_table(), isolate_);
    1525        1710 :   for (int index = 0; index < exceptions_table->length(); ++index) {
    1526        1485 :     if (!exceptions_table->get(index)->IsUndefined(isolate_)) continue;
    1527             :     Handle<WasmExceptionTag> exception_tag =
    1528         423 :         WasmExceptionTag::New(isolate_, index);
    1529         846 :     exceptions_table->set(index, *exception_tag);
    1530             :   }
    1531         378 : }
    1532             : 
    1533             : }  // namespace wasm
    1534             : }  // namespace internal
    1535      183867 : }  // namespace v8
    1536             : 
    1537             : #undef TRACE

Generated by: LCOV version 1.10