Home | History | Annotate | Download | only in wasm
      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 "src/api.h"
      8 #include "src/asmjs/asm-js.h"
      9 #include "src/base/optional.h"
     10 #include "src/base/template-utils.h"
     11 #include "src/base/utils/random-number-generator.h"
     12 #include "src/compiler/wasm-compiler.h"
     13 #include "src/counters.h"
     14 #include "src/identity-map.h"
     15 #include "src/property-descriptor.h"
     16 #include "src/tracing/trace-event.h"
     17 #include "src/trap-handler/trap-handler.h"
     18 #include "src/wasm/module-decoder.h"
     19 #include "src/wasm/streaming-decoder.h"
     20 #include "src/wasm/wasm-code-manager.h"
     21 #include "src/wasm/wasm-engine.h"
     22 #include "src/wasm/wasm-js.h"
     23 #include "src/wasm/wasm-limits.h"
     24 #include "src/wasm/wasm-memory.h"
     25 #include "src/wasm/wasm-objects-inl.h"
     26 #include "src/wasm/wasm-result.h"
     27 
     28 #define TRACE(...)                                      \
     29   do {                                                  \
     30     if (FLAG_trace_wasm_instances) PrintF(__VA_ARGS__); \
     31   } while (false)
     32 
     33 #define TRACE_COMPILE(...)                             \
     34   do {                                                 \
     35     if (FLAG_trace_wasm_compiler) PrintF(__VA_ARGS__); \
     36   } while (false)
     37 
     38 #define TRACE_STREAMING(...)                            \
     39   do {                                                  \
     40     if (FLAG_trace_wasm_streaming) PrintF(__VA_ARGS__); \
     41   } while (false)
     42 
     43 #define TRACE_LAZY(...)                                        \
     44   do {                                                         \
     45     if (FLAG_trace_wasm_lazy_compilation) PrintF(__VA_ARGS__); \
     46   } while (false)
     47 
     48 namespace v8 {
     49 namespace internal {
     50 namespace wasm {
     51 
     52 enum class CompilationEvent : uint8_t {
     53   kFinishedBaselineCompilation,
     54   kFinishedTopTierCompilation,
     55   kFailedCompilation
     56 };
     57 
     58 enum class CompileMode : uint8_t { kRegular, kTiering };
     59 
     60 // The CompilationState keeps track of the compilation state of the
     61 // owning NativeModule, i.e. which functions are left to be compiled.
     62 // It contains a task manager to allow parallel and asynchronous background
     63 // compilation of functions.
     64 class CompilationState {
     65  public:
     66   CompilationState(internal::Isolate*, const ModuleEnv&);
     67   ~CompilationState();
     68 
     69   // Set the number of compilations unit expected to be executed. Needs to be
     70   // set before {AddCompilationUnits} is run, which triggers background
     71   // compilation.
     72   void SetNumberOfFunctionsToCompile(size_t num_functions);
     73 
     74   // Set the callback function to be called on compilation events. Needs to be
     75   // set before {AddCompilationUnits} is run.
     76   void SetCallback(
     77       std::function<void(CompilationEvent, ErrorThrower*)> callback);
     78 
     79   // Inserts new functions to compile and kicks off compilation.
     80   void AddCompilationUnits(
     81       std::vector<std::unique_ptr<WasmCompilationUnit>>& baseline_units,
     82       std::vector<std::unique_ptr<WasmCompilationUnit>>& tiering_units);
     83   std::unique_ptr<WasmCompilationUnit> GetNextCompilationUnit();
     84   std::unique_ptr<WasmCompilationUnit> GetNextExecutedUnit();
     85 
     86   bool HasCompilationUnitToFinish();
     87 
     88   void OnError(ErrorThrower* thrower);
     89   void OnFinishedUnit();
     90   void ScheduleUnitForFinishing(std::unique_ptr<WasmCompilationUnit> unit,
     91                                 ExecutionTier mode);
     92 
     93   void OnBackgroundTaskStopped(const WasmFeatures& detected);
     94   void PublishDetectedFeatures(Isolate* isolate, const WasmFeatures& detected);
     95   void RestartBackgroundTasks(size_t max = std::numeric_limits<size_t>::max());
     96   // Only one foreground thread (finisher) is allowed to run at a time.
     97   // {SetFinisherIsRunning} returns whether the flag changed its state.
     98   bool SetFinisherIsRunning(bool value);
     99   void ScheduleFinisherTask();
    100 
    101   void Abort();
    102 
    103   Isolate* isolate() const { return isolate_; }
    104 
    105   bool failed() const {
    106     base::LockGuard<base::Mutex> guard(&mutex_);
    107     return failed_;
    108   }
    109 
    110   bool baseline_compilation_finished() const {
    111     return baseline_compilation_finished_;
    112   }
    113 
    114   WasmEngine* wasm_engine() const { return wasm_engine_; }
    115   CompileMode compile_mode() const { return compile_mode_; }
    116   ModuleEnv* module_env() { return &module_env_; }
    117   WasmFeatures* detected_features() { return &detected_features_; }
    118 
    119  private:
    120   void NotifyOnEvent(CompilationEvent event, ErrorThrower* thrower);
    121 
    122   std::vector<std::unique_ptr<WasmCompilationUnit>>& finish_units() {
    123     return baseline_compilation_finished_ ? tiering_finish_units_
    124                                           : baseline_finish_units_;
    125   }
    126 
    127   // TODO(7423): Get rid of the Isolate field to make sure the CompilationState
    128   // can be shared across multiple Isolates.
    129   Isolate* const isolate_;
    130   WasmEngine* const wasm_engine_;
    131   // TODO(clemensh): Remove ModuleEnv, generate it when needed.
    132   ModuleEnv module_env_;
    133   const CompileMode compile_mode_;
    134   bool baseline_compilation_finished_ = false;
    135 
    136   // This mutex protects all information of this CompilationState which is being
    137   // accessed concurrently.
    138   mutable base::Mutex mutex_;
    139 
    140   //////////////////////////////////////////////////////////////////////////////
    141   // Protected by {mutex_}:
    142 
    143   std::vector<std::unique_ptr<WasmCompilationUnit>> baseline_compilation_units_;
    144   std::vector<std::unique_ptr<WasmCompilationUnit>> tiering_compilation_units_;
    145 
    146   bool finisher_is_running_ = false;
    147   bool failed_ = false;
    148   size_t num_background_tasks_ = 0;
    149 
    150   std::vector<std::unique_ptr<WasmCompilationUnit>> baseline_finish_units_;
    151   std::vector<std::unique_ptr<WasmCompilationUnit>> tiering_finish_units_;
    152 
    153   // Features detected to be used in this module. Features can be detected
    154   // as a module is being compiled.
    155   WasmFeatures detected_features_ = kNoWasmFeatures;
    156 
    157   // End of fields protected by {mutex_}.
    158   //////////////////////////////////////////////////////////////////////////////
    159 
    160   // Callback function to be called on compilation events.
    161   std::function<void(CompilationEvent, ErrorThrower*)> callback_;
    162 
    163   CancelableTaskManager background_task_manager_;
    164   CancelableTaskManager foreground_task_manager_;
    165   std::shared_ptr<v8::TaskRunner> foreground_task_runner_;
    166 
    167   const size_t max_background_tasks_ = 0;
    168 
    169   size_t outstanding_units_ = 0;
    170   size_t num_tiering_units_ = 0;
    171 };
    172 
    173 namespace {
    174 
    175 void UpdateFeatureUseCounts(Isolate* isolate, const WasmFeatures& detected) {
    176   if (detected.threads) {
    177     isolate->CountUsage(v8::Isolate::UseCounterFeature::kWasmThreadOpcodes);
    178   }
    179 }
    180 
    181 class JSToWasmWrapperCache {
    182  public:
    183   Handle<Code> GetOrCompileJSToWasmWrapper(Isolate* isolate,
    184                                            const NativeModule* native_module,
    185                                            uint32_t func_index,
    186                                            UseTrapHandler use_trap_handler) {
    187     const WasmModule* module = native_module->module();
    188     const WasmFunction* func = &module->functions[func_index];
    189     bool is_import = func_index < module->num_imported_functions;
    190     std::pair<bool, FunctionSig> key(is_import, *func->sig);
    191     Handle<Code>& cached = cache_[key];
    192     if (!cached.is_null()) return cached;
    193 
    194     Handle<Code> code =
    195         compiler::CompileJSToWasmWrapper(isolate, native_module, func->sig,
    196                                          is_import, use_trap_handler)
    197             .ToHandleChecked();
    198     cached = code;
    199     return code;
    200   }
    201 
    202  private:
    203   // We generate different code for calling imports than calling wasm functions
    204   // in this module. Both are cached separately.
    205   using CacheKey = std::pair<bool, FunctionSig>;
    206   std::unordered_map<CacheKey, Handle<Code>, base::hash<CacheKey>> cache_;
    207 };
    208 
    209 // A helper class to simplify instantiating a module from a module object.
    210 // It closes over the {Isolate}, the {ErrorThrower}, etc.
    211 class InstanceBuilder {
    212  public:
    213   InstanceBuilder(Isolate* isolate, ErrorThrower* thrower,
    214                   Handle<WasmModuleObject> module_object,
    215                   MaybeHandle<JSReceiver> ffi,
    216                   MaybeHandle<JSArrayBuffer> memory);
    217 
    218   // Build an instance, in all of its glory.
    219   MaybeHandle<WasmInstanceObject> Build();
    220   // Run the start function, if any.
    221   bool ExecuteStartFunction();
    222 
    223  private:
    224   // Represents the initialized state of a table.
    225   struct TableInstance {
    226     Handle<WasmTableObject> table_object;  // WebAssembly.Table instance
    227     Handle<FixedArray> js_wrappers;        // JSFunctions exported
    228     size_t table_size;
    229   };
    230 
    231   // A pre-evaluated value to use in import binding.
    232   struct SanitizedImport {
    233     Handle<String> module_name;
    234     Handle<String> import_name;
    235     Handle<Object> value;
    236   };
    237 
    238   Isolate* isolate_;
    239   const WasmFeatures enabled_;
    240   const WasmModule* const module_;
    241   ErrorThrower* thrower_;
    242   Handle<WasmModuleObject> module_object_;
    243   MaybeHandle<JSReceiver> ffi_;
    244   MaybeHandle<JSArrayBuffer> memory_;
    245   Handle<JSArrayBuffer> globals_;
    246   std::vector<TableInstance> table_instances_;
    247   std::vector<Handle<JSFunction>> js_wrappers_;
    248   Handle<WasmExportedFunction> start_function_;
    249   JSToWasmWrapperCache js_to_wasm_cache_;
    250   std::vector<SanitizedImport> sanitized_imports_;
    251 
    252   UseTrapHandler use_trap_handler() const {
    253     return module_object_->native_module()->use_trap_handler() ? kUseTrapHandler
    254                                                                : kNoTrapHandler;
    255   }
    256 
    257 // Helper routines to print out errors with imports.
    258 #define ERROR_THROWER_WITH_MESSAGE(TYPE)                                      \
    259   void Report##TYPE(const char* error, uint32_t index,                        \
    260                     Handle<String> module_name, Handle<String> import_name) { \
    261     thrower_->TYPE("Import #%d module=\"%s\" function=\"%s\" error: %s",      \
    262                    index, module_name->ToCString().get(),                     \
    263                    import_name->ToCString().get(), error);                    \
    264   }                                                                           \
    265                                                                               \
    266   MaybeHandle<Object> Report##TYPE(const char* error, uint32_t index,         \
    267                                    Handle<String> module_name) {              \
    268     thrower_->TYPE("Import #%d module=\"%s\" error: %s", index,               \
    269                    module_name->ToCString().get(), error);                    \
    270     return MaybeHandle<Object>();                                             \
    271   }
    272 
    273   ERROR_THROWER_WITH_MESSAGE(LinkError)
    274   ERROR_THROWER_WITH_MESSAGE(TypeError)
    275 
    276 #undef ERROR_THROWER_WITH_MESSAGE
    277 
    278   // Look up an import value in the {ffi_} object.
    279   MaybeHandle<Object> LookupImport(uint32_t index, Handle<String> module_name,
    280                                    Handle<String> import_name);
    281 
    282   // Look up an import value in the {ffi_} object specifically for linking an
    283   // asm.js module. This only performs non-observable lookups, which allows
    284   // falling back to JavaScript proper (and hence re-executing all lookups) if
    285   // module instantiation fails.
    286   MaybeHandle<Object> LookupImportAsm(uint32_t index,
    287                                       Handle<String> import_name);
    288 
    289   uint32_t EvalUint32InitExpr(const WasmInitExpr& expr);
    290 
    291   // Load data segments into the memory.
    292   void LoadDataSegments(Handle<WasmInstanceObject> instance);
    293 
    294   void WriteGlobalValue(const WasmGlobal& global, double value);
    295   void WriteGlobalValue(const WasmGlobal& global,
    296                         Handle<WasmGlobalObject> value);
    297 
    298   void SanitizeImports();
    299 
    300   // Find the imported memory buffer if there is one. This is used to see if we
    301   // need to recompile with bounds checks before creating the instance.
    302   MaybeHandle<JSArrayBuffer> FindImportedMemoryBuffer() const;
    303 
    304   // Process the imports, including functions, tables, globals, and memory, in
    305   // order, loading them from the {ffi_} object. Returns the number of imported
    306   // functions.
    307   int ProcessImports(Handle<WasmInstanceObject> instance);
    308 
    309   template <typename T>
    310   T* GetRawGlobalPtr(const WasmGlobal& global);
    311 
    312   // Process initialization of globals.
    313   void InitGlobals();
    314 
    315   // Allocate memory for a module instance as a new JSArrayBuffer.
    316   Handle<JSArrayBuffer> AllocateMemory(uint32_t num_pages);
    317 
    318   bool NeedsWrappers() const;
    319 
    320   // Process the exports, creating wrappers for functions, tables, memories,
    321   // and globals.
    322   void ProcessExports(Handle<WasmInstanceObject> instance);
    323 
    324   void InitializeTables(Handle<WasmInstanceObject> instance);
    325 
    326   void LoadTableSegments(Handle<WasmInstanceObject> instance);
    327 };
    328 
    329 }  // namespace
    330 
    331 MaybeHandle<WasmInstanceObject> InstantiateToInstanceObject(
    332     Isolate* isolate, ErrorThrower* thrower,
    333     Handle<WasmModuleObject> module_object, MaybeHandle<JSReceiver> imports,
    334     MaybeHandle<JSArrayBuffer> memory) {
    335   InstanceBuilder builder(isolate, thrower, module_object, imports, memory);
    336   auto instance = builder.Build();
    337   if (!instance.is_null() && builder.ExecuteStartFunction()) {
    338     return instance;
    339   }
    340   return {};
    341 }
    342 
    343 WasmCode* LazyCompileFunction(Isolate* isolate, NativeModule* native_module,
    344                               int func_index) {
    345   base::ElapsedTimer compilation_timer;
    346   DCHECK(!native_module->has_code(static_cast<uint32_t>(func_index)));
    347 
    348   compilation_timer.Start();
    349 
    350   ModuleEnv* module_env = native_module->compilation_state()->module_env();
    351   // TODO(wasm): Refactor this to only get the name if it is really needed for
    352   // tracing / debugging.
    353   WasmName func_name;
    354   {
    355     ModuleWireBytes wire_bytes(native_module->wire_bytes());
    356     WireBytesRef name_ref =
    357         module_env->module->LookupFunctionName(wire_bytes, func_index);
    358     func_name = wire_bytes.GetName(name_ref);
    359   }
    360 
    361   TRACE_LAZY("Compiling function '%.*s' (#%d).\n", func_name.length(),
    362              func_name.start(), func_index);
    363 
    364   const uint8_t* module_start = native_module->wire_bytes().start();
    365 
    366   const WasmFunction* func = &module_env->module->functions[func_index];
    367   FunctionBody body{func->sig, func->code.offset(),
    368                     module_start + func->code.offset(),
    369                     module_start + func->code.end_offset()};
    370 
    371   ErrorThrower thrower(isolate, "WasmLazyCompile");
    372   WasmCompilationUnit unit(isolate->wasm_engine(), module_env, native_module,
    373                            body, func_name, func_index, isolate->counters());
    374   unit.ExecuteCompilation(
    375       native_module->compilation_state()->detected_features());
    376   WasmCode* wasm_code = unit.FinishCompilation(&thrower);
    377 
    378   if (WasmCode::ShouldBeLogged(isolate)) wasm_code->LogCode(isolate);
    379 
    380   // If there is a pending error, something really went wrong. The module was
    381   // verified before starting execution with lazy compilation.
    382   // This might be OOM, but then we cannot continue execution anyway.
    383   // TODO(clemensh): According to the spec, we can actually skip validation at
    384   // module creation time, and return a function that always traps here.
    385   CHECK(!thrower.error());
    386 
    387   int64_t func_size =
    388       static_cast<int64_t>(func->code.end_offset() - func->code.offset());
    389   int64_t compilation_time = compilation_timer.Elapsed().InMicroseconds();
    390 
    391   auto counters = isolate->counters();
    392   counters->wasm_lazily_compiled_functions()->Increment();
    393 
    394   counters->wasm_lazy_compilation_throughput()->AddSample(
    395       compilation_time != 0 ? static_cast<int>(func_size / compilation_time)
    396                             : 0);
    397 
    398   return wasm_code;
    399 }
    400 
    401 Address CompileLazy(Isolate* isolate, NativeModule* native_module,
    402                     uint32_t func_index) {
    403   HistogramTimerScope lazy_time_scope(
    404       isolate->counters()->wasm_lazy_compilation_time());
    405 
    406   DCHECK(!native_module->lazy_compile_frozen());
    407 
    408   NativeModuleModificationScope native_module_modification_scope(native_module);
    409 
    410   WasmCode* result = LazyCompileFunction(isolate, native_module, func_index);
    411   DCHECK_NOT_NULL(result);
    412   DCHECK_EQ(func_index, result->index());
    413 
    414   return result->instruction_start();
    415 }
    416 
    417 namespace {
    418 bool compile_lazy(const WasmModule* module) {
    419   return FLAG_wasm_lazy_compilation ||
    420          (FLAG_asm_wasm_lazy_compilation && module->origin == kAsmJsOrigin);
    421 }
    422 
    423 byte* raw_buffer_ptr(MaybeHandle<JSArrayBuffer> buffer, int offset) {
    424   return static_cast<byte*>(buffer.ToHandleChecked()->backing_store()) + offset;
    425 }
    426 
    427 void RecordStats(const Code* code, Counters* counters) {
    428   counters->wasm_generated_code_size()->Increment(code->body_size());
    429   counters->wasm_reloc_size()->Increment(code->relocation_info()->length());
    430 }
    431 
    432 bool in_bounds(uint32_t offset, size_t size, size_t upper) {
    433   return offset + size <= upper && offset + size >= offset;
    434 }
    435 
    436 using WasmInstanceMap =
    437     IdentityMap<Handle<WasmInstanceObject>, FreeStoreAllocationPolicy>;
    438 
    439 double MonotonicallyIncreasingTimeInMs() {
    440   return V8::GetCurrentPlatform()->MonotonicallyIncreasingTime() *
    441          base::Time::kMillisecondsPerSecond;
    442 }
    443 
    444 ModuleEnv CreateDefaultModuleEnv(const WasmModule* module,
    445                                  bool allow_trap_handler = true) {
    446   UseTrapHandler use_trap_handler =
    447       trap_handler::IsTrapHandlerEnabled() && allow_trap_handler
    448           ? kUseTrapHandler
    449           : kNoTrapHandler;
    450   return ModuleEnv(module, use_trap_handler, kRuntimeExceptionSupport);
    451 }
    452 
    453 // The CompilationUnitBuilder builds compilation units and stores them in an
    454 // internal buffer. The buffer is moved into the working queue of the
    455 // CompilationState when {Commit} is called.
    456 class CompilationUnitBuilder {
    457  public:
    458   explicit CompilationUnitBuilder(NativeModule* native_module)
    459       : native_module_(native_module),
    460         compilation_state_(native_module->compilation_state()) {}
    461 
    462   void AddUnit(const WasmFunction* function, uint32_t buffer_offset,
    463                Vector<const uint8_t> bytes, WasmName name) {
    464     switch (compilation_state_->compile_mode()) {
    465       case CompileMode::kTiering:
    466         tiering_units_.emplace_back(CreateUnit(
    467             function, buffer_offset, bytes, name, ExecutionTier::kOptimized));
    468         baseline_units_.emplace_back(CreateUnit(
    469             function, buffer_offset, bytes, name, ExecutionTier::kBaseline));
    470         return;
    471       case CompileMode::kRegular:
    472         baseline_units_.emplace_back(
    473             CreateUnit(function, buffer_offset, bytes, name,
    474                        WasmCompilationUnit::GetDefaultExecutionTier()));
    475         return;
    476     }
    477     UNREACHABLE();
    478   }
    479 
    480   bool Commit() {
    481     if (baseline_units_.empty() && tiering_units_.empty()) return false;
    482     compilation_state_->AddCompilationUnits(baseline_units_, tiering_units_);
    483     Clear();
    484     return true;
    485   }
    486 
    487   void Clear() {
    488     baseline_units_.clear();
    489     tiering_units_.clear();
    490   }
    491 
    492  private:
    493   std::unique_ptr<WasmCompilationUnit> CreateUnit(const WasmFunction* function,
    494                                                   uint32_t buffer_offset,
    495                                                   Vector<const uint8_t> bytes,
    496                                                   WasmName name,
    497                                                   ExecutionTier mode) {
    498     return base::make_unique<WasmCompilationUnit>(
    499         compilation_state_->wasm_engine(), compilation_state_->module_env(),
    500         native_module_,
    501         FunctionBody{function->sig, buffer_offset, bytes.begin(), bytes.end()},
    502         name, function->func_index,
    503         compilation_state_->isolate()->async_counters().get(), mode);
    504   }
    505 
    506   NativeModule* native_module_;
    507   CompilationState* compilation_state_;
    508   std::vector<std::unique_ptr<WasmCompilationUnit>> baseline_units_;
    509   std::vector<std::unique_ptr<WasmCompilationUnit>> tiering_units_;
    510 };
    511 
    512 // Run by each compilation task and by the main thread (i.e. in both
    513 // foreground and background threads). The no_finisher_callback is called
    514 // within the result_mutex_ lock when no finishing task is running, i.e. when
    515 // the finisher_is_running_ flag is not set.
    516 bool FetchAndExecuteCompilationUnit(CompilationState* compilation_state,
    517                                     WasmFeatures* detected) {
    518   DisallowHeapAccess no_heap_access;
    519 
    520   std::unique_ptr<WasmCompilationUnit> unit =
    521       compilation_state->GetNextCompilationUnit();
    522   if (unit == nullptr) return false;
    523 
    524   // TODO(kimanh): We need to find out in which mode the unit
    525   // should be compiled in before compiling it, as it might fallback
    526   // to Turbofan if it cannot be compiled using Liftoff. This can be removed
    527   // later as soon as Liftoff can compile any function. Then, we can directly
    528   // access {unit->mode()} within {ScheduleUnitForFinishing()}.
    529   ExecutionTier mode = unit->mode();
    530   unit->ExecuteCompilation(detected);
    531   compilation_state->ScheduleUnitForFinishing(std::move(unit), mode);
    532 
    533   return true;
    534 }
    535 
    536 void InitializeCompilationUnits(NativeModule* native_module) {
    537   ModuleWireBytes wire_bytes(native_module->wire_bytes());
    538   const WasmModule* module = native_module->module();
    539   CompilationUnitBuilder builder(native_module);
    540   uint32_t start = module->num_imported_functions;
    541   uint32_t end = start + module->num_declared_functions;
    542   for (uint32_t i = start; i < end; ++i) {
    543     const WasmFunction* func = &module->functions[i];
    544     uint32_t buffer_offset = func->code.offset();
    545     Vector<const uint8_t> bytes(wire_bytes.start() + func->code.offset(),
    546                                 func->code.end_offset() - func->code.offset());
    547 
    548     WasmName name = wire_bytes.GetName(func, module);
    549     DCHECK_NOT_NULL(native_module);
    550     builder.AddUnit(func, buffer_offset, bytes, name);
    551   }
    552   builder.Commit();
    553 }
    554 
    555 void FinishCompilationUnits(CompilationState* compilation_state,
    556                             ErrorThrower* thrower) {
    557   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), "FinishCompilationUnits");
    558   while (true) {
    559     if (compilation_state->failed()) break;
    560     std::unique_ptr<WasmCompilationUnit> unit =
    561         compilation_state->GetNextExecutedUnit();
    562     if (unit == nullptr) break;
    563     WasmCode* result = unit->FinishCompilation(thrower);
    564 
    565     if (thrower->error()) {
    566       compilation_state->Abort();
    567       break;
    568     }
    569 
    570     // Update the compilation state.
    571     compilation_state->OnFinishedUnit();
    572     DCHECK_IMPLIES(result == nullptr, thrower->error());
    573     if (result == nullptr) break;
    574   }
    575   if (!compilation_state->failed()) {
    576     compilation_state->RestartBackgroundTasks();
    577   }
    578 }
    579 
    580 void CompileInParallel(Isolate* isolate, NativeModule* native_module,
    581                        Handle<WasmModuleObject> module_object,
    582                        ErrorThrower* thrower) {
    583   // Data structures for the parallel compilation.
    584 
    585   //-----------------------------------------------------------------------
    586   // For parallel compilation:
    587   // 1) The main thread allocates a compilation unit for each wasm function
    588   //    and stores them in the vector {compilation_units} within the
    589   //    {compilation_state}. By adding units to the {compilation_state}, new
    590   //    {BackgroundCompileTasks} instances are spawned which run on
    591   //    the background threads.
    592   // 2.a) The background threads and the main thread pick one compilation
    593   //      unit at a time and execute the parallel phase of the compilation
    594   //      unit. After finishing the execution of the parallel phase, the
    595   //      result is enqueued in {baseline_finish_units_}.
    596   // 2.b) If {baseline_finish_units_} contains a compilation unit, the main
    597   //      thread dequeues it and finishes the compilation.
    598   // 3) After the parallel phase of all compilation units has started, the
    599   //    main thread continues to finish all compilation units as long as
    600   //    baseline-compilation units are left to be processed.
    601   // 4) If tier-up is enabled, the main thread restarts background tasks
    602   //    that take care of compiling and finishing the top-tier compilation
    603   //    units.
    604 
    605   // Turn on the {CanonicalHandleScope} so that the background threads can
    606   // use the node cache.
    607   CanonicalHandleScope canonical(isolate);
    608 
    609   CompilationState* compilation_state = native_module->compilation_state();
    610   // Make sure that no foreground task is spawned for finishing
    611   // the compilation units. This foreground thread will be
    612   // responsible for finishing compilation.
    613   compilation_state->SetFinisherIsRunning(true);
    614   uint32_t num_wasm_functions =
    615       native_module->num_functions() - native_module->num_imported_functions();
    616   compilation_state->SetNumberOfFunctionsToCompile(num_wasm_functions);
    617 
    618   // 1) The main thread allocates a compilation unit for each wasm function
    619   //    and stores them in the vector {compilation_units} within the
    620   //    {compilation_state}. By adding units to the {compilation_state}, new
    621   //    {BackgroundCompileTask} instances are spawned which run on
    622   //    background threads.
    623   InitializeCompilationUnits(native_module);
    624 
    625   // 2.a) The background threads and the main thread pick one compilation
    626   //      unit at a time and execute the parallel phase of the compilation
    627   //      unit. After finishing the execution of the parallel phase, the
    628   //      result is enqueued in {baseline_finish_units_}.
    629   //      The foreground task bypasses waiting on memory threshold, because
    630   //      its results will immediately be converted to code (below).
    631   WasmFeatures detected_features;
    632   while (
    633       FetchAndExecuteCompilationUnit(compilation_state, &detected_features) &&
    634       !compilation_state->baseline_compilation_finished()) {
    635     // 2.b) If {baseline_finish_units_} contains a compilation unit, the main
    636     //      thread dequeues it and finishes the compilation unit. Compilation
    637     //      units are finished concurrently to the background threads to save
    638     //      memory.
    639     FinishCompilationUnits(compilation_state, thrower);
    640 
    641     if (compilation_state->failed()) break;
    642   }
    643 
    644   while (!compilation_state->failed()) {
    645     // 3) After the parallel phase of all compilation units has started, the
    646     //    main thread continues to finish compilation units as long as
    647     //    baseline compilation units are left to be processed. If compilation
    648     //    already failed, all background tasks have already been canceled
    649     //    in {FinishCompilationUnits}, and there are no units to finish.
    650     FinishCompilationUnits(compilation_state, thrower);
    651 
    652     if (compilation_state->baseline_compilation_finished()) break;
    653   }
    654 
    655   // Publish features from the foreground and background tasks.
    656   compilation_state->PublishDetectedFeatures(isolate, detected_features);
    657 
    658   // 4) If tiering-compilation is enabled, we need to set the finisher
    659   //    to false, such that the background threads will spawn a foreground
    660   //    thread to finish the top-tier compilation units.
    661   if (!compilation_state->failed() &&
    662       compilation_state->compile_mode() == CompileMode::kTiering) {
    663     compilation_state->SetFinisherIsRunning(false);
    664     compilation_state->RestartBackgroundTasks();
    665   }
    666 }
    667 
    668 void CompileSequentially(Isolate* isolate, NativeModule* native_module,
    669                          ModuleEnv* module_env, ErrorThrower* thrower) {
    670   DCHECK(!thrower->error());
    671 
    672   ModuleWireBytes wire_bytes(native_module->wire_bytes());
    673   const WasmModule* module = module_env->module;
    674   WasmFeatures detected = kNoWasmFeatures;
    675   for (uint32_t i = 0; i < module->functions.size(); ++i) {
    676     const WasmFunction& func = module->functions[i];
    677     if (func.imported) continue;  // Imports are compiled at instantiation time.
    678 
    679     // Compile the function.
    680     WasmCode* code = WasmCompilationUnit::CompileWasmFunction(
    681         isolate, native_module, &detected, thrower, module_env, &func);
    682     if (code == nullptr) {
    683       TruncatedUserString<> name(wire_bytes.GetName(&func, module));
    684       thrower->CompileError("Compilation of #%d:%.*s failed.", i, name.length(),
    685                             name.start());
    686       break;
    687     }
    688   }
    689   UpdateFeatureUseCounts(isolate, detected);
    690 }
    691 
    692 void ValidateSequentially(Isolate* isolate, NativeModule* native_module,
    693                           ErrorThrower* thrower) {
    694   DCHECK(!thrower->error());
    695 
    696   ModuleWireBytes wire_bytes(native_module->wire_bytes());
    697   const WasmModule* module = native_module->module();
    698   uint32_t start = module->num_imported_functions;
    699   uint32_t end = start + module->num_declared_functions;
    700   for (uint32_t i = start; i < end; ++i) {
    701     const WasmFunction& func = module->functions[i];
    702 
    703     const byte* base = wire_bytes.start();
    704     FunctionBody body{func.sig, func.code.offset(), base + func.code.offset(),
    705                       base + func.code.end_offset()};
    706     DecodeResult result;
    707     {
    708       auto time_counter =
    709           SELECT_WASM_COUNTER(isolate->async_counters(), module->origin,
    710                               wasm_decode, function_time);
    711 
    712       TimedHistogramScope wasm_decode_function_time_scope(time_counter);
    713       WasmFeatures detected;
    714       result = VerifyWasmCode(isolate->allocator(),
    715                               native_module->enabled_features(), module,
    716                               &detected, body);
    717     }
    718     if (result.failed()) {
    719       TruncatedUserString<> name(wire_bytes.GetName(&func, module));
    720       thrower->CompileError("Compiling function #%d:%.*s failed: %s @+%u", i,
    721                             name.length(), name.start(),
    722                             result.error_msg().c_str(), result.error_offset());
    723       break;
    724     }
    725   }
    726 }
    727 
    728 void CompileNativeModule(Isolate* isolate, ErrorThrower* thrower,
    729                          Handle<WasmModuleObject> module_object,
    730                          const WasmModule* wasm_module, ModuleEnv* env) {
    731   NativeModule* const native_module = module_object->native_module();
    732   ModuleWireBytes wire_bytes(native_module->wire_bytes());
    733 
    734   if (compile_lazy(wasm_module)) {
    735     if (wasm_module->origin == kWasmOrigin) {
    736       // Validate wasm modules for lazy compilation. Don't validate asm.js
    737       // modules, they are valid by construction (otherwise a CHECK will fail
    738       // during lazy compilation).
    739       // TODO(clemensh): According to the spec, we can actually skip validation
    740       // at module creation time, and return a function that always traps at
    741       // (lazy) compilation time.
    742       ValidateSequentially(isolate, native_module, thrower);
    743       if (thrower->error()) return;
    744     }
    745 
    746     native_module->SetLazyBuiltin(BUILTIN_CODE(isolate, WasmCompileLazy));
    747   } else {
    748     size_t funcs_to_compile =
    749         wasm_module->functions.size() - wasm_module->num_imported_functions;
    750     bool compile_parallel =
    751         !FLAG_trace_wasm_decoder && FLAG_wasm_num_compilation_tasks > 0 &&
    752         funcs_to_compile > 1 &&
    753         V8::GetCurrentPlatform()->NumberOfWorkerThreads() > 0;
    754 
    755     if (compile_parallel) {
    756       CompileInParallel(isolate, native_module, module_object, thrower);
    757     } else {
    758       CompileSequentially(isolate, native_module, env, thrower);
    759     }
    760     if (thrower->error()) return;
    761   }
    762 }
    763 
    764 // The runnable task that finishes compilation in foreground (e.g. updating
    765 // the NativeModule, the code table, etc.).
    766 class FinishCompileTask : public CancelableTask {
    767  public:
    768   explicit FinishCompileTask(CompilationState* compilation_state,
    769                              CancelableTaskManager* task_manager)
    770       : CancelableTask(task_manager), compilation_state_(compilation_state) {}
    771 
    772   void RunInternal() override {
    773     Isolate* isolate = compilation_state_->isolate();
    774     HandleScope scope(isolate);
    775     SaveContext saved_context(isolate);
    776     isolate->set_context(nullptr);
    777 
    778     TRACE_COMPILE("(4a) Finishing compilation units...\n");
    779     if (compilation_state_->failed()) {
    780       compilation_state_->SetFinisherIsRunning(false);
    781       return;
    782     }
    783 
    784     // We execute for 1 ms and then reschedule the task, same as the GC.
    785     double deadline = MonotonicallyIncreasingTimeInMs() + 1.0;
    786     while (true) {
    787       compilation_state_->RestartBackgroundTasks();
    788 
    789       std::unique_ptr<WasmCompilationUnit> unit =
    790           compilation_state_->GetNextExecutedUnit();
    791 
    792       if (unit == nullptr) {
    793         // It might happen that a background task just scheduled a unit to be
    794         // finished, but did not start a finisher task since the flag was still
    795         // set. Check for this case, and continue if there is more work.
    796         compilation_state_->SetFinisherIsRunning(false);
    797         if (compilation_state_->HasCompilationUnitToFinish() &&
    798             compilation_state_->SetFinisherIsRunning(true)) {
    799           continue;
    800         }
    801         break;
    802       }
    803 
    804       ErrorThrower thrower(compilation_state_->isolate(), "AsyncCompile");
    805       WasmCode* result = unit->FinishCompilation(&thrower);
    806 
    807       if (thrower.error()) {
    808         DCHECK_NULL(result);
    809         compilation_state_->OnError(&thrower);
    810         compilation_state_->SetFinisherIsRunning(false);
    811         thrower.Reset();
    812         break;
    813       }
    814 
    815       if (compilation_state_->baseline_compilation_finished()) {
    816         // If Liftoff compilation finishes it will directly start executing.
    817         // As soon as we have Turbofan-compiled code available, it will
    818         // directly be used by Liftoff-compiled code via the jump table.
    819         DCHECK_EQ(CompileMode::kTiering, compilation_state_->compile_mode());
    820         DCHECK(!result->is_liftoff());
    821 
    822         if (WasmCode::ShouldBeLogged(isolate)) result->LogCode(isolate);
    823       }
    824 
    825       // Update the compilation state, and possibly notify
    826       // threads waiting for events.
    827       compilation_state_->OnFinishedUnit();
    828 
    829       if (deadline < MonotonicallyIncreasingTimeInMs()) {
    830         // We reached the deadline. We reschedule this task and return
    831         // immediately. Since we rescheduled this task already, we do not set
    832         // the FinisherIsRunning flag to false.
    833         compilation_state_->ScheduleFinisherTask();
    834         return;
    835       }
    836     }
    837   }
    838 
    839  private:
    840   CompilationState* compilation_state_;
    841 };
    842 
    843 // The runnable task that performs compilations in the background.
    844 class BackgroundCompileTask : public CancelableTask {
    845  public:
    846   explicit BackgroundCompileTask(CompilationState* compilation_state,
    847                                  CancelableTaskManager* task_manager)
    848       : CancelableTask(task_manager), compilation_state_(compilation_state) {}
    849 
    850   void RunInternal() override {
    851     TRACE_COMPILE("(3b) Compiling...\n");
    852     // The number of currently running background tasks is reduced in
    853     // {OnBackgroundTaskStopped}.
    854     while (!compilation_state_->failed()) {
    855       if (!FetchAndExecuteCompilationUnit(compilation_state_,
    856                                           &detected_features_)) {
    857         break;
    858       }
    859     }
    860     compilation_state_->OnBackgroundTaskStopped(detected_features_);
    861   }
    862 
    863  private:
    864   CompilationState* compilation_state_;
    865   WasmFeatures detected_features_ = kNoWasmFeatures;
    866 };
    867 }  // namespace
    868 
    869 MaybeHandle<WasmModuleObject> CompileToModuleObject(
    870     Isolate* isolate, const WasmFeatures& enabled, ErrorThrower* thrower,
    871     std::shared_ptr<const WasmModule> module, const ModuleWireBytes& wire_bytes,
    872     Handle<Script> asm_js_script,
    873     Vector<const byte> asm_js_offset_table_bytes) {
    874   const WasmModule* wasm_module = module.get();
    875   TimedHistogramScope wasm_compile_module_time_scope(SELECT_WASM_COUNTER(
    876       isolate->counters(), wasm_module->origin, wasm_compile, module_time));
    877 
    878   // Embedder usage count for declared shared memories.
    879   if (wasm_module->has_shared_memory) {
    880     isolate->CountUsage(v8::Isolate::UseCounterFeature::kWasmSharedMemory);
    881   }
    882 
    883   // TODO(6792): No longer needed once WebAssembly code is off heap. Use
    884   // base::Optional to be able to close the scope before notifying the debugger.
    885   base::Optional<CodeSpaceMemoryModificationScope> modification_scope(
    886       base::in_place_t(), isolate->heap());
    887 
    888   // Create heap objects for script, module bytes and asm.js offset table to
    889   // be stored in the module object.
    890   Handle<Script> script;
    891   Handle<ByteArray> asm_js_offset_table;
    892   if (asm_js_script.is_null()) {
    893     script = CreateWasmScript(isolate, wire_bytes);
    894   } else {
    895     script = asm_js_script;
    896     asm_js_offset_table =
    897         isolate->factory()->NewByteArray(asm_js_offset_table_bytes.length());
    898     asm_js_offset_table->copy_in(0, asm_js_offset_table_bytes.start(),
    899                                  asm_js_offset_table_bytes.length());
    900   }
    901   // TODO(wasm): only save the sections necessary to deserialize a
    902   // {WasmModule}. E.g. function bodies could be omitted.
    903   OwnedVector<uint8_t> wire_bytes_copy =
    904       OwnedVector<uint8_t>::Of(wire_bytes.module_bytes());
    905 
    906   // Create the module object.
    907   // TODO(clemensh): For the same module (same bytes / same hash), we should
    908   // only have one WasmModuleObject. Otherwise, we might only set
    909   // breakpoints on a (potentially empty) subset of the instances.
    910   ModuleEnv env = CreateDefaultModuleEnv(wasm_module);
    911 
    912   // Create the compiled module object and populate with compiled functions
    913   // and information needed at instantiation time. This object needs to be
    914   // serializable. Instantiation may occur off a deserialized version of this
    915   // object.
    916   Handle<WasmModuleObject> module_object = WasmModuleObject::New(
    917       isolate, enabled, std::move(module), env, std::move(wire_bytes_copy),
    918       script, asm_js_offset_table);
    919   CompileNativeModule(isolate, thrower, module_object, wasm_module, &env);
    920   if (thrower->error()) return {};
    921 
    922   // Compile JS->wasm wrappers for exported functions.
    923   CompileJsToWasmWrappers(isolate, module_object);
    924 
    925   // If we created a wasm script, finish it now and make it public to the
    926   // debugger.
    927   if (asm_js_script.is_null()) {
    928     // Close the CodeSpaceMemoryModificationScope before calling into the
    929     // debugger.
    930     modification_scope.reset();
    931     isolate->debug()->OnAfterCompile(script);
    932   }
    933 
    934   // Log the code within the generated module for profiling.
    935   module_object->native_module()->LogWasmCodes(isolate);
    936 
    937   return module_object;
    938 }
    939 
    940 InstanceBuilder::InstanceBuilder(Isolate* isolate, ErrorThrower* thrower,
    941                                  Handle<WasmModuleObject> module_object,
    942                                  MaybeHandle<JSReceiver> ffi,
    943                                  MaybeHandle<JSArrayBuffer> memory)
    944     : isolate_(isolate),
    945       enabled_(module_object->native_module()->enabled_features()),
    946       module_(module_object->module()),
    947       thrower_(thrower),
    948       module_object_(module_object),
    949       ffi_(ffi),
    950       memory_(memory) {
    951   sanitized_imports_.reserve(module_->import_table.size());
    952 }
    953 
    954 // Build an instance, in all of its glory.
    955 MaybeHandle<WasmInstanceObject> InstanceBuilder::Build() {
    956   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"), "InstanceBuilder::Build");
    957   // Check that an imports argument was provided, if the module requires it.
    958   // No point in continuing otherwise.
    959   if (!module_->import_table.empty() && ffi_.is_null()) {
    960     thrower_->TypeError(
    961         "Imports argument must be present and must be an object");
    962     return {};
    963   }
    964 
    965   SanitizeImports();
    966   if (thrower_->error()) return {};
    967 
    968   // TODO(6792): No longer needed once WebAssembly code is off heap.
    969   CodeSpaceMemoryModificationScope modification_scope(isolate_->heap());
    970   // From here on, we expect the build pipeline to run without exiting to JS.
    971   DisallowJavascriptExecution no_js(isolate_);
    972   // Record build time into correct bucket, then build instance.
    973   TimedHistogramScope wasm_instantiate_module_time_scope(SELECT_WASM_COUNTER(
    974       isolate_->counters(), module_->origin, wasm_instantiate, module_time));
    975 
    976   //--------------------------------------------------------------------------
    977   // Allocate the memory array buffer.
    978   //--------------------------------------------------------------------------
    979   // We allocate the memory buffer before cloning or reusing the compiled module
    980   // so we will know whether we need to recompile with bounds checks.
    981   uint32_t initial_pages = module_->initial_pages;
    982   auto initial_pages_counter = SELECT_WASM_COUNTER(
    983       isolate_->counters(), module_->origin, wasm, min_mem_pages_count);
    984   initial_pages_counter->AddSample(initial_pages);
    985   // Asm.js has memory_ already set at this point, so we don't want to
    986   // overwrite it.
    987   if (memory_.is_null()) {
    988     memory_ = FindImportedMemoryBuffer();
    989   }
    990   if (!memory_.is_null()) {
    991     // Set externally passed ArrayBuffer non neuterable.
    992     Handle<JSArrayBuffer> memory = memory_.ToHandleChecked();
    993     memory->set_is_neuterable(false);
    994 
    995     DCHECK_IMPLIES(use_trap_handler(), module_->origin == kAsmJsOrigin ||
    996                                            memory->is_wasm_memory() ||
    997                                            memory->backing_store() == nullptr);
    998   } else if (initial_pages > 0 || use_trap_handler()) {
    999     // We need to unconditionally create a guard region if using trap handlers,
   1000     // even when the size is zero to prevent null-dereference issues
   1001     // (e.g. https://crbug.com/769637).
   1002     // Allocate memory if the initial size is more than 0 pages.
   1003     memory_ = AllocateMemory(initial_pages);
   1004     if (memory_.is_null()) return {};  // failed to allocate memory
   1005   }
   1006 
   1007   //--------------------------------------------------------------------------
   1008   // Recompile module if using trap handlers but could not get guarded memory
   1009   //--------------------------------------------------------------------------
   1010   if (module_->origin == kWasmOrigin && use_trap_handler()) {
   1011     // Make sure the memory has suitable guard regions.
   1012     WasmMemoryTracker* const memory_tracker =
   1013         isolate_->wasm_engine()->memory_tracker();
   1014 
   1015     if (!memory_tracker->HasFullGuardRegions(
   1016             memory_.ToHandleChecked()->backing_store())) {
   1017       if (!FLAG_wasm_trap_handler_fallback) {
   1018         return {};
   1019       }
   1020 
   1021       TRACE("Recompiling module without bounds checks\n");
   1022       constexpr bool allow_trap_handler = false;
   1023       ModuleEnv env = CreateDefaultModuleEnv(module_, allow_trap_handler);
   1024       // Disable trap handlers on this native module.
   1025       NativeModule* native_module = module_object_->native_module();
   1026       native_module->DisableTrapHandler();
   1027 
   1028       // Recompile all functions in this native module.
   1029       ErrorThrower thrower(isolate_, "recompile");
   1030       CompileNativeModule(isolate_, &thrower, module_object_, module_, &env);
   1031       if (thrower.error()) {
   1032         return {};
   1033       }
   1034       DCHECK(!native_module->use_trap_handler());
   1035     }
   1036   }
   1037 
   1038   //--------------------------------------------------------------------------
   1039   // Create the WebAssembly.Instance object.
   1040   //--------------------------------------------------------------------------
   1041   NativeModule* native_module = module_object_->native_module();
   1042   TRACE("New module instantiation for %p\n", native_module);
   1043   Handle<WasmInstanceObject> instance =
   1044       WasmInstanceObject::New(isolate_, module_object_);
   1045   NativeModuleModificationScope native_modification_scope(native_module);
   1046 
   1047   //--------------------------------------------------------------------------
   1048   // Set up the globals for the new instance.
   1049   //--------------------------------------------------------------------------
   1050   MaybeHandle<JSArrayBuffer> old_globals;
   1051   uint32_t globals_buffer_size = module_->globals_buffer_size;
   1052   if (globals_buffer_size > 0) {
   1053     void* backing_store =
   1054         isolate_->array_buffer_allocator()->Allocate(globals_buffer_size);
   1055     if (backing_store == nullptr) {
   1056       thrower_->RangeError("Out of memory: wasm globals");
   1057       return {};
   1058     }
   1059     globals_ =
   1060         isolate_->factory()->NewJSArrayBuffer(SharedFlag::kNotShared, TENURED);
   1061     constexpr bool is_external = false;
   1062     constexpr bool is_wasm_memory = false;
   1063     JSArrayBuffer::Setup(globals_, isolate_, is_external, backing_store,
   1064                          globals_buffer_size, SharedFlag::kNotShared,
   1065                          is_wasm_memory);
   1066     if (globals_.is_null()) {
   1067       thrower_->RangeError("Out of memory: wasm globals");
   1068       return {};
   1069     }
   1070     instance->set_globals_start(
   1071         reinterpret_cast<byte*>(globals_->backing_store()));
   1072     instance->set_globals_buffer(*globals_);
   1073   }
   1074 
   1075   //--------------------------------------------------------------------------
   1076   // Set up the array of references to imported globals' array buffers.
   1077   //--------------------------------------------------------------------------
   1078   if (module_->num_imported_mutable_globals > 0) {
   1079     // TODO(binji): This allocates one slot for each mutable global, which is
   1080     // more than required if multiple globals are imported from the same
   1081     // module.
   1082     Handle<FixedArray> buffers_array = isolate_->factory()->NewFixedArray(
   1083         module_->num_imported_mutable_globals, TENURED);
   1084     instance->set_imported_mutable_globals_buffers(*buffers_array);
   1085   }
   1086 
   1087   //--------------------------------------------------------------------------
   1088   // Reserve the metadata for indirect function tables.
   1089   //--------------------------------------------------------------------------
   1090   int table_count = static_cast<int>(module_->tables.size());
   1091   table_instances_.resize(table_count);
   1092 
   1093   //--------------------------------------------------------------------------
   1094   // Process the imports for the module.
   1095   //--------------------------------------------------------------------------
   1096   int num_imported_functions = ProcessImports(instance);
   1097   if (num_imported_functions < 0) return {};
   1098 
   1099   //--------------------------------------------------------------------------
   1100   // Process the initialization for the module's globals.
   1101   //--------------------------------------------------------------------------
   1102   InitGlobals();
   1103 
   1104   //--------------------------------------------------------------------------
   1105   // Initialize the indirect tables.
   1106   //--------------------------------------------------------------------------
   1107   if (table_count > 0) {
   1108     InitializeTables(instance);
   1109   }
   1110 
   1111   //--------------------------------------------------------------------------
   1112   // Create the WebAssembly.Memory object.
   1113   //--------------------------------------------------------------------------
   1114   if (module_->has_memory) {
   1115     if (!instance->has_memory_object()) {
   1116       // No memory object exists. Create one.
   1117       Handle<WasmMemoryObject> memory_object = WasmMemoryObject::New(
   1118           isolate_, memory_,
   1119           module_->maximum_pages != 0 ? module_->maximum_pages : -1);
   1120       instance->set_memory_object(*memory_object);
   1121     }
   1122 
   1123     // Add the instance object to the list of instances for this memory.
   1124     Handle<WasmMemoryObject> memory_object(instance->memory_object(), isolate_);
   1125     WasmMemoryObject::AddInstance(isolate_, memory_object, instance);
   1126 
   1127     if (!memory_.is_null()) {
   1128       // Double-check the {memory} array buffer matches the instance.
   1129       Handle<JSArrayBuffer> memory = memory_.ToHandleChecked();
   1130       CHECK_EQ(instance->memory_size(), memory->byte_length()->Number());
   1131       CHECK_EQ(instance->memory_start(), memory->backing_store());
   1132     }
   1133   }
   1134 
   1135   //--------------------------------------------------------------------------
   1136   // Check that indirect function table segments are within bounds.
   1137   //--------------------------------------------------------------------------
   1138   for (const WasmTableInit& table_init : module_->table_inits) {
   1139     DCHECK(table_init.table_index < table_instances_.size());
   1140     uint32_t base = EvalUint32InitExpr(table_init.offset);
   1141     size_t table_size = table_instances_[table_init.table_index].table_size;
   1142     if (!in_bounds(base, table_init.entries.size(), table_size)) {
   1143       thrower_->LinkError("table initializer is out of bounds");
   1144       return {};
   1145     }
   1146   }
   1147 
   1148   //--------------------------------------------------------------------------
   1149   // Check that memory segments are within bounds.
   1150   //--------------------------------------------------------------------------
   1151   for (const WasmDataSegment& seg : module_->data_segments) {
   1152     uint32_t base = EvalUint32InitExpr(seg.dest_addr);
   1153     if (!in_bounds(base, seg.source.length(), instance->memory_size())) {
   1154       thrower_->LinkError("data segment is out of bounds");
   1155       return {};
   1156     }
   1157   }
   1158 
   1159   //--------------------------------------------------------------------------
   1160   // Set up the exports object for the new instance.
   1161   //--------------------------------------------------------------------------
   1162   ProcessExports(instance);
   1163   if (thrower_->error()) return {};
   1164 
   1165   //--------------------------------------------------------------------------
   1166   // Initialize the indirect function tables.
   1167   //--------------------------------------------------------------------------
   1168   if (table_count > 0) {
   1169     LoadTableSegments(instance);
   1170   }
   1171 
   1172   //--------------------------------------------------------------------------
   1173   // Initialize the memory by loading data segments.
   1174   //--------------------------------------------------------------------------
   1175   if (module_->data_segments.size() > 0) {
   1176     LoadDataSegments(instance);
   1177   }
   1178 
   1179   //--------------------------------------------------------------------------
   1180   // Install a finalizer on the new instance object.
   1181   //--------------------------------------------------------------------------
   1182   WasmInstanceObject::InstallFinalizer(isolate_, instance);
   1183 
   1184   //--------------------------------------------------------------------------
   1185   // Debugging support.
   1186   //--------------------------------------------------------------------------
   1187   // Set all breakpoints that were set on the shared module.
   1188   WasmModuleObject::SetBreakpointsOnNewInstance(module_object_, instance);
   1189 
   1190   if (FLAG_wasm_interpret_all && module_->origin == kWasmOrigin) {
   1191     Handle<WasmDebugInfo> debug_info =
   1192         WasmInstanceObject::GetOrCreateDebugInfo(instance);
   1193     std::vector<int> func_indexes;
   1194     for (int func_index = num_imported_functions,
   1195              num_wasm_functions = static_cast<int>(module_->functions.size());
   1196          func_index < num_wasm_functions; ++func_index) {
   1197       func_indexes.push_back(func_index);
   1198     }
   1199     WasmDebugInfo::RedirectToInterpreter(
   1200         debug_info, Vector<int>(func_indexes.data(),
   1201                                 static_cast<int>(func_indexes.size())));
   1202   }
   1203 
   1204   //--------------------------------------------------------------------------
   1205   // Create a wrapper for the start function.
   1206   //--------------------------------------------------------------------------
   1207   if (module_->start_function_index >= 0) {
   1208     int start_index = module_->start_function_index;
   1209     FunctionSig* sig = module_->functions[start_index].sig;
   1210     Handle<Code> wrapper_code = js_to_wasm_cache_.GetOrCompileJSToWasmWrapper(
   1211         isolate_, native_module, start_index, use_trap_handler());
   1212     // TODO(clemensh): Don't generate an exported function for the start
   1213     // function. Use CWasmEntry instead.
   1214     start_function_ = WasmExportedFunction::New(
   1215         isolate_, instance, MaybeHandle<String>(), start_index,
   1216         static_cast<int>(sig->parameter_count()), wrapper_code);
   1217   }
   1218 
   1219   DCHECK(!isolate_->has_pending_exception());
   1220   TRACE("Successfully built instance for module %p\n",
   1221         module_object_->native_module());
   1222   return instance;
   1223 }
   1224 
   1225 bool InstanceBuilder::ExecuteStartFunction() {
   1226   TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm"),
   1227                "InstanceBuilder::ExecuteStartFunction");
   1228   if (start_function_.is_null()) return true;  // No start function.
   1229 
   1230   HandleScope scope(isolate_);
   1231   // Call the JS function.
   1232   Handle<Object> undefined = isolate_->factory()->undefined_value();
   1233   MaybeHandle<Object> retval =
   1234       Execution::Call(isolate_, start_function_, undefined, 0, nullptr);
   1235 
   1236   if (retval.is_null()) {
   1237     DCHECK(isolate_->has_pending_exception());
   1238     return false;
   1239   }
   1240   return true;
   1241 }
   1242 
   1243 // Look up an import value in the {ffi_} object.
   1244 MaybeHandle<Object> InstanceBuilder::LookupImport(uint32_t index,
   1245                                                   Handle<String> module_name,
   1246 
   1247                                                   Handle<String> import_name) {
   1248   // We pre-validated in the js-api layer that the ffi object is present, and
   1249   // a JSObject, if the module has imports.
   1250   DCHECK(!ffi_.is_null());
   1251 
   1252   // Look up the module first.
   1253   MaybeHandle<Object> result = Object::GetPropertyOrElement(
   1254       isolate_, ffi_.ToHandleChecked(), module_name);
   1255   if (result.is_null()) {
   1256     return ReportTypeError("module not found", index, module_name);
   1257   }
   1258 
   1259   Handle<Object> module = result.ToHandleChecked();
   1260 
   1261   // Look up the value in the module.
   1262   if (!module->IsJSReceiver()) {
   1263     return ReportTypeError("module is not an object or function", index,
   1264                            module_name);
   1265   }
   1266 
   1267   result = Object::GetPropertyOrElement(isolate_, module, import_name);
   1268   if (result.is_null()) {
   1269     ReportLinkError("import not found", index, module_name, import_name);
   1270     return MaybeHandle<JSFunction>();
   1271   }
   1272 
   1273   return result;
   1274 }
   1275 
   1276 // Look up an import value in the {ffi_} object specifically for linking an
   1277 // asm.js module. This only performs non-observable lookups, which allows
   1278 // falling back to JavaScript proper (and hence re-executing all lookups) if
   1279 // module instantiation fails.
   1280 MaybeHandle<Object> InstanceBuilder::LookupImportAsm(
   1281     uint32_t index, Handle<String> import_name) {
   1282   // Check that a foreign function interface object was provided.
   1283   if (ffi_.is_null()) {
   1284     return ReportLinkError("missing imports object", index, import_name);
   1285   }
   1286 
   1287   // Perform lookup of the given {import_name} without causing any observable
   1288   // side-effect. We only accept accesses that resolve to data properties,
   1289   // which is indicated by the asm.js spec in section 7 ("Linking") as well.
   1290   Handle<Object> result;
   1291   LookupIterator it = LookupIterator::PropertyOrElement(
   1292       isolate_, ffi_.ToHandleChecked(), import_name);
   1293   switch (it.state()) {
   1294     case LookupIterator::ACCESS_CHECK:
   1295     case LookupIterator::INTEGER_INDEXED_EXOTIC:
   1296     case LookupIterator::INTERCEPTOR:
   1297     case LookupIterator::JSPROXY:
   1298     case LookupIterator::ACCESSOR:
   1299     case LookupIterator::TRANSITION:
   1300       return ReportLinkError("not a data property", index, import_name);
   1301     case LookupIterator::NOT_FOUND:
   1302       // Accepting missing properties as undefined does not cause any
   1303       // observable difference from JavaScript semantics, we are lenient.
   1304       result = isolate_->factory()->undefined_value();
   1305       break;
   1306     case LookupIterator::DATA:
   1307       result = it.GetDataValue();
   1308       break;
   1309   }
   1310 
   1311   return result;
   1312 }
   1313 
   1314 uint32_t InstanceBuilder::EvalUint32InitExpr(const WasmInitExpr& expr) {
   1315   switch (expr.kind) {
   1316     case WasmInitExpr::kI32Const:
   1317       return expr.val.i32_const;
   1318     case WasmInitExpr::kGlobalIndex: {
   1319       uint32_t offset = module_->globals[expr.val.global_index].offset;
   1320       return ReadLittleEndianValue<uint32_t>(
   1321           reinterpret_cast<Address>(raw_buffer_ptr(globals_, offset)));
   1322     }
   1323     default:
   1324       UNREACHABLE();
   1325   }
   1326 }
   1327 
   1328 // Load data segments into the memory.
   1329 void InstanceBuilder::LoadDataSegments(Handle<WasmInstanceObject> instance) {
   1330   Vector<const uint8_t> wire_bytes =
   1331       module_object_->native_module()->wire_bytes();
   1332   for (const WasmDataSegment& segment : module_->data_segments) {
   1333     uint32_t source_size = segment.source.length();
   1334     // Segments of size == 0 are just nops.
   1335     if (source_size == 0) continue;
   1336     uint32_t dest_offset = EvalUint32InitExpr(segment.dest_addr);
   1337     DCHECK(in_bounds(dest_offset, source_size, instance->memory_size()));
   1338     byte* dest = instance->memory_start() + dest_offset;
   1339     const byte* src = wire_bytes.start() + segment.source.offset();
   1340     memcpy(dest, src, source_size);
   1341   }
   1342 }
   1343 
   1344 void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global, double num) {
   1345   TRACE("init [globals_start=%p + %u] = %lf, type = %s\n",
   1346         reinterpret_cast<void*>(raw_buffer_ptr(globals_, 0)), global.offset,
   1347         num, ValueTypes::TypeName(global.type));
   1348   switch (global.type) {
   1349     case kWasmI32:
   1350       WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global),
   1351                                       static_cast<int32_t>(num));
   1352       break;
   1353     case kWasmI64:
   1354       // TODO(titzer): initialization of imported i64 globals.
   1355       UNREACHABLE();
   1356       break;
   1357     case kWasmF32:
   1358       WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global),
   1359                                     static_cast<float>(num));
   1360       break;
   1361     case kWasmF64:
   1362       WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global),
   1363                                      static_cast<double>(num));
   1364       break;
   1365     default:
   1366       UNREACHABLE();
   1367   }
   1368 }
   1369 
   1370 void InstanceBuilder::WriteGlobalValue(const WasmGlobal& global,
   1371                                        Handle<WasmGlobalObject> value) {
   1372   TRACE("init [globals_start=%p + %u] = ",
   1373         reinterpret_cast<void*>(raw_buffer_ptr(globals_, 0)), global.offset);
   1374   switch (global.type) {
   1375     case kWasmI32: {
   1376       int32_t num = value->GetI32();
   1377       WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global), num);
   1378       TRACE("%d", num);
   1379       break;
   1380     }
   1381     case kWasmI64: {
   1382       int64_t num = value->GetI64();
   1383       WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global), num);
   1384       TRACE("%" PRId64, num);
   1385       break;
   1386     }
   1387     case kWasmF32: {
   1388       float num = value->GetF32();
   1389       WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global), num);
   1390       TRACE("%f", num);
   1391       break;
   1392     }
   1393     case kWasmF64: {
   1394       double num = value->GetF64();
   1395       WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global), num);
   1396       TRACE("%lf", num);
   1397       break;
   1398     }
   1399     default:
   1400       UNREACHABLE();
   1401   }
   1402   TRACE(", type = %s (from WebAssembly.Global)\n",
   1403         ValueTypes::TypeName(global.type));
   1404 }
   1405 
   1406 void InstanceBuilder::SanitizeImports() {
   1407   Vector<const uint8_t> wire_bytes =
   1408       module_object_->native_module()->wire_bytes();
   1409   for (size_t index = 0; index < module_->import_table.size(); ++index) {
   1410     const WasmImport& import = module_->import_table[index];
   1411 
   1412     Handle<String> module_name;
   1413     MaybeHandle<String> maybe_module_name =
   1414         WasmModuleObject::ExtractUtf8StringFromModuleBytes(isolate_, wire_bytes,
   1415                                                            import.module_name);
   1416     if (!maybe_module_name.ToHandle(&module_name)) {
   1417       thrower_->LinkError("Could not resolve module name for import %zu",
   1418                           index);
   1419       return;
   1420     }
   1421 
   1422     Handle<String> import_name;
   1423     MaybeHandle<String> maybe_import_name =
   1424         WasmModuleObject::ExtractUtf8StringFromModuleBytes(isolate_, wire_bytes,
   1425                                                            import.field_name);
   1426     if (!maybe_import_name.ToHandle(&import_name)) {
   1427       thrower_->LinkError("Could not resolve import name for import %zu",
   1428                           index);
   1429       return;
   1430     }
   1431 
   1432     int int_index = static_cast<int>(index);
   1433     MaybeHandle<Object> result =
   1434         module_->origin == kAsmJsOrigin
   1435             ? LookupImportAsm(int_index, import_name)
   1436             : LookupImport(int_index, module_name, import_name);
   1437     if (thrower_->error()) {
   1438       thrower_->LinkError("Could not find value for import %zu", index);
   1439       return;
   1440     }
   1441     Handle<Object> value = result.ToHandleChecked();
   1442     sanitized_imports_.push_back({module_name, import_name, value});
   1443   }
   1444 }
   1445 
   1446 MaybeHandle<JSArrayBuffer> InstanceBuilder::FindImportedMemoryBuffer() const {
   1447   DCHECK_EQ(module_->import_table.size(), sanitized_imports_.size());
   1448   for (size_t index = 0; index < module_->import_table.size(); index++) {
   1449     const WasmImport& import = module_->import_table[index];
   1450 
   1451     if (import.kind == kExternalMemory) {
   1452       const auto& value = sanitized_imports_[index].value;
   1453       if (!value->IsWasmMemoryObject()) {
   1454         return {};
   1455       }
   1456       auto memory = Handle<WasmMemoryObject>::cast(value);
   1457       Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate_);
   1458       return buffer;
   1459     }
   1460   }
   1461   return {};
   1462 }
   1463 
   1464 // Process the imports, including functions, tables, globals, and memory, in
   1465 // order, loading them from the {ffi_} object. Returns the number of imported
   1466 // functions.
   1467 int InstanceBuilder::ProcessImports(Handle<WasmInstanceObject> instance) {
   1468   int num_imported_functions = 0;
   1469   int num_imported_tables = 0;
   1470   int num_imported_mutable_globals = 0;
   1471 
   1472   DCHECK_EQ(module_->import_table.size(), sanitized_imports_.size());
   1473   int num_imports = static_cast<int>(module_->import_table.size());
   1474   NativeModule* native_module = instance->module_object()->native_module();
   1475   for (int index = 0; index < num_imports; ++index) {
   1476     const WasmImport& import = module_->import_table[index];
   1477 
   1478     Handle<String> module_name = sanitized_imports_[index].module_name;
   1479     Handle<String> import_name = sanitized_imports_[index].import_name;
   1480     Handle<Object> value = sanitized_imports_[index].value;
   1481 
   1482     switch (import.kind) {
   1483       case kExternalFunction: {
   1484         // Function imports must be callable.
   1485         if (!value->IsCallable()) {
   1486           ReportLinkError("function import requires a callable", index,
   1487                           module_name, import_name);
   1488           return -1;
   1489         }
   1490         uint32_t func_index = import.index;
   1491         DCHECK_EQ(num_imported_functions, func_index);
   1492         FunctionSig* expected_sig = module_->functions[func_index].sig;
   1493         if (WasmExportedFunction::IsWasmExportedFunction(*value)) {
   1494           // The imported function is a WASM function from another instance.
   1495           Handle<WasmExportedFunction> imported_function(
   1496               WasmExportedFunction::cast(*value), isolate_);
   1497           Handle<WasmInstanceObject> imported_instance(
   1498               imported_function->instance(), isolate_);
   1499           FunctionSig* imported_sig =
   1500               imported_instance->module()
   1501                   ->functions[imported_function->function_index()]
   1502                   .sig;
   1503           if (*imported_sig != *expected_sig) {
   1504             ReportLinkError(
   1505                 "imported function does not match the expected type", index,
   1506                 module_name, import_name);
   1507             return -1;
   1508           }
   1509           // The import reference is the instance object itself.
   1510           Address imported_target = imported_function->GetWasmCallTarget();
   1511           ImportedFunctionEntry entry(instance, func_index);
   1512           entry.set_wasm_to_wasm(*imported_instance, imported_target);
   1513         } else {
   1514           // The imported function is a callable.
   1515           Handle<JSReceiver> js_receiver(JSReceiver::cast(*value), isolate_);
   1516           Handle<Code> wrapper_code =
   1517               compiler::CompileWasmToJSWrapper(
   1518                   isolate_, js_receiver, expected_sig, func_index,
   1519                   module_->origin, use_trap_handler())
   1520                   .ToHandleChecked();
   1521           RecordStats(*wrapper_code, isolate_->counters());
   1522 
   1523           WasmCode* wasm_code = native_module->AddCodeCopy(
   1524               wrapper_code, WasmCode::kWasmToJsWrapper, func_index);
   1525           ImportedFunctionEntry entry(instance, func_index);
   1526           entry.set_wasm_to_js(*js_receiver, wasm_code);
   1527         }
   1528         num_imported_functions++;
   1529         break;
   1530       }
   1531       case kExternalTable: {
   1532         if (!value->IsWasmTableObject()) {
   1533           ReportLinkError("table import requires a WebAssembly.Table", index,
   1534                           module_name, import_name);
   1535           return -1;
   1536         }
   1537         uint32_t table_num = import.index;
   1538         DCHECK_EQ(table_num, num_imported_tables);
   1539         const WasmTable& table = module_->tables[table_num];
   1540         TableInstance& table_instance = table_instances_[table_num];
   1541         table_instance.table_object = Handle<WasmTableObject>::cast(value);
   1542         instance->set_table_object(*table_instance.table_object);
   1543         table_instance.js_wrappers = Handle<FixedArray>(
   1544             table_instance.table_object->functions(), isolate_);
   1545 
   1546         int imported_table_size = table_instance.js_wrappers->length();
   1547         if (imported_table_size < static_cast<int>(table.initial_size)) {
   1548           thrower_->LinkError(
   1549               "table import %d is smaller than initial %d, got %u", index,
   1550               table.initial_size, imported_table_size);
   1551           return -1;
   1552         }
   1553 
   1554         if (table.has_maximum_size) {
   1555           int64_t imported_maximum_size =
   1556               table_instance.table_object->maximum_length()->Number();
   1557           if (imported_maximum_size < 0) {
   1558             thrower_->LinkError(
   1559                 "table import %d has no maximum length, expected %d", index,
   1560                 table.maximum_size);
   1561             return -1;
   1562           }
   1563           if (imported_maximum_size > table.maximum_size) {
   1564             thrower_->LinkError(
   1565                 " table import %d has a larger maximum size %" PRIx64
   1566                 " than the module's declared maximum %u",
   1567                 index, imported_maximum_size, table.maximum_size);
   1568             return -1;
   1569           }
   1570         }
   1571 
   1572         // Allocate a new dispatch table.
   1573         if (!instance->has_indirect_function_table()) {
   1574           WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
   1575               instance, imported_table_size);
   1576           table_instances_[table_num].table_size = imported_table_size;
   1577         }
   1578         // Initialize the dispatch table with the (foreign) JS functions
   1579         // that are already in the table.
   1580         for (int i = 0; i < imported_table_size; ++i) {
   1581           Handle<Object> val(table_instance.js_wrappers->get(i), isolate_);
   1582           // TODO(mtrofin): this is the same logic as WasmTableObject::Set:
   1583           // insert in the local table a wrapper from the other module, and add
   1584           // a reference to the owning instance of the other module.
   1585           if (!val->IsJSFunction()) continue;
   1586           if (!WasmExportedFunction::IsWasmExportedFunction(*val)) {
   1587             thrower_->LinkError("table import %d[%d] is not a wasm function",
   1588                                 index, i);
   1589             return -1;
   1590           }
   1591           // Look up the signature's canonical id. If there is no canonical
   1592           // id, then the signature does not appear at all in this module,
   1593           // so putting {-1} in the table will cause checks to always fail.
   1594           auto target = Handle<WasmExportedFunction>::cast(val);
   1595           Handle<WasmInstanceObject> imported_instance =
   1596               handle(target->instance(), isolate_);
   1597           Address exported_call_target = target->GetWasmCallTarget();
   1598           FunctionSig* sig = imported_instance->module()
   1599                                  ->functions[target->function_index()]
   1600                                  .sig;
   1601           IndirectFunctionTableEntry(instance, i)
   1602               .set(module_->signature_map.Find(*sig), *imported_instance,
   1603                    exported_call_target);
   1604         }
   1605         num_imported_tables++;
   1606         break;
   1607       }
   1608       case kExternalMemory: {
   1609         // Validation should have failed if more than one memory object was
   1610         // provided.
   1611         DCHECK(!instance->has_memory_object());
   1612         if (!value->IsWasmMemoryObject()) {
   1613           ReportLinkError("memory import must be a WebAssembly.Memory object",
   1614                           index, module_name, import_name);
   1615           return -1;
   1616         }
   1617         auto memory = Handle<WasmMemoryObject>::cast(value);
   1618         instance->set_memory_object(*memory);
   1619         Handle<JSArrayBuffer> buffer(memory->array_buffer(), isolate_);
   1620         // memory_ should have already been assigned in Build().
   1621         DCHECK_EQ(*memory_.ToHandleChecked(), *buffer);
   1622         uint32_t imported_cur_pages = static_cast<uint32_t>(
   1623             buffer->byte_length()->Number() / kWasmPageSize);
   1624         if (imported_cur_pages < module_->initial_pages) {
   1625           thrower_->LinkError(
   1626               "memory import %d is smaller than initial %u, got %u", index,
   1627               module_->initial_pages, imported_cur_pages);
   1628         }
   1629         int32_t imported_maximum_pages = memory->maximum_pages();
   1630         if (module_->has_maximum_pages) {
   1631           if (imported_maximum_pages < 0) {
   1632             thrower_->LinkError(
   1633                 "memory import %d has no maximum limit, expected at most %u",
   1634                 index, imported_maximum_pages);
   1635             return -1;
   1636           }
   1637           if (static_cast<uint32_t>(imported_maximum_pages) >
   1638               module_->maximum_pages) {
   1639             thrower_->LinkError(
   1640                 "memory import %d has a larger maximum size %u than the "
   1641                 "module's declared maximum %u",
   1642                 index, imported_maximum_pages, module_->maximum_pages);
   1643             return -1;
   1644           }
   1645         }
   1646         if (module_->has_shared_memory != buffer->is_shared()) {
   1647           thrower_->LinkError(
   1648               "mismatch in shared state of memory, declared = %d, imported = "
   1649               "%d",
   1650               module_->has_shared_memory, buffer->is_shared());
   1651           return -1;
   1652         }
   1653 
   1654         break;
   1655       }
   1656       case kExternalGlobal: {
   1657         // Immutable global imports are converted to numbers and written into
   1658         // the {globals_} array buffer.
   1659         //
   1660         // Mutable global imports instead have their backing array buffers
   1661         // referenced by this instance, and store the address of the imported
   1662         // global in the {imported_mutable_globals_} array.
   1663         const WasmGlobal& global = module_->globals[import.index];
   1664 
   1665         // The mutable-global proposal allows importing i64 values, but only if
   1666         // they are passed as a WebAssembly.Global object.
   1667         if (global.type == kWasmI64 &&
   1668             !(enabled_.mut_global && value->IsWasmGlobalObject())) {
   1669           ReportLinkError("global import cannot have type i64", index,
   1670                           module_name, import_name);
   1671           return -1;
   1672         }
   1673         if (module_->origin == kAsmJsOrigin) {
   1674           // Accepting {JSFunction} on top of just primitive values here is a
   1675           // workaround to support legacy asm.js code with broken binding. Note
   1676           // that using {NaN} (or Smi::kZero) here is what using the observable
   1677           // conversion via {ToPrimitive} would produce as well.
   1678           // TODO(mstarzinger): Still observable if Function.prototype.valueOf
   1679           // or friends are patched, we might need to check for that as well.
   1680           if (value->IsJSFunction()) value = isolate_->factory()->nan_value();
   1681           if (value->IsPrimitive() && !value->IsSymbol()) {
   1682             if (global.type == kWasmI32) {
   1683               value = Object::ToInt32(isolate_, value).ToHandleChecked();
   1684             } else {
   1685               value = Object::ToNumber(isolate_, value).ToHandleChecked();
   1686             }
   1687           }
   1688         }
   1689         if (enabled_.mut_global) {
   1690           if (value->IsWasmGlobalObject()) {
   1691             auto global_object = Handle<WasmGlobalObject>::cast(value);
   1692             if (global_object->type() != global.type) {
   1693               ReportLinkError(
   1694                   "imported global does not match the expected type", index,
   1695                   module_name, import_name);
   1696               return -1;
   1697             }
   1698             if (global_object->is_mutable() != global.mutability) {
   1699               ReportLinkError(
   1700                   "imported global does not match the expected mutability",
   1701                   index, module_name, import_name);
   1702               return -1;
   1703             }
   1704             if (global.mutability) {
   1705               Handle<JSArrayBuffer> buffer(global_object->array_buffer(),
   1706                                            isolate_);
   1707               int index = num_imported_mutable_globals++;
   1708               instance->imported_mutable_globals_buffers()->set(index, *buffer);
   1709               // It is safe in this case to store the raw pointer to the buffer
   1710               // since the backing store of the JSArrayBuffer will not be
   1711               // relocated.
   1712               instance->imported_mutable_globals()[index] =
   1713                   reinterpret_cast<Address>(
   1714                       raw_buffer_ptr(buffer, global_object->offset()));
   1715             } else {
   1716               WriteGlobalValue(global, global_object);
   1717             }
   1718           } else if (value->IsNumber()) {
   1719             if (global.mutability) {
   1720               ReportLinkError(
   1721                   "imported mutable global must be a WebAssembly.Global object",
   1722                   index, module_name, import_name);
   1723               return -1;
   1724             }
   1725             WriteGlobalValue(global, value->Number());
   1726           } else {
   1727             ReportLinkError(
   1728                 "global import must be a number or WebAssembly.Global object",
   1729                 index, module_name, import_name);
   1730             return -1;
   1731           }
   1732         } else {
   1733           if (value->IsNumber()) {
   1734             WriteGlobalValue(global, value->Number());
   1735           } else {
   1736             ReportLinkError("global import must be a number", index,
   1737                             module_name, import_name);
   1738             return -1;
   1739           }
   1740         }
   1741         break;
   1742       }
   1743       default:
   1744         UNREACHABLE();
   1745         break;
   1746     }
   1747   }
   1748 
   1749   DCHECK_EQ(module_->num_imported_mutable_globals,
   1750             num_imported_mutable_globals);
   1751 
   1752   return num_imported_functions;
   1753 }
   1754 
   1755 template <typename T>
   1756 T* InstanceBuilder::GetRawGlobalPtr(const WasmGlobal& global) {
   1757   return reinterpret_cast<T*>(raw_buffer_ptr(globals_, global.offset));
   1758 }
   1759 
   1760 // Process initialization of globals.
   1761 void InstanceBuilder::InitGlobals() {
   1762   for (auto global : module_->globals) {
   1763     if (global.mutability && global.imported) {
   1764       continue;
   1765     }
   1766 
   1767     switch (global.init.kind) {
   1768       case WasmInitExpr::kI32Const:
   1769         WriteLittleEndianValue<int32_t>(GetRawGlobalPtr<int32_t>(global),
   1770                                         global.init.val.i32_const);
   1771         break;
   1772       case WasmInitExpr::kI64Const:
   1773         WriteLittleEndianValue<int64_t>(GetRawGlobalPtr<int64_t>(global),
   1774                                         global.init.val.i64_const);
   1775         break;
   1776       case WasmInitExpr::kF32Const:
   1777         WriteLittleEndianValue<float>(GetRawGlobalPtr<float>(global),
   1778                                       global.init.val.f32_const);
   1779         break;
   1780       case WasmInitExpr::kF64Const:
   1781         WriteLittleEndianValue<double>(GetRawGlobalPtr<double>(global),
   1782                                        global.init.val.f64_const);
   1783         break;
   1784       case WasmInitExpr::kGlobalIndex: {
   1785         // Initialize with another global.
   1786         uint32_t new_offset = global.offset;
   1787         uint32_t old_offset =
   1788             module_->globals[global.init.val.global_index].offset;
   1789         TRACE("init [globals+%u] = [globals+%d]\n", global.offset, old_offset);
   1790         size_t size = (global.type == kWasmI64 || global.type == kWasmF64)
   1791                           ? sizeof(double)
   1792                           : sizeof(int32_t);
   1793         memcpy(raw_buffer_ptr(globals_, new_offset),
   1794                raw_buffer_ptr(globals_, old_offset), size);
   1795         break;
   1796       }
   1797       case WasmInitExpr::kNone:
   1798         // Happens with imported globals.
   1799         break;
   1800       default:
   1801         UNREACHABLE();
   1802         break;
   1803     }
   1804   }
   1805 }
   1806 
   1807 // Allocate memory for a module instance as a new JSArrayBuffer.
   1808 Handle<JSArrayBuffer> InstanceBuilder::AllocateMemory(uint32_t num_pages) {
   1809   if (num_pages > FLAG_wasm_max_mem_pages) {
   1810     thrower_->RangeError("Out of memory: wasm memory too large");
   1811     return Handle<JSArrayBuffer>::null();
   1812   }
   1813   const bool is_shared_memory = module_->has_shared_memory && enabled_.threads;
   1814   i::SharedFlag shared_flag =
   1815       is_shared_memory ? i::SharedFlag::kShared : i::SharedFlag::kNotShared;
   1816   Handle<JSArrayBuffer> mem_buffer;
   1817   if (!NewArrayBuffer(isolate_, num_pages * kWasmPageSize, shared_flag)
   1818            .ToHandle(&mem_buffer)) {
   1819     thrower_->RangeError("Out of memory: wasm memory");
   1820   }
   1821   return mem_buffer;
   1822 }
   1823 
   1824 bool InstanceBuilder::NeedsWrappers() const {
   1825   if (module_->num_exported_functions > 0) return true;
   1826   for (auto& table_instance : table_instances_) {
   1827     if (!table_instance.js_wrappers.is_null()) return true;
   1828   }
   1829   for (auto& table : module_->tables) {
   1830     if (table.exported) return true;
   1831   }
   1832   return false;
   1833 }
   1834 
   1835 // Process the exports, creating wrappers for functions, tables, memories,
   1836 // and globals.
   1837 void InstanceBuilder::ProcessExports(Handle<WasmInstanceObject> instance) {
   1838   Handle<FixedArray> export_wrappers(module_object_->export_wrappers(),
   1839                                      isolate_);
   1840   if (NeedsWrappers()) {
   1841     // Fill the table to cache the exported JSFunction wrappers.
   1842     js_wrappers_.insert(js_wrappers_.begin(), module_->functions.size(),
   1843                         Handle<JSFunction>::null());
   1844 
   1845     // If an imported WebAssembly function gets exported, the exported function
   1846     // has to be identical to to imported function. Therefore we put all
   1847     // imported WebAssembly functions into the js_wrappers_ list.
   1848     for (int index = 0, end = static_cast<int>(module_->import_table.size());
   1849          index < end; ++index) {
   1850       const WasmImport& import = module_->import_table[index];
   1851       if (import.kind == kExternalFunction) {
   1852         Handle<Object> value = sanitized_imports_[index].value;
   1853         if (WasmExportedFunction::IsWasmExportedFunction(*value)) {
   1854           js_wrappers_[import.index] = Handle<JSFunction>::cast(value);
   1855         }
   1856       }
   1857     }
   1858   }
   1859 
   1860   Handle<JSObject> exports_object;
   1861   bool is_asm_js = false;
   1862   switch (module_->origin) {
   1863     case kWasmOrigin: {
   1864       // Create the "exports" object.
   1865       exports_object = isolate_->factory()->NewJSObjectWithNullProto();
   1866       break;
   1867     }
   1868     case kAsmJsOrigin: {
   1869       Handle<JSFunction> object_function = Handle<JSFunction>(
   1870           isolate_->native_context()->object_function(), isolate_);
   1871       exports_object = isolate_->factory()->NewJSObject(object_function);
   1872       is_asm_js = true;
   1873       break;
   1874     }
   1875     default:
   1876       UNREACHABLE();
   1877   }
   1878   instance->set_exports_object(*exports_object);
   1879 
   1880   Handle<String> single_function_name =
   1881       isolate_->factory()->InternalizeUtf8String(AsmJs::kSingleFunctionName);
   1882 
   1883   PropertyDescriptor desc;
   1884   desc.set_writable(is_asm_js);
   1885   desc.set_enumerable(true);
   1886   desc.set_configurable(is_asm_js);
   1887 
   1888   // Process each export in the export table.
   1889   int export_index = 0;  // Index into {export_wrappers}.
   1890   for (const WasmExport& exp : module_->export_table) {
   1891     Handle<String> name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
   1892                               isolate_, module_object_, exp.name)
   1893                               .ToHandleChecked();
   1894     Handle<JSObject> export_to;
   1895     if (is_asm_js && exp.kind == kExternalFunction &&
   1896         String::Equals(isolate_, name, single_function_name)) {
   1897       export_to = instance;
   1898     } else {
   1899       export_to = exports_object;
   1900     }
   1901 
   1902     switch (exp.kind) {
   1903       case kExternalFunction: {
   1904         // Wrap and export the code as a JSFunction.
   1905         const WasmFunction& function = module_->functions[exp.index];
   1906         Handle<JSFunction> js_function = js_wrappers_[exp.index];
   1907         if (js_function.is_null()) {
   1908           // Wrap the exported code as a JSFunction.
   1909           Handle<Code> export_code =
   1910               export_wrappers->GetValueChecked<Code>(isolate_, export_index);
   1911           MaybeHandle<String> func_name;
   1912           if (is_asm_js) {
   1913             // For modules arising from asm.js, honor the names section.
   1914             WireBytesRef func_name_ref = module_->LookupFunctionName(
   1915                 module_object_->native_module()->wire_bytes(),
   1916                 function.func_index);
   1917             func_name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
   1918                             isolate_, module_object_, func_name_ref)
   1919                             .ToHandleChecked();
   1920           }
   1921           js_function = WasmExportedFunction::New(
   1922               isolate_, instance, func_name, function.func_index,
   1923               static_cast<int>(function.sig->parameter_count()), export_code);
   1924           js_wrappers_[exp.index] = js_function;
   1925         }
   1926         desc.set_value(js_function);
   1927         export_index++;
   1928         break;
   1929       }
   1930       case kExternalTable: {
   1931         // Export a table as a WebAssembly.Table object.
   1932         TableInstance& table_instance = table_instances_[exp.index];
   1933         const WasmTable& table = module_->tables[exp.index];
   1934         if (table_instance.table_object.is_null()) {
   1935           uint32_t maximum = table.has_maximum_size ? table.maximum_size
   1936                                                     : FLAG_wasm_max_table_size;
   1937           table_instance.table_object =
   1938               WasmTableObject::New(isolate_, table.initial_size, maximum,
   1939                                    &table_instance.js_wrappers);
   1940         }
   1941         desc.set_value(table_instance.table_object);
   1942         break;
   1943       }
   1944       case kExternalMemory: {
   1945         // Export the memory as a WebAssembly.Memory object. A WasmMemoryObject
   1946         // should already be available if the module has memory, since we always
   1947         // create or import it when building an WasmInstanceObject.
   1948         DCHECK(instance->has_memory_object());
   1949         desc.set_value(
   1950             Handle<WasmMemoryObject>(instance->memory_object(), isolate_));
   1951         break;
   1952       }
   1953       case kExternalGlobal: {
   1954         const WasmGlobal& global = module_->globals[exp.index];
   1955         if (enabled_.mut_global) {
   1956           Handle<JSArrayBuffer> buffer;
   1957           uint32_t offset;
   1958 
   1959           if (global.mutability && global.imported) {
   1960             Handle<FixedArray> buffers_array(
   1961                 instance->imported_mutable_globals_buffers(), isolate_);
   1962             buffer = buffers_array->GetValueChecked<JSArrayBuffer>(
   1963                 isolate_, global.index);
   1964             Address global_addr =
   1965                 instance->imported_mutable_globals()[global.index];
   1966 
   1967             uint32_t buffer_size = 0;
   1968             CHECK(buffer->byte_length()->ToUint32(&buffer_size));
   1969 
   1970             Address backing_store =
   1971                 reinterpret_cast<Address>(buffer->backing_store());
   1972             CHECK(global_addr >= backing_store &&
   1973                   global_addr < backing_store + buffer_size);
   1974             offset = static_cast<uint32_t>(global_addr - backing_store);
   1975           } else {
   1976             buffer = handle(instance->globals_buffer(), isolate_);
   1977             offset = global.offset;
   1978           }
   1979 
   1980           // Since the global's array buffer is always provided, allocation
   1981           // should never fail.
   1982           Handle<WasmGlobalObject> global_obj =
   1983               WasmGlobalObject::New(isolate_, buffer, global.type, offset,
   1984                                     global.mutability)
   1985                   .ToHandleChecked();
   1986           desc.set_value(global_obj);
   1987         } else {
   1988           // Export the value of the global variable as a number.
   1989           double num = 0;
   1990           switch (global.type) {
   1991             case kWasmI32:
   1992               num = ReadLittleEndianValue<int32_t>(
   1993                   GetRawGlobalPtr<int32_t>(global));
   1994               break;
   1995             case kWasmF32:
   1996               num =
   1997                   ReadLittleEndianValue<float>(GetRawGlobalPtr<float>(global));
   1998               break;
   1999             case kWasmF64:
   2000               num = ReadLittleEndianValue<double>(
   2001                   GetRawGlobalPtr<double>(global));
   2002               break;
   2003             case kWasmI64:
   2004               thrower_->LinkError(
   2005                   "export of globals of type I64 is not allowed.");
   2006               return;
   2007             default:
   2008               UNREACHABLE();
   2009           }
   2010           desc.set_value(isolate_->factory()->NewNumber(num));
   2011         }
   2012         break;
   2013       }
   2014       default:
   2015         UNREACHABLE();
   2016         break;
   2017     }
   2018 
   2019     v8::Maybe<bool> status = JSReceiver::DefineOwnProperty(
   2020         isolate_, export_to, name, &desc, kThrowOnError);
   2021     if (!status.IsJust()) {
   2022       TruncatedUserString<> trunc_name(name->GetCharVector<uint8_t>());
   2023       thrower_->LinkError("export of %.*s failed.", trunc_name.length(),
   2024                           trunc_name.start());
   2025       return;
   2026     }
   2027   }
   2028   DCHECK_EQ(export_index, export_wrappers->length());
   2029 
   2030   if (module_->origin == kWasmOrigin) {
   2031     v8::Maybe<bool> success =
   2032         JSReceiver::SetIntegrityLevel(exports_object, FROZEN, kDontThrow);
   2033     DCHECK(success.FromMaybe(false));
   2034     USE(success);
   2035   }
   2036 }
   2037 
   2038 void InstanceBuilder::InitializeTables(Handle<WasmInstanceObject> instance) {
   2039   size_t table_count = module_->tables.size();
   2040   for (size_t index = 0; index < table_count; ++index) {
   2041     const WasmTable& table = module_->tables[index];
   2042     TableInstance& table_instance = table_instances_[index];
   2043 
   2044     if (!instance->has_indirect_function_table() &&
   2045         table.type == kWasmAnyFunc) {
   2046       WasmInstanceObject::EnsureIndirectFunctionTableWithMinimumSize(
   2047           instance, table.initial_size);
   2048       table_instance.table_size = table.initial_size;
   2049     }
   2050   }
   2051 }
   2052 
   2053 void InstanceBuilder::LoadTableSegments(Handle<WasmInstanceObject> instance) {
   2054   NativeModule* native_module = module_object_->native_module();
   2055   for (auto& table_init : module_->table_inits) {
   2056     uint32_t base = EvalUint32InitExpr(table_init.offset);
   2057     uint32_t num_entries = static_cast<uint32_t>(table_init.entries.size());
   2058     uint32_t index = table_init.table_index;
   2059     TableInstance& table_instance = table_instances_[index];
   2060     DCHECK(in_bounds(base, num_entries, table_instance.table_size));
   2061     for (uint32_t i = 0; i < num_entries; ++i) {
   2062       uint32_t func_index = table_init.entries[i];
   2063       const WasmFunction* function = &module_->functions[func_index];
   2064       int table_index = static_cast<int>(i + base);
   2065 
   2066       // Update the local dispatch table first.
   2067       uint32_t sig_id = module_->signature_ids[function->sig_index];
   2068       Handle<WasmInstanceObject> target_instance = instance;
   2069       Address call_target;
   2070       const bool is_import = func_index < module_->num_imported_functions;
   2071       if (is_import) {
   2072         // For imported calls, take target instance and address from the
   2073         // import table.
   2074         ImportedFunctionEntry entry(instance, func_index);
   2075         target_instance = handle(entry.instance(), isolate_);
   2076         call_target = entry.target();
   2077       } else {
   2078         call_target = native_module->GetCallTargetForFunction(func_index);
   2079       }
   2080       IndirectFunctionTableEntry(instance, table_index)
   2081           .set(sig_id, *target_instance, call_target);
   2082 
   2083       if (!table_instance.table_object.is_null()) {
   2084         // Update the table object's other dispatch tables.
   2085         if (js_wrappers_[func_index].is_null()) {
   2086           // No JSFunction entry yet exists for this function. Create one.
   2087           // TODO(titzer): We compile JS->wasm wrappers for functions are
   2088           // not exported but are in an exported table. This should be done
   2089           // at module compile time and cached instead.
   2090 
   2091           Handle<Code> wrapper_code =
   2092               js_to_wasm_cache_.GetOrCompileJSToWasmWrapper(
   2093                   isolate_, native_module, func_index, use_trap_handler());
   2094           MaybeHandle<String> func_name;
   2095           if (module_->origin == kAsmJsOrigin) {
   2096             // For modules arising from asm.js, honor the names section.
   2097             WireBytesRef func_name_ref = module_->LookupFunctionName(
   2098                 native_module->wire_bytes(), func_index);
   2099             func_name = WasmModuleObject::ExtractUtf8StringFromModuleBytes(
   2100                             isolate_, module_object_, func_name_ref)
   2101                             .ToHandleChecked();
   2102           }
   2103           Handle<WasmExportedFunction> js_function = WasmExportedFunction::New(
   2104               isolate_, instance, func_name, func_index,
   2105               static_cast<int>(function->sig->parameter_count()), wrapper_code);
   2106           js_wrappers_[func_index] = js_function;
   2107         }
   2108         table_instance.js_wrappers->set(table_index, *js_wrappers_[func_index]);
   2109         // UpdateDispatchTables() updates all other dispatch tables, since
   2110         // we have not yet added the dispatch table we are currently building.
   2111         WasmTableObject::UpdateDispatchTables(
   2112             isolate_, table_instance.table_object, table_index, function->sig,
   2113             target_instance, call_target);
   2114       }
   2115     }
   2116   }
   2117 
   2118   int table_count = static_cast<int>(module_->tables.size());
   2119   for (int index = 0; index < table_count; ++index) {
   2120     TableInstance& table_instance = table_instances_[index];
   2121 
   2122     // Add the new dispatch table at the end to avoid redundant lookups.
   2123     if (!table_instance.table_object.is_null()) {
   2124       WasmTableObject::AddDispatchTable(isolate_, table_instance.table_object,
   2125                                         instance, index);
   2126     }
   2127   }
   2128 }
   2129 
   2130 AsyncCompileJob::AsyncCompileJob(
   2131     Isolate* isolate, const WasmFeatures& enabled,
   2132     std::unique_ptr<byte[]> bytes_copy, size_t length, Handle<Context> context,
   2133     std::shared_ptr<CompilationResultResolver> resolver)
   2134     : isolate_(isolate),
   2135       enabled_features_(enabled),
   2136       async_counters_(isolate->async_counters()),
   2137       bytes_copy_(std::move(bytes_copy)),
   2138       wire_bytes_(bytes_copy_.get(), bytes_copy_.get() + length),
   2139       resolver_(std::move(resolver)) {
   2140   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
   2141   v8::Platform* platform = V8::GetCurrentPlatform();
   2142   foreground_task_runner_ = platform->GetForegroundTaskRunner(v8_isolate);
   2143   // The handle for the context must be deferred.
   2144   DeferredHandleScope deferred(isolate);
   2145   native_context_ = Handle<Context>(context->native_context(), isolate);
   2146   DCHECK(native_context_->IsNativeContext());
   2147   deferred_handles_.push_back(deferred.Detach());
   2148 }
   2149 
   2150 void AsyncCompileJob::Start() {
   2151   DoAsync<DecodeModule>();  // --
   2152 }
   2153 
   2154 void AsyncCompileJob::Abort() {
   2155   // Removing this job will trigger the destructor, which will cancel all
   2156   // compilation.
   2157   isolate_->wasm_engine()->RemoveCompileJob(this);
   2158 }
   2159 
   2160 class AsyncStreamingProcessor final : public StreamingProcessor {
   2161  public:
   2162   explicit AsyncStreamingProcessor(AsyncCompileJob* job);
   2163 
   2164   bool ProcessModuleHeader(Vector<const uint8_t> bytes,
   2165                            uint32_t offset) override;
   2166 
   2167   bool ProcessSection(SectionCode section_code, Vector<const uint8_t> bytes,
   2168                       uint32_t offset) override;
   2169 
   2170   bool ProcessCodeSectionHeader(size_t functions_count,
   2171                                 uint32_t offset) override;
   2172 
   2173   bool ProcessFunctionBody(Vector<const uint8_t> bytes,
   2174                            uint32_t offset) override;
   2175 
   2176   void OnFinishedChunk() override;
   2177 
   2178   void OnFinishedStream(OwnedVector<uint8_t> bytes) override;
   2179 
   2180   void OnError(DecodeResult result) override;
   2181 
   2182   void OnAbort() override;
   2183 
   2184  private:
   2185   // Finishes the AsyncCompileJob with an error.
   2186   void FinishAsyncCompileJobWithError(ResultBase result);
   2187 
   2188   void CommitCompilationUnits();
   2189 
   2190   ModuleDecoder decoder_;
   2191   AsyncCompileJob* job_;
   2192   std::unique_ptr<CompilationUnitBuilder> compilation_unit_builder_;
   2193   uint32_t next_function_ = 0;
   2194 };
   2195 
   2196 std::shared_ptr<StreamingDecoder> AsyncCompileJob::CreateStreamingDecoder() {
   2197   DCHECK_NULL(stream_);
   2198   stream_.reset(
   2199       new StreamingDecoder(base::make_unique<AsyncStreamingProcessor>(this)));
   2200   return stream_;
   2201 }
   2202 
   2203 AsyncCompileJob::~AsyncCompileJob() {
   2204   background_task_manager_.CancelAndWait();
   2205   if (native_module_) native_module_->compilation_state()->Abort();
   2206   // Tell the streaming decoder that the AsyncCompileJob is not available
   2207   // anymore.
   2208   // TODO(ahaas): Is this notification really necessary? Check
   2209   // https://crbug.com/888170.
   2210   if (stream_) stream_->NotifyCompilationEnded();
   2211   CancelPendingForegroundTask();
   2212   for (auto d : deferred_handles_) delete d;
   2213 }
   2214 
   2215 // This function assumes that it is executed in a HandleScope, and that a
   2216 // context is set on the isolate.
   2217 void AsyncCompileJob::FinishCompile() {
   2218   DCHECK_NOT_NULL(isolate_->context());
   2219   // Finish the wasm script now and make it public to the debugger.
   2220   Handle<Script> script(module_object_->script(), isolate_);
   2221   isolate_->debug()->OnAfterCompile(script);
   2222 
   2223   // Log the code within the generated module for profiling.
   2224   native_module_->LogWasmCodes(isolate_);
   2225 
   2226   // We can only update the feature counts once the entire compile is done.
   2227   auto compilation_state = native_module_->compilation_state();
   2228   compilation_state->PublishDetectedFeatures(
   2229       isolate_, *compilation_state->detected_features());
   2230 
   2231   // TODO(wasm): compiling wrappers should be made async as well.
   2232   DoSync<CompileWrappers>();
   2233 }
   2234 
   2235 void AsyncCompileJob::AsyncCompileFailed(Handle<Object> error_reason) {
   2236   // {job} keeps the {this} pointer alive.
   2237   std::shared_ptr<AsyncCompileJob> job =
   2238       isolate_->wasm_engine()->RemoveCompileJob(this);
   2239   resolver_->OnCompilationFailed(error_reason);
   2240 }
   2241 
   2242 void AsyncCompileJob::AsyncCompileSucceeded(Handle<WasmModuleObject> result) {
   2243   resolver_->OnCompilationSucceeded(result);
   2244 }
   2245 
   2246 // A closure to run a compilation step (either as foreground or background
   2247 // task) and schedule the next step(s), if any.
   2248 class AsyncCompileJob::CompileStep {
   2249  public:
   2250   virtual ~CompileStep() {}
   2251 
   2252   void Run(bool on_foreground) {
   2253     if (on_foreground) {
   2254       HandleScope scope(job_->isolate_);
   2255       SaveContext saved_context(job_->isolate_);
   2256       job_->isolate_->set_context(*job_->native_context_);
   2257       RunInForeground();
   2258     } else {
   2259       RunInBackground();
   2260     }
   2261   }
   2262 
   2263   virtual void RunInForeground() { UNREACHABLE(); }
   2264   virtual void RunInBackground() { UNREACHABLE(); }
   2265 
   2266   AsyncCompileJob* job_ = nullptr;
   2267 };
   2268 
   2269 class AsyncCompileJob::CompileTask : public CancelableTask {
   2270  public:
   2271   CompileTask(AsyncCompileJob* job, bool on_foreground)
   2272       // We only manage the background tasks with the {CancelableTaskManager} of
   2273       // the {AsyncCompileJob}. Foreground tasks are managed by the system's
   2274       // {CancelableTaskManager}. Background tasks cannot spawn tasks managed by
   2275       // their own task manager.
   2276       : CancelableTask(on_foreground ? job->isolate_->cancelable_task_manager()
   2277                                      : &job->background_task_manager_),
   2278         job_(job),
   2279         on_foreground_(on_foreground) {}
   2280 
   2281   ~CompileTask() {
   2282     if (job_ != nullptr && on_foreground_) ResetPendingForegroundTask();
   2283   }
   2284 
   2285   void RunInternal() final {
   2286     if (!job_) return;
   2287     if (on_foreground_) ResetPendingForegroundTask();
   2288     job_->step_->Run(on_foreground_);
   2289     // After execution, reset {job_} such that we don't try to reset the pending
   2290     // foreground task when the task is deleted.
   2291     job_ = nullptr;
   2292   }
   2293 
   2294   void Cancel() {
   2295     DCHECK_NOT_NULL(job_);
   2296     job_ = nullptr;
   2297   }
   2298 
   2299  private:
   2300   // {job_} will be cleared to cancel a pending task.
   2301   AsyncCompileJob* job_;
   2302   bool on_foreground_;
   2303 
   2304   void ResetPendingForegroundTask() const {
   2305     DCHECK_EQ(this, job_->pending_foreground_task_);
   2306     job_->pending_foreground_task_ = nullptr;
   2307   }
   2308 };
   2309 
   2310 void AsyncCompileJob::StartForegroundTask() {
   2311   DCHECK_NULL(pending_foreground_task_);
   2312 
   2313   auto new_task = base::make_unique<CompileTask>(this, true);
   2314   pending_foreground_task_ = new_task.get();
   2315   foreground_task_runner_->PostTask(std::move(new_task));
   2316 }
   2317 
   2318 void AsyncCompileJob::ExecuteForegroundTaskImmediately() {
   2319   DCHECK_NULL(pending_foreground_task_);
   2320 
   2321   auto new_task = base::make_unique<CompileTask>(this, true);
   2322   pending_foreground_task_ = new_task.get();
   2323   new_task->Run();
   2324 }
   2325 
   2326 void AsyncCompileJob::CancelPendingForegroundTask() {
   2327   if (!pending_foreground_task_) return;
   2328   pending_foreground_task_->Cancel();
   2329   pending_foreground_task_ = nullptr;
   2330 }
   2331 
   2332 void AsyncCompileJob::StartBackgroundTask() {
   2333   auto task = base::make_unique<CompileTask>(this, false);
   2334 
   2335   // If --wasm-num-compilation-tasks=0 is passed, do only spawn foreground
   2336   // tasks. This is used to make timing deterministic.
   2337   if (FLAG_wasm_num_compilation_tasks > 0) {
   2338     V8::GetCurrentPlatform()->CallOnWorkerThread(std::move(task));
   2339   } else {
   2340     foreground_task_runner_->PostTask(std::move(task));
   2341   }
   2342 }
   2343 
   2344 template <typename Step, typename... Args>
   2345 void AsyncCompileJob::DoSync(Args&&... args) {
   2346   NextStep<Step>(std::forward<Args>(args)...);
   2347   StartForegroundTask();
   2348 }
   2349 
   2350 template <typename Step, typename... Args>
   2351 void AsyncCompileJob::DoImmediately(Args&&... args) {
   2352   NextStep<Step>(std::forward<Args>(args)...);
   2353   ExecuteForegroundTaskImmediately();
   2354 }
   2355 
   2356 template <typename Step, typename... Args>
   2357 void AsyncCompileJob::DoAsync(Args&&... args) {
   2358   NextStep<Step>(std::forward<Args>(args)...);
   2359   StartBackgroundTask();
   2360 }
   2361 
   2362 template <typename Step, typename... Args>
   2363 void AsyncCompileJob::NextStep(Args&&... args) {
   2364   step_.reset(new Step(std::forward<Args>(args)...));
   2365   step_->job_ = this;
   2366 }
   2367 
   2368 //==========================================================================
   2369 // Step 1: (async) Decode the module.
   2370 //==========================================================================
   2371 class AsyncCompileJob::DecodeModule : public AsyncCompileJob::CompileStep {
   2372  public:
   2373   void RunInBackground() override {
   2374     ModuleResult result;
   2375     {
   2376       DisallowHandleAllocation no_handle;
   2377       DisallowHeapAllocation no_allocation;
   2378       // Decode the module bytes.
   2379       TRACE_COMPILE("(1) Decoding module...\n");
   2380       result =
   2381           DecodeWasmModule(job_->enabled_features_, job_->wire_bytes_.start(),
   2382                            job_->wire_bytes_.end(), false, kWasmOrigin,
   2383                            job_->async_counters().get(),
   2384                            job_->isolate()->wasm_engine()->allocator());
   2385     }
   2386     if (result.failed()) {
   2387       // Decoding failure; reject the promise and clean up.
   2388       job_->DoSync<DecodeFail>(std::move(result));
   2389     } else {
   2390       // Decode passed.
   2391       job_->DoSync<PrepareAndStartCompile>(std::move(result.val), true);
   2392     }
   2393   }
   2394 };
   2395 
   2396 //==========================================================================
   2397 // Step 1b: (sync) Fail decoding the module.
   2398 //==========================================================================
   2399 class AsyncCompileJob::DecodeFail : public CompileStep {
   2400  public:
   2401   explicit DecodeFail(ModuleResult result) : result_(std::move(result)) {}
   2402 
   2403  private:
   2404   ModuleResult result_;
   2405   void RunInForeground() override {
   2406     TRACE_COMPILE("(1b) Decoding failed.\n");
   2407     ErrorThrower thrower(job_->isolate_, "AsyncCompile");
   2408     thrower.CompileFailed("Wasm decoding failed", result_);
   2409     // {job_} is deleted in AsyncCompileFailed, therefore the {return}.
   2410     return job_->AsyncCompileFailed(thrower.Reify());
   2411   }
   2412 };
   2413 
   2414 //==========================================================================
   2415 // Step 2 (sync): Create heap-allocated data and start compile.
   2416 //==========================================================================
   2417 class AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
   2418  public:
   2419   PrepareAndStartCompile(std::shared_ptr<const WasmModule> module,
   2420                          bool start_compilation)
   2421       : module_(module), start_compilation_(start_compilation) {}
   2422 
   2423  private:
   2424   std::shared_ptr<const WasmModule> module_;
   2425   bool start_compilation_;
   2426 
   2427   void RunInForeground() override {
   2428     TRACE_COMPILE("(2) Prepare and start compile...\n");
   2429 
   2430     // Make sure all compilation tasks stopped running. Decoding (async step)
   2431     // is done.
   2432     job_->background_task_manager_.CancelAndWait();
   2433 
   2434     // Embedder usage count for declared shared memories.
   2435     if (module_->has_shared_memory) {
   2436       job_->isolate_->CountUsage(
   2437           v8::Isolate::UseCounterFeature::kWasmSharedMemory);
   2438     }
   2439 
   2440     // Create heap objects for script and module bytes to be stored in the
   2441     // module object. Asm.js is not compiled asynchronously.
   2442     Handle<Script> script = CreateWasmScript(job_->isolate_, job_->wire_bytes_);
   2443     Handle<ByteArray> asm_js_offset_table;
   2444 
   2445     const WasmModule* module = module_.get();
   2446     ModuleEnv env = CreateDefaultModuleEnv(module);
   2447     // TODO(wasm): Improve efficiency of storing module wire bytes. Only store
   2448     // relevant sections, not function bodies
   2449 
   2450     // Create the module object and populate with compiled functions and
   2451     // information needed at instantiation time.
   2452     // TODO(clemensh): For the same module (same bytes / same hash), we should
   2453     // only have one {WasmModuleObject}. Otherwise, we might only set
   2454     // breakpoints on a (potentially empty) subset of the instances.
   2455     // Create the module object.
   2456     job_->module_object_ = WasmModuleObject::New(
   2457         job_->isolate_, job_->enabled_features_, module_, env,
   2458         {std::move(job_->bytes_copy_), job_->wire_bytes_.length()}, script,
   2459         asm_js_offset_table);
   2460     job_->native_module_ = job_->module_object_->native_module();
   2461 
   2462     {
   2463       DeferredHandleScope deferred(job_->isolate_);
   2464       job_->module_object_ = handle(*job_->module_object_, job_->isolate_);
   2465       job_->deferred_handles_.push_back(deferred.Detach());
   2466     }
   2467     size_t num_functions =
   2468         module->functions.size() - module->num_imported_functions;
   2469 
   2470     if (num_functions == 0) {
   2471       // Tiering has nothing to do if module is empty.
   2472       job_->tiering_completed_ = true;
   2473 
   2474       // Degenerate case of an empty module.
   2475       job_->FinishCompile();
   2476       return;
   2477     }
   2478 
   2479     CompilationState* compilation_state =
   2480         job_->native_module_->compilation_state();
   2481     {
   2482       // Instance field {job_} cannot be captured by copy, therefore
   2483       // we need to add a local helper variable {job}. We want to
   2484       // capture the {job} pointer by copy, as it otherwise is dependent
   2485       // on the current step we are in.
   2486       AsyncCompileJob* job = job_;
   2487       compilation_state->SetCallback(
   2488           [job](CompilationEvent event, ErrorThrower* thrower) {
   2489             // Callback is called from a foreground thread.
   2490             switch (event) {
   2491               case CompilationEvent::kFinishedBaselineCompilation:
   2492                 if (job->DecrementAndCheckFinisherCount()) {
   2493                   SaveContext saved_context(job->isolate());
   2494                   job->isolate()->set_context(*job->native_context_);
   2495                   job->FinishCompile();
   2496                 }
   2497                 return;
   2498               case CompilationEvent::kFinishedTopTierCompilation:
   2499                 // If a foreground task or a finisher is pending, we rely on
   2500                 // FinishModule to remove the job.
   2501                 if (job->pending_foreground_task_ ||
   2502                     job->outstanding_finishers_.load() > 0) {
   2503                   job->tiering_completed_ = true;
   2504                   return;
   2505                 }
   2506                 job->isolate_->wasm_engine()->RemoveCompileJob(job);
   2507                 return;
   2508               case CompilationEvent::kFailedCompilation: {
   2509                 // Tier-up compilation should not fail if baseline compilation
   2510                 // did not fail.
   2511                 DCHECK(!job->native_module_->compilation_state()
   2512                             ->baseline_compilation_finished());
   2513 
   2514                 SaveContext saved_context(job->isolate());
   2515                 job->isolate()->set_context(*job->native_context_);
   2516                 Handle<Object> error = thrower->Reify();
   2517 
   2518                 DeferredHandleScope deferred(job->isolate());
   2519                 error = handle(*error, job->isolate());
   2520                 job->deferred_handles_.push_back(deferred.Detach());
   2521                 job->DoSync<CompileFailed>(error);
   2522                 return;
   2523               }
   2524             }
   2525             UNREACHABLE();
   2526           });
   2527     }
   2528     if (start_compilation_) {
   2529       // TODO(ahaas): Try to remove the {start_compilation_} check when
   2530       // streaming decoding is done in the background. If
   2531       // InitializeCompilationUnits always returns 0 for streaming compilation,
   2532       // then DoAsync would do the same as NextStep already.
   2533 
   2534       compilation_state->SetNumberOfFunctionsToCompile(
   2535           module->num_declared_functions);
   2536       // Add compilation units and kick off compilation.
   2537       InitializeCompilationUnits(job_->native_module_);
   2538     }
   2539   }
   2540 };
   2541 
   2542 //==========================================================================
   2543 // Step 4b (sync): Compilation failed. Reject Promise.
   2544 //==========================================================================
   2545 class AsyncCompileJob::CompileFailed : public CompileStep {
   2546  public:
   2547   explicit CompileFailed(Handle<Object> error_reason)
   2548       : error_reason_(error_reason) {}
   2549 
   2550   void RunInForeground() override {
   2551     TRACE_COMPILE("(4b) Compilation Failed...\n");
   2552     return job_->AsyncCompileFailed(error_reason_);
   2553   }
   2554 
   2555  private:
   2556   Handle<Object> error_reason_;
   2557 };
   2558 
   2559 //==========================================================================
   2560 // Step 5 (sync): Compile JS->wasm wrappers.
   2561 //==========================================================================
   2562 class AsyncCompileJob::CompileWrappers : public CompileStep {
   2563   // TODO(wasm): Compile all wrappers here, including the start function wrapper
   2564   // and the wrappers for the function table elements.
   2565   void RunInForeground() override {
   2566     TRACE_COMPILE("(5) Compile wrappers...\n");
   2567     // TODO(6792): No longer needed once WebAssembly code is off heap.
   2568     CodeSpaceMemoryModificationScope modification_scope(job_->isolate_->heap());
   2569     // Compile JS->wasm wrappers for exported functions.
   2570     CompileJsToWasmWrappers(job_->isolate_, job_->module_object_);
   2571     job_->DoSync<FinishModule>();
   2572   }
   2573 };
   2574 
   2575 //==========================================================================
   2576 // Step 6 (sync): Finish the module and resolve the promise.
   2577 //==========================================================================
   2578 class AsyncCompileJob::FinishModule : public CompileStep {
   2579   void RunInForeground() override {
   2580     TRACE_COMPILE("(6) Finish module...\n");
   2581     job_->AsyncCompileSucceeded(job_->module_object_);
   2582 
   2583     size_t num_functions = job_->native_module_->num_functions() -
   2584                            job_->native_module_->num_imported_functions();
   2585     if (job_->native_module_->compilation_state()->compile_mode() ==
   2586             CompileMode::kRegular ||
   2587         num_functions == 0) {
   2588       // If we do not tier up, the async compile job is done here and
   2589       // can be deleted.
   2590       job_->isolate_->wasm_engine()->RemoveCompileJob(job_);
   2591       return;
   2592     }
   2593     // If background tiering compilation finished before we resolved the
   2594     // promise, switch to patching now. Otherwise, patching will be scheduled
   2595     // by a callback.
   2596     DCHECK_EQ(CompileMode::kTiering,
   2597               job_->native_module_->compilation_state()->compile_mode());
   2598     if (job_->tiering_completed_) {
   2599       job_->isolate_->wasm_engine()->RemoveCompileJob(job_);
   2600     }
   2601   }
   2602 };
   2603 
   2604 AsyncStreamingProcessor::AsyncStreamingProcessor(AsyncCompileJob* job)
   2605     : decoder_(job->enabled_features_),
   2606       job_(job),
   2607       compilation_unit_builder_(nullptr) {}
   2608 
   2609 void AsyncStreamingProcessor::FinishAsyncCompileJobWithError(ResultBase error) {
   2610   // Make sure all background tasks stopped executing before we change the state
   2611   // of the AsyncCompileJob to DecodeFail.
   2612   job_->background_task_manager_.CancelAndWait();
   2613 
   2614   // Create a ModuleResult from the result we got as parameter. Since there was
   2615   // no error, we don't have to provide a real wasm module to the ModuleResult.
   2616   ModuleResult result(nullptr);
   2617   result.MoveErrorFrom(error);
   2618 
   2619   // Check if there is already a CompiledModule, in which case we have to clean
   2620   // up the CompilationState as well.
   2621   if (job_->native_module_) {
   2622     job_->native_module_->compilation_state()->Abort();
   2623 
   2624     if (job_->pending_foreground_task_ == nullptr) {
   2625       job_->DoSync<AsyncCompileJob::DecodeFail>(std::move(result));
   2626     } else {
   2627       job_->NextStep<AsyncCompileJob::DecodeFail>(std::move(result));
   2628     }
   2629 
   2630     // Clear the {compilation_unit_builder_} if it exists. This is needed
   2631     // because there is a check in the destructor of the
   2632     // {CompilationUnitBuilder} that it is empty.
   2633     if (compilation_unit_builder_) compilation_unit_builder_->Clear();
   2634   } else {
   2635     job_->DoSync<AsyncCompileJob::DecodeFail>(std::move(result));
   2636   }
   2637 }
   2638 
   2639 // Process the module header.
   2640 bool AsyncStreamingProcessor::ProcessModuleHeader(Vector<const uint8_t> bytes,
   2641                                                   uint32_t offset) {
   2642   TRACE_STREAMING("Process module header...\n");
   2643   decoder_.StartDecoding(job_->async_counters().get(),
   2644                          job_->isolate()->wasm_engine()->allocator());
   2645   decoder_.DecodeModuleHeader(bytes, offset);
   2646   if (!decoder_.ok()) {
   2647     FinishAsyncCompileJobWithError(decoder_.FinishDecoding(false));
   2648     return false;
   2649   }
   2650   return true;
   2651 }
   2652 
   2653 // Process all sections except for the code section.
   2654 bool AsyncStreamingProcessor::ProcessSection(SectionCode section_code,
   2655                                              Vector<const uint8_t> bytes,
   2656                                              uint32_t offset) {
   2657   TRACE_STREAMING("Process section %d ...\n", section_code);
   2658   if (compilation_unit_builder_) {
   2659     // We reached a section after the code section, we do not need the
   2660     // compilation_unit_builder_ anymore.
   2661     CommitCompilationUnits();
   2662     compilation_unit_builder_.reset();
   2663   }
   2664   if (section_code == SectionCode::kUnknownSectionCode) {
   2665     Decoder decoder(bytes, offset);
   2666     section_code = ModuleDecoder::IdentifyUnknownSection(
   2667         decoder, bytes.start() + bytes.length());
   2668     if (section_code == SectionCode::kUnknownSectionCode) {
   2669       // Skip unknown sections that we do not know how to handle.
   2670       return true;
   2671     }
   2672     // Remove the unknown section tag from the payload bytes.
   2673     offset += decoder.position();
   2674     bytes = bytes.SubVector(decoder.position(), bytes.size());
   2675   }
   2676   constexpr bool verify_functions = false;
   2677   decoder_.DecodeSection(section_code, bytes, offset, verify_functions);
   2678   if (!decoder_.ok()) {
   2679     FinishAsyncCompileJobWithError(decoder_.FinishDecoding(false));
   2680     return false;
   2681   }
   2682   return true;
   2683 }
   2684 
   2685 // Start the code section.
   2686 bool AsyncStreamingProcessor::ProcessCodeSectionHeader(size_t functions_count,
   2687                                                        uint32_t offset) {
   2688   TRACE_STREAMING("Start the code section with %zu functions...\n",
   2689                   functions_count);
   2690   if (!decoder_.CheckFunctionsCount(static_cast<uint32_t>(functions_count),
   2691                                     offset)) {
   2692     FinishAsyncCompileJobWithError(decoder_.FinishDecoding(false));
   2693     return false;
   2694   }
   2695   // Execute the PrepareAndStartCompile step immediately and not in a separate
   2696   // task.
   2697   job_->DoImmediately<AsyncCompileJob::PrepareAndStartCompile>(
   2698       decoder_.shared_module(), false);
   2699 
   2700   job_->native_module_->compilation_state()->SetNumberOfFunctionsToCompile(
   2701       functions_count);
   2702 
   2703   // Set outstanding_finishers_ to 2, because both the AsyncCompileJob and the
   2704   // AsyncStreamingProcessor have to finish.
   2705   job_->outstanding_finishers_.store(2);
   2706   compilation_unit_builder_.reset(
   2707       new CompilationUnitBuilder(job_->native_module_));
   2708   return true;
   2709 }
   2710 
   2711 // Process a function body.
   2712 bool AsyncStreamingProcessor::ProcessFunctionBody(Vector<const uint8_t> bytes,
   2713                                                   uint32_t offset) {
   2714   TRACE_STREAMING("Process function body %d ...\n", next_function_);
   2715 
   2716     decoder_.DecodeFunctionBody(
   2717         next_function_, static_cast<uint32_t>(bytes.length()), offset, false);
   2718 
   2719     uint32_t index = next_function_ + decoder_.module()->num_imported_functions;
   2720     const WasmFunction* func = &decoder_.module()->functions[index];
   2721     WasmName name = {nullptr, 0};
   2722     compilation_unit_builder_->AddUnit(func, offset, bytes, name);
   2723   ++next_function_;
   2724   // This method always succeeds. The return value is necessary to comply with
   2725   // the StreamingProcessor interface.
   2726   return true;
   2727 }
   2728 
   2729 void AsyncStreamingProcessor::CommitCompilationUnits() {
   2730   DCHECK(compilation_unit_builder_);
   2731   compilation_unit_builder_->Commit();
   2732 }
   2733 
   2734 void AsyncStreamingProcessor::OnFinishedChunk() {
   2735   TRACE_STREAMING("FinishChunk...\n");
   2736   if (compilation_unit_builder_) CommitCompilationUnits();
   2737 }
   2738 
   2739 // Finish the processing of the stream.
   2740 void AsyncStreamingProcessor::OnFinishedStream(OwnedVector<uint8_t> bytes) {
   2741   TRACE_STREAMING("Finish stream...\n");
   2742   ModuleResult result = decoder_.FinishDecoding(false);
   2743   DCHECK(result.ok());
   2744   bool needs_finish = job_->DecrementAndCheckFinisherCount();
   2745   if (job_->native_module_ == nullptr) {
   2746     // We are processing a WebAssembly module without code section. We need to
   2747     // prepare compilation first before we can finish it.
   2748     // {PrepareAndStartCompile} will call {FinishCompile} by itself if there
   2749     // is no code section.
   2750     DCHECK(needs_finish);
   2751     needs_finish = false;
   2752     job_->DoImmediately<AsyncCompileJob::PrepareAndStartCompile>(result.val,
   2753                                                                  true);
   2754   }
   2755   job_->wire_bytes_ = ModuleWireBytes(bytes.as_vector());
   2756   job_->native_module_->set_wire_bytes(std::move(bytes));
   2757   if (needs_finish) {
   2758     HandleScope scope(job_->isolate_);
   2759     SaveContext saved_context(job_->isolate_);
   2760     job_->isolate_->set_context(*job_->native_context_);
   2761     job_->FinishCompile();
   2762   }
   2763 }
   2764 
   2765 // Report an error detected in the StreamingDecoder.
   2766 void AsyncStreamingProcessor::OnError(DecodeResult result) {
   2767   TRACE_STREAMING("Stream error...\n");
   2768   FinishAsyncCompileJobWithError(std::move(result));
   2769 }
   2770 
   2771 void AsyncStreamingProcessor::OnAbort() {
   2772   TRACE_STREAMING("Abort stream...\n");
   2773   job_->Abort();
   2774 }
   2775 
   2776 void CompilationStateDeleter::operator()(
   2777     CompilationState* compilation_state) const {
   2778   delete compilation_state;
   2779 }
   2780 
   2781 std::unique_ptr<CompilationState, CompilationStateDeleter> NewCompilationState(
   2782     Isolate* isolate, const ModuleEnv& env) {
   2783   return std::unique_ptr<CompilationState, CompilationStateDeleter>(
   2784       new CompilationState(isolate, env));
   2785 }
   2786 
   2787 ModuleEnv* GetModuleEnv(CompilationState* compilation_state) {
   2788   return compilation_state->module_env();
   2789 }
   2790 
   2791 CompilationState::CompilationState(internal::Isolate* isolate,
   2792                                    const ModuleEnv& env)
   2793     : isolate_(isolate),
   2794       wasm_engine_(isolate->wasm_engine()),
   2795       module_env_(env),
   2796       compile_mode_(FLAG_wasm_tier_up && env.module->origin == kWasmOrigin
   2797                         ? CompileMode::kTiering
   2798                         : CompileMode::kRegular),
   2799       max_background_tasks_(std::max(
   2800           1, std::min(FLAG_wasm_num_compilation_tasks,
   2801                       V8::GetCurrentPlatform()->NumberOfWorkerThreads()))) {
   2802   v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate_);
   2803   v8::Platform* platform = V8::GetCurrentPlatform();
   2804   foreground_task_runner_ = platform->GetForegroundTaskRunner(v8_isolate);
   2805 }
   2806 
   2807 CompilationState::~CompilationState() {
   2808   background_task_manager_.CancelAndWait();
   2809   foreground_task_manager_.CancelAndWait();
   2810 }
   2811 
   2812 void CompilationState::SetNumberOfFunctionsToCompile(size_t num_functions) {
   2813   DCHECK(!failed());
   2814   outstanding_units_ = num_functions;
   2815 
   2816   if (compile_mode_ == CompileMode::kTiering) {
   2817     outstanding_units_ += num_functions;
   2818     num_tiering_units_ = num_functions;
   2819   }
   2820 }
   2821 
   2822 void CompilationState::SetCallback(
   2823     std::function<void(CompilationEvent, ErrorThrower*)> callback) {
   2824   DCHECK_NULL(callback_);
   2825   callback_ = callback;
   2826 }
   2827 
   2828 void CompilationState::AddCompilationUnits(
   2829     std::vector<std::unique_ptr<WasmCompilationUnit>>& baseline_units,
   2830     std::vector<std::unique_ptr<WasmCompilationUnit>>& tiering_units) {
   2831   {
   2832     base::LockGuard<base::Mutex> guard(&mutex_);
   2833 
   2834     if (compile_mode_ == CompileMode::kTiering) {
   2835       DCHECK_EQ(baseline_units.size(), tiering_units.size());
   2836       DCHECK_EQ(tiering_units.back()->mode(), ExecutionTier::kOptimized);
   2837       tiering_compilation_units_.insert(
   2838           tiering_compilation_units_.end(),
   2839           std::make_move_iterator(tiering_units.begin()),
   2840           std::make_move_iterator(tiering_units.end()));
   2841     } else {
   2842       DCHECK(tiering_compilation_units_.empty());
   2843     }
   2844 
   2845     baseline_compilation_units_.insert(
   2846         baseline_compilation_units_.end(),
   2847         std::make_move_iterator(baseline_units.begin()),
   2848         std::make_move_iterator(baseline_units.end()));
   2849   }
   2850 
   2851   RestartBackgroundTasks();
   2852 }
   2853 
   2854 std::unique_ptr<WasmCompilationUnit>
   2855 CompilationState::GetNextCompilationUnit() {
   2856   base::LockGuard<base::Mutex> guard(&mutex_);
   2857 
   2858   std::vector<std::unique_ptr<WasmCompilationUnit>>& units =
   2859       baseline_compilation_units_.empty() ? tiering_compilation_units_
   2860                                           : baseline_compilation_units_;
   2861 
   2862   if (!units.empty()) {
   2863     std::unique_ptr<WasmCompilationUnit> unit = std::move(units.back());
   2864     units.pop_back();
   2865     return unit;
   2866   }
   2867 
   2868   return std::unique_ptr<WasmCompilationUnit>();
   2869 }
   2870 
   2871 std::unique_ptr<WasmCompilationUnit> CompilationState::GetNextExecutedUnit() {
   2872   base::LockGuard<base::Mutex> guard(&mutex_);
   2873   std::vector<std::unique_ptr<WasmCompilationUnit>>& units = finish_units();
   2874   if (units.empty()) return {};
   2875   std::unique_ptr<WasmCompilationUnit> ret = std::move(units.back());
   2876   units.pop_back();
   2877   return ret;
   2878 }
   2879 
   2880 bool CompilationState::HasCompilationUnitToFinish() {
   2881   base::LockGuard<base::Mutex> guard(&mutex_);
   2882   return !finish_units().empty();
   2883 }
   2884 
   2885 void CompilationState::OnError(ErrorThrower* thrower) {
   2886   Abort();
   2887   DCHECK(thrower->error());
   2888   NotifyOnEvent(CompilationEvent::kFailedCompilation, thrower);
   2889 }
   2890 
   2891 void CompilationState::OnFinishedUnit() {
   2892   DCHECK_GT(outstanding_units_, 0);
   2893   --outstanding_units_;
   2894 
   2895   if (outstanding_units_ == 0) {
   2896     background_task_manager_.CancelAndWait();
   2897     baseline_compilation_finished_ = true;
   2898 
   2899     DCHECK(compile_mode_ == CompileMode::kRegular ||
   2900            compile_mode_ == CompileMode::kTiering);
   2901     NotifyOnEvent(compile_mode_ == CompileMode::kRegular
   2902                       ? CompilationEvent::kFinishedBaselineCompilation
   2903                       : CompilationEvent::kFinishedTopTierCompilation,
   2904                   nullptr);
   2905 
   2906   } else if (outstanding_units_ == num_tiering_units_) {
   2907     DCHECK_EQ(compile_mode_, CompileMode::kTiering);
   2908     baseline_compilation_finished_ = true;
   2909 
   2910     // TODO(wasm): For streaming compilation, we want to start top tier
   2911     // compilation before all functions have been compiled with Liftoff, e.g.
   2912     // in the case when all received functions have been compiled with Liftoff
   2913     // and we are waiting for new functions to compile.
   2914 
   2915     // If we are in {kRegular} mode, {num_tiering_units_} is 0, therefore
   2916     // this case is already caught by the previous check.
   2917     NotifyOnEvent(CompilationEvent::kFinishedBaselineCompilation, nullptr);
   2918     RestartBackgroundTasks();
   2919   }
   2920 }
   2921 
   2922 void CompilationState::ScheduleUnitForFinishing(
   2923     std::unique_ptr<WasmCompilationUnit> unit, ExecutionTier mode) {
   2924   base::LockGuard<base::Mutex> guard(&mutex_);
   2925   if (compile_mode_ == CompileMode::kTiering &&
   2926       mode == ExecutionTier::kOptimized) {
   2927     tiering_finish_units_.push_back(std::move(unit));
   2928   } else {
   2929     baseline_finish_units_.push_back(std::move(unit));
   2930   }
   2931 
   2932   if (!finisher_is_running_ && !failed_) {
   2933     ScheduleFinisherTask();
   2934     // We set the flag here so that not more than one finisher is started.
   2935     finisher_is_running_ = true;
   2936   }
   2937 }
   2938 
   2939 void CompilationState::OnBackgroundTaskStopped(const WasmFeatures& detected) {
   2940   base::LockGuard<base::Mutex> guard(&mutex_);
   2941   DCHECK_LE(1, num_background_tasks_);
   2942   --num_background_tasks_;
   2943   UnionFeaturesInto(&detected_features_, detected);
   2944 }
   2945 
   2946 void CompilationState::PublishDetectedFeatures(Isolate* isolate,
   2947                                                const WasmFeatures& detected) {
   2948   // Notifying the isolate of the feature counts must take place under
   2949   // the mutex, because even if we have finished baseline compilation,
   2950   // tiering compilations may still occur in the background.
   2951   base::LockGuard<base::Mutex> guard(&mutex_);
   2952   UnionFeaturesInto(&detected_features_, detected);
   2953   UpdateFeatureUseCounts(isolate, detected_features_);
   2954 }
   2955 
   2956 void CompilationState::RestartBackgroundTasks(size_t max) {
   2957   size_t num_restart;
   2958   {
   2959     base::LockGuard<base::Mutex> guard(&mutex_);
   2960     // No need to restart tasks if compilation already failed.
   2961     if (failed_) return;
   2962 
   2963     DCHECK_LE(num_background_tasks_, max_background_tasks_);
   2964     if (num_background_tasks_ == max_background_tasks_) return;
   2965     size_t num_compilation_units =
   2966         baseline_compilation_units_.size() + tiering_compilation_units_.size();
   2967     size_t stopped_tasks = max_background_tasks_ - num_background_tasks_;
   2968     num_restart = std::min(max, std::min(num_compilation_units, stopped_tasks));
   2969     num_background_tasks_ += num_restart;
   2970   }
   2971 
   2972   for (; num_restart > 0; --num_restart) {
   2973     auto task = base::make_unique<BackgroundCompileTask>(
   2974         this, &background_task_manager_);
   2975 
   2976     // If --wasm-num-compilation-tasks=0 is passed, do only spawn foreground
   2977     // tasks. This is used to make timing deterministic.
   2978     if (FLAG_wasm_num_compilation_tasks > 0) {
   2979       V8::GetCurrentPlatform()->CallOnWorkerThread(std::move(task));
   2980     } else {
   2981       foreground_task_runner_->PostTask(std::move(task));
   2982     }
   2983   }
   2984 }
   2985 
   2986 bool CompilationState::SetFinisherIsRunning(bool value) {
   2987   base::LockGuard<base::Mutex> guard(&mutex_);
   2988   if (finisher_is_running_ == value) return false;
   2989   finisher_is_running_ = value;
   2990   return true;
   2991 }
   2992 
   2993 void CompilationState::ScheduleFinisherTask() {
   2994   foreground_task_runner_->PostTask(
   2995       base::make_unique<FinishCompileTask>(this, &foreground_task_manager_));
   2996 }
   2997 
   2998 void CompilationState::Abort() {
   2999   {
   3000     base::LockGuard<base::Mutex> guard(&mutex_);
   3001     failed_ = true;
   3002   }
   3003   background_task_manager_.CancelAndWait();
   3004 }
   3005 
   3006 void CompilationState::NotifyOnEvent(CompilationEvent event,
   3007                                      ErrorThrower* thrower) {
   3008   if (callback_) callback_(event, thrower);
   3009 }
   3010 
   3011 void CompileJsToWasmWrappers(Isolate* isolate,
   3012                              Handle<WasmModuleObject> module_object) {
   3013   JSToWasmWrapperCache js_to_wasm_cache;
   3014   int wrapper_index = 0;
   3015   Handle<FixedArray> export_wrappers(module_object->export_wrappers(), isolate);
   3016   NativeModule* native_module = module_object->native_module();
   3017   UseTrapHandler use_trap_handler =
   3018       native_module->use_trap_handler() ? kUseTrapHandler : kNoTrapHandler;
   3019   const WasmModule* module = native_module->module();
   3020   for (auto exp : module->export_table) {
   3021     if (exp.kind != kExternalFunction) continue;
   3022     Handle<Code> wrapper_code = js_to_wasm_cache.GetOrCompileJSToWasmWrapper(
   3023         isolate, native_module, exp.index, use_trap_handler);
   3024     export_wrappers->set(wrapper_index, *wrapper_code);
   3025     RecordStats(*wrapper_code, isolate->counters());
   3026     ++wrapper_index;
   3027   }
   3028 }
   3029 
   3030 Handle<Script> CreateWasmScript(Isolate* isolate,
   3031                                 const ModuleWireBytes& wire_bytes) {
   3032   Handle<Script> script =
   3033       isolate->factory()->NewScript(isolate->factory()->empty_string());
   3034   script->set_context_data(isolate->native_context()->debug_context_id());
   3035   script->set_type(Script::TYPE_WASM);
   3036 
   3037   int hash = StringHasher::HashSequentialString(
   3038       reinterpret_cast<const char*>(wire_bytes.start()),
   3039       static_cast<int>(wire_bytes.length()), kZeroHashSeed);
   3040 
   3041   const int kBufferSize = 32;
   3042   char buffer[kBufferSize];
   3043   int url_chars = SNPrintF(ArrayVector(buffer), "wasm://wasm/%08x", hash);
   3044   DCHECK(url_chars >= 0 && url_chars < kBufferSize);
   3045   MaybeHandle<String> url_str = isolate->factory()->NewStringFromOneByte(
   3046       Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), url_chars),
   3047       TENURED);
   3048   script->set_source_url(*url_str.ToHandleChecked());
   3049 
   3050   int name_chars = SNPrintF(ArrayVector(buffer), "wasm-%08x", hash);
   3051   DCHECK(name_chars >= 0 && name_chars < kBufferSize);
   3052   MaybeHandle<String> name_str = isolate->factory()->NewStringFromOneByte(
   3053       Vector<const uint8_t>(reinterpret_cast<uint8_t*>(buffer), name_chars),
   3054       TENURED);
   3055   script->set_name(*name_str.ToHandleChecked());
   3056 
   3057   return script;
   3058 }
   3059 
   3060 }  // namespace wasm
   3061 }  // namespace internal
   3062 }  // namespace v8
   3063 
   3064 #undef TRACE
   3065 #undef TRACE_COMPILE
   3066 #undef TRACE_STREAMING
   3067 #undef TRACE_LAZY
   3068