LCOV - code coverage report
Current view: top level - src/wasm - wasm-module.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1200 1249 96.1 %
Date: 2017-04-26 Functions: 92 96 95.8 %

          Line data    Source code
       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/frames-inl.h"
      14             : #include "src/objects.h"
      15             : #include "src/property-descriptor.h"
      16             : #include "src/simulator.h"
      17             : #include "src/snapshot/snapshot.h"
      18             : #include "src/trap-handler/trap-handler.h"
      19             : #include "src/v8.h"
      20             : 
      21             : #include "src/asmjs/asm-wasm-builder.h"
      22             : #include "src/wasm/function-body-decoder.h"
      23             : #include "src/wasm/module-decoder.h"
      24             : #include "src/wasm/wasm-code-specialization.h"
      25             : #include "src/wasm/wasm-js.h"
      26             : #include "src/wasm/wasm-limits.h"
      27             : #include "src/wasm/wasm-module.h"
      28             : #include "src/wasm/wasm-objects.h"
      29             : #include "src/wasm/wasm-result.h"
      30             : 
      31             : using namespace v8::internal;
      32             : using namespace v8::internal::wasm;
      33             : namespace base = v8::base;
      34             : 
      35             : #define TRACE(...)                                      \
      36             :   do {                                                  \
      37             :     if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \
      38             :   } while (false)
      39             : 
      40             : #define TRACE_CHAIN(instance)        \
      41             :   do {                               \
      42             :     instance->PrintInstancesChain(); \
      43             :   } while (false)
      44             : 
      45             : #define TRACE_COMPILE(...)                             \
      46             :   do {                                                 \
      47             :     if (FLAG_trace_wasm_compiler) PrintF(__VA_ARGS__); \
      48             :   } while (false)
      49             : 
      50             : namespace {
      51             : 
      52             : static const int kInvalidSigIndex = -1;
      53             : 
      54       12359 : byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) {
      55       12359 :   return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset;
      56             : }
      57             : 
      58        1239 : static void MemoryFinalizer(const v8::WeakCallbackInfo<void>& data) {
      59             :   DisallowHeapAllocation no_gc;
      60             :   JSArrayBuffer** p = reinterpret_cast<JSArrayBuffer**>(data.GetParameter());
      61         633 :   JSArrayBuffer* buffer = *p;
      62             : 
      63         633 :   if (!buffer->was_neutered()) {
      64             :     void* memory = buffer->backing_store();
      65             :     DCHECK(memory != nullptr);
      66             :     base::OS::Free(memory,
      67        1212 :                    RoundUp(kWasmMaxHeapOffset, base::OS::CommitPageSize()));
      68             : 
      69             :     data.GetIsolate()->AdjustAmountOfExternalAllocatedMemory(
      70         606 :         -buffer->byte_length()->Number());
      71             :   }
      72             : 
      73         633 :   GlobalHandles::Destroy(reinterpret_cast<Object**>(p));
      74         633 : }
      75             : 
      76      784371 : static void RecordStats(Isolate* isolate, Code* code) {
      77      522914 :   isolate->counters()->wasm_generated_code_size()->Increment(code->body_size());
      78             :   isolate->counters()->wasm_reloc_size()->Increment(
      79      261457 :       code->relocation_info()->length());
      80      261457 : }
      81             : 
      82       32123 : static void RecordStats(Isolate* isolate, Handle<FixedArray> functions) {
      83             :   DisallowHeapAllocation no_gc;
      84      295642 :   for (int i = 0; i < functions->length(); ++i) {
      85      115698 :     RecordStats(isolate, Code::cast(functions->get(i)));
      86             :   }
      87       32123 : }
      88             : 
      89       22759 : void* TryAllocateBackingStore(Isolate* isolate, size_t size,
      90             :                               bool enable_guard_regions, bool& is_external) {
      91       11695 :   is_external = false;
      92             :   // TODO(eholk): Right now enable_guard_regions has no effect on 32-bit
      93             :   // systems. It may be safer to fail instead, given that other code might do
      94             :   // things that would be unsafe if they expected guard pages where there
      95             :   // weren't any.
      96       11695 :   if (enable_guard_regions && kGuardRegionsSupported) {
      97             :     // TODO(eholk): On Windows we want to make sure we don't commit the guard
      98             :     // pages yet.
      99             : 
     100             :     // We always allocate the largest possible offset into the heap, so the
     101             :     // addressable memory after the guard page can be made inaccessible.
     102             :     const size_t alloc_size =
     103         631 :         RoundUp(kWasmMaxHeapOffset, base::OS::CommitPageSize());
     104             :     DCHECK_EQ(0, size % base::OS::CommitPageSize());
     105             : 
     106             :     // AllocateGuarded makes the whole region inaccessible by default.
     107         631 :     void* memory = base::OS::AllocateGuarded(alloc_size);
     108         631 :     if (memory == nullptr) {
     109             :       return nullptr;
     110             :     }
     111             : 
     112             :     // Make the part we care about accessible.
     113         631 :     base::OS::Unprotect(memory, size);
     114             : 
     115             :     reinterpret_cast<v8::Isolate*>(isolate)
     116         631 :         ->AdjustAmountOfExternalAllocatedMemory(size);
     117             : 
     118         631 :     is_external = true;
     119         631 :     return memory;
     120             :   } else {
     121       11064 :     void* memory = isolate->array_buffer_allocator()->Allocate(size);
     122       11064 :     return memory;
     123             :   }
     124             : }
     125             : 
     126       47279 : void FlushICache(Isolate* isolate, Handle<FixedArray> code_table) {
     127      536322 :   for (int i = 0; i < code_table->length(); ++i) {
     128      220882 :     Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i);
     129      220882 :     Assembler::FlushICache(isolate, code->instruction_start(),
     130      441764 :                            code->instruction_size());
     131             :   }
     132       47279 : }
     133             : 
     134       12185 : Handle<Script> CreateWasmScript(Isolate* isolate,
     135             :                                 const ModuleWireBytes& wire_bytes) {
     136             :   Handle<Script> script =
     137       12185 :       isolate->factory()->NewScript(isolate->factory()->empty_string());
     138       24370 :   script->set_context_data(isolate->native_context()->debug_context_id());
     139             :   script->set_type(Script::TYPE_WASM);
     140             : 
     141             :   int hash = StringHasher::HashSequentialString(
     142             :       reinterpret_cast<const char*>(wire_bytes.start()), wire_bytes.length(),
     143       12185 :       kZeroHashSeed);
     144             : 
     145             :   const int kBufferSize = 32;
     146             :   char buffer[kBufferSize];
     147       12185 :   int url_chars = SNPrintF(ArrayVector(buffer), "wasm://wasm/%08x", hash);
     148             :   DCHECK(url_chars >= 0 && url_chars < kBufferSize);
     149             :   MaybeHandle<String> url_str = isolate->factory()->NewStringFromOneByte(
     150             :       Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), url_chars),
     151       12185 :       TENURED);
     152       12185 :   script->set_source_url(*url_str.ToHandleChecked());
     153             : 
     154       12185 :   int name_chars = SNPrintF(ArrayVector(buffer), "wasm-%08x", hash);
     155             :   DCHECK(name_chars >= 0 && name_chars < kBufferSize);
     156             :   MaybeHandle<String> name_str = isolate->factory()->NewStringFromOneByte(
     157             :       Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), name_chars),
     158       12185 :       TENURED);
     159       12185 :   script->set_name(*name_str.ToHandleChecked());
     160             : 
     161       12185 :   return script;
     162             : }
     163             : 
     164      127772 : class JSToWasmWrapperCache {
     165             :  public:
     166       49253 :   Handle<Code> CloneOrCompileJSToWasmWrapper(Isolate* isolate,
     167             :                                              const wasm::WasmModule* module,
     168             :                                              Handle<Code> wasm_code,
     169             :                                              uint32_t index) {
     170       49253 :     const wasm::WasmFunction* func = &module->functions[index];
     171       49253 :     int cached_idx = sig_map_.Find(func->sig);
     172       49253 :     if (cached_idx >= 0) {
     173       46600 :       Handle<Code> code = isolate->factory()->CopyCode(code_cache_[cached_idx]);
     174             :       // Now patch the call to wasm code.
     175       52855 :       for (RelocIterator it(*code, RelocInfo::kCodeTargetMask);; it.next()) {
     176             :         DCHECK(!it.done());
     177             :         Code* target =
     178       52855 :             Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
     179       84271 :         if (target->kind() == Code::WASM_FUNCTION ||
     180       31416 :             target->kind() == Code::WASM_TO_JS_FUNCTION ||
     181       84196 :             target->builtin_index() == Builtins::kIllegal ||
     182             :             target->builtin_index() == Builtins::kWasmCompileLazy) {
     183             :           it.rinfo()->set_target_address(isolate,
     184       23300 :                                          wasm_code->instruction_start());
     185             :           break;
     186             :         }
     187       29555 :       }
     188       23300 :       return code;
     189             :     }
     190             : 
     191             :     Handle<Code> code =
     192       25953 :         compiler::CompileJSToWasmWrapper(isolate, module, wasm_code, index);
     193       25953 :     uint32_t new_cache_idx = sig_map_.FindOrInsert(func->sig);
     194             :     DCHECK_EQ(code_cache_.size(), new_cache_idx);
     195             :     USE(new_cache_idx);
     196       25953 :     code_cache_.push_back(code);
     197       25953 :     return code;
     198             :   }
     199             : 
     200             :  private:
     201             :   // sig_map_ maps signatures to an index in code_cache_.
     202             :   wasm::SignatureMap sig_map_;
     203             :   std::vector<Handle<Code>> code_cache_;
     204             : };
     205             : 
     206             : // Ensure that the code object in <code_table> at offset <func_index> has
     207             : // deoptimization data attached. This is needed for lazy compile stubs which are
     208             : // called from JS_TO_WASM functions or via exported function tables. The deopt
     209             : // data is used to determine which function this lazy compile stub belongs to.
     210       56511 : Handle<Code> EnsureExportedLazyDeoptData(Isolate* isolate,
     211             :                                          Handle<WasmInstanceObject> instance,
     212             :                                          Handle<FixedArray> code_table,
     213             :                                          int func_index) {
     214             :   Handle<Code> code(Code::cast(code_table->get(func_index)), isolate);
     215       56511 :   if (code->builtin_index() != Builtins::kWasmCompileLazy) {
     216             :     // No special deopt data needed for compiled functions, and imported
     217             :     // functions, which map to Illegal at this point (they get compiled at
     218             :     // instantiation time).
     219             :     DCHECK(code->kind() == Code::WASM_FUNCTION ||
     220             :            code->kind() == Code::WASM_TO_JS_FUNCTION ||
     221             :            code->builtin_index() == Builtins::kIllegal);
     222       39052 :     return code;
     223             :   }
     224             :   // deopt_data:
     225             :   //   #0: weak instance
     226             :   //   #1: func_index
     227             :   // might be extended later for table exports (see
     228             :   // EnsureTableExportLazyDeoptData).
     229             :   Handle<FixedArray> deopt_data(code->deoptimization_data());
     230             :   DCHECK_EQ(0, deopt_data->length() % 2);
     231       17459 :   if (deopt_data->length() == 0) {
     232       13631 :     code = isolate->factory()->CopyCode(code);
     233       13631 :     code_table->set(func_index, *code);
     234       13631 :     deopt_data = isolate->factory()->NewFixedArray(2, TENURED);
     235       13631 :     code->set_deoptimization_data(*deopt_data);
     236       13631 :     if (!instance.is_null()) {
     237             :       Handle<WeakCell> weak_instance =
     238        5217 :           isolate->factory()->NewWeakCell(instance);
     239        5217 :       deopt_data->set(0, *weak_instance);
     240             :     }
     241             :     deopt_data->set(1, Smi::FromInt(func_index));
     242             :   }
     243             :   DCHECK_IMPLIES(!instance.is_null(),
     244             :                  WeakCell::cast(code->deoptimization_data()->get(0))->value() ==
     245             :                      *instance);
     246             :   DCHECK_EQ(func_index,
     247             :             Smi::cast(code->deoptimization_data()->get(1))->value());
     248       17459 :   return code;
     249             : }
     250             : 
     251             : // Ensure that the code object in <code_table> at offset <func_index> has
     252             : // deoptimization data attached. This is needed for lazy compile stubs which are
     253             : // called from JS_TO_WASM functions or via exported function tables. The deopt
     254             : // data is used to determine which function this lazy compile stub belongs to.
     255        8610 : Handle<Code> EnsureTableExportLazyDeoptData(
     256             :     Isolate* isolate, Handle<WasmInstanceObject> instance,
     257             :     Handle<FixedArray> code_table, int func_index,
     258             :     Handle<FixedArray> export_table, int export_index,
     259             :     std::unordered_map<uint32_t, uint32_t>& table_export_count) {
     260             :   Handle<Code> code =
     261        8610 :       EnsureExportedLazyDeoptData(isolate, instance, code_table, func_index);
     262        8610 :   if (code->builtin_index() != Builtins::kWasmCompileLazy) return code;
     263             : 
     264             :   // deopt_data:
     265             :   // #0: weak instance
     266             :   // #1: func_index
     267             :   // [#2: export table
     268             :   //  #3: export table index]
     269             :   // [#4: export table
     270             :   //  #5: export table index]
     271             :   // ...
     272             :   // table_export_count counts down and determines the index for the new export
     273             :   // table entry.
     274       11884 :   auto table_export_entry = table_export_count.find(func_index);
     275             :   DCHECK(table_export_entry != table_export_count.end());
     276             :   DCHECK_LT(0, table_export_entry->second);
     277        5942 :   uint32_t this_idx = 2 * table_export_entry->second;
     278        5942 :   --table_export_entry->second;
     279             :   Handle<FixedArray> deopt_data(code->deoptimization_data());
     280             :   DCHECK_EQ(0, deopt_data->length() % 2);
     281        5942 :   if (deopt_data->length() == 2) {
     282             :     // Then only the "header" (#0 and #1) exists. Extend for the export table
     283             :     // entries (make space for this_idx + 2 elements).
     284             :     deopt_data = isolate->factory()->CopyFixedArrayAndGrow(deopt_data, this_idx,
     285        4128 :                                                            TENURED);
     286        4128 :     code->set_deoptimization_data(*deopt_data);
     287             :   }
     288             :   DCHECK_LE(this_idx + 2, deopt_data->length());
     289             :   DCHECK(deopt_data->get(this_idx)->IsUndefined(isolate));
     290             :   DCHECK(deopt_data->get(this_idx + 1)->IsUndefined(isolate));
     291       11884 :   deopt_data->set(this_idx, *export_table);
     292        5942 :   deopt_data->set(this_idx + 1, Smi::FromInt(export_index));
     293        5942 :   return code;
     294             : }
     295             : 
     296        4607 : bool compile_lazy(const WasmModule* module) {
     297       16812 :   return FLAG_wasm_lazy_compilation ||
     298        4607 :          (FLAG_asm_wasm_lazy_compilation && module->is_asm_js());
     299             : }
     300             : 
     301             : // A helper for compiling an entire module.
     302       55658 : class CompilationHelper {
     303             :  public:
     304       27829 :   CompilationHelper(Isolate* isolate, WasmModule* module)
     305       83487 :       : isolate_(isolate), module_(module) {}
     306             : 
     307             :   // The actual runnable task that performs compilations in the background.
     308       28619 :   class CompilationTask : public CancelableTask {
     309             :    public:
     310             :     CompilationHelper* helper_;
     311             :     explicit CompilationTask(CompilationHelper* helper)
     312       14322 :         : CancelableTask(helper->isolate_), helper_(helper) {}
     313             : 
     314       12375 :     void RunInternal() override {
     315       12375 :       while (helper_->FetchAndExecuteCompilationUnit()) {
     316             :       }
     317       24768 :       helper_->module_->pending_tasks.get()->Signal();
     318       12372 :     }
     319             :   };
     320             : 
     321             :   Isolate* isolate_;
     322             :   WasmModule* module_;
     323             :   std::vector<compiler::WasmCompilationUnit*> compilation_units_;
     324             :   std::queue<compiler::WasmCompilationUnit*> executed_units_;
     325             :   base::Mutex result_mutex_;
     326             :   base::AtomicNumber<size_t> next_unit_;
     327             :   size_t num_background_tasks_ = 0;
     328             : 
     329             :   // Run by each compilation task and by the main thread.
     330       41103 :   bool FetchAndExecuteCompilationUnit() {
     331             :     DisallowHeapAllocation no_allocation;
     332             :     DisallowHandleAllocation no_handles;
     333             :     DisallowHandleDereference no_deref;
     334             :     DisallowCodeDependencyChange no_dependency_change;
     335             : 
     336             :     // - 1 because AtomicIncrement returns the value after the atomic increment.
     337       41107 :     size_t index = next_unit_.Increment(1) - 1;
     338       82214 :     if (index >= compilation_units_.size()) {
     339             :       return false;
     340             :     }
     341             : 
     342       26468 :     compiler::WasmCompilationUnit* unit = compilation_units_.at(index);
     343       26468 :     unit->ExecuteCompilation();
     344       26468 :     base::LockGuard<base::Mutex> guard(&result_mutex_);
     345             :     executed_units_.push(unit);
     346             :     return true;
     347             :   }
     348             : 
     349        2256 :   size_t InitializeParallelCompilation(
     350       28728 :       const std::vector<WasmFunction>& functions, ModuleBytesEnv& module_env) {
     351        2256 :     uint32_t start = module_env.module_env.module->num_imported_functions +
     352        2256 :                      FLAG_skip_compiling_wasm_funcs;
     353        2256 :     uint32_t num_funcs = static_cast<uint32_t>(functions.size());
     354        2256 :     uint32_t funcs_to_compile = start > num_funcs ? 0 : num_funcs - start;
     355        2256 :     compilation_units_.reserve(funcs_to_compile);
     356       28728 :     for (uint32_t i = start; i < num_funcs; ++i) {
     357       26472 :       const WasmFunction* func = &functions[i];
     358             :       compilation_units_.push_back(
     359       52944 :           new compiler::WasmCompilationUnit(isolate_, &module_env, func));
     360             :     }
     361        2256 :     return funcs_to_compile;
     362             :   }
     363             : 
     364             :   void InitializeHandles() {
     365       55740 :     for (auto unit : compilation_units_) {
     366       26472 :       unit->InitializeHandles();
     367             :     }
     368             :   }
     369             : 
     370        2046 :   uint32_t* StartCompilationTasks() {
     371             :     num_background_tasks_ =
     372             :         Min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks),
     373        4092 :             V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads());
     374        2046 :     uint32_t* task_ids = new uint32_t[num_background_tasks_];
     375       16368 :     for (size_t i = 0; i < num_background_tasks_; ++i) {
     376       14322 :       CompilationTask* task = new CompilationTask(this);
     377       14322 :       task_ids[i] = task->id();
     378       14322 :       V8::GetCurrentPlatform()->CallOnBackgroundThread(
     379       14322 :           task, v8::Platform::kShortRunningTask);
     380             :     }
     381        2046 :     return task_ids;
     382             :   }
     383             : 
     384        2046 :   void WaitForCompilationTasks(uint32_t* task_ids) {
     385       16368 :     for (size_t i = 0; i < num_background_tasks_; ++i) {
     386             :       // If the task has not started yet, then we abort it. Otherwise we wait
     387             :       // for it to finish.
     388       14322 :       if (isolate_->cancelable_task_manager()->TryAbort(task_ids[i]) !=
     389             :           CancelableTaskManager::kTaskAborted) {
     390       24772 :         module_->pending_tasks.get()->Wait();
     391             :       }
     392             :     }
     393        2046 :   }
     394             : 
     395       29502 :   void FinishCompilationUnits(std::vector<Handle<Code>>& results,
     396             :                               ErrorThrower* thrower) {
     397             :     while (true) {
     398       29502 :       int func_index = -1;
     399       29502 :       Handle<Code> result = FinishCompilationUnit(thrower, &func_index);
     400       29502 :       if (func_index < 0) break;
     401       52524 :       results[func_index] = result;
     402       26262 :     }
     403        3240 :   }
     404             : 
     405       29712 :   Handle<Code> FinishCompilationUnit(ErrorThrower* thrower, int* func_index) {
     406       26472 :     compiler::WasmCompilationUnit* unit = nullptr;
     407             :     {
     408       29712 :       base::LockGuard<base::Mutex> guard(&result_mutex_);
     409       29712 :       if (executed_units_.empty()) return Handle<Code>::null();
     410       26472 :       unit = executed_units_.front();
     411             :       executed_units_.pop();
     412             :     }
     413       26472 :     *func_index = unit->func_index();
     414       26472 :     Handle<Code> result = unit->FinishCompilation(thrower);
     415       26472 :     delete unit;
     416       26472 :     return result;
     417             :   }
     418             : 
     419        2046 :   void CompileInParallel(ModuleBytesEnv* module_env,
     420             :                          std::vector<Handle<Code>>& results,
     421             :                          ErrorThrower* thrower) {
     422        2046 :     const WasmModule* module = module_env->module_env.module;
     423             :     // Data structures for the parallel compilation.
     424             : 
     425             :     //-----------------------------------------------------------------------
     426             :     // For parallel compilation:
     427             :     // 1) The main thread allocates a compilation unit for each wasm function
     428             :     //    and stores them in the vector {compilation_units}.
     429             :     // 2) The main thread spawns {CompilationTask} instances which run on
     430             :     //    the background threads.
     431             :     // 3.a) The background threads and the main thread pick one compilation
     432             :     //      unit at a time and execute the parallel phase of the compilation
     433             :     //      unit. After finishing the execution of the parallel phase, the
     434             :     //      result is enqueued in {executed_units}.
     435             :     // 3.b) If {executed_units} contains a compilation unit, the main thread
     436             :     //      dequeues it and finishes the compilation.
     437             :     // 4) After the parallel phase of all compilation units has started, the
     438             :     //    main thread waits for all {CompilationTask} instances to finish.
     439             :     // 5) The main thread finishes the compilation.
     440             : 
     441             :     // Turn on the {CanonicalHandleScope} so that the background threads can
     442             :     // use the node cache.
     443        2046 :     CanonicalHandleScope canonical(isolate_);
     444             : 
     445             :     // 1) The main thread allocates a compilation unit for each wasm function
     446             :     //    and stores them in the vector {compilation_units}.
     447        2046 :     InitializeParallelCompilation(module->functions, *module_env);
     448             :     InitializeHandles();
     449             : 
     450             :     // Objects for the synchronization with the background threads.
     451             :     base::AtomicNumber<size_t> next_unit(
     452             :         static_cast<size_t>(FLAG_skip_compiling_wasm_funcs));
     453             : 
     454             :     // 2) The main thread spawns {CompilationTask} instances which run on
     455             :     //    the background threads.
     456        2046 :     std::unique_ptr<uint32_t[]> task_ids(StartCompilationTasks());
     457             : 
     458             :     // 3.a) The background threads and the main thread pick one compilation
     459             :     //      unit at a time and execute the parallel phase of the compilation
     460             :     //      unit. After finishing the execution of the parallel phase, the
     461             :     //      result is enqueued in {executed_units}.
     462        3240 :     while (FetchAndExecuteCompilationUnit()) {
     463             :       // 3.b) If {executed_units} contains a compilation unit, the main thread
     464             :       //      dequeues it and finishes the compilation unit. Compilation units
     465             :       //      are finished concurrently to the background threads to save
     466             :       //      memory.
     467        1194 :       FinishCompilationUnits(results, thrower);
     468             :     }
     469             :     // 4) After the parallel phase of all compilation units has started, the
     470             :     //    main thread waits for all {CompilationTask} instances to finish.
     471        2046 :     WaitForCompilationTasks(task_ids.get());
     472             :     // Finish the compilation of the remaining compilation units.
     473        4092 :     FinishCompilationUnits(results, thrower);
     474        2046 :   }
     475             : 
     476        9689 :   void CompileSequentially(ModuleBytesEnv* module_env,
     477        8371 :                            std::vector<Handle<Code>>& results,
     478             :                            ErrorThrower* thrower) {
     479             :     DCHECK(!thrower->error());
     480             : 
     481        9689 :     const WasmModule* module = module_env->module_env.module;
     482       46782 :     for (uint32_t i = FLAG_skip_compiling_wasm_funcs;
     483       23391 :          i < module->functions.size(); ++i) {
     484       23554 :       const WasmFunction& func = module->functions[i];
     485       13865 :       if (func.imported)
     486        5331 :         continue;  // Imports are compiled at instantiation time.
     487             : 
     488             :       // Compile the function.
     489             :       Handle<Code> code = compiler::WasmCompilationUnit::CompileWasmFunction(
     490        8534 :           thrower, isolate_, module_env, &func);
     491        8534 :       if (code.is_null()) {
     492         163 :         WasmName str = module_env->wire_bytes.GetName(&func);
     493             :         thrower->CompileError("Compilation of #%d:%.*s failed.", i,
     494         163 :                               str.length(), str.start());
     495             :         break;
     496             :       }
     497        8371 :       results[i] = code;
     498             :     }
     499        9689 :   }
     500             : 
     501       15344 :   MaybeHandle<WasmModuleObject> CompileToModuleObject(
     502             :       ErrorThrower* thrower, const ModuleWireBytes& wire_bytes,
     503             :       Handle<Script> asm_js_script,
     504             :       Vector<const byte> asm_js_offset_table_bytes) {
     505       57467 :     Factory* factory = isolate_->factory();
     506             :     // The {module_wrapper} will take ownership of the {WasmModule} object,
     507             :     // and it will be destroyed when the GC reclaims the wrapper object.
     508             :     Handle<WasmModuleWrapper> module_wrapper =
     509       46032 :         WasmModuleWrapper::New(isolate_, module_);
     510       15344 :     WasmInstance temp_instance(module_);
     511       15344 :     temp_instance.context = isolate_->native_context();
     512       15344 :     temp_instance.mem_size = WasmModule::kPageSize * module_->min_mem_pages;
     513       15344 :     temp_instance.mem_start = nullptr;
     514       15344 :     temp_instance.globals_start = nullptr;
     515             : 
     516             :     // Initialize the indirect tables with placeholders.
     517             :     int function_table_count =
     518       30688 :         static_cast<int>(module_->function_tables.size());
     519             :     Handle<FixedArray> function_tables =
     520       15344 :         factory->NewFixedArray(function_table_count, TENURED);
     521             :     Handle<FixedArray> signature_tables =
     522       15344 :         factory->NewFixedArray(function_table_count, TENURED);
     523         949 :     for (int i = 0; i < function_table_count; ++i) {
     524        1898 :       temp_instance.function_tables[i] = factory->NewFixedArray(1, TENURED);
     525        1898 :       temp_instance.signature_tables[i] = factory->NewFixedArray(1, TENURED);
     526        1898 :       function_tables->set(i, *temp_instance.function_tables[i]);
     527        1898 :       signature_tables->set(i, *temp_instance.signature_tables[i]);
     528             :     }
     529             : 
     530             :     HistogramTimerScope wasm_compile_module_time_scope(
     531       15344 :         module_->is_wasm()
     532       11735 :             ? isolate_->counters()->wasm_compile_wasm_module_time()
     533       30688 :             : isolate_->counters()->wasm_compile_asm_module_time());
     534             : 
     535       15344 :     ModuleBytesEnv module_env(module_, &temp_instance, wire_bytes);
     536             : 
     537             :     // The {code_table} array contains import wrappers and functions (which
     538             :     // are both included in {functions.size()}, and export wrappers.
     539       98679 :     int code_table_size = static_cast<int>(module_->functions.size() +
     540       15344 :                                            module_->num_exported_functions);
     541             :     Handle<FixedArray> code_table =
     542       15344 :         factory->NewFixedArray(static_cast<int>(code_table_size), TENURED);
     543             : 
     544             :     // Check whether lazy compilation is enabled for this module.
     545       15344 :     bool lazy_compile = compile_lazy(module_);
     546             : 
     547             :     // If lazy compile: Initialize the code table with the lazy compile builtin.
     548             :     // Otherwise: Initialize with the illegal builtin. All call sites will be
     549             :     // patched at instantiation.
     550             :     Handle<Code> init_builtin = lazy_compile
     551        3609 :                                     ? isolate_->builtins()->WasmCompileLazy()
     552       18953 :                                     : isolate_->builtins()->Illegal();
     553       91758 :     for (int i = 0, e = static_cast<int>(module_->functions.size()); i < e;
     554             :          ++i) {
     555       61070 :       code_table->set(i, *init_builtin);
     556      122140 :       temp_instance.function_code[i] = init_builtin;
     557             :     }
     558             : 
     559       11735 :     (module_->is_wasm() ? isolate_->counters()->wasm_functions_per_wasm_module()
     560        3609 :                         : isolate_->counters()->wasm_functions_per_asm_module())
     561       61376 :         ->AddSample(static_cast<int>(module_->functions.size()));
     562             : 
     563       15344 :     if (!lazy_compile) {
     564       11735 :       CompilationHelper helper(isolate_, module_);
     565             :       size_t funcs_to_compile =
     566       23470 :           module_->functions.size() - module_->num_imported_functions;
     567       11735 :       if (!FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks != 0 &&
     568             :           funcs_to_compile > 1) {
     569             :         // Avoid a race condition by collecting results into a second vector.
     570        2046 :         std::vector<Handle<Code>> results(temp_instance.function_code);
     571        2046 :         helper.CompileInParallel(&module_env, results, thrower);
     572             :         temp_instance.function_code.swap(results);
     573             :       } else {
     574             :         helper.CompileSequentially(&module_env, temp_instance.function_code,
     575        9689 :                                    thrower);
     576             :       }
     577       12035 :       if (thrower->error()) return {};
     578             :     }
     579             : 
     580             :     // At this point, compilation has completed. Update the code table.
     581      150732 :     for (size_t i = FLAG_skip_compiling_wasm_funcs;
     582       75366 :          i < temp_instance.function_code.size(); ++i) {
     583             :       Code* code = *temp_instance.function_code[i];
     584      120644 :       code_table->set(static_cast<int>(i), code);
     585       60322 :       RecordStats(isolate_, code);
     586             :     }
     587             : 
     588             :     // Create heap objects for script, module bytes and asm.js offset table to
     589             :     // be
     590             :     // stored in the shared module data.
     591             :     Handle<Script> script;
     592             :     Handle<ByteArray> asm_js_offset_table;
     593       15044 :     if (asm_js_script.is_null()) {
     594       11435 :       script = CreateWasmScript(isolate_, wire_bytes);
     595             :     } else {
     596             :       script = asm_js_script;
     597             :       asm_js_offset_table =
     598        3609 :           isolate_->factory()->NewByteArray(asm_js_offset_table_bytes.length());
     599             :       asm_js_offset_table->copy_in(0, asm_js_offset_table_bytes.start(),
     600        3609 :                                    asm_js_offset_table_bytes.length());
     601             :     }
     602             :     // TODO(wasm): only save the sections necessary to deserialize a
     603             :     // {WasmModule}. E.g. function bodies could be omitted.
     604             :     Handle<String> module_bytes =
     605             :         factory
     606             :             ->NewStringFromOneByte({wire_bytes.start(), wire_bytes.length()},
     607             :                                    TENURED)
     608       30088 :             .ToHandleChecked();
     609             :     DCHECK(module_bytes->IsSeqOneByteString());
     610             : 
     611             :     // Create the shared module data.
     612             :     // TODO(clemensh): For the same module (same bytes / same hash), we should
     613             :     // only have one WasmSharedModuleData. Otherwise, we might only set
     614             :     // breakpoints on a (potentially empty) subset of the instances.
     615             : 
     616             :     Handle<WasmSharedModuleData> shared = WasmSharedModuleData::New(
     617             :         isolate_, module_wrapper, Handle<SeqOneByteString>::cast(module_bytes),
     618       15044 :         script, asm_js_offset_table);
     619       15044 :     if (lazy_compile) WasmSharedModuleData::PrepareForLazyCompilation(shared);
     620             : 
     621             :     // Create the compiled module object, and populate with compiled functions
     622             :     // and information needed at instantiation time. This object needs to be
     623             :     // serializable. Instantiation may occur off a deserialized version of this
     624             :     // object.
     625             :     Handle<WasmCompiledModule> compiled_module = WasmCompiledModule::New(
     626       15044 :         isolate_, shared, code_table, function_tables, signature_tables);
     627             : 
     628             :     // If we created a wasm script, finish it now and make it public to the
     629             :     // debugger.
     630       15044 :     if (asm_js_script.is_null()) {
     631       11435 :       script->set_wasm_compiled_module(*compiled_module);
     632       22870 :       isolate_->debug()->OnAfterCompile(script);
     633             :     }
     634             : 
     635             :     // Compile JS->WASM wrappers for exported functions.
     636       15044 :     JSToWasmWrapperCache js_to_wasm_cache;
     637             :     int func_index = 0;
     638      113930 :     for (auto exp : module_->export_table) {
     639       42930 :       if (exp.kind != kExternalFunction) continue;
     640             :       Handle<Code> wasm_code = EnsureExportedLazyDeoptData(
     641       40912 :           isolate_, Handle<WasmInstanceObject>::null(), code_table, exp.index);
     642             :       Handle<Code> wrapper_code =
     643             :           js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(isolate_, module_,
     644       40912 :                                                          wasm_code, exp.index);
     645             :       int export_index =
     646       40912 :           static_cast<int>(module_->functions.size() + func_index);
     647       40912 :       code_table->set(export_index, *wrapper_code);
     648       40912 :       RecordStats(isolate_, *wrapper_code);
     649       40912 :       func_index++;
     650             :     }
     651             : 
     652       30388 :     return WasmModuleObject::New(isolate_, compiled_module);
     653             : }
     654             : };
     655             : 
     656       15949 : static void MemoryInstanceFinalizer(Isolate* isolate,
     657             :                                     WasmInstanceObject* instance) {
     658             :   DisallowHeapAllocation no_gc;
     659             :   // If the memory object is destroyed, nothing needs to be done here.
     660       15949 :   if (!instance->has_memory_object()) return;
     661             :   Handle<WasmInstanceWrapper> instance_wrapper =
     662        1137 :       handle(instance->instance_wrapper());
     663             :   DCHECK(WasmInstanceWrapper::IsWasmInstanceWrapper(*instance_wrapper));
     664             :   DCHECK(instance_wrapper->has_instance());
     665        1137 :   bool has_prev = instance_wrapper->has_previous();
     666        1137 :   bool has_next = instance_wrapper->has_next();
     667        1137 :   Handle<WasmMemoryObject> memory_object(instance->memory_object());
     668             : 
     669        1137 :   if (!has_prev && !has_next) {
     670         807 :     memory_object->ResetInstancesLink(isolate);
     671         807 :     return;
     672             :   } else {
     673             :     Handle<WasmInstanceWrapper> next_wrapper, prev_wrapper;
     674         330 :     if (!has_prev) {
     675             :       Handle<WasmInstanceWrapper> next_wrapper =
     676          61 :           instance_wrapper->next_wrapper();
     677             :       next_wrapper->reset_previous_wrapper();
     678             :       // As this is the first link in the memory object, destroying
     679             :       // without updating memory object would corrupt the instance chain in
     680             :       // the memory object.
     681          61 :       memory_object->set_instances_link(*next_wrapper);
     682         269 :     } else if (!has_next) {
     683         414 :       instance_wrapper->previous_wrapper()->reset_next_wrapper();
     684             :     } else {
     685             :       DCHECK(has_next && has_prev);
     686             :       Handle<WasmInstanceWrapper> prev_wrapper =
     687          62 :           instance_wrapper->previous_wrapper();
     688             :       Handle<WasmInstanceWrapper> next_wrapper =
     689          62 :           instance_wrapper->next_wrapper();
     690             :       prev_wrapper->set_next_wrapper(*next_wrapper);
     691             :       next_wrapper->set_previous_wrapper(*prev_wrapper);
     692             :     }
     693             :     // Reset to avoid dangling pointers
     694             :     instance_wrapper->reset();
     695             :   }
     696             : }
     697             : 
     698       31898 : static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) {
     699             :   DisallowHeapAllocation no_gc;
     700             :   JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter());
     701       15949 :   WasmInstanceObject* owner = reinterpret_cast<WasmInstanceObject*>(*p);
     702             :   Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate());
     703             :   // If a link to shared memory instances exists, update the list of memory
     704             :   // instances before the instance is destroyed.
     705       15949 :   if (owner->has_instance_wrapper()) MemoryInstanceFinalizer(isolate, owner);
     706       15949 :   WasmCompiledModule* compiled_module = owner->compiled_module();
     707             :   TRACE("Finalizing %d {\n", compiled_module->instance_id());
     708             :   DCHECK(compiled_module->has_weak_wasm_module());
     709             :   WeakCell* weak_wasm_module = compiled_module->ptr_to_weak_wasm_module();
     710             : 
     711       15949 :   if (trap_handler::UseTrapHandler()) {
     712        3096 :     Handle<FixedArray> code_table = compiled_module->code_table();
     713       35292 :     for (int i = 0; i < code_table->length(); ++i) {
     714       14550 :       Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i);
     715             :       int index = code->trap_handler_index()->value();
     716       14550 :       if (index >= 0) {
     717         188 :         trap_handler::ReleaseHandlerData(index);
     718         188 :         code->set_trap_handler_index(Smi::FromInt(-1));
     719             :       }
     720             :     }
     721             :   }
     722             : 
     723             :   // weak_wasm_module may have been cleared, meaning the module object
     724             :   // was GC-ed. In that case, there won't be any new instances created,
     725             :   // and we don't need to maintain the links between instances.
     726       15949 :   if (!weak_wasm_module->cleared()) {
     727             :     JSObject* wasm_module = JSObject::cast(weak_wasm_module->value());
     728             :     WasmCompiledModule* current_template =
     729             :         WasmCompiledModule::cast(wasm_module->GetEmbedderField(0));
     730             : 
     731             :     TRACE("chain before {\n");
     732        2786 :     TRACE_CHAIN(current_template);
     733             :     TRACE("}\n");
     734             : 
     735             :     DCHECK(!current_template->has_weak_prev_instance());
     736        2786 :     WeakCell* next = compiled_module->maybe_ptr_to_weak_next_instance();
     737        2786 :     WeakCell* prev = compiled_module->maybe_ptr_to_weak_prev_instance();
     738             : 
     739        2786 :     if (current_template == compiled_module) {
     740        2014 :       if (next == nullptr) {
     741        1665 :         WasmCompiledModule::Reset(isolate, compiled_module);
     742             :       } else {
     743             :         DCHECK(next->value()->IsFixedArray());
     744         349 :         wasm_module->SetEmbedderField(0, next->value());
     745             :         DCHECK_NULL(prev);
     746             :         WasmCompiledModule::cast(next->value())->reset_weak_prev_instance();
     747             :       }
     748             :     } else {
     749             :       DCHECK(!(prev == nullptr && next == nullptr));
     750             :       // the only reason prev or next would be cleared is if the
     751             :       // respective objects got collected, but if that happened,
     752             :       // we would have relinked the list.
     753         772 :       if (prev != nullptr) {
     754             :         DCHECK(!prev->cleared());
     755         772 :         if (next == nullptr) {
     756             :           WasmCompiledModule::cast(prev->value())->reset_weak_next_instance();
     757             :         } else {
     758             :           WasmCompiledModule::cast(prev->value())
     759             :               ->set_ptr_to_weak_next_instance(next);
     760             :         }
     761             :       }
     762         772 :       if (next != nullptr) {
     763             :         DCHECK(!next->cleared());
     764         180 :         if (prev == nullptr) {
     765             :           WasmCompiledModule::cast(next->value())->reset_weak_prev_instance();
     766             :         } else {
     767             :           WasmCompiledModule::cast(next->value())
     768             :               ->set_ptr_to_weak_prev_instance(prev);
     769             :         }
     770             :       }
     771             :     }
     772             :     TRACE("chain after {\n");
     773        2786 :     TRACE_CHAIN(WasmCompiledModule::cast(wasm_module->GetEmbedderField(0)));
     774             :     TRACE("}\n");
     775             :   }
     776             :   compiled_module->reset_weak_owning_instance();
     777       15949 :   GlobalHandles::Destroy(reinterpret_cast<Object**>(p));
     778             :   TRACE("}\n");
     779       15949 : }
     780             : 
     781      136345 : int AdvanceSourcePositionTableIterator(SourcePositionTableIterator& iterator,
     782             :                                        int offset) {
     783             :   DCHECK(!iterator.done());
     784             :   int byte_pos;
     785       55302 :   do {
     786             :     byte_pos = iterator.source_position().ScriptOffset();
     787       55302 :     iterator.Advance();
     788      110604 :   } while (!iterator.done() && iterator.code_offset() <= offset);
     789       25741 :   return byte_pos;
     790             : }
     791             : 
     792       25741 : int ExtractDirectCallIndex(wasm::Decoder& decoder, const byte* pc) {
     793             :   DCHECK_EQ(static_cast<int>(kExprCallFunction), static_cast<int>(*pc));
     794             :   // Read the leb128 encoded u32 value (up to 5 bytes starting at pc + 1).
     795       25741 :   decoder.Reset(pc + 1, pc + 6);
     796             :   uint32_t call_idx = decoder.consume_u32v("call index");
     797             :   DCHECK(decoder.ok());
     798             :   DCHECK_GE(kMaxInt, call_idx);
     799       25741 :   return static_cast<int>(call_idx);
     800             : }
     801             : 
     802       37449 : void RecordLazyCodeStats(Isolate* isolate, Code* code) {
     803       12483 :   isolate->counters()->wasm_lazily_compiled_functions()->Increment();
     804       24966 :   isolate->counters()->wasm_generated_code_size()->Increment(code->body_size());
     805             :   isolate->counters()->wasm_reloc_size()->Increment(
     806       12483 :       code->relocation_info()->length());
     807       12483 : }
     808             : 
     809             : }  // namespace
     810             : 
     811       12329 : Handle<JSArrayBuffer> wasm::SetupArrayBuffer(Isolate* isolate,
     812             :                                              void* backing_store, size_t size,
     813             :                                              bool is_external,
     814             :                                              bool enable_guard_regions) {
     815       11695 :   Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
     816             :   JSArrayBuffer::Setup(buffer, isolate, is_external, backing_store,
     817       11695 :                        static_cast<int>(size));
     818             :   buffer->set_is_neuterable(false);
     819             :   buffer->set_has_guard_region(enable_guard_regions);
     820             : 
     821       11695 :   if (is_external) {
     822             :     // We mark the buffer as external if we allocated it here with guard
     823             :     // pages. That means we need to arrange for it to be freed.
     824             : 
     825             :     // TODO(eholk): Finalizers may not run when the main thread is shutting
     826             :     // down, which means we may leak memory here.
     827             :     Handle<Object> global_handle = isolate->global_handles()->Create(*buffer);
     828             :     GlobalHandles::MakeWeak(global_handle.location(), global_handle.location(),
     829         634 :                             &MemoryFinalizer, v8::WeakCallbackType::kFinalizer);
     830             :   }
     831       11695 :   return buffer;
     832             : }
     833             : 
     834       11650 : Handle<JSArrayBuffer> wasm::NewArrayBuffer(Isolate* isolate, size_t size,
     835             :                                            bool enable_guard_regions) {
     836       11650 :   if (size > (FLAG_wasm_max_mem_pages * WasmModule::kPageSize)) {
     837             :     // TODO(titzer): lift restriction on maximum memory allocated here.
     838             :     return Handle<JSArrayBuffer>::null();
     839             :   }
     840             : 
     841             :   enable_guard_regions = enable_guard_regions && kGuardRegionsSupported;
     842             : 
     843             :   bool is_external;  // Set by TryAllocateBackingStore
     844             :   void* memory =
     845       11650 :       TryAllocateBackingStore(isolate, size, enable_guard_regions, is_external);
     846             : 
     847       11650 :   if (memory == nullptr) {
     848             :     return Handle<JSArrayBuffer>::null();
     849             :   }
     850             : 
     851             : #if DEBUG
     852             :   // Double check the API allocator actually zero-initialized the memory.
     853             :   const byte* bytes = reinterpret_cast<const byte*>(memory);
     854             :   for (size_t i = 0; i < size; ++i) {
     855             :     DCHECK_EQ(0, bytes[i]);
     856             :   }
     857             : #endif
     858             : 
     859             :   return SetupArrayBuffer(isolate, memory, size, is_external,
     860       11650 :                           enable_guard_regions);
     861             : }
     862             : 
     863        6186 : void wasm::UnpackAndRegisterProtectedInstructions(
     864        7741 :     Isolate* isolate, Handle<FixedArray> code_table) {
     865       50346 :   for (int i = 0; i < code_table->length(); ++i) {
     866             :     Handle<Code> code;
     867             :     // This is sometimes undefined when we're called from cctests.
     868       37974 :     if (!code_table->GetValue<Code>(isolate, i).ToHandle(&code)) {
     869       11246 :       continue;
     870             :     }
     871             : 
     872       18078 :     if (code->kind() != Code::WASM_FUNCTION) {
     873             :       continue;
     874             :     }
     875             : 
     876        7741 :     const intptr_t base = reinterpret_cast<intptr_t>(code->entry());
     877             : 
     878        7741 :     Zone zone(isolate->allocator(), "Wasm Module");
     879             :     ZoneVector<trap_handler::ProtectedInstructionData> unpacked(&zone);
     880             :     const int mode_mask =
     881             :         RelocInfo::ModeMask(RelocInfo::WASM_PROTECTED_INSTRUCTION_LANDING);
     882        9428 :     for (RelocIterator it(*code, mode_mask); !it.done(); it.next()) {
     883             :       trap_handler::ProtectedInstructionData data;
     884        1687 :       data.instr_offset = it.rinfo()->data();
     885        1687 :       data.landing_offset = reinterpret_cast<intptr_t>(it.rinfo()->pc()) - base;
     886        1687 :       unpacked.emplace_back(data);
     887             :     }
     888       15482 :     if (unpacked.size() > 0) {
     889             :       int size = code->CodeSize();
     890             :       const int index = RegisterHandlerData(reinterpret_cast<void*>(base), size,
     891         336 :                                             unpacked.size(), &unpacked[0]);
     892             :       // TODO(eholk): if index is negative, fail.
     893             :       DCHECK(index >= 0);
     894         336 :       code->set_trap_handler_index(Smi::FromInt(index));
     895             :     }
     896        7741 :   }
     897        6186 : }
     898             : 
     899         466 : std::ostream& wasm::operator<<(std::ostream& os, const WasmFunctionName& name) {
     900         466 :   os << "#" << name.function_->func_index;
     901         466 :   if (name.function_->name_offset > 0) {
     902           0 :     if (name.name_.start()) {
     903           0 :       os << ":";
     904           0 :       os.write(name.name_.start(), name.name_.length());
     905             :     }
     906             :   } else {
     907         466 :     os << "?";
     908             :   }
     909         466 :   return os;
     910             : }
     911             : 
     912      162287 : WasmInstanceObject* wasm::GetOwningWasmInstance(Code* code) {
     913             :   DisallowHeapAllocation no_gc;
     914             :   DCHECK(code->kind() == Code::WASM_FUNCTION ||
     915             :          code->kind() == Code::WASM_INTERPRETER_ENTRY);
     916             :   FixedArray* deopt_data = code->deoptimization_data();
     917             :   DCHECK_EQ(code->kind() == Code::WASM_INTERPRETER_ENTRY ? 1 : 2,
     918             :             deopt_data->length());
     919             :   Object* weak_link = deopt_data->get(0);
     920             :   DCHECK(weak_link->IsWeakCell());
     921             :   WeakCell* cell = WeakCell::cast(weak_link);
     922      162287 :   if (cell->cleared()) return nullptr;
     923      162287 :   return WasmInstanceObject::cast(cell->value());
     924             : }
     925             : 
     926       59651 : WasmModule::WasmModule(Zone* owned)
     927      238604 :     : owned_zone(owned), pending_tasks(new base::Semaphore(0)) {}
     928             : 
     929             : namespace {
     930             : 
     931       39906 : WasmFunction* GetWasmFunctionForImportWrapper(Isolate* isolate,
     932             :                                               Handle<Object> target) {
     933       39906 :   if (target->IsJSFunction()) {
     934             :     Handle<JSFunction> func = Handle<JSFunction>::cast(target);
     935       39861 :     if (func->code()->kind() == Code::JS_TO_WASM_FUNCTION) {
     936             :       auto exported = Handle<WasmExportedFunction>::cast(func);
     937        3171 :       Handle<WasmInstanceObject> other_instance(exported->instance(), isolate);
     938        3171 :       int func_index = exported->function_index();
     939        6342 :       return &other_instance->module()->functions[func_index];
     940             :     }
     941             :   }
     942             :   return nullptr;
     943             : }
     944             : 
     945        3126 : static Handle<Code> UnwrapImportWrapper(Handle<Object> import_wrapper) {
     946             :   Handle<JSFunction> func = Handle<JSFunction>::cast(import_wrapper);
     947        3126 :   Handle<Code> export_wrapper_code = handle(func->code());
     948             :   int mask = RelocInfo::ModeMask(RelocInfo::CODE_TARGET);
     949        3981 :   for (RelocIterator it(*export_wrapper_code, mask);; it.next()) {
     950             :     DCHECK(!it.done());
     951        7962 :     Code* target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
     952        5997 :     if (target->kind() != Code::WASM_FUNCTION &&
     953        4842 :         target->kind() != Code::WASM_TO_JS_FUNCTION &&
     954             :         target->kind() != Code::WASM_INTERPRETER_ENTRY)
     955             :       continue;
     956             : // There should only be this one call to wasm code.
     957             : #ifdef DEBUG
     958             :     for (it.next(); !it.done(); it.next()) {
     959             :       Code* code = Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
     960             :       DCHECK(code->kind() != Code::WASM_FUNCTION &&
     961             :              code->kind() != Code::WASM_TO_JS_FUNCTION &&
     962             :              code->kind() != Code::WASM_INTERPRETER_ENTRY);
     963             :     }
     964             : #endif
     965             :     return handle(target);
     966         855 :   }
     967             :   UNREACHABLE();
     968             :   return Handle<Code>::null();
     969             : }
     970             : 
     971       36831 : Handle<Code> CompileImportWrapper(Isolate* isolate, int index, FunctionSig* sig,
     972             :                                   Handle<JSReceiver> target,
     973             :                                   Handle<String> module_name,
     974             :                                   MaybeHandle<String> import_name,
     975             :                                   ModuleOrigin origin) {
     976       36831 :   WasmFunction* other_func = GetWasmFunctionForImportWrapper(isolate, target);
     977       36831 :   if (other_func) {
     978          96 :     if (!sig->Equals(other_func->sig)) return Handle<Code>::null();
     979             :     // Signature matched. Unwrap the JS->WASM wrapper and return the raw
     980             :     // WASM function code.
     981          51 :     return UnwrapImportWrapper(target);
     982             :   }
     983             :   // No wasm function or being debugged. Compile a new wrapper for the new
     984             :   // signature.
     985             :   return compiler::CompileWasmToJSWrapper(isolate, target, sig, index,
     986       36735 :                                           module_name, import_name, origin);
     987             : }
     988             : 
     989        4772 : void UpdateDispatchTablesInternal(Isolate* isolate,
     990             :                                   Handle<FixedArray> dispatch_tables, int index,
     991             :                                   WasmFunction* function, Handle<Code> code) {
     992             :   DCHECK_EQ(0, dispatch_tables->length() % 4);
     993       18934 :   for (int i = 0; i < dispatch_tables->length(); i += 4) {
     994        4695 :     int table_index = Smi::cast(dispatch_tables->get(i + 1))->value();
     995             :     Handle<FixedArray> function_table(
     996        4695 :         FixedArray::cast(dispatch_tables->get(i + 2)), isolate);
     997             :     Handle<FixedArray> signature_table(
     998        4695 :         FixedArray::cast(dispatch_tables->get(i + 3)), isolate);
     999        4695 :     if (function) {
    1000             :       // TODO(titzer): the signature might need to be copied to avoid
    1001             :       // a dangling pointer in the signature map.
    1002             :       Handle<WasmInstanceObject> instance(
    1003        3045 :           WasmInstanceObject::cast(dispatch_tables->get(i)), isolate);
    1004        9135 :       auto func_table = instance->module()->function_tables[table_index];
    1005        3045 :       uint32_t sig_index = func_table.map.FindOrInsert(function->sig);
    1006        3045 :       signature_table->set(index, Smi::FromInt(static_cast<int>(sig_index)));
    1007        3045 :       function_table->set(index, *code);
    1008             :     } else {
    1009             :       signature_table->set(index, Smi::FromInt(-1));
    1010             :       function_table->set(index, Smi::kZero);
    1011             :     }
    1012             :   }
    1013        4772 : }
    1014             : 
    1015             : }  // namespace
    1016             : 
    1017        3480 : void wasm::UpdateDispatchTables(Isolate* isolate,
    1018             :                                 Handle<FixedArray> dispatch_tables, int index,
    1019             :                                 Handle<JSFunction> function) {
    1020        3480 :   if (function.is_null()) {
    1021             :     UpdateDispatchTablesInternal(isolate, dispatch_tables, index, nullptr,
    1022        2250 :                                  Handle<Code>::null());
    1023             :   } else {
    1024             :     UpdateDispatchTablesInternal(
    1025             :         isolate, dispatch_tables, index,
    1026             :         GetWasmFunctionForImportWrapper(isolate, function),
    1027        2460 :         UnwrapImportWrapper(function));
    1028             :   }
    1029        3480 : }
    1030             : 
    1031             : // A helper class to simplify instantiating a module from a compiled module.
    1032             : // It closes over the {Isolate}, the {ErrorThrower}, the {WasmCompiledModule},
    1033             : // etc.
    1034       96184 : class InstantiationHelper {
    1035             :  public:
    1036       48092 :   InstantiationHelper(Isolate* isolate, ErrorThrower* thrower,
    1037             :                       Handle<WasmModuleObject> module_object,
    1038             :                       MaybeHandle<JSReceiver> ffi,
    1039             :                       MaybeHandle<JSArrayBuffer> memory)
    1040             :       : isolate_(isolate),
    1041       48092 :         module_(module_object->compiled_module()->module()),
    1042             :         thrower_(thrower),
    1043             :         module_object_(module_object),
    1044             :         ffi_(ffi.is_null() ? Handle<JSReceiver>::null()
    1045             :                            : ffi.ToHandleChecked()),
    1046             :         memory_(memory.is_null() ? Handle<JSArrayBuffer>::null()
    1047      282075 :                                  : memory.ToHandleChecked()) {}
    1048             : 
    1049             :   // Build an instance, in all of its glory.
    1050       54592 :   MaybeHandle<WasmInstanceObject> Build() {
    1051             :     // Check that an imports argument was provided, if the module requires it.
    1052             :     // No point in continuing otherwise.
    1053      228814 :     if (!module_->import_table.empty() && ffi_.is_null()) {
    1054             :       thrower_->TypeError(
    1055         122 :           "Imports argument must be present and must be an object");
    1056             :       return {};
    1057             :     }
    1058             : 
    1059             :     // Record build time into correct bucket, then build instance.
    1060             :     HistogramTimerScope wasm_instantiate_module_time_scope(
    1061             :         module_->is_wasm()
    1062      190514 :             ? isolate_->counters()->wasm_instantiate_wasm_module_time()
    1063       95940 :             : isolate_->counters()->wasm_instantiate_asm_module_time());
    1064       47970 :     Factory* factory = isolate_->factory();
    1065             : 
    1066             :     //--------------------------------------------------------------------------
    1067             :     // Reuse the compiled module (if no owner), otherwise clone.
    1068             :     //--------------------------------------------------------------------------
    1069             :     Handle<FixedArray> code_table;
    1070             :     // We keep around a copy of the old code table, because we'll be replacing
    1071             :     // imports for the new instance, and then we need the old imports to be
    1072             :     // able to relocate.
    1073             :     Handle<FixedArray> old_code_table;
    1074             :     MaybeHandle<WasmInstanceObject> owner;
    1075             : 
    1076             :     TRACE("Starting new module instantiation\n");
    1077             :     {
    1078             :       // Root the owner, if any, before doing any allocations, which
    1079             :       // may trigger GC.
    1080             :       // Both owner and original template need to be in sync. Even
    1081             :       // after we lose the original template handle, the code
    1082             :       // objects we copied from it have data relative to the
    1083             :       // instance - such as globals addresses.
    1084             :       Handle<WasmCompiledModule> original;
    1085             :       {
    1086             :         DisallowHeapAllocation no_gc;
    1087       47970 :         original = handle(module_object_->compiled_module());
    1088       47970 :         if (original->has_weak_owning_instance()) {
    1089             :           owner = handle(WasmInstanceObject::cast(
    1090       96369 :               original->weak_owning_instance()->value()));
    1091             :         }
    1092             :       }
    1093             :       DCHECK(!original.is_null());
    1094       47970 :       if (original->has_weak_owning_instance()) {
    1095             :         // Clone, but don't insert yet the clone in the instances chain.
    1096             :         // We do that last. Since we are holding on to the owner instance,
    1097             :         // the owner + original state used for cloning and patching
    1098             :         // won't be mutated by possible finalizer runs.
    1099             :         DCHECK(!owner.is_null());
    1100             :         TRACE("Cloning from %d\n", original->instance_id());
    1101       32123 :         old_code_table = original->code_table();
    1102       32123 :         compiled_module_ = WasmCompiledModule::Clone(isolate_, original);
    1103       32123 :         code_table = compiled_module_->code_table();
    1104             :         // Avoid creating too many handles in the outer scope.
    1105       32123 :         HandleScope scope(isolate_);
    1106             : 
    1107             :         // Clone the code for WASM functions and exports.
    1108      295642 :         for (int i = 0; i < code_table->length(); ++i) {
    1109      115698 :           Handle<Code> orig_code(Code::cast(code_table->get(i)), isolate_);
    1110      115698 :           switch (orig_code->kind()) {
    1111             :             case Code::WASM_TO_JS_FUNCTION:
    1112             :               // Imports will be overwritten with newly compiled wrappers.
    1113             :               break;
    1114             :             case Code::BUILTIN:
    1115             :               DCHECK_EQ(Builtins::kWasmCompileLazy, orig_code->builtin_index());
    1116             :               // If this code object has deoptimization data, then we need a
    1117             :               // unique copy to attach updated deoptimization data.
    1118        6811 :               if (orig_code->deoptimization_data()->length() > 0) {
    1119        3894 :                 Handle<Code> code = factory->CopyCode(orig_code);
    1120             :                 Handle<FixedArray> deopt_data =
    1121        3894 :                     factory->NewFixedArray(2, TENURED);
    1122             :                 deopt_data->set(1, Smi::FromInt(i));
    1123        3894 :                 code->set_deoptimization_data(*deopt_data);
    1124        3894 :                 code_table->set(i, *code);
    1125             :               }
    1126             :               break;
    1127             :             case Code::JS_TO_WASM_FUNCTION:
    1128             :             case Code::WASM_FUNCTION: {
    1129       78812 :               Handle<Code> code = factory->CopyCode(orig_code);
    1130       78812 :               code_table->set(i, *code);
    1131             :               break;
    1132             :             }
    1133             :             default:
    1134           0 :               UNREACHABLE();
    1135             :           }
    1136             :         }
    1137       32123 :         RecordStats(isolate_, code_table);
    1138             :       } else {
    1139             :         // There was no owner, so we can reuse the original.
    1140       15847 :         compiled_module_ = original;
    1141             :         old_code_table =
    1142       15847 :             factory->CopyFixedArray(compiled_module_->code_table());
    1143       15847 :         code_table = compiled_module_->code_table();
    1144             :         TRACE("Reusing existing instance %d\n",
    1145             :               compiled_module_->instance_id());
    1146             :       }
    1147       47970 :       compiled_module_->set_native_context(isolate_->native_context());
    1148             :     }
    1149             : 
    1150             :     //--------------------------------------------------------------------------
    1151             :     // Allocate the instance object.
    1152             :     //--------------------------------------------------------------------------
    1153       95940 :     Zone instantiation_zone(isolate_->allocator(), ZONE_NAME);
    1154       95940 :     CodeSpecialization code_specialization(isolate_, &instantiation_zone);
    1155             :     Handle<WasmInstanceObject> instance =
    1156       47970 :         WasmInstanceObject::New(isolate_, compiled_module_);
    1157             : 
    1158             :     //--------------------------------------------------------------------------
    1159             :     // Set up the globals for the new instance.
    1160             :     //--------------------------------------------------------------------------
    1161             :     MaybeHandle<JSArrayBuffer> old_globals;
    1162       47970 :     uint32_t globals_size = module_->globals_size;
    1163       47970 :     if (globals_size > 0) {
    1164             :       const bool enable_guard_regions = false;
    1165             :       Handle<JSArrayBuffer> global_buffer =
    1166        2860 :           NewArrayBuffer(isolate_, globals_size, enable_guard_regions);
    1167        2860 :       globals_ = global_buffer;
    1168        2860 :       if (globals_.is_null()) {
    1169           0 :         thrower_->RangeError("Out of memory: wasm globals");
    1170             :         return {};
    1171             :       }
    1172        2860 :       Address old_globals_start = compiled_module_->GetGlobalsStartOrNull();
    1173             :       Address new_globals_start =
    1174             :           static_cast<Address>(global_buffer->backing_store());
    1175        2860 :       code_specialization.RelocateGlobals(old_globals_start, new_globals_start);
    1176             :       // The address of the backing buffer for the golbals is in native memory
    1177             :       // and, thus, not moving. We need it saved for
    1178             :       // serialization/deserialization purposes - so that the other end
    1179             :       // understands how to relocate the references. We still need to save the
    1180             :       // JSArrayBuffer on the instance, to keep it all alive.
    1181             :       WasmCompiledModule::SetGlobalsStartAddressFrom(factory, compiled_module_,
    1182        2860 :                                                      global_buffer);
    1183        2860 :       instance->set_globals_buffer(*global_buffer);
    1184             :     }
    1185             : 
    1186             :     //--------------------------------------------------------------------------
    1187             :     // Prepare for initialization of function tables.
    1188             :     //--------------------------------------------------------------------------
    1189             :     int function_table_count =
    1190       95940 :         static_cast<int>(module_->function_tables.size());
    1191       49088 :     table_instances_.reserve(module_->function_tables.size());
    1192       49603 :     for (int index = 0; index < function_table_count; ++index) {
    1193             :       table_instances_.push_back(
    1194             :           {Handle<WasmTableObject>::null(), Handle<FixedArray>::null(),
    1195        3266 :            Handle<FixedArray>::null(), Handle<FixedArray>::null()});
    1196             :     }
    1197             : 
    1198             :     //--------------------------------------------------------------------------
    1199             :     // Process the imports for the module.
    1200             :     //--------------------------------------------------------------------------
    1201       47970 :     int num_imported_functions = ProcessImports(code_table, instance);
    1202       47970 :     if (num_imported_functions < 0) return {};
    1203             : 
    1204             :     //--------------------------------------------------------------------------
    1205             :     // Process the initialization for the module's globals.
    1206             :     //--------------------------------------------------------------------------
    1207       47295 :     InitGlobals();
    1208             : 
    1209             :     //--------------------------------------------------------------------------
    1210             :     // Set up the indirect function tables for the new instance.
    1211             :     //--------------------------------------------------------------------------
    1212       47295 :     if (function_table_count > 0)
    1213        1468 :       InitializeTables(instance, &code_specialization);
    1214             : 
    1215             :     //--------------------------------------------------------------------------
    1216             :     // Set up the memory for the new instance.
    1217             :     //--------------------------------------------------------------------------
    1218       47295 :     uint32_t min_mem_pages = module_->min_mem_pages;
    1219       40815 :     (module_->is_wasm() ? isolate_->counters()->wasm_wasm_min_mem_pages_count()
    1220        6480 :                         : isolate_->counters()->wasm_asm_min_mem_pages_count())
    1221      141885 :         ->AddSample(min_mem_pages);
    1222             : 
    1223       47295 :     if (!memory_.is_null()) {
    1224             :       // Set externally passed ArrayBuffer non neuterable.
    1225             :       memory_->set_is_neuterable(false);
    1226             : 
    1227             :       DCHECK_IMPLIES(EnableGuardRegions(),
    1228             :                      module_->is_asm_js() || memory_->has_guard_region());
    1229       44100 :     } else if (min_mem_pages > 0) {
    1230        6500 :       memory_ = AllocateMemory(min_mem_pages);
    1231        6500 :       if (memory_.is_null()) return {};  // failed to allocate memory
    1232             :     }
    1233             : 
    1234             :     //--------------------------------------------------------------------------
    1235             :     // Check that indirect function table segments are within bounds.
    1236             :     //--------------------------------------------------------------------------
    1237      143003 :     for (WasmTableInit& table_init : module_->table_inits) {
    1238             :       DCHECK(table_init.table_index < table_instances_.size());
    1239        1118 :       uint32_t base = EvalUint32InitExpr(table_init.offset);
    1240             :       uint32_t table_size =
    1241        2236 :           table_instances_[table_init.table_index].function_table->length();
    1242        2236 :       if (!in_bounds(base, static_cast<uint32_t>(table_init.entries.size()),
    1243        1118 :                      table_size)) {
    1244           0 :         thrower_->LinkError("table initializer is out of bounds");
    1245             :         return {};
    1246             :       }
    1247             :     }
    1248             : 
    1249             :     //--------------------------------------------------------------------------
    1250             :     // Check that memory segments are within bounds.
    1251             :     //--------------------------------------------------------------------------
    1252       94876 :     for (WasmDataSegment& seg : module_->data_segments) {
    1253         302 :       uint32_t base = EvalUint32InitExpr(seg.dest_addr);
    1254             :       uint32_t mem_size = memory_.is_null()
    1255         588 :           ? 0 : static_cast<uint32_t>(memory_->byte_length()->Number());
    1256         604 :       if (!in_bounds(base, seg.source_size, mem_size)) {
    1257          16 :         thrower_->LinkError("data segment is out of bounds");
    1258             :         return {};
    1259             :       }
    1260             :     }
    1261             : 
    1262             :     //--------------------------------------------------------------------------
    1263             :     // Initialize memory.
    1264             :     //--------------------------------------------------------------------------
    1265       47279 :     if (!memory_.is_null()) {
    1266             :       Address mem_start = static_cast<Address>(memory_->backing_store());
    1267             :       uint32_t mem_size =
    1268        9687 :           static_cast<uint32_t>(memory_->byte_length()->Number());
    1269        9687 :       LoadDataSegments(mem_start, mem_size);
    1270             : 
    1271        9687 :       uint32_t old_mem_size = compiled_module_->mem_size();
    1272        9687 :       Address old_mem_start = compiled_module_->GetEmbeddedMemStartOrNull();
    1273             :       // We might get instantiated again with the same memory. No patching
    1274             :       // needed in this case.
    1275        9687 :       if (old_mem_start != mem_start || old_mem_size != mem_size) {
    1276             :         code_specialization.RelocateMemoryReferences(
    1277        9429 :             old_mem_start, old_mem_size, mem_start, mem_size);
    1278             :       }
    1279             :       // Just like with globals, we need to keep both the JSArrayBuffer
    1280             :       // and save the start pointer.
    1281        9687 :       instance->set_memory_buffer(*memory_);
    1282             :       WasmCompiledModule::SetSpecializationMemInfoFrom(
    1283        9687 :           factory, compiled_module_, memory_);
    1284             :     }
    1285             : 
    1286             :     //--------------------------------------------------------------------------
    1287             :     // Set up the runtime support for the new instance.
    1288             :     //--------------------------------------------------------------------------
    1289       47279 :     Handle<WeakCell> weak_link = factory->NewWeakCell(instance);
    1290             : 
    1291      198864 :     for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs,
    1292      102597 :              num_functions = static_cast<int>(module_->functions.size());
    1293             :          i < num_functions; ++i) {
    1294      104306 :       Handle<Code> code = handle(Code::cast(code_table->get(i)), isolate_);
    1295      104306 :       if (code->kind() == Code::WASM_FUNCTION) {
    1296       78947 :         Handle<FixedArray> deopt_data = factory->NewFixedArray(2, TENURED);
    1297       78947 :         deopt_data->set(0, *weak_link);
    1298             :         deopt_data->set(1, Smi::FromInt(i));
    1299       78947 :         code->set_deoptimization_data(*deopt_data);
    1300             :         continue;
    1301             :       }
    1302             :       DCHECK_EQ(Builtins::kWasmCompileLazy, code->builtin_index());
    1303       25359 :       if (code->deoptimization_data()->length() == 0) continue;
    1304             :       DCHECK_LE(2, code->deoptimization_data()->length());
    1305             :       DCHECK_EQ(i, Smi::cast(code->deoptimization_data()->get(1))->value());
    1306       11858 :       code->deoptimization_data()->set(0, *weak_link);
    1307             :     }
    1308             : 
    1309             :     //--------------------------------------------------------------------------
    1310             :     // Set up the exports object for the new instance.
    1311             :     //--------------------------------------------------------------------------
    1312       47279 :     ProcessExports(code_table, instance, compiled_module_);
    1313             : 
    1314             :     //--------------------------------------------------------------------------
    1315             :     // Add instance to Memory object
    1316             :     //--------------------------------------------------------------------------
    1317             :     DCHECK(wasm::IsWasmInstance(*instance));
    1318       47279 :     if (instance->has_memory_object()) {
    1319        3484 :       instance->memory_object()->AddInstance(isolate_, instance);
    1320             :     }
    1321             : 
    1322             :     //--------------------------------------------------------------------------
    1323             :     // Initialize the indirect function tables.
    1324             :     //--------------------------------------------------------------------------
    1325       47279 :     if (function_table_count > 0) LoadTableSegments(code_table, instance);
    1326             : 
    1327             :     // Patch all code with the relocations registered in code_specialization.
    1328       47279 :     code_specialization.RelocateDirectCalls(instance);
    1329       47279 :     code_specialization.ApplyToWholeInstance(*instance, SKIP_ICACHE_FLUSH);
    1330             : 
    1331       47279 :     FlushICache(isolate_, code_table);
    1332             : 
    1333             :     //--------------------------------------------------------------------------
    1334             :     // Unpack and notify signal handler of protected instructions.
    1335             :     //--------------------------------------------------------------------------
    1336       47279 :     if (trap_handler::UseTrapHandler()) {
    1337        3167 :       UnpackAndRegisterProtectedInstructions(isolate_, code_table);
    1338             :     }
    1339             : 
    1340             :     //--------------------------------------------------------------------------
    1341             :     // Set up and link the new instance.
    1342             :     //--------------------------------------------------------------------------
    1343             :     {
    1344             :       Handle<Object> global_handle =
    1345       94558 :           isolate_->global_handles()->Create(*instance);
    1346       47279 :       Handle<WeakCell> link_to_clone = factory->NewWeakCell(compiled_module_);
    1347       47279 :       Handle<WeakCell> link_to_owning_instance = factory->NewWeakCell(instance);
    1348             :       MaybeHandle<WeakCell> link_to_original;
    1349             :       MaybeHandle<WasmCompiledModule> original;
    1350       47279 :       if (!owner.is_null()) {
    1351             :         // prepare the data needed for publishing in a chain, but don't link
    1352             :         // just yet, because
    1353             :         // we want all the publishing to happen free from GC interruptions, and
    1354             :         // so we do it in
    1355             :         // one GC-free scope afterwards.
    1356       32123 :         original = handle(owner.ToHandleChecked()->compiled_module());
    1357       32123 :         link_to_original = factory->NewWeakCell(original.ToHandleChecked());
    1358             :       }
    1359             :       // Publish the new instance to the instances chain.
    1360             :       {
    1361             :         DisallowHeapAllocation no_gc;
    1362       47279 :         if (!link_to_original.is_null()) {
    1363             :           compiled_module_->set_weak_next_instance(
    1364             :               link_to_original.ToHandleChecked());
    1365             :           original.ToHandleChecked()->set_weak_prev_instance(link_to_clone);
    1366             :           compiled_module_->set_weak_wasm_module(
    1367       32123 :               original.ToHandleChecked()->weak_wasm_module());
    1368             :         }
    1369       47279 :         module_object_->SetEmbedderField(0, *compiled_module_);
    1370             :         compiled_module_->set_weak_owning_instance(link_to_owning_instance);
    1371             :         GlobalHandles::MakeWeak(global_handle.location(),
    1372             :                                 global_handle.location(), &InstanceFinalizer,
    1373       47279 :                                 v8::WeakCallbackType::kFinalizer);
    1374             :       }
    1375             :     }
    1376             : 
    1377             :     //--------------------------------------------------------------------------
    1378             :     // Debugging support.
    1379             :     //--------------------------------------------------------------------------
    1380             :     // Set all breakpoints that were set on the shared module.
    1381             :     WasmSharedModuleData::SetBreakpointsOnNewInstance(
    1382       47279 :         compiled_module_->shared(), instance);
    1383             : 
    1384       47279 :     if (FLAG_wasm_interpret_all) {
    1385             :       Handle<WasmDebugInfo> debug_info =
    1386        1050 :           WasmInstanceObject::GetOrCreateDebugInfo(instance);
    1387             :       std::vector<int> func_indexes;
    1388        5640 :       for (int func_index = num_imported_functions,
    1389        2100 :                num_wasm_functions = static_cast<int>(module_->functions.size());
    1390        2295 :            func_index < num_wasm_functions; ++func_index) {
    1391        1245 :         func_indexes.push_back(func_index);
    1392             :       }
    1393             :       WasmDebugInfo::RedirectToInterpreter(
    1394             :           debug_info, Vector<int>(func_indexes.data(),
    1395        3150 :                                   static_cast<int>(func_indexes.size())));
    1396             :     }
    1397             : 
    1398             :     //--------------------------------------------------------------------------
    1399             :     // Run the start function if one was specified.
    1400             :     //--------------------------------------------------------------------------
    1401       47279 :     if (module_->start_function_index >= 0) {
    1402        6989 :       HandleScope scope(isolate_);
    1403             :       int start_index = module_->start_function_index;
    1404             :       Handle<Code> startup_code = EnsureExportedLazyDeoptData(
    1405        6989 :           isolate_, instance, code_table, start_index);
    1406       20967 :       FunctionSig* sig = module_->functions[start_index].sig;
    1407             :       Handle<Code> wrapper_code =
    1408             :           js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper(
    1409        6989 :               isolate_, module_, startup_code, start_index);
    1410             :       Handle<WasmExportedFunction> startup_fct = WasmExportedFunction::New(
    1411             :           isolate_, instance, MaybeHandle<String>(), start_index,
    1412       13978 :           static_cast<int>(sig->parameter_count()), wrapper_code);
    1413        6989 :       RecordStats(isolate_, *startup_code);
    1414             :       // Call the JS function.
    1415             :       Handle<Object> undefined = factory->undefined_value();
    1416             :       MaybeHandle<Object> retval =
    1417        6989 :           Execution::Call(isolate_, startup_fct, undefined, 0, nullptr);
    1418             : 
    1419        6989 :       if (retval.is_null()) {
    1420             :         DCHECK(isolate_->has_pending_exception());
    1421          32 :         isolate_->OptionalRescheduleException(false);
    1422             :         // It's unfortunate that the new instance is already linked in the
    1423             :         // chain. However, we need to set up everything before executing the
    1424             :         // start function, such that stack trace information can be generated
    1425             :         // correctly already in the start function.
    1426             :         return {};
    1427             :       }
    1428             :     }
    1429             : 
    1430             :     DCHECK(!isolate_->has_pending_exception());
    1431             :     TRACE("Finishing instance %d\n", compiled_module_->instance_id());
    1432       47247 :     TRACE_CHAIN(module_object_->compiled_module());
    1433       47970 :     return instance;
    1434             :   }
    1435             : 
    1436             :  private:
    1437             :   // Represents the initialized state of a table.
    1438             :   struct TableInstance {
    1439             :     Handle<WasmTableObject> table_object;    // WebAssembly.Table instance
    1440             :     Handle<FixedArray> js_wrappers;          // JSFunctions exported
    1441             :     Handle<FixedArray> function_table;       // internal code array
    1442             :     Handle<FixedArray> signature_table;      // internal sig array
    1443             :   };
    1444             : 
    1445             :   Isolate* isolate_;
    1446             :   WasmModule* const module_;
    1447             :   ErrorThrower* thrower_;
    1448             :   Handle<WasmModuleObject> module_object_;
    1449             :   Handle<JSReceiver> ffi_;        // TODO(titzer): Use MaybeHandle
    1450             :   Handle<JSArrayBuffer> memory_;  // TODO(titzer): Use MaybeHandle
    1451             :   Handle<JSArrayBuffer> globals_;
    1452             :   Handle<WasmCompiledModule> compiled_module_;
    1453             :   std::vector<TableInstance> table_instances_;
    1454             :   std::vector<Handle<JSFunction>> js_wrappers_;
    1455             :   JSToWasmWrapperCache js_to_wasm_cache_;
    1456             : 
    1457             : // Helper routines to print out errors with imports.
    1458             : #define ERROR_THROWER_WITH_MESSAGE(TYPE)                                      \
    1459             :   void Report##TYPE(const char* error, uint32_t index,                        \
    1460             :                     Handle<String> module_name, Handle<String> import_name) { \
    1461             :     thrower_->TYPE("Import #%d module=\"%.*s\" function=\"%.*s\" error: %s",  \
    1462             :                    index, module_name->length(),                              \
    1463             :                    module_name->ToCString().get(), import_name->length(),     \
    1464             :                    import_name->ToCString().get(), error);                    \
    1465             :   }                                                                           \
    1466             :                                                                               \
    1467             :   MaybeHandle<Object> Report##TYPE(const char* error, uint32_t index,         \
    1468             :                                    Handle<String> module_name) {              \
    1469             :     thrower_->TYPE("Import #%d module=\"%.*s\" error: %s", index,             \
    1470             :                    module_name->length(), module_name->ToCString().get(),     \
    1471             :                    error);                                                    \
    1472             :     return MaybeHandle<Object>();                                             \
    1473             :   }
    1474             : 
    1475        1440 :   ERROR_THROWER_WITH_MESSAGE(LinkError)
    1476        1275 :   ERROR_THROWER_WITH_MESSAGE(TypeError)
    1477             : 
    1478             :   // Look up an import value in the {ffi_} object.
    1479       40207 :   MaybeHandle<Object> LookupImport(uint32_t index, Handle<String> module_name,
    1480             :                                    Handle<String> import_name) {
    1481             :     // We pre-validated in the js-api layer that the ffi object is present, and
    1482             :     // a JSObject, if the module has imports.
    1483             :     DCHECK(!ffi_.is_null());
    1484             : 
    1485             :     // Look up the module first.
    1486             :     MaybeHandle<Object> result =
    1487       40207 :         Object::GetPropertyOrElement(ffi_, module_name);
    1488       40207 :     if (result.is_null()) {
    1489           0 :       return ReportTypeError("module not found", index, module_name);
    1490             :     }
    1491             : 
    1492             :     Handle<Object> module = result.ToHandleChecked();
    1493             : 
    1494             :     // Look up the value in the module.
    1495       40207 :     if (!module->IsJSReceiver()) {
    1496             :       return ReportTypeError("module is not an object or function", index,
    1497         255 :                              module_name);
    1498             :     }
    1499             : 
    1500       39952 :     result = Object::GetPropertyOrElement(module, import_name);
    1501       39952 :     if (result.is_null()) {
    1502           0 :       ReportLinkError("import not found", index, module_name, import_name);
    1503             :       return MaybeHandle<JSFunction>();
    1504             :     }
    1505             : 
    1506       39952 :     return result;
    1507             :   }
    1508             : 
    1509        2816 :   uint32_t EvalUint32InitExpr(const WasmInitExpr& expr) {
    1510        2816 :     switch (expr.kind) {
    1511             :       case WasmInitExpr::kI32Const:
    1512        1256 :         return expr.val.i32_const;
    1513             :       case WasmInitExpr::kGlobalIndex: {
    1514        3120 :         uint32_t offset = module_->globals[expr.val.global_index].offset;
    1515        3120 :         return *reinterpret_cast<uint32_t*>(raw_buffer_ptr(globals_, offset));
    1516             :       }
    1517             :       default:
    1518           0 :         UNREACHABLE();
    1519             :         return 0;
    1520             :     }
    1521             :   }
    1522             : 
    1523             :   bool in_bounds(uint32_t offset, uint32_t size, uint32_t upper) {
    1524        1420 :     return offset + size <= upper && offset + size >= offset;
    1525             :   }
    1526             : 
    1527             :   // Load data segments into the memory.
    1528        9687 :   void LoadDataSegments(Address mem_addr, size_t mem_size) {
    1529             :     Handle<SeqOneByteString> module_bytes(compiled_module_->module_bytes(),
    1530       19374 :                                           isolate_);
    1531       29339 :     for (const WasmDataSegment& segment : module_->data_segments) {
    1532         278 :       uint32_t source_size = segment.source_size;
    1533             :       // Segments of size == 0 are just nops.
    1534         278 :       if (source_size == 0) continue;
    1535         278 :       uint32_t dest_offset = EvalUint32InitExpr(segment.dest_addr);
    1536             :       DCHECK(in_bounds(dest_offset, source_size,
    1537             :                        static_cast<uint32_t>(mem_size)));
    1538         278 :       byte* dest = mem_addr + dest_offset;
    1539             :       const byte* src = reinterpret_cast<const byte*>(
    1540         278 :           module_bytes->GetCharsAddress() + segment.source_offset);
    1541         278 :       memcpy(dest, src, source_size);
    1542             :     }
    1543        9687 :   }
    1544             : 
    1545        2372 :   void WriteGlobalValue(WasmGlobal& global, Handle<Object> value) {
    1546             :     double num = value->Number();
    1547             :     TRACE("init [globals+%u] = %lf, type = %s\n", global.offset, num,
    1548             :           WasmOpcodes::TypeName(global.type));
    1549        1186 :     switch (global.type) {
    1550             :       case kWasmI32:
    1551        1003 :         *GetRawGlobalPtr<int32_t>(global) = static_cast<int32_t>(num);
    1552        1003 :         break;
    1553             :       case kWasmI64:
    1554             :         // TODO(titzer): initialization of imported i64 globals.
    1555           0 :         UNREACHABLE();
    1556             :         break;
    1557             :       case kWasmF32:
    1558          45 :         *GetRawGlobalPtr<float>(global) = static_cast<float>(num);
    1559          45 :         break;
    1560             :       case kWasmF64:
    1561         138 :         *GetRawGlobalPtr<double>(global) = static_cast<double>(num);
    1562         138 :         break;
    1563             :       default:
    1564           0 :         UNREACHABLE();
    1565             :     }
    1566        1186 :   }
    1567             : 
    1568             :   // Process the imports, including functions, tables, globals, and memory, in
    1569             :   // order, loading them from the {ffi_} object. Returns the number of imported
    1570             :   // functions.
    1571       47970 :   int ProcessImports(Handle<FixedArray> code_table,
    1572             :                      Handle<WasmInstanceObject> instance) {
    1573             :     int num_imported_functions = 0;
    1574             :     int num_imported_tables = 0;
    1575      262506 :     for (int index = 0; index < static_cast<int>(module_->import_table.size());
    1576             :          ++index) {
    1577      165771 :       WasmImport& import = module_->import_table[index];
    1578             : 
    1579             :       Handle<String> module_name;
    1580             :       MaybeHandle<String> maybe_module_name =
    1581             :           WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    1582             :               isolate_, compiled_module_, import.module_name_offset,
    1583       40207 :               import.module_name_length);
    1584       40207 :       if (!maybe_module_name.ToHandle(&module_name)) return -1;
    1585             : 
    1586             :       Handle<String> import_name;
    1587             :       MaybeHandle<String> maybe_import_name =
    1588             :           WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    1589             :               isolate_, compiled_module_, import.field_name_offset,
    1590       40207 :               import.field_name_length);
    1591       40207 :       if (!maybe_import_name.ToHandle(&import_name)) return -1;
    1592             : 
    1593             :       MaybeHandle<Object> result =
    1594       40207 :           LookupImport(index, module_name, import_name);
    1595       80414 :       if (thrower_->error()) return -1;
    1596             :       Handle<Object> value = result.ToHandleChecked();
    1597             : 
    1598       39952 :       switch (import.kind) {
    1599             :         case kExternalFunction: {
    1600             :           // Function imports must be callable.
    1601       36921 :           if (!value->IsCallable()) {
    1602             :             ReportLinkError("function import requires a callable", index,
    1603          90 :                             module_name, import_name);
    1604          90 :             return -1;
    1605             :           }
    1606             : 
    1607             :           Handle<Code> import_wrapper = CompileImportWrapper(
    1608       36831 :               isolate_, index, module_->functions[import.index].sig,
    1609             :               Handle<JSReceiver>::cast(value), module_name, import_name,
    1610      110493 :               module_->get_origin());
    1611       36831 :           if (import_wrapper.is_null()) {
    1612             :             ReportLinkError(
    1613             :                 "imported function does not match the expected type", index,
    1614          45 :                 module_name, import_name);
    1615          45 :             return -1;
    1616             :           }
    1617       36786 :           code_table->set(num_imported_functions, *import_wrapper);
    1618       36786 :           RecordStats(isolate_, *import_wrapper);
    1619       36786 :           num_imported_functions++;
    1620             :           break;
    1621             :         }
    1622             :         case kExternalTable: {
    1623         765 :           if (!WasmJs::IsWasmTableObject(isolate_, value)) {
    1624             :             ReportLinkError("table import requires a WebAssembly.Table", index,
    1625           0 :                             module_name, import_name);
    1626           0 :             return -1;
    1627             :           }
    1628             :           WasmIndirectFunctionTable& table =
    1629         765 :               module_->function_tables[num_imported_tables];
    1630         765 :           TableInstance& table_instance = table_instances_[num_imported_tables];
    1631         765 :           table_instance.table_object = Handle<WasmTableObject>::cast(value);
    1632             :           table_instance.js_wrappers = Handle<FixedArray>(
    1633        2295 :               table_instance.table_object->functions(), isolate_);
    1634             : 
    1635             :           int imported_cur_size = table_instance.js_wrappers->length();
    1636         765 :           if (imported_cur_size < static_cast<int>(table.min_size)) {
    1637             :             thrower_->LinkError(
    1638             :                 "table import %d is smaller than minimum %d, got %u", index,
    1639          45 :                 table.min_size, imported_cur_size);
    1640          45 :             return -1;
    1641             :           }
    1642             : 
    1643         720 :           if (table.has_max) {
    1644             :             int64_t imported_max_size =
    1645         705 :                 table_instance.table_object->maximum_length();
    1646         705 :             if (imported_max_size < 0) {
    1647             :               thrower_->LinkError(
    1648             :                   "table import %d has no maximum length, expected %d", index,
    1649          15 :                   table.max_size);
    1650          15 :               return -1;
    1651             :             }
    1652         690 :             if (imported_max_size > table.max_size) {
    1653             :               thrower_->LinkError(
    1654             :                   "table import %d has maximum larger than maximum %d, "
    1655             :                   "got %" PRIx64,
    1656          75 :                   index, table.max_size, imported_max_size);
    1657          75 :               return -1;
    1658             :             }
    1659             :           }
    1660             : 
    1661             :           // Allocate a new dispatch table and signature table.
    1662             :           int table_size = imported_cur_size;
    1663             :           table_instance.function_table =
    1664         630 :               isolate_->factory()->NewFixedArray(table_size);
    1665             :           table_instance.signature_table =
    1666         630 :               isolate_->factory()->NewFixedArray(table_size);
    1667        5970 :           for (int i = 0; i < table_size; ++i) {
    1668             :             table_instance.signature_table->set(i,
    1669             :                                                 Smi::FromInt(kInvalidSigIndex));
    1670             :           }
    1671             :           // Initialize the dispatch table with the (foreign) JS functions
    1672             :           // that are already in the table.
    1673        5340 :           for (int i = 0; i < table_size; ++i) {
    1674        5340 :             Handle<Object> val(table_instance.js_wrappers->get(i), isolate_);
    1675        5340 :             if (!val->IsJSFunction()) continue;
    1676             :             WasmFunction* function =
    1677        1845 :                 GetWasmFunctionForImportWrapper(isolate_, val);
    1678        1845 :             if (function == nullptr) {
    1679             :               thrower_->LinkError("table import %d[%d] is not a WASM function",
    1680           0 :                                   index, i);
    1681             :               return -1;
    1682             :             }
    1683        1845 :             int sig_index = table.map.FindOrInsert(function->sig);
    1684             :             table_instance.signature_table->set(i, Smi::FromInt(sig_index));
    1685        3690 :             table_instance.function_table->set(i, *UnwrapImportWrapper(val));
    1686             :           }
    1687             : 
    1688         630 :           num_imported_tables++;
    1689         630 :           break;
    1690             :         }
    1691             :         case kExternalMemory: {
    1692             :           // Validation should have failed if more than one memory object was
    1693             :           // provided.
    1694             :           DCHECK(!instance->has_memory_object());
    1695        1035 :           if (!WasmJs::IsWasmMemoryObject(isolate_, value)) {
    1696             :             ReportLinkError("memory import must be a WebAssembly.Memory object",
    1697          60 :                             index, module_name, import_name);
    1698          60 :             return -1;
    1699             :           }
    1700             :           auto memory = Handle<WasmMemoryObject>::cast(value);
    1701             :           DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory));
    1702         975 :           instance->set_memory_object(*memory);
    1703        2925 :           memory_ = Handle<JSArrayBuffer>(memory->buffer(), isolate_);
    1704             :           uint32_t imported_cur_pages = static_cast<uint32_t>(
    1705         975 :               memory_->byte_length()->Number() / WasmModule::kPageSize);
    1706         975 :           if (imported_cur_pages < module_->min_mem_pages) {
    1707             :             thrower_->LinkError(
    1708             :                 "memory import %d is smaller than maximum %u, got %u", index,
    1709           0 :                 module_->min_mem_pages, imported_cur_pages);
    1710             :           }
    1711         975 :           int32_t imported_max_pages = memory->maximum_pages();
    1712         975 :           if (module_->has_max_mem) {
    1713          60 :             if (imported_max_pages < 0) {
    1714             :               thrower_->LinkError(
    1715             :                   "memory import %d has no maximum limit, expected at most %u",
    1716          15 :                   index, imported_max_pages);
    1717          15 :               return -1;
    1718             :             }
    1719          45 :             if (static_cast<uint32_t>(imported_max_pages) >
    1720             :                 module_->max_mem_pages) {
    1721             :               thrower_->LinkError(
    1722             :                   "memory import %d has larger maximum than maximum %u, got %d",
    1723          30 :                   index, module_->max_mem_pages, imported_max_pages);
    1724          30 :               return -1;
    1725             :             }
    1726             :           }
    1727             :           break;
    1728             :         }
    1729             :         case kExternalGlobal: {
    1730             :           // Global imports are converted to numbers and written into the
    1731             :           // {globals_} array buffer.
    1732        3648 :           if (module_->globals[import.index].type == kWasmI64) {
    1733             :             ReportLinkError("global import cannot have type i64", index,
    1734           0 :                             module_name, import_name);
    1735           0 :             return -1;
    1736             :           }
    1737        1231 :           if (module_->is_asm_js() && FLAG_fast_validate_asm) {
    1738         256 :             if (module_->globals[import.index].type == kWasmI32) {
    1739         326 :               value = Object::ToInt32(isolate_, value).ToHandleChecked();
    1740             :             } else {
    1741         186 :               value = Object::ToNumber(value).ToHandleChecked();
    1742             :             }
    1743             :           }
    1744        1231 :           if (!value->IsNumber()) {
    1745             :             ReportLinkError("global import must be a number", index,
    1746          45 :                             module_name, import_name);
    1747          45 :             return -1;
    1748             :           }
    1749        2372 :           WriteGlobalValue(module_->globals[import.index], value);
    1750        1186 :           break;
    1751             :         }
    1752             :         default:
    1753           0 :           UNREACHABLE();
    1754             :           break;
    1755             :       }
    1756             :     }
    1757             :     return num_imported_functions;
    1758             :   }
    1759             : 
    1760             :   template <typename T>
    1761             :   T* GetRawGlobalPtr(WasmGlobal& global) {
    1762       21238 :     return reinterpret_cast<T*>(raw_buffer_ptr(globals_, global.offset));
    1763             :   }
    1764             : 
    1765             :   // Process initialization of globals.
    1766       47295 :   void InitGlobals() {
    1767      152498 :     for (auto global : module_->globals) {
    1768       10613 :       switch (global.init.kind) {
    1769             :         case WasmInitExpr::kI32Const:
    1770        5560 :           *GetRawGlobalPtr<int32_t>(global) = global.init.val.i32_const;
    1771        5560 :           break;
    1772             :         case WasmInitExpr::kI64Const:
    1773          32 :           *GetRawGlobalPtr<int64_t>(global) = global.init.val.i64_const;
    1774          32 :           break;
    1775             :         case WasmInitExpr::kF32Const:
    1776        2748 :           *GetRawGlobalPtr<float>(global) = global.init.val.f32_const;
    1777        2748 :           break;
    1778             :         case WasmInitExpr::kF64Const:
    1779         997 :           *GetRawGlobalPtr<double>(global) = global.init.val.f64_const;
    1780         997 :           break;
    1781             :         case WasmInitExpr::kGlobalIndex: {
    1782             :           // Initialize with another global.
    1783             :           uint32_t new_offset = global.offset;
    1784             :           uint32_t old_offset =
    1785         180 :               module_->globals[global.init.val.global_index].offset;
    1786             :           TRACE("init [globals+%u] = [globals+%d]\n", global.offset,
    1787             :                 old_offset);
    1788          90 :           size_t size = (global.type == kWasmI64 || global.type == kWasmF64)
    1789             :                             ? sizeof(double)
    1790          90 :                             : sizeof(int32_t);
    1791         270 :           memcpy(raw_buffer_ptr(globals_, new_offset),
    1792         270 :                  raw_buffer_ptr(globals_, old_offset), size);
    1793          90 :           break;
    1794             :         }
    1795             :         case WasmInitExpr::kNone:
    1796             :           // Happens with imported globals.
    1797             :           break;
    1798             :         default:
    1799           0 :           UNREACHABLE();
    1800             :           break;
    1801             :       }
    1802             :     }
    1803       47295 :   }
    1804             : 
    1805             :   // Allocate memory for a module instance as a new JSArrayBuffer.
    1806        6500 :   Handle<JSArrayBuffer> AllocateMemory(uint32_t min_mem_pages) {
    1807        6500 :     if (min_mem_pages > FLAG_wasm_max_mem_pages) {
    1808           0 :       thrower_->RangeError("Out of memory: wasm memory too large");
    1809             :       return Handle<JSArrayBuffer>::null();
    1810             :     }
    1811             :     const bool enable_guard_regions = EnableGuardRegions();
    1812             :     Handle<JSArrayBuffer> mem_buffer = NewArrayBuffer(
    1813        6500 :         isolate_, min_mem_pages * WasmModule::kPageSize, enable_guard_regions);
    1814             : 
    1815        6500 :     if (mem_buffer.is_null()) {
    1816           0 :       thrower_->RangeError("Out of memory: wasm memory");
    1817             :     }
    1818        6500 :     return mem_buffer;
    1819             :   }
    1820             : 
    1821       47279 :   bool NeedsWrappers() {
    1822       47279 :     if (module_->num_exported_functions > 0) return true;
    1823        2107 :     for (auto table_instance : table_instances_) {
    1824         333 :       if (!table_instance.js_wrappers.is_null()) return true;
    1825             :     }
    1826        1654 :     for (auto table : module_->function_tables) {
    1827         213 :       if (table.exported) return true;
    1828           0 :     }
    1829         614 :     return false;
    1830             :   }
    1831             : 
    1832             :   // Process the exports, creating wrappers for functions, tables, memories,
    1833             :   // and globals.
    1834       47279 :   void ProcessExports(Handle<FixedArray> code_table,
    1835             :                       Handle<WasmInstanceObject> instance,
    1836             :                       Handle<WasmCompiledModule> compiled_module) {
    1837       47279 :     if (NeedsWrappers()) {
    1838             :       // Fill the table to cache the exported JSFunction wrappers.
    1839             :       js_wrappers_.insert(js_wrappers_.begin(), module_->functions.size(),
    1840      842932 :                           Handle<JSFunction>::null());
    1841             :     }
    1842             : 
    1843             :     Handle<JSObject> exports_object;
    1844       94558 :     if (module_->is_wasm()) {
    1845             :       // Create the "exports" object.
    1846       40799 :       exports_object = isolate_->factory()->NewJSObjectWithNullProto();
    1847        6480 :     } else if (module_->is_asm_js()) {
    1848             :       Handle<JSFunction> object_function = Handle<JSFunction>(
    1849       12960 :           isolate_->native_context()->object_function(), isolate_);
    1850        6480 :       exports_object = isolate_->factory()->NewJSObject(object_function);
    1851             :     } else {
    1852           0 :       UNREACHABLE();
    1853             :     }
    1854             :     Handle<String> exports_name =
    1855       47279 :         isolate_->factory()->InternalizeUtf8String("exports");
    1856       47279 :     JSObject::AddProperty(instance, exports_name, exports_object, NONE);
    1857             : 
    1858             :     Handle<String> foreign_init_name =
    1859             :         isolate_->factory()->InternalizeUtf8String(
    1860       47279 :             wasm::AsmWasmBuilder::foreign_init_name);
    1861             :     Handle<String> single_function_name =
    1862             :         isolate_->factory()->InternalizeUtf8String(
    1863       47279 :             wasm::AsmWasmBuilder::single_function_name);
    1864             : 
    1865             :     PropertyDescriptor desc;
    1866       47279 :     desc.set_writable(module_->is_asm_js());
    1867             :     desc.set_enumerable(true);
    1868             :     desc.set_configurable(module_->is_asm_js());
    1869             : 
    1870             :     // Count up export indexes.
    1871             :     int export_index = 0;
    1872      175822 :     for (auto exp : module_->export_table) {
    1873       81264 :       if (exp.kind == kExternalFunction) {
    1874       79790 :         ++export_index;
    1875             :       }
    1876             :     }
    1877             : 
    1878             :     // Store weak references to all exported functions.
    1879             :     Handle<FixedArray> weak_exported_functions;
    1880       47279 :     if (compiled_module->has_weak_exported_functions()) {
    1881        1246 :       weak_exported_functions = compiled_module->weak_exported_functions();
    1882             :     } else {
    1883             :       weak_exported_functions =
    1884       46033 :           isolate_->factory()->NewFixedArray(export_index);
    1885             :       compiled_module->set_weak_exported_functions(weak_exported_functions);
    1886             :     }
    1887             :     DCHECK_EQ(export_index, weak_exported_functions->length());
    1888             : 
    1889             :     // Process each export in the export table (go in reverse so asm.js
    1890             :     // can skip duplicates).
    1891      257086 :     for (auto exp : base::Reversed(module_->export_table)) {
    1892             :       Handle<String> name =
    1893             :           WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    1894             :               isolate_, compiled_module_, exp.name_offset, exp.name_length)
    1895      162528 :               .ToHandleChecked();
    1896             :       Handle<JSObject> export_to;
    1897      261276 :       if (module_->is_asm_js() && exp.kind == kExternalFunction &&
    1898       29178 :           (String::Equals(name, foreign_init_name) ||
    1899       11694 :            String::Equals(name, single_function_name))) {
    1900             :         export_to = instance;
    1901             :       } else {
    1902             :         export_to = exports_object;
    1903             :       }
    1904             : 
    1905       81264 :       switch (exp.kind) {
    1906             :         case kExternalFunction: {
    1907             :           // Wrap and export the code as a JSFunction.
    1908       79790 :           WasmFunction& function = module_->functions[exp.index];
    1909             :           int func_index =
    1910       79790 :               static_cast<int>(module_->functions.size() + --export_index);
    1911       79790 :           Handle<JSFunction> js_function = js_wrappers_[exp.index];
    1912       79790 :           if (js_function.is_null()) {
    1913             :             // Wrap the exported code as a JSFunction.
    1914             :             Handle<Code> export_code =
    1915      159202 :                 code_table->GetValueChecked<Code>(isolate_, func_index);
    1916             :             MaybeHandle<String> func_name;
    1917      159202 :             if (module_->is_asm_js()) {
    1918             :               // For modules arising from asm.js, honor the names section.
    1919             :               func_name = WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    1920             :                               isolate_, compiled_module_, function.name_offset,
    1921             :                               function.name_length)
    1922       34938 :                               .ToHandleChecked();
    1923             :             }
    1924             :             js_function = WasmExportedFunction::New(
    1925             :                 isolate_, instance, func_name, function.func_index,
    1926       79601 :                 static_cast<int>(function.sig->parameter_count()), export_code);
    1927       79601 :             js_wrappers_[exp.index] = js_function;
    1928             :           }
    1929             :           desc.set_value(js_function);
    1930             :           Handle<WeakCell> weak_export =
    1931       79790 :               isolate_->factory()->NewWeakCell(js_function);
    1932             :           DCHECK_GT(weak_exported_functions->length(), export_index);
    1933       79790 :           weak_exported_functions->set(export_index, *weak_export);
    1934             :           break;
    1935             :         }
    1936             :         case kExternalTable: {
    1937             :           // Export a table as a WebAssembly.Table object.
    1938         337 :           TableInstance& table_instance = table_instances_[exp.index];
    1939             :           WasmIndirectFunctionTable& table =
    1940         337 :               module_->function_tables[exp.index];
    1941         337 :           if (table_instance.table_object.is_null()) {
    1942             :             uint32_t maximum =
    1943         337 :                 table.has_max ? table.max_size : FLAG_wasm_max_table_size;
    1944             :             table_instance.table_object = WasmTableObject::New(
    1945         337 :                 isolate_, table.min_size, maximum, &table_instance.js_wrappers);
    1946             :           }
    1947             :           desc.set_value(table_instance.table_object);
    1948         337 :           break;
    1949             :         }
    1950             :         case kExternalMemory: {
    1951             :           // Export the memory as a WebAssembly.Memory object.
    1952             :           Handle<WasmMemoryObject> memory_object;
    1953        1025 :           if (!instance->has_memory_object()) {
    1954             :             // If there was no imported WebAssembly.Memory object, create one.
    1955             :             memory_object = WasmMemoryObject::New(
    1956             :                 isolate_,
    1957         812 :                 (instance->has_memory_buffer())
    1958         797 :                     ? handle(instance->memory_buffer())
    1959             :                     : Handle<JSArrayBuffer>::null(),
    1960        2436 :                 (module_->max_mem_pages != 0) ? module_->max_mem_pages : -1);
    1961         812 :             instance->set_memory_object(*memory_object);
    1962             :           } else {
    1963             :             memory_object =
    1964         426 :                 Handle<WasmMemoryObject>(instance->memory_object(), isolate_);
    1965             :             DCHECK(WasmJs::IsWasmMemoryObject(isolate_, memory_object));
    1966         426 :             memory_object->ResetInstancesLink(isolate_);
    1967             :           }
    1968             : 
    1969             :           desc.set_value(memory_object);
    1970             :           break;
    1971             :         }
    1972             :         case kExternalGlobal: {
    1973             :           // Export the value of the global variable as a number.
    1974         208 :           WasmGlobal& global = module_->globals[exp.index];
    1975             :           double num = 0;
    1976         112 :           switch (global.type) {
    1977             :             case kWasmI32:
    1978          34 :               num = *GetRawGlobalPtr<int32_t>(global);
    1979          34 :               break;
    1980             :             case kWasmF32:
    1981          31 :               num = *GetRawGlobalPtr<float>(global);
    1982          31 :               break;
    1983             :             case kWasmF64:
    1984          31 :               num = *GetRawGlobalPtr<double>(global);
    1985          31 :               break;
    1986             :             case kWasmI64:
    1987             :               thrower_->LinkError(
    1988          16 :                   "export of globals of type I64 is not allowed.");
    1989          16 :               break;
    1990             :             default:
    1991           0 :               UNREACHABLE();
    1992             :           }
    1993         112 :           desc.set_value(isolate_->factory()->NewNumber(num));
    1994             :           break;
    1995             :         }
    1996             :         default:
    1997           0 :           UNREACHABLE();
    1998             :           break;
    1999             :       }
    2000             : 
    2001             :       // Skip duplicates for asm.js.
    2002      162528 :       if (module_->is_asm_js()) {
    2003       17484 :         v8::Maybe<bool> status = JSReceiver::HasOwnProperty(export_to, name);
    2004       17484 :         if (status.FromMaybe(false)) {
    2005           7 :           continue;
    2006             :         }
    2007             :       }
    2008             :       v8::Maybe<bool> status = JSReceiver::DefineOwnProperty(
    2009       81257 :           isolate_, export_to, name, &desc, Object::THROW_ON_ERROR);
    2010       81257 :       if (!status.IsJust()) {
    2011             :         thrower_->LinkError("export of %.*s failed.", name->length(),
    2012           0 :                             name->ToCString().get());
    2013       47279 :         return;
    2014             :       }
    2015             :     }
    2016             : 
    2017       94558 :     if (module_->is_wasm()) {
    2018             :       v8::Maybe<bool> success = JSReceiver::SetIntegrityLevel(
    2019       40799 :           exports_object, FROZEN, Object::DONT_THROW);
    2020             :       DCHECK(success.FromMaybe(false));
    2021             :       USE(success);
    2022             :     }
    2023             :   }
    2024             : 
    2025        1468 :   void InitializeTables(Handle<WasmInstanceObject> instance,
    2026             :                         CodeSpecialization* code_specialization) {
    2027             :     int function_table_count =
    2028        4404 :         static_cast<int>(module_->function_tables.size());
    2029             :     Handle<FixedArray> new_function_tables =
    2030        1468 :         isolate_->factory()->NewFixedArray(function_table_count);
    2031             :     Handle<FixedArray> new_signature_tables =
    2032        1468 :         isolate_->factory()->NewFixedArray(function_table_count);
    2033        2936 :     for (int index = 0; index < function_table_count; ++index) {
    2034        1468 :       WasmIndirectFunctionTable& table = module_->function_tables[index];
    2035        1468 :       TableInstance& table_instance = table_instances_[index];
    2036        1468 :       int table_size = static_cast<int>(table.min_size);
    2037             : 
    2038        1468 :       if (table_instance.function_table.is_null()) {
    2039             :         // Create a new dispatch table if necessary.
    2040             :         table_instance.function_table =
    2041         838 :             isolate_->factory()->NewFixedArray(table_size);
    2042             :         table_instance.signature_table =
    2043         838 :             isolate_->factory()->NewFixedArray(table_size);
    2044       11160 :         for (int i = 0; i < table_size; ++i) {
    2045             :           // Fill the table with invalid signature indexes so that
    2046             :           // uninitialized entries will always fail the signature check.
    2047             :           table_instance.signature_table->set(i,
    2048             :                                               Smi::FromInt(kInvalidSigIndex));
    2049             :         }
    2050             :       } else {
    2051             :         // Table is imported, patch table bounds check
    2052             :         DCHECK(table_size <= table_instance.function_table->length());
    2053         630 :         if (table_size < table_instance.function_table->length()) {
    2054             :           code_specialization->PatchTableSize(
    2055          45 :               table_size, table_instance.function_table->length());
    2056             :         }
    2057             :       }
    2058             : 
    2059             :       new_function_tables->set(static_cast<int>(index),
    2060        1468 :                                *table_instance.function_table);
    2061             :       new_signature_tables->set(static_cast<int>(index),
    2062        1468 :                                 *table_instance.signature_table);
    2063             :     }
    2064             : 
    2065             :     FixedArray* old_function_tables =
    2066             :         compiled_module_->ptr_to_function_tables();
    2067             :     DCHECK_EQ(old_function_tables->length(), new_function_tables->length());
    2068        2936 :     for (int i = 0, e = new_function_tables->length(); i < e; ++i) {
    2069             :       code_specialization->RelocateObject(
    2070             :           handle(old_function_tables->get(i), isolate_),
    2071        4404 :           handle(new_function_tables->get(i), isolate_));
    2072             :     }
    2073             :     FixedArray* old_signature_tables =
    2074             :         compiled_module_->ptr_to_signature_tables();
    2075             :     DCHECK_EQ(old_signature_tables->length(), new_signature_tables->length());
    2076        2936 :     for (int i = 0, e = new_signature_tables->length(); i < e; ++i) {
    2077             :       code_specialization->RelocateObject(
    2078             :           handle(old_signature_tables->get(i), isolate_),
    2079        4404 :           handle(new_signature_tables->get(i), isolate_));
    2080             :     }
    2081             : 
    2082             :     compiled_module_->set_function_tables(new_function_tables);
    2083             :     compiled_module_->set_signature_tables(new_signature_tables);
    2084        1468 :   }
    2085             : 
    2086        1468 :   void LoadTableSegments(Handle<FixedArray> code_table,
    2087             :                          Handle<WasmInstanceObject> instance) {
    2088             :     int function_table_count =
    2089        5621 :         static_cast<int>(module_->function_tables.size());
    2090        2936 :     for (int index = 0; index < function_table_count; ++index) {
    2091        1468 :       WasmIndirectFunctionTable& table = module_->function_tables[index];
    2092        1468 :       TableInstance& table_instance = table_instances_[index];
    2093             : 
    2094             :       Handle<FixedArray> all_dispatch_tables;
    2095        1468 :       if (!table_instance.table_object.is_null()) {
    2096             :         // Get the existing dispatch table(s) with the WebAssembly.Table object.
    2097             :         all_dispatch_tables = WasmTableObject::AddDispatchTable(
    2098             :             isolate_, table_instance.table_object,
    2099             :             Handle<WasmInstanceObject>::null(), index,
    2100         967 :             Handle<FixedArray>::null(), Handle<FixedArray>::null());
    2101             :       }
    2102             : 
    2103             :       // Count the number of table exports for each function (needed for lazy
    2104             :       // compilation).
    2105        1468 :       std::unordered_map<uint32_t, uint32_t> num_table_exports;
    2106        2936 :       if (compile_lazy(module_)) {
    2107         450 :         for (auto table_init : module_->table_inits) {
    2108        6705 :           for (uint32_t func_index : table_init.entries) {
    2109             :             Code* code =
    2110        6405 :                 Code::cast(code_table->get(static_cast<int>(func_index)));
    2111             :             // Only increase the counter for lazy compile builtins (it's not
    2112             :             // needed otherwise).
    2113        6405 :             if (code->is_wasm_code()) continue;
    2114             :             DCHECK_EQ(Builtins::kWasmCompileLazy, code->builtin_index());
    2115        5942 :             ++num_table_exports[func_index];
    2116             :           }
    2117             :         }
    2118             :       }
    2119             : 
    2120             :       // TODO(titzer): this does redundant work if there are multiple tables,
    2121             :       // since initializations are not sorted by table index.
    2122        5522 :       for (auto table_init : module_->table_inits) {
    2123        1118 :         uint32_t base = EvalUint32InitExpr(table_init.offset);
    2124             :         DCHECK(in_bounds(base, static_cast<uint32_t>(table_init.entries.size()),
    2125             :                          table_instance.function_table->length()));
    2126       10846 :         for (int i = 0, e = static_cast<int>(table_init.entries.size()); i < e;
    2127             :              ++i) {
    2128       17220 :           uint32_t func_index = table_init.entries[i];
    2129        8610 :           WasmFunction* function = &module_->functions[func_index];
    2130        8610 :           int table_index = static_cast<int>(i + base);
    2131        9827 :           int32_t sig_index = table.map.Find(function->sig);
    2132             :           DCHECK_GE(sig_index, 0);
    2133             :           table_instance.signature_table->set(table_index,
    2134             :                                               Smi::FromInt(sig_index));
    2135             :           Handle<Code> wasm_code = EnsureTableExportLazyDeoptData(
    2136             :               isolate_, instance, code_table, func_index,
    2137        8610 :               table_instance.function_table, table_index, num_table_exports);
    2138        8610 :           table_instance.function_table->set(table_index, *wasm_code);
    2139             : 
    2140        8610 :           if (!all_dispatch_tables.is_null()) {
    2141        5093 :             if (js_wrappers_[func_index].is_null()) {
    2142             :               // No JSFunction entry yet exists for this function. Create one.
    2143             :               // TODO(titzer): We compile JS->WASM wrappers for functions are
    2144             :               // not exported but are in an exported table. This should be done
    2145             :               // at module compile time and cached instead.
    2146             : 
    2147             :               Handle<Code> wrapper_code =
    2148             :                   js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper(
    2149        1217 :                       isolate_, module_, wasm_code, func_index);
    2150             :               MaybeHandle<String> func_name;
    2151        2434 :               if (module_->is_asm_js()) {
    2152             :                 // For modules arising from asm.js, honor the names section.
    2153             :                 func_name =
    2154             :                     WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    2155             :                         isolate_, compiled_module_, function->name_offset,
    2156             :                         function->name_length)
    2157           0 :                         .ToHandleChecked();
    2158             :               }
    2159             :               Handle<WasmExportedFunction> js_function =
    2160             :                   WasmExportedFunction::New(
    2161             :                       isolate_, instance, func_name, func_index,
    2162        1217 :                       static_cast<int>(function->sig->parameter_count()),
    2163        1217 :                       wrapper_code);
    2164        1217 :               js_wrappers_[func_index] = js_function;
    2165             :             }
    2166             :             table_instance.js_wrappers->set(table_index,
    2167        1292 :                                             *js_wrappers_[func_index]);
    2168             : 
    2169             :             UpdateDispatchTablesInternal(isolate_, all_dispatch_tables,
    2170        1292 :                                          table_index, function, wasm_code);
    2171             :           }
    2172             :         }
    2173             :       }
    2174             : 
    2175             : #ifdef DEBUG
    2176             :       // Check that the count of table exports was accurate. The entries are
    2177             :       // decremented on each export, so all should be zero now.
    2178             :       for (auto e : num_table_exports) {
    2179             :         DCHECK_EQ(0, e.second);
    2180             :       }
    2181             : #endif
    2182             : 
    2183             :       // TODO(titzer): we add the new dispatch table at the end to avoid
    2184             :       // redundant work and also because the new instance is not yet fully
    2185             :       // initialized.
    2186        1468 :       if (!table_instance.table_object.is_null()) {
    2187             :         // Add the new dispatch table to the WebAssembly.Table object.
    2188             :         all_dispatch_tables = WasmTableObject::AddDispatchTable(
    2189             :             isolate_, table_instance.table_object, instance, index,
    2190         967 :             table_instance.function_table, table_instance.signature_table);
    2191             :       }
    2192             :     }
    2193        1468 :   }
    2194             : };
    2195             : 
    2196           0 : bool wasm::IsWasmInstance(Object* object) {
    2197          60 :   return WasmInstanceObject::IsWasmInstanceObject(object);
    2198             : }
    2199             : 
    2200        1806 : Handle<Script> wasm::GetScript(Handle<JSObject> instance) {
    2201             :   WasmCompiledModule* compiled_module =
    2202        1806 :       WasmInstanceObject::cast(*instance)->compiled_module();
    2203        3612 :   return handle(compiled_module->script());
    2204             : }
    2205             : 
    2206       12373 : bool wasm::IsWasmCodegenAllowed(Isolate* isolate, Handle<Context> context) {
    2207       12394 :   return isolate->allow_code_gen_callback() == nullptr ||
    2208         195 :          isolate->allow_code_gen_callback()(v8::Utils::ToLocal(context));
    2209             : }
    2210             : 
    2211         756 : void wasm::DetachWebAssemblyMemoryBuffer(Isolate* isolate,
    2212             :                                          Handle<JSArrayBuffer> buffer) {
    2213             :   int64_t byte_length =
    2214             :       buffer->byte_length()->IsNumber()
    2215             :           ? static_cast<uint32_t>(buffer->byte_length()->Number())
    2216         840 :           : 0;
    2217         840 :   if (buffer.is_null() || byte_length == 0) return;
    2218             :   const bool has_guard_regions = buffer->has_guard_region();
    2219             :   const bool is_external = buffer->is_external();
    2220             :   void* backing_store = buffer->backing_store();
    2221             :   DCHECK(!buffer->is_neuterable());
    2222         360 :   if (!has_guard_regions && !is_external) {
    2223             :     buffer->set_is_external(true);
    2224         336 :     isolate->heap()->UnregisterArrayBuffer(*buffer);
    2225             :   }
    2226             :   buffer->set_is_neuterable(true);
    2227         360 :   buffer->Neuter();
    2228         360 :   if (has_guard_regions) {
    2229             :     base::OS::Free(backing_store, RoundUp(i::wasm::kWasmMaxHeapOffset,
    2230          48 :                                           base::OS::CommitPageSize()));
    2231             :     reinterpret_cast<v8::Isolate*>(isolate)
    2232          24 :         ->AdjustAmountOfExternalAllocatedMemory(-byte_length);
    2233         336 :   } else if (!has_guard_regions && !is_external) {
    2234         336 :     isolate->array_buffer_allocator()->Free(backing_store, byte_length);
    2235             :   }
    2236             : }
    2237             : 
    2238         255 : void wasm::GrowDispatchTables(Isolate* isolate,
    2239             :                               Handle<FixedArray> dispatch_tables,
    2240             :                               uint32_t old_size, uint32_t count) {
    2241             :   DCHECK_EQ(0, dispatch_tables->length() % 4);
    2242             : 
    2243         255 :   Zone specialization_zone(isolate->allocator(), ZONE_NAME);
    2244        1020 :   for (int i = 0; i < dispatch_tables->length(); i += 4) {
    2245             :     Handle<FixedArray> old_function_table(
    2246         255 :         FixedArray::cast(dispatch_tables->get(i + 2)));
    2247             :     Handle<FixedArray> old_signature_table(
    2248         255 :         FixedArray::cast(dispatch_tables->get(i + 3)));
    2249             :     Handle<FixedArray> new_function_table =
    2250         255 :         isolate->factory()->CopyFixedArrayAndGrow(old_function_table, count);
    2251             :     Handle<FixedArray> new_signature_table =
    2252         255 :         isolate->factory()->CopyFixedArrayAndGrow(old_signature_table, count);
    2253             : 
    2254             :     // Update dispatch tables with new function/signature tables
    2255         255 :     dispatch_tables->set(i + 2, *new_function_table);
    2256         255 :     dispatch_tables->set(i + 3, *new_signature_table);
    2257             : 
    2258             :     // Patch the code of the respective instance.
    2259         255 :     CodeSpecialization code_specialization(isolate, &specialization_zone);
    2260         255 :     code_specialization.PatchTableSize(old_size, old_size + count);
    2261         255 :     code_specialization.RelocateObject(old_function_table, new_function_table);
    2262             :     code_specialization.RelocateObject(old_signature_table,
    2263         255 :                                        new_signature_table);
    2264             :     code_specialization.ApplyToWholeInstance(
    2265         255 :         WasmInstanceObject::cast(dispatch_tables->get(i)));
    2266         510 :   }
    2267         255 : }
    2268             : 
    2269          90 : void testing::ValidateInstancesChain(Isolate* isolate,
    2270             :                                      Handle<WasmModuleObject> module_obj,
    2271             :                                      int instance_count) {
    2272          90 :   CHECK_GE(instance_count, 0);
    2273             :   DisallowHeapAllocation no_gc;
    2274          90 :   WasmCompiledModule* compiled_module = module_obj->compiled_module();
    2275          90 :   CHECK_EQ(JSObject::cast(compiled_module->ptr_to_weak_wasm_module()->value()),
    2276             :            *module_obj);
    2277             :   Object* prev = nullptr;
    2278          90 :   int found_instances = compiled_module->has_weak_owning_instance() ? 1 : 0;
    2279             :   WasmCompiledModule* current_instance = compiled_module;
    2280         240 :   while (current_instance->has_weak_next_instance()) {
    2281          75 :     CHECK((prev == nullptr && !current_instance->has_weak_prev_instance()) ||
    2282             :           current_instance->ptr_to_weak_prev_instance()->value() == prev);
    2283          60 :     CHECK_EQ(current_instance->ptr_to_weak_wasm_module()->value(), *module_obj);
    2284          60 :     CHECK(IsWasmInstance(
    2285             :         current_instance->ptr_to_weak_owning_instance()->value()));
    2286             :     prev = current_instance;
    2287             :     current_instance = WasmCompiledModule::cast(
    2288             :         current_instance->ptr_to_weak_next_instance()->value());
    2289          60 :     ++found_instances;
    2290          60 :     CHECK_LE(found_instances, instance_count);
    2291             :   }
    2292          90 :   CHECK_EQ(found_instances, instance_count);
    2293          90 : }
    2294             : 
    2295          30 : void testing::ValidateModuleState(Isolate* isolate,
    2296             :                                   Handle<WasmModuleObject> module_obj) {
    2297             :   DisallowHeapAllocation no_gc;
    2298          30 :   WasmCompiledModule* compiled_module = module_obj->compiled_module();
    2299          30 :   CHECK(compiled_module->has_weak_wasm_module());
    2300          30 :   CHECK_EQ(compiled_module->ptr_to_weak_wasm_module()->value(), *module_obj);
    2301          30 :   CHECK(!compiled_module->has_weak_prev_instance());
    2302          30 :   CHECK(!compiled_module->has_weak_next_instance());
    2303          30 :   CHECK(!compiled_module->has_weak_owning_instance());
    2304          30 : }
    2305             : 
    2306          15 : void testing::ValidateOrphanedInstance(Isolate* isolate,
    2307             :                                        Handle<WasmInstanceObject> instance) {
    2308             :   DisallowHeapAllocation no_gc;
    2309          15 :   WasmCompiledModule* compiled_module = instance->compiled_module();
    2310          15 :   CHECK(compiled_module->has_weak_wasm_module());
    2311          15 :   CHECK(compiled_module->ptr_to_weak_wasm_module()->cleared());
    2312          15 : }
    2313             : 
    2314          60 : Handle<JSArray> wasm::GetImports(Isolate* isolate,
    2315             :                                  Handle<WasmModuleObject> module_object) {
    2316             :   Handle<WasmCompiledModule> compiled_module(module_object->compiled_module(),
    2317          60 :                                              isolate);
    2318             :   Factory* factory = isolate->factory();
    2319             : 
    2320          60 :   Handle<String> module_string = factory->InternalizeUtf8String("module");
    2321          60 :   Handle<String> name_string = factory->InternalizeUtf8String("name");
    2322          60 :   Handle<String> kind_string = factory->InternalizeUtf8String("kind");
    2323             : 
    2324          60 :   Handle<String> function_string = factory->InternalizeUtf8String("function");
    2325          60 :   Handle<String> table_string = factory->InternalizeUtf8String("table");
    2326          60 :   Handle<String> memory_string = factory->InternalizeUtf8String("memory");
    2327          60 :   Handle<String> global_string = factory->InternalizeUtf8String("global");
    2328             : 
    2329             :   // Create the result array.
    2330          60 :   WasmModule* module = compiled_module->module();
    2331         240 :   int num_imports = static_cast<int>(module->import_table.size());
    2332          60 :   Handle<JSArray> array_object = factory->NewJSArray(FAST_ELEMENTS, 0, 0);
    2333          60 :   Handle<FixedArray> storage = factory->NewFixedArray(num_imports);
    2334          60 :   JSArray::SetContent(array_object, storage);
    2335             :   array_object->set_length(Smi::FromInt(num_imports));
    2336             : 
    2337             :   Handle<JSFunction> object_function =
    2338         120 :       Handle<JSFunction>(isolate->native_context()->object_function(), isolate);
    2339             : 
    2340             :   // Populate the result array.
    2341         180 :   for (int index = 0; index < num_imports; ++index) {
    2342         120 :     WasmImport& import = module->import_table[index];
    2343             : 
    2344         120 :     Handle<JSObject> entry = factory->NewJSObject(object_function);
    2345             : 
    2346             :     Handle<String> import_kind;
    2347         120 :     switch (import.kind) {
    2348             :       case kExternalFunction:
    2349          30 :         import_kind = function_string;
    2350          30 :         break;
    2351             :       case kExternalTable:
    2352          30 :         import_kind = table_string;
    2353          30 :         break;
    2354             :       case kExternalMemory:
    2355          30 :         import_kind = memory_string;
    2356          30 :         break;
    2357             :       case kExternalGlobal:
    2358          30 :         import_kind = global_string;
    2359          30 :         break;
    2360             :       default:
    2361           0 :         UNREACHABLE();
    2362             :     }
    2363             : 
    2364             :     MaybeHandle<String> import_module =
    2365             :         WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    2366             :             isolate, compiled_module, import.module_name_offset,
    2367         120 :             import.module_name_length);
    2368             : 
    2369             :     MaybeHandle<String> import_name =
    2370             :         WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    2371             :             isolate, compiled_module, import.field_name_offset,
    2372         120 :             import.field_name_length);
    2373             : 
    2374             :     JSObject::AddProperty(entry, module_string, import_module.ToHandleChecked(),
    2375         120 :                           NONE);
    2376             :     JSObject::AddProperty(entry, name_string, import_name.ToHandleChecked(),
    2377         120 :                           NONE);
    2378         120 :     JSObject::AddProperty(entry, kind_string, import_kind, NONE);
    2379             : 
    2380         120 :     storage->set(index, *entry);
    2381             :   }
    2382             : 
    2383          60 :   return array_object;
    2384             : }
    2385             : 
    2386          60 : Handle<JSArray> wasm::GetExports(Isolate* isolate,
    2387             :                                  Handle<WasmModuleObject> module_object) {
    2388             :   Handle<WasmCompiledModule> compiled_module(module_object->compiled_module(),
    2389          60 :                                              isolate);
    2390             :   Factory* factory = isolate->factory();
    2391             : 
    2392          60 :   Handle<String> name_string = factory->InternalizeUtf8String("name");
    2393          60 :   Handle<String> kind_string = factory->InternalizeUtf8String("kind");
    2394             : 
    2395          60 :   Handle<String> function_string = factory->InternalizeUtf8String("function");
    2396          60 :   Handle<String> table_string = factory->InternalizeUtf8String("table");
    2397          60 :   Handle<String> memory_string = factory->InternalizeUtf8String("memory");
    2398          60 :   Handle<String> global_string = factory->InternalizeUtf8String("global");
    2399             : 
    2400             :   // Create the result array.
    2401          60 :   WasmModule* module = compiled_module->module();
    2402         240 :   int num_exports = static_cast<int>(module->export_table.size());
    2403          60 :   Handle<JSArray> array_object = factory->NewJSArray(FAST_ELEMENTS, 0, 0);
    2404          60 :   Handle<FixedArray> storage = factory->NewFixedArray(num_exports);
    2405          60 :   JSArray::SetContent(array_object, storage);
    2406             :   array_object->set_length(Smi::FromInt(num_exports));
    2407             : 
    2408             :   Handle<JSFunction> object_function =
    2409         120 :       Handle<JSFunction>(isolate->native_context()->object_function(), isolate);
    2410             : 
    2411             :   // Populate the result array.
    2412         180 :   for (int index = 0; index < num_exports; ++index) {
    2413         120 :     WasmExport& exp = module->export_table[index];
    2414             : 
    2415             :     Handle<String> export_kind;
    2416         120 :     switch (exp.kind) {
    2417             :       case kExternalFunction:
    2418          30 :         export_kind = function_string;
    2419          30 :         break;
    2420             :       case kExternalTable:
    2421          30 :         export_kind = table_string;
    2422          30 :         break;
    2423             :       case kExternalMemory:
    2424          30 :         export_kind = memory_string;
    2425          30 :         break;
    2426             :       case kExternalGlobal:
    2427          30 :         export_kind = global_string;
    2428          30 :         break;
    2429             :       default:
    2430           0 :         UNREACHABLE();
    2431             :     }
    2432             : 
    2433         120 :     Handle<JSObject> entry = factory->NewJSObject(object_function);
    2434             : 
    2435             :     MaybeHandle<String> export_name =
    2436             :         WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    2437         120 :             isolate, compiled_module, exp.name_offset, exp.name_length);
    2438             : 
    2439             :     JSObject::AddProperty(entry, name_string, export_name.ToHandleChecked(),
    2440         120 :                           NONE);
    2441         120 :     JSObject::AddProperty(entry, kind_string, export_kind, NONE);
    2442             : 
    2443         120 :     storage->set(index, *entry);
    2444             :   }
    2445             : 
    2446          60 :   return array_object;
    2447             : }
    2448             : 
    2449          60 : Handle<JSArray> wasm::GetCustomSections(Isolate* isolate,
    2450             :                                         Handle<WasmModuleObject> module_object,
    2451             :                                         Handle<String> name,
    2452             :                                         ErrorThrower* thrower) {
    2453             :   Handle<WasmCompiledModule> compiled_module(module_object->compiled_module(),
    2454          60 :                                              isolate);
    2455             :   Factory* factory = isolate->factory();
    2456             : 
    2457             :   std::vector<CustomSectionOffset> custom_sections;
    2458             :   {
    2459             :     DisallowHeapAllocation no_gc;  // for raw access to string bytes.
    2460             :     Handle<SeqOneByteString> module_bytes(compiled_module->module_bytes(),
    2461          60 :                                           isolate);
    2462             :     const byte* start =
    2463          60 :         reinterpret_cast<const byte*>(module_bytes->GetCharsAddress());
    2464          60 :     const byte* end = start + module_bytes->length();
    2465         120 :     custom_sections = DecodeCustomSections(start, end);
    2466             :   }
    2467             : 
    2468             :   std::vector<Handle<Object>> matching_sections;
    2469             : 
    2470             :   // Gather matching sections.
    2471         300 :   for (auto section : custom_sections) {
    2472             :     MaybeHandle<String> section_name =
    2473             :         WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    2474         180 :             isolate, compiled_module, section.name_offset, section.name_length);
    2475             : 
    2476         180 :     if (!name->Equals(*section_name.ToHandleChecked())) continue;
    2477             : 
    2478             :     // Make a copy of the payload data in the section.
    2479             :     bool is_external;  // Set by TryAllocateBackingStore
    2480             :     void* memory = TryAllocateBackingStore(isolate, section.payload_length,
    2481          45 :                                            false, is_external);
    2482             : 
    2483             :     Handle<Object> section_data = factory->undefined_value();
    2484          45 :     if (memory) {
    2485          45 :       Handle<JSArrayBuffer> buffer = isolate->factory()->NewJSArrayBuffer();
    2486             :       JSArrayBuffer::Setup(buffer, isolate, is_external, memory,
    2487          45 :                            static_cast<int>(section.payload_length));
    2488             :       DisallowHeapAllocation no_gc;  // for raw access to string bytes.
    2489             :       Handle<SeqOneByteString> module_bytes(compiled_module->module_bytes(),
    2490          45 :                                             isolate);
    2491             :       const byte* start =
    2492          45 :           reinterpret_cast<const byte*>(module_bytes->GetCharsAddress());
    2493          45 :       memcpy(memory, start + section.payload_offset, section.payload_length);
    2494          45 :       section_data = buffer;
    2495             :     } else {
    2496           0 :       thrower->RangeError("out of memory allocating custom section data");
    2497           0 :       return Handle<JSArray>();
    2498             :     }
    2499             : 
    2500          45 :     matching_sections.push_back(section_data);
    2501             :   }
    2502             : 
    2503         120 :   int num_custom_sections = static_cast<int>(matching_sections.size());
    2504          60 :   Handle<JSArray> array_object = factory->NewJSArray(FAST_ELEMENTS, 0, 0);
    2505          60 :   Handle<FixedArray> storage = factory->NewFixedArray(num_custom_sections);
    2506          60 :   JSArray::SetContent(array_object, storage);
    2507             :   array_object->set_length(Smi::FromInt(num_custom_sections));
    2508             : 
    2509         105 :   for (int i = 0; i < num_custom_sections; i++) {
    2510          90 :     storage->set(i, *matching_sections[i]);
    2511             :   }
    2512             : 
    2513          60 :   return array_object;
    2514             : }
    2515             : 
    2516        1110 : bool wasm::SyncValidate(Isolate* isolate, ErrorThrower* thrower,
    2517             :                         const ModuleWireBytes& bytes) {
    2518        2220 :   if (bytes.start() == nullptr || bytes.length() == 0) return false;
    2519             :   ModuleResult result =
    2520        2220 :       DecodeWasmModule(isolate, bytes.start(), bytes.end(), true, kWasmOrigin);
    2521        1110 :   if (result.val) delete result.val;
    2522             :   return result.ok();
    2523             : }
    2524             : 
    2525        3609 : MaybeHandle<WasmModuleObject> wasm::SyncCompileTranslatedAsmJs(
    2526             :     Isolate* isolate, ErrorThrower* thrower, const ModuleWireBytes& bytes,
    2527             :     Handle<Script> asm_js_script,
    2528        3609 :     Vector<const byte> asm_js_offset_table_bytes) {
    2529             : 
    2530             :   ModuleResult result = DecodeWasmModule(isolate, bytes.start(), bytes.end(),
    2531        7218 :                                          false, kAsmJsOrigin);
    2532        3609 :   if (result.failed()) {
    2533             :     // TODO(titzer): use Result<std::unique_ptr<const WasmModule*>>?
    2534           0 :     if (result.val) delete result.val;
    2535             :     thrower->CompileFailed("Wasm decoding failed", result);
    2536             :     return {};
    2537             :   }
    2538             : 
    2539        7218 :   CompilationHelper helper(isolate, const_cast<WasmModule*>(result.val));
    2540             :   return helper.CompileToModuleObject(thrower, bytes, asm_js_script,
    2541        3609 :                                       asm_js_offset_table_bytes);
    2542             : }
    2543             : 
    2544       12199 : MaybeHandle<WasmModuleObject> wasm::SyncCompile(Isolate* isolate,
    2545             :                                                 ErrorThrower* thrower,
    2546             :                                                 const ModuleWireBytes& bytes) {
    2547       24398 :   if (!IsWasmCodegenAllowed(isolate, isolate->native_context())) {
    2548          14 :     thrower->CompileError("Wasm code generation disallowed in this context");
    2549             :     return {};
    2550             :   }
    2551             : 
    2552             :   ModuleResult result =
    2553       24370 :       DecodeWasmModule(isolate, bytes.start(), bytes.end(), false, kWasmOrigin);
    2554       12185 :   if (result.failed()) {
    2555         450 :     if (result.val) delete result.val;
    2556             :     thrower->CompileFailed("Wasm decoding failed", result);
    2557             :     return {};
    2558             :   }
    2559             : 
    2560       23470 :   CompilationHelper helper(isolate, const_cast<WasmModule*>(result.val));
    2561             :   return helper.CompileToModuleObject(thrower, bytes, Handle<Script>(),
    2562       11735 :                                       Vector<const byte>());
    2563             : }
    2564             : 
    2565       48092 : MaybeHandle<WasmInstanceObject> wasm::SyncInstantiate(
    2566             :     Isolate* isolate, ErrorThrower* thrower,
    2567             :     Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports,
    2568             :     MaybeHandle<JSArrayBuffer> memory) {
    2569       48092 :   InstantiationHelper helper(isolate, thrower, module_object, imports, memory);
    2570       48092 :   return helper.Build();
    2571             : }
    2572             : 
    2573             : namespace {
    2574             : 
    2575          15 : void RejectPromise(Isolate* isolate, Handle<Context> context,
    2576             :                    ErrorThrower* thrower, Handle<JSPromise> promise) {
    2577             :   v8::Local<v8::Promise::Resolver> resolver =
    2578             :       v8::Utils::PromiseToLocal(promise).As<v8::Promise::Resolver>();
    2579             :   auto maybe = resolver->Reject(v8::Utils::ToLocal(context),
    2580          15 :                    v8::Utils::ToLocal(thrower->Reify()));
    2581          15 :   CHECK_IMPLIES(!maybe.FromMaybe(false), isolate->has_scheduled_exception());
    2582          15 : }
    2583             : 
    2584         750 : void ResolvePromise(Isolate* isolate, Handle<Context> context,
    2585             :                     Handle<JSPromise> promise, Handle<Object> result) {
    2586             :   v8::Local<v8::Promise::Resolver> resolver =
    2587             :       v8::Utils::PromiseToLocal(promise).As<v8::Promise::Resolver>();
    2588             :   auto maybe = resolver->Resolve(v8::Utils::ToLocal(context),
    2589         750 :                                  v8::Utils::ToLocal(result));
    2590         750 :   CHECK_IMPLIES(!maybe.FromMaybe(false), isolate->has_scheduled_exception());
    2591         750 : }
    2592             : 
    2593             : }  // namespace
    2594             : 
    2595           0 : void wasm::AsyncInstantiate(Isolate* isolate, Handle<JSPromise> promise,
    2596             :                             Handle<WasmModuleObject> module_object,
    2597             :                             MaybeHandle<JSReceiver> imports) {
    2598             :   ErrorThrower thrower(isolate, nullptr);
    2599             :   MaybeHandle<WasmInstanceObject> instance_object = SyncInstantiate(
    2600           0 :       isolate, &thrower, module_object, imports, Handle<JSArrayBuffer>::null());
    2601           0 :   if (thrower.error()) {
    2602           0 :     RejectPromise(isolate, handle(isolate->context()), &thrower, promise);
    2603           0 :     return;
    2604             :   }
    2605             :   ResolvePromise(isolate, handle(isolate->context()), promise,
    2606           0 :                  instance_object.ToHandleChecked());
    2607             : }
    2608             : 
    2609             : // Encapsulates all the state and steps of an asynchronous compilation.
    2610             : // An asynchronous compile job consists of a number of tasks that are executed
    2611             : // as foreground and background tasks. Any phase that touches the V8 heap or
    2612             : // allocates on the V8 heap (e.g. creating the module object) must be a
    2613             : // foreground task. All other tasks (e.g. decoding and validating, the majority
    2614             : // of the work of compilation) can be background tasks.
    2615             : // TODO(wasm): factor out common parts of this with the synchronous pipeline.
    2616             : //
    2617             : // Note: In predictable mode, DoSync and DoAsync execute the referenced function
    2618             : // immediately before returning. Thus we handle the predictable mode specially,
    2619             : // e.g. when we synchronizing tasks or when we delete the AyncCompileJob.
    2620             : class AsyncCompileJob {
    2621             :   // TODO(ahaas): Fix https://bugs.chromium.org/p/v8/issues/detail?id=6263 to
    2622             :   // make sure that d8 does not shut down before the AsyncCompileJob is
    2623             :   // finished.
    2624             :  public:
    2625         765 :   explicit AsyncCompileJob(Isolate* isolate, std::unique_ptr<byte[]> bytes_copy,
    2626             :                            int length, Handle<Context> context,
    2627             :                            Handle<JSPromise> promise)
    2628             :       : isolate_(isolate),
    2629             :         bytes_copy_(std::move(bytes_copy)),
    2630        3825 :         wire_bytes_(bytes_copy_.get(), bytes_copy_.get() + length) {
    2631             :     // The handles for the context and promise must be deferred.
    2632         765 :     DeferredHandleScope deferred(isolate);
    2633         765 :     context_ = Handle<Context>(*context);
    2634         765 :     module_promise_ = Handle<JSPromise>(*promise);
    2635        1530 :     deferred_handles_.push_back(deferred.Detach());
    2636         765 :   }
    2637             : 
    2638             :   bool Start() {
    2639         765 :     return DoAsync(&AsyncCompileJob::DecodeModule);  // --
    2640             :   }
    2641             : 
    2642         765 :   ~AsyncCompileJob() {
    2643        3795 :     for (auto d : deferred_handles_) delete d;
    2644         765 :   }
    2645             : 
    2646             :  private:
    2647             :   Isolate* isolate_;
    2648             :   std::unique_ptr<byte[]> bytes_copy_;
    2649             :   ModuleWireBytes wire_bytes_;
    2650             :   Handle<Context> context_;
    2651             :   Handle<JSPromise> module_promise_;
    2652             :   WasmModule* module_ = nullptr;
    2653             :   ModuleResult result_;
    2654             :   std::unique_ptr<CompilationHelper> helper_ = nullptr;
    2655             :   std::unique_ptr<ModuleBytesEnv> module_bytes_env_ = nullptr;
    2656             : 
    2657             :   volatile bool failed_ = false;
    2658             :   std::vector<DeferredHandles*> deferred_handles_;
    2659             :   Handle<WasmModuleWrapper> module_wrapper_;
    2660             :   Handle<WasmModuleObject> module_object_;
    2661             :   Handle<FixedArray> function_tables_;
    2662             :   Handle<FixedArray> signature_tables_;
    2663             :   Handle<WasmCompiledModule> compiled_module_;
    2664             :   Handle<FixedArray> code_table_;
    2665             :   std::unique_ptr<WasmInstance> temp_instance_ = nullptr;
    2666             :   size_t outstanding_units_ = 0;
    2667             :   size_t num_background_tasks_ = 0;
    2668             : 
    2669         750 :   void ReopenHandlesInDeferredScope() {
    2670         750 :     DeferredHandleScope deferred(isolate_);
    2671        1500 :     module_wrapper_ = handle(*module_wrapper_, isolate_);
    2672        1500 :     function_tables_ = handle(*function_tables_, isolate_);
    2673        1500 :     signature_tables_ = handle(*signature_tables_, isolate_);
    2674        1500 :     code_table_ = handle(*code_table_, isolate_);
    2675        1500 :     temp_instance_->ReopenHandles(isolate_);
    2676             :     helper_->InitializeHandles();
    2677        1500 :     deferred_handles_.push_back(deferred.Detach());
    2678         750 :   }
    2679             : 
    2680             :   //==========================================================================
    2681             :   // Step 1: (async) Decode the module.
    2682             :   //==========================================================================
    2683         765 :   bool DecodeModule() {
    2684             :     {
    2685             :       DisallowHandleAllocation no_handle;
    2686             :       DisallowHeapAllocation no_allocation;
    2687             :       // Decode the module bytes.
    2688         765 :       TRACE_COMPILE("(1) Decoding module...\n");
    2689        1530 :       result_ = DecodeWasmModule(isolate_, wire_bytes_.start(),
    2690             :                                  wire_bytes_.end(), true, kWasmOrigin);
    2691             :     }
    2692         765 :     if (result_.failed()) {
    2693             :       // Decoding failure; reject the promise and clean up.
    2694          15 :       if (result_.val) delete result_.val;
    2695          15 :       return DoSync(&AsyncCompileJob::DecodeFail);
    2696             :     } else {
    2697             :       // Decode passed.
    2698         750 :       module_ = const_cast<WasmModule*>(result_.val);
    2699         750 :       return DoSync(&AsyncCompileJob::PrepareAndStartCompile);
    2700             :     }
    2701             :   }
    2702             : 
    2703             :   //==========================================================================
    2704             :   // Step 1b: (sync) Fail decoding the module.
    2705             :   //==========================================================================
    2706          15 :   bool DecodeFail() {
    2707          15 :     HandleScope scope(isolate_);
    2708          15 :     ErrorThrower thrower(isolate_, nullptr);
    2709             :     thrower.CompileFailed("Wasm decoding failed", result_);
    2710          15 :     RejectPromise(isolate_, context_, &thrower, module_promise_);
    2711          15 :     return false;
    2712             :   }
    2713             : 
    2714             :   //==========================================================================
    2715             :   // Step 2 (sync): Create heap-allocated data and start compile.
    2716             :   //==========================================================================
    2717         750 :   bool PrepareAndStartCompile() {
    2718         750 :     TRACE_COMPILE("(2) Prepare and start compile...\n");
    2719        1500 :     HandleScope scope(isolate_);
    2720             : 
    2721             :     Factory* factory = isolate_->factory();
    2722             :     // The {module_wrapper} will take ownership of the {WasmModule} object,
    2723             :     // and it will be destroyed when the GC reclaims the wrapper object.
    2724         750 :     module_wrapper_ = WasmModuleWrapper::New(isolate_, module_);
    2725         750 :     temp_instance_ = std::unique_ptr<WasmInstance>(new WasmInstance(module_));
    2726         750 :     temp_instance_->context = context_;
    2727         750 :     temp_instance_->mem_size = WasmModule::kPageSize * module_->min_mem_pages;
    2728         750 :     temp_instance_->mem_start = nullptr;
    2729         750 :     temp_instance_->globals_start = nullptr;
    2730             : 
    2731             :     // Initialize the indirect tables with placeholders.
    2732             :     int function_table_count =
    2733        1500 :         static_cast<int>(module_->function_tables.size());
    2734         750 :     function_tables_ = factory->NewFixedArray(function_table_count, TENURED);
    2735         750 :     signature_tables_ = factory->NewFixedArray(function_table_count, TENURED);
    2736         855 :     for (int i = 0; i < function_table_count; ++i) {
    2737         315 :       temp_instance_->function_tables[i] = factory->NewFixedArray(1, TENURED);
    2738         210 :       temp_instance_->signature_tables[i] = factory->NewFixedArray(1, TENURED);
    2739         210 :       function_tables_->set(i, *temp_instance_->function_tables[i]);
    2740         210 :       signature_tables_->set(i, *temp_instance_->signature_tables[i]);
    2741             :     }
    2742             : 
    2743             :     // The {code_table} array contains import wrappers and functions (which
    2744             :     // are both included in {functions.size()}, and export wrappers.
    2745             :     // The results of compilation will be written into it.
    2746        2865 :     int code_table_size = static_cast<int>(module_->functions.size() +
    2747         750 :                                            module_->num_exported_functions);
    2748         750 :     code_table_ = factory->NewFixedArray(code_table_size, TENURED);
    2749             : 
    2750             :     // Initialize {code_table_} with the illegal builtin. All call sites
    2751             :     // will be patched at instantiation.
    2752         750 :     Handle<Code> illegal_builtin = isolate_->builtins()->Illegal();
    2753             :     // TODO(wasm): Fix this for lazy compilation.
    2754        2730 :     for (uint32_t i = 0; i < module_->functions.size(); ++i) {
    2755        1230 :       code_table_->set(static_cast<int>(i), *illegal_builtin);
    2756        1230 :       temp_instance_->function_code[i] = illegal_builtin;
    2757             :     }
    2758             : 
    2759             :     isolate_->counters()->wasm_functions_per_wasm_module()->AddSample(
    2760        1500 :         static_cast<int>(module_->functions.size()));
    2761             : 
    2762         750 :     helper_.reset(new CompilationHelper(isolate_, module_));
    2763             : 
    2764             :     DCHECK_LE(module_->num_imported_functions, module_->functions.size());
    2765             :     size_t num_functions =
    2766        1500 :         module_->functions.size() - module_->num_imported_functions;
    2767         750 :     if (num_functions == 0) {
    2768         540 :       ReopenHandlesInDeferredScope();
    2769             :       // Degenerate case of an empty module.
    2770         540 :       return DoSync(&AsyncCompileJob::FinishCompile);
    2771             :     }
    2772             : 
    2773             :     // Start asynchronous compilation tasks.
    2774             :     num_background_tasks_ =
    2775             :         Max(static_cast<size_t>(1),
    2776             :             Min(num_functions,
    2777             :                 Min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks),
    2778         210 :                     V8::GetCurrentPlatform()
    2779         420 :                         ->NumberOfAvailableBackgroundThreads())));
    2780         210 :     module_bytes_env_ = std::unique_ptr<ModuleBytesEnv>(
    2781         210 :         new ModuleBytesEnv(module_, temp_instance_.get(), wire_bytes_));
    2782             :     outstanding_units_ = helper_->InitializeParallelCompilation(
    2783         420 :         module_->functions, *module_bytes_env_);
    2784             : 
    2785             :     // Reopen all handles which should survive in the DeferredHandleScope.
    2786         210 :     ReopenHandlesInDeferredScope();
    2787         420 :     for (size_t i = 0; i < num_background_tasks_; ++i) {
    2788         210 :       DoAsync(&AsyncCompileJob::ExecuteCompilationUnits);
    2789             :     }
    2790             :     return true;
    2791             :   }
    2792             : 
    2793             :   //==========================================================================
    2794             :   // Step 3 (async x K tasks): Execute compilation units.
    2795             :   //==========================================================================
    2796         210 :   bool ExecuteCompilationUnits() {
    2797         210 :     TRACE_COMPILE("(3) Compiling...\n");
    2798         420 :     while (!failed_) {
    2799             :       {
    2800             :         DisallowHandleAllocation no_handle;
    2801             :         DisallowHeapAllocation no_allocation;
    2802         420 :         if (!helper_->FetchAndExecuteCompilationUnit()) break;
    2803             :       }
    2804             :       // TODO(ahaas): Create one FinishCompilationUnit job for all compilation
    2805             :       // units.
    2806         210 :       DoSync(&AsyncCompileJob::FinishCompilationUnit);
    2807             :       // TODO(ahaas): Limit the number of outstanding compilation units to be
    2808             :       // finished to reduce memory overhead.
    2809             :     }
    2810             :     // Special handling for predictable mode, see above.
    2811             :     if (!FLAG_verify_predictable)
    2812         418 :       helper_->module_->pending_tasks.get()->Signal();
    2813         210 :     return true;
    2814             :   }
    2815             : 
    2816             :   //==========================================================================
    2817             :   // Step 4 (sync x each function): Finish a single compilation unit.
    2818             :   //==========================================================================
    2819         210 :   bool FinishCompilationUnit() {
    2820         210 :     TRACE_COMPILE("(4a) Finishing compilation unit...\n");
    2821         210 :     HandleScope scope(isolate_);
    2822         210 :     if (failed_) return true;  // already failed
    2823             : 
    2824         210 :     int func_index = -1;
    2825         210 :     ErrorThrower thrower(isolate_, nullptr);
    2826         210 :     Handle<Code> result = helper_->FinishCompilationUnit(&thrower, &func_index);
    2827         210 :     if (thrower.error()) {
    2828           0 :       RejectPromise(isolate_, context_, &thrower, module_promise_);
    2829           0 :       failed_ = true;
    2830             :     } else {
    2831             :       DCHECK(func_index >= 0);
    2832         420 :       code_table_->set(func_index, *(result));
    2833             :     }
    2834         210 :     if (failed_ || --outstanding_units_ == 0) {
    2835             :       // All compilation units are done. We still need to wait for the
    2836             :       // background tasks to shut down and only then is it safe to finish the
    2837             :       // compile and delete this job. We can wait for that to happen also
    2838             :       // in a background task.
    2839         210 :       DoAsync(&AsyncCompileJob::WaitForBackgroundTasks);
    2840             :     }
    2841             :     return true;
    2842             :   }
    2843             : 
    2844             :   //==========================================================================
    2845             :   // Step 4b (async): Wait for all background tasks to finish.
    2846             :   //==========================================================================
    2847         210 :   bool WaitForBackgroundTasks() {
    2848         210 :     TRACE_COMPILE("(4b) Waiting for background tasks...\n");
    2849             :     // Special handling for predictable mode, see above.
    2850             :     if (!FLAG_verify_predictable) {
    2851         209 :       for (size_t i = 0; i < num_background_tasks_; ++i) {
    2852             :         // We wait for it to finish.
    2853         420 :         module_->pending_tasks.get()->Wait();
    2854             :       }
    2855             :     }
    2856         209 :     if (failed_) {
    2857             :       // If {failed_}, we've already rejected the promise and there
    2858             :       // is nothing more to do.
    2859             :       return false;
    2860             :     } else {
    2861             :       // Otherwise, post a synchronous task to finish the compile.
    2862         209 :       DoSync(&AsyncCompileJob::FinishCompile);
    2863         210 :       return true;
    2864             :     }
    2865             :   }
    2866             : 
    2867             :   //==========================================================================
    2868             :   // Step 5 (sync): Finish heap-allocated data structures.
    2869             :   //==========================================================================
    2870         750 :   bool FinishCompile() {
    2871         750 :     TRACE_COMPILE("(5) Finish compile...\n");
    2872        1500 :     HandleScope scope(isolate_);
    2873        1500 :     SaveContext saved_context(isolate_);
    2874         750 :     isolate_->set_context(*context_);
    2875             :     // At this point, compilation has completed. Update the code table.
    2876        2730 :     for (size_t i = FLAG_skip_compiling_wasm_funcs;
    2877        1365 :          i < temp_instance_->function_code.size(); ++i) {
    2878         615 :       Code* code = Code::cast(code_table_->get(static_cast<int>(i)));
    2879         615 :       RecordStats(isolate_, code);
    2880             :     }
    2881             : 
    2882             :     // Create heap objects for script and module bytes to be stored in the
    2883             :     // shared module data. Asm.js is not compiled asynchronously.
    2884         750 :     Handle<Script> script = CreateWasmScript(isolate_, wire_bytes_);
    2885             :     Handle<ByteArray> asm_js_offset_table;
    2886             :     // TODO(wasm): Improve efficiency of storing module wire bytes.
    2887             :     //   1. Only store relevant sections, not function bodies
    2888             :     //   2. Don't make a second copy of the bytes here; reuse the copy made
    2889             :     //      for asynchronous compilation and store it as an external one
    2890             :     //      byte string for serialization/deserialization.
    2891             :     Handle<String> module_bytes =
    2892             :         isolate_->factory()
    2893             :             ->NewStringFromOneByte({wire_bytes_.start(), wire_bytes_.length()},
    2894             :                                    TENURED)
    2895        1500 :             .ToHandleChecked();
    2896             :     DCHECK(module_bytes->IsSeqOneByteString());
    2897             : 
    2898             :     // Create the shared module data.
    2899             :     // TODO(clemensh): For the same module (same bytes / same hash), we should
    2900             :     // only have one WasmSharedModuleData. Otherwise, we might only set
    2901             :     // breakpoints on a (potentially empty) subset of the instances.
    2902             : 
    2903             :     Handle<WasmSharedModuleData> shared = WasmSharedModuleData::New(
    2904             :         isolate_, module_wrapper_, Handle<SeqOneByteString>::cast(module_bytes),
    2905         750 :         script, asm_js_offset_table);
    2906             : 
    2907             :     // Create the compiled module object and populate with compiled functions
    2908             :     // and information needed at instantiation time. This object needs to be
    2909             :     // serializable. Instantiation may occur off a deserialized version of this
    2910             :     // object.
    2911             :     compiled_module_ = WasmCompiledModule::New(
    2912         750 :         isolate_, shared, code_table_, function_tables_, signature_tables_);
    2913             : 
    2914             :     // Finish the WASM script now and make it public to the debugger.
    2915         750 :     script->set_wasm_compiled_module(*compiled_module_);
    2916        1500 :     isolate_->debug()->OnAfterCompile(script);
    2917             : 
    2918        1500 :     DeferredHandleScope deferred(isolate_);
    2919        1500 :     compiled_module_ = handle(*compiled_module_, isolate_);
    2920        1500 :     deferred_handles_.push_back(deferred.Detach());
    2921             :     // TODO(wasm): compiling wrappers should be made async as well.
    2922        1500 :     return DoSync(&AsyncCompileJob::CompileWrappers);
    2923             :   }
    2924             : 
    2925             :   //==========================================================================
    2926             :   // Step 6 (sync): Compile JS->WASM wrappers.
    2927             :   //==========================================================================
    2928         750 :   bool CompileWrappers() {
    2929         750 :     TRACE_COMPILE("(6) Compile wrappers...\n");
    2930             :     // Compile JS->WASM wrappers for exported functions.
    2931         750 :     HandleScope scope(isolate_);
    2932         750 :     JSToWasmWrapperCache js_to_wasm_cache;
    2933             :     int func_index = 0;
    2934        2445 :     for (auto exp : module_->export_table) {
    2935         255 :       if (exp.kind != kExternalFunction) continue;
    2936         135 :       Handle<Code> wasm_code(Code::cast(code_table_->get(exp.index)), isolate_);
    2937             :       Handle<Code> wrapper_code =
    2938             :           js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(isolate_, module_,
    2939         135 :                                                          wasm_code, exp.index);
    2940             :       int export_index =
    2941         270 :           static_cast<int>(module_->functions.size() + func_index);
    2942         135 :       code_table_->set(export_index, *wrapper_code);
    2943         135 :       RecordStats(isolate_, *wrapper_code);
    2944         135 :       func_index++;
    2945             :     }
    2946             : 
    2947        1500 :     return DoSync(&AsyncCompileJob::FinishModule);
    2948             :   }
    2949             : 
    2950             :   //==========================================================================
    2951             :   // Step 7 (sync): Finish the module and resolve the promise.
    2952             :   //==========================================================================
    2953         750 :   bool FinishModule() {
    2954         750 :     TRACE_COMPILE("(7) Finish module...\n");
    2955         750 :     HandleScope scope(isolate_);
    2956        1500 :     SaveContext saved_context(isolate_);
    2957         750 :     isolate_->set_context(*context_);
    2958             :     Handle<WasmModuleObject> result =
    2959         750 :         WasmModuleObject::New(isolate_, compiled_module_);
    2960         750 :     ResolvePromise(isolate_, context_, module_promise_, result);
    2961         750 :     return false;  // no more work to do.
    2962             :   }
    2963             : 
    2964             :   // Run the given member method as an asynchronous task.
    2965        1185 :   bool DoAsync(bool (AsyncCompileJob::*func)()) {
    2966        1185 :     auto task = new AsyncCompileTask(this, func);
    2967        1185 :     V8::GetCurrentPlatform()->CallOnBackgroundThread(
    2968        1185 :         task, v8::Platform::kShortRunningTask);
    2969        1185 :     return true;  // more work to do.
    2970             :   }
    2971             : 
    2972             :   // Run the given member method as a synchronous task.
    2973        3224 :   bool DoSync(bool (AsyncCompileJob::*func)()) {
    2974        3224 :     V8::GetCurrentPlatform()->CallOnForegroundThread(
    2975             :         reinterpret_cast<v8::Isolate*>(isolate_),
    2976        6446 :         new AsyncCompileTask(this, func));
    2977        3225 :     return true;  // more work to do.
    2978             :   }
    2979             : 
    2980             :   // A helper closure to run a particular member method as a task.
    2981        8818 :   class AsyncCompileTask : NON_EXPORTED_BASE(public v8::Task) {
    2982             :    public:
    2983             :     AsyncCompileJob* job_;
    2984             :     bool (AsyncCompileJob::*func_)();
    2985             :     AsyncCompileTask(AsyncCompileJob* job, bool (AsyncCompileJob::*func)())
    2986        4410 :         : v8::Task(), job_(job), func_(func) {}
    2987             : 
    2988        4410 :     void Run() {
    2989        4410 :       bool more = (job_->*func_)();  // run the task.
    2990        4410 :       if (!more) {
    2991             :         // If no more work, then this job is done. Predictable mode is handled
    2992             :         // specially though, see above.
    2993         765 :         if (!FLAG_verify_predictable) delete job_;
    2994             :       }
    2995        4410 :     }
    2996             :   };
    2997             : };
    2998             : 
    2999        1530 : void wasm::AsyncCompile(Isolate* isolate, Handle<JSPromise> promise,
    3000             :                         const ModuleWireBytes& bytes) {
    3001         765 :   if (!FLAG_wasm_async_compilation) {
    3002             :     ErrorThrower thrower(isolate, "WasmCompile");
    3003             :     // Compile the module.
    3004             :     MaybeHandle<WasmModuleObject> module_object =
    3005           0 :         SyncCompile(isolate, &thrower, bytes);
    3006           0 :     if (thrower.error()) {
    3007           0 :       RejectPromise(isolate, handle(isolate->context()), &thrower, promise);
    3008           0 :       return;
    3009             :     }
    3010             :     Handle<WasmModuleObject> module = module_object.ToHandleChecked();
    3011           0 :     ResolvePromise(isolate, handle(isolate->context()), promise, module);
    3012           0 :     return;
    3013             :   }
    3014             : 
    3015             :   // Make a copy of the wire bytes in case the user program changes them
    3016             :   // during asynchronous compilation.
    3017         765 :   std::unique_ptr<byte[]> copy(new byte[bytes.length()]);
    3018         765 :   memcpy(copy.get(), bytes.start(), bytes.length());
    3019             :   auto job = new AsyncCompileJob(isolate, std::move(copy), bytes.length(),
    3020        1530 :                                  handle(isolate->context()), promise);
    3021             :   job->Start();
    3022             :   // Special handling for predictable mode, see above.
    3023             :   if (FLAG_verify_predictable) delete job;
    3024             : }
    3025             : 
    3026       12686 : Handle<Code> wasm::CompileLazy(Isolate* isolate) {
    3027             :   HistogramTimerScope lazy_time_scope(
    3028       12686 :       isolate->counters()->wasm_lazy_compilation_time());
    3029             : 
    3030             :   // Find the wasm frame which triggered the lazy compile, to get the wasm
    3031             :   // instance.
    3032       12686 :   StackFrameIterator it(isolate);
    3033             :   // First frame: C entry stub.
    3034             :   DCHECK(!it.done());
    3035             :   DCHECK_EQ(StackFrame::EXIT, it.frame()->type());
    3036       12686 :   it.Advance();
    3037             :   // Second frame: WasmCompileLazy builtin.
    3038             :   DCHECK(!it.done());
    3039       12686 :   Handle<Code> lazy_compile_code(it.frame()->LookupCode(), isolate);
    3040             :   DCHECK_EQ(Builtins::kWasmCompileLazy, lazy_compile_code->builtin_index());
    3041             :   Handle<WasmInstanceObject> instance;
    3042             :   Handle<FixedArray> exp_deopt_data;
    3043             :   int func_index = -1;
    3044       12686 :   if (lazy_compile_code->deoptimization_data()->length() > 0) {
    3045             :     // Then it's an indirect call or via JS->WASM wrapper.
    3046             :     DCHECK_LE(2, lazy_compile_code->deoptimization_data()->length());
    3047             :     exp_deopt_data = handle(lazy_compile_code->deoptimization_data(), isolate);
    3048             :     auto* weak_cell = WeakCell::cast(exp_deopt_data->get(0));
    3049       10094 :     instance = handle(WasmInstanceObject::cast(weak_cell->value()), isolate);
    3050             :     func_index = Smi::cast(exp_deopt_data->get(1))->value();
    3051             :   }
    3052       12686 :   it.Advance();
    3053             :   // Third frame: The calling wasm code or js-to-wasm wrapper.
    3054             :   DCHECK(!it.done());
    3055             :   DCHECK(it.frame()->is_js_to_wasm() || it.frame()->is_wasm_compiled());
    3056       12686 :   Handle<Code> caller_code = handle(it.frame()->LookupCode(), isolate);
    3057       25372 :   if (it.frame()->is_js_to_wasm()) {
    3058             :     DCHECK(!instance.is_null());
    3059        3124 :   } else if (instance.is_null()) {
    3060        2592 :     instance = handle(wasm::GetOwningWasmInstance(*caller_code), isolate);
    3061             :   } else {
    3062             :     DCHECK(*instance == wasm::GetOwningWasmInstance(*caller_code));
    3063             :   }
    3064             :   int offset =
    3065       38058 :       static_cast<int>(it.frame()->pc() - caller_code->instruction_start());
    3066             :   // Only patch the caller code if this is *no* indirect call.
    3067             :   // exp_deopt_data will be null if the called function is not exported at all,
    3068             :   // and its length will be <= 2 if all entries in tables were already patched.
    3069             :   // Note that this check is conservative: If the first call to an exported
    3070             :   // function is direct, we will just patch the export tables, and only on the
    3071             :   // second call we will patch the caller.
    3072        3124 :   bool patch_caller = caller_code->kind() == Code::JS_TO_WASM_FUNCTION ||
    3073       13218 :                       exp_deopt_data.is_null() || exp_deopt_data->length() <= 2;
    3074             : 
    3075             :   MaybeHandle<Code> maybe_compiled_code = WasmCompiledModule::CompileLazy(
    3076       12686 :       isolate, instance, caller_code, offset, func_index, patch_caller);
    3077       12686 :   if (maybe_compiled_code.is_null()) {
    3078             :     DCHECK(isolate->has_pending_exception());
    3079           0 :     return isolate->builtins()->Illegal();
    3080             :   }
    3081             :   Handle<Code> compiled_code = maybe_compiled_code.ToHandleChecked();
    3082       22780 :   if (!exp_deopt_data.is_null() && exp_deopt_data->length() > 2) {
    3083             :     // See EnsureExportedLazyDeoptData: exp_deopt_data[2...(len-1)] are pairs of
    3084             :     // <export_table, index> followed by undefined values.
    3085             :     // Use this information here to patch all export tables.
    3086             :     DCHECK_EQ(0, exp_deopt_data->length() % 2);
    3087         770 :     for (int idx = 2, end = exp_deopt_data->length(); idx < end; idx += 2) {
    3088         392 :       if (exp_deopt_data->get(idx)->IsUndefined(isolate)) break;
    3089             :       FixedArray* exp_table = FixedArray::cast(exp_deopt_data->get(idx));
    3090         392 :       int exp_index = Smi::cast(exp_deopt_data->get(idx + 1))->value();
    3091             :       DCHECK(exp_table->get(exp_index) == *lazy_compile_code);
    3092         392 :       exp_table->set(exp_index, *compiled_code);
    3093             :     }
    3094             :     // After processing, remove the list of exported entries, such that we don't
    3095             :     // do the patching redundantly.
    3096             :     Handle<FixedArray> new_deopt_data =
    3097         378 :         isolate->factory()->CopyFixedArrayUpTo(exp_deopt_data, 2, TENURED);
    3098         378 :     lazy_compile_code->set_deoptimization_data(*new_deopt_data);
    3099             :   }
    3100             : 
    3101       12686 :   return compiled_code;
    3102             : }
    3103             : 
    3104       12686 : bool LazyCompilationOrchestrator::CompileFunction(
    3105       12483 :     Isolate* isolate, Handle<WasmInstanceObject> instance, int func_index) {
    3106             :   Handle<WasmCompiledModule> compiled_module(instance->compiled_module(),
    3107       12686 :                                              isolate);
    3108       25372 :   if (Code::cast(compiled_module->code_table()->get(func_index))->kind() ==
    3109             :       Code::WASM_FUNCTION) {
    3110             :     return true;
    3111             :   }
    3112             :   size_t num_function_tables =
    3113       12483 :       compiled_module->module()->function_tables.size();
    3114             :   // Store a vector of handles to be embedded in the generated code.
    3115             :   // TODO(clemensh): For concurrent compilation, these will have to live in a
    3116             :   // DeferredHandleScope.
    3117       12483 :   std::vector<Handle<FixedArray>> fun_tables(num_function_tables);
    3118       12483 :   std::vector<Handle<FixedArray>> sig_tables(num_function_tables);
    3119       15540 :   for (size_t i = 0; i < num_function_tables; ++i) {
    3120             :     Object* fun_table =
    3121        9171 :         compiled_module->function_tables()->get(static_cast<int>(i));
    3122        6114 :     fun_tables[i] = handle(FixedArray::cast(fun_table), isolate);
    3123             :     Object* sig_table =
    3124        6114 :         compiled_module->signature_tables()->get(static_cast<int>(i));
    3125        6114 :     sig_tables[i] = handle(FixedArray::cast(sig_table), isolate);
    3126             :   }
    3127       12483 :   wasm::ModuleEnv module_env(compiled_module->module(), &fun_tables,
    3128             :                              &sig_tables);
    3129       12483 :   uint8_t* module_start = compiled_module->module_bytes()->GetChars();
    3130       12483 :   const WasmFunction* func = &module_env.module->functions[func_index];
    3131             :   wasm::FunctionBody body{func->sig, module_start,
    3132             :                           module_start + func->code_start_offset,
    3133       12483 :                           module_start + func->code_end_offset};
    3134             :   // TODO(wasm): Refactor this to only get the name if it is really needed for
    3135             :   // tracing / debugging.
    3136             :   std::string func_name;
    3137             :   {
    3138             :     wasm::WasmName name = Vector<const char>::cast(
    3139       24966 :         compiled_module->GetRawFunctionName(func_index));
    3140             :     // Copy to std::string, because the underlying string object might move on
    3141             :     // the heap.
    3142       12483 :     func_name.assign(name.start(), static_cast<size_t>(name.length()));
    3143             :   }
    3144       12483 :   ErrorThrower thrower(isolate, "WasmLazyCompile");
    3145             :   compiler::WasmCompilationUnit unit(isolate, &module_env, body,
    3146       24966 :                                      CStrVector(func_name.c_str()), func_index);
    3147       12483 :   unit.InitializeHandles();
    3148       12483 :   unit.ExecuteCompilation();
    3149       12483 :   Handle<Code> code = unit.FinishCompilation(&thrower);
    3150             : 
    3151       12483 :   Handle<FixedArray> deopt_data = isolate->factory()->NewFixedArray(2, TENURED);
    3152       12483 :   Handle<WeakCell> weak_instance = isolate->factory()->NewWeakCell(instance);
    3153             :   // TODO(wasm): Introduce constants for the indexes in wasm deopt data.
    3154       12483 :   deopt_data->set(0, *weak_instance);
    3155             :   deopt_data->set(1, Smi::FromInt(func_index));
    3156       12483 :   code->set_deoptimization_data(*deopt_data);
    3157             : 
    3158       12483 :   if (thrower.error()) {
    3159           0 :     if (!isolate->has_pending_exception()) isolate->Throw(*thrower.Reify());
    3160             :     return false;
    3161             :   }
    3162             : 
    3163             :   DCHECK_EQ(Builtins::kWasmCompileLazy,
    3164             :             Code::cast(compiled_module->code_table()->get(func_index))
    3165             :                 ->builtin_index());
    3166       24966 :   compiled_module->code_table()->set(func_index, *code);
    3167             : 
    3168             :   // Now specialize the generated code for this instance.
    3169       24966 :   Zone specialization_zone(isolate->allocator(), ZONE_NAME);
    3170       24966 :   CodeSpecialization code_specialization(isolate, &specialization_zone);
    3171       12483 :   if (module_env.module->globals_size) {
    3172             :     Address globals_start =
    3173        4679 :         reinterpret_cast<Address>(compiled_module->globals_start());
    3174        4679 :     code_specialization.RelocateGlobals(nullptr, globals_start);
    3175             :   }
    3176       12483 :   if (instance->has_memory_buffer()) {
    3177             :     Address mem_start =
    3178       12483 :         reinterpret_cast<Address>(instance->memory_buffer()->backing_store());
    3179       24966 :     int mem_size = instance->memory_buffer()->byte_length()->Number();
    3180             :     DCHECK_IMPLIES(mem_size == 0, mem_start == nullptr);
    3181       12483 :     if (mem_size > 0) {
    3182             :       code_specialization.RelocateMemoryReferences(nullptr, 0, mem_start,
    3183       12470 :                                                    mem_size);
    3184             :     }
    3185             :   }
    3186       12483 :   code_specialization.RelocateDirectCalls(instance);
    3187       12483 :   code_specialization.ApplyToWasmCode(*code, SKIP_ICACHE_FLUSH);
    3188       12483 :   Assembler::FlushICache(isolate, code->instruction_start(),
    3189       24966 :                          code->instruction_size());
    3190       12483 :   RecordLazyCodeStats(isolate, *code);
    3191             :   return true;
    3192             : }
    3193             : 
    3194       12686 : MaybeHandle<Code> LazyCompilationOrchestrator::CompileLazy(
    3195             :     Isolate* isolate, Handle<WasmInstanceObject> instance, Handle<Code> caller,
    3196             :     int call_offset, int exported_func_index, bool patch_caller) {
    3197             :   struct NonCompiledFunction {
    3198             :     int offset;
    3199             :     int func_index;
    3200             :   };
    3201             :   std::vector<NonCompiledFunction> non_compiled_functions;
    3202             :   int func_to_return_idx = exported_func_index;
    3203             :   wasm::Decoder decoder(nullptr, nullptr);
    3204       12686 :   bool is_js_to_wasm = caller->kind() == Code::JS_TO_WASM_FUNCTION;
    3205             :   Handle<WasmCompiledModule> compiled_module(instance->compiled_module(),
    3206       12686 :                                              isolate);
    3207             : 
    3208       12686 :   if (is_js_to_wasm) {
    3209       19124 :     non_compiled_functions.push_back({0, exported_func_index});
    3210        3124 :   } else if (patch_caller) {
    3211             :     DisallowHeapAllocation no_gc;
    3212        2753 :     SeqOneByteString* module_bytes = compiled_module->module_bytes();
    3213             :     SourcePositionTableIterator source_pos_iterator(
    3214        2753 :         caller->SourcePositionTable());
    3215             :     DCHECK_EQ(2, caller->deoptimization_data()->length());
    3216             :     int caller_func_index =
    3217             :         Smi::cast(caller->deoptimization_data()->get(1))->value();
    3218             :     const byte* func_bytes =
    3219        5506 :         module_bytes->GetChars() + compiled_module->module()
    3220        5506 :                                        ->functions[caller_func_index]
    3221        2753 :                                        .code_start_offset;
    3222       81263 :     for (RelocIterator it(*caller, RelocInfo::kCodeTargetMask); !it.done();
    3223       75757 :          it.next()) {
    3224             :       Code* callee =
    3225       75757 :           Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
    3226       75757 :       if (callee->builtin_index() != Builtins::kWasmCompileLazy) continue;
    3227             :       // TODO(clemensh): Introduce safe_cast<T, bool> which (D)CHECKS
    3228             :       // (depending on the bool) against limits of T and then static_casts.
    3229       51482 :       size_t offset_l = it.rinfo()->pc() - caller->instruction_start();
    3230             :       DCHECK_GE(kMaxInt, offset_l);
    3231       25741 :       int offset = static_cast<int>(offset_l);
    3232             :       int byte_pos =
    3233       25741 :           AdvanceSourcePositionTableIterator(source_pos_iterator, offset);
    3234             :       int called_func_index =
    3235       25741 :           ExtractDirectCallIndex(decoder, func_bytes + byte_pos);
    3236       51482 :       non_compiled_functions.push_back({offset, called_func_index});
    3237             :       // Call offset one instruction after the call. Remember the last called
    3238             :       // function before that offset.
    3239       25741 :       if (offset < call_offset) func_to_return_idx = called_func_index;
    3240             :     }
    3241             :   }
    3242             : 
    3243             :   // TODO(clemensh): compile all functions in non_compiled_functions in
    3244             :   // background, wait for func_to_return_idx.
    3245       12686 :   if (!CompileFunction(isolate, instance, func_to_return_idx)) {
    3246             :     return {};
    3247             :   }
    3248             : 
    3249       12686 :   if (is_js_to_wasm || patch_caller) {
    3250             :     DisallowHeapAllocation no_gc;
    3251             :     // Now patch the code object with all functions which are now compiled.
    3252             :     int idx = 0;
    3253      121463 :     for (RelocIterator it(*caller, RelocInfo::kCodeTargetMask); !it.done();
    3254       96833 :          it.next()) {
    3255             :       Code* callee =
    3256       96833 :           Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
    3257       96833 :       if (callee->builtin_index() != Builtins::kWasmCompileLazy) continue;
    3258             :       DCHECK_GT(non_compiled_functions.size(), idx);
    3259       70606 :       int called_func_index = non_compiled_functions[idx].func_index;
    3260             :       // Check that the callee agrees with our assumed called_func_index.
    3261             :       DCHECK_IMPLIES(
    3262             :           callee->deoptimization_data()->length() > 0,
    3263             :           Smi::cast(callee->deoptimization_data()->get(1))->value() ==
    3264             :               called_func_index);
    3265             :       if (is_js_to_wasm) {
    3266             :         DCHECK_EQ(func_to_return_idx, called_func_index);
    3267             :       } else {
    3268             :         DCHECK_EQ(non_compiled_functions[idx].offset,
    3269             :                   it.rinfo()->pc() - caller->instruction_start());
    3270             :       }
    3271       35303 :       ++idx;
    3272             :       Handle<Code> callee_compiled(
    3273       70606 :           Code::cast(compiled_module->code_table()->get(called_func_index)));
    3274       35303 :       if (callee_compiled->builtin_index() == Builtins::kWasmCompileLazy) {
    3275             :         DCHECK_NE(func_to_return_idx, called_func_index);
    3276             :         continue;
    3277             :       }
    3278             :       DCHECK_EQ(Code::WASM_FUNCTION, callee_compiled->kind());
    3279             :       it.rinfo()->set_target_address(isolate,
    3280       14772 :                                      callee_compiled->instruction_start());
    3281             :     }
    3282             :     DCHECK_EQ(non_compiled_functions.size(), idx);
    3283             :   }
    3284             : 
    3285             :   Code* ret =
    3286       25372 :       Code::cast(compiled_module->code_table()->get(func_to_return_idx));
    3287             :   DCHECK_EQ(Code::WASM_FUNCTION, ret->kind());
    3288             :   return handle(ret, isolate);
    3289             : }

Generated by: LCOV version 1.10