Home | History | Annotate | Download | only in wasm
      1 // Copyright 2015 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 <memory>
      6 
      7 #include "src/assembler-inl.h"
      8 #include "src/base/adapters.h"
      9 #include "src/base/atomic-utils.h"
     10 #include "src/code-stubs.h"
     11 #include "src/compiler/wasm-compiler.h"
     12 #include "src/debug/interface-types.h"
     13 #include "src/objects.h"
     14 #include "src/property-descriptor.h"
     15 #include "src/simulator.h"
     16 #include "src/snapshot/snapshot.h"
     17 #include "src/v8.h"
     18 
     19 #include "src/asmjs/asm-wasm-builder.h"
     20 #include "src/wasm/function-body-decoder.h"
     21 #include "src/wasm/module-decoder.h"
     22 #include "src/wasm/wasm-code-specialization.h"
     23 #include "src/wasm/wasm-js.h"
     24 #include "src/wasm/wasm-limits.h"
     25 #include "src/wasm/wasm-module.h"
     26 #include "src/wasm/wasm-objects.h"
     27 #include "src/wasm/wasm-result.h"
     28 
     29 using namespace v8::internal;
     30 using namespace v8::internal::wasm;
     31 namespace base = v8::base;
     32 
     33 #define TRACE(...)                                      \
     34   do {                                                  \
     35     if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \
     36   } while (false)
     37 
     38 #define TRACE_CHAIN(instance)        \
     39   do {                               \
     40     instance->PrintInstancesChain(); \
     41   } while (false)
     42 
     43 namespace {
     44 
     45 static const int kInvalidSigIndex = -1;
     46 
     47 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) {
     48   return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset;
     49 }
     50 
     51 static void MemoryFinalizer(const v8::WeakCallbackInfo<void>& data) {
     52   DisallowHeapAllocation no_gc;
     53   JSArrayBuffer** p = reinterpret_cast<JSArrayBuffer**>(data.GetParameter());
     54   JSArrayBuffer* buffer = *p;
     55 
     56   if (!buffer->was_neutered()) {
     57     void* memory = buffer->backing_store();
     58     DCHECK(memory != nullptr);
     59     base::OS::Free(memory,
     60                    RoundUp(kWasmMaxHeapOffset, base::OS::CommitPageSize()));
     61 
     62     data.GetIsolate()->AdjustAmountOfExternalAllocatedMemory(
     63         -buffer->byte_length()->Number());
     64   }
     65 
     66   GlobalHandles::Destroy(reinterpret_cast<Object**>(p));
     67 }
     68 
     69 #if V8_TARGET_ARCH_64_BIT
     70 const bool kGuardRegionsSupported = true;
     71 #else
     72 const bool kGuardRegionsSupported = false;
     73 #endif
     74 
     75 bool EnableGuardRegions() {
     76   return FLAG_wasm_guard_pages && kGuardRegionsSupported;
     77 }
     78 
     79 static void RecordStats(Isolate* isolate, Code* code) {
     80   isolate->counters()->wasm_generated_code_size()->Increment(code->body_size());
     81   isolate->counters()->wasm_reloc_size()->Increment(
     82       code->relocation_info()->length());
     83 }
     84 
     85 static void RecordStats(Isolate* isolate, Handle<FixedArray> functions) {
     86   DisallowHeapAllocation no_gc;
     87   for (int i = 0; i < functions->length(); ++i) {
     88     RecordStats(isolate, Code::cast(functions->get(i)));
     89   }
     90 }
     91 
     92 void* TryAllocateBackingStore(Isolate* isolate, size_t size,
     93                               bool enable_guard_regions, bool& is_external) {
     94   is_external = false;
     95   // TODO(eholk): Right now enable_guard_regions has no effect on 32-bit
     96   // systems. It may be safer to fail instead, given that other code might do
     97   // things that would be unsafe if they expected guard pages where there
     98   // weren't any.
     99   if (enable_guard_regions && kGuardRegionsSupported) {
    100     // TODO(eholk): On Windows we want to make sure we don't commit the guard
    101     // pages yet.
    102 
    103     // We always allocate the largest possible offset into the heap, so the
    104     // addressable memory after the guard page can be made inaccessible.
    105     const size_t alloc_size =
    106         RoundUp(kWasmMaxHeapOffset, base::OS::CommitPageSize());
    107     DCHECK_EQ(0, size % base::OS::CommitPageSize());
    108 
    109     // AllocateGuarded makes the whole region inaccessible by default.
    110     void* memory = base::OS::AllocateGuarded(alloc_size);
    111     if (memory == nullptr) {
    112       return nullptr;
    113     }
    114 
    115     // Make the part we care about accessible.
    116     base::OS::Unprotect(memory, size);
    117 
    118     reinterpret_cast<v8::Isolate*>(isolate)
    119         ->AdjustAmountOfExternalAllocatedMemory(size);
    120 
    121     is_external = true;
    122     return memory;
    123   } else {
    124     void* memory = isolate->array_buffer_allocator()->Allocate(size);
    125     return memory;
    126   }
    127 }
    128 
    129 void FlushICache(Isolate* isolate, Handle<FixedArray> code_table) {
    130   for (int i = 0; i < code_table->length(); ++i) {
    131     Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i);
    132     Assembler::FlushICache(isolate, code->instruction_start(),
    133                            code->instruction_size());
    134   }
    135 }
    136 
    137 Handle<Script> CreateWasmScript(Isolate* isolate,
    138                                 const ModuleWireBytes& wire_bytes) {
    139   Handle<Script> script =
    140       isolate->factory()->NewScript(isolate->factory()->empty_string());
    141   FixedArray* array = isolate->native_context()->embedder_data();
    142   script->set_context_data(array->get(v8::Context::kDebugIdIndex));
    143   script->set_type(Script::TYPE_WASM);
    144 
    145   int hash = StringHasher::HashSequentialString(
    146       reinterpret_cast<const char*>(wire_bytes.start()), wire_bytes.length(),
    147       kZeroHashSeed);
    148 
    149   const int kBufferSize = 32;
    150   char buffer[kBufferSize];
    151   int url_chars = SNPrintF(ArrayVector(buffer), "wasm://wasm/%08x", hash);
    152   DCHECK(url_chars >= 0 && url_chars < kBufferSize);
    153   MaybeHandle<String> url_str = isolate->factory()->NewStringFromOneByte(
    154       Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), url_chars),
    155       TENURED);
    156   script->set_source_url(*url_str.ToHandleChecked());
    157 
    158   int name_chars = SNPrintF(ArrayVector(buffer), "wasm-%08x", hash);
    159   DCHECK(name_chars >= 0 && name_chars < kBufferSize);
    160   MaybeHandle<String> name_str = isolate->factory()->NewStringFromOneByte(
    161       Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), name_chars),
    162       TENURED);
    163   script->set_name(*name_str.ToHandleChecked());
    164 
    165   return script;
    166 }
    167 
    168 class JSToWasmWrapperCache {
    169  public:
    170   Handle<Code> CloneOrCompileJSToWasmWrapper(Isolate* isolate,
    171                                              const wasm::WasmModule* module,
    172                                              Handle<Code> wasm_code,
    173                                              uint32_t index) {
    174     const wasm::WasmFunction* func = &module->functions[index];
    175     int cached_idx = sig_map_.Find(func->sig);
    176     if (cached_idx >= 0) {
    177       Handle<Code> code = isolate->factory()->CopyCode(code_cache_[cached_idx]);
    178       // Now patch the call to wasm code.
    179       for (RelocIterator it(*code, RelocInfo::kCodeTargetMask);; it.next()) {
    180         DCHECK(!it.done());
    181         Code* target =
    182             Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
    183         if (target->kind() == Code::WASM_FUNCTION ||
    184             target->kind() == Code::WASM_TO_JS_FUNCTION ||
    185             target->builtin_index() == Builtins::kIllegal) {
    186           it.rinfo()->set_target_address(wasm_code->instruction_start());
    187           break;
    188         }
    189       }
    190       return code;
    191     }
    192 
    193     Handle<Code> code =
    194         compiler::CompileJSToWasmWrapper(isolate, module, wasm_code, index);
    195     uint32_t new_cache_idx = sig_map_.FindOrInsert(func->sig);
    196     DCHECK_EQ(code_cache_.size(), new_cache_idx);
    197     USE(new_cache_idx);
    198     code_cache_.push_back(code);
    199     return code;
    200   }
    201 
    202  private:
    203   // sig_map_ maps signatures to an index in code_cache_.
    204   wasm::SignatureMap sig_map_;
    205   std::vector<Handle<Code>> code_cache_;
    206 };
    207 
    208 // A helper for compiling an entire module.
    209 class CompilationHelper {
    210  public:
    211   CompilationHelper(Isolate* isolate, WasmModule* module)
    212       : isolate_(isolate), module_(module) {}
    213 
    214   // The actual runnable task that performs compilations in the background.
    215   class CompilationTask : public CancelableTask {
    216    public:
    217     CompilationHelper* helper_;
    218     explicit CompilationTask(CompilationHelper* helper)
    219         : CancelableTask(helper->isolate_), helper_(helper) {}
    220 
    221     void RunInternal() override {
    222       while (helper_->FetchAndExecuteCompilationUnit()) {
    223       }
    224       helper_->module_->pending_tasks.get()->Signal();
    225     }
    226   };
    227 
    228   Isolate* isolate_;
    229   WasmModule* module_;
    230   std::vector<compiler::WasmCompilationUnit*> compilation_units_;
    231   std::queue<compiler::WasmCompilationUnit*> executed_units_;
    232   base::Mutex result_mutex_;
    233   base::AtomicNumber<size_t> next_unit_;
    234 
    235   // Run by each compilation task and by the main thread.
    236   bool FetchAndExecuteCompilationUnit() {
    237     DisallowHeapAllocation no_allocation;
    238     DisallowHandleAllocation no_handles;
    239     DisallowHandleDereference no_deref;
    240     DisallowCodeDependencyChange no_dependency_change;
    241 
    242     // - 1 because AtomicIncrement returns the value after the atomic increment.
    243     size_t index = next_unit_.Increment(1) - 1;
    244     if (index >= compilation_units_.size()) {
    245       return false;
    246     }
    247 
    248     compiler::WasmCompilationUnit* unit = compilation_units_.at(index);
    249     if (unit != nullptr) {
    250       unit->ExecuteCompilation();
    251       base::LockGuard<base::Mutex> guard(&result_mutex_);
    252       executed_units_.push(unit);
    253     }
    254     return true;
    255   }
    256 
    257   void InitializeParallelCompilation(const std::vector<WasmFunction>& functions,
    258                                      ModuleBytesEnv& module_env,
    259                                      ErrorThrower* thrower) {
    260     compilation_units_.reserve(functions.size());
    261     for (uint32_t i = FLAG_skip_compiling_wasm_funcs; i < functions.size();
    262          ++i) {
    263       const WasmFunction* func = &functions[i];
    264       compilation_units_.push_back(
    265           func->imported ? nullptr
    266                          : new compiler::WasmCompilationUnit(
    267                                thrower, isolate_, &module_env, func, i));
    268     }
    269   }
    270 
    271   uint32_t* StartCompilationTasks() {
    272     const size_t num_tasks =
    273         Min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks),
    274             V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads());
    275     uint32_t* task_ids = new uint32_t[num_tasks];
    276     for (size_t i = 0; i < num_tasks; ++i) {
    277       CompilationTask* task = new CompilationTask(this);
    278       task_ids[i] = task->id();
    279       V8::GetCurrentPlatform()->CallOnBackgroundThread(
    280           task, v8::Platform::kShortRunningTask);
    281     }
    282     return task_ids;
    283   }
    284 
    285   void WaitForCompilationTasks(uint32_t* task_ids) {
    286     const size_t num_tasks =
    287         Min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks),
    288             V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads());
    289     for (size_t i = 0; i < num_tasks; ++i) {
    290       // If the task has not started yet, then we abort it. Otherwise we wait
    291       // for
    292       // it to finish.
    293       if (isolate_->cancelable_task_manager()->TryAbort(task_ids[i]) !=
    294           CancelableTaskManager::kTaskAborted) {
    295         module_->pending_tasks.get()->Wait();
    296       }
    297     }
    298   }
    299 
    300   void FinishCompilationUnits(std::vector<Handle<Code>>& results) {
    301     while (true) {
    302       compiler::WasmCompilationUnit* unit = nullptr;
    303       {
    304         base::LockGuard<base::Mutex> guard(&result_mutex_);
    305         if (executed_units_.empty()) {
    306           break;
    307         }
    308         unit = executed_units_.front();
    309         executed_units_.pop();
    310       }
    311       int j = unit->index();
    312       results[j] = unit->FinishCompilation();
    313       delete unit;
    314     }
    315   }
    316 
    317   void CompileInParallel(ModuleBytesEnv* module_env,
    318                          std::vector<Handle<Code>>& results,
    319                          ErrorThrower* thrower) {
    320     const WasmModule* module = module_env->module_env.module;
    321     // Data structures for the parallel compilation.
    322 
    323     //-----------------------------------------------------------------------
    324     // For parallel compilation:
    325     // 1) The main thread allocates a compilation unit for each wasm function
    326     //    and stores them in the vector {compilation_units}.
    327     // 2) The main thread spawns {CompilationTask} instances which run on
    328     //    the background threads.
    329     // 3.a) The background threads and the main thread pick one compilation
    330     //      unit at a time and execute the parallel phase of the compilation
    331     //      unit. After finishing the execution of the parallel phase, the
    332     //      result is enqueued in {executed_units}.
    333     // 3.b) If {executed_units} contains a compilation unit, the main thread
    334     //      dequeues it and finishes the compilation.
    335     // 4) After the parallel phase of all compilation units has started, the
    336     //    main thread waits for all {CompilationTask} instances to finish.
    337     // 5) The main thread finishes the compilation.
    338 
    339     // Turn on the {CanonicalHandleScope} so that the background threads can
    340     // use the node cache.
    341     CanonicalHandleScope canonical(isolate_);
    342 
    343     // 1) The main thread allocates a compilation unit for each wasm function
    344     //    and stores them in the vector {compilation_units}.
    345     InitializeParallelCompilation(module->functions, *module_env, thrower);
    346 
    347     // Objects for the synchronization with the background threads.
    348     base::AtomicNumber<size_t> next_unit(
    349         static_cast<size_t>(FLAG_skip_compiling_wasm_funcs));
    350 
    351     // 2) The main thread spawns {CompilationTask} instances which run on
    352     //    the background threads.
    353     std::unique_ptr<uint32_t[]> task_ids(StartCompilationTasks());
    354 
    355     // 3.a) The background threads and the main thread pick one compilation
    356     //      unit at a time and execute the parallel phase of the compilation
    357     //      unit. After finishing the execution of the parallel phase, the
    358     //      result is enqueued in {executed_units}.
    359     while (FetchAndExecuteCompilationUnit()) {
    360       // 3.b) If {executed_units} contains a compilation unit, the main thread
    361       //      dequeues it and finishes the compilation unit. Compilation units
    362       //      are finished concurrently to the background threads to save
    363       //      memory.
    364       FinishCompilationUnits(results);
    365     }
    366     // 4) After the parallel phase of all compilation units has started, the
    367     //    main thread waits for all {CompilationTask} instances to finish.
    368     WaitForCompilationTasks(task_ids.get());
    369     // Finish the compilation of the remaining compilation units.
    370     FinishCompilationUnits(results);
    371   }
    372 
    373   void CompileSequentially(ModuleBytesEnv* module_env,
    374                            std::vector<Handle<Code>>& results,
    375                            ErrorThrower* thrower) {
    376     DCHECK(!thrower->error());
    377 
    378     const WasmModule* module = module_env->module_env.module;
    379     for (uint32_t i = FLAG_skip_compiling_wasm_funcs;
    380          i < module->functions.size(); ++i) {
    381       const WasmFunction& func = module->functions[i];
    382       if (func.imported)
    383         continue;  // Imports are compiled at instantiation time.
    384 
    385       Handle<Code> code = Handle<Code>::null();
    386       // Compile the function.
    387       code = compiler::WasmCompilationUnit::CompileWasmFunction(
    388           thrower, isolate_, module_env, &func);
    389       if (code.is_null()) {
    390         WasmName str = module_env->wire_bytes.GetName(&func);
    391         thrower->CompileError("Compilation of #%d:%.*s failed.", i,
    392                               str.length(), str.start());
    393         break;
    394       }
    395       results[i] = code;
    396     }
    397   }
    398 
    399   MaybeHandle<WasmModuleObject> CompileToModuleObject(
    400       ErrorThrower* thrower, const ModuleWireBytes& wire_bytes,
    401       Handle<Script> asm_js_script,
    402       Vector<const byte> asm_js_offset_table_bytes) {
    403     Factory* factory = isolate_->factory();
    404     // The {module_wrapper} will take ownership of the {WasmModule} object,
    405     // and it will be destroyed when the GC reclaims the wrapper object.
    406     Handle<WasmModuleWrapper> module_wrapper =
    407         WasmModuleWrapper::New(isolate_, module_);
    408     WasmInstance temp_instance(module_);
    409     temp_instance.context = isolate_->native_context();
    410     temp_instance.mem_size = WasmModule::kPageSize * module_->min_mem_pages;
    411     temp_instance.mem_start = nullptr;
    412     temp_instance.globals_start = nullptr;
    413 
    414     // Initialize the indirect tables with placeholders.
    415     int function_table_count =
    416         static_cast<int>(module_->function_tables.size());
    417     Handle<FixedArray> function_tables =
    418         factory->NewFixedArray(function_table_count, TENURED);
    419     Handle<FixedArray> signature_tables =
    420         factory->NewFixedArray(function_table_count, TENURED);
    421     for (int i = 0; i < function_table_count; ++i) {
    422       temp_instance.function_tables[i] = factory->NewFixedArray(1, TENURED);
    423       temp_instance.signature_tables[i] = factory->NewFixedArray(1, TENURED);
    424       function_tables->set(i, *temp_instance.function_tables[i]);
    425       signature_tables->set(i, *temp_instance.signature_tables[i]);
    426     }
    427 
    428     HistogramTimerScope wasm_compile_module_time_scope(
    429         isolate_->counters()->wasm_compile_module_time());
    430 
    431     ModuleBytesEnv module_env(module_, &temp_instance, wire_bytes);
    432 
    433     // The {code_table} array contains import wrappers and functions (which
    434     // are both included in {functions.size()}, and export wrappers.
    435     int code_table_size = static_cast<int>(module_->functions.size() +
    436                                            module_->num_exported_functions);
    437     Handle<FixedArray> code_table =
    438         factory->NewFixedArray(static_cast<int>(code_table_size), TENURED);
    439 
    440     // Initialize the code table with the illegal builtin. All call sites will
    441     // be
    442     // patched at instantiation.
    443     Handle<Code> illegal_builtin = isolate_->builtins()->Illegal();
    444     for (uint32_t i = 0; i < module_->functions.size(); ++i) {
    445       code_table->set(static_cast<int>(i), *illegal_builtin);
    446       temp_instance.function_code[i] = illegal_builtin;
    447     }
    448 
    449     isolate_->counters()->wasm_functions_per_module()->AddSample(
    450         static_cast<int>(module_->functions.size()));
    451     CompilationHelper helper(isolate_, module_);
    452     if (!FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks != 0) {
    453       // Avoid a race condition by collecting results into a second vector.
    454       std::vector<Handle<Code>> results(temp_instance.function_code);
    455       helper.CompileInParallel(&module_env, results, thrower);
    456       temp_instance.function_code.swap(results);
    457     } else {
    458       helper.CompileSequentially(&module_env, temp_instance.function_code,
    459                                  thrower);
    460     }
    461     if (thrower->error()) return {};
    462 
    463     // At this point, compilation has completed. Update the code table.
    464     for (size_t i = FLAG_skip_compiling_wasm_funcs;
    465          i < temp_instance.function_code.size(); ++i) {
    466       Code* code = *temp_instance.function_code[i];
    467       code_table->set(static_cast<int>(i), code);
    468       RecordStats(isolate_, code);
    469     }
    470 
    471     // Create heap objects for script, module bytes and asm.js offset table to
    472     // be
    473     // stored in the shared module data.
    474     Handle<Script> script;
    475     Handle<ByteArray> asm_js_offset_table;
    476     if (asm_js_script.is_null()) {
    477       script = CreateWasmScript(isolate_, wire_bytes);
    478     } else {
    479       script = asm_js_script;
    480       asm_js_offset_table =
    481           isolate_->factory()->NewByteArray(asm_js_offset_table_bytes.length());
    482       asm_js_offset_table->copy_in(0, asm_js_offset_table_bytes.start(),
    483                                    asm_js_offset_table_bytes.length());
    484     }
    485     // TODO(wasm): only save the sections necessary to deserialize a
    486     // {WasmModule}. E.g. function bodies could be omitted.
    487     Handle<String> module_bytes =
    488         factory
    489             ->NewStringFromOneByte({wire_bytes.start(), wire_bytes.length()},
    490                                    TENURED)
    491             .ToHandleChecked();
    492     DCHECK(module_bytes->IsSeqOneByteString());
    493 
    494     // Create the shared module data.
    495     // TODO(clemensh): For the same module (same bytes / same hash), we should
    496     // only have one WasmSharedModuleData. Otherwise, we might only set
    497     // breakpoints on a (potentially empty) subset of the instances.
    498 
    499     Handle<WasmSharedModuleData> shared = WasmSharedModuleData::New(
    500         isolate_, module_wrapper, Handle<SeqOneByteString>::cast(module_bytes),
    501         script, asm_js_offset_table);
    502 
    503     // Create the compiled module object, and populate with compiled functions
    504     // and information needed at instantiation time. This object needs to be
    505     // serializable. Instantiation may occur off a deserialized version of this
    506     // object.
    507     Handle<WasmCompiledModule> compiled_module =
    508         WasmCompiledModule::New(isolate_, shared);
    509     compiled_module->set_num_imported_functions(
    510         module_->num_imported_functions);
    511     compiled_module->set_code_table(code_table);
    512     compiled_module->set_min_mem_pages(module_->min_mem_pages);
    513     compiled_module->set_max_mem_pages(module_->max_mem_pages);
    514     if (function_table_count > 0) {
    515       compiled_module->set_function_tables(function_tables);
    516       compiled_module->set_signature_tables(signature_tables);
    517       compiled_module->set_empty_function_tables(function_tables);
    518     }
    519 
    520     // If we created a wasm script, finish it now and make it public to the
    521     // debugger.
    522     if (asm_js_script.is_null()) {
    523       script->set_wasm_compiled_module(*compiled_module);
    524       isolate_->debug()->OnAfterCompile(script);
    525     }
    526 
    527     // Compile JS->WASM wrappers for exported functions.
    528     JSToWasmWrapperCache js_to_wasm_cache;
    529     int func_index = 0;
    530     for (auto exp : module_->export_table) {
    531       if (exp.kind != kExternalFunction) continue;
    532       Handle<Code> wasm_code(Code::cast(code_table->get(exp.index)), isolate_);
    533       Handle<Code> wrapper_code =
    534           js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(isolate_, module_,
    535                                                          wasm_code, exp.index);
    536       int export_index =
    537           static_cast<int>(module_->functions.size() + func_index);
    538       code_table->set(export_index, *wrapper_code);
    539       RecordStats(isolate_, *wrapper_code);
    540       func_index++;
    541     }
    542 
    543     return WasmModuleObject::New(isolate_, compiled_module);
    544 }
    545 };
    546 
    547 static void ResetCompiledModule(Isolate* isolate, WasmInstanceObject* owner,
    548                                 WasmCompiledModule* compiled_module) {
    549   TRACE("Resetting %d\n", compiled_module->instance_id());
    550   Object* undefined = *isolate->factory()->undefined_value();
    551   Object* fct_obj = compiled_module->ptr_to_code_table();
    552   if (fct_obj != nullptr && fct_obj != undefined) {
    553     uint32_t old_mem_size = compiled_module->mem_size();
    554     uint32_t default_mem_size = compiled_module->default_mem_size();
    555     Object* mem_start = compiled_module->maybe_ptr_to_memory();
    556 
    557     // Patch code to update memory references, global references, and function
    558     // table references.
    559     Zone specialization_zone(isolate->allocator(), ZONE_NAME);
    560     CodeSpecialization code_specialization(isolate, &specialization_zone);
    561 
    562     if (old_mem_size > 0) {
    563       CHECK_NE(mem_start, undefined);
    564       Address old_mem_address =
    565           static_cast<Address>(JSArrayBuffer::cast(mem_start)->backing_store());
    566       code_specialization.RelocateMemoryReferences(
    567           old_mem_address, old_mem_size, nullptr, default_mem_size);
    568     }
    569 
    570     if (owner->has_globals_buffer()) {
    571       Address globals_start =
    572           static_cast<Address>(owner->globals_buffer()->backing_store());
    573       code_specialization.RelocateGlobals(globals_start, nullptr);
    574     }
    575 
    576     // Reset function tables.
    577     if (compiled_module->has_function_tables()) {
    578       FixedArray* function_tables = compiled_module->ptr_to_function_tables();
    579       FixedArray* empty_function_tables =
    580           compiled_module->ptr_to_empty_function_tables();
    581       DCHECK_EQ(function_tables->length(), empty_function_tables->length());
    582       for (int i = 0, e = function_tables->length(); i < e; ++i) {
    583         code_specialization.RelocateObject(
    584             handle(function_tables->get(i), isolate),
    585             handle(empty_function_tables->get(i), isolate));
    586       }
    587       compiled_module->set_ptr_to_function_tables(empty_function_tables);
    588     }
    589 
    590     FixedArray* functions = FixedArray::cast(fct_obj);
    591     for (int i = compiled_module->num_imported_functions(),
    592              end = functions->length();
    593          i < end; ++i) {
    594       Code* code = Code::cast(functions->get(i));
    595       if (code->kind() != Code::WASM_FUNCTION) {
    596         // From here on, there should only be wrappers for exported functions.
    597         for (; i < end; ++i) {
    598           DCHECK_EQ(Code::JS_TO_WASM_FUNCTION,
    599                     Code::cast(functions->get(i))->kind());
    600         }
    601         break;
    602       }
    603       bool changed =
    604           code_specialization.ApplyToWasmCode(code, SKIP_ICACHE_FLUSH);
    605       // TODO(wasm): Check if this is faster than passing FLUSH_ICACHE_IF_NEEDED
    606       // above.
    607       if (changed) {
    608         Assembler::FlushICache(isolate, code->instruction_start(),
    609                                code->instruction_size());
    610       }
    611     }
    612   }
    613   compiled_module->reset_memory();
    614 }
    615 
    616 static void MemoryInstanceFinalizer(Isolate* isolate,
    617                                     WasmInstanceObject* instance) {
    618   DisallowHeapAllocation no_gc;
    619   // If the memory object is destroyed, nothing needs to be done here.
    620   if (!instance->has_memory_object()) return;
    621   Handle<WasmInstanceWrapper> instance_wrapper =
    622       handle(instance->instance_wrapper());
    623   DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper));
    624   DCHECK(instance_wrapper->has_instance());
    625   bool has_prev = instance_wrapper->has_previous();
    626   bool has_next = instance_wrapper->has_next();
    627   Handle<WasmMemoryObject> memory_object(instance->memory_object());
    628 
    629   if (!has_prev && !has_next) {
    630     memory_object->ResetInstancesLink(isolate);
    631     return;
    632   } else {
    633     Handle<WasmInstanceWrapper> next_wrapper, prev_wrapper;
    634     if (!has_prev) {
    635       Handle<WasmInstanceWrapper> next_wrapper =
    636           instance_wrapper->next_wrapper();
    637       next_wrapper->reset_previous_wrapper();
    638       // As this is the first link in the memory object, destroying
    639       // without updating memory object would corrupt the instance chain in
    640       // the memory object.
    641       memory_object->set_instances_link(*next_wrapper);
    642     } else if (!has_next) {
    643       instance_wrapper->previous_wrapper()->reset_next_wrapper();
    644     } else {
    645       DCHECK(has_next && has_prev);
    646       Handle<WasmInstanceWrapper> prev_wrapper =
    647           instance_wrapper->previous_wrapper();
    648       Handle<WasmInstanceWrapper> next_wrapper =
    649           instance_wrapper->next_wrapper();
    650       prev_wrapper->set_next_wrapper(*next_wrapper);
    651       next_wrapper->set_previous_wrapper(*prev_wrapper);
    652     }
    653     // Reset to avoid dangling pointers
    654     instance_wrapper->reset();
    655   }
    656 }
    657 
    658 static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) {
    659   DisallowHeapAllocation no_gc;
    660   JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter());
    661   WasmInstanceObject* owner = reinterpret_cast<WasmInstanceObject*>(*p);
    662   Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate());
    663   // If a link to shared memory instances exists, update the list of memory
    664   // instances before the instance is destroyed.
    665   if (owner->has_instance_wrapper()) MemoryInstanceFinalizer(isolate, owner);
    666   WasmCompiledModule* compiled_module = owner->compiled_module();
    667   TRACE("Finalizing %d {\n", compiled_module->instance_id());
    668   DCHECK(compiled_module->has_weak_wasm_module());
    669   WeakCell* weak_wasm_module = compiled_module->ptr_to_weak_wasm_module();
    670 
    671   // weak_wasm_module may have been cleared, meaning the module object
    672   // was GC-ed. In that case, there won't be any new instances created,
    673   // and we don't need to maintain the links between instances.
    674   if (!weak_wasm_module->cleared()) {
    675     JSObject* wasm_module = JSObject::cast(weak_wasm_module->value());
    676     WasmCompiledModule* current_template =
    677         WasmCompiledModule::cast(wasm_module->GetInternalField(0));
    678 
    679     TRACE("chain before {\n");
    680     TRACE_CHAIN(current_template);
    681     TRACE("}\n");
    682 
    683     DCHECK(!current_template->has_weak_prev_instance());
    684     WeakCell* next = compiled_module->maybe_ptr_to_weak_next_instance();
    685     WeakCell* prev = compiled_module->maybe_ptr_to_weak_prev_instance();
    686 
    687     if (current_template == compiled_module) {
    688       if (next == nullptr) {
    689         ResetCompiledModule(isolate, owner, compiled_module);
    690       } else {
    691         DCHECK(next->value()->IsFixedArray());
    692         wasm_module->SetInternalField(0, next->value());
    693         DCHECK_NULL(prev);
    694         WasmCompiledModule::cast(next->value())->reset_weak_prev_instance();
    695       }
    696     } else {
    697       DCHECK(!(prev == nullptr && next == nullptr));
    698       // the only reason prev or next would be cleared is if the
    699       // respective objects got collected, but if that happened,
    700       // we would have relinked the list.
    701       if (prev != nullptr) {
    702         DCHECK(!prev->cleared());
    703         if (next == nullptr) {
    704           WasmCompiledModule::cast(prev->value())->reset_weak_next_instance();
    705         } else {
    706           WasmCompiledModule::cast(prev->value())
    707               ->set_ptr_to_weak_next_instance(next);
    708         }
    709       }
    710       if (next != nullptr) {
    711         DCHECK(!next->cleared());
    712         if (prev == nullptr) {
    713           WasmCompiledModule::cast(next->value())->reset_weak_prev_instance();
    714         } else {
    715           WasmCompiledModule::cast(next->value())
    716               ->set_ptr_to_weak_prev_instance(prev);
    717         }
    718       }
    719     }
    720     TRACE("chain after {\n");
    721     TRACE_CHAIN(WasmCompiledModule::cast(wasm_module->GetInternalField(0)));
    722     TRACE("}\n");
    723   }
    724   compiled_module->reset_weak_owning_instance();
    725   GlobalHandles::Destroy(reinterpret_cast<Object**>(p));
    726   TRACE("}\n");
    727 }
    728 
    729 std::pair<int, int> GetFunctionOffsetAndLength(
    730     Handle<WasmCompiledModule> compiled_module, int func_index) {
    731   WasmModule* module = compiled_module->module();
    732   if (func_index < 0 ||
    733       static_cast<size_t>(func_index) > module->functions.size()) {
    734     return {0, 0};
    735   }
    736   WasmFunction& func = module->functions[func_index];
    737   return {static_cast<int>(func.code_start_offset),
    738           static_cast<int>(func.code_end_offset - func.code_start_offset)};
    739 }
    740 }  // namespace
    741 
    742 Handle<JSArrayBuffer> SetupArrayBuffer(Isolate* isolate, void* backing_store,
    743                                        size_t size, bool is_external,
    744                                        bool enable_guard_regions) {
    745   Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
    746   JSArrayBuffer::Setup(buffer, isolate, is_external, backing_store,
    747                        static_cast<int>(size));
    748   buffer->set_is_neuterable(false);
    749   buffer->set_has_guard_region(enable_guard_regions);
    750 
    751   if (is_external) {
    752     // We mark the buffer as external if we allocated it here with guard
    753     // pages. That means we need to arrange for it to be freed.
    754 
    755     // TODO(eholk): Finalizers may not run when the main thread is shutting
    756     // down, which means we may leak memory here.
    757     Handle<Object> global_handle = isolate->global_handles()->Create(*buffer);
    758     GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(),
    759                             &MemoryFinalizer, v8::WeakCallbackType::kFinalizer);
    760   }
    761   return buffer;
    762 }
    763 
    764 Handle<JSArrayBuffer> wasm::NewArrayBuffer(Isolate* isolate, size_t size,
    765                                            bool enable_guard_regions) {
    766   if (size > (FLAG_wasm_max_mem_pages * WasmModule::kPageSize)) {
    767     // TODO(titzer): lift restriction on maximum memory allocated here.
    768     return Handle<JSArrayBuffer>::null();
    769   }
    770 
    771   enable_guard_regions = enable_guard_regions && kGuardRegionsSupported;
    772 
    773   bool is_external;  // Set by TryAllocateBackingStore
    774   void* memory =
    775       TryAllocateBackingStore(isolate, size, enable_guard_regions, is_external);
    776 
    777   if (memory == nullptr) {
    778     return Handle<JSArrayBuffer>::null();
    779   }
    780 
    781 #if DEBUG
    782   // Double check the API allocator actually zero-initialized the memory.
    783   const byte* bytes = reinterpret_cast<const byte*>(memory);
    784   for (size_t i = 0; i < size; ++i) {
    785     DCHECK_EQ(0, bytes[i]);
    786   }
    787 #endif
    788 
    789   return SetupArrayBuffer(isolate, memory, size, is_external,
    790                           enable_guard_regions);
    791 }
    792 
    793 std::ostream& wasm::operator<<(std::ostream& os, const WasmModule& module) {
    794   os << "WASM module with ";
    795   os << (module.min_mem_pages * module.kPageSize) << " min mem";
    796   os << (module.max_mem_pages * module.kPageSize) << " max mem";
    797   os << module.functions.size() << " functions";
    798   os << module.functions.size() << " globals";
    799   os << module.functions.size() << " data segments";
    800   return os;
    801 }
    802 
    803 std::ostream& wasm::operator<<(std::ostream& os, const WasmFunction& function) {
    804   os << "WASM function with signature " << *function.sig;
    805 
    806   os << " code bytes: "
    807      << (function.code_end_offset - function.code_start_offset);
    808   return os;
    809 }
    810 
    811 std::ostream& wasm::operator<<(std::ostream& os, const WasmFunctionName& name) {
    812   os << "#" << name.function_->func_index;
    813   if (name.function_->name_offset > 0) {
    814     if (name.name_.start()) {
    815       os << ":";
    816       os.write(name.name_.start(), name.name_.length());
    817     }
    818   } else {
    819     os << "?";
    820   }
    821   return os;
    822 }
    823 
    824 WasmInstanceObject* wasm::GetOwningWasmInstance(Code* code) {
    825   DisallowHeapAllocation no_gc;
    826   DCHECK(code->kind() == Code::WASM_FUNCTION ||
    827          code->kind() == Code::WASM_INTERPRETER_ENTRY);
    828   FixedArray* deopt_data = code->deoptimization_data();
    829   DCHECK_NOT_NULL(deopt_data);
    830   DCHECK_EQ(code->kind() == Code::WASM_INTERPRETER_ENTRY ? 1 : 2,
    831             deopt_data->length());
    832   Object* weak_link = deopt_data->get(0);
    833   DCHECK(weak_link->IsWeakCell());
    834   WeakCell* cell = WeakCell::cast(weak_link);
    835   if (cell->cleared()) return nullptr;
    836   return WasmInstanceObject::cast(cell->value());
    837 }
    838 
    839 int wasm::GetFunctionCodeOffset(Handle<WasmCompiledModule> compiled_module,
    840                                 int func_index) {
    841   return GetFunctionOffsetAndLength(compiled_module, func_index).first;
    842 }
    843 
    844 WasmModule::WasmModule(Zone* owned)
    845     : owned_zone(owned), pending_tasks(new base::Semaphore(0)) {}
    846 
    847 static WasmFunction* GetWasmFunctionForImportWrapper(Isolate* isolate,
    848                                                      Handle<Object> target) {
    849   if (target->IsJSFunction()) {
    850     Handle<JSFunction> func = Handle<JSFunction>::cast(target);
    851     if (func->code()->kind() == Code::JS_TO_WASM_FUNCTION) {
    852       auto exported = Handle<WasmExportedFunction>::cast(func);
    853       Handle<WasmInstanceObject> other_instance(exported->instance(), isolate);
    854       int func_index = exported->function_index();
    855       return &other_instance->module()->functions[func_index];
    856     }
    857   }
    858   return nullptr;
    859 }
    860 
    861 static Handle<Code> UnwrapImportWrapper(Handle<Object> target) {
    862   Handle<JSFunction> func = Handle<JSFunction>::cast(target);
    863   Handle<Code> export_wrapper_code = handle(func->code());
    864   int found = 0;
    865   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
    866   Handle<Code> code;
    867   for (RelocIterator it(*export_wrapper_code, mask); !it.done(); it.next()) {
    868     RelocInfo* rinfo = it.rinfo();
    869     Address target_address = rinfo->target_address();
    870     Code* target = Code::GetCodeFromTargetAddress(target_address);
    871     if (target->kind() == Code::WASM_FUNCTION ||
    872         target->kind() == Code::WASM_TO_JS_FUNCTION) {
    873       ++found;
    874       code = handle(target);
    875     }
    876   }
    877   DCHECK_EQ(1, found);
    878   return code;
    879 }
    880 
    881 static Handle<Code> CompileImportWrapper(Isolate* isolate, int index,
    882                                          FunctionSig* sig,
    883                                          Handle<JSReceiver> target,
    884                                          Handle<String> module_name,
    885                                          MaybeHandle<String> import_name,
    886                                          ModuleOrigin origin) {
    887   WasmFunction* other_func = GetWasmFunctionForImportWrapper(isolate, target);
    888   if (other_func) {
    889     if (sig->Equals(other_func->sig)) {
    890       // Signature matched. Unwrap the JS->WASM wrapper and return the raw
    891       // WASM function code.
    892       return UnwrapImportWrapper(target);
    893     } else {
    894       return Handle<Code>::null();
    895     }
    896   } else {
    897     // Signature mismatch. Compile a new wrapper for the new signature.
    898     return compiler::CompileWasmToJSWrapper(isolate, target, sig, index,
    899                                             module_name, import_name, origin);
    900   }
    901 }
    902 
    903 static void UpdateDispatchTablesInternal(Isolate* isolate,
    904                                          Handle<FixedArray> dispatch_tables,
    905                                          int index, WasmFunction* function,
    906                                          Handle<Code> code) {
    907   DCHECK_EQ(0, dispatch_tables->length() % 4);
    908   for (int i = 0; i < dispatch_tables->length(); i += 4) {
    909     int table_index = Smi::cast(dispatch_tables->get(i + 1))->value();
    910     Handle<FixedArray> function_table(
    911         FixedArray::cast(dispatch_tables->get(i + 2)), isolate);
    912     Handle<FixedArray> signature_table(
    913         FixedArray::cast(dispatch_tables->get(i + 3)), isolate);
    914     if (function) {
    915       // TODO(titzer): the signature might need to be copied to avoid
    916       // a dangling pointer in the signature map.
    917       Handle<WasmInstanceObject> instance(
    918           WasmInstanceObject::cast(dispatch_tables->get(i)), isolate);
    919       int sig_index = static_cast<int>(
    920           instance->module()->function_tables[table_index].map.FindOrInsert(
    921               function->sig));
    922       signature_table->set(index, Smi::FromInt(sig_index));
    923       function_table->set(index, *code);
    924     } else {
    925       Code* code = nullptr;
    926       signature_table->set(index, Smi::FromInt(-1));
    927       function_table->set(index, code);
    928     }
    929   }
    930 }
    931 
    932 void wasm::UpdateDispatchTables(Isolate* isolate,
    933                                 Handle<FixedArray> dispatch_tables, int index,
    934                                 Handle<JSFunction> function) {
    935   if (function.is_null()) {
    936     UpdateDispatchTablesInternal(isolate, dispatch_tables, index, nullptr,
    937                                  Handle<Code>::null());
    938   } else {
    939     UpdateDispatchTablesInternal(
    940         isolate, dispatch_tables, index,
    941         GetWasmFunctionForImportWrapper(isolate, function),
    942         UnwrapImportWrapper(function));
    943   }
    944 }
    945 
    946 // A helper class to simplify instantiating a module from a compiled module.
    947 // It closes over the {Isolate}, the {ErrorThrower}, the {WasmCompiledModule},
    948 // etc.
    949 class InstantiationHelper {
    950  public:
    951   InstantiationHelper(Isolate* isolate, ErrorThrower* thrower,
    952                       Handle<WasmModuleObject> module_object,
    953                       MaybeHandle<JSReceiver> ffi,
    954                       MaybeHandle<JSArrayBuffer> memory)
    955       : isolate_(isolate),
    956         module_(module_object->compiled_module()->module()),
    957         thrower_(thrower),
    958         module_object_(module_object),
    959         ffi_(ffi.is_null() ? Handle<JSReceiver>::null()
    960                            : ffi.ToHandleChecked()),
    961         memory_(memory.is_null() ? Handle<JSArrayBuffer>::null()
    962                                  : memory.ToHandleChecked()) {}
    963 
    964   // Build an instance, in all of its glory.
    965   MaybeHandle<WasmInstanceObject> Build() {
    966     // Check that an imports argument was provided, if the module requires it.
    967     // No point in continuing otherwise.
    968     if (!module_->import_table.empty() && ffi_.is_null()) {
    969       thrower_->TypeError(
    970           "Imports argument must be present and must be an object");
    971       return {};
    972     }
    973 
    974     HistogramTimerScope wasm_instantiate_module_time_scope(
    975         isolate_->counters()->wasm_instantiate_module_time());
    976     Factory* factory = isolate_->factory();
    977 
    978     //--------------------------------------------------------------------------
    979     // Reuse the compiled module (if no owner), otherwise clone.
    980     //--------------------------------------------------------------------------
    981     Handle<FixedArray> code_table;
    982     Handle<FixedArray> old_code_table;
    983     MaybeHandle<WasmInstanceObject> owner;
    984 
    985     TRACE("Starting new module instantiation\n");
    986     {
    987       // Root the owner, if any, before doing any allocations, which
    988       // may trigger GC.
    989       // Both owner and original template need to be in sync. Even
    990       // after we lose the original template handle, the code
    991       // objects we copied from it have data relative to the
    992       // instance - such as globals addresses.
    993       Handle<WasmCompiledModule> original;
    994       {
    995         DisallowHeapAllocation no_gc;
    996         original = handle(module_object_->compiled_module());
    997         if (original->has_weak_owning_instance()) {
    998           owner = handle(WasmInstanceObject::cast(
    999               original->weak_owning_instance()->value()));
   1000         }
   1001       }
   1002       DCHECK(!original.is_null());
   1003       // Always make a new copy of the code_table, since the old_code_table
   1004       // may still have placeholders for imports.
   1005       old_code_table = original->code_table();
   1006       code_table = factory->CopyFixedArray(old_code_table);
   1007 
   1008       if (original->has_weak_owning_instance()) {
   1009         // Clone, but don't insert yet the clone in the instances chain.
   1010         // We do that last. Since we are holding on to the owner instance,
   1011         // the owner + original state used for cloning and patching
   1012         // won't be mutated by possible finalizer runs.
   1013         DCHECK(!owner.is_null());
   1014         TRACE("Cloning from %d\n", original->instance_id());
   1015         compiled_module_ = WasmCompiledModule::Clone(isolate_, original);
   1016         // Avoid creating too many handles in the outer scope.
   1017         HandleScope scope(isolate_);
   1018 
   1019         // Clone the code for WASM functions and exports.
   1020         for (int i = 0; i < code_table->length(); ++i) {
   1021           Handle<Code> orig_code =
   1022               code_table->GetValueChecked<Code>(isolate_, i);
   1023           switch (orig_code->kind()) {
   1024             case Code::WASM_TO_JS_FUNCTION:
   1025               // Imports will be overwritten with newly compiled wrappers.
   1026               break;
   1027             case Code::JS_TO_WASM_FUNCTION:
   1028             case Code::WASM_FUNCTION: {
   1029               Handle<Code> code = factory->CopyCode(orig_code);
   1030               code_table->set(i, *code);
   1031               break;
   1032             }
   1033             default:
   1034               UNREACHABLE();
   1035           }
   1036         }
   1037         RecordStats(isolate_, code_table);
   1038       } else {
   1039         // There was no owner, so we can reuse the original.
   1040         compiled_module_ = original;
   1041         TRACE("Reusing existing instance %d\n",
   1042               compiled_module_->instance_id());
   1043       }
   1044       compiled_module_->set_code_table(code_table);
   1045       compiled_module_->set_native_context(isolate_->native_context());
   1046     }
   1047 
   1048     //--------------------------------------------------------------------------
   1049     // Allocate the instance object.
   1050     //--------------------------------------------------------------------------
   1051     Zone instantiation_zone(isolate_->allocator(), ZONE_NAME);
   1052     CodeSpecialization code_specialization(isolate_, &instantiation_zone);
   1053     Handle<WasmInstanceObject> instance =
   1054         WasmInstanceObject::New(isolate_, compiled_module_);
   1055 
   1056     //--------------------------------------------------------------------------
   1057     // Set up the globals for the new instance.
   1058     //--------------------------------------------------------------------------
   1059     MaybeHandle<JSArrayBuffer> old_globals;
   1060     uint32_t globals_size = module_->globals_size;
   1061     if (globals_size > 0) {
   1062       const bool enable_guard_regions = false;
   1063       Handle<JSArrayBuffer> global_buffer =
   1064           NewArrayBuffer(isolate_, globals_size, enable_guard_regions);
   1065       globals_ = global_buffer;
   1066       if (globals_.is_null()) {
   1067         thrower_->RangeError("Out of memory: wasm globals");
   1068         return {};
   1069       }
   1070       Address old_globals_start = nullptr;
   1071       if (!owner.is_null()) {
   1072         DCHECK(owner.ToHandleChecked()->has_globals_buffer());
   1073         old_globals_start = static_cast<Address>(
   1074             owner.ToHandleChecked()->globals_buffer()->backing_store());
   1075       }
   1076       Address new_globals_start =
   1077           static_cast<Address>(global_buffer->backing_store());
   1078       code_specialization.RelocateGlobals(old_globals_start, new_globals_start);
   1079       instance->set_globals_buffer(*global_buffer);
   1080     }
   1081 
   1082     //--------------------------------------------------------------------------
   1083     // Prepare for initialization of function tables.
   1084     //--------------------------------------------------------------------------
   1085     int function_table_count =
   1086         static_cast<int>(module_->function_tables.size());
   1087     table_instances_.reserve(module_->function_tables.size());
   1088     for (int index = 0; index < function_table_count; ++index) {
   1089       table_instances_.push_back(
   1090           {Handle<WasmTableObject>::null(), Handle<FixedArray>::null(),
   1091            Handle<FixedArray>::null(), Handle<FixedArray>::null()});
   1092     }
   1093 
   1094     //--------------------------------------------------------------------------
   1095     // Process the imports for the module.
   1096     //--------------------------------------------------------------------------
   1097     int num_imported_functions = ProcessImports(code_table, instance);
   1098     if (num_imported_functions < 0) return {};
   1099 
   1100     //--------------------------------------------------------------------------
   1101     // Process the initialization for the module's globals.
   1102     //--------------------------------------------------------------------------
   1103     InitGlobals();
   1104 
   1105     //--------------------------------------------------------------------------
   1106     // Set up the indirect function tables for the new instance.
   1107     //--------------------------------------------------------------------------
   1108     if (function_table_count > 0)
   1109       InitializeTables(code_table, instance, &code_specialization);
   1110 
   1111     //--------------------------------------------------------------------------
   1112     // Set up the memory for the new instance.
   1113     //--------------------------------------------------------------------------
   1114     MaybeHandle<JSArrayBuffer> old_memory;
   1115 
   1116     uint32_t min_mem_pages = module_->min_mem_pages;
   1117     isolate_->counters()->wasm_min_mem_pages_count()->AddSample(min_mem_pages);
   1118 
   1119     if (!memory_.is_null()) {
   1120       // Set externally passed ArrayBuffer non neuterable.
   1121       memory_->set_is_neuterable(false);
   1122 
   1123       DCHECK_IMPLIES(EnableGuardRegions(), module_->origin == kAsmJsOrigin ||
   1124                                                memory_->has_guard_region());
   1125     } else if (min_mem_pages > 0) {
   1126       memory_ = AllocateMemory(min_mem_pages);
   1127       if (memory_.is_null()) return {};  // failed to allocate memory
   1128     }
   1129 
   1130     //--------------------------------------------------------------------------
   1131     // Check that indirect function table segments are within bounds.
   1132     //--------------------------------------------------------------------------
   1133     for (WasmTableInit& table_init : module_->table_inits) {
   1134       DCHECK(table_init.table_index < table_instances_.size());
   1135       uint32_t base = EvalUint32InitExpr(table_init.offset);
   1136       uint32_t table_size =
   1137           table_instances_[table_init.table_index].function_table->length();
   1138       if (!in_bounds(base, static_cast<uint32_t>(table_init.entries.size()),
   1139                      table_size)) {
   1140         thrower_->LinkError("table initializer is out of bounds");
   1141         return {};
   1142       }
   1143     }
   1144 
   1145     //--------------------------------------------------------------------------
   1146     // Check that memory segments are within bounds.
   1147     //--------------------------------------------------------------------------
   1148     for (WasmDataSegment& seg : module_->data_segments) {
   1149       uint32_t base = EvalUint32InitExpr(seg.dest_addr);
   1150       uint32_t mem_size = memory_.is_null()
   1151           ? 0 : static_cast<uint32_t>(memory_->byte_length()->Number());
   1152       if (!in_bounds(base, seg.source_size, mem_size)) {
   1153         thrower_->LinkError("data segment is out of bounds");
   1154         return {};
   1155       }
   1156     }
   1157 
   1158     //--------------------------------------------------------------------------
   1159     // Initialize memory.
   1160     //--------------------------------------------------------------------------
   1161     if (!memory_.is_null()) {
   1162       instance->set_memory_buffer(*memory_);
   1163       Address mem_start = static_cast<Address>(memory_->backing_store());
   1164       uint32_t mem_size =
   1165           static_cast<uint32_t>(memory_->byte_length()->Number());
   1166       LoadDataSegments(mem_start, mem_size);
   1167 
   1168       uint32_t old_mem_size = compiled_module_->mem_size();
   1169       Address old_mem_start =
   1170           compiled_module_->has_memory()
   1171               ? static_cast<Address>(
   1172                     compiled_module_->memory()->backing_store())
   1173               : nullptr;
   1174       // We might get instantiated again with the same memory. No patching
   1175       // needed in this case.
   1176       if (old_mem_start != mem_start || old_mem_size != mem_size) {
   1177         code_specialization.RelocateMemoryReferences(
   1178             old_mem_start, old_mem_size, mem_start, mem_size);
   1179       }
   1180       compiled_module_->set_memory(memory_);
   1181     }
   1182 
   1183     //--------------------------------------------------------------------------
   1184     // Set up the runtime support for the new instance.
   1185     //--------------------------------------------------------------------------
   1186     Handle<WeakCell> weak_link = factory->NewWeakCell(instance);
   1187 
   1188     for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs;
   1189          i < code_table->length(); ++i) {
   1190       Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i);
   1191       if (code->kind() == Code::WASM_FUNCTION) {
   1192         Handle<FixedArray> deopt_data = factory->NewFixedArray(2, TENURED);
   1193         deopt_data->set(0, *weak_link);
   1194         deopt_data->set(1, Smi::FromInt(static_cast<int>(i)));
   1195         deopt_data->set_length(2);
   1196         code->set_deoptimization_data(*deopt_data);
   1197       }
   1198     }
   1199 
   1200     //--------------------------------------------------------------------------
   1201     // Set up the exports object for the new instance.
   1202     //--------------------------------------------------------------------------
   1203     ProcessExports(code_table, instance, compiled_module_);
   1204 
   1205     //--------------------------------------------------------------------------
   1206     // Add instance to Memory object
   1207     //--------------------------------------------------------------------------
   1208     DCHECK(wasm::IsWasmInstance(*instance));
   1209     if (instance->has_memory_object()) {
   1210       instance->memory_object()->AddInstance(isolate_, instance);
   1211     }
   1212 
   1213     //--------------------------------------------------------------------------
   1214     // Initialize the indirect function tables.
   1215     //--------------------------------------------------------------------------
   1216     if (function_table_count > 0) LoadTableSegments(code_table, instance);
   1217 
   1218     // Patch all code with the relocations registered in code_specialization.
   1219     {
   1220       code_specialization.RelocateDirectCalls(instance);
   1221       code_specialization.ApplyToWholeInstance(*instance, SKIP_ICACHE_FLUSH);
   1222     }
   1223 
   1224     FlushICache(isolate_, code_table);
   1225 
   1226     //--------------------------------------------------------------------------
   1227     // Unpack and notify signal handler of protected instructions.
   1228     //--------------------------------------------------------------------------
   1229     if (FLAG_wasm_trap_handler) {
   1230       for (int i = 0; i < code_table->length(); ++i) {
   1231         Handle<Code> code = code_table->GetValueChecked<Code>(isolate_, i);
   1232 
   1233         if (code->kind() != Code::WASM_FUNCTION) {
   1234           continue;
   1235         }
   1236 
   1237         const intptr_t base = reinterpret_cast<intptr_t>(code->entry());
   1238 
   1239         Zone zone(isolate_->allocator(), "Wasm Module");
   1240         ZoneVector<trap_handler::ProtectedInstructionData> unpacked(&zone);
   1241         const int mode_mask =
   1242             RelocInfo::ModeMask(RelocInfo::WASM_PROTECTED_INSTRUCTION_LANDING);
   1243         for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
   1244           trap_handler::ProtectedInstructionData data;
   1245           data.instr_offset = it.rinfo()->data();
   1246           data.landing_offset =
   1247               reinterpret_cast<intptr_t>(it.rinfo()->pc()) - base;
   1248           unpacked.emplace_back(data);
   1249         }
   1250         // TODO(eholk): Register the protected instruction information once the
   1251         // trap handler is in place.
   1252       }
   1253     }
   1254 
   1255     //--------------------------------------------------------------------------
   1256     // Set up and link the new instance.
   1257     //--------------------------------------------------------------------------
   1258     {
   1259       Handle<Object> global_handle =
   1260           isolate_->global_handles()->Create(*instance);
   1261       Handle<WeakCell> link_to_clone = factory->NewWeakCell(compiled_module_);
   1262       Handle<WeakCell> link_to_owning_instance = factory->NewWeakCell(instance);
   1263       MaybeHandle<WeakCell> link_to_original;
   1264       MaybeHandle<WasmCompiledModule> original;
   1265       if (!owner.is_null()) {
   1266         // prepare the data needed for publishing in a chain, but don't link
   1267         // just yet, because
   1268         // we want all the publishing to happen free from GC interruptions, and
   1269         // so we do it in
   1270         // one GC-free scope afterwards.
   1271         original = handle(owner.ToHandleChecked()->compiled_module());
   1272         link_to_original = factory->NewWeakCell(original.ToHandleChecked());
   1273       }
   1274       // Publish the new instance to the instances chain.
   1275       {
   1276         DisallowHeapAllocation no_gc;
   1277         if (!link_to_original.is_null()) {
   1278           compiled_module_->set_weak_next_instance(
   1279               link_to_original.ToHandleChecked());
   1280           original.ToHandleChecked()->set_weak_prev_instance(link_to_clone);
   1281           compiled_module_->set_weak_wasm_module(
   1282               original.ToHandleChecked()->weak_wasm_module());
   1283         }
   1284         module_object_->SetInternalField(0, *compiled_module_);
   1285         compiled_module_->set_weak_owning_instance(link_to_owning_instance);
   1286         GlobalHandles::MakeWeak(global_handle.location(),
   1287                                 global_handle.location(), &InstanceFinalizer,
   1288                                 v8::WeakCallbackType::kFinalizer);
   1289       }
   1290     }
   1291 
   1292     //--------------------------------------------------------------------------
   1293     // Set all breakpoints that were set on the shared module.
   1294     //--------------------------------------------------------------------------
   1295     WasmSharedModuleData::SetBreakpointsOnNewInstance(
   1296         compiled_module_->shared(), instance);
   1297 
   1298     //--------------------------------------------------------------------------
   1299     // Run the start function if one was specified.
   1300     //--------------------------------------------------------------------------
   1301     if (module_->start_function_index >= 0) {
   1302       HandleScope scope(isolate_);
   1303       int start_index = module_->start_function_index;
   1304       Handle<Code> startup_code =
   1305           code_table->GetValueChecked<Code>(isolate_, start_index);
   1306       FunctionSig* sig = module_->functions[start_index].sig;
   1307       Handle<Code> wrapper_code =
   1308           js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper(
   1309               isolate_, module_, startup_code, start_index);
   1310       Handle<WasmExportedFunction> startup_fct = WasmExportedFunction::New(
   1311           isolate_, instance, MaybeHandle<String>(), start_index,
   1312           static_cast<int>(sig->parameter_count()), wrapper_code);
   1313       RecordStats(isolate_, *startup_code);
   1314       // Call the JS function.
   1315       Handle<Object> undefined = factory->undefined_value();
   1316       MaybeHandle<Object> retval =
   1317           Execution::Call(isolate_, startup_fct, undefined, 0, nullptr);
   1318 
   1319       if (retval.is_null()) {
   1320         DCHECK(isolate_->has_pending_exception());
   1321         isolate_->OptionalRescheduleException(false);
   1322         // It's unfortunate that the new instance is already linked in the
   1323         // chain. However, we need to set up everything before executing the
   1324         // start function, such that stack trace information can be generated
   1325         // correctly already in the start function.
   1326         return {};
   1327       }
   1328     }
   1329 
   1330     DCHECK(!isolate_->has_pending_exception());
   1331     TRACE("Finishing instance %d\n", compiled_module_->instance_id());
   1332     TRACE_CHAIN(module_object_->compiled_module());
   1333     return instance;
   1334   }
   1335 
   1336  private:
   1337   // Represents the initialized state of a table.
   1338   struct TableInstance {
   1339     Handle<WasmTableObject> table_object;    // WebAssembly.Table instance
   1340     Handle<FixedArray> js_wrappers;          // JSFunctions exported
   1341     Handle<FixedArray> function_table;       // internal code array
   1342     Handle<FixedArray> signature_table;      // internal sig array
   1343   };
   1344 
   1345   Isolate* isolate_;
   1346   WasmModule* const module_;
   1347   ErrorThrower* thrower_;
   1348   Handle<WasmModuleObject> module_object_;
   1349   Handle<JSReceiver> ffi_;        // TODO(titzer): Use MaybeHandle
   1350   Handle<JSArrayBuffer> memory_;  // TODO(titzer): Use MaybeHandle
   1351   Handle<JSArrayBuffer> globals_;
   1352   Handle<WasmCompiledModule> compiled_module_;
   1353   std::vector<TableInstance> table_instances_;
   1354   std::vector<Handle<JSFunction>> js_wrappers_;
   1355   JSToWasmWrapperCache js_to_wasm_cache_;
   1356 
   1357   // Helper routines to print out errors with imports.
   1358   void ReportLinkError(const char* error, uint32_t index,
   1359                        Handle<String> module_name, Handle<String> import_name) {
   1360     thrower_->LinkError(
   1361         "Import #%d module=\"%.*s\" function=\"%.*s\" error: %s", index,
   1362         module_name->length(), module_name->ToCString().get(),
   1363         import_name->length(), import_name->ToCString().get(), error);
   1364   }
   1365 
   1366   MaybeHandle<Object> ReportLinkError(const char* error, uint32_t index,
   1367                                       Handle<String> module_name) {
   1368     thrower_->LinkError("Import #%d module=\"%.*s\" error: %s", index,
   1369                         module_name->length(), module_name->ToCString().get(),
   1370                         error);
   1371     return MaybeHandle<Object>();
   1372   }
   1373 
   1374   // Look up an import value in the {ffi_} object.
   1375   MaybeHandle<Object> LookupImport(uint32_t index, Handle<String> module_name,
   1376                                    Handle<String> import_name) {
   1377     // We pre-validated in the js-api layer that the ffi object is present, and
   1378     // a JSObject, if the module has imports.
   1379     DCHECK(!ffi_.is_null());
   1380 
   1381     // Look up the module first.
   1382     MaybeHandle<Object> result =
   1383         Object::GetPropertyOrElement(ffi_, module_name);
   1384     if (result.is_null()) {
   1385       return ReportLinkError("module not found", index, module_name);
   1386     }
   1387 
   1388     Handle<Object> module = result.ToHandleChecked();
   1389 
   1390     // Look up the value in the module.
   1391     if (!module->IsJSReceiver()) {
   1392       return ReportLinkError("module is not an object or function", index,
   1393                              module_name);
   1394     }
   1395 
   1396     result = Object::GetPropertyOrElement(module, import_name);
   1397     if (result.is_null()) {
   1398       ReportLinkError("import not found", index, module_name, import_name);
   1399       return MaybeHandle<JSFunction>();
   1400     }
   1401 
   1402     return result;
   1403   }
   1404 
   1405   uint32_t EvalUint32InitExpr(const WasmInitExpr& expr) {
   1406     switch (expr.kind) {
   1407       case WasmInitExpr::kI32Const:
   1408         return expr.val.i32_const;
   1409       case WasmInitExpr::kGlobalIndex: {
   1410         uint32_t offset = module_->globals[expr.val.global_index].offset;
   1411         return *reinterpret_cast<uint32_t*>(raw_buffer_ptr(globals_, offset));
   1412       }
   1413       default:
   1414         UNREACHABLE();
   1415         return 0;
   1416     }
   1417   }
   1418 
   1419   bool in_bounds(uint32_t offset, uint32_t size, uint32_t upper) {
   1420     return offset + size <= upper && offset + size >= offset;
   1421   }
   1422 
   1423   // Load data segments into the memory.
   1424   void LoadDataSegments(Address mem_addr, size_t mem_size) {
   1425     Handle<SeqOneByteString> module_bytes(compiled_module_->module_bytes(),
   1426                                           isolate_);
   1427     for (const WasmDataSegment& segment : module_->data_segments) {
   1428       uint32_t source_size = segment.source_size;
   1429       // Segments of size == 0 are just nops.
   1430       if (source_size == 0) continue;
   1431       uint32_t dest_offset = EvalUint32InitExpr(segment.dest_addr);
   1432       DCHECK(in_bounds(dest_offset, source_size,
   1433                        static_cast<uint32_t>(mem_size)));
   1434       byte* dest = mem_addr + dest_offset;
   1435       const byte* src = reinterpret_cast<const byte*>(
   1436           module_bytes->GetCharsAddress() + segment.source_offset);
   1437       memcpy(dest, src, source_size);
   1438     }
   1439   }
   1440 
   1441   void WriteGlobalValue(WasmGlobal& global, Handle<Object> value) {
   1442     double num = 0;
   1443     if (value->IsSmi()) {
   1444       num = Smi::cast(*value)->value();
   1445     } else if (value->IsHeapNumber()) {
   1446       num = HeapNumber::cast(*value)->value();
   1447     } else {
   1448       UNREACHABLE();
   1449     }
   1450     TRACE("init [globals+%u] = %lf, type = %s\n", global.offset, num,
   1451           WasmOpcodes::TypeName(global.type));
   1452     switch (global.type) {
   1453       case kWasmI32:
   1454         *GetRawGlobalPtr<int32_t>(global) = static_cast<int32_t>(num);
   1455         break;
   1456       case kWasmI64:
   1457         // TODO(titzer): initialization of imported i64 globals.
   1458         UNREACHABLE();
   1459         break;
   1460       case kWasmF32:
   1461         *GetRawGlobalPtr<float>(global) = static_cast<float>(num);
   1462         break;
   1463       case kWasmF64:
   1464         *GetRawGlobalPtr<double>(global) = static_cast<double>(num);
   1465         break;
   1466       default:
   1467         UNREACHABLE();
   1468     }
   1469   }
   1470 
   1471   // Process the imports, including functions, tables, globals, and memory, in
   1472   // order, loading them from the {ffi_} object. Returns the number of imported
   1473   // functions.
   1474   int ProcessImports(Handle<FixedArray> code_table,
   1475                      Handle<WasmInstanceObject> instance) {
   1476     int num_imported_functions = 0;
   1477     int num_imported_tables = 0;
   1478     for (int index = 0; index < static_cast<int>(module_->import_table.size());
   1479          ++index) {
   1480       WasmImport& import = module_->import_table[index];
   1481 
   1482       Handle<String> module_name;
   1483       MaybeHandle<String> maybe_module_name =
   1484           WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
   1485               isolate_, compiled_module_, import.module_name_offset,
   1486               import.module_name_length);
   1487       if (!maybe_module_name.ToHandle(&module_name)) return -1;
   1488 
   1489       Handle<String> import_name;
   1490       MaybeHandle<String> maybe_import_name =
   1491           WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
   1492               isolate_, compiled_module_, import.field_name_offset,
   1493               import.field_name_length);
   1494       if (!maybe_import_name.ToHandle(&import_name)) return -1;
   1495 
   1496       MaybeHandle<Object> result =
   1497           LookupImport(index, module_name, import_name);
   1498       if (thrower_->error()) return -1;
   1499       Handle<Object> value = result.ToHandleChecked();
   1500 
   1501       switch (import.kind) {
   1502         case kExternalFunction: {
   1503           // Function imports must be callable.
   1504           if (!value->IsCallable()) {
   1505             ReportLinkError("function import requires a callable", index,
   1506                             module_name, import_name);
   1507             return -1;
   1508           }
   1509 
   1510           Handle<Code> import_wrapper = CompileImportWrapper(
   1511               isolate_, index, module_->functions[import.index].sig,
   1512               Handle<JSReceiver>::cast(value), module_name, import_name,
   1513               module_->origin);
   1514           if (import_wrapper.is_null()) {
   1515             ReportLinkError(
   1516                 "imported function does not match the expected type", index,
   1517                 module_name, import_name);
   1518             return -1;
   1519           }
   1520           code_table->set(num_imported_functions, *import_wrapper);
   1521           RecordStats(isolate_, *import_wrapper);
   1522           num_imported_functions++;
   1523           break;
   1524         }
   1525         case kExternalTable: {
   1526           if (!WasmJs::IsWasmTableObject(isolate_, value)) {
   1527             ReportLinkError("table import requires a WebAssembly.Table", index,
   1528                             module_name, import_name);
   1529             return -1;
   1530           }
   1531           WasmIndirectFunctionTable& table =
   1532               module_->function_tables[num_imported_tables];
   1533           TableInstance& table_instance = table_instances_[num_imported_tables];
   1534           table_instance.table_object = Handle<WasmTableObject>::cast(value);
   1535           table_instance.js_wrappers = Handle<FixedArray>(
   1536               table_instance.table_object->functions(), isolate_);
   1537 
   1538           int imported_cur_size = table_instance.js_wrappers->length();
   1539           if (imported_cur_size < static_cast<int>(table.min_size)) {
   1540             thrower_->LinkError(
   1541                 "table import %d is smaller than minimum %d, got %u", index,
   1542                 table.min_size, imported_cur_size);
   1543             return -1;
   1544           }
   1545 
   1546           if (table.has_max) {
   1547             int64_t imported_max_size =
   1548                 table_instance.table_object->maximum_length();
   1549             if (imported_max_size < 0) {
   1550               thrower_->LinkError(
   1551                   "table import %d has no maximum length, expected %d", index,
   1552                   table.max_size);
   1553               return -1;
   1554             }
   1555             if (imported_max_size > table.max_size) {
   1556               thrower_->LinkError(
   1557                   "table import %d has maximum larger than maximum %d, "
   1558                   "got %" PRIx64,
   1559                   index, table.max_size, imported_max_size);
   1560               return -1;
   1561             }
   1562           }
   1563 
   1564           // Allocate a new dispatch table and signature table.
   1565           int table_size = imported_cur_size;
   1566           table_instance.function_table =
   1567               isolate_->factory()->NewFixedArray(table_size);
   1568           table_instance.signature_table =
   1569               isolate_->factory()->NewFixedArray(table_size);
   1570           for (int i = 0; i < table_size; ++i) {
   1571             table_instance.signature_table->set(i,
   1572                                                 Smi::FromInt(kInvalidSigIndex));
   1573           }
   1574           // Initialize the dispatch table with the (foreign) JS functions
   1575           // that are already in the table.
   1576           for (int i = 0; i < table_size; ++i) {
   1577             Handle<Object> val(table_instance.js_wrappers->get(i), isolate_);
   1578             if (!val->IsJSFunction()) continue;
   1579             WasmFunction* function =
   1580                 GetWasmFunctionForImportWrapper(isolate_, val);
   1581             if (function == nullptr) {
   1582               thrower_->LinkError("table import %d[%d] is not a WASM function",
   1583                                   index, i);
   1584               return -1;
   1585             }
   1586             int sig_index = table.map.FindOrInsert(function->sig);
   1587             table_instance.signature_table->set(i, Smi::FromInt(sig_index));
   1588             table_instance.function_table->set(i, *UnwrapImportWrapper(val));
   1589           }
   1590 
   1591           num_imported_tables++;
   1592           break;
   1593         }
   1594         case kExternalMemory: {
   1595           // Validation should have failed if more than one memory object was
   1596           // provided.
   1597           DCHECK(!instance->has_memory_object());
   1598           if (!WasmJs::IsWasmMemoryObject(isolate_, value)) {
   1599             ReportLinkError("memory import must be a WebAssembly.Memory object",
   1600                             index, module_name, import_name);
   1601             return -1;
   1602           }
   1603           auto memory = Handle<WasmMemoryObject>::cast(value);
   1604           DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory));
   1605           instance->set_memory_object(*memory);
   1606           memory_ = Handle<JSArrayBuffer>(memory->buffer(), isolate_);
   1607           uint32_t imported_cur_pages = static_cast<uint32_t>(
   1608               memory_->byte_length()->Number() / WasmModule::kPageSize);
   1609           if (imported_cur_pages < module_->min_mem_pages) {
   1610             thrower_->LinkError(
   1611                 "memory import %d is smaller than maximum %u, got %u", index,
   1612                 module_->min_mem_pages, imported_cur_pages);
   1613           }
   1614           int32_t imported_max_pages = memory->maximum_pages();
   1615           if (module_->has_max_mem) {
   1616             if (imported_max_pages < 0) {
   1617               thrower_->LinkError(
   1618                   "memory import %d has no maximum limit, expected at most %u",
   1619                   index, imported_max_pages);
   1620               return -1;
   1621             }
   1622             if (static_cast<uint32_t>(imported_max_pages) >
   1623                 module_->max_mem_pages) {
   1624               thrower_->LinkError(
   1625                   "memory import %d has larger maximum than maximum %u, got %d",
   1626                   index, module_->max_mem_pages, imported_max_pages);
   1627               return -1;
   1628             }
   1629           }
   1630           break;
   1631         }
   1632         case kExternalGlobal: {
   1633           // Global imports are converted to numbers and written into the
   1634           // {globals_} array buffer.
   1635           if (module_->globals[import.index].type == kWasmI64) {
   1636             ReportLinkError("global import cannot have type i64", index,
   1637                             module_name, import_name);
   1638             return -1;
   1639           }
   1640           if (!value->IsNumber()) {
   1641             ReportLinkError("global import must be a number", index,
   1642                             module_name, import_name);
   1643             return -1;
   1644           }
   1645           WriteGlobalValue(module_->globals[import.index], value);
   1646           break;
   1647         }
   1648         default:
   1649           UNREACHABLE();
   1650           break;
   1651       }
   1652     }
   1653     return num_imported_functions;
   1654   }
   1655 
   1656   template <typename T>
   1657   T* GetRawGlobalPtr(WasmGlobal& global) {
   1658     return reinterpret_cast<T*>(raw_buffer_ptr(globals_, global.offset));
   1659   }
   1660 
   1661   // Process initialization of globals.
   1662   void InitGlobals() {
   1663     for (auto global : module_->globals) {
   1664       switch (global.init.kind) {
   1665         case WasmInitExpr::kI32Const:
   1666           *GetRawGlobalPtr<int32_t>(global) = global.init.val.i32_const;
   1667           break;
   1668         case WasmInitExpr::kI64Const:
   1669           *GetRawGlobalPtr<int64_t>(global) = global.init.val.i64_const;
   1670           break;
   1671         case WasmInitExpr::kF32Const:
   1672           *GetRawGlobalPtr<float>(global) = global.init.val.f32_const;
   1673           break;
   1674         case WasmInitExpr::kF64Const:
   1675           *GetRawGlobalPtr<double>(global) = global.init.val.f64_const;
   1676           break;
   1677         case WasmInitExpr::kGlobalIndex: {
   1678           // Initialize with another global.
   1679           uint32_t new_offset = global.offset;
   1680           uint32_t old_offset =
   1681               module_->globals[global.init.val.global_index].offset;
   1682           TRACE("init [globals+%u] = [globals+%d]\n", global.offset,
   1683                 old_offset);
   1684           size_t size = (global.type == kWasmI64 || global.type == kWasmF64)
   1685                             ? sizeof(double)
   1686                             : sizeof(int32_t);
   1687           memcpy(raw_buffer_ptr(globals_, new_offset),
   1688                  raw_buffer_ptr(globals_, old_offset), size);
   1689           break;
   1690         }
   1691         case WasmInitExpr::kNone:
   1692           // Happens with imported globals.
   1693           break;
   1694         default:
   1695           UNREACHABLE();
   1696           break;
   1697       }
   1698     }
   1699   }
   1700 
   1701   // Allocate memory for a module instance as a new JSArrayBuffer.
   1702   Handle<JSArrayBuffer> AllocateMemory(uint32_t min_mem_pages) {
   1703     if (min_mem_pages > FLAG_wasm_max_mem_pages) {
   1704       thrower_->RangeError("Out of memory: wasm memory too large");
   1705       return Handle<JSArrayBuffer>::null();
   1706     }
   1707     const bool enable_guard_regions = EnableGuardRegions();
   1708     Handle<JSArrayBuffer> mem_buffer = NewArrayBuffer(
   1709         isolate_, min_mem_pages * WasmModule::kPageSize, enable_guard_regions);
   1710 
   1711     if (mem_buffer.is_null()) {
   1712       thrower_->RangeError("Out of memory: wasm memory");
   1713     }
   1714     return mem_buffer;
   1715   }
   1716 
   1717   bool NeedsWrappers() {
   1718     if (module_->num_exported_functions > 0) return true;
   1719     for (auto table_instance : table_instances_) {
   1720       if (!table_instance.js_wrappers.is_null()) return true;
   1721     }
   1722     for (auto table : module_->function_tables) {
   1723       if (table.exported) return true;
   1724     }
   1725     return false;
   1726   }
   1727 
   1728   // Process the exports, creating wrappers for functions, tables, memories,
   1729   // and globals.
   1730   void ProcessExports(Handle<FixedArray> code_table,
   1731                       Handle<WasmInstanceObject> instance,
   1732                       Handle<WasmCompiledModule> compiled_module) {
   1733     if (NeedsWrappers()) {
   1734       // Fill the table to cache the exported JSFunction wrappers.
   1735       js_wrappers_.insert(js_wrappers_.begin(), module_->functions.size(),
   1736                           Handle<JSFunction>::null());
   1737     }
   1738 
   1739     Handle<JSObject> exports_object;
   1740     if (module_->origin == kWasmOrigin) {
   1741       // Create the "exports" object.
   1742       exports_object = isolate_->factory()->NewJSObjectWithNullProto();
   1743     } else if (module_->origin == kAsmJsOrigin) {
   1744       Handle<JSFunction> object_function = Handle<JSFunction>(
   1745           isolate_->native_context()->object_function(), isolate_);
   1746       exports_object = isolate_->factory()->NewJSObject(object_function);
   1747     } else {
   1748       UNREACHABLE();
   1749     }
   1750     Handle<String> exports_name =
   1751         isolate_->factory()->InternalizeUtf8String("exports");
   1752     JSObject::AddProperty(instance, exports_name, exports_object, NONE);
   1753 
   1754     Handle<String> foreign_init_name =
   1755         isolate_->factory()->InternalizeUtf8String(
   1756             wasm::AsmWasmBuilder::foreign_init_name);
   1757     Handle<String> single_function_name =
   1758         isolate_->factory()->InternalizeUtf8String(
   1759             wasm::AsmWasmBuilder::single_function_name);
   1760 
   1761     PropertyDescriptor desc;
   1762     desc.set_writable(module_->origin == kAsmJsOrigin);
   1763     desc.set_enumerable(true);
   1764 
   1765     // Count up export indexes.
   1766     int export_index = 0;
   1767     for (auto exp : module_->export_table) {
   1768       if (exp.kind == kExternalFunction) {
   1769         ++export_index;
   1770       }
   1771     }
   1772 
   1773     // Store weak references to all exported functions.
   1774     Handle<FixedArray> weak_exported_functions;
   1775     if (compiled_module->has_weak_exported_functions()) {
   1776       weak_exported_functions = compiled_module->weak_exported_functions();
   1777     } else {
   1778       weak_exported_functions =
   1779           isolate_->factory()->NewFixedArray(export_index);
   1780       compiled_module->set_weak_exported_functions(weak_exported_functions);
   1781     }
   1782     DCHECK_EQ(export_index, weak_exported_functions->length());
   1783 
   1784     // Process each export in the export table (go in reverse so asm.js
   1785     // can skip duplicates).
   1786     for (auto exp : base::Reversed(module_->export_table)) {
   1787       Handle<String> name =
   1788           WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
   1789               isolate_, compiled_module_, exp.name_offset, exp.name_length)
   1790               .ToHandleChecked();
   1791       Handle<JSObject> export_to;
   1792       if (module_->origin == kAsmJsOrigin && exp.kind == kExternalFunction &&
   1793           (String::Equals(name, foreign_init_name) ||
   1794            String::Equals(name, single_function_name))) {
   1795         export_to = instance;
   1796       } else {
   1797         export_to = exports_object;
   1798       }
   1799 
   1800       switch (exp.kind) {
   1801         case kExternalFunction: {
   1802           // Wrap and export the code as a JSFunction.
   1803           WasmFunction& function = module_->functions[exp.index];
   1804           int func_index =
   1805               static_cast<int>(module_->functions.size() + --export_index);
   1806           Handle<JSFunction> js_function = js_wrappers_[exp.index];
   1807           if (js_function.is_null()) {
   1808             // Wrap the exported code as a JSFunction.
   1809             Handle<Code> export_code =
   1810                 code_table->GetValueChecked<Code>(isolate_, func_index);
   1811             MaybeHandle<String> func_name;
   1812             if (module_->origin == kAsmJsOrigin) {
   1813               // For modules arising from asm.js, honor the names section.
   1814               func_name = WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
   1815                               isolate_, compiled_module_, function.name_offset,
   1816                               function.name_length)
   1817                               .ToHandleChecked();
   1818             }
   1819             js_function = WasmExportedFunction::New(
   1820                 isolate_, instance, func_name, function.func_index,
   1821                 static_cast<int>(function.sig->parameter_count()), export_code);
   1822             js_wrappers_[exp.index] = js_function;
   1823           }
   1824           desc.set_value(js_function);
   1825           Handle<WeakCell> weak_export =
   1826               isolate_->factory()->NewWeakCell(js_function);
   1827           DCHECK_GT(weak_exported_functions->length(), export_index);
   1828           weak_exported_functions->set(export_index, *weak_export);
   1829           break;
   1830         }
   1831         case kExternalTable: {
   1832           // Export a table as a WebAssembly.Table object.
   1833           TableInstance& table_instance = table_instances_[exp.index];
   1834           WasmIndirectFunctionTable& table =
   1835               module_->function_tables[exp.index];
   1836           if (table_instance.table_object.is_null()) {
   1837             uint32_t maximum =
   1838                 table.has_max ? table.max_size : FLAG_wasm_max_table_size;
   1839             table_instance.table_object = WasmTableObject::New(
   1840                 isolate_, table.min_size, maximum, &table_instance.js_wrappers);
   1841           }
   1842           desc.set_value(table_instance.table_object);
   1843           break;
   1844         }
   1845         case kExternalMemory: {
   1846           // Export the memory as a WebAssembly.Memory object.
   1847           Handle<WasmMemoryObject> memory_object;
   1848           if (!instance->has_memory_object()) {
   1849             // If there was no imported WebAssembly.Memory object, create one.
   1850             Handle<JSArrayBuffer> buffer(instance->memory_buffer(), isolate_);
   1851             memory_object = WasmMemoryObject::New(
   1852                 isolate_, buffer,
   1853                 (module_->max_mem_pages != 0) ? module_->max_mem_pages : -1);
   1854             instance->set_memory_object(*memory_object);
   1855           } else {
   1856             memory_object =
   1857                 Handle<WasmMemoryObject>(instance->memory_object(), isolate_);
   1858             DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory_object));
   1859             memory_object->ResetInstancesLink(isolate_);
   1860           }
   1861 
   1862           desc.set_value(memory_object);
   1863           break;
   1864         }
   1865         case kExternalGlobal: {
   1866           // Export the value of the global variable as a number.
   1867           WasmGlobal& global = module_->globals[exp.index];
   1868           double num = 0;
   1869           switch (global.type) {
   1870             case kWasmI32:
   1871               num = *GetRawGlobalPtr<int32_t>(global);
   1872               break;
   1873             case kWasmF32:
   1874               num = *GetRawGlobalPtr<float>(global);
   1875               break;
   1876             case kWasmF64:
   1877               num = *GetRawGlobalPtr<double>(global);
   1878               break;
   1879             case kWasmI64:
   1880               thrower_->LinkError(
   1881                   "export of globals of type I64 is not allowed.");
   1882               break;
   1883             default:
   1884               UNREACHABLE();
   1885           }
   1886           desc.set_value(isolate_->factory()->NewNumber(num));
   1887           break;
   1888         }
   1889         default:
   1890           UNREACHABLE();
   1891           break;
   1892       }
   1893 
   1894       // Skip duplicates for asm.js.
   1895       if (module_->origin == kAsmJsOrigin) {
   1896         v8::Maybe<bool> status = JSReceiver::HasOwnProperty(export_to, name);
   1897         if (status.FromMaybe(false)) {
   1898           continue;
   1899         }
   1900       }
   1901       v8::Maybe<bool> status = JSReceiver::DefineOwnProperty(
   1902           isolate_, export_to, name, &desc, Object::THROW_ON_ERROR);
   1903       if (!status.IsJust()) {
   1904         thrower_->LinkError("export of %.*s failed.", name->length(),
   1905                             name->ToCString().get());
   1906         return;
   1907       }
   1908     }
   1909 
   1910     if (module_->origin == kWasmOrigin) {
   1911       v8::Maybe<bool> success = JSReceiver::SetIntegrityLevel(
   1912           exports_object, FROZEN, Object::DONT_THROW);
   1913       DCHECK(success.FromMaybe(false));
   1914       USE(success);
   1915     }
   1916   }
   1917 
   1918   void InitializeTables(Handle<FixedArray> code_table,
   1919                         Handle<WasmInstanceObject> instance,
   1920                         CodeSpecialization* code_specialization) {
   1921     int function_table_count =
   1922         static_cast<int>(module_->function_tables.size());
   1923     Handle<FixedArray> new_function_tables =
   1924         isolate_->factory()->NewFixedArray(function_table_count);
   1925     Handle<FixedArray> new_signature_tables =
   1926         isolate_->factory()->NewFixedArray(function_table_count);
   1927     for (int index = 0; index < function_table_count; ++index) {
   1928       WasmIndirectFunctionTable& table = module_->function_tables[index];
   1929       TableInstance& table_instance = table_instances_[index];
   1930       int table_size = static_cast<int>(table.min_size);
   1931 
   1932       if (table_instance.function_table.is_null()) {
   1933         // Create a new dispatch table if necessary.
   1934         table_instance.function_table =
   1935             isolate_->factory()->NewFixedArray(table_size);
   1936         table_instance.signature_table =
   1937             isolate_->factory()->NewFixedArray(table_size);
   1938         for (int i = 0; i < table_size; ++i) {
   1939           // Fill the table with invalid signature indexes so that
   1940           // uninitialized entries will always fail the signature check.
   1941           table_instance.signature_table->set(i,
   1942                                               Smi::FromInt(kInvalidSigIndex));
   1943         }
   1944       } else {
   1945         // Table is imported, patch table bounds check
   1946         DCHECK(table_size <= table_instance.function_table->length());
   1947         if (table_size < table_instance.function_table->length()) {
   1948           code_specialization->PatchTableSize(
   1949               table_size, table_instance.function_table->length());
   1950         }
   1951       }
   1952 
   1953       new_function_tables->set(static_cast<int>(index),
   1954                                *table_instance.function_table);
   1955       new_signature_tables->set(static_cast<int>(index),
   1956                                 *table_instance.signature_table);
   1957     }
   1958 
   1959     FixedArray* old_function_tables =
   1960         compiled_module_->ptr_to_function_tables();
   1961     DCHECK_EQ(old_function_tables->length(), new_function_tables->length());
   1962     for (int i = 0, e = new_function_tables->length(); i < e; ++i) {
   1963       code_specialization->RelocateObject(
   1964           handle(old_function_tables->get(i), isolate_),
   1965           handle(new_function_tables->get(i), isolate_));
   1966     }
   1967     FixedArray* old_signature_tables =
   1968         compiled_module_->ptr_to_signature_tables();
   1969     DCHECK_EQ(old_signature_tables->length(), new_signature_tables->length());
   1970     for (int i = 0, e = new_signature_tables->length(); i < e; ++i) {
   1971       code_specialization->RelocateObject(
   1972           handle(old_signature_tables->get(i), isolate_),
   1973           handle(new_signature_tables->get(i), isolate_));
   1974     }
   1975 
   1976     compiled_module_->set_function_tables(new_function_tables);
   1977     compiled_module_->set_signature_tables(new_signature_tables);
   1978   }
   1979 
   1980   void LoadTableSegments(Handle<FixedArray> code_table,
   1981                          Handle<WasmInstanceObject> instance) {
   1982     int function_table_count =
   1983         static_cast<int>(module_->function_tables.size());
   1984     for (int index = 0; index < function_table_count; ++index) {
   1985       WasmIndirectFunctionTable& table = module_->function_tables[index];
   1986       TableInstance& table_instance = table_instances_[index];
   1987 
   1988       Handle<FixedArray> all_dispatch_tables;
   1989       if (!table_instance.table_object.is_null()) {
   1990         // Get the existing dispatch table(s) with the WebAssembly.Table object.
   1991         all_dispatch_tables = WasmTableObject::AddDispatchTable(
   1992             isolate_, table_instance.table_object,
   1993             Handle<WasmInstanceObject>::null(), index,
   1994             Handle<FixedArray>::null(), Handle<FixedArray>::null());
   1995       }
   1996 
   1997       // TODO(titzer): this does redundant work if there are multiple tables,
   1998       // since initializations are not sorted by table index.
   1999       for (auto table_init : module_->table_inits) {
   2000         uint32_t base = EvalUint32InitExpr(table_init.offset);
   2001         DCHECK(in_bounds(base, static_cast<uint32_t>(table_init.entries.size()),
   2002                          table_instance.function_table->length()));
   2003         for (int i = 0; i < static_cast<int>(table_init.entries.size()); ++i) {
   2004           uint32_t func_index = table_init.entries[i];
   2005           WasmFunction* function = &module_->functions[func_index];
   2006           int table_index = static_cast<int>(i + base);
   2007           int32_t sig_index = table.map.Find(function->sig);
   2008           DCHECK_GE(sig_index, 0);
   2009           table_instance.signature_table->set(table_index,
   2010                                               Smi::FromInt(sig_index));
   2011           table_instance.function_table->set(table_index,
   2012                                              code_table->get(func_index));
   2013 
   2014           if (!all_dispatch_tables.is_null()) {
   2015             Handle<Code> wasm_code(Code::cast(code_table->get(func_index)),
   2016                                    isolate_);
   2017             if (js_wrappers_[func_index].is_null()) {
   2018               // No JSFunction entry yet exists for this function. Create one.
   2019               // TODO(titzer): We compile JS->WASM wrappers for functions are
   2020               // not exported but are in an exported table. This should be done
   2021               // at module compile time and cached instead.
   2022 
   2023               Handle<Code> wrapper_code =
   2024                   js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper(
   2025                       isolate_, module_, wasm_code, func_index);
   2026               MaybeHandle<String> func_name;
   2027               if (module_->origin == kAsmJsOrigin) {
   2028                 // For modules arising from asm.js, honor the names section.
   2029                 func_name =
   2030                     WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
   2031                         isolate_, compiled_module_, function->name_offset,
   2032                         function->name_length)
   2033                         .ToHandleChecked();
   2034               }
   2035               Handle<WasmExportedFunction> js_function =
   2036                   WasmExportedFunction::New(
   2037                       isolate_, instance, func_name, func_index,
   2038                       static_cast<int>(function->sig->parameter_count()),
   2039                       wrapper_code);
   2040               js_wrappers_[func_index] = js_function;
   2041             }
   2042             table_instance.js_wrappers->set(table_index,
   2043                                             *js_wrappers_[func_index]);
   2044 
   2045             UpdateDispatchTablesInternal(isolate_, all_dispatch_tables,
   2046                                          table_index, function, wasm_code);
   2047           }
   2048         }
   2049       }
   2050 
   2051       // TODO(titzer): we add the new dispatch table at the end to avoid
   2052       // redundant work and also because the new instance is not yet fully
   2053       // initialized.
   2054       if (!table_instance.table_object.is_null()) {
   2055         // Add the new dispatch table to the WebAssembly.Table object.
   2056         all_dispatch_tables = WasmTableObject::AddDispatchTable(
   2057             isolate_, table_instance.table_object, instance, index,
   2058             table_instance.function_table, table_instance.signature_table);
   2059       }
   2060     }
   2061   }
   2062 };
   2063 
   2064 bool wasm::IsWasmInstance(Object* object) {
   2065   return WasmInstanceObject::IsWasmInstanceObject(object);
   2066 }
   2067 
   2068 Handle<Script> wasm::GetScript(Handle<JSObject> instance) {
   2069   WasmCompiledModule* compiled_module =
   2070       WasmInstanceObject::cast(*instance)->compiled_module();
   2071   return handle(compiled_module->script());
   2072 }
   2073 
   2074 bool wasm::IsWasmCodegenAllowed(Isolate* isolate, Handle<Context> context) {
   2075   return isolate->allow_code_gen_callback() == nullptr ||
   2076          isolate->allow_code_gen_callback()(v8::Utils::ToLocal(context));
   2077 }
   2078 
   2079 MaybeHandle<JSArrayBuffer> wasm::GetInstanceMemory(
   2080     Isolate* isolate, Handle<WasmInstanceObject> object) {
   2081   auto instance = Handle<WasmInstanceObject>::cast(object);
   2082   if (instance->has_memory_buffer()) {
   2083     return Handle<JSArrayBuffer>(instance->memory_buffer(), isolate);
   2084   }
   2085   return MaybeHandle<JSArrayBuffer>();
   2086 }
   2087 
   2088 void SetInstanceMemory(Handle<WasmInstanceObject> instance,
   2089                        JSArrayBuffer* buffer) {
   2090   DisallowHeapAllocation no_gc;
   2091   instance->set_memory_buffer(buffer);
   2092   instance->compiled_module()->set_ptr_to_memory(buffer);
   2093 }
   2094 
   2095 int32_t wasm::GetInstanceMemorySize(Isolate* isolate,
   2096                                     Handle<WasmInstanceObject> instance) {
   2097   DCHECK(IsWasmInstance(*instance));
   2098   MaybeHandle<JSArrayBuffer> maybe_mem_buffer =
   2099       GetInstanceMemory(isolate, instance);
   2100   Handle<JSArrayBuffer> buffer;
   2101   if (!maybe_mem_buffer.ToHandle(&buffer)) {
   2102     return 0;
   2103   } else {
   2104     return buffer->byte_length()->Number() / WasmModule::kPageSize;
   2105   }
   2106 }
   2107 
   2108 uint32_t GetMaxInstanceMemoryPages(Isolate* isolate,
   2109                                    Handle<WasmInstanceObject> instance) {
   2110   if (instance->has_memory_object()) {
   2111     Handle<WasmMemoryObject> memory_object(instance->memory_object(), isolate);
   2112     if (memory_object->has_maximum_pages()) {
   2113       uint32_t maximum = static_cast<uint32_t>(memory_object->maximum_pages());
   2114       if (maximum < FLAG_wasm_max_mem_pages) return maximum;
   2115     }
   2116   }
   2117   uint32_t compiled_max_pages = instance->compiled_module()->max_mem_pages();
   2118   isolate->counters()->wasm_max_mem_pages_count()->AddSample(
   2119       compiled_max_pages);
   2120   if (compiled_max_pages != 0) return compiled_max_pages;
   2121   return FLAG_wasm_max_mem_pages;
   2122 }
   2123 
   2124 Handle<JSArrayBuffer> GrowMemoryBuffer(Isolate* isolate,
   2125                                        MaybeHandle<JSArrayBuffer> buffer,
   2126                                        uint32_t pages, uint32_t max_pages) {
   2127   Handle<JSArrayBuffer> old_buffer;
   2128   Address old_mem_start = nullptr;
   2129   uint32_t old_size = 0;
   2130   if (buffer.ToHandle(&old_buffer) && old_buffer->backing_store() != nullptr) {
   2131     old_mem_start = static_cast<Address>(old_buffer->backing_store());
   2132     DCHECK_NOT_NULL(old_mem_start);
   2133     old_size = old_buffer->byte_length()->Number();
   2134   }
   2135   DCHECK(old_size + pages * WasmModule::kPageSize <=
   2136          std::numeric_limits<uint32_t>::max());
   2137   uint32_t new_size = old_size + pages * WasmModule::kPageSize;
   2138   if (new_size <= old_size || max_pages * WasmModule::kPageSize < new_size ||
   2139       FLAG_wasm_max_mem_pages * WasmModule::kPageSize < new_size) {
   2140     return Handle<JSArrayBuffer>::null();
   2141   }
   2142 
   2143   // TODO(gdeepti): Change the protection here instead of allocating a new
   2144   // buffer before guard regions are turned on, see issue #5886.
   2145   const bool enable_guard_regions =
   2146       !old_buffer.is_null() && old_buffer->has_guard_region();
   2147   Handle<JSArrayBuffer> new_buffer =
   2148       NewArrayBuffer(isolate, new_size, enable_guard_regions);
   2149   if (new_buffer.is_null()) return new_buffer;
   2150   Address new_mem_start = static_cast<Address>(new_buffer->backing_store());
   2151   if (old_size != 0) {
   2152     memcpy(new_mem_start, old_mem_start, old_size);
   2153   }
   2154   return new_buffer;
   2155 }
   2156 
   2157 void UncheckedUpdateInstanceMemory(Isolate* isolate,
   2158                                    Handle<WasmInstanceObject> instance,
   2159                                    Address old_mem_start, uint32_t old_size) {
   2160   DCHECK(instance->has_memory_buffer());
   2161   Handle<JSArrayBuffer> mem_buffer(instance->memory_buffer());
   2162   uint32_t new_size = mem_buffer->byte_length()->Number();
   2163   Address new_mem_start = static_cast<Address>(mem_buffer->backing_store());
   2164   DCHECK_NOT_NULL(new_mem_start);
   2165   Zone specialization_zone(isolate->allocator(), ZONE_NAME);
   2166   CodeSpecialization code_specialization(isolate, &specialization_zone);
   2167   code_specialization.RelocateMemoryReferences(old_mem_start, old_size,
   2168                                                new_mem_start, new_size);
   2169   code_specialization.ApplyToWholeInstance(*instance);
   2170 }
   2171 
   2172 void DetachArrayBuffer(Isolate* isolate, Handle<JSArrayBuffer> buffer) {
   2173   const bool has_guard_regions =
   2174       (!buffer.is_null() && buffer->has_guard_region());
   2175   void* backing_store = buffer->backing_store();
   2176   if (backing_store != nullptr) {
   2177     DCHECK(!buffer->is_neuterable());
   2178     int64_t byte_length = NumberToSize(buffer->byte_length());
   2179     buffer->set_is_neuterable(true);
   2180     if (!has_guard_regions) {
   2181       buffer->set_is_external(true);
   2182       isolate->heap()->UnregisterArrayBuffer(*buffer);
   2183     }
   2184     buffer->Neuter();
   2185     if (!has_guard_regions) {
   2186       isolate->array_buffer_allocator()->Free(backing_store, byte_length);
   2187     } else {
   2188       base::OS::Free(backing_store, RoundUp(i::wasm::kWasmMaxHeapOffset,
   2189                                             base::OS::CommitPageSize()));
   2190       reinterpret_cast<v8::Isolate*>(isolate)
   2191           ->AdjustAmountOfExternalAllocatedMemory(-byte_length);
   2192     }
   2193   }
   2194 }
   2195 
   2196 int32_t wasm::GrowWebAssemblyMemory(Isolate* isolate,
   2197                                     Handle<WasmMemoryObject> receiver,
   2198                                     uint32_t pages) {
   2199   DCHECK(WasmJs::IsWasmMemoryObject(isolate, receiver));
   2200   Handle<WasmMemoryObject> memory_object =
   2201       handle(WasmMemoryObject::cast(*receiver));
   2202   MaybeHandle<JSArrayBuffer> memory_buffer = handle(memory_object->buffer());
   2203   Handle<JSArrayBuffer> old_buffer;
   2204   uint32_t old_size = 0;
   2205   Address old_mem_start = nullptr;
   2206   if (memory_buffer.ToHandle(&old_buffer) &&
   2207       old_buffer->backing_store() != nullptr) {
   2208     old_size = old_buffer->byte_length()->Number();
   2209     old_mem_start = static_cast<Address>(old_buffer->backing_store());
   2210   }
   2211   Handle<JSArrayBuffer> new_buffer;
   2212   // Return current size if grow by 0
   2213   if (pages == 0) {
   2214     if (!old_buffer.is_null() && old_buffer->backing_store() != nullptr) {
   2215       new_buffer = SetupArrayBuffer(isolate, old_buffer->backing_store(),
   2216                                     old_size, old_buffer->is_external(),
   2217                                     old_buffer->has_guard_region());
   2218       memory_object->set_buffer(*new_buffer);
   2219       old_buffer->set_is_neuterable(true);
   2220       if (!old_buffer->has_guard_region()) {
   2221         old_buffer->set_is_external(true);
   2222         isolate->heap()->UnregisterArrayBuffer(*old_buffer);
   2223       }
   2224       // Neuter but don't free the memory because it is now being used by
   2225       // new_buffer.
   2226       old_buffer->Neuter();
   2227     }
   2228     DCHECK(old_size % WasmModule::kPageSize == 0);
   2229     return (old_size / WasmModule::kPageSize);
   2230   }
   2231   if (!memory_object->has_instances_link()) {
   2232     // Memory object does not have an instance associated with it, just grow
   2233     uint32_t max_pages;
   2234     if (memory_object->has_maximum_pages()) {
   2235       max_pages = static_cast<uint32_t>(memory_object->maximum_pages());
   2236       if (FLAG_wasm_max_mem_pages < max_pages) return -1;
   2237     } else {
   2238       max_pages = FLAG_wasm_max_mem_pages;
   2239     }
   2240     new_buffer = GrowMemoryBuffer(isolate, memory_buffer, pages, max_pages);
   2241     if (new_buffer.is_null()) return -1;
   2242   } else {
   2243     Handle<WasmInstanceWrapper> instance_wrapper(
   2244         memory_object->instances_link());
   2245     DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper));
   2246     DCHECK(instance_wrapper->has_instance());
   2247     Handle<WasmInstanceObject> instance = instance_wrapper->instance_object();
   2248     DCHECK(IsWasmInstance(*instance));
   2249     uint32_t max_pages = GetMaxInstanceMemoryPages(isolate, instance);
   2250 
   2251     // Grow memory object buffer and update instances associated with it.
   2252     new_buffer = GrowMemoryBuffer(isolate, memory_buffer, pages, max_pages);
   2253     if (new_buffer.is_null()) return -1;
   2254     DCHECK(!instance_wrapper->has_previous());
   2255     SetInstanceMemory(instance, *new_buffer);
   2256     UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size);
   2257     while (instance_wrapper->has_next()) {
   2258       instance_wrapper = instance_wrapper->next_wrapper();
   2259       DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper));
   2260       Handle<WasmInstanceObject> instance = instance_wrapper->instance_object();
   2261       DCHECK(IsWasmInstance(*instance));
   2262       SetInstanceMemory(instance, *new_buffer);
   2263       UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size);
   2264     }
   2265   }
   2266   memory_object->set_buffer(*new_buffer);
   2267   DetachArrayBuffer(isolate, old_buffer);
   2268   DCHECK(old_size % WasmModule::kPageSize == 0);
   2269   return (old_size / WasmModule::kPageSize);
   2270 }
   2271 
   2272 int32_t wasm::GrowMemory(Isolate* isolate, Handle<WasmInstanceObject> instance,
   2273                          uint32_t pages) {
   2274   if (!IsWasmInstance(*instance)) return -1;
   2275   if (pages == 0) return GetInstanceMemorySize(isolate, instance);
   2276   Handle<WasmInstanceObject> instance_obj(WasmInstanceObject::cast(*instance));
   2277   if (!instance_obj->has_memory_object()) {
   2278     // No other instances to grow, grow just the one.
   2279     MaybeHandle<JSArrayBuffer> instance_buffer =
   2280         GetInstanceMemory(isolate, instance);
   2281     Handle<JSArrayBuffer> old_buffer;
   2282     uint32_t old_size = 0;
   2283     Address old_mem_start = nullptr;
   2284     if (instance_buffer.ToHandle(&old_buffer) &&
   2285         old_buffer->backing_store() != nullptr) {
   2286       old_size = old_buffer->byte_length()->Number();
   2287       old_mem_start = static_cast<Address>(old_buffer->backing_store());
   2288     }
   2289     uint32_t max_pages = GetMaxInstanceMemoryPages(isolate, instance_obj);
   2290     Handle<JSArrayBuffer> buffer =
   2291         GrowMemoryBuffer(isolate, instance_buffer, pages, max_pages);
   2292     if (buffer.is_null()) return -1;
   2293     SetInstanceMemory(instance, *buffer);
   2294     UncheckedUpdateInstanceMemory(isolate, instance, old_mem_start, old_size);
   2295     DCHECK(old_size % WasmModule::kPageSize == 0);
   2296     return (old_size / WasmModule::kPageSize);
   2297   } else {
   2298     return GrowWebAssemblyMemory(isolate, handle(instance_obj->memory_object()),
   2299                                  pages);
   2300   }
   2301 }
   2302 
   2303 void wasm::GrowDispatchTables(Isolate* isolate,
   2304                               Handle<FixedArray> dispatch_tables,
   2305                               uint32_t old_size, uint32_t count) {
   2306   DCHECK_EQ(0, dispatch_tables->length() % 4);
   2307 
   2308   Zone specialization_zone(isolate->allocator(), ZONE_NAME);
   2309   for (int i = 0; i < dispatch_tables->length(); i += 4) {
   2310     Handle<FixedArray> old_function_table(
   2311         FixedArray::cast(dispatch_tables->get(i + 2)));
   2312     Handle<FixedArray> old_signature_table(
   2313         FixedArray::cast(dispatch_tables->get(i + 3)));
   2314     Handle<FixedArray> new_function_table =
   2315         isolate->factory()->CopyFixedArrayAndGrow(old_function_table, count);
   2316     Handle<FixedArray> new_signature_table =
   2317         isolate->factory()->CopyFixedArrayAndGrow(old_signature_table, count);
   2318 
   2319     // Update dispatch tables with new function/signature tables
   2320     dispatch_tables->set(i + 2, *new_function_table);
   2321     dispatch_tables->set(i + 3, *new_signature_table);
   2322 
   2323     // Patch the code of the respective instance.
   2324     CodeSpecialization code_specialization(isolate, &specialization_zone);
   2325     code_specialization.PatchTableSize(old_size, old_size + count);
   2326     code_specialization.RelocateObject(old_function_table, new_function_table);
   2327     code_specialization.RelocateObject(old_signature_table,
   2328                                        new_signature_table);
   2329     code_specialization.ApplyToWholeInstance(
   2330         WasmInstanceObject::cast(dispatch_tables->get(i)));
   2331   }
   2332 }
   2333 
   2334 void testing::ValidateInstancesChain(Isolate* isolate,
   2335                                      Handle<WasmModuleObject> module_obj,
   2336                                      int instance_count) {
   2337   CHECK_GE(instance_count, 0);
   2338   DisallowHeapAllocation no_gc;
   2339   WasmCompiledModule* compiled_module = module_obj->compiled_module();
   2340   CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()),
   2341            *module_obj);
   2342   Object* prev = nullptr;
   2343   int found_instances = compiled_module->has_weak_owning_instance() ? 1 : 0;
   2344   WasmCompiledModule* current_instance = compiled_module;
   2345   while (current_instance->has_weak_next_instance()) {
   2346     CHECK((prev == nullptr && !current_instance->has_weak_prev_instance()) ||
   2347           current_instance->ptr_to_weak_prev_instance()->value() == prev);
   2348     CHECK_EQ(current_instance->ptr_to_weak_wasm_module()->value(), *module_obj);
   2349     CHECK(IsWasmInstance(
   2350         current_instance->ptr_to_weak_owning_instance()->value()));
   2351     prev = current_instance;
   2352     current_instance = WasmCompiledModule::cast(
   2353         current_instance->ptr_to_weak_next_instance()->value());
   2354     ++found_instances;
   2355     CHECK_LE(found_instances, instance_count);
   2356   }
   2357   CHECK_EQ(found_instances, instance_count);
   2358 }
   2359 
   2360 void testing::ValidateModuleState(Isolate* isolate,
   2361                                   Handle<WasmModuleObject> module_obj) {
   2362   DisallowHeapAllocation no_gc;
   2363   WasmCompiledModule* compiled_module = module_obj->compiled_module();
   2364   CHECK(compiled_module->has_weak_wasm_module());
   2365   CHECK_EQ(compiled_module->ptr_to_weak_wasm_module()->value(), *module_obj);
   2366   CHECK(!compiled_module->has_weak_prev_instance());
   2367   CHECK(!compiled_module->has_weak_next_instance());
   2368   CHECK(!compiled_module->has_weak_owning_instance());
   2369 }
   2370 
   2371 void testing::ValidateOrphanedInstance(Isolate* isolate,
   2372                                        Handle<WasmInstanceObject> instance) {
   2373   DisallowHeapAllocation no_gc;
   2374   WasmCompiledModule* compiled_module = instance->compiled_module();
   2375   CHECK(compiled_module->has_weak_wasm_module());
   2376   CHECK(compiled_module->ptr_to_weak_wasm_module()->cleared());
   2377 }
   2378 
   2379 Handle<JSArray> wasm::GetImports(Isolate* isolate,
   2380                                  Handle<WasmModuleObject> module_object) {
   2381   Handle<WasmCompiledModule> compiled_module(module_object->compiled_module(),
   2382                                              isolate);
   2383   Factory* factory = isolate->factory();
   2384 
   2385   Handle<String> module_string = factory->InternalizeUtf8String("module");
   2386   Handle<String> name_string = factory->InternalizeUtf8String("name");
   2387   Handle<String> kind_string = factory->InternalizeUtf8String("kind");
   2388 
   2389   Handle<String> function_string = factory->InternalizeUtf8String("function");
   2390   Handle<String> table_string = factory->InternalizeUtf8String("table");
   2391   Handle<String> memory_string = factory->InternalizeUtf8String("memory");
   2392   Handle<String> global_string = factory->InternalizeUtf8String("global");
   2393 
   2394   // Create the result array.
   2395   WasmModule* module = compiled_module->module();
   2396   int num_imports = static_cast<int>(module->import_table.size());
   2397   Handle<JSArray> array_object = factory->NewJSArray(FAST_ELEMENTS, 0, 0);
   2398   Handle<FixedArray> storage = factory->NewFixedArray(num_imports);
   2399   JSArray::SetContent(array_object, storage);
   2400   array_object->set_length(Smi::FromInt(num_imports));
   2401 
   2402   Handle<JSFunction> object_function =
   2403       Handle<JSFunction>(isolate->native_context()->object_function(), isolate);
   2404 
   2405   // Populate the result array.
   2406   for (int index = 0; index < num_imports; ++index) {
   2407     WasmImport& import = module->import_table[index];
   2408 
   2409     Handle<JSObject> entry = factory->NewJSObject(object_function);
   2410 
   2411     Handle<String> import_kind;
   2412     switch (import.kind) {
   2413       case kExternalFunction:
   2414         import_kind = function_string;
   2415         break;
   2416       case kExternalTable:
   2417         import_kind = table_string;
   2418         break;
   2419       case kExternalMemory:
   2420         import_kind = memory_string;
   2421         break;
   2422       case kExternalGlobal:
   2423         import_kind = global_string;
   2424         break;
   2425       default:
   2426         UNREACHABLE();
   2427     }
   2428 
   2429     MaybeHandle<String> import_module =
   2430         WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
   2431             isolate, compiled_module, import.module_name_offset,
   2432             import.module_name_length);
   2433 
   2434     MaybeHandle<String> import_name =
   2435         WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
   2436             isolate, compiled_module, import.field_name_offset,
   2437             import.field_name_length);
   2438 
   2439     JSObject::AddProperty(entry, module_string, import_module.ToHandleChecked(),
   2440                           NONE);
   2441     JSObject::AddProperty(entry, name_string, import_name.ToHandleChecked(),
   2442                           NONE);
   2443     JSObject::AddProperty(entry, kind_string, import_kind, NONE);
   2444 
   2445     storage->set(index, *entry);
   2446   }
   2447 
   2448   return array_object;
   2449 }
   2450 
   2451 Handle<JSArray> wasm::GetExports(Isolate* isolate,
   2452                                  Handle<WasmModuleObject> module_object) {
   2453   Handle<WasmCompiledModule> compiled_module(module_object->compiled_module(),
   2454                                              isolate);
   2455   Factory* factory = isolate->factory();
   2456 
   2457   Handle<String> name_string = factory->InternalizeUtf8String("name");
   2458   Handle<String> kind_string = factory->InternalizeUtf8String("kind");
   2459 
   2460   Handle<String> function_string = factory->InternalizeUtf8String("function");
   2461   Handle<String> table_string = factory->InternalizeUtf8String("table");
   2462   Handle<String> memory_string = factory->InternalizeUtf8String("memory");
   2463   Handle<String> global_string = factory->InternalizeUtf8String("global");
   2464 
   2465   // Create the result array.
   2466   WasmModule* module = compiled_module->module();
   2467   int num_exports = static_cast<int>(module->export_table.size());
   2468   Handle<JSArray> array_object = factory->NewJSArray(FAST_ELEMENTS, 0, 0);
   2469   Handle<FixedArray> storage = factory->NewFixedArray(num_exports);
   2470   JSArray::SetContent(array_object, storage);
   2471   array_object->set_length(Smi::FromInt(num_exports));
   2472 
   2473   Handle<JSFunction> object_function =
   2474       Handle<JSFunction>(isolate->native_context()->object_function(), isolate);
   2475 
   2476   // Populate the result array.
   2477   for (int index = 0; index < num_exports; ++index) {
   2478     WasmExport& exp = module->export_table[index];
   2479 
   2480     Handle<String> export_kind;
   2481     switch (exp.kind) {
   2482       case kExternalFunction:
   2483         export_kind = function_string;
   2484         break;
   2485       case kExternalTable:
   2486         export_kind = table_string;
   2487         break;
   2488       case kExternalMemory:
   2489         export_kind = memory_string;
   2490         break;
   2491       case kExternalGlobal:
   2492         export_kind = global_string;
   2493         break;
   2494       default:
   2495         UNREACHABLE();
   2496     }
   2497 
   2498     Handle<JSObject> entry = factory->NewJSObject(object_function);
   2499 
   2500     MaybeHandle<String> export_name =
   2501         WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
   2502             isolate, compiled_module, exp.name_offset, exp.name_length);
   2503 
   2504     JSObject::AddProperty(entry, name_string, export_name.ToHandleChecked(),
   2505                           NONE);
   2506     JSObject::AddProperty(entry, kind_string, export_kind, NONE);
   2507 
   2508     storage->set(index, *entry);
   2509   }
   2510 
   2511   return array_object;
   2512 }
   2513 
   2514 Handle<JSArray> wasm::GetCustomSections(Isolate* isolate,
   2515                                         Handle<WasmModuleObject> module_object,
   2516                                         Handle<String> name,
   2517                                         ErrorThrower* thrower) {
   2518   Handle<WasmCompiledModule> compiled_module(module_object->compiled_module(),
   2519                                              isolate);
   2520   Factory* factory = isolate->factory();
   2521 
   2522   std::vector<CustomSectionOffset> custom_sections;
   2523   {
   2524     DisallowHeapAllocation no_gc;  // for raw access to string bytes.
   2525     Handle<SeqOneByteString> module_bytes(compiled_module->module_bytes(),
   2526                                           isolate);
   2527     const byte* start =
   2528         reinterpret_cast<const byte*>(module_bytes->GetCharsAddress());
   2529     const byte* end = start + module_bytes->length();
   2530     custom_sections = DecodeCustomSections(start, end);
   2531   }
   2532 
   2533   std::vector<Handle<Object>> matching_sections;
   2534 
   2535   // Gather matching sections.
   2536   for (auto section : custom_sections) {
   2537     MaybeHandle<String> section_name =
   2538         WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
   2539             isolate, compiled_module, section.name_offset, section.name_length);
   2540 
   2541     if (!name->Equals(*section_name.ToHandleChecked())) continue;
   2542 
   2543     // Make a copy of the payload data in the section.
   2544     bool is_external;  // Set by TryAllocateBackingStore
   2545     void* memory = TryAllocateBackingStore(isolate, section.payload_length,
   2546                                            false, is_external);
   2547 
   2548     Handle<Object> section_data = factory->undefined_value();
   2549     if (memory) {
   2550       Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
   2551       JSArrayBuffer::Setup(buffer, isolate, is_external, memory,
   2552                            static_cast<int>(section.payload_length));
   2553       DisallowHeapAllocation no_gc;  // for raw access to string bytes.
   2554       Handle<SeqOneByteString> module_bytes(compiled_module->module_bytes(),
   2555                                             isolate);
   2556       const byte* start =
   2557           reinterpret_cast<const byte*>(module_bytes->GetCharsAddress());
   2558       memcpy(memory, start + section.payload_offset, section.payload_length);
   2559       section_data = buffer;
   2560     } else {
   2561       thrower->RangeError("out of memory allocating custom section data");
   2562       return Handle<JSArray>();
   2563     }
   2564 
   2565     matching_sections.push_back(section_data);
   2566   }
   2567 
   2568   int num_custom_sections = static_cast<int>(matching_sections.size());
   2569   Handle<JSArray> array_object = factory->NewJSArray(FAST_ELEMENTS, 0, 0);
   2570   Handle<FixedArray> storage = factory->NewFixedArray(num_custom_sections);
   2571   JSArray::SetContent(array_object, storage);
   2572   array_object->set_length(Smi::FromInt(num_custom_sections));
   2573 
   2574   for (int i = 0; i < num_custom_sections; i++) {
   2575     storage->set(i, *matching_sections[i]);
   2576   }
   2577 
   2578   return array_object;
   2579 }
   2580 
   2581 bool wasm::SyncValidate(Isolate* isolate, ErrorThrower* thrower,
   2582                         const ModuleWireBytes& bytes) {
   2583   if (bytes.start() == nullptr || bytes.length() == 0) return false;
   2584   ModuleResult result =
   2585       DecodeWasmModule(isolate, bytes.start(), bytes.end(), true, kWasmOrigin);
   2586   if (result.val) delete result.val;
   2587   return result.ok();
   2588 }
   2589 
   2590 MaybeHandle<WasmModuleObject> wasm::SyncCompileTranslatedAsmJs(
   2591     Isolate* isolate, ErrorThrower* thrower, const ModuleWireBytes& bytes,
   2592     Handle<Script> asm_js_script,
   2593     Vector<const byte> asm_js_offset_table_bytes) {
   2594 
   2595   ModuleResult result = DecodeWasmModule(isolate, bytes.start(), bytes.end(),
   2596                                          false, kAsmJsOrigin);
   2597   if (result.failed()) {
   2598     // TODO(titzer): use Result<std::unique_ptr<const WasmModule*>>?
   2599     if (result.val) delete result.val;
   2600     thrower->CompileFailed("Wasm decoding failed", result);
   2601     return {};
   2602   }
   2603 
   2604   CompilationHelper helper(isolate, const_cast<WasmModule*>(result.val));
   2605   return helper.CompileToModuleObject(thrower, bytes, asm_js_script,
   2606                                       asm_js_offset_table_bytes);
   2607 }
   2608 
   2609 MaybeHandle<WasmModuleObject> wasm::SyncCompile(Isolate* isolate,
   2610                                                 ErrorThrower* thrower,
   2611                                                 const ModuleWireBytes& bytes) {
   2612   if (!IsWasmCodegenAllowed(isolate, isolate->native_context())) {
   2613     thrower->CompileError("Wasm code generation disallowed in this context");
   2614     return {};
   2615   }
   2616 
   2617   ModuleResult result =
   2618       DecodeWasmModule(isolate, bytes.start(), bytes.end(), false, kWasmOrigin);
   2619   if (result.failed()) {
   2620     if (result.val) delete result.val;
   2621     thrower->CompileFailed("Wasm decoding failed", result);
   2622     return {};
   2623   }
   2624 
   2625   CompilationHelper helper(isolate, const_cast<WasmModule*>(result.val));
   2626   return helper.CompileToModuleObject(thrower, bytes, Handle<Script>(),
   2627                                       Vector<const byte>());
   2628 }
   2629 
   2630 MaybeHandle<WasmInstanceObject> wasm::SyncInstantiate(
   2631     Isolate* isolate, ErrorThrower* thrower,
   2632     Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports,
   2633     MaybeHandle<JSArrayBuffer> memory) {
   2634   InstantiationHelper helper(isolate, thrower, module_object, imports, memory);
   2635   return helper.Build();
   2636 }
   2637 
   2638 void RejectPromise(Isolate* isolate, ErrorThrower* thrower,
   2639                    Handle<JSPromise> promise) {
   2640   v8::Local<v8::Promise::Resolver> resolver =
   2641       v8::Utils::PromiseToLocal(promise).As<v8::Promise::Resolver>();
   2642   Handle<Context> context(isolate->context(), isolate);
   2643   resolver->Reject(v8::Utils::ToLocal(context),
   2644                    v8::Utils::ToLocal(thrower->Reify()));
   2645 }
   2646 
   2647 void ResolvePromise(Isolate* isolate, Handle<JSPromise> promise,
   2648                     Handle<Object> result) {
   2649   v8::Local<v8::Promise::Resolver> resolver =
   2650       v8::Utils::PromiseToLocal(promise).As<v8::Promise::Resolver>();
   2651   Handle<Context> context(isolate->context(), isolate);
   2652   resolver->Resolve(v8::Utils::ToLocal(context), v8::Utils::ToLocal(result));
   2653 }
   2654 
   2655 void wasm::AsyncCompile(Isolate* isolate, Handle<JSPromise> promise,
   2656                         const ModuleWireBytes& bytes) {
   2657   ErrorThrower thrower(isolate, nullptr);
   2658   MaybeHandle<WasmModuleObject> module_object =
   2659       SyncCompile(isolate, &thrower, bytes);
   2660   if (thrower.error()) {
   2661     RejectPromise(isolate, &thrower, promise);
   2662     return;
   2663   }
   2664   ResolvePromise(isolate, promise, module_object.ToHandleChecked());
   2665 }
   2666 
   2667 void wasm::AsyncInstantiate(Isolate* isolate, Handle<JSPromise> promise,
   2668                             Handle<WasmModuleObject> module_object,
   2669                             MaybeHandle<JSReceiver> imports) {
   2670   ErrorThrower thrower(isolate, nullptr);
   2671   MaybeHandle<WasmInstanceObject> instance_object = SyncInstantiate(
   2672       isolate, &thrower, module_object, imports, Handle<JSArrayBuffer>::null());
   2673   if (thrower.error()) {
   2674     RejectPromise(isolate, &thrower, promise);
   2675     return;
   2676   }
   2677   ResolvePromise(isolate, promise, instance_object.ToHandleChecked());
   2678 }
   2679 
   2680 void wasm::AsyncCompileAndInstantiate(Isolate* isolate,
   2681                                       Handle<JSPromise> promise,
   2682                                       const ModuleWireBytes& bytes,
   2683                                       MaybeHandle<JSReceiver> imports) {
   2684   ErrorThrower thrower(isolate, nullptr);
   2685 
   2686   // Compile the module.
   2687   MaybeHandle<WasmModuleObject> module_object =
   2688       SyncCompile(isolate, &thrower, bytes);
   2689   if (thrower.error()) {
   2690     RejectPromise(isolate, &thrower, promise);
   2691     return;
   2692   }
   2693   Handle<WasmModuleObject> module = module_object.ToHandleChecked();
   2694 
   2695   // Instantiate the module.
   2696   MaybeHandle<WasmInstanceObject> instance_object = SyncInstantiate(
   2697       isolate, &thrower, module, imports, Handle<JSArrayBuffer>::null());
   2698   if (thrower.error()) {
   2699     RejectPromise(isolate, &thrower, promise);
   2700     return;
   2701   }
   2702 
   2703   Handle<JSFunction> object_function =
   2704       Handle<JSFunction>(isolate->native_context()->object_function(), isolate);
   2705   Handle<JSObject> ret =
   2706       isolate->factory()->NewJSObject(object_function, TENURED);
   2707   Handle<String> module_property_name =
   2708       isolate->factory()->InternalizeUtf8String("module");
   2709   Handle<String> instance_property_name =
   2710       isolate->factory()->InternalizeUtf8String("instance");
   2711   JSObject::AddProperty(ret, module_property_name, module, NONE);
   2712   JSObject::AddProperty(ret, instance_property_name,
   2713                         instance_object.ToHandleChecked(), NONE);
   2714 
   2715   ResolvePromise(isolate, promise, ret);
   2716 }
   2717