LCOV - code coverage report
Current view: top level - src/wasm - module-compiler.cc (source / functions) Hit Total Coverage
Test: app.info Lines: 1216 1268 95.9 %
Date: 2017-10-20 Functions: 119 141 84.4 %

          Line data    Source code
       1             : // Copyright 2017 the V8 project authors. All rights reserved.
       2             : // Use of this source code is governed by a BSD-style license that can be
       3             : // found in the LICENSE file.
       4             : 
       5             : #include "src/wasm/module-compiler.h"
       6             : 
       7             : #include <atomic>
       8             : 
       9             : #include "src/api.h"
      10             : #include "src/asmjs/asm-js.h"
      11             : #include "src/assembler-inl.h"
      12             : #include "src/base/template-utils.h"
      13             : #include "src/base/utils/random-number-generator.h"
      14             : #include "src/code-stubs.h"
      15             : #include "src/compiler/wasm-compiler.h"
      16             : #include "src/counters.h"
      17             : #include "src/property-descriptor.h"
      18             : #include "src/wasm/compilation-manager.h"
      19             : #include "src/wasm/module-decoder.h"
      20             : #include "src/wasm/wasm-code-specialization.h"
      21             : #include "src/wasm/wasm-js.h"
      22             : #include "src/wasm/wasm-memory.h"
      23             : #include "src/wasm/wasm-objects-inl.h"
      24             : #include "src/wasm/wasm-result.h"
      25             : 
      26             : #define TRACE(...)                                      \
      27             :   do {                                                  \
      28             :     if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \
      29             :   } while (false)
      30             : 
      31             : #define TRACE_CHAIN(instance)        \
      32             :   do {                               \
      33             :     instance->PrintInstancesChain(); \
      34             :   } while (false)
      35             : 
      36             : #define TRACE_COMPILE(...)                             \
      37             :   do {                                                 \
      38             :     if (FLAG_trace_wasm_compiler) PrintF(__VA_ARGS__); \
      39             :   } while (false)
      40             : 
      41             : #define TRACE_STREAMING(...)                            \
      42             :   do {                                                  \
      43             :     if (FLAG_trace_wasm_streaming) PrintF(__VA_ARGS__); \
      44             :   } while (false)
      45             : static const int kInvalidSigIndex = -1;
      46             : 
      47             : namespace v8 {
      48             : namespace internal {
      49             : namespace wasm {
      50             : 
      51             : // A class compiling an entire module.
      52      461427 : class ModuleCompiler {
      53             :  public:
      54             :   ModuleCompiler(Isolate* isolate, WasmModule* module,
      55             :                  Handle<Code> centry_stub);
      56             : 
      57             :   // The actual runnable task that performs compilations in the background.
      58       47041 :   class CompilationTask : public CancelableTask {
      59             :    public:
      60             :     ModuleCompiler* compiler_;
      61             :     explicit CompilationTask(ModuleCompiler* compiler)
      62             :         : CancelableTask(&compiler->background_task_manager_),
      63       23548 :           compiler_(compiler) {}
      64             : 
      65       22196 :     void RunInternal() override {
      66      196954 :       while (compiler_->executed_units_.CanAcceptWork() &&
      67      174758 :              compiler_->FetchAndExecuteCompilationUnit()) {
      68             :       }
      69             : 
      70       22205 :       compiler_->OnBackgroundTaskStopped();
      71       22198 :     }
      72             :   };
      73             : 
      74             :   // The CompilationUnitBuilder builds compilation units and stores them in an
      75             :   // internal buffer. The buffer is moved into the working queue of the
      76             :   // ModuleCompiler when {Commit} is called.
      77             :   class CompilationUnitBuilder {
      78             :    public:
      79             :     explicit CompilationUnitBuilder(ModuleCompiler* compiler)
      80        3619 :         : compiler_(compiler) {}
      81             : 
      82        3619 :     ~CompilationUnitBuilder() { DCHECK(units_.empty()); }
      83             : 
      84       38744 :     void AddUnit(compiler::ModuleEnv* module_env, const WasmFunction* function,
      85             :                  uint32_t buffer_offset, Vector<const uint8_t> bytes,
      86             :                  WasmName name) {
      87             :       units_.emplace_back(new compiler::WasmCompilationUnit(
      88             :           compiler_->isolate_, module_env,
      89             :           wasm::FunctionBody{function->sig, buffer_offset, bytes.begin(),
      90             :                              bytes.end()},
      91             :           name, function->func_index, compiler_->centry_stub_,
      92      116232 :           compiler_->counters()));
      93       38744 :     }
      94             : 
      95        3677 :     void Commit() {
      96             :       {
      97             :         base::LockGuard<base::Mutex> guard(
      98        3677 :             &compiler_->compilation_units_mutex_);
      99             :         compiler_->compilation_units_.insert(
     100             :             compiler_->compilation_units_.end(),
     101             :             std::make_move_iterator(units_.begin()),
     102        7354 :             std::make_move_iterator(units_.end()));
     103             :       }
     104             :       units_.clear();
     105        3677 :     }
     106             : 
     107             :     void Clear() { units_.clear(); }
     108             : 
     109             :    private:
     110             :     ModuleCompiler* compiler_;
     111             :     std::vector<std::unique_ptr<compiler::WasmCompilationUnit>> units_;
     112             :   };
     113             : 
     114      153809 :   class CodeGenerationSchedule {
     115             :    public:
     116             :     explicit CodeGenerationSchedule(
     117             :         base::RandomNumberGenerator* random_number_generator,
     118             :         size_t max_memory = 0);
     119             : 
     120             :     void Schedule(std::unique_ptr<compiler::WasmCompilationUnit>&& item);
     121             : 
     122             :     bool IsEmpty() const { return schedule_.empty(); }
     123             : 
     124             :     std::unique_ptr<compiler::WasmCompilationUnit> GetNext();
     125             : 
     126             :     bool CanAcceptWork() const;
     127             : 
     128             :     bool ShouldIncreaseWorkload() const;
     129             : 
     130        3619 :     void EnableThrottling() { throttle_ = true; }
     131             : 
     132             :    private:
     133             :     size_t GetRandomIndexInSchedule();
     134             : 
     135             :     base::RandomNumberGenerator* random_number_generator_ = nullptr;
     136             :     std::vector<std::unique_ptr<compiler::WasmCompilationUnit>> schedule_;
     137             :     const size_t max_memory_;
     138             :     bool throttle_ = false;
     139             :     base::AtomicNumber<size_t> allocated_memory_{0};
     140             :   };
     141             : 
     142      546061 :   Counters* counters() const { return async_counters_.get(); }
     143             : 
     144             :   // Run by each compilation task and by the main thread (i.e. in both
     145             :   // foreground and background threads). The no_finisher_callback is called
     146             :   // within the result_mutex_ lock when no finishing task is running, i.e. when
     147             :   // the finisher_is_running_ flag is not set.
     148             :   bool FetchAndExecuteCompilationUnit(
     149             :       std::function<void()> no_finisher_callback = nullptr);
     150             : 
     151             :   void OnBackgroundTaskStopped();
     152             : 
     153             :   void EnableThrottling() { executed_units_.EnableThrottling(); }
     154             : 
     155             :   bool CanAcceptWork() const { return executed_units_.CanAcceptWork(); }
     156             : 
     157             :   bool ShouldIncreaseWorkload() const {
     158          36 :     return executed_units_.ShouldIncreaseWorkload();
     159             :   }
     160             : 
     161             :   size_t InitializeCompilationUnits(const std::vector<WasmFunction>& functions,
     162             :                                     const ModuleWireBytes& wire_bytes,
     163             :                                     compiler::ModuleEnv* module_env);
     164             : 
     165             :   void RestartCompilationTasks();
     166             : 
     167             :   size_t FinishCompilationUnits(std::vector<Handle<Code>>& results,
     168             :                                 ErrorThrower* thrower);
     169             : 
     170             :   bool IsFinisherRunning() const { return finisher_is_running_; }
     171             : 
     172             :   void SetFinisherIsRunning(bool value);
     173             : 
     174             :   MaybeHandle<Code> FinishCompilationUnit(ErrorThrower* thrower,
     175             :                                           int* func_index);
     176             : 
     177             :   void CompileInParallel(const ModuleWireBytes& wire_bytes,
     178             :                          compiler::ModuleEnv* module_env,
     179             :                          std::vector<Handle<Code>>& results,
     180             :                          ErrorThrower* thrower);
     181             : 
     182             :   void CompileSequentially(const ModuleWireBytes& wire_bytes,
     183             :                            compiler::ModuleEnv* module_env,
     184             :                            std::vector<Handle<Code>>& results,
     185             :                            ErrorThrower* thrower);
     186             : 
     187             :   void ValidateSequentially(const ModuleWireBytes& wire_bytes,
     188             :                             compiler::ModuleEnv* module_env,
     189             :                             ErrorThrower* thrower);
     190             : 
     191             :   static MaybeHandle<WasmModuleObject> CompileToModuleObject(
     192             :       Isolate* isolate, ErrorThrower* thrower,
     193             :       std::unique_ptr<WasmModule> module, const ModuleWireBytes& wire_bytes,
     194             :       Handle<Script> asm_js_script,
     195             :       Vector<const byte> asm_js_offset_table_bytes);
     196             : 
     197             :  private:
     198             :   MaybeHandle<WasmModuleObject> CompileToModuleObjectInternal(
     199             :       ErrorThrower* thrower, std::unique_ptr<WasmModule> module,
     200             :       const ModuleWireBytes& wire_bytes, Handle<Script> asm_js_script,
     201             :       Vector<const byte> asm_js_offset_table_bytes);
     202             : 
     203             :   Isolate* isolate_;
     204             :   WasmModule* module_;
     205             :   const std::shared_ptr<Counters> async_counters_;
     206             :   std::vector<std::unique_ptr<compiler::WasmCompilationUnit>>
     207             :       compilation_units_;
     208             :   base::Mutex compilation_units_mutex_;
     209             :   CodeGenerationSchedule executed_units_;
     210             :   base::Mutex result_mutex_;
     211             :   const size_t num_background_tasks_;
     212             :   // This flag should only be set while holding result_mutex_.
     213             :   bool finisher_is_running_ = false;
     214             :   CancelableTaskManager background_task_manager_;
     215             :   size_t stopped_compilation_tasks_ = 0;
     216             :   base::Mutex tasks_mutex_;
     217             :   Handle<Code> centry_stub_;
     218             : };
     219             : 
     220      906318 : class JSToWasmWrapperCache {
     221             :  public:
     222             :   void SetContextAddress(Address context_address) {
     223             :     // Prevent to have different context addresses in the cache.
     224             :     DCHECK(code_cache_.empty());
     225      152712 :     context_address_ = context_address;
     226             :   }
     227             : 
     228      187576 :   Handle<Code> CloneOrCompileJSToWasmWrapper(Isolate* isolate,
     229             :                                              wasm::WasmModule* module,
     230             :                                              Handle<Code> wasm_code,
     231             :                                              uint32_t index) {
     232      187576 :     const wasm::WasmFunction* func = &module->functions[index];
     233      187576 :     int cached_idx = sig_map_.Find(func->sig);
     234      187576 :     if (cached_idx >= 0) {
     235       62984 :       Handle<Code> code = isolate->factory()->CopyCode(code_cache_[cached_idx]);
     236             :       // Now patch the call to wasm code.
     237       58514 :       for (RelocIterator it(*code, RelocInfo::kCodeTargetMask);; it.next()) {
     238             :         DCHECK(!it.done());
     239             :         Code* target =
     240       58514 :             Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
     241       87571 :         if (target->kind() == Code::WASM_FUNCTION ||
     242       29057 :             target->kind() == Code::WASM_TO_JS_FUNCTION ||
     243       87381 :             target->builtin_index() == Builtins::kIllegal ||
     244             :             target->builtin_index() == Builtins::kWasmCompileLazy) {
     245             :           it.rinfo()->set_target_address(isolate,
     246       31492 :                                          wasm_code->instruction_start());
     247             :           break;
     248             :         }
     249       27022 :       }
     250       31492 :       return code;
     251             :     }
     252             : 
     253             :     Handle<Code> code = compiler::CompileJSToWasmWrapper(
     254      156084 :         isolate, module, wasm_code, index, context_address_);
     255      156084 :     uint32_t new_cache_idx = sig_map_.FindOrInsert(func->sig);
     256             :     DCHECK_EQ(code_cache_.size(), new_cache_idx);
     257             :     USE(new_cache_idx);
     258      156084 :     code_cache_.push_back(code);
     259      156084 :     return code;
     260             :   }
     261             : 
     262             :  private:
     263             :   // sig_map_ maps signatures to an index in code_cache_.
     264             :   wasm::SignatureMap sig_map_;
     265             :   std::vector<Handle<Code>> code_cache_;
     266             :   Address context_address_ = nullptr;
     267             : };
     268             : 
     269             : // A helper class to simplify instantiating a module from a compiled module.
     270             : // It closes over the {Isolate}, the {ErrorThrower}, the {WasmCompiledModule},
     271             : // etc.
     272      462444 : class InstanceBuilder {
     273             :  public:
     274             :   InstanceBuilder(Isolate* isolate, ErrorThrower* thrower,
     275             :                   Handle<WasmModuleObject> module_object,
     276             :                   MaybeHandle<JSReceiver> ffi,
     277             :                   MaybeHandle<JSArrayBuffer> memory,
     278             :                   WeakCallbackInfo<void>::Callback instance_finalizer_callback);
     279             : 
     280             :   // Build an instance, in all of its glory.
     281             :   MaybeHandle<WasmInstanceObject> Build();
     282             : 
     283             :  private:
     284             :   // Represents the initialized state of a table.
     285             :   struct TableInstance {
     286             :     Handle<WasmTableObject> table_object;  // WebAssembly.Table instance
     287             :     Handle<FixedArray> js_wrappers;        // JSFunctions exported
     288             :     Handle<FixedArray> function_table;     // internal code array
     289             :     Handle<FixedArray> signature_table;    // internal sig array
     290             :   };
     291             : 
     292             :   // A pre-evaluated value to use in import binding.
     293             :   struct SanitizedImport {
     294             :     Handle<String> module_name;
     295             :     Handle<String> import_name;
     296             :     Handle<Object> value;
     297             :   };
     298             : 
     299             :   Isolate* isolate_;
     300             :   WasmModule* const module_;
     301             :   const std::shared_ptr<Counters> async_counters_;
     302             :   ErrorThrower* thrower_;
     303             :   Handle<WasmModuleObject> module_object_;
     304             :   MaybeHandle<JSReceiver> ffi_;
     305             :   MaybeHandle<JSArrayBuffer> memory_;
     306             :   Handle<JSArrayBuffer> globals_;
     307             :   Handle<WasmCompiledModule> compiled_module_;
     308             :   std::vector<TableInstance> table_instances_;
     309             :   std::vector<Handle<JSFunction>> js_wrappers_;
     310             :   JSToWasmWrapperCache js_to_wasm_cache_;
     311             :   WeakCallbackInfo<void>::Callback instance_finalizer_callback_;
     312             :   std::vector<SanitizedImport> sanitized_imports_;
     313             : 
     314             :   const std::shared_ptr<Counters>& async_counters() const {
     315             :     return async_counters_;
     316             :   }
     317      468921 :   Counters* counters() const { return async_counters().get(); }
     318             : 
     319             : // Helper routines to print out errors with imports.
     320             : #define ERROR_THROWER_WITH_MESSAGE(TYPE)                                      \
     321             :   void Report##TYPE(const char* error, uint32_t index,                        \
     322             :                     Handle<String> module_name, Handle<String> import_name) { \
     323             :     thrower_->TYPE("Import #%d module=\"%s\" function=\"%s\" error: %s",      \
     324             :                    index, module_name->ToCString().get(),                     \
     325             :                    import_name->ToCString().get(), error);                    \
     326             :   }                                                                           \
     327             :                                                                               \
     328             :   MaybeHandle<Object> Report##TYPE(const char* error, uint32_t index,         \
     329             :                                    Handle<String> module_name) {              \
     330             :     thrower_->TYPE("Import #%d module=\"%s\" error: %s", index,               \
     331             :                    module_name->ToCString().get(), error);                    \
     332             :     return MaybeHandle<Object>();                                             \
     333             :   }
     334             : 
     335        4538 :   ERROR_THROWER_WITH_MESSAGE(LinkError)
     336         640 :   ERROR_THROWER_WITH_MESSAGE(TypeError)
     337             : 
     338             :   // Look up an import value in the {ffi_} object.
     339             :   MaybeHandle<Object> LookupImport(uint32_t index, Handle<String> module_name,
     340             :                                    Handle<String> import_name);
     341             : 
     342             :   // Look up an import value in the {ffi_} object specifically for linking an
     343             :   // asm.js module. This only performs non-observable lookups, which allows
     344             :   // falling back to JavaScript proper (and hence re-executing all lookups) if
     345             :   // module instantiation fails.
     346             :   MaybeHandle<Object> LookupImportAsm(uint32_t index,
     347             :                                       Handle<String> import_name);
     348             : 
     349             :   uint32_t EvalUint32InitExpr(const WasmInitExpr& expr);
     350             : 
     351             :   // Load data segments into the memory.
     352             :   void LoadDataSegments(Address mem_addr, size_t mem_size);
     353             : 
     354             :   void WriteGlobalValue(WasmGlobal& global, Handle<Object> value);
     355             : 
     356             :   void SanitizeImports();
     357             : 
     358             :   Handle<FixedArray> SetupWasmToJSImportsTable(
     359             :       Handle<WasmInstanceObject> instance);
     360             : 
     361             :   // Process the imports, including functions, tables, globals, and memory, in
     362             :   // order, loading them from the {ffi_} object. Returns the number of imported
     363             :   // functions.
     364             :   int ProcessImports(Handle<FixedArray> code_table,
     365             :                      Handle<WasmInstanceObject> instance);
     366             : 
     367             :   template <typename T>
     368             :   T* GetRawGlobalPtr(WasmGlobal& global);
     369             : 
     370             :   // Process initialization of globals.
     371             :   void InitGlobals();
     372             : 
     373             :   // Allocate memory for a module instance as a new JSArrayBuffer.
     374             :   Handle<JSArrayBuffer> AllocateMemory(uint32_t num_pages);
     375             : 
     376             :   bool NeedsWrappers() const;
     377             : 
     378             :   // Process the exports, creating wrappers for functions, tables, memories,
     379             :   // and globals.
     380             :   void ProcessExports(Handle<WasmInstanceObject> instance,
     381             :                       Handle<WasmCompiledModule> compiled_module);
     382             : 
     383             :   void InitializeTables(Handle<WasmInstanceObject> instance,
     384             :                         CodeSpecialization* code_specialization);
     385             : 
     386             :   void LoadTableSegments(Handle<FixedArray> code_table,
     387             :                          Handle<WasmInstanceObject> instance);
     388             : };
     389             : 
     390             : // TODO(titzer): move to wasm-objects.cc
     391      111452 : static void InstanceFinalizer(const v8::WeakCallbackInfo<void>& data) {
     392             :   DisallowHeapAllocation no_gc;
     393             :   JSObject** p = reinterpret_cast<JSObject**>(data.GetParameter());
     394       55726 :   WasmInstanceObject* owner = reinterpret_cast<WasmInstanceObject*>(*p);
     395             :   Isolate* isolate = reinterpret_cast<Isolate*>(data.GetIsolate());
     396             :   // If a link to shared memory instances exists, update the list of memory
     397             :   // instances before the instance is destroyed.
     398             :   WasmCompiledModule* compiled_module = owner->compiled_module();
     399             :   TRACE("Finalizing %d {\n", compiled_module->instance_id());
     400             :   DCHECK(compiled_module->has_weak_wasm_module());
     401             :   WeakCell* weak_wasm_module = compiled_module->ptr_to_weak_wasm_module();
     402             : 
     403       55726 :   if (trap_handler::UseTrapHandler()) {
     404       15313 :     Handle<FixedArray> code_table = compiled_module->code_table();
     405      100408 :     for (int i = 0; i < code_table->length(); ++i) {
     406       34891 :       Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i);
     407             :       int index = code->trap_handler_index()->value();
     408       34891 :       if (index >= 0) {
     409         456 :         trap_handler::ReleaseHandlerData(index);
     410         456 :         code->set_trap_handler_index(Smi::FromInt(trap_handler::kInvalidIndex));
     411             :       }
     412             :     }
     413             :   }
     414             : 
     415             :   // Since the order of finalizers is not guaranteed, it can be the case
     416             :   // that {instance->compiled_module()->module()}, which is a
     417             :   // {Managed<WasmModule>} has been collected earlier in this GC cycle.
     418             :   // Weak references to this instance won't be cleared until
     419             :   // the next GC cycle, so we need to manually break some links (such as
     420             :   // the weak references from {WasmMemoryObject::instances}.
     421       55726 :   if (owner->has_memory_object()) {
     422             :     Handle<WasmMemoryObject> memory(owner->memory_object(), isolate);
     423             :     Handle<WasmInstanceObject> instance(owner, isolate);
     424        3143 :     WasmMemoryObject::RemoveInstance(isolate, memory, instance);
     425             :   }
     426             : 
     427             :   // weak_wasm_module may have been cleared, meaning the module object
     428             :   // was GC-ed. In that case, there won't be any new instances created,
     429             :   // and we don't need to maintain the links between instances.
     430       55726 :   if (!weak_wasm_module->cleared()) {
     431             :     WasmModuleObject* wasm_module =
     432             :         WasmModuleObject::cast(weak_wasm_module->value());
     433             :     WasmCompiledModule* current_template = wasm_module->compiled_module();
     434             : 
     435             :     TRACE("chain before {\n");
     436        1108 :     TRACE_CHAIN(current_template);
     437             :     TRACE("}\n");
     438             : 
     439             :     DCHECK(!current_template->has_weak_prev_instance());
     440        1108 :     WeakCell* next = compiled_module->maybe_ptr_to_weak_next_instance();
     441        1108 :     WeakCell* prev = compiled_module->maybe_ptr_to_weak_prev_instance();
     442             : 
     443        1108 :     if (current_template == compiled_module) {
     444         589 :       if (next == nullptr) {
     445         460 :         WasmCompiledModule::Reset(isolate, compiled_module);
     446             :       } else {
     447             :         WasmCompiledModule* next_compiled_module =
     448             :             WasmCompiledModule::cast(next->value());
     449             :         WasmModuleObject::cast(wasm_module)
     450         129 :             ->set_compiled_module(next_compiled_module);
     451             :         DCHECK_NULL(prev);
     452             :         next_compiled_module->reset_weak_prev_instance();
     453             :       }
     454             :     } else {
     455             :       DCHECK(!(prev == nullptr && next == nullptr));
     456             :       // the only reason prev or next would be cleared is if the
     457             :       // respective objects got collected, but if that happened,
     458             :       // we would have relinked the list.
     459         519 :       if (prev != nullptr) {
     460             :         DCHECK(!prev->cleared());
     461         519 :         if (next == nullptr) {
     462             :           WasmCompiledModule::cast(prev->value())->reset_weak_next_instance();
     463             :         } else {
     464             :           WasmCompiledModule::cast(prev->value())
     465             :               ->set_ptr_to_weak_next_instance(next);
     466             :         }
     467             :       }
     468         519 :       if (next != nullptr) {
     469             :         DCHECK(!next->cleared());
     470         189 :         if (prev == nullptr) {
     471             :           WasmCompiledModule::cast(next->value())->reset_weak_prev_instance();
     472             :         } else {
     473             :           WasmCompiledModule::cast(next->value())
     474             :               ->set_ptr_to_weak_prev_instance(prev);
     475             :         }
     476             :       }
     477             :     }
     478             :     TRACE("chain after {\n");
     479        1108 :     TRACE_CHAIN(wasm_module->compiled_module());
     480             :     TRACE("}\n");
     481             :   }
     482             :   compiled_module->reset_weak_owning_instance();
     483       55726 :   GlobalHandles::Destroy(reinterpret_cast<Object**>(p));
     484             :   TRACE("}\n");
     485       55726 : }
     486             : 
     487      147392 : bool SyncValidate(Isolate* isolate, const ModuleWireBytes& bytes) {
     488      294784 :   if (bytes.start() == nullptr || bytes.length() == 0) return false;
     489             :   ModuleResult result = SyncDecodeWasmModule(isolate, bytes.start(),
     490      294784 :                                              bytes.end(), true, kWasmOrigin);
     491      147392 :   return result.ok();
     492             : }
     493             : 
     494        3547 : MaybeHandle<WasmModuleObject> SyncCompileTranslatedAsmJs(
     495             :     Isolate* isolate, ErrorThrower* thrower, const ModuleWireBytes& bytes,
     496             :     Handle<Script> asm_js_script,
     497             :     Vector<const byte> asm_js_offset_table_bytes) {
     498             :   ModuleResult result = SyncDecodeWasmModule(isolate, bytes.start(),
     499        7094 :                                              bytes.end(), false, kAsmJsOrigin);
     500        3547 :   if (result.failed()) {
     501             :     thrower->CompileFailed("Wasm decoding failed", result);
     502           0 :     return {};
     503             :   }
     504             : 
     505             :   // Transfer ownership of the WasmModule to the {WasmModuleWrapper} generated
     506             :   // in {CompileToModuleObject}.
     507             :   return ModuleCompiler::CompileToModuleObject(
     508             :       isolate, thrower, std::move(result.val), bytes, asm_js_script,
     509        7094 :       asm_js_offset_table_bytes);
     510             : }
     511             : 
     512      156720 : MaybeHandle<WasmModuleObject> SyncCompile(Isolate* isolate,
     513             :                                           ErrorThrower* thrower,
     514             :                                           const ModuleWireBytes& bytes) {
     515             :   // TODO(titzer): only make a copy of the bytes if SharedArrayBuffer
     516      156720 :   std::unique_ptr<byte[]> copy(new byte[bytes.length()]);
     517             :   memcpy(copy.get(), bytes.start(), bytes.length());
     518      156720 :   ModuleWireBytes bytes_copy(copy.get(), copy.get() + bytes.length());
     519             : 
     520             :   ModuleResult result = SyncDecodeWasmModule(
     521      470160 :       isolate, bytes_copy.start(), bytes_copy.end(), false, kWasmOrigin);
     522      156720 :   if (result.failed()) {
     523             :     thrower->CompileFailed("Wasm decoding failed", result);
     524        6713 :     return {};
     525             :   }
     526             : 
     527             :   // Transfer ownership of the WasmModule to the {WasmModuleWrapper} generated
     528             :   // in {CompileToModuleObject}.
     529             :   return ModuleCompiler::CompileToModuleObject(
     530             :       isolate, thrower, std::move(result.val), bytes_copy, Handle<Script>(),
     531      300014 :       Vector<const byte>());
     532             : }
     533             : 
     534      154148 : MaybeHandle<WasmInstanceObject> SyncInstantiate(
     535             :     Isolate* isolate, ErrorThrower* thrower,
     536             :     Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports,
     537             :     MaybeHandle<JSArrayBuffer> memory) {
     538             :   InstanceBuilder builder(isolate, thrower, module_object, imports, memory,
     539      154148 :                           &InstanceFinalizer);
     540      154148 :   return builder.Build();
     541             : }
     542             : 
     543         300 : MaybeHandle<WasmInstanceObject> SyncCompileAndInstantiate(
     544             :     Isolate* isolate, ErrorThrower* thrower, const ModuleWireBytes& bytes,
     545             :     MaybeHandle<JSReceiver> imports, MaybeHandle<JSArrayBuffer> memory) {
     546         300 :   MaybeHandle<WasmModuleObject> module = SyncCompile(isolate, thrower, bytes);
     547             :   DCHECK_EQ(thrower->error(), module.is_null());
     548         300 :   if (module.is_null()) return {};
     549             : 
     550             :   return SyncInstantiate(isolate, thrower, module.ToHandleChecked(),
     551             :                          Handle<JSReceiver>::null(),
     552         300 :                          Handle<JSArrayBuffer>::null());
     553             : }
     554             : 
     555         261 : void RejectPromise(Isolate* isolate, Handle<Context> context,
     556             :                    ErrorThrower& thrower, Handle<JSPromise> promise) {
     557             :   Local<Promise::Resolver> resolver =
     558             :       Utils::PromiseToLocal(promise).As<Promise::Resolver>();
     559             :   auto maybe = resolver->Reject(Utils::ToLocal(context),
     560         261 :                                 Utils::ToLocal(thrower.Reify()));
     561         261 :   CHECK_IMPLIES(!maybe.FromMaybe(false), isolate->has_scheduled_exception());
     562         261 : }
     563             : 
     564         615 : void ResolvePromise(Isolate* isolate, Handle<Context> context,
     565             :                     Handle<JSPromise> promise, Handle<Object> result) {
     566             :   Local<Promise::Resolver> resolver =
     567             :       Utils::PromiseToLocal(promise).As<Promise::Resolver>();
     568             :   auto maybe =
     569         615 :       resolver->Resolve(Utils::ToLocal(context), Utils::ToLocal(result));
     570         615 :   CHECK_IMPLIES(!maybe.FromMaybe(false), isolate->has_scheduled_exception());
     571         615 : }
     572             : 
     573           0 : void AsyncInstantiate(Isolate* isolate, Handle<JSPromise> promise,
     574             :                       Handle<WasmModuleObject> module_object,
     575             :                       MaybeHandle<JSReceiver> imports) {
     576             :   ErrorThrower thrower(isolate, nullptr);
     577             :   MaybeHandle<WasmInstanceObject> instance_object = SyncInstantiate(
     578           0 :       isolate, &thrower, module_object, imports, Handle<JSArrayBuffer>::null());
     579           0 :   if (thrower.error()) {
     580           0 :     RejectPromise(isolate, handle(isolate->context()), thrower, promise);
     581           0 :     return;
     582             :   }
     583             :   ResolvePromise(isolate, handle(isolate->context()), promise,
     584           0 :                  instance_object.ToHandleChecked());
     585             : }
     586             : 
     587        1586 : void AsyncCompile(Isolate* isolate, Handle<JSPromise> promise,
     588             :                   const ModuleWireBytes& bytes) {
     589         793 :   if (!FLAG_wasm_async_compilation) {
     590             :     ErrorThrower thrower(isolate, "WasmCompile");
     591             :     // Compile the module.
     592             :     MaybeHandle<WasmModuleObject> module_object =
     593         530 :         SyncCompile(isolate, &thrower, bytes);
     594         530 :     if (thrower.error()) {
     595          30 :       RejectPromise(isolate, handle(isolate->context()), thrower, promise);
     596          30 :       return;
     597             :     }
     598             :     Handle<WasmModuleObject> module = module_object.ToHandleChecked();
     599         500 :     ResolvePromise(isolate, handle(isolate->context()), promise, module);
     600         500 :     return;
     601             :   }
     602             : 
     603         263 :   if (FLAG_wasm_test_streaming) {
     604             :     std::shared_ptr<StreamingDecoder> streaming_decoder =
     605             :         isolate->wasm_compilation_manager()->StartStreamingCompilation(
     606         200 :             isolate, handle(isolate->context()), promise);
     607         200 :     streaming_decoder->OnBytesReceived(bytes.module_bytes());
     608         200 :     streaming_decoder->Finish();
     609             :     return;
     610             :   }
     611             :   // Make a copy of the wire bytes in case the user program changes them
     612             :   // during asynchronous compilation.
     613          63 :   std::unique_ptr<byte[]> copy(new byte[bytes.length()]);
     614             :   memcpy(copy.get(), bytes.start(), bytes.length());
     615             :   isolate->wasm_compilation_manager()->StartAsyncCompileJob(
     616             :       isolate, std::move(copy), bytes.length(), handle(isolate->context()),
     617         126 :       promise);
     618             : }
     619             : 
     620       11477 : Handle<Code> CompileLazy(Isolate* isolate) {
     621             :   HistogramTimerScope lazy_time_scope(
     622       11477 :       isolate->counters()->wasm_lazy_compilation_time());
     623             : 
     624             :   // Find the wasm frame which triggered the lazy compile, to get the wasm
     625             :   // instance.
     626       11477 :   StackFrameIterator it(isolate);
     627             :   // First frame: C entry stub.
     628             :   DCHECK(!it.done());
     629             :   DCHECK_EQ(StackFrame::EXIT, it.frame()->type());
     630       11477 :   it.Advance();
     631             :   // Second frame: WasmCompileLazy builtin.
     632             :   DCHECK(!it.done());
     633       11477 :   Handle<Code> lazy_compile_code(it.frame()->LookupCode(), isolate);
     634             :   DCHECK_EQ(Builtins::kWasmCompileLazy, lazy_compile_code->builtin_index());
     635             :   Handle<WasmInstanceObject> instance;
     636             :   Handle<FixedArray> exp_deopt_data;
     637             :   int func_index = -1;
     638       11477 :   if (lazy_compile_code->deoptimization_data()->length() > 0) {
     639             :     // Then it's an indirect call or via JS->wasm wrapper.
     640             :     DCHECK_LE(2, lazy_compile_code->deoptimization_data()->length());
     641             :     exp_deopt_data = handle(lazy_compile_code->deoptimization_data(), isolate);
     642             :     auto* weak_cell = WeakCell::cast(exp_deopt_data->get(0));
     643             :     instance = handle(WasmInstanceObject::cast(weak_cell->value()), isolate);
     644             :     func_index = Smi::ToInt(exp_deopt_data->get(1));
     645             :   }
     646       11477 :   it.Advance();
     647             :   // Third frame: The calling wasm code or js-to-wasm wrapper.
     648             :   DCHECK(!it.done());
     649             :   DCHECK(it.frame()->is_js_to_wasm() || it.frame()->is_wasm_compiled());
     650       11477 :   Handle<Code> caller_code = handle(it.frame()->LookupCode(), isolate);
     651       22954 :   if (it.frame()->is_js_to_wasm()) {
     652             :     DCHECK(!instance.is_null());
     653        3701 :   } else if (instance.is_null()) {
     654             :     // Then this is a direct call (otherwise we would have attached the instance
     655             :     // via deopt data to the lazy compile stub). Just use the instance of the
     656             :     // caller.
     657             :     instance =
     658        2963 :         handle(WasmInstanceObject::GetOwningInstance(*caller_code), isolate);
     659             :   }
     660             :   int offset =
     661       34431 :       static_cast<int>(it.frame()->pc() - caller_code->instruction_start());
     662             :   // Only patch the caller code if this is *no* indirect call.
     663             :   // exp_deopt_data will be null if the called function is not exported at all,
     664             :   // and its length will be <= 2 if all entries in tables were already patched.
     665             :   // Note that this check is conservative: If the first call to an exported
     666             :   // function is direct, we will just patch the export tables, and only on the
     667             :   // second call we will patch the caller.
     668        3701 :   bool patch_caller = caller_code->kind() == Code::JS_TO_WASM_FUNCTION ||
     669       12215 :                       exp_deopt_data.is_null() || exp_deopt_data->length() <= 2;
     670             : 
     671             :   Handle<Code> compiled_code = WasmCompiledModule::CompileLazy(
     672       11477 :       isolate, instance, caller_code, offset, func_index, patch_caller);
     673       19991 :   if (!exp_deopt_data.is_null() && exp_deopt_data->length() > 2) {
     674             :     // See EnsureExportedLazyDeoptData: exp_deopt_data[2...(len-1)] are pairs of
     675             :     // <export_table, index> followed by undefined values.
     676             :     // Use this information here to patch all export tables.
     677             :     DCHECK_EQ(0, exp_deopt_data->length() % 2);
     678        1154 :     for (int idx = 2, end = exp_deopt_data->length(); idx < end; idx += 2) {
     679         583 :       if (exp_deopt_data->get(idx)->IsUndefined(isolate)) break;
     680             :       FixedArray* exp_table = FixedArray::cast(exp_deopt_data->get(idx));
     681         583 :       int exp_index = Smi::ToInt(exp_deopt_data->get(idx + 1));
     682             :       DCHECK(exp_table->get(exp_index) == *lazy_compile_code);
     683         583 :       exp_table->set(exp_index, *compiled_code);
     684             :     }
     685             :     // After processing, remove the list of exported entries, such that we don't
     686             :     // do the patching redundantly.
     687             :     Handle<FixedArray> new_deopt_data =
     688         571 :         isolate->factory()->CopyFixedArrayUpTo(exp_deopt_data, 2, TENURED);
     689         571 :     lazy_compile_code->set_deoptimization_data(*new_deopt_data);
     690             :   }
     691             : 
     692       22954 :   return compiled_code;
     693             : }
     694             : 
     695       11259 : compiler::ModuleEnv CreateModuleEnvFromCompiledModule(
     696             :     Isolate* isolate, Handle<WasmCompiledModule> compiled_module) {
     697             :   DisallowHeapAllocation no_gc;
     698       11259 :   WasmModule* module = compiled_module->module();
     699             : 
     700             :   std::vector<GlobalHandleAddress> function_tables;
     701             :   std::vector<GlobalHandleAddress> signature_tables;
     702             : 
     703       22518 :   int num_function_tables = static_cast<int>(module->function_tables.size());
     704       14854 :   for (int i = 0; i < num_function_tables; ++i) {
     705             :     FixedArray* ft = compiled_module->ptr_to_function_tables();
     706             :     FixedArray* st = compiled_module->ptr_to_signature_tables();
     707             : 
     708             :     // TODO(clemensh): defer these handles for concurrent compilation.
     709        7190 :     function_tables.push_back(WasmCompiledModule::GetTableValue(ft, i));
     710        7190 :     signature_tables.push_back(WasmCompiledModule::GetTableValue(st, i));
     711             :   }
     712             : 
     713             :   std::vector<Handle<Code>> empty_code;
     714             : 
     715             :   compiler::ModuleEnv result = {module,            // --
     716             :                                 function_tables,   // --
     717             :                                 signature_tables,  // --
     718             :                                 empty_code,        // --
     719       11259 :                                 BUILTIN_CODE(isolate, WasmCompileLazy)};
     720       11259 :   return result;
     721             : }
     722             : 
     723       11477 : void LazyCompilationOrchestrator::CompileFunction(
     724       11259 :     Isolate* isolate, Handle<WasmInstanceObject> instance, int func_index) {
     725             :   base::ElapsedTimer compilation_timer;
     726             :   compilation_timer.Start();
     727             :   Handle<WasmCompiledModule> compiled_module(instance->compiled_module(),
     728             :                                              isolate);
     729       22954 :   if (Code::cast(compiled_module->code_table()->get(func_index))->kind() ==
     730             :       Code::WASM_FUNCTION) {
     731         218 :     return;
     732             :   }
     733             : 
     734             :   compiler::ModuleEnv module_env =
     735       11259 :       CreateModuleEnvFromCompiledModule(isolate, compiled_module);
     736             : 
     737       11259 :   const uint8_t* module_start = compiled_module->module_bytes()->GetChars();
     738             : 
     739       11259 :   const WasmFunction* func = &module_env.module->functions[func_index];
     740       11259 :   FunctionBody body{func->sig, func->code.offset(),
     741       11259 :                     module_start + func->code.offset(),
     742       45036 :                     module_start + func->code.end_offset()};
     743             :   // TODO(wasm): Refactor this to only get the name if it is really needed for
     744             :   // tracing / debugging.
     745             :   std::string func_name;
     746             :   {
     747             :     WasmName name = Vector<const char>::cast(
     748       22518 :         compiled_module->GetRawFunctionName(func_index));
     749             :     // Copy to std::string, because the underlying string object might move on
     750             :     // the heap.
     751       11259 :     func_name.assign(name.start(), static_cast<size_t>(name.length()));
     752             :   }
     753       11259 :   ErrorThrower thrower(isolate, "WasmLazyCompile");
     754             :   compiler::WasmCompilationUnit unit(isolate, &module_env, body,
     755             :                                      CStrVector(func_name.c_str()), func_index,
     756       45036 :                                      CEntryStub(isolate, 1).GetCode());
     757       11259 :   unit.ExecuteCompilation();
     758       11259 :   MaybeHandle<Code> maybe_code = unit.FinishCompilation(&thrower);
     759             : 
     760             :   // If there is a pending error, something really went wrong. The module was
     761             :   // verified before starting execution with lazy compilation.
     762             :   // This might be OOM, but then we cannot continue execution anyway.
     763             :   // TODO(clemensh): According to the spec, we can actually skip validation at
     764             :   // module creation time, and return a function that always traps here.
     765       22518 :   CHECK(!thrower.error());
     766             :   Handle<Code> code = maybe_code.ToHandleChecked();
     767             : 
     768       11259 :   Handle<FixedArray> deopt_data = isolate->factory()->NewFixedArray(2, TENURED);
     769       11259 :   Handle<WeakCell> weak_instance = isolate->factory()->NewWeakCell(instance);
     770             :   // TODO(wasm): Introduce constants for the indexes in wasm deopt data.
     771       11259 :   deopt_data->set(0, *weak_instance);
     772             :   deopt_data->set(1, Smi::FromInt(func_index));
     773       11259 :   code->set_deoptimization_data(*deopt_data);
     774             : 
     775             :   DCHECK_EQ(Builtins::kWasmCompileLazy,
     776             :             Code::cast(compiled_module->code_table()->get(func_index))
     777             :                 ->builtin_index());
     778       22518 :   compiled_module->code_table()->set(func_index, *code);
     779             : 
     780             :   // Now specialize the generated code for this instance.
     781       22518 :   Zone specialization_zone(isolate->allocator(), ZONE_NAME);
     782       22518 :   CodeSpecialization code_specialization(isolate, &specialization_zone);
     783       11259 :   code_specialization.RelocateDirectCalls(instance);
     784       11259 :   code_specialization.ApplyToWasmCode(*code, SKIP_ICACHE_FLUSH);
     785       11259 :   Assembler::FlushICache(isolate, code->instruction_start(),
     786       22518 :                          code->instruction_size());
     787             :   int64_t func_size =
     788       11259 :       static_cast<int64_t>(func->code.end_offset() - func->code.offset());
     789             :   int64_t compilation_time = compilation_timer.Elapsed().InMicroseconds();
     790             :   auto counters = isolate->counters();
     791       11259 :   counters->wasm_lazily_compiled_functions()->Increment();
     792       11259 :   counters->wasm_generated_code_size()->Increment(code->body_size());
     793       11259 :   counters->wasm_reloc_size()->Increment(code->relocation_info()->length());
     794             :   counters->wasm_lazy_compilation_throughput()->AddSample(
     795       11259 :       compilation_time != 0 ? static_cast<int>(func_size / compilation_time)
     796       33777 :                             : 0);
     797             : }
     798             : 
     799      158487 : int AdvanceSourcePositionTableIterator(SourcePositionTableIterator& iterator,
     800             :                                        int offset) {
     801             :   DCHECK(!iterator.done());
     802             :   int byte_pos;
     803       64607 :   do {
     804             :     byte_pos = iterator.source_position().ScriptOffset();
     805       64607 :     iterator.Advance();
     806      129214 :   } while (!iterator.done() && iterator.code_offset() <= offset);
     807       29273 :   return byte_pos;
     808             : }
     809             : 
     810       11477 : Handle<Code> LazyCompilationOrchestrator::CompileLazy(
     811             :     Isolate* isolate, Handle<WasmInstanceObject> instance, Handle<Code> caller,
     812             :     int call_offset, int exported_func_index, bool patch_caller) {
     813             :   struct NonCompiledFunction {
     814             :     int offset;
     815             :     int func_index;
     816             :   };
     817             :   std::vector<NonCompiledFunction> non_compiled_functions;
     818             :   int func_to_return_idx = exported_func_index;
     819             :   Decoder decoder(nullptr, nullptr);
     820       11477 :   bool is_js_to_wasm = caller->kind() == Code::JS_TO_WASM_FUNCTION;
     821             :   Handle<WasmCompiledModule> compiled_module(instance->compiled_module(),
     822             :                                              isolate);
     823             : 
     824       11477 :   if (is_js_to_wasm) {
     825       15552 :     non_compiled_functions.push_back({0, exported_func_index});
     826        3701 :   } else if (patch_caller) {
     827             :     DisallowHeapAllocation no_gc;
     828             :     SeqOneByteString* module_bytes = compiled_module->module_bytes();
     829             :     SourcePositionTableIterator source_pos_iterator(
     830        3136 :         caller->SourcePositionTable());
     831             :     DCHECK_EQ(2, caller->deoptimization_data()->length());
     832             :     int caller_func_index = Smi::ToInt(caller->deoptimization_data()->get(1));
     833             :     const byte* func_bytes =
     834        3136 :         module_bytes->GetChars() +
     835        9408 :         compiled_module->module()->functions[caller_func_index].code.offset();
     836       95583 :     for (RelocIterator it(*caller, RelocInfo::kCodeTargetMask); !it.done();
     837       89311 :          it.next()) {
     838             :       Code* callee =
     839       89311 :           Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
     840       89311 :       if (callee->builtin_index() != Builtins::kWasmCompileLazy) continue;
     841             :       // TODO(clemensh): Introduce safe_cast<T, bool> which (D)CHECKS
     842             :       // (depending on the bool) against limits of T and then static_casts.
     843       58546 :       size_t offset_l = it.rinfo()->pc() - caller->instruction_start();
     844             :       DCHECK_GE(kMaxInt, offset_l);
     845       29273 :       int offset = static_cast<int>(offset_l);
     846             :       int byte_pos =
     847       29273 :           AdvanceSourcePositionTableIterator(source_pos_iterator, offset);
     848             :       int called_func_index =
     849       29273 :           ExtractDirectCallIndex(decoder, func_bytes + byte_pos);
     850       58546 :       non_compiled_functions.push_back({offset, called_func_index});
     851             :       // Call offset one instruction after the call. Remember the last called
     852             :       // function before that offset.
     853       29273 :       if (offset < call_offset) func_to_return_idx = called_func_index;
     854             :     }
     855             :   }
     856             : 
     857             :   // TODO(clemensh): compile all functions in non_compiled_functions in
     858             :   // background, wait for func_to_return_idx.
     859       11477 :   CompileFunction(isolate, instance, func_to_return_idx);
     860             : 
     861       11477 :   if (is_js_to_wasm || patch_caller) {
     862             :     DisallowHeapAllocation no_gc;
     863             :     // Now patch the code object with all functions which are now compiled.
     864             :     int idx = 0;
     865      128264 :     for (RelocIterator it(*caller, RelocInfo::kCodeTargetMask); !it.done();
     866      106440 :          it.next()) {
     867             :       Code* callee =
     868      106440 :           Code::GetCodeFromTargetAddress(it.rinfo()->target_address());
     869      106440 :       if (callee->builtin_index() != Builtins::kWasmCompileLazy) continue;
     870             :       DCHECK_GT(non_compiled_functions.size(), idx);
     871       74098 :       int called_func_index = non_compiled_functions[idx].func_index;
     872             :       // Check that the callee agrees with our assumed called_func_index.
     873             :       DCHECK_IMPLIES(callee->deoptimization_data()->length() > 0,
     874             :                      Smi::ToInt(callee->deoptimization_data()->get(1)) ==
     875             :                          called_func_index);
     876             :       if (is_js_to_wasm) {
     877             :         DCHECK_EQ(func_to_return_idx, called_func_index);
     878             :       } else {
     879             :         DCHECK_EQ(non_compiled_functions[idx].offset,
     880             :                   it.rinfo()->pc() - caller->instruction_start());
     881             :       }
     882       37049 :       ++idx;
     883             :       Handle<Code> callee_compiled(
     884       74098 :           Code::cast(compiled_module->code_table()->get(called_func_index)));
     885       37049 :       if (callee_compiled->builtin_index() == Builtins::kWasmCompileLazy) {
     886             :         DCHECK_NE(func_to_return_idx, called_func_index);
     887             :         continue;
     888             :       }
     889             :       DCHECK_EQ(Code::WASM_FUNCTION, callee_compiled->kind());
     890             :       it.rinfo()->set_target_address(isolate,
     891       13695 :                                      callee_compiled->instruction_start());
     892             :     }
     893             :     DCHECK_EQ(non_compiled_functions.size(), idx);
     894             :   }
     895             : 
     896             :   Code* ret =
     897       22954 :       Code::cast(compiled_module->code_table()->get(func_to_return_idx));
     898             :   DCHECK_EQ(Code::WASM_FUNCTION, ret->kind());
     899       11477 :   return handle(ret, isolate);
     900             : }
     901             : 
     902           0 : ModuleCompiler::CodeGenerationSchedule::CodeGenerationSchedule(
     903             :     base::RandomNumberGenerator* random_number_generator, size_t max_memory)
     904             :     : random_number_generator_(random_number_generator),
     905      307618 :       max_memory_(max_memory) {
     906             :   DCHECK_NOT_NULL(random_number_generator_);
     907             :   DCHECK_GT(max_memory_, 0);
     908           0 : }
     909             : 
     910       38670 : void ModuleCompiler::CodeGenerationSchedule::Schedule(
     911             :     std::unique_ptr<compiler::WasmCompilationUnit>&& item) {
     912       38670 :   size_t cost = item->memory_cost();
     913       38670 :   schedule_.push_back(std::move(item));
     914             :   allocated_memory_.Increment(cost);
     915       38671 : }
     916             : 
     917           0 : bool ModuleCompiler::CodeGenerationSchedule::CanAcceptWork() const {
     918      120252 :   return (!throttle_ || allocated_memory_.Value() <= max_memory_);
     919             : }
     920             : 
     921          36 : bool ModuleCompiler::CodeGenerationSchedule::ShouldIncreaseWorkload() const {
     922             :   // Half the memory is unused again, we can increase the workload again.
     923          72 :   return (!throttle_ || allocated_memory_.Value() <= max_memory_ / 2);
     924             : }
     925             : 
     926             : std::unique_ptr<compiler::WasmCompilationUnit>
     927       38441 : ModuleCompiler::CodeGenerationSchedule::GetNext() {
     928             :   DCHECK(!IsEmpty());
     929       38441 :   size_t index = GetRandomIndexInSchedule();
     930      115323 :   auto ret = std::move(schedule_[index]);
     931       38441 :   std::swap(schedule_[schedule_.size() - 1], schedule_[index]);
     932       38441 :   schedule_.pop_back();
     933       38441 :   allocated_memory_.Decrement(ret->memory_cost());
     934       38441 :   return ret;
     935             : }
     936             : 
     937       38441 : size_t ModuleCompiler::CodeGenerationSchedule::GetRandomIndexInSchedule() {
     938       38441 :   double factor = random_number_generator_->NextDouble();
     939       76882 :   size_t index = (size_t)(factor * schedule_.size());
     940             :   DCHECK_GE(index, 0);
     941             :   DCHECK_LT(index, schedule_.size());
     942       38441 :   return index;
     943             : }
     944             : 
     945      153809 : ModuleCompiler::ModuleCompiler(Isolate* isolate, WasmModule* module,
     946             :                                Handle<Code> centry_stub)
     947             :     : isolate_(isolate),
     948             :       module_(module),
     949             :       async_counters_(isolate->async_counters()),
     950             :       executed_units_(
     951             :           isolate->random_number_generator(),
     952      153809 :           (isolate->heap()->memory_allocator()->code_range()->valid()
     953             :                ? isolate->heap()->memory_allocator()->code_range()->size()
     954           0 :                : isolate->heap()->code_space()->Capacity()) /
     955             :               2),
     956             :       num_background_tasks_(
     957             :           Min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks),
     958      153809 :               V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads())),
     959             :       stopped_compilation_tasks_(num_background_tasks_),
     960      922854 :       centry_stub_(centry_stub) {}
     961             : 
     962             : // The actual runnable task that performs compilations in the background.
     963       22205 : void ModuleCompiler::OnBackgroundTaskStopped() {
     964       22205 :   base::LockGuard<base::Mutex> guard(&tasks_mutex_);
     965       22205 :   ++stopped_compilation_tasks_;
     966             :   DCHECK_LE(stopped_compilation_tasks_, num_background_tasks_);
     967       22198 : }
     968             : 
     969             : // Run by each compilation task The no_finisher_callback is called
     970             : // within the result_mutex_ lock when no finishing task is running,
     971             : // i.e. when the finisher_is_running_ flag is not set.
     972       64531 : bool ModuleCompiler::FetchAndExecuteCompilationUnit(
     973             :     std::function<void()> no_finisher_callback) {
     974             :   DisallowHeapAllocation no_allocation;
     975             :   DisallowHandleAllocation no_handles;
     976             :   DisallowHandleDereference no_deref;
     977             :   DisallowCodeDependencyChange no_dependency_change;
     978             : 
     979       64531 :   std::unique_ptr<compiler::WasmCompilationUnit> unit;
     980             :   {
     981       64531 :     base::LockGuard<base::Mutex> guard(&compilation_units_mutex_);
     982       64591 :     if (compilation_units_.empty()) return false;
     983             :     unit = std::move(compilation_units_.back());
     984       38671 :     compilation_units_.pop_back();
     985             :   }
     986       38671 :   unit->ExecuteCompilation();
     987             :   {
     988       38541 :     base::LockGuard<base::Mutex> guard(&result_mutex_);
     989       38671 :     executed_units_.Schedule(std::move(unit));
     990       38671 :     if (no_finisher_callback != nullptr && !finisher_is_running_) {
     991         199 :       no_finisher_callback();
     992             :       // We set the flag here so that not more than one finisher is started.
     993         199 :       finisher_is_running_ = true;
     994             :     }
     995             :   }
     996       38671 :   return true;
     997             : }
     998             : 
     999        3425 : size_t ModuleCompiler::InitializeCompilationUnits(
    1000       41731 :     const std::vector<WasmFunction>& functions,
    1001             :     const ModuleWireBytes& wire_bytes, compiler::ModuleEnv* module_env) {
    1002        3425 :   uint32_t start = module_env->module->num_imported_functions +
    1003        3425 :                    FLAG_skip_compiling_wasm_funcs;
    1004        3425 :   uint32_t num_funcs = static_cast<uint32_t>(functions.size());
    1005        3425 :   uint32_t funcs_to_compile = start > num_funcs ? 0 : num_funcs - start;
    1006             :   CompilationUnitBuilder builder(this);
    1007       41731 :   for (uint32_t i = start; i < num_funcs; ++i) {
    1008       38306 :     const WasmFunction* func = &functions[i];
    1009       38306 :     uint32_t buffer_offset = func->code.offset();
    1010             :     Vector<const uint8_t> bytes(wire_bytes.start() + func->code.offset(),
    1011       76612 :                                 func->code.end_offset() - func->code.offset());
    1012       38306 :     WasmName name = wire_bytes.GetName(func);
    1013       38306 :     builder.AddUnit(module_env, func, buffer_offset, bytes, name);
    1014             :   }
    1015        3425 :   builder.Commit();
    1016        6850 :   return funcs_to_compile;
    1017             : }
    1018             : 
    1019        4005 : void ModuleCompiler::RestartCompilationTasks() {
    1020        4005 :   base::LockGuard<base::Mutex> guard(&tasks_mutex_);
    1021       23548 :   for (; stopped_compilation_tasks_ > 0; --stopped_compilation_tasks_) {
    1022       23548 :     V8::GetCurrentPlatform()->CallOnBackgroundThread(
    1023             :         new CompilationTask(this),
    1024       47096 :         v8::Platform::ExpectedRuntime::kShortRunningTask);
    1025             :   }
    1026        4005 : }
    1027             : 
    1028        4466 : size_t ModuleCompiler::FinishCompilationUnits(
    1029       36981 :     std::vector<Handle<Code>>& results, ErrorThrower* thrower) {
    1030             :   size_t finished = 0;
    1031             :   while (true) {
    1032       41447 :     int func_index = -1;
    1033       41447 :     MaybeHandle<Code> result = FinishCompilationUnit(thrower, &func_index);
    1034       41447 :     if (func_index < 0) break;
    1035       37111 :     ++finished;
    1036             :     DCHECK_IMPLIES(result.is_null(), thrower->error());
    1037       37111 :     if (result.is_null()) break;
    1038       73962 :     results[func_index] = result.ToHandleChecked();
    1039             :   }
    1040             :   bool do_restart;
    1041             :   {
    1042        4466 :     base::LockGuard<base::Mutex> guard(&compilation_units_mutex_);
    1043             :     do_restart = !compilation_units_.empty();
    1044             :   }
    1045        4466 :   if (do_restart) RestartCompilationTasks();
    1046       41447 :   return finished;
    1047             : }
    1048             : 
    1049           0 : void ModuleCompiler::SetFinisherIsRunning(bool value) {
    1050         195 :   base::LockGuard<base::Mutex> guard(&result_mutex_);
    1051         195 :   finisher_is_running_ = value;
    1052           0 : }
    1053             : 
    1054       42930 : MaybeHandle<Code> ModuleCompiler::FinishCompilationUnit(ErrorThrower* thrower,
    1055             :                                                         int* func_index) {
    1056             :   std::unique_ptr<compiler::WasmCompilationUnit> unit;
    1057             :   {
    1058       42930 :     base::LockGuard<base::Mutex> guard(&result_mutex_);
    1059       42930 :     if (executed_units_.IsEmpty()) return {};
    1060       76882 :     unit = executed_units_.GetNext();
    1061             :   }
    1062       38441 :   *func_index = unit->func_index();
    1063       38441 :   return unit->FinishCompilation(thrower);
    1064             : }
    1065             : 
    1066        3364 : void ModuleCompiler::CompileInParallel(const ModuleWireBytes& wire_bytes,
    1067             :                                        compiler::ModuleEnv* module_env,
    1068             :                                        std::vector<Handle<Code>>& results,
    1069             :                                        ErrorThrower* thrower) {
    1070        3364 :   const WasmModule* module = module_env->module;
    1071             :   // Data structures for the parallel compilation.
    1072             : 
    1073             :   //-----------------------------------------------------------------------
    1074             :   // For parallel compilation:
    1075             :   // 1) The main thread allocates a compilation unit for each wasm function
    1076             :   //    and stores them in the vector {compilation_units}.
    1077             :   // 2) The main thread spawns {CompilationTask} instances which run on
    1078             :   //    the background threads.
    1079             :   // 3.a) The background threads and the main thread pick one compilation
    1080             :   //      unit at a time and execute the parallel phase of the compilation
    1081             :   //      unit. After finishing the execution of the parallel phase, the
    1082             :   //      result is enqueued in {executed_units}.
    1083             :   // 3.b) If {executed_units} contains a compilation unit, the main thread
    1084             :   //      dequeues it and finishes the compilation.
    1085             :   // 4) After the parallel phase of all compilation units has started, the
    1086             :   //    main thread waits for all {CompilationTask} instances to finish.
    1087             :   // 5) The main thread finishes the compilation.
    1088             : 
    1089             :   // Turn on the {CanonicalHandleScope} so that the background threads can
    1090             :   // use the node cache.
    1091        3364 :   CanonicalHandleScope canonical(isolate_);
    1092             : 
    1093             :   // 1) The main thread allocates a compilation unit for each wasm function
    1094             :   //    and stores them in the vector {compilation_units}.
    1095        3364 :   InitializeCompilationUnits(module->functions, wire_bytes, module_env);
    1096             :   executed_units_.EnableThrottling();
    1097             : 
    1098             :   // 2) The main thread spawns {CompilationTask} instances which run on
    1099             :   //    the background threads.
    1100        3364 :   RestartCompilationTasks();
    1101             : 
    1102             :   // 3.a) The background threads and the main thread pick one compilation
    1103             :   //      unit at a time and execute the parallel phase of the compilation
    1104             :   //      unit. After finishing the execution of the parallel phase, the
    1105             :   //      result is enqueued in {executed_units}.
    1106             :   //      The foreground task bypasses waiting on memory threshold, because
    1107             :   //      its results will immediately be converted to code (below).
    1108       12296 :   while (FetchAndExecuteCompilationUnit()) {
    1109             :     // 3.b) If {executed_units} contains a compilation unit, the main thread
    1110             :     //      dequeues it and finishes the compilation unit. Compilation units
    1111             :     //      are finished concurrently to the background threads to save
    1112             :     //      memory.
    1113        1102 :     FinishCompilationUnits(results, thrower);
    1114             :   }
    1115             :   // 4) After the parallel phase of all compilation units has started, the
    1116             :   //    main thread waits for all {CompilationTask} instances to finish - which
    1117             :   //    happens once they all realize there's no next work item to process.
    1118        3364 :   background_task_manager_.CancelAndWait();
    1119             :   // Finish all compilation units which have been executed while we waited.
    1120        3364 :   FinishCompilationUnits(results, thrower);
    1121        3364 : }
    1122             : 
    1123      146609 : void ModuleCompiler::CompileSequentially(const ModuleWireBytes& wire_bytes,
    1124             :                                          compiler::ModuleEnv* module_env,
    1125      137964 :                                          std::vector<Handle<Code>>& results,
    1126             :                                          ErrorThrower* thrower) {
    1127             :   DCHECK(!thrower->error());
    1128             : 
    1129      146609 :   const WasmModule* module = module_env->module;
    1130      839896 :   for (uint32_t i = FLAG_skip_compiling_wasm_funcs;
    1131      419948 :        i < module->functions.size(); ++i) {
    1132      419948 :     const WasmFunction& func = module->functions[i];
    1133      278910 :     if (func.imported) continue;  // Imports are compiled at instantiation time.
    1134             : 
    1135             :     // Compile the function.
    1136             :     MaybeHandle<Code> code = compiler::WasmCompilationUnit::CompileWasmFunction(
    1137      143535 :         thrower, isolate_, wire_bytes, module_env, &func);
    1138      143535 :     if (code.is_null()) {
    1139             :       TruncatedUserString<> name(wire_bytes.GetName(&func));
    1140             :       thrower->CompileError("Compilation of #%d:%.*s failed.", i, name.length(),
    1141        5571 :                             name.start());
    1142             :       break;
    1143             :     }
    1144      137964 :     results[i] = code.ToHandleChecked();
    1145             :   }
    1146      146609 : }
    1147             : 
    1148          40 : void ModuleCompiler::ValidateSequentially(const ModuleWireBytes& wire_bytes,
    1149             :                                           compiler::ModuleEnv* module_env,
    1150             :                                           ErrorThrower* thrower) {
    1151             :   DCHECK(!thrower->error());
    1152             : 
    1153          80 :   const WasmModule* module = module_env->module;
    1154         140 :   for (uint32_t i = 0; i < module->functions.size(); ++i) {
    1155          70 :     const WasmFunction& func = module->functions[i];
    1156          40 :     if (func.imported) continue;
    1157             : 
    1158             :     const byte* base = wire_bytes.start();
    1159          80 :     FunctionBody body{func.sig, func.code.offset(), base + func.code.offset(),
    1160         160 :                       base + func.code.end_offset()};
    1161             :     DecodeResult result = VerifyWasmCodeWithStats(
    1162          80 :         isolate_->allocator(), module, body, module->is_wasm(), counters());
    1163          40 :     if (result.failed()) {
    1164             :       TruncatedUserString<> name(wire_bytes.GetName(&func));
    1165             :       thrower->CompileError("Compiling function #%d:%.*s failed: %s @+%u", i,
    1166             :                             name.length(), name.start(),
    1167          10 :                             result.error_msg().c_str(), result.error_offset());
    1168             :       break;
    1169             :     }
    1170             :   }
    1171          40 : }
    1172             : 
    1173             : // static
    1174      153554 : MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObject(
    1175             :     Isolate* isolate, ErrorThrower* thrower, std::unique_ptr<WasmModule> module,
    1176             :     const ModuleWireBytes& wire_bytes, Handle<Script> asm_js_script,
    1177             :     Vector<const byte> asm_js_offset_table_bytes) {
    1178      307108 :   Handle<Code> centry_stub = CEntryStub(isolate, 1).GetCode();
    1179      153554 :   ModuleCompiler compiler(isolate, module.get(), centry_stub);
    1180             :   return compiler.CompileToModuleObjectInternal(thrower, std::move(module),
    1181             :                                                 wire_bytes, asm_js_script,
    1182      307108 :                                                 asm_js_offset_table_bytes);
    1183             : }
    1184             : 
    1185             : namespace {
    1186      155062 : bool compile_lazy(const WasmModule* module) {
    1187      155384 :   return FLAG_wasm_lazy_compilation ||
    1188      155062 :          (FLAG_asm_wasm_lazy_compilation && module->is_asm_js());
    1189             : }
    1190             : 
    1191      305324 : void FlushICache(Isolate* isolate, Handle<FixedArray> code_table) {
    1192     1688864 :   for (int i = 0; i < code_table->length(); ++i) {
    1193      539108 :     Handle<Code> code = code_table->GetValueChecked<Code>(isolate, i);
    1194      539108 :     Assembler::FlushICache(isolate, code->instruction_start(),
    1195     1078216 :                            code->instruction_size());
    1196             :   }
    1197      305324 : }
    1198             : 
    1199       11140 : byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) {
    1200       11140 :   return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset;
    1201             : }
    1202             : 
    1203      533509 : void RecordStats(Code* code, Counters* counters) {
    1204      533509 :   counters->wasm_generated_code_size()->Increment(code->body_size());
    1205      533509 :   counters->wasm_reloc_size()->Increment(code->relocation_info()->length());
    1206      533509 : }
    1207             : 
    1208       13250 : void RecordStats(Handle<FixedArray> functions, Counters* counters) {
    1209             :   DisallowHeapAllocation no_gc;
    1210       84210 :   for (int i = 0; i < functions->length(); ++i) {
    1211             :     Object* val = functions->get(i);
    1212       28855 :     if (val->IsCode()) RecordStats(Code::cast(val), counters);
    1213             :   }
    1214       13250 : }
    1215      144411 : Handle<Script> CreateWasmScript(Isolate* isolate,
    1216             :                                 const ModuleWireBytes& wire_bytes) {
    1217             :   Handle<Script> script =
    1218      144411 :       isolate->factory()->NewScript(isolate->factory()->empty_string());
    1219      288822 :   script->set_context_data(isolate->native_context()->debug_context_id());
    1220             :   script->set_type(Script::TYPE_WASM);
    1221             : 
    1222             :   int hash = StringHasher::HashSequentialString(
    1223             :       reinterpret_cast<const char*>(wire_bytes.start()),
    1224      144411 :       static_cast<int>(wire_bytes.length()), kZeroHashSeed);
    1225             : 
    1226             :   const int kBufferSize = 32;
    1227             :   char buffer[kBufferSize];
    1228      144411 :   int url_chars = SNPrintF(ArrayVector(buffer), "wasm://wasm/%08x", hash);
    1229             :   DCHECK(url_chars >= 0 && url_chars < kBufferSize);
    1230             :   MaybeHandle<String> url_str = isolate->factory()->NewStringFromOneByte(
    1231             :       Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), url_chars),
    1232      288822 :       TENURED);
    1233      144411 :   script->set_source_url(*url_str.ToHandleChecked());
    1234             : 
    1235      144411 :   int name_chars = SNPrintF(ArrayVector(buffer), "wasm-%08x", hash);
    1236             :   DCHECK(name_chars >= 0 && name_chars < kBufferSize);
    1237             :   MaybeHandle<String> name_str = isolate->factory()->NewStringFromOneByte(
    1238             :       Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), name_chars),
    1239      288822 :       TENURED);
    1240      144411 :   script->set_name(*name_str.ToHandleChecked());
    1241             : 
    1242      144411 :   return script;
    1243             : }
    1244             : 
    1245             : // Ensure that the code object in <code_table> at offset <func_index> has
    1246             : // deoptimization data attached. This is needed for lazy compile stubs which are
    1247             : // called from JS_TO_WASM functions or via exported function tables. The deopt
    1248             : // data is used to determine which function this lazy compile stub belongs to.
    1249      194766 : Handle<Code> EnsureExportedLazyDeoptData(Isolate* isolate,
    1250             :                                          Handle<WasmInstanceObject> instance,
    1251             :                                          Handle<FixedArray> code_table,
    1252             :                                          int func_index) {
    1253             :   Handle<Code> code(Code::cast(code_table->get(func_index)), isolate);
    1254      194766 :   if (code->builtin_index() != Builtins::kWasmCompileLazy) {
    1255             :     // No special deopt data needed for compiled functions, and imported
    1256             :     // functions, which map to Illegal at this point (they get compiled at
    1257             :     // instantiation time).
    1258             :     DCHECK(code->kind() == Code::WASM_FUNCTION ||
    1259             :            code->kind() == Code::WASM_TO_JS_FUNCTION ||
    1260             :            code->builtin_index() == Builtins::kIllegal);
    1261      178757 :     return code;
    1262             :   }
    1263             :   // deopt_data:
    1264             :   //   #0: weak instance
    1265             :   //   #1: func_index
    1266             :   // might be extended later for table exports (see
    1267             :   // EnsureTableExportLazyDeoptData).
    1268             :   Handle<FixedArray> deopt_data(code->deoptimization_data());
    1269             :   DCHECK_EQ(0, deopt_data->length() % 2);
    1270       16009 :   if (deopt_data->length() == 0) {
    1271       12918 :     code = isolate->factory()->CopyCode(code);
    1272       12918 :     code_table->set(func_index, *code);
    1273       12918 :     deopt_data = isolate->factory()->NewFixedArray(2, TENURED);
    1274       12918 :     code->set_deoptimization_data(*deopt_data);
    1275       12918 :     if (!instance.is_null()) {
    1276             :       Handle<WeakCell> weak_instance =
    1277        6843 :           isolate->factory()->NewWeakCell(instance);
    1278        6843 :       deopt_data->set(0, *weak_instance);
    1279             :     }
    1280             :     deopt_data->set(1, Smi::FromInt(func_index));
    1281             :   }
    1282             :   DCHECK_IMPLIES(!instance.is_null(),
    1283             :                  WeakCell::cast(code->deoptimization_data()->get(0))->value() ==
    1284             :                      *instance);
    1285             :   DCHECK_EQ(func_index, Smi::ToInt(code->deoptimization_data()->get(1)));
    1286       16009 :   return code;
    1287             : }
    1288             : 
    1289             : // Ensure that the code object in <code_table> at offset <func_index> has
    1290             : // deoptimization data attached. This is needed for lazy compile stubs which are
    1291             : // called from JS_TO_WASM functions or via exported function tables. The deopt
    1292             : // data is used to determine which function this lazy compile stub belongs to.
    1293        9582 : Handle<Code> EnsureTableExportLazyDeoptData(
    1294             :     Isolate* isolate, Handle<WasmInstanceObject> instance,
    1295             :     Handle<FixedArray> code_table, int func_index,
    1296             :     Handle<FixedArray> export_table, int export_index,
    1297             :     std::unordered_map<uint32_t, uint32_t>& table_export_count) {
    1298             :   Handle<Code> code =
    1299        9582 :       EnsureExportedLazyDeoptData(isolate, instance, code_table, func_index);
    1300        9582 :   if (code->builtin_index() != Builtins::kWasmCompileLazy) return code;
    1301             : 
    1302             :   // deopt_data:
    1303             :   // #0: weak instance
    1304             :   // #1: func_index
    1305             :   // [#2: export table
    1306             :   //  #3: export table index]
    1307             :   // [#4: export table
    1308             :   //  #5: export table index]
    1309             :   // ...
    1310             :   // table_export_count counts down and determines the index for the new export
    1311             :   // table entry.
    1312       13086 :   auto table_export_entry = table_export_count.find(func_index);
    1313             :   DCHECK(table_export_entry != table_export_count.end());
    1314             :   DCHECK_LT(0, table_export_entry->second);
    1315        6543 :   uint32_t this_idx = 2 * table_export_entry->second;
    1316        6543 :   --table_export_entry->second;
    1317             :   Handle<FixedArray> deopt_data(code->deoptimization_data());
    1318             :   DCHECK_EQ(0, deopt_data->length() % 2);
    1319        6543 :   if (deopt_data->length() == 2) {
    1320             :     // Then only the "header" (#0 and #1) exists. Extend for the export table
    1321             :     // entries (make space for this_idx + 2 elements).
    1322             :     deopt_data = isolate->factory()->CopyFixedArrayAndGrow(deopt_data, this_idx,
    1323        4486 :                                                            TENURED);
    1324        4486 :     code->set_deoptimization_data(*deopt_data);
    1325             :   }
    1326             :   DCHECK_LE(this_idx + 2, deopt_data->length());
    1327             :   DCHECK(deopt_data->get(this_idx)->IsUndefined(isolate));
    1328             :   DCHECK(deopt_data->get(this_idx + 1)->IsUndefined(isolate));
    1329       13086 :   deopt_data->set(this_idx, *export_table);
    1330        6543 :   deopt_data->set(this_idx + 1, Smi::FromInt(export_index));
    1331        6543 :   return code;
    1332             : }
    1333             : 
    1334             : bool in_bounds(uint32_t offset, uint32_t size, uint32_t upper) {
    1335        2130 :   return offset + size <= upper && offset + size >= offset;
    1336             : }
    1337             : 
    1338             : using WasmInstanceMap =
    1339             :     IdentityMap<Handle<WasmInstanceObject>, FreeStoreAllocationPolicy>;
    1340             : 
    1341      133885 : Handle<Code> MakeWasmToWasmWrapper(
    1342             :     Isolate* isolate, Handle<WasmExportedFunction> imported_function,
    1343             :     FunctionSig* expected_sig, FunctionSig** sig,
    1344             :     WasmInstanceMap* imported_instances, Handle<WasmInstanceObject> instance) {
    1345             :   // TODO(wasm): cache WASM-to-WASM wrappers by signature and clone+patch.
    1346             :   Handle<WasmInstanceObject> imported_instance(imported_function->instance(),
    1347      133885 :                                                isolate);
    1348             :   imported_instances->Set(imported_instance, imported_instance);
    1349      133885 :   Handle<Code> wasm_code = imported_function->GetWasmCode();
    1350             :   WasmContext* new_wasm_context = imported_instance->wasm_context()->get();
    1351             :   Address new_wasm_context_address =
    1352             :       reinterpret_cast<Address>(new_wasm_context);
    1353      133885 :   *sig = imported_instance->module()
    1354      267770 :              ->functions[imported_function->function_index()]
    1355      133885 :              .sig;
    1356      133885 :   if (expected_sig && !expected_sig->Equals(*sig)) return Handle<Code>::null();
    1357             : 
    1358             :   Handle<Code> wrapper_code = compiler::CompileWasmToWasmWrapper(
    1359      133665 :       isolate, wasm_code, *sig, imported_function->function_index(),
    1360      133665 :       new_wasm_context_address);
    1361             :   // Set the deoptimization data for the WasmToWasm wrapper. This is
    1362             :   // needed by the interpreter to find the imported instance for
    1363             :   // a cross-instance call.
    1364             :   Factory* factory = isolate->factory();
    1365      133665 :   Handle<WeakCell> weak_link = factory->NewWeakCell(imported_instance);
    1366      133665 :   Handle<FixedArray> deopt_data = factory->NewFixedArray(2, TENURED);
    1367      133665 :   deopt_data->set(0, *weak_link);
    1368      133665 :   auto function_index = Smi::FromInt(imported_function->function_index());
    1369             :   deopt_data->set(1, function_index);
    1370      133665 :   wrapper_code->set_deoptimization_data(*deopt_data);
    1371      133665 :   return wrapper_code;
    1372             : }
    1373             : 
    1374      142795 : Handle<Code> UnwrapExportOrCompileImportWrapper(
    1375             :     Isolate* isolate, FunctionSig* sig, Handle<JSReceiver> target,
    1376             :     uint32_t import_index, ModuleOrigin origin,
    1377             :     WasmInstanceMap* imported_instances, Handle<FixedArray> js_imports_table,
    1378             :     Handle<WasmInstanceObject> instance) {
    1379      142795 :   if (WasmExportedFunction::IsWasmExportedFunction(*target)) {
    1380      131265 :     FunctionSig* unused = nullptr;
    1381             :     return MakeWasmToWasmWrapper(isolate,
    1382             :                                  Handle<WasmExportedFunction>::cast(target),
    1383      131265 :                                  sig, &unused, imported_instances, instance);
    1384             :   }
    1385             :   // No wasm function or being debugged. Compile a new wrapper for the new
    1386             :   // signature.
    1387             :   return compiler::CompileWasmToJSWrapper(isolate, target, sig, import_index,
    1388       11530 :                                           origin, js_imports_table);
    1389             : }
    1390             : 
    1391        1485 : double MonotonicallyIncreasingTimeInMs() {
    1392        1485 :   return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() *
    1393        1485 :          base::Time::kMillisecondsPerSecond;
    1394             : }
    1395             : 
    1396       56532 : void FunctionTableFinalizer(const v8::WeakCallbackInfo<void>& data) {
    1397             :   GlobalHandles::Destroy(reinterpret_cast<Object**>(
    1398       56532 :       reinterpret_cast<JSObject**>(data.GetParameter())));
    1399       56532 : }
    1400             : 
    1401      153809 : std::unique_ptr<compiler::ModuleEnv> CreateDefaultModuleEnv(
    1402        3480 :     Isolate* isolate, WasmModule* module, Handle<Code> illegal_builtin) {
    1403             :   std::vector<GlobalHandleAddress> function_tables;
    1404             :   std::vector<GlobalHandleAddress> signature_tables;
    1405             : 
    1406      311098 :   for (size_t i = 0; i < module->function_tables.size(); i++) {
    1407             :     Handle<Object> func_table =
    1408        1740 :         isolate->global_handles()->Create(isolate->heap()->undefined_value());
    1409             :     Handle<Object> sig_table =
    1410        1740 :         isolate->global_handles()->Create(isolate->heap()->undefined_value());
    1411             :     GlobalHandles::MakeWeak(func_table.location(), func_table.location(),
    1412             :                             &FunctionTableFinalizer,
    1413        1740 :                             v8::WeakCallbackType::kFinalizer);
    1414             :     GlobalHandles::MakeWeak(sig_table.location(), sig_table.location(),
    1415             :                             &FunctionTableFinalizer,
    1416        1740 :                             v8::WeakCallbackType::kFinalizer);
    1417        3480 :     function_tables.push_back(func_table.address());
    1418        3480 :     signature_tables.push_back(sig_table.address());
    1419             :   }
    1420             : 
    1421             :   std::vector<Handle<Code>> empty_code;
    1422             : 
    1423             :   compiler::ModuleEnv result = {
    1424             :       module,            // --
    1425             :       function_tables,   // --
    1426             :       signature_tables,  // --
    1427             :       empty_code,        // --
    1428             :       illegal_builtin    // --
    1429      307618 :   };
    1430      307618 :   return std::unique_ptr<compiler::ModuleEnv>(new compiler::ModuleEnv(result));
    1431             : }
    1432             : 
    1433             : Handle<WasmCompiledModule> NewCompiledModule(
    1434             :     Isolate* isolate, Handle<WasmSharedModuleData> shared,
    1435             :     Handle<FixedArray> code_table, Handle<FixedArray> export_wrappers,
    1436             :     compiler::ModuleEnv* env) {
    1437             :   Handle<WasmCompiledModule> compiled_module =
    1438             :       WasmCompiledModule::New(isolate, shared, code_table, export_wrappers,
    1439      147958 :                               env->function_tables, env->signature_tables);
    1440      147958 :   return compiled_module;
    1441             : }
    1442             : 
    1443             : template <typename T>
    1444         255 : void ReopenHandles(Isolate* isolate, const std::vector<Handle<T>>& vec) {
    1445         255 :   auto& mut = const_cast<std::vector<Handle<T>>&>(vec);
    1446         510 :   for (size_t i = 0; i < mut.size(); i++) {
    1447           0 :     mut[i] = Handle<T>(*mut[i], isolate);
    1448             :   }
    1449         255 : }
    1450             : 
    1451             : }  // namespace
    1452             : 
    1453      153554 : MaybeHandle<WasmModuleObject> ModuleCompiler::CompileToModuleObjectInternal(
    1454      297826 :     ErrorThrower* thrower, std::unique_ptr<WasmModule> module,
    1455             :     const ModuleWireBytes& wire_bytes, Handle<Script> asm_js_script,
    1456             :     Vector<const byte> asm_js_offset_table_bytes) {
    1457             :   TimedHistogramScope wasm_compile_module_time_scope(
    1458      157135 :       module_->is_wasm() ? counters()->wasm_compile_wasm_module_time()
    1459      307108 :                          : counters()->wasm_compile_asm_module_time());
    1460             :   // The {module> parameter is passed in to transfer ownership of the WasmModule
    1461             :   // to this function. The WasmModule itself existed already as an instance
    1462             :   // variable of the ModuleCompiler. We check here that the parameter and the
    1463             :   // instance variable actually point to the same object.
    1464             :   DCHECK_EQ(module.get(), module_);
    1465             :   // Check whether lazy compilation is enabled for this module.
    1466      153554 :   bool lazy_compile = compile_lazy(module_);
    1467             : 
    1468      297850 :   Factory* factory = isolate_->factory();
    1469             : 
    1470             :   // If lazy compile: Initialize the code table with the lazy compile builtin.
    1471             :   // Otherwise: Initialize with the illegal builtin. All call sites will be
    1472             :   // patched at instantiation.
    1473             :   Handle<Code> init_builtin = lazy_compile
    1474        3581 :                                   ? BUILTIN_CODE(isolate_, WasmCompileLazy)
    1475      157135 :                                   : BUILTIN_CODE(isolate_, Illegal);
    1476             : 
    1477      153554 :   auto env = CreateDefaultModuleEnv(isolate_, module_, init_builtin);
    1478             : 
    1479             :   // The {code_table} array contains import wrappers and functions (which
    1480             :   // are both included in {functions.size()}, and export wrappers).
    1481      457081 :   int code_table_size = static_cast<int>(module_->functions.size());
    1482      153554 :   int export_wrappers_size = static_cast<int>(module_->num_exported_functions);
    1483             :   Handle<FixedArray> code_table =
    1484      153554 :       factory->NewFixedArray(static_cast<int>(code_table_size), TENURED);
    1485             :   Handle<FixedArray> export_wrappers =
    1486      153554 :       factory->NewFixedArray(static_cast<int>(export_wrappers_size), TENURED);
    1487             :   // Initialize the code table.
    1488      492136 :   for (int i = 0, e = code_table->length(); i < e; ++i) {
    1489      338582 :     code_table->set(i, *init_builtin);
    1490             :   }
    1491             : 
    1492      332480 :   for (int i = 0, e = export_wrappers->length(); i < e; ++i) {
    1493      178926 :     export_wrappers->set(i, *init_builtin);
    1494             :   }
    1495             : 
    1496      153554 :   if (!lazy_compile) {
    1497             :     size_t funcs_to_compile =
    1498      299946 :         module_->functions.size() - module_->num_imported_functions;
    1499             :     bool compile_parallel =
    1500      299946 :         !FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks > 0 &&
    1501      153337 :         funcs_to_compile > 1 &&
    1502        3364 :         V8::GetCurrentPlatform()->NumberOfAvailableBackgroundThreads() > 0;
    1503             :     // Avoid a race condition by collecting results into a second vector.
    1504      299946 :     std::vector<Handle<Code>> results(env->module->functions.size());
    1505             : 
    1506      149973 :     if (compile_parallel) {
    1507        3364 :       CompileInParallel(wire_bytes, env.get(), results, thrower);
    1508             :     } else {
    1509      146609 :       CompileSequentially(wire_bytes, env.get(), results, thrower);
    1510             :     }
    1511      149973 :     if (thrower->error()) return {};
    1512             : 
    1513             :     // At this point, compilation has completed. Update the code table.
    1514      638260 :     for (size_t i =
    1515      144272 :              module_->num_imported_functions + FLAG_skip_compiling_wasm_funcs;
    1516      319130 :          i < results.size(); ++i) {
    1517             :       Code* code = *results[i];
    1518      349716 :       code_table->set(static_cast<int>(i), code);
    1519      174858 :       RecordStats(code, counters());
    1520             :     }
    1521        7162 :   } else if (module_->is_wasm()) {
    1522             :     // Validate wasm modules for lazy compilation. Don't validate asm.js
    1523             :     // modules, they are valid by construction (otherwise a CHECK will fail
    1524             :     // during lazy compilation).
    1525             :     // TODO(clemensh): According to the spec, we can actually skip validation
    1526             :     // at module creation time, and return a function that always traps at
    1527             :     // (lazy) compilation time.
    1528          40 :     ValidateSequentially(wire_bytes, env.get(), thrower);
    1529             :   }
    1530      147853 :   if (thrower->error()) return {};
    1531             : 
    1532             :   // Create heap objects for script, module bytes and asm.js offset table to
    1533             :   // be stored in the shared module data.
    1534             :   Handle<Script> script;
    1535             :   Handle<ByteArray> asm_js_offset_table;
    1536      147843 :   if (asm_js_script.is_null()) {
    1537      144296 :     script = CreateWasmScript(isolate_, wire_bytes);
    1538             :   } else {
    1539             :     script = asm_js_script;
    1540             :     asm_js_offset_table =
    1541        3547 :         isolate_->factory()->NewByteArray(asm_js_offset_table_bytes.length());
    1542             :     asm_js_offset_table->copy_in(0, asm_js_offset_table_bytes.start(),
    1543        3547 :                                  asm_js_offset_table_bytes.length());
    1544             :   }
    1545             :   // TODO(wasm): only save the sections necessary to deserialize a
    1546             :   // {WasmModule}. E.g. function bodies could be omitted.
    1547             :   Handle<String> module_bytes =
    1548             :       factory
    1549             :           ->NewStringFromOneByte({wire_bytes.start(), wire_bytes.length()},
    1550      147843 :                                  TENURED)
    1551      295686 :           .ToHandleChecked();
    1552             :   DCHECK(module_bytes->IsSeqOneByteString());
    1553             : 
    1554             :   // The {module_wrapper} will take ownership of the {WasmModule} object,
    1555             :   // and it will be destroyed when the GC reclaims the wrapper object.
    1556             :   Handle<WasmModuleWrapper> module_wrapper =
    1557      147843 :       WasmModuleWrapper::From(isolate_, module.release());
    1558             : 
    1559             :   // Create the shared module data.
    1560             :   // TODO(clemensh): For the same module (same bytes / same hash), we should
    1561             :   // only have one WasmSharedModuleData. Otherwise, we might only set
    1562             :   // breakpoints on a (potentially empty) subset of the instances.
    1563             : 
    1564             :   Handle<WasmSharedModuleData> shared = WasmSharedModuleData::New(
    1565             :       isolate_, module_wrapper, Handle<SeqOneByteString>::cast(module_bytes),
    1566      147843 :       script, asm_js_offset_table);
    1567      147843 :   if (lazy_compile) WasmSharedModuleData::PrepareForLazyCompilation(shared);
    1568             : 
    1569             :   // Create the compiled module object and populate with compiled functions
    1570             :   // and information needed at instantiation time. This object needs to be
    1571             :   // serializable. Instantiation may occur off a deserialized version of this
    1572             :   // object.
    1573             :   Handle<WasmCompiledModule> compiled_module = NewCompiledModule(
    1574      147843 :       isolate_, shared, code_table, export_wrappers, env.get());
    1575             : 
    1576             :   // If we created a wasm script, finish it now and make it public to the
    1577             :   // debugger.
    1578      147843 :   if (asm_js_script.is_null()) {
    1579      144296 :     script->set_wasm_compiled_module(*compiled_module);
    1580      288592 :     isolate_->debug()->OnAfterCompile(script);
    1581             :   }
    1582             : 
    1583             :   // Compile JS->wasm wrappers for exported functions.
    1584      147843 :   JSToWasmWrapperCache js_to_wasm_cache;
    1585             :   int wrapper_index = 0;
    1586      624164 :   for (auto exp : module_->export_table) {
    1587      182405 :     if (exp.kind != kExternalFunction) continue;
    1588             :     Handle<Code> wasm_code = EnsureExportedLazyDeoptData(
    1589      178865 :         isolate_, Handle<WasmInstanceObject>::null(), code_table, exp.index);
    1590             :     Handle<Code> wrapper_code = js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(
    1591      178865 :         isolate_, module_, wasm_code, exp.index);
    1592      178865 :     export_wrappers->set(wrapper_index, *wrapper_code);
    1593      178865 :     RecordStats(*wrapper_code, counters());
    1594      178865 :     ++wrapper_index;
    1595             :   }
    1596      147843 :   return WasmModuleObject::New(isolate_, compiled_module);
    1597             : }
    1598             : 
    1599      154148 : InstanceBuilder::InstanceBuilder(
    1600             :     Isolate* isolate, ErrorThrower* thrower,
    1601             :     Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> ffi,
    1602             :     MaybeHandle<JSArrayBuffer> memory,
    1603             :     WeakCallbackInfo<void>::Callback instance_finalizer_callback)
    1604             :     : isolate_(isolate),
    1605      154148 :       module_(module_object->compiled_module()->module()),
    1606             :       async_counters_(isolate->async_counters()),
    1607             :       thrower_(thrower),
    1608             :       module_object_(module_object),
    1609             :       ffi_(ffi),
    1610             :       memory_(memory),
    1611      616592 :       instance_finalizer_callback_(instance_finalizer_callback) {
    1612      308296 :   sanitized_imports_.reserve(module_->import_table.size());
    1613      154148 : }
    1614             : 
    1615             : // Build an instance, in all of its glory.
    1616      154148 : MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
    1617             :   // Check that an imports argument was provided, if the module requires it.
    1618             :   // No point in continuing otherwise.
    1619      758001 :   if (!module_->import_table.empty() && ffi_.is_null()) {
    1620             :     thrower_->TypeError(
    1621      306860 :         "Imports argument must be present and must be an object");
    1622          99 :     return {};
    1623             :   }
    1624             : 
    1625      154049 :   SanitizeImports();
    1626      308098 :   if (thrower_->error()) return {};
    1627             : 
    1628             :   // From here on, we expect the build pipeline to run without exiting to JS.
    1629             :   // Exception is when we run the startup function.
    1630      460388 :   DisallowJavascriptExecution no_js(isolate_);
    1631             :   // Record build time into correct bucket, then build instance.
    1632             :   TimedHistogramScope wasm_instantiate_module_time_scope(
    1633      153863 :       module_->is_wasm() ? counters()->wasm_instantiate_wasm_module_time()
    1634      307726 :                          : counters()->wasm_instantiate_asm_module_time());
    1635      153863 :   Factory* factory = isolate_->factory();
    1636             : 
    1637             :   //--------------------------------------------------------------------------
    1638             :   // Reuse the compiled module (if no owner), otherwise clone.
    1639             :   //--------------------------------------------------------------------------
    1640             :   Handle<FixedArray> code_table;
    1641             :   Handle<FixedArray> wrapper_table;
    1642             :   // We keep around a copy of the old code table, because we'll be replacing
    1643             :   // imports for the new instance, and then we need the old imports to be
    1644             :   // able to relocate.
    1645             :   Handle<FixedArray> old_code_table;
    1646             :   MaybeHandle<WasmInstanceObject> owner;
    1647             : 
    1648             :   TRACE("Starting new module instantiation\n");
    1649             :   {
    1650             :     // Root the owner, if any, before doing any allocations, which
    1651             :     // may trigger GC.
    1652             :     // Both owner and original template need to be in sync. Even
    1653             :     // after we lose the original template handle, the code
    1654             :     // objects we copied from it have data relative to the
    1655             :     // instance - such as globals addresses.
    1656             :     Handle<WasmCompiledModule> original;
    1657             :     {
    1658             :       DisallowHeapAllocation no_gc;
    1659             :       original = handle(module_object_->compiled_module());
    1660      153863 :       if (original->has_weak_owning_instance()) {
    1661             :         owner = handle(WasmInstanceObject::cast(
    1662       13250 :             original->weak_owning_instance()->value()));
    1663             :       }
    1664             :     }
    1665             :     DCHECK(!original.is_null());
    1666      153863 :     if (original->has_weak_owning_instance()) {
    1667             :       // Clone, but don't insert yet the clone in the instances chain.
    1668             :       // We do that last. Since we are holding on to the owner instance,
    1669             :       // the owner + original state used for cloning and patching
    1670             :       // won't be mutated by possible finalizer runs.
    1671             :       DCHECK(!owner.is_null());
    1672             :       TRACE("Cloning from %d\n", original->instance_id());
    1673        6625 :       old_code_table = original->code_table();
    1674        6625 :       compiled_module_ = WasmCompiledModule::Clone(isolate_, original);
    1675        6625 :       code_table = compiled_module_->code_table();
    1676        6625 :       wrapper_table = compiled_module_->export_wrappers();
    1677             :       // Avoid creating too many handles in the outer scope.
    1678        6625 :       HandleScope scope(isolate_);
    1679             : 
    1680             :       // Clone the code for wasm functions and exports.
    1681       54440 :       for (int i = 0; i < code_table->length(); ++i) {
    1682       20595 :         Handle<Code> orig_code(Code::cast(code_table->get(i)), isolate_);
    1683       20595 :         switch (orig_code->kind()) {
    1684             :           case Code::WASM_TO_JS_FUNCTION:
    1685             :             // Imports will be overwritten with newly compiled wrappers.
    1686             :             break;
    1687             :           case Code::BUILTIN:
    1688             :             DCHECK_EQ(Builtins::kWasmCompileLazy, orig_code->builtin_index());
    1689             :             // If this code object has deoptimization data, then we need a
    1690             :             // unique copy to attach updated deoptimization data.
    1691        3891 :             if (orig_code->deoptimization_data()->length() > 0) {
    1692        2416 :               Handle<Code> code = factory->CopyCode(orig_code);
    1693             :               Handle<FixedArray> deopt_data =
    1694        2416 :                   factory->NewFixedArray(2, TENURED);
    1695             :               deopt_data->set(1, Smi::FromInt(i));
    1696        2416 :               code->set_deoptimization_data(*deopt_data);
    1697        2416 :               code_table->set(i, *code);
    1698             :             }
    1699             :             break;
    1700             :           case Code::WASM_FUNCTION: {
    1701       12113 :             Handle<Code> code = factory->CopyCode(orig_code);
    1702       12113 :             code_table->set(i, *code);
    1703             :             break;
    1704             :           }
    1705             :           default:
    1706           0 :             UNREACHABLE();
    1707             :         }
    1708             :       }
    1709       23145 :       for (int i = 0; i < wrapper_table->length(); ++i) {
    1710        8260 :         Handle<Code> orig_code(Code::cast(wrapper_table->get(i)), isolate_);
    1711             :         DCHECK_EQ(orig_code->kind(), Code::JS_TO_WASM_FUNCTION);
    1712        8260 :         Handle<Code> code = factory->CopyCode(orig_code);
    1713        8260 :         wrapper_table->set(i, *code);
    1714             :       }
    1715             : 
    1716        6625 :       RecordStats(code_table, counters());
    1717        6625 :       RecordStats(wrapper_table, counters());
    1718             :     } else {
    1719             :       // There was no owner, so we can reuse the original.
    1720      147238 :       compiled_module_ = original;
    1721      147238 :       old_code_table = factory->CopyFixedArray(compiled_module_->code_table());
    1722      147238 :       code_table = compiled_module_->code_table();
    1723      147238 :       wrapper_table = compiled_module_->export_wrappers();
    1724             :       TRACE("Reusing existing instance %d\n", compiled_module_->instance_id());
    1725             :     }
    1726      153863 :     compiled_module_->set_native_context(isolate_->native_context());
    1727             :   }
    1728             : 
    1729             :   //--------------------------------------------------------------------------
    1730             :   // Allocate the instance object.
    1731             :   //--------------------------------------------------------------------------
    1732      307726 :   Zone instantiation_zone(isolate_->allocator(), ZONE_NAME);
    1733      307726 :   CodeSpecialization code_specialization(isolate_, &instantiation_zone);
    1734             :   Handle<WasmInstanceObject> instance =
    1735      153863 :       WasmInstanceObject::New(isolate_, compiled_module_);
    1736             : 
    1737             :   //--------------------------------------------------------------------------
    1738             :   // Set up the globals for the new instance.
    1739             :   //--------------------------------------------------------------------------
    1740             :   MaybeHandle<JSArrayBuffer> old_globals;
    1741      153863 :   uint32_t globals_size = module_->globals_size;
    1742      153863 :   if (globals_size > 0) {
    1743             :     const bool enable_guard_regions = false;
    1744             :     Handle<JSArrayBuffer> global_buffer =
    1745        2995 :         NewArrayBuffer(isolate_, globals_size, enable_guard_regions);
    1746        2995 :     globals_ = global_buffer;
    1747        2995 :     if (globals_.is_null()) {
    1748           0 :       thrower_->RangeError("Out of memory: wasm globals");
    1749           0 :       return {};
    1750             :     }
    1751             :     instance->wasm_context()->get()->globals_start =
    1752        2995 :         reinterpret_cast<byte*>(global_buffer->backing_store());
    1753        2995 :     instance->set_globals_buffer(*global_buffer);
    1754             :   }
    1755             : 
    1756             :   //--------------------------------------------------------------------------
    1757             :   // Prepare for initialization of function tables.
    1758             :   //--------------------------------------------------------------------------
    1759      307726 :   int function_table_count = static_cast<int>(module_->function_tables.size());
    1760      155203 :   table_instances_.reserve(module_->function_tables.size());
    1761      155973 :   for (int index = 0; index < function_table_count; ++index) {
    1762             :     table_instances_.push_back(
    1763             :         {Handle<WasmTableObject>::null(), Handle<FixedArray>::null(),
    1764        4220 :          Handle<FixedArray>::null(), Handle<FixedArray>::null()});
    1765             :   }
    1766             : 
    1767             :   //--------------------------------------------------------------------------
    1768             :   // Process the imports for the module.
    1769             :   //--------------------------------------------------------------------------
    1770      153863 :   int num_imported_functions = ProcessImports(code_table, instance);
    1771      153863 :   if (num_imported_functions < 0) return {};
    1772             : 
    1773             :   //--------------------------------------------------------------------------
    1774             :   // Process the initialization for the module's globals.
    1775             :   //--------------------------------------------------------------------------
    1776      152914 :   InitGlobals();
    1777             : 
    1778             :   //--------------------------------------------------------------------------
    1779             :   // Set up the indirect function tables for the new instance.
    1780             :   //--------------------------------------------------------------------------
    1781      152914 :   if (function_table_count > 0)
    1782        1900 :     InitializeTables(instance, &code_specialization);
    1783             : 
    1784             :   //--------------------------------------------------------------------------
    1785             :   // Set up the memory for the new instance.
    1786             :   //--------------------------------------------------------------------------
    1787      152914 :   uint32_t initial_pages = module_->initial_pages;
    1788             :   (module_->is_wasm() ? counters()->wasm_wasm_min_mem_pages_count()
    1789             :                       : counters()->wasm_asm_min_mem_pages_count())
    1790      458742 :       ->AddSample(initial_pages);
    1791             : 
    1792      152914 :   if (!memory_.is_null()) {
    1793             :     Handle<JSArrayBuffer> memory = memory_.ToHandleChecked();
    1794             :     // Set externally passed ArrayBuffer non neuterable.
    1795             :     memory->set_is_neuterable(false);
    1796             :     memory->set_is_wasm_buffer(true);
    1797             : 
    1798             :     DCHECK_IMPLIES(trap_handler::UseTrapHandler(),
    1799             :                    module_->is_asm_js() || memory->has_guard_region());
    1800      150139 :   } else if (initial_pages > 0) {
    1801        2237 :     memory_ = AllocateMemory(initial_pages);
    1802        2237 :     if (memory_.is_null()) return {};  // failed to allocate memory
    1803             :   }
    1804             : 
    1805             :   //--------------------------------------------------------------------------
    1806             :   // Check that indirect function table segments are within bounds.
    1807             :   //--------------------------------------------------------------------------
    1808      459992 :   for (WasmTableInit& table_init : module_->table_inits) {
    1809             :     DCHECK(table_init.table_index < table_instances_.size());
    1810        1340 :     uint32_t base = EvalUint32InitExpr(table_init.offset);
    1811             :     uint32_t table_size =
    1812        2680 :         table_instances_[table_init.table_index].function_table->length();
    1813        2680 :     if (!in_bounds(base, static_cast<uint32_t>(table_init.entries.size()),
    1814        1340 :                    table_size)) {
    1815          60 :       thrower_->LinkError("table initializer is out of bounds");
    1816          60 :       return {};
    1817             :     }
    1818             :   }
    1819             : 
    1820             :   //--------------------------------------------------------------------------
    1821             :   // Check that memory segments are within bounds.
    1822             :   //--------------------------------------------------------------------------
    1823      306346 :   for (WasmDataSegment& seg : module_->data_segments) {
    1824         790 :     uint32_t base = EvalUint32InitExpr(seg.dest_addr);
    1825         790 :     uint32_t mem_size = 0;
    1826         790 :     if (!memory_.is_null()) {
    1827         688 :       CHECK(memory_.ToHandleChecked()->byte_length()->ToUint32(&mem_size));
    1828             :     }
    1829        1580 :     if (!in_bounds(base, seg.source.length(), mem_size)) {
    1830         132 :       thrower_->LinkError("data segment is out of bounds");
    1831         132 :       return {};
    1832             :     }
    1833             :   }
    1834             : 
    1835             :   //--------------------------------------------------------------------------
    1836             :   // Initialize memory.
    1837             :   //--------------------------------------------------------------------------
    1838             :   Address mem_start = nullptr;
    1839      152712 :   uint32_t mem_size = 0;
    1840      152712 :   if (!memory_.is_null()) {
    1841             :     Handle<JSArrayBuffer> memory = memory_.ToHandleChecked();
    1842             :     mem_start = static_cast<Address>(memory->backing_store());
    1843        4906 :     CHECK(memory->byte_length()->ToUint32(&mem_size));
    1844        4906 :     LoadDataSegments(mem_start, mem_size);
    1845             :     // Just like with globals, we need to keep both the JSArrayBuffer
    1846             :     // and save the start pointer.
    1847        4906 :     instance->set_memory_buffer(*memory);
    1848             :   }
    1849             : 
    1850             :   //--------------------------------------------------------------------------
    1851             :   // Create a memory object if there is not already one.
    1852             :   //--------------------------------------------------------------------------
    1853      162738 :   if (module_->has_memory && !instance->has_memory_object()) {
    1854             :     Handle<WasmMemoryObject> memory_object = WasmMemoryObject::New(
    1855             :         isolate_,
    1856             :         instance->has_memory_buffer() ? handle(instance->memory_buffer())
    1857             :                                       : Handle<JSArrayBuffer>::null(),
    1858       26658 :         module_->maximum_pages != 0 ? module_->maximum_pages : -1);
    1859        8886 :     instance->set_memory_object(*memory_object);
    1860             :   }
    1861             : 
    1862             :   // Set the WasmContext address in wrappers.
    1863             :   // TODO(wasm): the wasm context should only appear as a constant in wrappers;
    1864             :   //             this code specialization is applied to the whole instance.
    1865             :   WasmContext* wasm_context = instance->wasm_context()->get();
    1866             :   Address wasm_context_address = reinterpret_cast<Address>(wasm_context);
    1867      152712 :   code_specialization.RelocateWasmContextReferences(wasm_context_address);
    1868             :   js_to_wasm_cache_.SetContextAddress(wasm_context_address);
    1869             : 
    1870             :   //--------------------------------------------------------------------------
    1871             :   // Set up the runtime support for the new instance.
    1872             :   //--------------------------------------------------------------------------
    1873      152712 :   Handle<WeakCell> weak_link = factory->NewWeakCell(instance);
    1874             : 
    1875      515114 :   for (int i = num_imported_functions + FLAG_skip_compiling_wasm_funcs,
    1876      312519 :            num_functions = static_cast<int>(module_->functions.size());
    1877             :        i < num_functions; ++i) {
    1878      209690 :     Handle<Code> code = handle(Code::cast(code_table->get(i)), isolate_);
    1879      209690 :     if (code->kind() == Code::WASM_FUNCTION) {
    1880      186792 :       Handle<FixedArray> deopt_data = factory->NewFixedArray(2, TENURED);
    1881      186792 :       deopt_data->set(0, *weak_link);
    1882             :       deopt_data->set(1, Smi::FromInt(i));
    1883      186792 :       code->set_deoptimization_data(*deopt_data);
    1884             :       continue;
    1885             :     }
    1886             :     DCHECK_EQ(Builtins::kWasmCompileLazy, code->builtin_index());
    1887             :     int deopt_len = code->deoptimization_data()->length();
    1888       22898 :     if (deopt_len == 0) continue;
    1889             :     DCHECK_LE(2, deopt_len);
    1890             :     DCHECK_EQ(i, Smi::ToInt(code->deoptimization_data()->get(1)));
    1891        8395 :     code->deoptimization_data()->set(0, *weak_link);
    1892             :     // Entries [2, deopt_len) encode information about table exports of this
    1893             :     // function. This is rebuilt in {LoadTableSegments}, so reset it here.
    1894        8415 :     for (int i = 2; i < deopt_len; ++i) {
    1895          20 :       code->deoptimization_data()->set_undefined(isolate_, i);
    1896             :     }
    1897             :   }
    1898             : 
    1899             :   //--------------------------------------------------------------------------
    1900             :   // Set up the exports object for the new instance.
    1901             :   //--------------------------------------------------------------------------
    1902      152712 :   ProcessExports(instance, compiled_module_);
    1903      305424 :   if (thrower_->error()) return {};
    1904             : 
    1905             :   //--------------------------------------------------------------------------
    1906             :   // Add instance to Memory object
    1907             :   //--------------------------------------------------------------------------
    1908      152662 :   if (instance->has_memory_object()) {
    1909        9996 :     Handle<WasmMemoryObject> memory(instance->memory_object(), isolate_);
    1910        9996 :     WasmMemoryObject::AddInstance(isolate_, memory, instance);
    1911             :   }
    1912             : 
    1913             :   //--------------------------------------------------------------------------
    1914             :   // Initialize the indirect function tables.
    1915             :   //--------------------------------------------------------------------------
    1916      152662 :   if (function_table_count > 0) LoadTableSegments(code_table, instance);
    1917             : 
    1918             :   // Patch all code with the relocations registered in code_specialization.
    1919      152662 :   code_specialization.RelocateDirectCalls(instance);
    1920      152662 :   code_specialization.ApplyToWholeInstance(*instance, SKIP_ICACHE_FLUSH);
    1921             : 
    1922      152662 :   FlushICache(isolate_, code_table);
    1923      152662 :   FlushICache(isolate_, wrapper_table);
    1924             : 
    1925             :   //--------------------------------------------------------------------------
    1926             :   // Unpack and notify signal handler of protected instructions.
    1927             :   //--------------------------------------------------------------------------
    1928      152662 :   if (trap_handler::UseTrapHandler()) {
    1929       15314 :     UnpackAndRegisterProtectedInstructions(isolate_, code_table);
    1930             :   }
    1931             : 
    1932             :   //--------------------------------------------------------------------------
    1933             :   // Set up and link the new instance.
    1934             :   //--------------------------------------------------------------------------
    1935             :   {
    1936             :     Handle<Object> global_handle =
    1937      152662 :         isolate_->global_handles()->Create(*instance);
    1938      152662 :     Handle<WeakCell> link_to_clone = factory->NewWeakCell(compiled_module_);
    1939      152662 :     Handle<WeakCell> link_to_owning_instance = factory->NewWeakCell(instance);
    1940             :     MaybeHandle<WeakCell> link_to_original;
    1941             :     MaybeHandle<WasmCompiledModule> original;
    1942      152662 :     if (!owner.is_null()) {
    1943             :       // prepare the data needed for publishing in a chain, but don't link
    1944             :       // just yet, because
    1945             :       // we want all the publishing to happen free from GC interruptions, and
    1946             :       // so we do it in
    1947             :       // one GC-free scope afterwards.
    1948             :       original = handle(owner.ToHandleChecked()->compiled_module());
    1949        6625 :       link_to_original = factory->NewWeakCell(original.ToHandleChecked());
    1950             :     }
    1951             :     // Publish the new instance to the instances chain.
    1952             :     {
    1953             :       DisallowHeapAllocation no_gc;
    1954      152662 :       if (!link_to_original.is_null()) {
    1955             :         compiled_module_->set_weak_next_instance(
    1956             :             link_to_original.ToHandleChecked());
    1957             :         original.ToHandleChecked()->set_weak_prev_instance(link_to_clone);
    1958             :         compiled_module_->set_weak_wasm_module(
    1959        6625 :             original.ToHandleChecked()->weak_wasm_module());
    1960             :       }
    1961      152662 :       module_object_->set_compiled_module(*compiled_module_);
    1962             :       compiled_module_->set_weak_owning_instance(link_to_owning_instance);
    1963             :       GlobalHandles::MakeWeak(
    1964             :           global_handle.location(), global_handle.location(),
    1965      152662 :           instance_finalizer_callback_, v8::WeakCallbackType::kFinalizer);
    1966             :     }
    1967             :   }
    1968             : 
    1969             :   //--------------------------------------------------------------------------
    1970             :   // Debugging support.
    1971             :   //--------------------------------------------------------------------------
    1972             :   // Set all breakpoints that were set on the shared module.
    1973             :   WasmSharedModuleData::SetBreakpointsOnNewInstance(compiled_module_->shared(),
    1974      152662 :                                                     instance);
    1975             : 
    1976      153448 :   if (FLAG_wasm_interpret_all && module_->is_wasm()) {
    1977             :     Handle<WasmDebugInfo> debug_info =
    1978         776 :         WasmInstanceObject::GetOrCreateDebugInfo(instance);
    1979             :     std::vector<int> func_indexes;
    1980        4208 :     for (int func_index = num_imported_functions,
    1981        1552 :              num_wasm_functions = static_cast<int>(module_->functions.size());
    1982        1716 :          func_index < num_wasm_functions; ++func_index) {
    1983         940 :       func_indexes.push_back(func_index);
    1984             :     }
    1985             :     WasmDebugInfo::RedirectToInterpreter(
    1986             :         debug_info, Vector<int>(func_indexes.data(),
    1987        2328 :                                 static_cast<int>(func_indexes.size())));
    1988             :   }
    1989             : 
    1990             :   //--------------------------------------------------------------------------
    1991             :   // Run the start function if one was specified.
    1992             :   //--------------------------------------------------------------------------
    1993      152662 :   if (module_->start_function_index >= 0) {
    1994        6319 :     HandleScope scope(isolate_);
    1995        6319 :     int start_index = module_->start_function_index;
    1996             :     Handle<Code> startup_code = EnsureExportedLazyDeoptData(
    1997        6319 :         isolate_, instance, code_table, start_index);
    1998       18957 :     FunctionSig* sig = module_->functions[start_index].sig;
    1999             :     Handle<Code> wrapper_code = js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper(
    2000        6319 :         isolate_, module_, startup_code, start_index);
    2001             :     Handle<WasmExportedFunction> startup_fct = WasmExportedFunction::New(
    2002             :         isolate_, instance, MaybeHandle<String>(), start_index,
    2003       12638 :         static_cast<int>(sig->parameter_count()), wrapper_code);
    2004        6319 :     RecordStats(*startup_code, counters());
    2005             :     // Call the JS function.
    2006             :     Handle<Object> undefined = factory->undefined_value();
    2007             :     {
    2008             :       // We're OK with JS execution here. The instance is fully setup.
    2009        6319 :       AllowJavascriptExecution allow_js(isolate_);
    2010             :       MaybeHandle<Object> retval =
    2011        6319 :           Execution::Call(isolate_, startup_fct, undefined, 0, nullptr);
    2012             : 
    2013        6319 :       if (retval.is_null()) {
    2014             :         DCHECK(isolate_->has_pending_exception());
    2015             :         // It's unfortunate that the new instance is already linked in the
    2016             :         // chain. However, we need to set up everything before executing the
    2017             :         // startup unction, such that stack trace information can be generated
    2018             :         // correctly already in the start function.
    2019          46 :         return {};
    2020        6273 :       }
    2021             :     }
    2022             :   }
    2023             : 
    2024             :   DCHECK(!isolate_->has_pending_exception());
    2025             :   TRACE("Finishing instance %d\n", compiled_module_->instance_id());
    2026      152616 :   TRACE_CHAIN(module_object_->compiled_module());
    2027      460342 :   return instance;
    2028             : }
    2029             : 
    2030             : // Look up an import value in the {ffi_} object.
    2031      142324 : MaybeHandle<Object> InstanceBuilder::LookupImport(uint32_t index,
    2032             :                                                   Handle<String> module_name,
    2033             : 
    2034             :                                                   Handle<String> import_name) {
    2035             :   // We pre-validated in the js-api layer that the ffi object is present, and
    2036             :   // a JSObject, if the module has imports.
    2037             :   DCHECK(!ffi_.is_null());
    2038             : 
    2039             :   // Look up the module first.
    2040             :   MaybeHandle<Object> result =
    2041      142324 :       Object::GetPropertyOrElement(ffi_.ToHandleChecked(), module_name);
    2042      142324 :   if (result.is_null()) {
    2043           0 :     return ReportTypeError("module not found", index, module_name);
    2044             :   }
    2045             : 
    2046             :   Handle<Object> module = result.ToHandleChecked();
    2047             : 
    2048             :   // Look up the value in the module.
    2049      142324 :   if (!module->IsJSReceiver()) {
    2050             :     return ReportTypeError("module is not an object or function", index,
    2051         160 :                            module_name);
    2052             :   }
    2053             : 
    2054      142164 :   result = Object::GetPropertyOrElement(module, import_name);
    2055      142164 :   if (result.is_null()) {
    2056           0 :     ReportLinkError("import not found", index, module_name, import_name);
    2057           0 :     return MaybeHandle<JSFunction>();
    2058             :   }
    2059             : 
    2060      142164 :   return result;
    2061             : }
    2062             : 
    2063             : // Look up an import value in the {ffi_} object specifically for linking an
    2064             : // asm.js module. This only performs non-observable lookups, which allows
    2065             : // falling back to JavaScript proper (and hence re-executing all lookups) if
    2066             : // module instantiation fails.
    2067        5921 : MaybeHandle<Object> InstanceBuilder::LookupImportAsm(
    2068             :     uint32_t index, Handle<String> import_name) {
    2069             :   // Check that a foreign function interface object was provided.
    2070        5921 :   if (ffi_.is_null()) {
    2071           0 :     return ReportLinkError("missing imports object", index, import_name);
    2072             :   }
    2073             : 
    2074             :   // Perform lookup of the given {import_name} without causing any observable
    2075             :   // side-effect. We only accept accesses that resolve to data properties,
    2076             :   // which is indicated by the asm.js spec in section 7 ("Linking") as well.
    2077             :   Handle<Object> result;
    2078             :   LookupIterator it = LookupIterator::PropertyOrElement(
    2079        5921 :       isolate_, ffi_.ToHandleChecked(), import_name);
    2080        5921 :   switch (it.state()) {
    2081             :     case LookupIterator::ACCESS_CHECK:
    2082             :     case LookupIterator::INTEGER_INDEXED_EXOTIC:
    2083             :     case LookupIterator::INTERCEPTOR:
    2084             :     case LookupIterator::JSPROXY:
    2085             :     case LookupIterator::ACCESSOR:
    2086             :     case LookupIterator::TRANSITION:
    2087          26 :       return ReportLinkError("not a data property", index, import_name);
    2088             :     case LookupIterator::NOT_FOUND:
    2089             :       // Accepting missing properties as undefined does not cause any
    2090             :       // observable difference from JavaScript semantics, we are lenient.
    2091          90 :       result = isolate_->factory()->undefined_value();
    2092          90 :       break;
    2093             :     case LookupIterator::DATA:
    2094        5805 :       result = it.GetDataValue();
    2095        5805 :       break;
    2096             :   }
    2097             : 
    2098        5895 :   return result;
    2099             : }
    2100             : 
    2101        3962 : uint32_t InstanceBuilder::EvalUint32InitExpr(const WasmInitExpr& expr) {
    2102        3962 :   switch (expr.kind) {
    2103             :     case WasmInitExpr::kI32Const:
    2104        2612 :       return expr.val.i32_const;
    2105             :     case WasmInitExpr::kGlobalIndex: {
    2106        2700 :       uint32_t offset = module_->globals[expr.val.global_index].offset;
    2107        2700 :       return *reinterpret_cast<uint32_t*>(raw_buffer_ptr(globals_, offset));
    2108             :     }
    2109             :     default:
    2110           0 :       UNREACHABLE();
    2111             :   }
    2112             : }
    2113             : 
    2114             : // Load data segments into the memory.
    2115        4906 : void InstanceBuilder::LoadDataSegments(Address mem_addr, size_t mem_size) {
    2116             :   Handle<SeqOneByteString> module_bytes(compiled_module_->module_bytes(),
    2117        4906 :                                         isolate_);
    2118       15300 :   for (const WasmDataSegment& segment : module_->data_segments) {
    2119        1154 :     uint32_t source_size = segment.source.length();
    2120             :     // Segments of size == 0 are just nops.
    2121         582 :     if (source_size == 0) continue;
    2122         572 :     uint32_t dest_offset = EvalUint32InitExpr(segment.dest_addr);
    2123             :     DCHECK(
    2124             :         in_bounds(dest_offset, source_size, static_cast<uint32_t>(mem_size)));
    2125         572 :     byte* dest = mem_addr + dest_offset;
    2126             :     const byte* src = reinterpret_cast<const byte*>(
    2127        1144 :         module_bytes->GetCharsAddress() + segment.source.offset());
    2128         572 :     memcpy(dest, src, source_size);
    2129             :   }
    2130        4906 : }
    2131             : 
    2132        4930 : void InstanceBuilder::WriteGlobalValue(WasmGlobal& global,
    2133             :                                        Handle<Object> value) {
    2134             :   double num = value->Number();
    2135             :   TRACE("init [globals_start=%p + %u] = %lf, type = %s\n",
    2136             :         reinterpret_cast<void*>(raw_buffer_ptr(globals_, 0)), global.offset,
    2137             :         num, WasmOpcodes::TypeName(global.type));
    2138        2465 :   switch (global.type) {
    2139             :     case kWasmI32:
    2140        1955 :       *GetRawGlobalPtr<int32_t>(global) = static_cast<int32_t>(num);
    2141        1955 :       break;
    2142             :     case kWasmI64:
    2143             :       // TODO(titzer): initialization of imported i64 globals.
    2144           0 :       UNREACHABLE();
    2145             :       break;
    2146             :     case kWasmF32:
    2147          50 :       *GetRawGlobalPtr<float>(global) = static_cast<float>(num);
    2148          50 :       break;
    2149             :     case kWasmF64:
    2150         460 :       *GetRawGlobalPtr<double>(global) = static_cast<double>(num);
    2151         460 :       break;
    2152             :     default:
    2153           0 :       UNREACHABLE();
    2154             :   }
    2155        2465 : }
    2156             : 
    2157      154049 : void InstanceBuilder::SanitizeImports() {
    2158             :   Handle<SeqOneByteString> module_bytes(
    2159             :       module_object_->compiled_module()->module_bytes());
    2160      906324 :   for (size_t index = 0; index < module_->import_table.size(); ++index) {
    2161      450353 :     WasmImport& import = module_->import_table[index];
    2162             : 
    2163             :     Handle<String> module_name;
    2164             :     MaybeHandle<String> maybe_module_name =
    2165             :         WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    2166      148245 :             isolate_, module_bytes, import.module_name);
    2167      148245 :     if (!maybe_module_name.ToHandle(&module_name)) {
    2168             :       thrower_->LinkError("Could not resolve module name for import %zu",
    2169      148245 :                           index);
    2170           0 :       return;
    2171             :     }
    2172             : 
    2173             :     Handle<String> import_name;
    2174             :     MaybeHandle<String> maybe_import_name =
    2175             :         WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    2176      148245 :             isolate_, module_bytes, import.field_name);
    2177      148245 :     if (!maybe_import_name.ToHandle(&import_name)) {
    2178             :       thrower_->LinkError("Could not resolve import name for import %zu",
    2179           0 :                           index);
    2180           0 :       return;
    2181             :     }
    2182             : 
    2183             :     int int_index = static_cast<int>(index);
    2184             :     MaybeHandle<Object> result =
    2185      148245 :         module_->is_asm_js()
    2186        5921 :             ? LookupImportAsm(int_index, import_name)
    2187      154166 :             : LookupImport(int_index, module_name, import_name);
    2188      296490 :     if (thrower_->error()) {
    2189         186 :       thrower_->LinkError("Could not find value for import %zu", index);
    2190         186 :       return;
    2191             :     }
    2192             :     Handle<Object> value = result.ToHandleChecked();
    2193      296118 :     sanitized_imports_.push_back({module_name, import_name, value});
    2194             :   }
    2195             : }
    2196             : 
    2197      153863 : Handle<FixedArray> InstanceBuilder::SetupWasmToJSImportsTable(
    2198             :     Handle<WasmInstanceObject> instance) {
    2199             :   // The js_imports_table is set up so that index 0 has isolate->native_context
    2200             :   // and for every index, 3*index+1 has the JSReceiver, 3*index+2 has function's
    2201             :   // global proxy and 3*index+3 has function's context. Hence, the fixed array's
    2202             :   // size is 3*import_table.size+1.
    2203      307726 :   int size = static_cast<int>(module_->import_table.size());
    2204      153863 :   CHECK_LE(size, (kMaxInt - 1) / 3);
    2205             :   Handle<FixedArray> func_table =
    2206      307726 :       isolate_->factory()->NewFixedArray(3 * size + 1, TENURED);
    2207             :   Handle<FixedArray> js_imports_table =
    2208      153863 :       isolate_->global_handles()->Create(*func_table);
    2209             :   GlobalHandles::MakeWeak(
    2210             :       reinterpret_cast<Object**>(js_imports_table.location()),
    2211             :       js_imports_table.location(), &FunctionTableFinalizer,
    2212      153863 :       v8::WeakCallbackType::kFinalizer);
    2213      153863 :   instance->set_js_imports_table(*func_table);
    2214      307726 :   js_imports_table->set(0, *isolate_->native_context());
    2215      153863 :   return js_imports_table;
    2216             : }
    2217             : 
    2218             : // Process the imports, including functions, tables, globals, and memory, in
    2219             : // order, loading them from the {ffi_} object. Returns the number of imported
    2220             : // functions.
    2221      153863 : int InstanceBuilder::ProcessImports(Handle<FixedArray> code_table,
    2222             :                                     Handle<WasmInstanceObject> instance) {
    2223             :   int num_imported_functions = 0;
    2224             :   int num_imported_tables = 0;
    2225      153863 :   Handle<FixedArray> js_imports_table = SetupWasmToJSImportsTable(instance);
    2226      153863 :   WasmInstanceMap imported_wasm_instances(isolate_->heap());
    2227             :   DCHECK_EQ(module_->import_table.size(), sanitized_imports_.size());
    2228      902919 :   for (int index = 0; index < static_cast<int>(module_->import_table.size());
    2229             :        ++index) {
    2230      594421 :     WasmImport& import = module_->import_table[index];
    2231             : 
    2232      296118 :     Handle<String> module_name = sanitized_imports_[index].module_name;
    2233      148059 :     Handle<String> import_name = sanitized_imports_[index].import_name;
    2234      148059 :     Handle<Object> value = sanitized_imports_[index].value;
    2235             : 
    2236      148059 :     switch (import.kind) {
    2237             :       case kExternalFunction: {
    2238             :         // Function imports must be callable.
    2239      142985 :         if (!value->IsCallable()) {
    2240             :           ReportLinkError("function import requires a callable", index,
    2241         190 :                           module_name, import_name);
    2242         190 :           return -1;
    2243             :         }
    2244             : 
    2245             :         Handle<Code> import_code = UnwrapExportOrCompileImportWrapper(
    2246      142795 :             isolate_, module_->functions[import.index].sig,
    2247      142795 :             Handle<JSReceiver>::cast(value), index, module_->origin(),
    2248      285590 :             &imported_wasm_instances, js_imports_table, instance);
    2249      142795 :         if (import_code.is_null()) {
    2250             :           ReportLinkError("imported function does not match the expected type",
    2251         220 :                           index, module_name, import_name);
    2252         220 :           return -1;
    2253             :         }
    2254      142575 :         code_table->set(num_imported_functions, *import_code);
    2255      142575 :         RecordStats(*import_code, counters());
    2256      142575 :         num_imported_functions++;
    2257             :         break;
    2258             :       }
    2259             :       case kExternalTable: {
    2260        1090 :         if (!value->IsWasmTableObject()) {
    2261             :           ReportLinkError("table import requires a WebAssembly.Table", index,
    2262          70 :                           module_name, import_name);
    2263          70 :           return -1;
    2264             :         }
    2265             :         WasmIndirectFunctionTable& table =
    2266        1020 :             module_->function_tables[num_imported_tables];
    2267        1020 :         TableInstance& table_instance = table_instances_[num_imported_tables];
    2268        1020 :         table_instance.table_object = Handle<WasmTableObject>::cast(value);
    2269             :         table_instance.js_wrappers = Handle<FixedArray>(
    2270        2040 :             table_instance.table_object->functions(), isolate_);
    2271             : 
    2272             :         int imported_cur_size = table_instance.js_wrappers->length();
    2273        1020 :         if (imported_cur_size < static_cast<int>(table.initial_size)) {
    2274             :           thrower_->LinkError(
    2275             :               "table import %d is smaller than initial %d, got %u", index,
    2276          50 :               table.initial_size, imported_cur_size);
    2277          50 :           return -1;
    2278             :         }
    2279             : 
    2280         970 :         if (table.has_maximum_size) {
    2281             :           int64_t imported_maximum_size =
    2282         820 :               table_instance.table_object->maximum_length()->Number();
    2283         820 :           if (imported_maximum_size < 0) {
    2284             :             thrower_->LinkError(
    2285             :                 "table import %d has no maximum length, expected %d", index,
    2286          10 :                 table.maximum_size);
    2287          10 :             return -1;
    2288             :           }
    2289         810 :           if (imported_maximum_size > table.maximum_size) {
    2290             :             thrower_->LinkError(
    2291             :                 " table import %d has a larger maximum size %" PRIx64
    2292             :                 " than the module's declared maximum %u",
    2293          70 :                 index, imported_maximum_size, table.maximum_size);
    2294          70 :             return -1;
    2295             :           }
    2296             :         }
    2297             : 
    2298             :         // Allocate a new dispatch table and signature table.
    2299             :         int table_size = imported_cur_size;
    2300             :         table_instance.function_table =
    2301         890 :             isolate_->factory()->NewFixedArray(table_size);
    2302             :         table_instance.signature_table =
    2303         890 :             isolate_->factory()->NewFixedArray(table_size);
    2304     2629960 :         for (int i = 0; i < table_size; ++i) {
    2305             :           table_instance.signature_table->set(i,
    2306             :                                               Smi::FromInt(kInvalidSigIndex));
    2307             :         }
    2308             :         // Initialize the dispatch table with the (foreign) JS functions
    2309             :         // that are already in the table.
    2310     2629070 :         for (int i = 0; i < table_size; ++i) {
    2311     2629070 :           Handle<Object> val(table_instance.js_wrappers->get(i), isolate_);
    2312     5255520 :           if (!val->IsJSFunction()) continue;
    2313        2620 :           if (!WasmExportedFunction::IsWasmExportedFunction(*val)) {
    2314             :             thrower_->LinkError("table import %d[%d] is not a wasm function",
    2315           0 :                                 index, i);
    2316           0 :             return -1;
    2317             :           }
    2318             :           // Look up the signature's canonical id. If there is no canonical
    2319             :           // id, then the signature does not appear at all in this module,
    2320             :           // so putting {-1} in the table will cause checks to always fail.
    2321        2620 :           auto target = Handle<WasmExportedFunction>::cast(val);
    2322        2620 :           FunctionSig* sig = nullptr;
    2323             :           Handle<Code> code =
    2324             :               MakeWasmToWasmWrapper(isolate_, target, nullptr, &sig,
    2325        2620 :                                     &imported_wasm_instances, instance);
    2326        2620 :           int sig_index = module_->signature_map.Find(sig);
    2327             :           table_instance.signature_table->set(i, Smi::FromInt(sig_index));
    2328        2620 :           table_instance.function_table->set(i, *code);
    2329             :         }
    2330             : 
    2331         890 :         num_imported_tables++;
    2332         890 :         break;
    2333             :       }
    2334             :       case kExternalMemory: {
    2335             :         // Validation should have failed if more than one memory object was
    2336             :         // provided.
    2337             :         DCHECK(!instance->has_memory_object());
    2338        1390 :         if (!value->IsWasmMemoryObject()) {
    2339             :           ReportLinkError("memory import must be a WebAssembly.Memory object",
    2340         130 :                           index, module_name, import_name);
    2341         130 :           return -1;
    2342             :         }
    2343             :         auto memory = Handle<WasmMemoryObject>::cast(value);
    2344        1260 :         instance->set_memory_object(*memory);
    2345        1260 :         Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate_);
    2346        1260 :         memory_ = buffer;
    2347             :         uint32_t imported_cur_pages = static_cast<uint32_t>(
    2348        1260 :             buffer->byte_length()->Number() / WasmModule::kPageSize);
    2349        1260 :         if (imported_cur_pages < module_->initial_pages) {
    2350             :           thrower_->LinkError(
    2351             :               "memory import %d is smaller than initial %u, got %u", index,
    2352          30 :               module_->initial_pages, imported_cur_pages);
    2353             :         }
    2354             :         int32_t imported_maximum_pages = memory->maximum_pages();
    2355        1260 :         if (module_->has_maximum_pages) {
    2356         450 :           if (imported_maximum_pages < 0) {
    2357             :             thrower_->LinkError(
    2358             :                 "memory import %d has no maximum limit, expected at most %u",
    2359          10 :                 index, imported_maximum_pages);
    2360          10 :             return -1;
    2361             :           }
    2362         440 :           if (static_cast<uint32_t>(imported_maximum_pages) >
    2363             :               module_->maximum_pages) {
    2364             :             thrower_->LinkError(
    2365             :                 "memory import %d has a larger maximum size %u than the "
    2366             :                 "module's declared maximum %u",
    2367          50 :                 index, imported_maximum_pages, module_->maximum_pages);
    2368          50 :             return -1;
    2369             :           }
    2370             :         }
    2371        2400 :         if (module_->has_shared_memory != buffer->is_shared()) {
    2372             :           thrower_->LinkError(
    2373             :               "mismatch in shared state of memory, declared = %d, imported = "
    2374             :               "%d",
    2375          20 :               module_->has_shared_memory, buffer->is_shared());
    2376          20 :           return -1;
    2377             :         }
    2378             : 
    2379             :         break;
    2380             :       }
    2381             :       case kExternalGlobal: {
    2382             :         // Global imports are converted to numbers and written into the
    2383             :         // {globals_} array buffer.
    2384        9218 :         if (module_->globals[import.index].type == kWasmI64) {
    2385             :           ReportLinkError("global import cannot have type i64", index,
    2386           0 :                           module_name, import_name);
    2387           0 :           return -1;
    2388             :         }
    2389        2594 :         if (module_->is_asm_js()) {
    2390             :           // Accepting {JSFunction} on top of just primitive values here is a
    2391             :           // workaround to support legacy asm.js code with broken binding. Note
    2392             :           // that using {NaN} (or Smi::kZero) here is what using the observable
    2393             :           // conversion via {ToPrimitive} would produce as well.
    2394             :           // TODO(mstarzinger): Still observable if Function.prototype.valueOf
    2395             :           // or friends are patched, we might need to check for that as well.
    2396        1584 :           if (value->IsJSFunction()) value = isolate_->factory()->nan_value();
    2397        3155 :           if (value->IsPrimitive() && !value->IsSymbol()) {
    2398        3130 :             if (module_->globals[import.index].type == kWasmI32) {
    2399        1145 :               value = Object::ToInt32(isolate_, value).ToHandleChecked();
    2400             :             } else {
    2401         840 :               value = Object::ToNumber(value).ToHandleChecked();
    2402             :             }
    2403             :           }
    2404             :         }
    2405        2594 :         if (!value->IsNumber()) {
    2406             :           ReportLinkError("global import must be a number", index, module_name,
    2407         129 :                           import_name);
    2408         129 :           return -1;
    2409             :         }
    2410        4930 :         WriteGlobalValue(module_->globals[import.index], value);
    2411        2465 :         break;
    2412             :       }
    2413             :       default:
    2414           0 :         UNREACHABLE();
    2415             :         break;
    2416             :     }
    2417             :   }
    2418             : 
    2419      152914 :   if (!imported_wasm_instances.empty()) {
    2420      131625 :     WasmInstanceMap::IteratableScope iteratable_scope(&imported_wasm_instances);
    2421             :     Handle<FixedArray> instances_array = isolate_->factory()->NewFixedArray(
    2422      131625 :         imported_wasm_instances.size(), TENURED);
    2423      131625 :     instance->set_directly_called_instances(*instances_array);
    2424             :     int index = 0;
    2425      264410 :     for (auto it = iteratable_scope.begin(), end = iteratable_scope.end();
    2426             :          it != end; ++it, ++index) {
    2427      132785 :       instances_array->set(index, ***it);
    2428      131625 :     }
    2429             :   }
    2430             : 
    2431      152914 :   return num_imported_functions;
    2432             : }
    2433             : 
    2434             : template <typename T>
    2435             : T* InstanceBuilder::GetRawGlobalPtr(WasmGlobal& global) {
    2436       19340 :   return reinterpret_cast<T*>(raw_buffer_ptr(globals_, global.offset));
    2437             : }
    2438             : 
    2439             : // Process initialization of globals.
    2440      152914 : void InstanceBuilder::InitGlobals() {
    2441      468182 :   for (auto global : module_->globals) {
    2442        9440 :     switch (global.init.kind) {
    2443             :       case WasmInitExpr::kI32Const:
    2444        5701 :         *GetRawGlobalPtr<int32_t>(global) = global.init.val.i32_const;
    2445        5701 :         break;
    2446             :       case WasmInitExpr::kI64Const:
    2447          50 :         *GetRawGlobalPtr<int64_t>(global) = global.init.val.i64_const;
    2448          50 :         break;
    2449             :       case WasmInitExpr::kF32Const:
    2450         166 :         *GetRawGlobalPtr<float>(global) = global.init.val.f32_const;
    2451         166 :         break;
    2452             :       case WasmInitExpr::kF64Const:
    2453         998 :         *GetRawGlobalPtr<double>(global) = global.init.val.f64_const;
    2454         998 :         break;
    2455             :       case WasmInitExpr::kGlobalIndex: {
    2456             :         // Initialize with another global.
    2457             :         uint32_t new_offset = global.offset;
    2458             :         uint32_t old_offset =
    2459         120 :             module_->globals[global.init.val.global_index].offset;
    2460             :         TRACE("init [globals+%u] = [globals+%d]\n", global.offset, old_offset);
    2461          60 :         size_t size = (global.type == kWasmI64 || global.type == kWasmF64)
    2462             :                           ? sizeof(double)
    2463          60 :                           : sizeof(int32_t);
    2464         180 :         memcpy(raw_buffer_ptr(globals_, new_offset),
    2465         180 :                raw_buffer_ptr(globals_, old_offset), size);
    2466          60 :         break;
    2467             :       }
    2468             :       case WasmInitExpr::kNone:
    2469             :         // Happens with imported globals.
    2470             :         break;
    2471             :       default:
    2472           0 :         UNREACHABLE();
    2473             :         break;
    2474             :     }
    2475             :   }
    2476      152914 : }
    2477             : 
    2478             : // Allocate memory for a module instance as a new JSArrayBuffer.
    2479        2237 : Handle<JSArrayBuffer> InstanceBuilder::AllocateMemory(uint32_t num_pages) {
    2480        2237 :   if (num_pages > FLAG_wasm_max_mem_pages) {
    2481           0 :     thrower_->RangeError("Out of memory: wasm memory too large");
    2482             :     return Handle<JSArrayBuffer>::null();
    2483             :   }
    2484             :   const bool enable_guard_regions = trap_handler::UseTrapHandler();
    2485             :   Handle<JSArrayBuffer> mem_buffer = NewArrayBuffer(
    2486        2237 :       isolate_, num_pages * WasmModule::kPageSize, enable_guard_regions);
    2487             : 
    2488        2237 :   if (mem_buffer.is_null()) {
    2489          10 :     thrower_->RangeError("Out of memory: wasm memory");
    2490             :   }
    2491        2237 :   return mem_buffer;
    2492             : }
    2493             : 
    2494      152712 : bool InstanceBuilder::NeedsWrappers() const {
    2495      152712 :   if (module_->num_exported_functions > 0) return true;
    2496        4204 :   for (auto& table_instance : table_instances_) {
    2497         620 :     if (!table_instance.js_wrappers.is_null()) return true;
    2498             :   }
    2499        3284 :   for (auto& table : module_->function_tables) {
    2500         320 :     if (table.exported) return true;
    2501             :   }
    2502             :   return false;
    2503             : }
    2504             : 
    2505             : // Process the exports, creating wrappers for functions, tables, memories,
    2506             : // and globals.
    2507      152712 : void InstanceBuilder::ProcessExports(
    2508             :     Handle<WasmInstanceObject> instance,
    2509             :     Handle<WasmCompiledModule> compiled_module) {
    2510      152712 :   Handle<FixedArray> wrapper_table = compiled_module->export_wrappers();
    2511      152712 :   if (NeedsWrappers()) {
    2512             :     // Fill the table to cache the exported JSFunction wrappers.
    2513             :     js_wrappers_.insert(js_wrappers_.begin(), module_->functions.size(),
    2514     1848285 :                         Handle<JSFunction>::null());
    2515             :   }
    2516             : 
    2517             :   Handle<JSObject> exports_object;
    2518      305424 :   if (module_->is_wasm()) {
    2519             :     // Create the "exports" object.
    2520      146523 :     exports_object = isolate_->factory()->NewJSObjectWithNullProto();
    2521        6189 :   } else if (module_->is_asm_js()) {
    2522             :     Handle<JSFunction> object_function = Handle<JSFunction>(
    2523       12378 :         isolate_->native_context()->object_function(), isolate_);
    2524        6189 :     exports_object = isolate_->factory()->NewJSObject(object_function);
    2525             :   } else {
    2526           0 :     UNREACHABLE();
    2527             :   }
    2528      152712 :   instance->set_exports_object(*exports_object);
    2529             : 
    2530             :   Handle<String> single_function_name =
    2531      152712 :       isolate_->factory()->InternalizeUtf8String(AsmJs::kSingleFunctionName);
    2532             : 
    2533             :   PropertyDescriptor desc;
    2534      152712 :   desc.set_writable(module_->is_asm_js());
    2535             :   desc.set_enumerable(true);
    2536             :   desc.set_configurable(module_->is_asm_js());
    2537             : 
    2538             :   // Store weak references to all exported functions.
    2539             :   Handle<FixedArray> weak_exported_functions;
    2540      152712 :   if (compiled_module->has_weak_exported_functions()) {
    2541         232 :     weak_exported_functions = compiled_module->weak_exported_functions();
    2542             :   } else {
    2543             :     int export_count = 0;
    2544      646091 :     for (WasmExport& exp : module_->export_table) {
    2545      188651 :       if (exp.kind == kExternalFunction) ++export_count;
    2546             :     }
    2547      152480 :     weak_exported_functions = isolate_->factory()->NewFixedArray(export_count);
    2548             :     compiled_module->set_weak_exported_functions(weak_exported_functions);
    2549             :   }
    2550             : 
    2551             :   // Process each export in the export table.
    2552             :   int export_index = 0;  // Index into {weak_exported_functions}.
    2553      647079 :   for (WasmExport& exp : module_->export_table) {
    2554             :     Handle<String> name = WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    2555      188963 :                               isolate_, compiled_module_, exp.name)
    2556      377926 :                               .ToHandleChecked();
    2557             :     Handle<JSObject> export_to;
    2558      388290 :     if (module_->is_asm_js() && exp.kind == kExternalFunction &&
    2559       10364 :         String::Equals(name, single_function_name)) {
    2560             :       export_to = instance;
    2561             :     } else {
    2562             :       export_to = exports_object;
    2563             :     }
    2564             : 
    2565      188963 :     switch (exp.kind) {
    2566             :       case kExternalFunction: {
    2567             :         // Wrap and export the code as a JSFunction.
    2568      186853 :         WasmFunction& function = module_->functions[exp.index];
    2569      186853 :         Handle<JSFunction> js_function = js_wrappers_[exp.index];
    2570      186853 :         if (js_function.is_null()) {
    2571             :           // Wrap the exported code as a JSFunction.
    2572             :           Handle<Code> export_code =
    2573      373330 :               wrapper_table->GetValueChecked<Code>(isolate_, export_index);
    2574             :           MaybeHandle<String> func_name;
    2575      373330 :           if (module_->is_asm_js()) {
    2576             :             // For modules arising from asm.js, honor the names section.
    2577             :             func_name = WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    2578       10336 :                             isolate_, compiled_module_, function.name)
    2579       20672 :                             .ToHandleChecked();
    2580             :           }
    2581             :           js_function = WasmExportedFunction::New(
    2582             :               isolate_, instance, func_name, function.func_index,
    2583      186665 :               static_cast<int>(function.sig->parameter_count()), export_code);
    2584      373330 :           js_wrappers_[exp.index] = js_function;
    2585             :         }
    2586             :         desc.set_value(js_function);
    2587             :         Handle<WeakCell> weak_export =
    2588      186853 :             isolate_->factory()->NewWeakCell(js_function);
    2589             :         DCHECK_GT(weak_exported_functions->length(), export_index);
    2590      186853 :         weak_exported_functions->set(export_index, *weak_export);
    2591      186853 :         export_index++;
    2592             :         break;
    2593             :       }
    2594             :       case kExternalTable: {
    2595             :         // Export a table as a WebAssembly.Table object.
    2596         500 :         TableInstance& table_instance = table_instances_[exp.index];
    2597         500 :         WasmIndirectFunctionTable& table = module_->function_tables[exp.index];
    2598         500 :         if (table_instance.table_object.is_null()) {
    2599             :           uint32_t maximum = table.has_maximum_size ? table.maximum_size
    2600         440 :                                                     : FLAG_wasm_max_table_size;
    2601             :           table_instance.table_object =
    2602             :               WasmTableObject::New(isolate_, table.initial_size, maximum,
    2603         440 :                                    &table_instance.js_wrappers);
    2604             :         }
    2605             :         desc.set_value(table_instance.table_object);
    2606         500 :         break;
    2607             :       }
    2608             :       case kExternalMemory: {
    2609             :         // Export the memory as a WebAssembly.Memory object. A WasmMemoryObject
    2610             :         // should already be available if the module has memory, since we always
    2611             :         // create or import it when building an WasmInstanceObject.
    2612             :         DCHECK(instance->has_memory_object());
    2613             :         desc.set_value(
    2614        1300 :             Handle<WasmMemoryObject>(instance->memory_object(), isolate_));
    2615        1300 :         break;
    2616             :       }
    2617             :       case kExternalGlobal: {
    2618             :         // Export the value of the global variable as a number.
    2619         600 :         WasmGlobal& global = module_->globals[exp.index];
    2620             :         double num = 0;
    2621         310 :         switch (global.type) {
    2622             :           case kWasmI32:
    2623         200 :             num = *GetRawGlobalPtr<int32_t>(global);
    2624         200 :             break;
    2625             :           case kWasmF32:
    2626          50 :             num = *GetRawGlobalPtr<float>(global);
    2627          50 :             break;
    2628             :           case kWasmF64:
    2629          40 :             num = *GetRawGlobalPtr<double>(global);
    2630          40 :             break;
    2631             :           case kWasmI64:
    2632             :             thrower_->LinkError(
    2633          20 :                 "export of globals of type I64 is not allowed.");
    2634          20 :             return;
    2635             :           default:
    2636           0 :             UNREACHABLE();
    2637             :         }
    2638         290 :         desc.set_value(isolate_->factory()->NewNumber(num));
    2639             :         break;
    2640             :       }
    2641             :       default:
    2642           0 :         UNREACHABLE();
    2643             :         break;
    2644             :     }
    2645             : 
    2646             :     v8::Maybe<bool> status = JSReceiver::DefineOwnProperty(
    2647      188943 :         isolate_, export_to, name, &desc, Object::THROW_ON_ERROR);
    2648      188943 :     if (!status.IsJust()) {
    2649             :       TruncatedUserString<> trunc_name(name->GetCharVector<uint8_t>());
    2650             :       thrower_->LinkError("export of %.*s failed.", trunc_name.length(),
    2651           0 :                           trunc_name.start());
    2652             :       return;
    2653             :     }
    2654             :   }
    2655             :   DCHECK_EQ(export_index, weak_exported_functions->length());
    2656             : 
    2657      305384 :   if (module_->is_wasm()) {
    2658             :     v8::Maybe<bool> success = JSReceiver::SetIntegrityLevel(
    2659      146503 :         exports_object, FROZEN, Object::DONT_THROW);
    2660             :     DCHECK(success.FromMaybe(false));
    2661             :     USE(success);
    2662             :   }
    2663             : }
    2664             : 
    2665        1900 : void InstanceBuilder::InitializeTables(
    2666             :     Handle<WasmInstanceObject> instance,
    2667             :     CodeSpecialization* code_specialization) {
    2668        5700 :   int function_table_count = static_cast<int>(module_->function_tables.size());
    2669             :   Handle<FixedArray> new_function_tables =
    2670        5700 :       isolate_->factory()->NewFixedArray(function_table_count, TENURED);
    2671             :   Handle<FixedArray> new_signature_tables =
    2672        1900 :       isolate_->factory()->NewFixedArray(function_table_count, TENURED);
    2673        1900 :   Handle<FixedArray> old_function_tables = compiled_module_->function_tables();
    2674             :   Handle<FixedArray> old_signature_tables =
    2675        1900 :       compiled_module_->signature_tables();
    2676             : 
    2677             :   // These go on the instance.
    2678             :   Handle<FixedArray> rooted_function_tables =
    2679        1900 :       isolate_->factory()->NewFixedArray(function_table_count, TENURED);
    2680             :   Handle<FixedArray> rooted_signature_tables =
    2681        1900 :       isolate_->factory()->NewFixedArray(function_table_count, TENURED);
    2682             : 
    2683        1900 :   instance->set_function_tables(*rooted_function_tables);
    2684        1900 :   instance->set_signature_tables(*rooted_signature_tables);
    2685             : 
    2686             :   DCHECK_EQ(old_function_tables->length(), new_function_tables->length());
    2687             :   DCHECK_EQ(old_signature_tables->length(), new_signature_tables->length());
    2688             : 
    2689        3800 :   for (int index = 0; index < function_table_count; ++index) {
    2690        1900 :     WasmIndirectFunctionTable& table = module_->function_tables[index];
    2691        1900 :     TableInstance& table_instance = table_instances_[index];
    2692        1900 :     int table_size = static_cast<int>(table.initial_size);
    2693             : 
    2694        1900 :     if (table_instance.function_table.is_null()) {
    2695             :       // Create a new dispatch table if necessary.
    2696             :       table_instance.function_table =
    2697        1020 :           isolate_->factory()->NewFixedArray(table_size);
    2698             :       table_instance.signature_table =
    2699        1020 :           isolate_->factory()->NewFixedArray(table_size);
    2700       11912 :       for (int i = 0; i < table_size; ++i) {
    2701             :         // Fill the table with invalid signature indexes so that
    2702             :         // uninitialized entries will always fail the signature check.
    2703             :         table_instance.signature_table->set(i, Smi::FromInt(kInvalidSigIndex));
    2704             :       }
    2705             :     } else {
    2706             :       // Table is imported, patch table bounds check
    2707             :       DCHECK_LE(table_size, table_instance.function_table->length());
    2708             :       code_specialization->PatchTableSize(
    2709         880 :           table_size, table_instance.function_table->length());
    2710             :     }
    2711             :     int int_index = static_cast<int>(index);
    2712             : 
    2713             :     Handle<FixedArray> global_func_table =
    2714        1900 :         isolate_->global_handles()->Create(*table_instance.function_table);
    2715             :     Handle<FixedArray> global_sig_table =
    2716        1900 :         isolate_->global_handles()->Create(*table_instance.signature_table);
    2717             :     // Make the handles weak. The table objects are rooted on the instance, as
    2718             :     // they belong to it. We need the global handles in order to have stable
    2719             :     // pointers to embed in the instance's specialization (wasm compiled code).
    2720             :     // The order of finalization doesn't matter, in that the instance finalizer
    2721             :     // may be called before each table's finalizer, or vice-versa.
    2722             :     // This is because values used for embedding are only interesting should we
    2723             :     // {Reset} a specialization, in which case they are interesting as values,
    2724             :     // they are not dereferenced.
    2725             :     GlobalHandles::MakeWeak(
    2726             :         reinterpret_cast<Object**>(global_func_table.location()),
    2727             :         global_func_table.location(), &FunctionTableFinalizer,
    2728        1900 :         v8::WeakCallbackType::kFinalizer);
    2729             :     GlobalHandles::MakeWeak(
    2730             :         reinterpret_cast<Object**>(global_sig_table.location()),
    2731             :         global_sig_table.location(), &FunctionTableFinalizer,
    2732        1900 :         v8::WeakCallbackType::kFinalizer);
    2733             : 
    2734        1900 :     rooted_function_tables->set(int_index, *global_func_table);
    2735        1900 :     rooted_signature_tables->set(int_index, *global_sig_table);
    2736             : 
    2737             :     GlobalHandleAddress new_func_table_addr = global_func_table.address();
    2738             :     GlobalHandleAddress new_sig_table_addr = global_sig_table.address();
    2739             :     WasmCompiledModule::SetTableValue(isolate_, new_function_tables, int_index,
    2740        1900 :                                       new_func_table_addr);
    2741             :     WasmCompiledModule::SetTableValue(isolate_, new_signature_tables, int_index,
    2742        1900 :                                       new_sig_table_addr);
    2743             : 
    2744             :     GlobalHandleAddress old_func_table_addr =
    2745        1900 :         WasmCompiledModule::GetTableValue(*old_function_tables, int_index);
    2746             :     GlobalHandleAddress old_sig_table_addr =
    2747        1900 :         WasmCompiledModule::GetTableValue(*old_signature_tables, int_index);
    2748             : 
    2749             :     code_specialization->RelocatePointer(old_func_table_addr,
    2750        1900 :                                          new_func_table_addr);
    2751             :     code_specialization->RelocatePointer(old_sig_table_addr,
    2752        1900 :                                          new_sig_table_addr);
    2753             :   }
    2754             : 
    2755             :   compiled_module_->set_function_tables(new_function_tables);
    2756             :   compiled_module_->set_signature_tables(new_signature_tables);
    2757        1900 : }
    2758             : 
    2759        1830 : void InstanceBuilder::LoadTableSegments(Handle<FixedArray> code_table,
    2760             :                                         Handle<WasmInstanceObject> instance) {
    2761        5070 :   int function_table_count = static_cast<int>(module_->function_tables.size());
    2762        3660 :   for (int index = 0; index < function_table_count; ++index) {
    2763        1830 :     TableInstance& table_instance = table_instances_[index];
    2764             : 
    2765             :     Handle<FixedArray> all_dispatch_tables;
    2766        1830 :     if (!table_instance.table_object.is_null()) {
    2767             :       // Get the existing dispatch table(s) with the WebAssembly.Table object.
    2768             :       all_dispatch_tables =
    2769             :           handle(table_instance.table_object->dispatch_tables());
    2770             :     }
    2771             : 
    2772             :     // Count the number of table exports for each function (needed for lazy
    2773             :     // compilation).
    2774        1830 :     std::unordered_map<uint32_t, uint32_t> num_table_exports;
    2775        3660 :     if (compile_lazy(module_)) {
    2776         425 :       for (auto& table_init : module_->table_inits) {
    2777        7047 :         for (uint32_t func_index : table_init.entries) {
    2778             :           Code* code =
    2779        6777 :               Code::cast(code_table->get(static_cast<int>(func_index)));
    2780             :           // Only increase the counter for lazy compile builtins (it's not
    2781             :           // needed otherwise).
    2782        6777 :           if (code->is_wasm_code()) continue;
    2783             :           DCHECK_EQ(Builtins::kWasmCompileLazy, code->builtin_index());
    2784        6543 :           ++num_table_exports[func_index];
    2785             :         }
    2786             :       }
    2787             :     }
    2788             : 
    2789             :     // TODO(titzer): this does redundant work if there are multiple tables,
    2790             :     // since initializations are not sorted by table index.
    2791        6750 :     for (auto& table_init : module_->table_inits) {
    2792        1260 :       uint32_t base = EvalUint32InitExpr(table_init.offset);
    2793       12102 :       uint32_t num_entries = static_cast<uint32_t>(table_init.entries.size());
    2794             :       DCHECK(in_bounds(base, num_entries,
    2795             :                        table_instance.function_table->length()));
    2796       10842 :       for (uint32_t i = 0; i < num_entries; ++i) {
    2797       19164 :         uint32_t func_index = table_init.entries[i];
    2798        9582 :         WasmFunction* function = &module_->functions[func_index];
    2799        9582 :         int table_index = static_cast<int>(i + base);
    2800       19164 :         uint32_t sig_index = module_->signature_ids[function->sig_index];
    2801             :         table_instance.signature_table->set(table_index,
    2802        9582 :                                             Smi::FromInt(sig_index));
    2803             :         Handle<Code> wasm_code = EnsureTableExportLazyDeoptData(
    2804             :             isolate_, instance, code_table, func_index,
    2805        9582 :             table_instance.function_table, table_index, num_table_exports);
    2806        9582 :         table_instance.function_table->set(table_index, *wasm_code);
    2807             : 
    2808        9582 :         if (!all_dispatch_tables.is_null()) {
    2809        6180 :           if (js_wrappers_[func_index].is_null()) {
    2810             :             // No JSFunction entry yet exists for this function. Create one.
    2811             :             // TODO(titzer): We compile JS->wasm wrappers for functions are
    2812             :             // not exported but are in an exported table. This should be done
    2813             :             // at module compile time and cached instead.
    2814             : 
    2815             :             Handle<Code> wrapper_code =
    2816             :                 js_to_wasm_cache_.CloneOrCompileJSToWasmWrapper(
    2817        1410 :                     isolate_, module_, wasm_code, func_index);
    2818             :             MaybeHandle<String> func_name;
    2819        2820 :             if (module_->is_asm_js()) {
    2820             :               // For modules arising from asm.js, honor the names section.
    2821             :               func_name = WasmCompiledModule::ExtractUtf8StringFromModuleBytes(
    2822           0 :                               isolate_, compiled_module_, function->name)
    2823           0 :                               .ToHandleChecked();
    2824             :             }
    2825             :             Handle<WasmExportedFunction> js_function =
    2826             :                 WasmExportedFunction::New(
    2827             :                     isolate_, instance, func_name, func_index,
    2828        1410 :                     static_cast<int>(function->sig->parameter_count()),
    2829        1410 :                     wrapper_code);
    2830        1410 :             js_wrappers_[func_index] = js_function;
    2831             :           }
    2832             :           table_instance.js_wrappers->set(table_index,
    2833        1590 :                                           *js_wrappers_[func_index]);
    2834             : 
    2835             :           UpdateDispatchTables(isolate_, all_dispatch_tables, table_index,
    2836        1590 :                                function, wasm_code);
    2837             :         }
    2838             :       }
    2839             :     }
    2840             : 
    2841             : #ifdef DEBUG
    2842             :     // Check that the count of table exports was accurate. The entries are
    2843             :     // decremented on each export, so all should be zero now.
    2844             :     for (auto e : num_table_exports) {
    2845             :       DCHECK_EQ(0, e.second);
    2846             :     }
    2847             : #endif
    2848             : 
    2849             :     // TODO(titzer): we add the new dispatch table at the end to avoid
    2850             :     // redundant work and also because the new instance is not yet fully
    2851             :     // initialized.
    2852        1830 :     if (!table_instance.table_object.is_null()) {
    2853             :       // Add the new dispatch table to the WebAssembly.Table object.
    2854             :       all_dispatch_tables = WasmTableObject::AddDispatchTable(
    2855             :           isolate_, table_instance.table_object, instance, index,
    2856        1290 :           table_instance.function_table, table_instance.signature_table);
    2857             :     }
    2858             :   }
    2859        1830 : }
    2860             : 
    2861         413 : AsyncCompileJob::AsyncCompileJob(Isolate* isolate,
    2862             :                                  std::unique_ptr<byte[]> bytes_copy,
    2863             :                                  size_t length, Handle<Context> context,
    2864             :                                  Handle<JSPromise> promise)
    2865             :     : isolate_(isolate),
    2866             :       async_counters_(isolate->async_counters()),
    2867             :       bytes_copy_(std::move(bytes_copy)),
    2868        2065 :       wire_bytes_(bytes_copy_.get(), bytes_copy_.get() + length) {
    2869             :   // The handles for the context and promise must be deferred.
    2870         413 :   DeferredHandleScope deferred(isolate);
    2871         413 :   context_ = Handle<Context>(*context);
    2872         413 :   module_promise_ = Handle<JSPromise>(*promise);
    2873         826 :   deferred_handles_.push_back(deferred.Detach());
    2874         413 : }
    2875             : 
    2876          63 : void AsyncCompileJob::Start() {
    2877          63 :   DoAsync<DecodeModule>();  // --
    2878          63 : }
    2879             : 
    2880          66 : void AsyncCompileJob::Abort() {
    2881          66 :   background_task_manager_.CancelAndWait();
    2882          66 :   if (num_pending_foreground_tasks_ == 0) {
    2883             :     // No task is pending, we can just remove the AsyncCompileJob.
    2884         198 :     isolate_->wasm_compilation_manager()->RemoveJob(this);
    2885             :   } else {
    2886             :     // There is still a compilation task in the task queue. We enter the
    2887             :     // AbortCompilation state and wait for this compilation task to abort the
    2888             :     // AsyncCompileJob.
    2889           0 :     NextStep<AbortCompilation>();
    2890             :   }
    2891          66 : }
    2892             : 
    2893        1400 : class AsyncStreamingProcessor final : public StreamingProcessor {
    2894             :  public:
    2895             :   explicit AsyncStreamingProcessor(AsyncCompileJob* job);
    2896             : 
    2897             :   bool ProcessModuleHeader(Vector<const uint8_t> bytes,
    2898             :                            uint32_t offset) override;
    2899             : 
    2900             :   bool ProcessSection(SectionCode section_code, Vector<const uint8_t> bytes,
    2901             :                       uint32_t offset) override;
    2902             : 
    2903             :   bool ProcessCodeSectionHeader(size_t functions_count,
    2904             :                                 uint32_t offset) override;
    2905             : 
    2906             :   bool ProcessFunctionBody(Vector<const uint8_t> bytes,
    2907             :                            uint32_t offset) override;
    2908             : 
    2909             :   void OnFinishedChunk() override;
    2910             : 
    2911             :   void OnFinishedStream(std::unique_ptr<uint8_t[]> bytes,
    2912             :                         size_t length) override;
    2913             : 
    2914             :   void OnError(DecodeResult result) override;
    2915             : 
    2916             :   void OnAbort() override;
    2917             : 
    2918             :  private:
    2919             :   // Finishes the AsyncCOmpileJob with an error.
    2920             :   void FinishAsyncCompileJobWithError(ResultBase result);
    2921             : 
    2922             :   ModuleDecoder decoder_;
    2923             :   AsyncCompileJob* job_;
    2924             :   std::unique_ptr<ModuleCompiler::CompilationUnitBuilder>
    2925             :       compilation_unit_builder_;
    2926             :   uint32_t next_function_ = 0;
    2927             : };
    2928             : 
    2929         350 : std::shared_ptr<StreamingDecoder> AsyncCompileJob::CreateStreamingDecoder() {
    2930             :   DCHECK_NULL(stream_);
    2931             :   stream_.reset(
    2932        1400 :       new StreamingDecoder(base::make_unique<AsyncStreamingProcessor>(this)));
    2933         350 :   return stream_;
    2934             : }
    2935             : 
    2936         826 : AsyncCompileJob::~AsyncCompileJob() {
    2937         413 :   background_task_manager_.CancelAndWait();
    2938        1609 :   for (auto d : deferred_handles_) delete d;
    2939         413 : }
    2940             : 
    2941         231 : void AsyncCompileJob::AsyncCompileFailed(ErrorThrower& thrower) {
    2942         231 :   if (stream_) stream_->NotifyError();
    2943             :   // {job} keeps the {this} pointer alive.
    2944             :   std::shared_ptr<AsyncCompileJob> job =
    2945         462 :       isolate_->wasm_compilation_manager()->RemoveJob(this);
    2946         231 :   RejectPromise(isolate_, context_, thrower, module_promise_);
    2947         231 : }
    2948             : 
    2949         115 : void AsyncCompileJob::AsyncCompileSucceeded(Handle<Object> result) {
    2950             :   // {job} keeps the {this} pointer alive.
    2951             :   std::shared_ptr<AsyncCompileJob> job =
    2952         230 :       isolate_->wasm_compilation_manager()->RemoveJob(this);
    2953         115 :   ResolvePromise(isolate_, context_, module_promise_, result);
    2954         115 : }
    2955             : 
    2956             : // A closure to run a compilation step (either as foreground or background
    2957             : // task) and schedule the next step(s), if any.
    2958             : class AsyncCompileJob::CompileStep {
    2959             :  public:
    2960             :   explicit CompileStep(size_t num_background_tasks = 0)
    2961        1108 :       : num_background_tasks_(num_background_tasks) {}
    2962             : 
    2963        1108 :   virtual ~CompileStep() {}
    2964             : 
    2965        1416 :   void Run(bool on_foreground) {
    2966        1416 :     if (on_foreground) {
    2967         986 :       HandleScope scope(job_->isolate_);
    2968         986 :       --job_->num_pending_foreground_tasks_;
    2969             :       DCHECK_EQ(0, job_->num_pending_foreground_tasks_);
    2970        1972 :       SaveContext saved_context(job_->isolate_);
    2971        1972 :       job_->isolate_->set_context(*job_->context_);
    2972         986 :       RunInForeground();
    2973             :     } else {
    2974         430 :       RunInBackground();
    2975             :     }
    2976        1416 :   }
    2977             : 
    2978           0 :   virtual void RunInForeground() { UNREACHABLE(); }
    2979           0 :   virtual void RunInBackground() { UNREACHABLE(); }
    2980             : 
    2981             :   size_t NumberOfBackgroundTasks() { return num_background_tasks_; }
    2982             : 
    2983             :   AsyncCompileJob* job_ = nullptr;
    2984             :   const size_t num_background_tasks_;
    2985             : };
    2986             : 
    2987        2518 : class AsyncCompileJob::CompileTask : public CancelableTask {
    2988             :  public:
    2989             :   CompileTask(AsyncCompileJob* job, bool on_foreground)
    2990             :       // We only manage the background tasks with the {CancelableTaskManager} of
    2991             :       // the {AsyncCompileJob}. Foreground tasks are managed by the system's
    2992             :       // {CancelableTaskManager}. Background tasks cannot spawn tasks managed by
    2993             :       // their own task manager.
    2994         793 :       : CancelableTask(on_foreground ? job->isolate_->cancelable_task_manager()
    2995             :                                      : &job->background_task_manager_),
    2996             :         job_(job),
    2997        1259 :         on_foreground_(on_foreground) {}
    2998             : 
    2999        2444 :   void RunInternal() override { job_->step_->Run(on_foreground_); }
    3000             : 
    3001             :  private:
    3002             :   AsyncCompileJob* job_;
    3003             :   bool on_foreground_;
    3004             : };
    3005             : 
    3006         793 : void AsyncCompileJob::StartForegroundTask() {
    3007         793 :   ++num_pending_foreground_tasks_;
    3008             :   DCHECK_EQ(1, num_pending_foreground_tasks_);
    3009             : 
    3010         793 :   v8::Platform* platform = V8::GetCurrentPlatform();
    3011             :   // TODO(ahaas): This is a CHECK to debug issue 764313.
    3012         793 :   CHECK(platform);
    3013             :   platform->CallOnForegroundThread(reinterpret_cast<v8::Isolate*>(isolate_),
    3014        1586 :                                    new CompileTask(this, true));
    3015         793 : }
    3016             : 
    3017             : template <typename Step, typename... Args>
    3018             : void AsyncCompileJob::DoSync(Args&&... args) {
    3019         596 :   NextStep<Step>(std::forward<Args>(args)...);
    3020         596 :   StartForegroundTask();
    3021             : }
    3022             : 
    3023         466 : void AsyncCompileJob::StartBackgroundTask() {
    3024         466 :   V8::GetCurrentPlatform()->CallOnBackgroundThread(
    3025         932 :       new CompileTask(this, false), v8::Platform::kShortRunningTask);
    3026         466 : }
    3027             : 
    3028         288 : void AsyncCompileJob::RestartBackgroundTasks() {
    3029             :   size_t num_restarts = stopped_tasks_.Value();
    3030             :   stopped_tasks_.Decrement(num_restarts);
    3031             : 
    3032         516 :   for (size_t i = 0; i < num_restarts; ++i) {
    3033         228 :     StartBackgroundTask();
    3034             :   }
    3035         288 : }
    3036             : 
    3037             : template <typename Step, typename... Args>
    3038         124 : void AsyncCompileJob::DoAsync(Args&&... args) {
    3039         124 :   NextStep<Step>(std::forward<Args>(args)...);
    3040         124 :   size_t end = step_->NumberOfBackgroundTasks();
    3041         362 :   for (size_t i = 0; i < end; ++i) {
    3042         238 :     StartBackgroundTask();
    3043             :   }
    3044         124 : }
    3045             : 
    3046             : template <typename Step, typename... Args>
    3047        1108 : void AsyncCompileJob::NextStep(Args&&... args) {
    3048        1297 :   step_.reset(new Step(std::forward<Args>(args)...));
    3049        1108 :   step_->job_ = this;
    3050        1108 : }
    3051             : 
    3052             : //==========================================================================
    3053             : // Step 1: (async) Decode the module.
    3054             : //==========================================================================
    3055         126 : class AsyncCompileJob::DecodeModule : public AsyncCompileJob::CompileStep {
    3056             :  public:
    3057          63 :   DecodeModule() : CompileStep(1) {}
    3058             : 
    3059          63 :   void RunInBackground() override {
    3060             :     ModuleResult result;
    3061             :     {
    3062             :       DisallowHandleAllocation no_handle;
    3063             :       DisallowHeapAllocation no_allocation;
    3064             :       // Decode the module bytes.
    3065          63 :       TRACE_COMPILE("(1) Decoding module...\n");
    3066         252 :       result = AsyncDecodeWasmModule(job_->isolate_, job_->wire_bytes_.start(),
    3067             :                                      job_->wire_bytes_.end(), false,
    3068         126 :                                      kWasmOrigin, job_->async_counters());
    3069             :     }
    3070          63 :     if (result.failed()) {
    3071             :       // Decoding failure; reject the promise and clean up.
    3072           1 :       job_->DoSync<DecodeFail>(std::move(result));
    3073             :     } else {
    3074             :       // Decode passed.
    3075          62 :       job_->module_ = std::move(result.val);
    3076         186 :       job_->DoSync<PrepareAndStartCompile>(job_->module_.get(), true);
    3077          63 :     }
    3078          63 :   }
    3079             : };
    3080             : 
    3081             : //==========================================================================
    3082             : // Step 1b: (sync) Fail decoding the module.
    3083             : //==========================================================================
    3084         378 : class AsyncCompileJob::DecodeFail : public CompileStep {
    3085             :  public:
    3086         189 :   explicit DecodeFail(ModuleResult result) : result_(std::move(result)) {}
    3087             : 
    3088             :  private:
    3089             :   ModuleResult result_;
    3090         189 :   void RunInForeground() override {
    3091         189 :     TRACE_COMPILE("(1b) Decoding failed.\n");
    3092         189 :     ErrorThrower thrower(job_->isolate_, "AsyncCompile");
    3093             :     thrower.CompileFailed("Wasm decoding failed", result_);
    3094             :     // {job_} is deleted in AsyncCompileFailed, therefore the {return}.
    3095         189 :     return job_->AsyncCompileFailed(thrower);
    3096             :   }
    3097             : };
    3098             : 
    3099             : //==========================================================================
    3100             : // Step 2 (sync): Create heap-allocated data and start compile.
    3101             : //==========================================================================
    3102         512 : class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
    3103             :  public:
    3104             :   explicit PrepareAndStartCompile(WasmModule* module, bool start_compilation)
    3105         256 :       : module_(module), start_compilation_(start_compilation) {}
    3106             : 
    3107             :  private:
    3108             :   WasmModule* module_;
    3109             :   bool start_compilation_;
    3110             : 
    3111         255 :   void RunInForeground() override {
    3112         255 :     TRACE_COMPILE("(2) Prepare and start compile...\n");
    3113         255 :     Isolate* isolate = job_->isolate_;
    3114             : 
    3115             :     Factory* factory = isolate->factory();
    3116         255 :     Handle<Code> illegal_builtin = BUILTIN_CODE(isolate, Illegal);
    3117         510 :     job_->module_env_ =
    3118             :         CreateDefaultModuleEnv(isolate, module_, illegal_builtin);
    3119             : 
    3120             :     // The {code_table} array contains import wrappers and functions (which
    3121             :     // are both included in {functions.size()}.
    3122             :     // The results of compilation will be written into it.
    3123             :     // Initialize {code_table_} with the illegal builtin. All call sites
    3124             :     // will be patched at instantiation.
    3125         765 :     int code_table_size = static_cast<int>(module_->functions.size());
    3126         255 :     int export_wrapper_size = static_cast<int>(module_->num_exported_functions);
    3127         255 :     job_->code_table_ = factory->NewFixedArray(code_table_size, TENURED);
    3128             :     job_->export_wrappers_ =
    3129         255 :         factory->NewFixedArray(export_wrapper_size, TENURED);
    3130             : 
    3131         256 :     for (int i = 0, e = module_->num_imported_functions; i < e; ++i) {
    3132           2 :       job_->code_table_->set(i, *illegal_builtin);
    3133             :     }
    3134             :     // Transfer ownership of the {WasmModule} to the {ModuleCompiler}, but
    3135             :     // keep a pointer.
    3136         510 :     Handle<Code> centry_stub = CEntryStub(isolate, 1).GetCode();
    3137             :     {
    3138             :       // Now reopen the handles in a deferred scope in order to use
    3139             :       // them in the concurrent steps.
    3140         255 :       DeferredHandleScope deferred(isolate);
    3141             : 
    3142             :       centry_stub = Handle<Code>(*centry_stub, isolate);
    3143         510 :       job_->code_table_ = Handle<FixedArray>(*job_->code_table_, isolate);
    3144             :       job_->export_wrappers_ =
    3145         510 :           Handle<FixedArray>(*job_->export_wrappers_, isolate);
    3146         255 :       compiler::ModuleEnv* env = job_->module_env_.get();
    3147         255 :       ReopenHandles(isolate, env->function_code);
    3148             :       Handle<Code>* mut =
    3149             :           const_cast<Handle<Code>*>(&env->default_function_code);
    3150         255 :       *mut = Handle<Code>(**mut, isolate);
    3151             : 
    3152         510 :       job_->deferred_handles_.push_back(deferred.Detach());
    3153             :     }
    3154             : 
    3155         510 :     job_->compiler_.reset(new ModuleCompiler(isolate, module_, centry_stub));
    3156         255 :     job_->compiler_->EnableThrottling();
    3157             : 
    3158             :     DCHECK_LE(module_->num_imported_functions, module_->functions.size());
    3159             :     size_t num_functions =
    3160         510 :         module_->functions.size() - module_->num_imported_functions;
    3161         255 :     if (num_functions == 0) {
    3162             :       // Degenerate case of an empty module.
    3163           0 :       job_->DoSync<FinishCompile>();
    3164         255 :       return;
    3165             :     }
    3166             : 
    3167             :     // Start asynchronous compilation tasks.
    3168             :     size_t num_background_tasks =
    3169             :         Max(static_cast<size_t>(1),
    3170             :             Min(num_functions,
    3171             :                 Min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks),
    3172         255 :                     V8::GetCurrentPlatform()
    3173         510 :                         ->NumberOfAvailableBackgroundThreads())));
    3174             : 
    3175         255 :     if (start_compilation_) {
    3176             :       // TODO(ahaas): Try to remove the {start_compilation_} check when
    3177             :       // streaming decoding is done in the background. If
    3178             :       // InitializeCompilationUnits always returns 0 for streaming compilation,
    3179             :       // then DoAsync would do the same as NextStep already.
    3180             :       job_->outstanding_units_ = job_->compiler_->InitializeCompilationUnits(
    3181         183 :           module_->functions, job_->wire_bytes_, job_->module_env_.get());
    3182             : 
    3183          61 :       job_->DoAsync<ExecuteAndFinishCompilationUnits>(num_background_tasks);
    3184             :     } else {
    3185         194 :       job_->stopped_tasks_ = num_background_tasks;
    3186         194 :       job_->NextStep<ExecuteAndFinishCompilationUnits>(num_background_tasks);
    3187             :     }
    3188             :   }
    3189             : };
    3190             : 
    3191             : //==========================================================================
    3192             : // Step 3 (async x K tasks): Execute compilation units.
    3193             : //==========================================================================
    3194         510 : class AsyncCompileJob::ExecuteAndFinishCompilationUnits : public CompileStep {
    3195             :  public:
    3196             :   explicit ExecuteAndFinishCompilationUnits(size_t num_compile_tasks)
    3197         255 :       : CompileStep(num_compile_tasks) {}
    3198             : 
    3199         367 :   void RunInBackground() override {
    3200         199 :     std::function<void()> StartFinishCompilationUnit = [this]() {
    3201         398 :       if (!failed_) job_->StartForegroundTask();
    3202         199 :     };
    3203             : 
    3204         367 :     TRACE_COMPILE("(3) Compiling...\n");
    3205        3764 :     while (job_->compiler_->CanAcceptWork()) {
    3206        1882 :       if (failed_) break;
    3207             :       DisallowHandleAllocation no_handle;
    3208             :       DisallowHeapAllocation no_allocation;
    3209        1867 :       if (!job_->compiler_->FetchAndExecuteCompilationUnit(
    3210        5603 :               StartFinishCompilationUnit)) {
    3211             :         finished_ = true;
    3212             :         break;
    3213             :       }
    3214             :     }
    3215         366 :     job_->stopped_tasks_.Increment(1);
    3216         367 :   }
    3217             : 
    3218         197 :   void RunInForeground() override {
    3219         197 :     TRACE_COMPILE("(4a) Finishing compilation units...\n");
    3220         197 :     if (failed_) {
    3221             :       // The job failed already, no need to do more work.
    3222           0 :       job_->compiler_->SetFinisherIsRunning(false);
    3223          44 :       return;
    3224             :     }
    3225         197 :     ErrorThrower thrower(job_->isolate_, "AsyncCompile");
    3226             : 
    3227             :     // We execute for 1 ms and then reschedule the task, same as the GC.
    3228         197 :     double deadline = MonotonicallyIncreasingTimeInMs() + 1.0;
    3229             : 
    3230             :     while (true) {
    3231        1519 :       if (!finished_ && job_->compiler_->ShouldIncreaseWorkload()) {
    3232          36 :         job_->RestartBackgroundTasks();
    3233             :       }
    3234             : 
    3235        1483 :       int func_index = -1;
    3236             : 
    3237             :       MaybeHandle<Code> result =
    3238        2966 :           job_->compiler_->FinishCompilationUnit(&thrower, &func_index);
    3239             : 
    3240        1483 :       if (thrower.error()) {
    3241             :         // An error was detected, we stop compiling and wait for the
    3242             :         // background tasks to finish.
    3243             :         failed_ = true;
    3244         195 :         break;
    3245        1441 :       } else if (result.is_null()) {
    3246             :         // The working queue was empty, we break the loop. If new work units
    3247             :         // are enqueued, the background task will start this
    3248             :         // FinishCompilationUnits task again.
    3249             :         break;
    3250             :       } else {
    3251             :         DCHECK_LE(0, func_index);
    3252        2576 :         job_->code_table_->set(func_index, *result.ToHandleChecked());
    3253        1288 :         --job_->outstanding_units_;
    3254             :       }
    3255             : 
    3256        1288 :       if (deadline < MonotonicallyIncreasingTimeInMs()) {
    3257             :         // We reached the deadline. We reschedule this task and return
    3258             :         // immediately. Since we rescheduled this task already, we do not set
    3259             :         // the FinisherIsRunning flat to false.
    3260           2 :         job_->StartForegroundTask();
    3261           2 :         return;
    3262             :       }
    3263             :     }
    3264             :     // This task finishes without being rescheduled. Therefore we set the
    3265             :     // FinisherIsRunning flag to false.
    3266         195 :     job_->compiler_->SetFinisherIsRunning(false);
    3267         195 :     if (thrower.error()) {
    3268             :       // Make sure all compilation tasks stopped running.
    3269          42 :       job_->background_task_manager_.CancelAndWait();
    3270          42 :       return job_->AsyncCompileFailed(thrower);
    3271             :     }
    3272         153 :     if (job_->outstanding_units_ == 0) {
    3273             :       // Make sure all compilation tasks stopped running.
    3274         121 :       job_->background_task_manager_.CancelAndWait();
    3275         242 :       if (job_->DecrementAndCheckFinisherCount()) job_->DoSync<FinishCompile>();
    3276         153 :     }
    3277             :   }
    3278             : 
    3279             :  private:
    3280             :   std::atomic<bool> failed_{false};
    3281             :   std::atomic<bool> finished_{false};
    3282             : };
    3283             : 
    3284             : //==========================================================================
    3285             : // Step 5 (sync): Finish heap-allocated data structures.
    3286             : //==========================================================================
    3287         345 : class AsyncCompileJob::FinishCompile : public CompileStep {
    3288         115 :   void RunInForeground() override {
    3289         115 :     TRACE_COMPILE("(5b) Finish compile...\n");
    3290             :     // At this point, compilation has completed. Update the code table.
    3291        1285 :     for (int i = FLAG_skip_compiling_wasm_funcs,
    3292         115 :              e = job_->code_table_->length();
    3293             :          i < e; ++i) {
    3294        1055 :       Object* val = job_->code_table_->get(i);
    3295        2110 :       if (val->IsCode()) RecordStats(Code::cast(val), job_->counters());
    3296             :     }
    3297             : 
    3298             :     // Create heap objects for script and module bytes to be stored in the
    3299             :     // shared module data. Asm.js is not compiled asynchronously.
    3300         230 :     Handle<Script> script = CreateWasmScript(job_->isolate_, job_->wire_bytes_);
    3301             :     Handle<ByteArray> asm_js_offset_table;
    3302             :     // TODO(wasm): Improve efficiency of storing module wire bytes.
    3303             :     //   1. Only store relevant sections, not function bodies
    3304             :     //   2. Don't make a second copy of the bytes here; reuse the copy made
    3305             :     //      for asynchronous compilation and store it as an external one
    3306             :     //      byte string for serialization/deserialization.
    3307             :     Handle<String> module_bytes =
    3308             :         job_->isolate_->factory()
    3309             :             ->NewStringFromOneByte(
    3310             :                 {job_->wire_bytes_.start(), job_->wire_bytes_.length()},
    3311         345 :                 TENURED)
    3312         230 :             .ToHandleChecked();
    3313             :     DCHECK(module_bytes->IsSeqOneByteString());
    3314             : 
    3315             :     // The {module_wrapper} will take ownership of the {WasmModule} object,
    3316             :     // and it will be destroyed when the GC reclaims the wrapper object.
    3317             :     Handle<WasmModuleWrapper> module_wrapper =
    3318         230 :         WasmModuleWrapper::From(job_->isolate_, job_->module_.release());
    3319             : 
    3320             :     // Create the shared module data.
    3321             :     // TODO(clemensh): For the same module (same bytes / same hash), we should
    3322             :     // only have one WasmSharedModuleData. Otherwise, we might only set
    3323             :     // breakpoints on a (potentially empty) subset of the instances.
    3324             : 
    3325             :     Handle<WasmSharedModuleData> shared =
    3326             :         WasmSharedModuleData::New(job_->isolate_, module_wrapper,
    3327             :                                   Handle<SeqOneByteString>::cast(module_bytes),
    3328         115 :                                   script, asm_js_offset_table);
    3329             : 
    3330             :     // Create the compiled module object and populate with compiled functions
    3331             :     // and information needed at instantiation time. This object needs to be
    3332             :     // serializable. Instantiation may occur off a deserialized version of
    3333             :     // this object.
    3334             :     job_->compiled_module_ =
    3335             :         NewCompiledModule(job_->isolate_, shared, job_->code_table_,
    3336         345 :                           job_->export_wrappers_, job_->module_env_.get());
    3337             :     // Finish the wasm script now and make it public to the debugger.
    3338         230 :     script->set_wasm_compiled_module(*job_->compiled_module_);
    3339         230 :     job_->isolate_->debug()->OnAfterCompile(script);
    3340             : 
    3341         115 :     DeferredHandleScope deferred(job_->isolate_);
    3342         230 :     job_->compiled_module_ = handle(*job_->compiled_module_, job_->isolate_);
    3343         230 :     job_->deferred_handles_.push_back(deferred.Detach());
    3344             :     // TODO(wasm): compiling wrappers should be made async as well.
    3345         230 :     job_->DoSync<CompileWrappers>();
    3346         115 :   }
    3347             : };
    3348             : 
    3349             : //==========================================================================
    3350             : // Step 6 (sync): Compile JS->wasm wrappers.
    3351             : //==========================================================================
    3352         345 : class AsyncCompileJob::CompileWrappers : public CompileStep {
    3353             :   // TODO(wasm): Compile all wrappers here, including the start function wrapper
    3354             :   // and the wrappers for the function table elements.
    3355         115 :   void RunInForeground() override {
    3356         115 :     TRACE_COMPILE("(6) Compile wrappers...\n");
    3357             :     // Compile JS->wasm wrappers for exported functions.
    3358             :     JSToWasmWrapperCache js_to_wasm_cache;
    3359             :     int wrapper_index = 0;
    3360         230 :     WasmModule* module = job_->compiled_module_->module();
    3361        1231 :     for (auto exp : module->export_table) {
    3362        1020 :       if (exp.kind != kExternalFunction) continue;
    3363             :       Handle<Code> wasm_code(Code::cast(job_->code_table_->get(exp.index)),
    3364         982 :                              job_->isolate_);
    3365             :       Handle<Code> wrapper_code =
    3366             :           js_to_wasm_cache.CloneOrCompileJSToWasmWrapper(job_->isolate_, module,
    3367         982 :                                                          wasm_code, exp.index);
    3368        1964 :       job_->export_wrappers_->set(wrapper_index, *wrapper_code);
    3369        1964 :       RecordStats(*wrapper_code, job_->counters());
    3370         982 :       ++wrapper_index;
    3371             :     }
    3372             : 
    3373         230 :     job_->DoSync<FinishModule>();
    3374         115 :   }
    3375             : };
    3376             : 
    3377             : //==========================================================================
    3378             : // Step 7 (sync): Finish the module and resolve the promise.
    3379             : //==========================================================================
    3380         345 : class AsyncCompileJob::FinishModule : public CompileStep {
    3381         115 :   void RunInForeground() override {
    3382         115 :     TRACE_COMPILE("(7) Finish module...\n");
    3383             :     Handle<WasmModuleObject> result =
    3384         115 :         WasmModuleObject::New(job_->isolate_, job_->compiled_module_);
    3385             :     // {job_} is deleted in AsyncCompileSucceeded, therefore the {return}.
    3386         115 :     return job_->AsyncCompileSucceeded(result);
    3387             :   }
    3388             : };
    3389             : 
    3390           0 : class AsyncCompileJob::AbortCompilation : public CompileStep {
    3391           0 :   void RunInForeground() override {
    3392           0 :     TRACE_COMPILE("Abort asynchronous compilation ...\n");
    3393           0 :     job_->isolate_->wasm_compilation_manager()->RemoveJob(job_);
    3394           0 :   }
    3395             : };
    3396             : 
    3397           0 : AsyncStreamingProcessor::AsyncStreamingProcessor(AsyncCompileJob* job)
    3398         350 :     : job_(job), compilation_unit_builder_(nullptr) {}
    3399             : 
    3400         188 : void AsyncStreamingProcessor::FinishAsyncCompileJobWithError(ResultBase error) {
    3401             :   // Make sure all background tasks stopped executing before we change the state
    3402             :   // of the AsyncCompileJob to DecodeFail.
    3403         188 :   job_->background_task_manager_.CancelAndWait();
    3404             : 
    3405             :   // Create a ModuleResult from the result we got as parameter. Since there was
    3406             :   // no error, we don't have to provide a real wasm module to the ModuleResult.
    3407             :   ModuleResult result(nullptr);
    3408         188 :   result.MoveErrorFrom(error);
    3409             : 
    3410             :   // Check if there is already a ModuleCompiler, in which case we have to clean
    3411             :   // it up as well.
    3412         376 :   if (job_->compiler_) {
    3413             :     // If {IsFinisherRunning} is true, then there is already a foreground task
    3414             :     // in the task queue to execute the DecodeFail step. We do not have to start
    3415             :     // a new task ourselves with DoSync.
    3416          56 :     if (job_->compiler_->IsFinisherRunning()) {
    3417           0 :       job_->NextStep<AsyncCompileJob::DecodeFail>(std::move(result));
    3418             :     } else {
    3419             :       job_->DoSync<AsyncCompileJob::DecodeFail>(std::move(result));
    3420             :     }
    3421             : 
    3422             :     compilation_unit_builder_->Clear();
    3423             :   } else {
    3424             :     job_->DoSync<AsyncCompileJob::DecodeFail>(std::move(result));
    3425         188 :   }
    3426         188 : }
    3427             : 
    3428             : // Process the module header.
    3429         344 : bool AsyncStreamingProcessor::ProcessModuleHeader(Vector<const uint8_t> bytes,
    3430             :                                                   uint32_t offset) {
    3431         344 :   TRACE_STREAMING("Process module header...\n");
    3432         344 :   decoder_.StartDecoding(job_->isolate());
    3433         344 :   decoder_.DecodeModuleHeader(bytes, offset);
    3434         344 :   if (!decoder_.ok()) {
    3435          60 :     FinishAsyncCompileJobWithError(decoder_.FinishDecoding(false));
    3436          20 :     return false;
    3437             :   }
    3438             :   return true;
    3439             : }
    3440             : 
    3441             : // Process all sections except for the code section.
    3442         718 : bool AsyncStreamingProcessor::ProcessSection(SectionCode section_code,
    3443             :                                              Vector<const uint8_t> bytes,
    3444             :                                              uint32_t offset) {
    3445         718 :   TRACE_STREAMING("Process section %d ...\n", section_code);
    3446         718 :   if (section_code == SectionCode::kUnknownSectionCode) {
    3447             :     // No need to decode unknown sections, even the names section. If decoding
    3448             :     // of the unknown section fails, compilation should succeed anyways, and
    3449             :     // even decoding the names section is unnecessary because the result comes
    3450             :     // too late for streaming compilation.
    3451             :     return true;
    3452             :   }
    3453             :   constexpr bool verify_functions = false;
    3454         668 :   decoder_.DecodeSection(section_code, bytes, offset, verify_functions);
    3455         668 :   if (!decoder_.ok()) {
    3456          84 :     FinishAsyncCompileJobWithError(decoder_.FinishDecoding(false));
    3457          28 :     return false;
    3458             :   }
    3459             :   return true;
    3460             : }
    3461             : 
    3462             : // Start the code section.
    3463         210 : bool AsyncStreamingProcessor::ProcessCodeSectionHeader(size_t functions_count,
    3464             :                                                        uint32_t offset) {
    3465         210 :   TRACE_STREAMING("Start the code section with %zu functions...\n",
    3466             :                   functions_count);
    3467         210 :   if (!decoder_.CheckFunctionsCount(static_cast<uint32_t>(functions_count),
    3468         210 :                                     offset)) {
    3469          48 :     FinishAsyncCompileJobWithError(decoder_.FinishDecoding(false));
    3470          16 :     return false;
    3471             :   }
    3472         194 :   job_->NextStep<AsyncCompileJob::PrepareAndStartCompile>(decoder_.module(),
    3473         388 :                                                           false);
    3474             :   // Execute the PrepareAndStartCompile step immediately and not in a separate
    3475             :   // task. The step expects to be run on a separate foreground thread though, so
    3476             :   // we to increment {num_pending_foreground_tasks_} to look like one.
    3477         194 :   ++job_->num_pending_foreground_tasks_;
    3478             :   DCHECK_EQ(1, job_->num_pending_foreground_tasks_);
    3479             :   constexpr bool on_foreground = true;
    3480         388 :   job_->step_->Run(on_foreground);
    3481             : 
    3482         194 :   job_->outstanding_units_ = functions_count;
    3483             :   // Set outstanding_finishers_ to 2, because both the AsyncCompileJob and the
    3484             :   // AsyncStreamingProcessor have to finish.
    3485         194 :   job_->outstanding_finishers_.SetValue(2);
    3486         194 :   next_function_ = decoder_.module()->num_imported_functions +
    3487         194 :                    FLAG_skip_compiling_wasm_funcs;
    3488             :   compilation_unit_builder_.reset(
    3489         388 :       new ModuleCompiler::CompilationUnitBuilder(job_->compiler_.get()));
    3490             :   return true;
    3491             : }
    3492             : 
    3493             : // Process a function body.
    3494         438 : bool AsyncStreamingProcessor::ProcessFunctionBody(Vector<const uint8_t> bytes,
    3495             :                                                   uint32_t offset) {
    3496         438 :   TRACE_STREAMING("Process function body %d ...\n", next_function_);
    3497             : 
    3498             :   decoder_.DecodeFunctionBody(
    3499         876 :       next_function_, static_cast<uint32_t>(bytes.length()), offset, false);
    3500         438 :   if (next_function_ >= decoder_.module()->num_imported_functions +
    3501             :                             FLAG_skip_compiling_wasm_funcs) {
    3502         438 :     const WasmFunction* func = &decoder_.module()->functions[next_function_];
    3503             :     WasmName name = {nullptr, 0};
    3504             :     compilation_unit_builder_->AddUnit(job_->module_env_.get(), func, offset,
    3505         876 :                                        bytes, name);
    3506             :   }
    3507         438 :   ++next_function_;
    3508         438 :   return true;
    3509             : }
    3510             : 
    3511         306 : void AsyncStreamingProcessor::OnFinishedChunk() {
    3512             :   // TRACE_STREAMING("FinishChunk...\n");
    3513         306 :   if (compilation_unit_builder_) {
    3514         252 :     compilation_unit_builder_->Commit();
    3515         252 :     job_->RestartBackgroundTasks();
    3516             :   }
    3517         306 : }
    3518             : 
    3519             : // Finish the processing of the stream.
    3520          84 : void AsyncStreamingProcessor::OnFinishedStream(std::unique_ptr<uint8_t[]> bytes,
    3521             :                                                size_t length) {
    3522          84 :   TRACE_STREAMING("Finish stream...\n");
    3523          84 :   job_->bytes_copy_ = std::move(bytes);
    3524             :   job_->wire_bytes_ = ModuleWireBytes(job_->bytes_copy_.get(),
    3525         252 :                                       job_->bytes_copy_.get() + length);
    3526         168 :   ModuleResult result = decoder_.FinishDecoding(false);
    3527             :   DCHECK(result.ok());
    3528          84 :   job_->module_ = std::move(result.val);
    3529         168 :   if (job_->DecrementAndCheckFinisherCount())
    3530          96 :     job_->DoSync<AsyncCompileJob::FinishCompile>();
    3531          84 : }
    3532             : 
    3533             : // Report an error detected in the StreamingDecoder.
    3534         124 : void AsyncStreamingProcessor::OnError(DecodeResult result) {
    3535         124 :   TRACE_STREAMING("Stream error...\n");
    3536         248 :   FinishAsyncCompileJobWithError(std::move(result));
    3537         124 : }
    3538             : 
    3539          66 : void AsyncStreamingProcessor::OnAbort() {
    3540          66 :   TRACE_STREAMING("Abort stream...\n");
    3541          66 :   job_->Abort();
    3542          66 : }
    3543             : 
    3544             : }  // namespace wasm
    3545             : }  // namespace internal
    3546             : }  // namespace v8
    3547             : 
    3548             : #undef TRACE
    3549             : #undef TRACE_COMPILE
    3550             : #undef TRACE_STREAMING
    3551             : #undef TRACE_CHAIN
    3552             : #undef ERROR_THROWER_WITH_MESSAGE

Generated by: LCOV version 1.10