LCOV - code coverage report
Current view: top level - src/wasm - module-instantiate.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 558 602 92.7 %
Date: 2019-03-21 Functions: 37 39 94.9 %

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

Generated by: LCOV version 1.10