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

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

Generated by: LCOV version 1.10