11cb0ef41Sopenharmony_ci// Copyright 2017 the V8 project authors. All rights reserved.
21cb0ef41Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be
31cb0ef41Sopenharmony_ci// found in the LICENSE file.
41cb0ef41Sopenharmony_ci
51cb0ef41Sopenharmony_ci#include "src/wasm/module-compiler.h"
61cb0ef41Sopenharmony_ci
71cb0ef41Sopenharmony_ci#include <algorithm>
81cb0ef41Sopenharmony_ci#include <queue>
91cb0ef41Sopenharmony_ci
101cb0ef41Sopenharmony_ci#include "src/api/api-inl.h"
111cb0ef41Sopenharmony_ci#include "src/asmjs/asm-js.h"
121cb0ef41Sopenharmony_ci#include "src/base/enum-set.h"
131cb0ef41Sopenharmony_ci#include "src/base/optional.h"
141cb0ef41Sopenharmony_ci#include "src/base/platform/mutex.h"
151cb0ef41Sopenharmony_ci#include "src/base/platform/semaphore.h"
161cb0ef41Sopenharmony_ci#include "src/base/platform/time.h"
171cb0ef41Sopenharmony_ci#include "src/base/utils/random-number-generator.h"
181cb0ef41Sopenharmony_ci#include "src/compiler/wasm-compiler.h"
191cb0ef41Sopenharmony_ci#include "src/handles/global-handles-inl.h"
201cb0ef41Sopenharmony_ci#include "src/heap/heap-inl.h"  // For CodePageCollectionMemoryModificationScope.
211cb0ef41Sopenharmony_ci#include "src/logging/counters-scopes.h"
221cb0ef41Sopenharmony_ci#include "src/logging/metrics.h"
231cb0ef41Sopenharmony_ci#include "src/objects/property-descriptor.h"
241cb0ef41Sopenharmony_ci#include "src/tasks/task-utils.h"
251cb0ef41Sopenharmony_ci#include "src/tracing/trace-event.h"
261cb0ef41Sopenharmony_ci#include "src/trap-handler/trap-handler.h"
271cb0ef41Sopenharmony_ci#include "src/utils/identity-map.h"
281cb0ef41Sopenharmony_ci#include "src/wasm/code-space-access.h"
291cb0ef41Sopenharmony_ci#include "src/wasm/module-decoder.h"
301cb0ef41Sopenharmony_ci#include "src/wasm/streaming-decoder.h"
311cb0ef41Sopenharmony_ci#include "src/wasm/wasm-code-manager.h"
321cb0ef41Sopenharmony_ci#include "src/wasm/wasm-engine.h"
331cb0ef41Sopenharmony_ci#include "src/wasm/wasm-import-wrapper-cache.h"
341cb0ef41Sopenharmony_ci#include "src/wasm/wasm-js.h"
351cb0ef41Sopenharmony_ci#include "src/wasm/wasm-limits.h"
361cb0ef41Sopenharmony_ci#include "src/wasm/wasm-objects-inl.h"
371cb0ef41Sopenharmony_ci#include "src/wasm/wasm-result.h"
381cb0ef41Sopenharmony_ci#include "src/wasm/wasm-serialization.h"
391cb0ef41Sopenharmony_ci
401cb0ef41Sopenharmony_ci#define TRACE_COMPILE(...)                             \
411cb0ef41Sopenharmony_ci  do {                                                 \
421cb0ef41Sopenharmony_ci    if (FLAG_trace_wasm_compiler) PrintF(__VA_ARGS__); \
431cb0ef41Sopenharmony_ci  } while (false)
441cb0ef41Sopenharmony_ci
451cb0ef41Sopenharmony_ci#define TRACE_STREAMING(...)                            \
461cb0ef41Sopenharmony_ci  do {                                                  \
471cb0ef41Sopenharmony_ci    if (FLAG_trace_wasm_streaming) PrintF(__VA_ARGS__); \
481cb0ef41Sopenharmony_ci  } while (false)
491cb0ef41Sopenharmony_ci
501cb0ef41Sopenharmony_ci#define TRACE_LAZY(...)                                        \
511cb0ef41Sopenharmony_ci  do {                                                         \
521cb0ef41Sopenharmony_ci    if (FLAG_trace_wasm_lazy_compilation) PrintF(__VA_ARGS__); \
531cb0ef41Sopenharmony_ci  } while (false)
541cb0ef41Sopenharmony_ci
551cb0ef41Sopenharmony_cinamespace v8 {
561cb0ef41Sopenharmony_cinamespace internal {
571cb0ef41Sopenharmony_cinamespace wasm {
581cb0ef41Sopenharmony_ci
591cb0ef41Sopenharmony_cinamespace {
601cb0ef41Sopenharmony_ci
611cb0ef41Sopenharmony_cienum class CompileStrategy : uint8_t {
621cb0ef41Sopenharmony_ci  // Compiles functions on first use. In this case, execution will block until
631cb0ef41Sopenharmony_ci  // the function's baseline is reached and top tier compilation starts in
641cb0ef41Sopenharmony_ci  // background (if applicable).
651cb0ef41Sopenharmony_ci  // Lazy compilation can help to reduce startup time and code size at the risk
661cb0ef41Sopenharmony_ci  // of blocking execution.
671cb0ef41Sopenharmony_ci  kLazy,
681cb0ef41Sopenharmony_ci  // Compiles baseline ahead of execution and starts top tier compilation in
691cb0ef41Sopenharmony_ci  // background (if applicable).
701cb0ef41Sopenharmony_ci  kEager,
711cb0ef41Sopenharmony_ci  // Triggers baseline compilation on first use (just like {kLazy}) with the
721cb0ef41Sopenharmony_ci  // difference that top tier compilation is started eagerly.
731cb0ef41Sopenharmony_ci  // This strategy can help to reduce startup time at the risk of blocking
741cb0ef41Sopenharmony_ci  // execution, but only in its early phase (until top tier compilation
751cb0ef41Sopenharmony_ci  // finishes).
761cb0ef41Sopenharmony_ci  kLazyBaselineEagerTopTier,
771cb0ef41Sopenharmony_ci  // Marker for default strategy.
781cb0ef41Sopenharmony_ci  kDefault = kEager,
791cb0ef41Sopenharmony_ci};
801cb0ef41Sopenharmony_ci
811cb0ef41Sopenharmony_ciclass CompilationStateImpl;
821cb0ef41Sopenharmony_ciclass CompilationUnitBuilder;
831cb0ef41Sopenharmony_ci
841cb0ef41Sopenharmony_ciclass V8_NODISCARD BackgroundCompileScope {
851cb0ef41Sopenharmony_ci public:
861cb0ef41Sopenharmony_ci  explicit BackgroundCompileScope(std::weak_ptr<NativeModule> native_module)
871cb0ef41Sopenharmony_ci      : native_module_(native_module.lock()) {}
881cb0ef41Sopenharmony_ci
891cb0ef41Sopenharmony_ci  NativeModule* native_module() const {
901cb0ef41Sopenharmony_ci    DCHECK(native_module_);
911cb0ef41Sopenharmony_ci    return native_module_.get();
921cb0ef41Sopenharmony_ci  }
931cb0ef41Sopenharmony_ci  inline CompilationStateImpl* compilation_state() const;
941cb0ef41Sopenharmony_ci
951cb0ef41Sopenharmony_ci  bool cancelled() const;
961cb0ef41Sopenharmony_ci
971cb0ef41Sopenharmony_ci private:
981cb0ef41Sopenharmony_ci  // Keep the native module alive while in this scope.
991cb0ef41Sopenharmony_ci  std::shared_ptr<NativeModule> native_module_;
1001cb0ef41Sopenharmony_ci};
1011cb0ef41Sopenharmony_ci
1021cb0ef41Sopenharmony_cienum CompileBaselineOnly : bool {
1031cb0ef41Sopenharmony_ci  kBaselineOnly = true,
1041cb0ef41Sopenharmony_ci  kBaselineOrTopTier = false
1051cb0ef41Sopenharmony_ci};
1061cb0ef41Sopenharmony_ci
1071cb0ef41Sopenharmony_ci// A set of work-stealing queues (vectors of units). Each background compile
1081cb0ef41Sopenharmony_ci// task owns one of the queues and steals from all others once its own queue
1091cb0ef41Sopenharmony_ci// runs empty.
1101cb0ef41Sopenharmony_ciclass CompilationUnitQueues {
1111cb0ef41Sopenharmony_ci public:
1121cb0ef41Sopenharmony_ci  // Public API for QueueImpl.
1131cb0ef41Sopenharmony_ci  struct Queue {
1141cb0ef41Sopenharmony_ci    bool ShouldPublish(int num_processed_units) const;
1151cb0ef41Sopenharmony_ci  };
1161cb0ef41Sopenharmony_ci
1171cb0ef41Sopenharmony_ci  explicit CompilationUnitQueues(int num_declared_functions)
1181cb0ef41Sopenharmony_ci      : num_declared_functions_(num_declared_functions) {
1191cb0ef41Sopenharmony_ci    // Add one first queue, to add units to.
1201cb0ef41Sopenharmony_ci    queues_.emplace_back(std::make_unique<QueueImpl>(0));
1211cb0ef41Sopenharmony_ci
1221cb0ef41Sopenharmony_ci    for (auto& atomic_counter : num_units_) {
1231cb0ef41Sopenharmony_ci      std::atomic_init(&atomic_counter, size_t{0});
1241cb0ef41Sopenharmony_ci    }
1251cb0ef41Sopenharmony_ci
1261cb0ef41Sopenharmony_ci    top_tier_compiled_ =
1271cb0ef41Sopenharmony_ci        std::make_unique<std::atomic<bool>[]>(num_declared_functions);
1281cb0ef41Sopenharmony_ci
1291cb0ef41Sopenharmony_ci    for (int i = 0; i < num_declared_functions; i++) {
1301cb0ef41Sopenharmony_ci      std::atomic_init(&top_tier_compiled_.get()[i], false);
1311cb0ef41Sopenharmony_ci    }
1321cb0ef41Sopenharmony_ci  }
1331cb0ef41Sopenharmony_ci
1341cb0ef41Sopenharmony_ci  Queue* GetQueueForTask(int task_id) {
1351cb0ef41Sopenharmony_ci    int required_queues = task_id + 1;
1361cb0ef41Sopenharmony_ci    {
1371cb0ef41Sopenharmony_ci      base::SharedMutexGuard<base::kShared> queues_guard(&queues_mutex_);
1381cb0ef41Sopenharmony_ci      if (V8_LIKELY(static_cast<int>(queues_.size()) >= required_queues)) {
1391cb0ef41Sopenharmony_ci        return queues_[task_id].get();
1401cb0ef41Sopenharmony_ci      }
1411cb0ef41Sopenharmony_ci    }
1421cb0ef41Sopenharmony_ci
1431cb0ef41Sopenharmony_ci    // Otherwise increase the number of queues.
1441cb0ef41Sopenharmony_ci    base::SharedMutexGuard<base::kExclusive> queues_guard(&queues_mutex_);
1451cb0ef41Sopenharmony_ci    int num_queues = static_cast<int>(queues_.size());
1461cb0ef41Sopenharmony_ci    while (num_queues < required_queues) {
1471cb0ef41Sopenharmony_ci      int steal_from = num_queues + 1;
1481cb0ef41Sopenharmony_ci      queues_.emplace_back(std::make_unique<QueueImpl>(steal_from));
1491cb0ef41Sopenharmony_ci      ++num_queues;
1501cb0ef41Sopenharmony_ci    }
1511cb0ef41Sopenharmony_ci
1521cb0ef41Sopenharmony_ci    // Update the {publish_limit}s of all queues.
1531cb0ef41Sopenharmony_ci
1541cb0ef41Sopenharmony_ci    // We want background threads to publish regularly (to avoid contention when
1551cb0ef41Sopenharmony_ci    // they are all publishing at the end). On the other side, each publishing
1561cb0ef41Sopenharmony_ci    // has some overhead (part of it for synchronizing between threads), so it
1571cb0ef41Sopenharmony_ci    // should not happen *too* often. Thus aim for 4-8 publishes per thread, but
1581cb0ef41Sopenharmony_ci    // distribute it such that publishing is likely to happen at different
1591cb0ef41Sopenharmony_ci    // times.
1601cb0ef41Sopenharmony_ci    int units_per_thread = num_declared_functions_ / num_queues;
1611cb0ef41Sopenharmony_ci    int min = std::max(10, units_per_thread / 8);
1621cb0ef41Sopenharmony_ci    int queue_id = 0;
1631cb0ef41Sopenharmony_ci    for (auto& queue : queues_) {
1641cb0ef41Sopenharmony_ci      // Set a limit between {min} and {2*min}, but not smaller than {10}.
1651cb0ef41Sopenharmony_ci      int limit = min + (min * queue_id / num_queues);
1661cb0ef41Sopenharmony_ci      queue->publish_limit.store(limit, std::memory_order_relaxed);
1671cb0ef41Sopenharmony_ci      ++queue_id;
1681cb0ef41Sopenharmony_ci    }
1691cb0ef41Sopenharmony_ci
1701cb0ef41Sopenharmony_ci    return queues_[task_id].get();
1711cb0ef41Sopenharmony_ci  }
1721cb0ef41Sopenharmony_ci
1731cb0ef41Sopenharmony_ci  base::Optional<WasmCompilationUnit> GetNextUnit(
1741cb0ef41Sopenharmony_ci      Queue* queue, CompileBaselineOnly baseline_only) {
1751cb0ef41Sopenharmony_ci    // As long as any lower-tier units are outstanding we need to steal them
1761cb0ef41Sopenharmony_ci    // before executing own higher-tier units.
1771cb0ef41Sopenharmony_ci    int max_tier = baseline_only ? kBaseline : kTopTier;
1781cb0ef41Sopenharmony_ci    for (int tier = GetLowestTierWithUnits(); tier <= max_tier; ++tier) {
1791cb0ef41Sopenharmony_ci      if (auto unit = GetNextUnitOfTier(queue, tier)) {
1801cb0ef41Sopenharmony_ci        size_t old_units_count =
1811cb0ef41Sopenharmony_ci            num_units_[tier].fetch_sub(1, std::memory_order_relaxed);
1821cb0ef41Sopenharmony_ci        DCHECK_LE(1, old_units_count);
1831cb0ef41Sopenharmony_ci        USE(old_units_count);
1841cb0ef41Sopenharmony_ci        return unit;
1851cb0ef41Sopenharmony_ci      }
1861cb0ef41Sopenharmony_ci    }
1871cb0ef41Sopenharmony_ci    return {};
1881cb0ef41Sopenharmony_ci  }
1891cb0ef41Sopenharmony_ci
1901cb0ef41Sopenharmony_ci  void AddUnits(base::Vector<WasmCompilationUnit> baseline_units,
1911cb0ef41Sopenharmony_ci                base::Vector<WasmCompilationUnit> top_tier_units,
1921cb0ef41Sopenharmony_ci                const WasmModule* module) {
1931cb0ef41Sopenharmony_ci    DCHECK_LT(0, baseline_units.size() + top_tier_units.size());
1941cb0ef41Sopenharmony_ci    // Add to the individual queues in a round-robin fashion. No special care is
1951cb0ef41Sopenharmony_ci    // taken to balance them; they will be balanced by work stealing.
1961cb0ef41Sopenharmony_ci    QueueImpl* queue;
1971cb0ef41Sopenharmony_ci    {
1981cb0ef41Sopenharmony_ci      int queue_to_add = next_queue_to_add.load(std::memory_order_relaxed);
1991cb0ef41Sopenharmony_ci      base::SharedMutexGuard<base::kShared> queues_guard(&queues_mutex_);
2001cb0ef41Sopenharmony_ci      while (!next_queue_to_add.compare_exchange_weak(
2011cb0ef41Sopenharmony_ci          queue_to_add, next_task_id(queue_to_add, queues_.size()),
2021cb0ef41Sopenharmony_ci          std::memory_order_relaxed)) {
2031cb0ef41Sopenharmony_ci        // Retry with updated {queue_to_add}.
2041cb0ef41Sopenharmony_ci      }
2051cb0ef41Sopenharmony_ci      queue = queues_[queue_to_add].get();
2061cb0ef41Sopenharmony_ci    }
2071cb0ef41Sopenharmony_ci
2081cb0ef41Sopenharmony_ci    base::MutexGuard guard(&queue->mutex);
2091cb0ef41Sopenharmony_ci    base::Optional<base::MutexGuard> big_units_guard;
2101cb0ef41Sopenharmony_ci    for (auto pair : {std::make_pair(int{kBaseline}, baseline_units),
2111cb0ef41Sopenharmony_ci                      std::make_pair(int{kTopTier}, top_tier_units)}) {
2121cb0ef41Sopenharmony_ci      int tier = pair.first;
2131cb0ef41Sopenharmony_ci      base::Vector<WasmCompilationUnit> units = pair.second;
2141cb0ef41Sopenharmony_ci      if (units.empty()) continue;
2151cb0ef41Sopenharmony_ci      num_units_[tier].fetch_add(units.size(), std::memory_order_relaxed);
2161cb0ef41Sopenharmony_ci      for (WasmCompilationUnit unit : units) {
2171cb0ef41Sopenharmony_ci        size_t func_size = module->functions[unit.func_index()].code.length();
2181cb0ef41Sopenharmony_ci        if (func_size <= kBigUnitsLimit) {
2191cb0ef41Sopenharmony_ci          queue->units[tier].push_back(unit);
2201cb0ef41Sopenharmony_ci        } else {
2211cb0ef41Sopenharmony_ci          if (!big_units_guard) {
2221cb0ef41Sopenharmony_ci            big_units_guard.emplace(&big_units_queue_.mutex);
2231cb0ef41Sopenharmony_ci          }
2241cb0ef41Sopenharmony_ci          big_units_queue_.has_units[tier].store(true,
2251cb0ef41Sopenharmony_ci                                                 std::memory_order_relaxed);
2261cb0ef41Sopenharmony_ci          big_units_queue_.units[tier].emplace(func_size, unit);
2271cb0ef41Sopenharmony_ci        }
2281cb0ef41Sopenharmony_ci      }
2291cb0ef41Sopenharmony_ci    }
2301cb0ef41Sopenharmony_ci  }
2311cb0ef41Sopenharmony_ci
2321cb0ef41Sopenharmony_ci  void AddTopTierPriorityUnit(WasmCompilationUnit unit, size_t priority) {
2331cb0ef41Sopenharmony_ci    base::SharedMutexGuard<base::kShared> queues_guard(&queues_mutex_);
2341cb0ef41Sopenharmony_ci    // Add to the individual queues in a round-robin fashion. No special care is
2351cb0ef41Sopenharmony_ci    // taken to balance them; they will be balanced by work stealing. We use
2361cb0ef41Sopenharmony_ci    // the same counter for this reason.
2371cb0ef41Sopenharmony_ci    int queue_to_add = next_queue_to_add.load(std::memory_order_relaxed);
2381cb0ef41Sopenharmony_ci    while (!next_queue_to_add.compare_exchange_weak(
2391cb0ef41Sopenharmony_ci        queue_to_add, next_task_id(queue_to_add, queues_.size()),
2401cb0ef41Sopenharmony_ci        std::memory_order_relaxed)) {
2411cb0ef41Sopenharmony_ci      // Retry with updated {queue_to_add}.
2421cb0ef41Sopenharmony_ci    }
2431cb0ef41Sopenharmony_ci
2441cb0ef41Sopenharmony_ci    {
2451cb0ef41Sopenharmony_ci      auto* queue = queues_[queue_to_add].get();
2461cb0ef41Sopenharmony_ci      base::MutexGuard guard(&queue->mutex);
2471cb0ef41Sopenharmony_ci      queue->top_tier_priority_units.emplace(priority, unit);
2481cb0ef41Sopenharmony_ci    }
2491cb0ef41Sopenharmony_ci    num_priority_units_.fetch_add(1, std::memory_order_relaxed);
2501cb0ef41Sopenharmony_ci    num_units_[kTopTier].fetch_add(1, std::memory_order_relaxed);
2511cb0ef41Sopenharmony_ci  }
2521cb0ef41Sopenharmony_ci
2531cb0ef41Sopenharmony_ci  // Get the current total number of units in all queues. This is only a
2541cb0ef41Sopenharmony_ci  // momentary snapshot, it's not guaranteed that {GetNextUnit} returns a unit
2551cb0ef41Sopenharmony_ci  // if this method returns non-zero.
2561cb0ef41Sopenharmony_ci  size_t GetTotalSize() const {
2571cb0ef41Sopenharmony_ci    size_t total = 0;
2581cb0ef41Sopenharmony_ci    for (auto& atomic_counter : num_units_) {
2591cb0ef41Sopenharmony_ci      total += atomic_counter.load(std::memory_order_relaxed);
2601cb0ef41Sopenharmony_ci    }
2611cb0ef41Sopenharmony_ci    return total;
2621cb0ef41Sopenharmony_ci  }
2631cb0ef41Sopenharmony_ci
2641cb0ef41Sopenharmony_ci private:
2651cb0ef41Sopenharmony_ci  // Store tier in int so we can easily loop over it:
2661cb0ef41Sopenharmony_ci  static constexpr int kBaseline = 0;
2671cb0ef41Sopenharmony_ci  static constexpr int kTopTier = 1;
2681cb0ef41Sopenharmony_ci  static constexpr int kNumTiers = kTopTier + 1;
2691cb0ef41Sopenharmony_ci
2701cb0ef41Sopenharmony_ci  // Functions bigger than {kBigUnitsLimit} will be compiled first, in ascending
2711cb0ef41Sopenharmony_ci  // order of their function body size.
2721cb0ef41Sopenharmony_ci  static constexpr size_t kBigUnitsLimit = 4096;
2731cb0ef41Sopenharmony_ci
2741cb0ef41Sopenharmony_ci  struct BigUnit {
2751cb0ef41Sopenharmony_ci    BigUnit(size_t func_size, WasmCompilationUnit unit)
2761cb0ef41Sopenharmony_ci        : func_size{func_size}, unit(unit) {}
2771cb0ef41Sopenharmony_ci
2781cb0ef41Sopenharmony_ci    size_t func_size;
2791cb0ef41Sopenharmony_ci    WasmCompilationUnit unit;
2801cb0ef41Sopenharmony_ci
2811cb0ef41Sopenharmony_ci    bool operator<(const BigUnit& other) const {
2821cb0ef41Sopenharmony_ci      return func_size < other.func_size;
2831cb0ef41Sopenharmony_ci    }
2841cb0ef41Sopenharmony_ci  };
2851cb0ef41Sopenharmony_ci
2861cb0ef41Sopenharmony_ci  struct TopTierPriorityUnit {
2871cb0ef41Sopenharmony_ci    TopTierPriorityUnit(int priority, WasmCompilationUnit unit)
2881cb0ef41Sopenharmony_ci        : priority(priority), unit(unit) {}
2891cb0ef41Sopenharmony_ci
2901cb0ef41Sopenharmony_ci    size_t priority;
2911cb0ef41Sopenharmony_ci    WasmCompilationUnit unit;
2921cb0ef41Sopenharmony_ci
2931cb0ef41Sopenharmony_ci    bool operator<(const TopTierPriorityUnit& other) const {
2941cb0ef41Sopenharmony_ci      return priority < other.priority;
2951cb0ef41Sopenharmony_ci    }
2961cb0ef41Sopenharmony_ci  };
2971cb0ef41Sopenharmony_ci
2981cb0ef41Sopenharmony_ci  struct BigUnitsQueue {
2991cb0ef41Sopenharmony_ci    BigUnitsQueue() {
3001cb0ef41Sopenharmony_ci      for (auto& atomic : has_units) std::atomic_init(&atomic, false);
3011cb0ef41Sopenharmony_ci    }
3021cb0ef41Sopenharmony_ci
3031cb0ef41Sopenharmony_ci    base::Mutex mutex;
3041cb0ef41Sopenharmony_ci
3051cb0ef41Sopenharmony_ci    // Can be read concurrently to check whether any elements are in the queue.
3061cb0ef41Sopenharmony_ci    std::atomic<bool> has_units[kNumTiers];
3071cb0ef41Sopenharmony_ci
3081cb0ef41Sopenharmony_ci    // Protected by {mutex}:
3091cb0ef41Sopenharmony_ci    std::priority_queue<BigUnit> units[kNumTiers];
3101cb0ef41Sopenharmony_ci  };
3111cb0ef41Sopenharmony_ci
3121cb0ef41Sopenharmony_ci  struct QueueImpl : public Queue {
3131cb0ef41Sopenharmony_ci    explicit QueueImpl(int next_steal_task_id)
3141cb0ef41Sopenharmony_ci        : next_steal_task_id(next_steal_task_id) {}
3151cb0ef41Sopenharmony_ci
3161cb0ef41Sopenharmony_ci    // Number of units after which the task processing this queue should publish
3171cb0ef41Sopenharmony_ci    // compilation results. Updated (reduced, using relaxed ordering) when new
3181cb0ef41Sopenharmony_ci    // queues are allocated. If there is only one thread running, we can delay
3191cb0ef41Sopenharmony_ci    // publishing arbitrarily.
3201cb0ef41Sopenharmony_ci    std::atomic<int> publish_limit{kMaxInt};
3211cb0ef41Sopenharmony_ci
3221cb0ef41Sopenharmony_ci    base::Mutex mutex;
3231cb0ef41Sopenharmony_ci
3241cb0ef41Sopenharmony_ci    // All fields below are protected by {mutex}.
3251cb0ef41Sopenharmony_ci    std::vector<WasmCompilationUnit> units[kNumTiers];
3261cb0ef41Sopenharmony_ci    std::priority_queue<TopTierPriorityUnit> top_tier_priority_units;
3271cb0ef41Sopenharmony_ci    int next_steal_task_id;
3281cb0ef41Sopenharmony_ci  };
3291cb0ef41Sopenharmony_ci
3301cb0ef41Sopenharmony_ci  int next_task_id(int task_id, size_t num_queues) const {
3311cb0ef41Sopenharmony_ci    int next = task_id + 1;
3321cb0ef41Sopenharmony_ci    return next == static_cast<int>(num_queues) ? 0 : next;
3331cb0ef41Sopenharmony_ci  }
3341cb0ef41Sopenharmony_ci
3351cb0ef41Sopenharmony_ci  int GetLowestTierWithUnits() const {
3361cb0ef41Sopenharmony_ci    for (int tier = 0; tier < kNumTiers; ++tier) {
3371cb0ef41Sopenharmony_ci      if (num_units_[tier].load(std::memory_order_relaxed) > 0) return tier;
3381cb0ef41Sopenharmony_ci    }
3391cb0ef41Sopenharmony_ci    return kNumTiers;
3401cb0ef41Sopenharmony_ci  }
3411cb0ef41Sopenharmony_ci
3421cb0ef41Sopenharmony_ci  base::Optional<WasmCompilationUnit> GetNextUnitOfTier(Queue* public_queue,
3431cb0ef41Sopenharmony_ci                                                        int tier) {
3441cb0ef41Sopenharmony_ci    QueueImpl* queue = static_cast<QueueImpl*>(public_queue);
3451cb0ef41Sopenharmony_ci
3461cb0ef41Sopenharmony_ci    // First check whether there is a priority unit. Execute that first.
3471cb0ef41Sopenharmony_ci    if (tier == kTopTier) {
3481cb0ef41Sopenharmony_ci      if (auto unit = GetTopTierPriorityUnit(queue)) {
3491cb0ef41Sopenharmony_ci        return unit;
3501cb0ef41Sopenharmony_ci      }
3511cb0ef41Sopenharmony_ci    }
3521cb0ef41Sopenharmony_ci
3531cb0ef41Sopenharmony_ci    // Then check whether there is a big unit of that tier.
3541cb0ef41Sopenharmony_ci    if (auto unit = GetBigUnitOfTier(tier)) return unit;
3551cb0ef41Sopenharmony_ci
3561cb0ef41Sopenharmony_ci    // Finally check whether our own queue has a unit of the wanted tier. If
3571cb0ef41Sopenharmony_ci    // so, return it, otherwise get the task id to steal from.
3581cb0ef41Sopenharmony_ci    int steal_task_id;
3591cb0ef41Sopenharmony_ci    {
3601cb0ef41Sopenharmony_ci      base::MutexGuard mutex_guard(&queue->mutex);
3611cb0ef41Sopenharmony_ci      if (!queue->units[tier].empty()) {
3621cb0ef41Sopenharmony_ci        auto unit = queue->units[tier].back();
3631cb0ef41Sopenharmony_ci        queue->units[tier].pop_back();
3641cb0ef41Sopenharmony_ci        return unit;
3651cb0ef41Sopenharmony_ci      }
3661cb0ef41Sopenharmony_ci      steal_task_id = queue->next_steal_task_id;
3671cb0ef41Sopenharmony_ci    }
3681cb0ef41Sopenharmony_ci
3691cb0ef41Sopenharmony_ci    // Try to steal from all other queues. If this succeeds, return one of the
3701cb0ef41Sopenharmony_ci    // stolen units.
3711cb0ef41Sopenharmony_ci    {
3721cb0ef41Sopenharmony_ci      base::SharedMutexGuard<base::kShared> guard(&queues_mutex_);
3731cb0ef41Sopenharmony_ci      for (size_t steal_trials = 0; steal_trials < queues_.size();
3741cb0ef41Sopenharmony_ci           ++steal_trials, ++steal_task_id) {
3751cb0ef41Sopenharmony_ci        if (steal_task_id >= static_cast<int>(queues_.size())) {
3761cb0ef41Sopenharmony_ci          steal_task_id = 0;
3771cb0ef41Sopenharmony_ci        }
3781cb0ef41Sopenharmony_ci        if (auto unit = StealUnitsAndGetFirst(queue, steal_task_id, tier)) {
3791cb0ef41Sopenharmony_ci          return unit;
3801cb0ef41Sopenharmony_ci        }
3811cb0ef41Sopenharmony_ci      }
3821cb0ef41Sopenharmony_ci    }
3831cb0ef41Sopenharmony_ci
3841cb0ef41Sopenharmony_ci    // If we reach here, we didn't find any unit of the requested tier.
3851cb0ef41Sopenharmony_ci    return {};
3861cb0ef41Sopenharmony_ci  }
3871cb0ef41Sopenharmony_ci
3881cb0ef41Sopenharmony_ci  base::Optional<WasmCompilationUnit> GetBigUnitOfTier(int tier) {
3891cb0ef41Sopenharmony_ci    // Fast path without locking.
3901cb0ef41Sopenharmony_ci    if (!big_units_queue_.has_units[tier].load(std::memory_order_relaxed)) {
3911cb0ef41Sopenharmony_ci      return {};
3921cb0ef41Sopenharmony_ci    }
3931cb0ef41Sopenharmony_ci    base::MutexGuard guard(&big_units_queue_.mutex);
3941cb0ef41Sopenharmony_ci    if (big_units_queue_.units[tier].empty()) return {};
3951cb0ef41Sopenharmony_ci    WasmCompilationUnit unit = big_units_queue_.units[tier].top().unit;
3961cb0ef41Sopenharmony_ci    big_units_queue_.units[tier].pop();
3971cb0ef41Sopenharmony_ci    if (big_units_queue_.units[tier].empty()) {
3981cb0ef41Sopenharmony_ci      big_units_queue_.has_units[tier].store(false, std::memory_order_relaxed);
3991cb0ef41Sopenharmony_ci    }
4001cb0ef41Sopenharmony_ci    return unit;
4011cb0ef41Sopenharmony_ci  }
4021cb0ef41Sopenharmony_ci
4031cb0ef41Sopenharmony_ci  base::Optional<WasmCompilationUnit> GetTopTierPriorityUnit(QueueImpl* queue) {
4041cb0ef41Sopenharmony_ci    // Fast path without locking.
4051cb0ef41Sopenharmony_ci    if (num_priority_units_.load(std::memory_order_relaxed) == 0) {
4061cb0ef41Sopenharmony_ci      return {};
4071cb0ef41Sopenharmony_ci    }
4081cb0ef41Sopenharmony_ci
4091cb0ef41Sopenharmony_ci    int steal_task_id;
4101cb0ef41Sopenharmony_ci    {
4111cb0ef41Sopenharmony_ci      base::MutexGuard mutex_guard(&queue->mutex);
4121cb0ef41Sopenharmony_ci      while (!queue->top_tier_priority_units.empty()) {
4131cb0ef41Sopenharmony_ci        auto unit = queue->top_tier_priority_units.top().unit;
4141cb0ef41Sopenharmony_ci        queue->top_tier_priority_units.pop();
4151cb0ef41Sopenharmony_ci        num_priority_units_.fetch_sub(1, std::memory_order_relaxed);
4161cb0ef41Sopenharmony_ci
4171cb0ef41Sopenharmony_ci        if (!top_tier_compiled_[unit.func_index()].exchange(
4181cb0ef41Sopenharmony_ci                true, std::memory_order_relaxed)) {
4191cb0ef41Sopenharmony_ci          return unit;
4201cb0ef41Sopenharmony_ci        }
4211cb0ef41Sopenharmony_ci        num_units_[kTopTier].fetch_sub(1, std::memory_order_relaxed);
4221cb0ef41Sopenharmony_ci      }
4231cb0ef41Sopenharmony_ci      steal_task_id = queue->next_steal_task_id;
4241cb0ef41Sopenharmony_ci    }
4251cb0ef41Sopenharmony_ci
4261cb0ef41Sopenharmony_ci    // Try to steal from all other queues. If this succeeds, return one of the
4271cb0ef41Sopenharmony_ci    // stolen units.
4281cb0ef41Sopenharmony_ci    {
4291cb0ef41Sopenharmony_ci      base::SharedMutexGuard<base::kShared> guard(&queues_mutex_);
4301cb0ef41Sopenharmony_ci      for (size_t steal_trials = 0; steal_trials < queues_.size();
4311cb0ef41Sopenharmony_ci           ++steal_trials, ++steal_task_id) {
4321cb0ef41Sopenharmony_ci        if (steal_task_id >= static_cast<int>(queues_.size())) {
4331cb0ef41Sopenharmony_ci          steal_task_id = 0;
4341cb0ef41Sopenharmony_ci        }
4351cb0ef41Sopenharmony_ci        if (auto unit = StealTopTierPriorityUnit(queue, steal_task_id)) {
4361cb0ef41Sopenharmony_ci          return unit;
4371cb0ef41Sopenharmony_ci        }
4381cb0ef41Sopenharmony_ci      }
4391cb0ef41Sopenharmony_ci    }
4401cb0ef41Sopenharmony_ci
4411cb0ef41Sopenharmony_ci    return {};
4421cb0ef41Sopenharmony_ci  }
4431cb0ef41Sopenharmony_ci
4441cb0ef41Sopenharmony_ci  // Steal units of {wanted_tier} from {steal_from_task_id} to {queue}. Return
4451cb0ef41Sopenharmony_ci  // first stolen unit (rest put in queue of {task_id}), or {nullopt} if
4461cb0ef41Sopenharmony_ci  // {steal_from_task_id} had no units of {wanted_tier}.
4471cb0ef41Sopenharmony_ci  // Hold a shared lock on {queues_mutex_} when calling this method.
4481cb0ef41Sopenharmony_ci  base::Optional<WasmCompilationUnit> StealUnitsAndGetFirst(
4491cb0ef41Sopenharmony_ci      QueueImpl* queue, int steal_from_task_id, int wanted_tier) {
4501cb0ef41Sopenharmony_ci    auto* steal_queue = queues_[steal_from_task_id].get();
4511cb0ef41Sopenharmony_ci    // Cannot steal from own queue.
4521cb0ef41Sopenharmony_ci    if (steal_queue == queue) return {};
4531cb0ef41Sopenharmony_ci    std::vector<WasmCompilationUnit> stolen;
4541cb0ef41Sopenharmony_ci    base::Optional<WasmCompilationUnit> returned_unit;
4551cb0ef41Sopenharmony_ci    {
4561cb0ef41Sopenharmony_ci      base::MutexGuard guard(&steal_queue->mutex);
4571cb0ef41Sopenharmony_ci      auto* steal_from_vector = &steal_queue->units[wanted_tier];
4581cb0ef41Sopenharmony_ci      if (steal_from_vector->empty()) return {};
4591cb0ef41Sopenharmony_ci      size_t remaining = steal_from_vector->size() / 2;
4601cb0ef41Sopenharmony_ci      auto steal_begin = steal_from_vector->begin() + remaining;
4611cb0ef41Sopenharmony_ci      returned_unit = *steal_begin;
4621cb0ef41Sopenharmony_ci      stolen.assign(steal_begin + 1, steal_from_vector->end());
4631cb0ef41Sopenharmony_ci      steal_from_vector->erase(steal_begin, steal_from_vector->end());
4641cb0ef41Sopenharmony_ci    }
4651cb0ef41Sopenharmony_ci    base::MutexGuard guard(&queue->mutex);
4661cb0ef41Sopenharmony_ci    auto* target_queue = &queue->units[wanted_tier];
4671cb0ef41Sopenharmony_ci    target_queue->insert(target_queue->end(), stolen.begin(), stolen.end());
4681cb0ef41Sopenharmony_ci    queue->next_steal_task_id = steal_from_task_id + 1;
4691cb0ef41Sopenharmony_ci    return returned_unit;
4701cb0ef41Sopenharmony_ci  }
4711cb0ef41Sopenharmony_ci
4721cb0ef41Sopenharmony_ci  // Steal one priority unit from {steal_from_task_id} to {task_id}. Return
4731cb0ef41Sopenharmony_ci  // stolen unit, or {nullopt} if {steal_from_task_id} had no priority units.
4741cb0ef41Sopenharmony_ci  // Hold a shared lock on {queues_mutex_} when calling this method.
4751cb0ef41Sopenharmony_ci  base::Optional<WasmCompilationUnit> StealTopTierPriorityUnit(
4761cb0ef41Sopenharmony_ci      QueueImpl* queue, int steal_from_task_id) {
4771cb0ef41Sopenharmony_ci    auto* steal_queue = queues_[steal_from_task_id].get();
4781cb0ef41Sopenharmony_ci    // Cannot steal from own queue.
4791cb0ef41Sopenharmony_ci    if (steal_queue == queue) return {};
4801cb0ef41Sopenharmony_ci    base::Optional<WasmCompilationUnit> returned_unit;
4811cb0ef41Sopenharmony_ci    {
4821cb0ef41Sopenharmony_ci      base::MutexGuard guard(&steal_queue->mutex);
4831cb0ef41Sopenharmony_ci      while (true) {
4841cb0ef41Sopenharmony_ci        if (steal_queue->top_tier_priority_units.empty()) return {};
4851cb0ef41Sopenharmony_ci
4861cb0ef41Sopenharmony_ci        auto unit = steal_queue->top_tier_priority_units.top().unit;
4871cb0ef41Sopenharmony_ci        steal_queue->top_tier_priority_units.pop();
4881cb0ef41Sopenharmony_ci        num_priority_units_.fetch_sub(1, std::memory_order_relaxed);
4891cb0ef41Sopenharmony_ci
4901cb0ef41Sopenharmony_ci        if (!top_tier_compiled_[unit.func_index()].exchange(
4911cb0ef41Sopenharmony_ci                true, std::memory_order_relaxed)) {
4921cb0ef41Sopenharmony_ci          returned_unit = unit;
4931cb0ef41Sopenharmony_ci          break;
4941cb0ef41Sopenharmony_ci        }
4951cb0ef41Sopenharmony_ci        num_units_[kTopTier].fetch_sub(1, std::memory_order_relaxed);
4961cb0ef41Sopenharmony_ci      }
4971cb0ef41Sopenharmony_ci    }
4981cb0ef41Sopenharmony_ci    base::MutexGuard guard(&queue->mutex);
4991cb0ef41Sopenharmony_ci    queue->next_steal_task_id = steal_from_task_id + 1;
5001cb0ef41Sopenharmony_ci    return returned_unit;
5011cb0ef41Sopenharmony_ci  }
5021cb0ef41Sopenharmony_ci
5031cb0ef41Sopenharmony_ci  // {queues_mutex_} protectes {queues_};
5041cb0ef41Sopenharmony_ci  base::SharedMutex queues_mutex_;
5051cb0ef41Sopenharmony_ci  std::vector<std::unique_ptr<QueueImpl>> queues_;
5061cb0ef41Sopenharmony_ci
5071cb0ef41Sopenharmony_ci  const int num_declared_functions_;
5081cb0ef41Sopenharmony_ci
5091cb0ef41Sopenharmony_ci  BigUnitsQueue big_units_queue_;
5101cb0ef41Sopenharmony_ci
5111cb0ef41Sopenharmony_ci  std::atomic<size_t> num_units_[kNumTiers];
5121cb0ef41Sopenharmony_ci  std::atomic<size_t> num_priority_units_{0};
5131cb0ef41Sopenharmony_ci  std::unique_ptr<std::atomic<bool>[]> top_tier_compiled_;
5141cb0ef41Sopenharmony_ci  std::atomic<int> next_queue_to_add{0};
5151cb0ef41Sopenharmony_ci};
5161cb0ef41Sopenharmony_ci
5171cb0ef41Sopenharmony_cibool CompilationUnitQueues::Queue::ShouldPublish(
5181cb0ef41Sopenharmony_ci    int num_processed_units) const {
5191cb0ef41Sopenharmony_ci  auto* queue = static_cast<const QueueImpl*>(this);
5201cb0ef41Sopenharmony_ci  return num_processed_units >=
5211cb0ef41Sopenharmony_ci         queue->publish_limit.load(std::memory_order_relaxed);
5221cb0ef41Sopenharmony_ci}
5231cb0ef41Sopenharmony_ci
5241cb0ef41Sopenharmony_ci// The {CompilationStateImpl} keeps track of the compilation state of the
5251cb0ef41Sopenharmony_ci// owning NativeModule, i.e. which functions are left to be compiled.
5261cb0ef41Sopenharmony_ci// It contains a task manager to allow parallel and asynchronous background
5271cb0ef41Sopenharmony_ci// compilation of functions.
5281cb0ef41Sopenharmony_ci// Its public interface {CompilationState} lives in compilation-environment.h.
5291cb0ef41Sopenharmony_ciclass CompilationStateImpl {
5301cb0ef41Sopenharmony_ci public:
5311cb0ef41Sopenharmony_ci  CompilationStateImpl(const std::shared_ptr<NativeModule>& native_module,
5321cb0ef41Sopenharmony_ci                       std::shared_ptr<Counters> async_counters,
5331cb0ef41Sopenharmony_ci                       DynamicTiering dynamic_tiering);
5341cb0ef41Sopenharmony_ci  ~CompilationStateImpl() {
5351cb0ef41Sopenharmony_ci    if (compile_job_->IsValid()) compile_job_->CancelAndDetach();
5361cb0ef41Sopenharmony_ci  }
5371cb0ef41Sopenharmony_ci
5381cb0ef41Sopenharmony_ci  // Call right after the constructor, after the {compilation_state_} field in
5391cb0ef41Sopenharmony_ci  // the {NativeModule} has been initialized.
5401cb0ef41Sopenharmony_ci  void InitCompileJob();
5411cb0ef41Sopenharmony_ci
5421cb0ef41Sopenharmony_ci  // {kCancelUnconditionally}: Cancel all compilation.
5431cb0ef41Sopenharmony_ci  // {kCancelInitialCompilation}: Cancel all compilation if initial (baseline)
5441cb0ef41Sopenharmony_ci  // compilation is not finished yet.
5451cb0ef41Sopenharmony_ci  enum CancellationPolicy { kCancelUnconditionally, kCancelInitialCompilation };
5461cb0ef41Sopenharmony_ci  void CancelCompilation(CancellationPolicy);
5471cb0ef41Sopenharmony_ci
5481cb0ef41Sopenharmony_ci  bool cancelled() const;
5491cb0ef41Sopenharmony_ci
5501cb0ef41Sopenharmony_ci  // Initialize compilation progress. Set compilation tiers to expect for
5511cb0ef41Sopenharmony_ci  // baseline and top tier compilation. Must be set before
5521cb0ef41Sopenharmony_ci  // {CommitCompilationUnits} is invoked which triggers background compilation.
5531cb0ef41Sopenharmony_ci  void InitializeCompilationProgress(bool lazy_module, int num_import_wrappers,
5541cb0ef41Sopenharmony_ci                                     int num_export_wrappers);
5551cb0ef41Sopenharmony_ci
5561cb0ef41Sopenharmony_ci  // Initialize the compilation progress after deserialization. This is needed
5571cb0ef41Sopenharmony_ci  // for recompilation (e.g. for tier down) to work later.
5581cb0ef41Sopenharmony_ci  void InitializeCompilationProgressAfterDeserialization(
5591cb0ef41Sopenharmony_ci      base::Vector<const int> lazy_functions,
5601cb0ef41Sopenharmony_ci      base::Vector<const int> liftoff_functions);
5611cb0ef41Sopenharmony_ci
5621cb0ef41Sopenharmony_ci  // Initializes compilation units based on the information encoded in the
5631cb0ef41Sopenharmony_ci  // {compilation_progress_}.
5641cb0ef41Sopenharmony_ci  void InitializeCompilationUnits(
5651cb0ef41Sopenharmony_ci      std::unique_ptr<CompilationUnitBuilder> builder);
5661cb0ef41Sopenharmony_ci
5671cb0ef41Sopenharmony_ci  // Adds compilation units for another function to the
5681cb0ef41Sopenharmony_ci  // {CompilationUnitBuilder}. This function is the streaming compilation
5691cb0ef41Sopenharmony_ci  // equivalent to {InitializeCompilationUnits}.
5701cb0ef41Sopenharmony_ci  void AddCompilationUnit(CompilationUnitBuilder* builder, int func_index);
5711cb0ef41Sopenharmony_ci
5721cb0ef41Sopenharmony_ci  // Initialize recompilation of the whole module: Setup compilation progress
5731cb0ef41Sopenharmony_ci  // for recompilation and add the respective compilation units. The callback is
5741cb0ef41Sopenharmony_ci  // called immediately if no recompilation is needed, or called later
5751cb0ef41Sopenharmony_ci  // otherwise.
5761cb0ef41Sopenharmony_ci  void InitializeRecompilation(TieringState new_tiering_state,
5771cb0ef41Sopenharmony_ci                               std::unique_ptr<CompilationEventCallback>
5781cb0ef41Sopenharmony_ci                                   recompilation_finished_callback);
5791cb0ef41Sopenharmony_ci
5801cb0ef41Sopenharmony_ci  // Add the callback to be called on compilation events. Needs to be
5811cb0ef41Sopenharmony_ci  // set before {CommitCompilationUnits} is run to ensure that it receives all
5821cb0ef41Sopenharmony_ci  // events. The callback object must support being deleted from any thread.
5831cb0ef41Sopenharmony_ci  void AddCallback(std::unique_ptr<CompilationEventCallback> callback);
5841cb0ef41Sopenharmony_ci
5851cb0ef41Sopenharmony_ci  // Inserts new functions to compile and kicks off compilation.
5861cb0ef41Sopenharmony_ci  void CommitCompilationUnits(
5871cb0ef41Sopenharmony_ci      base::Vector<WasmCompilationUnit> baseline_units,
5881cb0ef41Sopenharmony_ci      base::Vector<WasmCompilationUnit> top_tier_units,
5891cb0ef41Sopenharmony_ci      base::Vector<std::shared_ptr<JSToWasmWrapperCompilationUnit>>
5901cb0ef41Sopenharmony_ci          js_to_wasm_wrapper_units);
5911cb0ef41Sopenharmony_ci  void CommitTopTierCompilationUnit(WasmCompilationUnit);
5921cb0ef41Sopenharmony_ci  void AddTopTierPriorityCompilationUnit(WasmCompilationUnit, size_t);
5931cb0ef41Sopenharmony_ci
5941cb0ef41Sopenharmony_ci  CompilationUnitQueues::Queue* GetQueueForCompileTask(int task_id);
5951cb0ef41Sopenharmony_ci
5961cb0ef41Sopenharmony_ci  base::Optional<WasmCompilationUnit> GetNextCompilationUnit(
5971cb0ef41Sopenharmony_ci      CompilationUnitQueues::Queue*, CompileBaselineOnly);
5981cb0ef41Sopenharmony_ci
5991cb0ef41Sopenharmony_ci  std::shared_ptr<JSToWasmWrapperCompilationUnit>
6001cb0ef41Sopenharmony_ci  GetNextJSToWasmWrapperCompilationUnit();
6011cb0ef41Sopenharmony_ci  void FinalizeJSToWasmWrappers(Isolate* isolate, const WasmModule* module,
6021cb0ef41Sopenharmony_ci                                Handle<FixedArray>* export_wrappers_out);
6031cb0ef41Sopenharmony_ci
6041cb0ef41Sopenharmony_ci  void OnFinishedUnits(base::Vector<WasmCode*>);
6051cb0ef41Sopenharmony_ci  void OnFinishedJSToWasmWrapperUnits(int num);
6061cb0ef41Sopenharmony_ci
6071cb0ef41Sopenharmony_ci  void OnCompilationStopped(WasmFeatures detected);
6081cb0ef41Sopenharmony_ci  void PublishDetectedFeatures(Isolate*);
6091cb0ef41Sopenharmony_ci  void SchedulePublishCompilationResults(
6101cb0ef41Sopenharmony_ci      std::vector<std::unique_ptr<WasmCode>> unpublished_code);
6111cb0ef41Sopenharmony_ci
6121cb0ef41Sopenharmony_ci  size_t NumOutstandingCompilations() const;
6131cb0ef41Sopenharmony_ci
6141cb0ef41Sopenharmony_ci  void SetError();
6151cb0ef41Sopenharmony_ci
6161cb0ef41Sopenharmony_ci  void WaitForCompilationEvent(CompilationEvent event);
6171cb0ef41Sopenharmony_ci
6181cb0ef41Sopenharmony_ci  void SetHighPriority() {
6191cb0ef41Sopenharmony_ci    // TODO(wasm): Keep a lower priority for TurboFan-only jobs.
6201cb0ef41Sopenharmony_ci    compile_job_->UpdatePriority(TaskPriority::kUserBlocking);
6211cb0ef41Sopenharmony_ci  }
6221cb0ef41Sopenharmony_ci
6231cb0ef41Sopenharmony_ci  bool failed() const {
6241cb0ef41Sopenharmony_ci    return compile_failed_.load(std::memory_order_relaxed);
6251cb0ef41Sopenharmony_ci  }
6261cb0ef41Sopenharmony_ci
6271cb0ef41Sopenharmony_ci  bool baseline_compilation_finished() const {
6281cb0ef41Sopenharmony_ci    base::MutexGuard guard(&callbacks_mutex_);
6291cb0ef41Sopenharmony_ci    return outstanding_baseline_units_ == 0 &&
6301cb0ef41Sopenharmony_ci           outstanding_export_wrappers_ == 0;
6311cb0ef41Sopenharmony_ci  }
6321cb0ef41Sopenharmony_ci
6331cb0ef41Sopenharmony_ci  bool top_tier_compilation_finished() const {
6341cb0ef41Sopenharmony_ci    base::MutexGuard guard(&callbacks_mutex_);
6351cb0ef41Sopenharmony_ci    return outstanding_top_tier_functions_ == 0;
6361cb0ef41Sopenharmony_ci  }
6371cb0ef41Sopenharmony_ci
6381cb0ef41Sopenharmony_ci  bool recompilation_finished() const {
6391cb0ef41Sopenharmony_ci    base::MutexGuard guard(&callbacks_mutex_);
6401cb0ef41Sopenharmony_ci    return outstanding_recompilation_functions_ == 0;
6411cb0ef41Sopenharmony_ci  }
6421cb0ef41Sopenharmony_ci
6431cb0ef41Sopenharmony_ci  DynamicTiering dynamic_tiering() const { return dynamic_tiering_; }
6441cb0ef41Sopenharmony_ci
6451cb0ef41Sopenharmony_ci  Counters* counters() const { return async_counters_.get(); }
6461cb0ef41Sopenharmony_ci
6471cb0ef41Sopenharmony_ci  void SetWireBytesStorage(
6481cb0ef41Sopenharmony_ci      std::shared_ptr<WireBytesStorage> wire_bytes_storage) {
6491cb0ef41Sopenharmony_ci    base::MutexGuard guard(&mutex_);
6501cb0ef41Sopenharmony_ci    wire_bytes_storage_ = std::move(wire_bytes_storage);
6511cb0ef41Sopenharmony_ci  }
6521cb0ef41Sopenharmony_ci
6531cb0ef41Sopenharmony_ci  std::shared_ptr<WireBytesStorage> GetWireBytesStorage() const {
6541cb0ef41Sopenharmony_ci    base::MutexGuard guard(&mutex_);
6551cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(wire_bytes_storage_);
6561cb0ef41Sopenharmony_ci    return wire_bytes_storage_;
6571cb0ef41Sopenharmony_ci  }
6581cb0ef41Sopenharmony_ci
6591cb0ef41Sopenharmony_ci  void set_compilation_id(int compilation_id) {
6601cb0ef41Sopenharmony_ci    DCHECK_EQ(compilation_id_, kInvalidCompilationID);
6611cb0ef41Sopenharmony_ci    compilation_id_ = compilation_id;
6621cb0ef41Sopenharmony_ci  }
6631cb0ef41Sopenharmony_ci
6641cb0ef41Sopenharmony_ci  std::weak_ptr<NativeModule> const native_module_weak() const {
6651cb0ef41Sopenharmony_ci    return native_module_weak_;
6661cb0ef41Sopenharmony_ci  }
6671cb0ef41Sopenharmony_ci
6681cb0ef41Sopenharmony_ci private:
6691cb0ef41Sopenharmony_ci  uint8_t SetupCompilationProgressForFunction(
6701cb0ef41Sopenharmony_ci      bool lazy_function, NativeModule* module,
6711cb0ef41Sopenharmony_ci      const WasmFeatures& enabled_features, int func_index);
6721cb0ef41Sopenharmony_ci
6731cb0ef41Sopenharmony_ci  // Returns the potentially-updated {function_progress}.
6741cb0ef41Sopenharmony_ci  uint8_t AddCompilationUnitInternal(CompilationUnitBuilder* builder,
6751cb0ef41Sopenharmony_ci                                     int function_index,
6761cb0ef41Sopenharmony_ci                                     uint8_t function_progress);
6771cb0ef41Sopenharmony_ci
6781cb0ef41Sopenharmony_ci  // Trigger callbacks according to the internal counters below
6791cb0ef41Sopenharmony_ci  // (outstanding_...), plus the given events.
6801cb0ef41Sopenharmony_ci  // Hold the {callbacks_mutex_} when calling this method.
6811cb0ef41Sopenharmony_ci  void TriggerCallbacks(base::EnumSet<CompilationEvent> additional_events = {});
6821cb0ef41Sopenharmony_ci
6831cb0ef41Sopenharmony_ci  void PublishCompilationResults(
6841cb0ef41Sopenharmony_ci      std::vector<std::unique_ptr<WasmCode>> unpublished_code);
6851cb0ef41Sopenharmony_ci  void PublishCode(base::Vector<std::unique_ptr<WasmCode>> codes);
6861cb0ef41Sopenharmony_ci
6871cb0ef41Sopenharmony_ci  NativeModule* const native_module_;
6881cb0ef41Sopenharmony_ci  std::weak_ptr<NativeModule> const native_module_weak_;
6891cb0ef41Sopenharmony_ci  const std::shared_ptr<Counters> async_counters_;
6901cb0ef41Sopenharmony_ci
6911cb0ef41Sopenharmony_ci  // Compilation error, atomically updated. This flag can be updated and read
6921cb0ef41Sopenharmony_ci  // using relaxed semantics.
6931cb0ef41Sopenharmony_ci  std::atomic<bool> compile_failed_{false};
6941cb0ef41Sopenharmony_ci
6951cb0ef41Sopenharmony_ci  // True if compilation was cancelled and worker threads should return. This
6961cb0ef41Sopenharmony_ci  // flag can be updated and read using relaxed semantics.
6971cb0ef41Sopenharmony_ci  std::atomic<bool> compile_cancelled_{false};
6981cb0ef41Sopenharmony_ci
6991cb0ef41Sopenharmony_ci  CompilationUnitQueues compilation_unit_queues_;
7001cb0ef41Sopenharmony_ci
7011cb0ef41Sopenharmony_ci  // Number of wrappers to be compiled. Initialized once, counted down in
7021cb0ef41Sopenharmony_ci  // {GetNextJSToWasmWrapperCompilationUnit}.
7031cb0ef41Sopenharmony_ci  std::atomic<size_t> outstanding_js_to_wasm_wrappers_{0};
7041cb0ef41Sopenharmony_ci  // Wrapper compilation units are stored in shared_ptrs so that they are kept
7051cb0ef41Sopenharmony_ci  // alive by the tasks even if the NativeModule dies.
7061cb0ef41Sopenharmony_ci  std::vector<std::shared_ptr<JSToWasmWrapperCompilationUnit>>
7071cb0ef41Sopenharmony_ci      js_to_wasm_wrapper_units_;
7081cb0ef41Sopenharmony_ci
7091cb0ef41Sopenharmony_ci  // Cache the dynamic tiering configuration to be consistent for the whole
7101cb0ef41Sopenharmony_ci  // compilation.
7111cb0ef41Sopenharmony_ci  const DynamicTiering dynamic_tiering_;
7121cb0ef41Sopenharmony_ci
7131cb0ef41Sopenharmony_ci  // This mutex protects all information of this {CompilationStateImpl} which is
7141cb0ef41Sopenharmony_ci  // being accessed concurrently.
7151cb0ef41Sopenharmony_ci  mutable base::Mutex mutex_;
7161cb0ef41Sopenharmony_ci
7171cb0ef41Sopenharmony_ci  // The compile job handle, initialized right after construction of
7181cb0ef41Sopenharmony_ci  // {CompilationStateImpl}.
7191cb0ef41Sopenharmony_ci  std::unique_ptr<JobHandle> compile_job_;
7201cb0ef41Sopenharmony_ci
7211cb0ef41Sopenharmony_ci  // The compilation id to identify trace events linked to this compilation.
7221cb0ef41Sopenharmony_ci  static constexpr int kInvalidCompilationID = -1;
7231cb0ef41Sopenharmony_ci  int compilation_id_ = kInvalidCompilationID;
7241cb0ef41Sopenharmony_ci
7251cb0ef41Sopenharmony_ci  //////////////////////////////////////////////////////////////////////////////
7261cb0ef41Sopenharmony_ci  // Protected by {mutex_}:
7271cb0ef41Sopenharmony_ci
7281cb0ef41Sopenharmony_ci  // Features detected to be used in this module. Features can be detected
7291cb0ef41Sopenharmony_ci  // as a module is being compiled.
7301cb0ef41Sopenharmony_ci  WasmFeatures detected_features_ = WasmFeatures::None();
7311cb0ef41Sopenharmony_ci
7321cb0ef41Sopenharmony_ci  // Abstraction over the storage of the wire bytes. Held in a shared_ptr so
7331cb0ef41Sopenharmony_ci  // that background compilation jobs can keep the storage alive while
7341cb0ef41Sopenharmony_ci  // compiling.
7351cb0ef41Sopenharmony_ci  std::shared_ptr<WireBytesStorage> wire_bytes_storage_;
7361cb0ef41Sopenharmony_ci
7371cb0ef41Sopenharmony_ci  // End of fields protected by {mutex_}.
7381cb0ef41Sopenharmony_ci  //////////////////////////////////////////////////////////////////////////////
7391cb0ef41Sopenharmony_ci
7401cb0ef41Sopenharmony_ci  // This mutex protects the callbacks vector, and the counters used to
7411cb0ef41Sopenharmony_ci  // determine which callbacks to call. The counters plus the callbacks
7421cb0ef41Sopenharmony_ci  // themselves need to be synchronized to ensure correct order of events.
7431cb0ef41Sopenharmony_ci  mutable base::Mutex callbacks_mutex_;
7441cb0ef41Sopenharmony_ci
7451cb0ef41Sopenharmony_ci  //////////////////////////////////////////////////////////////////////////////
7461cb0ef41Sopenharmony_ci  // Protected by {callbacks_mutex_}:
7471cb0ef41Sopenharmony_ci
7481cb0ef41Sopenharmony_ci  // Callbacks to be called on compilation events.
7491cb0ef41Sopenharmony_ci  std::vector<std::unique_ptr<CompilationEventCallback>> callbacks_;
7501cb0ef41Sopenharmony_ci
7511cb0ef41Sopenharmony_ci  // Events that already happened.
7521cb0ef41Sopenharmony_ci  base::EnumSet<CompilationEvent> finished_events_;
7531cb0ef41Sopenharmony_ci
7541cb0ef41Sopenharmony_ci  int outstanding_baseline_units_ = 0;
7551cb0ef41Sopenharmony_ci  int outstanding_export_wrappers_ = 0;
7561cb0ef41Sopenharmony_ci  int outstanding_top_tier_functions_ = 0;
7571cb0ef41Sopenharmony_ci  // The amount of generated top tier code since the last
7581cb0ef41Sopenharmony_ci  // {kFinishedCompilationChunk} event.
7591cb0ef41Sopenharmony_ci  size_t bytes_since_last_chunk_ = 0;
7601cb0ef41Sopenharmony_ci  std::vector<uint8_t> compilation_progress_;
7611cb0ef41Sopenharmony_ci
7621cb0ef41Sopenharmony_ci  int outstanding_recompilation_functions_ = 0;
7631cb0ef41Sopenharmony_ci  TieringState tiering_state_ = kTieredUp;
7641cb0ef41Sopenharmony_ci
7651cb0ef41Sopenharmony_ci  // End of fields protected by {callbacks_mutex_}.
7661cb0ef41Sopenharmony_ci  //////////////////////////////////////////////////////////////////////////////
7671cb0ef41Sopenharmony_ci
7681cb0ef41Sopenharmony_ci  // {publish_mutex_} protects {publish_queue_} and {publisher_running_}.
7691cb0ef41Sopenharmony_ci  base::Mutex publish_mutex_;
7701cb0ef41Sopenharmony_ci  std::vector<std::unique_ptr<WasmCode>> publish_queue_;
7711cb0ef41Sopenharmony_ci  bool publisher_running_ = false;
7721cb0ef41Sopenharmony_ci
7731cb0ef41Sopenharmony_ci  // Encoding of fields in the {compilation_progress_} vector.
7741cb0ef41Sopenharmony_ci  using RequiredBaselineTierField = base::BitField8<ExecutionTier, 0, 2>;
7751cb0ef41Sopenharmony_ci  using RequiredTopTierField = base::BitField8<ExecutionTier, 2, 2>;
7761cb0ef41Sopenharmony_ci  using ReachedTierField = base::BitField8<ExecutionTier, 4, 2>;
7771cb0ef41Sopenharmony_ci  using MissingRecompilationField = base::BitField8<bool, 6, 1>;
7781cb0ef41Sopenharmony_ci};
7791cb0ef41Sopenharmony_ci
7801cb0ef41Sopenharmony_ciCompilationStateImpl* Impl(CompilationState* compilation_state) {
7811cb0ef41Sopenharmony_ci  return reinterpret_cast<CompilationStateImpl*>(compilation_state);
7821cb0ef41Sopenharmony_ci}
7831cb0ef41Sopenharmony_ciconst CompilationStateImpl* Impl(const CompilationState* compilation_state) {
7841cb0ef41Sopenharmony_ci  return reinterpret_cast<const CompilationStateImpl*>(compilation_state);
7851cb0ef41Sopenharmony_ci}
7861cb0ef41Sopenharmony_ci
7871cb0ef41Sopenharmony_ciCompilationStateImpl* BackgroundCompileScope::compilation_state() const {
7881cb0ef41Sopenharmony_ci  DCHECK(native_module_);
7891cb0ef41Sopenharmony_ci  return Impl(native_module_->compilation_state());
7901cb0ef41Sopenharmony_ci}
7911cb0ef41Sopenharmony_ci
7921cb0ef41Sopenharmony_cibool BackgroundCompileScope::cancelled() const {
7931cb0ef41Sopenharmony_ci  return native_module_ == nullptr ||
7941cb0ef41Sopenharmony_ci         Impl(native_module_->compilation_state())->cancelled();
7951cb0ef41Sopenharmony_ci}
7961cb0ef41Sopenharmony_ci
7971cb0ef41Sopenharmony_civoid UpdateFeatureUseCounts(Isolate* isolate, const WasmFeatures& detected) {
7981cb0ef41Sopenharmony_ci  using Feature = v8::Isolate::UseCounterFeature;
7991cb0ef41Sopenharmony_ci  constexpr static std::pair<WasmFeature, Feature> kUseCounters[] = {
8001cb0ef41Sopenharmony_ci      {kFeature_reftypes, Feature::kWasmRefTypes},
8011cb0ef41Sopenharmony_ci      {kFeature_simd, Feature::kWasmSimdOpcodes},
8021cb0ef41Sopenharmony_ci      {kFeature_threads, Feature::kWasmThreadOpcodes},
8031cb0ef41Sopenharmony_ci      {kFeature_eh, Feature::kWasmExceptionHandling}};
8041cb0ef41Sopenharmony_ci
8051cb0ef41Sopenharmony_ci  for (auto& feature : kUseCounters) {
8061cb0ef41Sopenharmony_ci    if (detected.contains(feature.first)) isolate->CountUsage(feature.second);
8071cb0ef41Sopenharmony_ci  }
8081cb0ef41Sopenharmony_ci}
8091cb0ef41Sopenharmony_ci
8101cb0ef41Sopenharmony_ci}  // namespace
8111cb0ef41Sopenharmony_ci
8121cb0ef41Sopenharmony_ci//////////////////////////////////////////////////////
8131cb0ef41Sopenharmony_ci// PIMPL implementation of {CompilationState}.
8141cb0ef41Sopenharmony_ci
8151cb0ef41Sopenharmony_ciCompilationState::~CompilationState() { Impl(this)->~CompilationStateImpl(); }
8161cb0ef41Sopenharmony_ci
8171cb0ef41Sopenharmony_civoid CompilationState::InitCompileJob() { Impl(this)->InitCompileJob(); }
8181cb0ef41Sopenharmony_ci
8191cb0ef41Sopenharmony_civoid CompilationState::CancelCompilation() {
8201cb0ef41Sopenharmony_ci  Impl(this)->CancelCompilation(CompilationStateImpl::kCancelUnconditionally);
8211cb0ef41Sopenharmony_ci}
8221cb0ef41Sopenharmony_ci
8231cb0ef41Sopenharmony_civoid CompilationState::CancelInitialCompilation() {
8241cb0ef41Sopenharmony_ci  Impl(this)->CancelCompilation(
8251cb0ef41Sopenharmony_ci      CompilationStateImpl::kCancelInitialCompilation);
8261cb0ef41Sopenharmony_ci}
8271cb0ef41Sopenharmony_ci
8281cb0ef41Sopenharmony_civoid CompilationState::SetError() { Impl(this)->SetError(); }
8291cb0ef41Sopenharmony_ci
8301cb0ef41Sopenharmony_civoid CompilationState::SetWireBytesStorage(
8311cb0ef41Sopenharmony_ci    std::shared_ptr<WireBytesStorage> wire_bytes_storage) {
8321cb0ef41Sopenharmony_ci  Impl(this)->SetWireBytesStorage(std::move(wire_bytes_storage));
8331cb0ef41Sopenharmony_ci}
8341cb0ef41Sopenharmony_ci
8351cb0ef41Sopenharmony_cistd::shared_ptr<WireBytesStorage> CompilationState::GetWireBytesStorage()
8361cb0ef41Sopenharmony_ci    const {
8371cb0ef41Sopenharmony_ci  return Impl(this)->GetWireBytesStorage();
8381cb0ef41Sopenharmony_ci}
8391cb0ef41Sopenharmony_ci
8401cb0ef41Sopenharmony_civoid CompilationState::AddCallback(
8411cb0ef41Sopenharmony_ci    std::unique_ptr<CompilationEventCallback> callback) {
8421cb0ef41Sopenharmony_ci  return Impl(this)->AddCallback(std::move(callback));
8431cb0ef41Sopenharmony_ci}
8441cb0ef41Sopenharmony_ci
8451cb0ef41Sopenharmony_civoid CompilationState::WaitForTopTierFinished() {
8461cb0ef41Sopenharmony_ci  Impl(this)->WaitForCompilationEvent(
8471cb0ef41Sopenharmony_ci      CompilationEvent::kFinishedTopTierCompilation);
8481cb0ef41Sopenharmony_ci}
8491cb0ef41Sopenharmony_ci
8501cb0ef41Sopenharmony_civoid CompilationState::SetHighPriority() { Impl(this)->SetHighPriority(); }
8511cb0ef41Sopenharmony_ci
8521cb0ef41Sopenharmony_civoid CompilationState::InitializeAfterDeserialization(
8531cb0ef41Sopenharmony_ci    base::Vector<const int> lazy_functions,
8541cb0ef41Sopenharmony_ci    base::Vector<const int> liftoff_functions) {
8551cb0ef41Sopenharmony_ci  Impl(this)->InitializeCompilationProgressAfterDeserialization(
8561cb0ef41Sopenharmony_ci      lazy_functions, liftoff_functions);
8571cb0ef41Sopenharmony_ci}
8581cb0ef41Sopenharmony_ci
8591cb0ef41Sopenharmony_cibool CompilationState::failed() const { return Impl(this)->failed(); }
8601cb0ef41Sopenharmony_ci
8611cb0ef41Sopenharmony_cibool CompilationState::baseline_compilation_finished() const {
8621cb0ef41Sopenharmony_ci  return Impl(this)->baseline_compilation_finished();
8631cb0ef41Sopenharmony_ci}
8641cb0ef41Sopenharmony_ci
8651cb0ef41Sopenharmony_cibool CompilationState::top_tier_compilation_finished() const {
8661cb0ef41Sopenharmony_ci  return Impl(this)->top_tier_compilation_finished();
8671cb0ef41Sopenharmony_ci}
8681cb0ef41Sopenharmony_ci
8691cb0ef41Sopenharmony_cibool CompilationState::recompilation_finished() const {
8701cb0ef41Sopenharmony_ci  return Impl(this)->recompilation_finished();
8711cb0ef41Sopenharmony_ci}
8721cb0ef41Sopenharmony_ci
8731cb0ef41Sopenharmony_civoid CompilationState::set_compilation_id(int compilation_id) {
8741cb0ef41Sopenharmony_ci  Impl(this)->set_compilation_id(compilation_id);
8751cb0ef41Sopenharmony_ci}
8761cb0ef41Sopenharmony_ci
8771cb0ef41Sopenharmony_ciDynamicTiering CompilationState::dynamic_tiering() const {
8781cb0ef41Sopenharmony_ci  return Impl(this)->dynamic_tiering();
8791cb0ef41Sopenharmony_ci}
8801cb0ef41Sopenharmony_ci
8811cb0ef41Sopenharmony_ci// static
8821cb0ef41Sopenharmony_cistd::unique_ptr<CompilationState> CompilationState::New(
8831cb0ef41Sopenharmony_ci    const std::shared_ptr<NativeModule>& native_module,
8841cb0ef41Sopenharmony_ci    std::shared_ptr<Counters> async_counters, DynamicTiering dynamic_tiering) {
8851cb0ef41Sopenharmony_ci  return std::unique_ptr<CompilationState>(reinterpret_cast<CompilationState*>(
8861cb0ef41Sopenharmony_ci      new CompilationStateImpl(std::move(native_module),
8871cb0ef41Sopenharmony_ci                               std::move(async_counters), dynamic_tiering)));
8881cb0ef41Sopenharmony_ci}
8891cb0ef41Sopenharmony_ci
8901cb0ef41Sopenharmony_ci// End of PIMPL implementation of {CompilationState}.
8911cb0ef41Sopenharmony_ci//////////////////////////////////////////////////////
8921cb0ef41Sopenharmony_ci
8931cb0ef41Sopenharmony_cinamespace {
8941cb0ef41Sopenharmony_ci
8951cb0ef41Sopenharmony_ciExecutionTier ApplyHintToExecutionTier(WasmCompilationHintTier hint,
8961cb0ef41Sopenharmony_ci                                       ExecutionTier default_tier) {
8971cb0ef41Sopenharmony_ci  switch (hint) {
8981cb0ef41Sopenharmony_ci    case WasmCompilationHintTier::kDefault:
8991cb0ef41Sopenharmony_ci      return default_tier;
9001cb0ef41Sopenharmony_ci    case WasmCompilationHintTier::kBaseline:
9011cb0ef41Sopenharmony_ci      return ExecutionTier::kLiftoff;
9021cb0ef41Sopenharmony_ci    case WasmCompilationHintTier::kOptimized:
9031cb0ef41Sopenharmony_ci      return ExecutionTier::kTurbofan;
9041cb0ef41Sopenharmony_ci  }
9051cb0ef41Sopenharmony_ci  UNREACHABLE();
9061cb0ef41Sopenharmony_ci}
9071cb0ef41Sopenharmony_ci
9081cb0ef41Sopenharmony_ciconst WasmCompilationHint* GetCompilationHint(const WasmModule* module,
9091cb0ef41Sopenharmony_ci                                              uint32_t func_index) {
9101cb0ef41Sopenharmony_ci  DCHECK_LE(module->num_imported_functions, func_index);
9111cb0ef41Sopenharmony_ci  uint32_t hint_index = declared_function_index(module, func_index);
9121cb0ef41Sopenharmony_ci  const std::vector<WasmCompilationHint>& compilation_hints =
9131cb0ef41Sopenharmony_ci      module->compilation_hints;
9141cb0ef41Sopenharmony_ci  if (hint_index < compilation_hints.size()) {
9151cb0ef41Sopenharmony_ci    return &compilation_hints[hint_index];
9161cb0ef41Sopenharmony_ci  }
9171cb0ef41Sopenharmony_ci  return nullptr;
9181cb0ef41Sopenharmony_ci}
9191cb0ef41Sopenharmony_ci
9201cb0ef41Sopenharmony_ciCompileStrategy GetCompileStrategy(const WasmModule* module,
9211cb0ef41Sopenharmony_ci                                   const WasmFeatures& enabled_features,
9221cb0ef41Sopenharmony_ci                                   uint32_t func_index, bool lazy_module) {
9231cb0ef41Sopenharmony_ci  if (lazy_module) return CompileStrategy::kLazy;
9241cb0ef41Sopenharmony_ci  if (!enabled_features.has_compilation_hints()) {
9251cb0ef41Sopenharmony_ci    return CompileStrategy::kDefault;
9261cb0ef41Sopenharmony_ci  }
9271cb0ef41Sopenharmony_ci  auto* hint = GetCompilationHint(module, func_index);
9281cb0ef41Sopenharmony_ci  if (hint == nullptr) return CompileStrategy::kDefault;
9291cb0ef41Sopenharmony_ci  switch (hint->strategy) {
9301cb0ef41Sopenharmony_ci    case WasmCompilationHintStrategy::kLazy:
9311cb0ef41Sopenharmony_ci      return CompileStrategy::kLazy;
9321cb0ef41Sopenharmony_ci    case WasmCompilationHintStrategy::kEager:
9331cb0ef41Sopenharmony_ci      return CompileStrategy::kEager;
9341cb0ef41Sopenharmony_ci    case WasmCompilationHintStrategy::kLazyBaselineEagerTopTier:
9351cb0ef41Sopenharmony_ci      return CompileStrategy::kLazyBaselineEagerTopTier;
9361cb0ef41Sopenharmony_ci    case WasmCompilationHintStrategy::kDefault:
9371cb0ef41Sopenharmony_ci      return CompileStrategy::kDefault;
9381cb0ef41Sopenharmony_ci  }
9391cb0ef41Sopenharmony_ci}
9401cb0ef41Sopenharmony_ci
9411cb0ef41Sopenharmony_cistruct ExecutionTierPair {
9421cb0ef41Sopenharmony_ci  ExecutionTier baseline_tier;
9431cb0ef41Sopenharmony_ci  ExecutionTier top_tier;
9441cb0ef41Sopenharmony_ci};
9451cb0ef41Sopenharmony_ci
9461cb0ef41Sopenharmony_ciExecutionTierPair GetRequestedExecutionTiers(
9471cb0ef41Sopenharmony_ci    NativeModule* native_module, const WasmFeatures& enabled_features,
9481cb0ef41Sopenharmony_ci    uint32_t func_index) {
9491cb0ef41Sopenharmony_ci  const WasmModule* module = native_module->module();
9501cb0ef41Sopenharmony_ci  ExecutionTierPair result;
9511cb0ef41Sopenharmony_ci
9521cb0ef41Sopenharmony_ci  result.baseline_tier = WasmCompilationUnit::GetBaselineExecutionTier(module);
9531cb0ef41Sopenharmony_ci
9541cb0ef41Sopenharmony_ci  bool dynamic_tiering =
9551cb0ef41Sopenharmony_ci      Impl(native_module->compilation_state())->dynamic_tiering() ==
9561cb0ef41Sopenharmony_ci      DynamicTiering::kEnabled;
9571cb0ef41Sopenharmony_ci  bool tier_up_enabled = !dynamic_tiering && FLAG_wasm_tier_up;
9581cb0ef41Sopenharmony_ci  if (module->origin != kWasmOrigin || !tier_up_enabled ||
9591cb0ef41Sopenharmony_ci      V8_UNLIKELY(FLAG_wasm_tier_up_filter >= 0 &&
9601cb0ef41Sopenharmony_ci                  func_index !=
9611cb0ef41Sopenharmony_ci                      static_cast<uint32_t>(FLAG_wasm_tier_up_filter))) {
9621cb0ef41Sopenharmony_ci    result.top_tier = result.baseline_tier;
9631cb0ef41Sopenharmony_ci    return result;
9641cb0ef41Sopenharmony_ci  }
9651cb0ef41Sopenharmony_ci
9661cb0ef41Sopenharmony_ci  // Default tiering behaviour.
9671cb0ef41Sopenharmony_ci  result.top_tier = ExecutionTier::kTurbofan;
9681cb0ef41Sopenharmony_ci
9691cb0ef41Sopenharmony_ci  // Check if compilation hints override default tiering behaviour.
9701cb0ef41Sopenharmony_ci  if (enabled_features.has_compilation_hints()) {
9711cb0ef41Sopenharmony_ci    const WasmCompilationHint* hint = GetCompilationHint(module, func_index);
9721cb0ef41Sopenharmony_ci    if (hint != nullptr) {
9731cb0ef41Sopenharmony_ci      result.baseline_tier =
9741cb0ef41Sopenharmony_ci          ApplyHintToExecutionTier(hint->baseline_tier, result.baseline_tier);
9751cb0ef41Sopenharmony_ci      result.top_tier =
9761cb0ef41Sopenharmony_ci          ApplyHintToExecutionTier(hint->top_tier, result.top_tier);
9771cb0ef41Sopenharmony_ci    }
9781cb0ef41Sopenharmony_ci  }
9791cb0ef41Sopenharmony_ci
9801cb0ef41Sopenharmony_ci  // Correct top tier if necessary.
9811cb0ef41Sopenharmony_ci  static_assert(ExecutionTier::kLiftoff < ExecutionTier::kTurbofan,
9821cb0ef41Sopenharmony_ci                "Assume an order on execution tiers");
9831cb0ef41Sopenharmony_ci  if (result.baseline_tier > result.top_tier) {
9841cb0ef41Sopenharmony_ci    result.top_tier = result.baseline_tier;
9851cb0ef41Sopenharmony_ci  }
9861cb0ef41Sopenharmony_ci  return result;
9871cb0ef41Sopenharmony_ci}
9881cb0ef41Sopenharmony_ci
9891cb0ef41Sopenharmony_ci// The {CompilationUnitBuilder} builds compilation units and stores them in an
9901cb0ef41Sopenharmony_ci// internal buffer. The buffer is moved into the working queue of the
9911cb0ef41Sopenharmony_ci// {CompilationStateImpl} when {Commit} is called.
9921cb0ef41Sopenharmony_ciclass CompilationUnitBuilder {
9931cb0ef41Sopenharmony_ci public:
9941cb0ef41Sopenharmony_ci  explicit CompilationUnitBuilder(NativeModule* native_module)
9951cb0ef41Sopenharmony_ci      : native_module_(native_module) {}
9961cb0ef41Sopenharmony_ci
9971cb0ef41Sopenharmony_ci  void AddUnits(uint32_t func_index) {
9981cb0ef41Sopenharmony_ci    if (func_index < native_module_->module()->num_imported_functions) {
9991cb0ef41Sopenharmony_ci      baseline_units_.emplace_back(func_index, ExecutionTier::kNone,
10001cb0ef41Sopenharmony_ci                                   kNoDebugging);
10011cb0ef41Sopenharmony_ci      return;
10021cb0ef41Sopenharmony_ci    }
10031cb0ef41Sopenharmony_ci    ExecutionTierPair tiers = GetRequestedExecutionTiers(
10041cb0ef41Sopenharmony_ci        native_module_, native_module_->enabled_features(), func_index);
10051cb0ef41Sopenharmony_ci    // Compile everything for non-debugging initially. If needed, we will tier
10061cb0ef41Sopenharmony_ci    // down when the module is fully compiled. Synchronization would be pretty
10071cb0ef41Sopenharmony_ci    // difficult otherwise.
10081cb0ef41Sopenharmony_ci    baseline_units_.emplace_back(func_index, tiers.baseline_tier, kNoDebugging);
10091cb0ef41Sopenharmony_ci    if (tiers.baseline_tier != tiers.top_tier) {
10101cb0ef41Sopenharmony_ci      tiering_units_.emplace_back(func_index, tiers.top_tier, kNoDebugging);
10111cb0ef41Sopenharmony_ci    }
10121cb0ef41Sopenharmony_ci  }
10131cb0ef41Sopenharmony_ci
10141cb0ef41Sopenharmony_ci  void AddJSToWasmWrapperUnit(
10151cb0ef41Sopenharmony_ci      std::shared_ptr<JSToWasmWrapperCompilationUnit> unit) {
10161cb0ef41Sopenharmony_ci    js_to_wasm_wrapper_units_.emplace_back(std::move(unit));
10171cb0ef41Sopenharmony_ci  }
10181cb0ef41Sopenharmony_ci
10191cb0ef41Sopenharmony_ci  void AddBaselineUnit(int func_index, ExecutionTier tier) {
10201cb0ef41Sopenharmony_ci    baseline_units_.emplace_back(func_index, tier, kNoDebugging);
10211cb0ef41Sopenharmony_ci  }
10221cb0ef41Sopenharmony_ci
10231cb0ef41Sopenharmony_ci  void AddTopTierUnit(int func_index, ExecutionTier tier) {
10241cb0ef41Sopenharmony_ci    tiering_units_.emplace_back(func_index, tier, kNoDebugging);
10251cb0ef41Sopenharmony_ci  }
10261cb0ef41Sopenharmony_ci
10271cb0ef41Sopenharmony_ci  void AddDebugUnit(int func_index) {
10281cb0ef41Sopenharmony_ci    baseline_units_.emplace_back(func_index, ExecutionTier::kLiftoff,
10291cb0ef41Sopenharmony_ci                                 kForDebugging);
10301cb0ef41Sopenharmony_ci  }
10311cb0ef41Sopenharmony_ci
10321cb0ef41Sopenharmony_ci  void AddRecompilationUnit(int func_index, ExecutionTier tier) {
10331cb0ef41Sopenharmony_ci    // For recompilation, just treat all units like baseline units.
10341cb0ef41Sopenharmony_ci    baseline_units_.emplace_back(
10351cb0ef41Sopenharmony_ci        func_index, tier,
10361cb0ef41Sopenharmony_ci        tier == ExecutionTier::kLiftoff ? kForDebugging : kNoDebugging);
10371cb0ef41Sopenharmony_ci  }
10381cb0ef41Sopenharmony_ci
10391cb0ef41Sopenharmony_ci  bool Commit() {
10401cb0ef41Sopenharmony_ci    if (baseline_units_.empty() && tiering_units_.empty() &&
10411cb0ef41Sopenharmony_ci        js_to_wasm_wrapper_units_.empty()) {
10421cb0ef41Sopenharmony_ci      return false;
10431cb0ef41Sopenharmony_ci    }
10441cb0ef41Sopenharmony_ci    compilation_state()->CommitCompilationUnits(
10451cb0ef41Sopenharmony_ci        base::VectorOf(baseline_units_), base::VectorOf(tiering_units_),
10461cb0ef41Sopenharmony_ci        base::VectorOf(js_to_wasm_wrapper_units_));
10471cb0ef41Sopenharmony_ci    Clear();
10481cb0ef41Sopenharmony_ci    return true;
10491cb0ef41Sopenharmony_ci  }
10501cb0ef41Sopenharmony_ci
10511cb0ef41Sopenharmony_ci  void Clear() {
10521cb0ef41Sopenharmony_ci    baseline_units_.clear();
10531cb0ef41Sopenharmony_ci    tiering_units_.clear();
10541cb0ef41Sopenharmony_ci    js_to_wasm_wrapper_units_.clear();
10551cb0ef41Sopenharmony_ci  }
10561cb0ef41Sopenharmony_ci
10571cb0ef41Sopenharmony_ci  const WasmModule* module() { return native_module_->module(); }
10581cb0ef41Sopenharmony_ci
10591cb0ef41Sopenharmony_ci private:
10601cb0ef41Sopenharmony_ci  CompilationStateImpl* compilation_state() const {
10611cb0ef41Sopenharmony_ci    return Impl(native_module_->compilation_state());
10621cb0ef41Sopenharmony_ci  }
10631cb0ef41Sopenharmony_ci
10641cb0ef41Sopenharmony_ci  NativeModule* const native_module_;
10651cb0ef41Sopenharmony_ci  std::vector<WasmCompilationUnit> baseline_units_;
10661cb0ef41Sopenharmony_ci  std::vector<WasmCompilationUnit> tiering_units_;
10671cb0ef41Sopenharmony_ci  std::vector<std::shared_ptr<JSToWasmWrapperCompilationUnit>>
10681cb0ef41Sopenharmony_ci      js_to_wasm_wrapper_units_;
10691cb0ef41Sopenharmony_ci};
10701cb0ef41Sopenharmony_ci
10711cb0ef41Sopenharmony_civoid SetCompileError(ErrorThrower* thrower, ModuleWireBytes wire_bytes,
10721cb0ef41Sopenharmony_ci                     const WasmFunction* func, const WasmModule* module,
10731cb0ef41Sopenharmony_ci                     WasmError error) {
10741cb0ef41Sopenharmony_ci  WasmName name = wire_bytes.GetNameOrNull(func, module);
10751cb0ef41Sopenharmony_ci  if (name.begin() == nullptr) {
10761cb0ef41Sopenharmony_ci    thrower->CompileError("Compiling function #%d failed: %s @+%u",
10771cb0ef41Sopenharmony_ci                          func->func_index, error.message().c_str(),
10781cb0ef41Sopenharmony_ci                          error.offset());
10791cb0ef41Sopenharmony_ci  } else {
10801cb0ef41Sopenharmony_ci    TruncatedUserString<> truncated_name(name);
10811cb0ef41Sopenharmony_ci    thrower->CompileError("Compiling function #%d:\"%.*s\" failed: %s @+%u",
10821cb0ef41Sopenharmony_ci                          func->func_index, truncated_name.length(),
10831cb0ef41Sopenharmony_ci                          truncated_name.start(), error.message().c_str(),
10841cb0ef41Sopenharmony_ci                          error.offset());
10851cb0ef41Sopenharmony_ci  }
10861cb0ef41Sopenharmony_ci}
10871cb0ef41Sopenharmony_ci
10881cb0ef41Sopenharmony_ciDecodeResult ValidateSingleFunction(const WasmModule* module, int func_index,
10891cb0ef41Sopenharmony_ci                                    base::Vector<const uint8_t> code,
10901cb0ef41Sopenharmony_ci                                    Counters* counters,
10911cb0ef41Sopenharmony_ci                                    AccountingAllocator* allocator,
10921cb0ef41Sopenharmony_ci                                    WasmFeatures enabled_features) {
10931cb0ef41Sopenharmony_ci  const WasmFunction* func = &module->functions[func_index];
10941cb0ef41Sopenharmony_ci  FunctionBody body{func->sig, func->code.offset(), code.begin(), code.end()};
10951cb0ef41Sopenharmony_ci  DecodeResult result;
10961cb0ef41Sopenharmony_ci
10971cb0ef41Sopenharmony_ci  WasmFeatures detected;
10981cb0ef41Sopenharmony_ci  return VerifyWasmCode(allocator, enabled_features, module, &detected, body);
10991cb0ef41Sopenharmony_ci}
11001cb0ef41Sopenharmony_ci
11011cb0ef41Sopenharmony_cienum OnlyLazyFunctions : bool {
11021cb0ef41Sopenharmony_ci  kAllFunctions = false,
11031cb0ef41Sopenharmony_ci  kOnlyLazyFunctions = true,
11041cb0ef41Sopenharmony_ci};
11051cb0ef41Sopenharmony_ci
11061cb0ef41Sopenharmony_civoid ValidateSequentially(
11071cb0ef41Sopenharmony_ci    const WasmModule* module, NativeModule* native_module, Counters* counters,
11081cb0ef41Sopenharmony_ci    AccountingAllocator* allocator, ErrorThrower* thrower, bool lazy_module,
11091cb0ef41Sopenharmony_ci    OnlyLazyFunctions only_lazy_functions = kAllFunctions) {
11101cb0ef41Sopenharmony_ci  DCHECK(!thrower->error());
11111cb0ef41Sopenharmony_ci  uint32_t start = module->num_imported_functions;
11121cb0ef41Sopenharmony_ci  uint32_t end = start + module->num_declared_functions;
11131cb0ef41Sopenharmony_ci  auto enabled_features = native_module->enabled_features();
11141cb0ef41Sopenharmony_ci  for (uint32_t func_index = start; func_index < end; func_index++) {
11151cb0ef41Sopenharmony_ci    // Skip non-lazy functions if requested.
11161cb0ef41Sopenharmony_ci    if (only_lazy_functions) {
11171cb0ef41Sopenharmony_ci      CompileStrategy strategy =
11181cb0ef41Sopenharmony_ci          GetCompileStrategy(module, enabled_features, func_index, lazy_module);
11191cb0ef41Sopenharmony_ci      if (strategy != CompileStrategy::kLazy &&
11201cb0ef41Sopenharmony_ci          strategy != CompileStrategy::kLazyBaselineEagerTopTier) {
11211cb0ef41Sopenharmony_ci        continue;
11221cb0ef41Sopenharmony_ci      }
11231cb0ef41Sopenharmony_ci    }
11241cb0ef41Sopenharmony_ci
11251cb0ef41Sopenharmony_ci    ModuleWireBytes wire_bytes{native_module->wire_bytes()};
11261cb0ef41Sopenharmony_ci    const WasmFunction* func = &module->functions[func_index];
11271cb0ef41Sopenharmony_ci    base::Vector<const uint8_t> code = wire_bytes.GetFunctionBytes(func);
11281cb0ef41Sopenharmony_ci    DecodeResult result = ValidateSingleFunction(
11291cb0ef41Sopenharmony_ci        module, func_index, code, counters, allocator, enabled_features);
11301cb0ef41Sopenharmony_ci    if (result.failed()) {
11311cb0ef41Sopenharmony_ci      SetCompileError(thrower, wire_bytes, func, module, result.error());
11321cb0ef41Sopenharmony_ci    }
11331cb0ef41Sopenharmony_ci  }
11341cb0ef41Sopenharmony_ci}
11351cb0ef41Sopenharmony_ci
11361cb0ef41Sopenharmony_cibool IsLazyModule(const WasmModule* module) {
11371cb0ef41Sopenharmony_ci  return FLAG_wasm_lazy_compilation ||
11381cb0ef41Sopenharmony_ci         (FLAG_asm_wasm_lazy_compilation && is_asmjs_module(module));
11391cb0ef41Sopenharmony_ci}
11401cb0ef41Sopenharmony_ci
11411cb0ef41Sopenharmony_ci}  // namespace
11421cb0ef41Sopenharmony_ci
11431cb0ef41Sopenharmony_cibool CompileLazy(Isolate* isolate, Handle<WasmInstanceObject> instance,
11441cb0ef41Sopenharmony_ci                 int func_index) {
11451cb0ef41Sopenharmony_ci  Handle<WasmModuleObject> module_object(instance->module_object(), isolate);
11461cb0ef41Sopenharmony_ci  NativeModule* native_module = module_object->native_module();
11471cb0ef41Sopenharmony_ci  const WasmModule* module = native_module->module();
11481cb0ef41Sopenharmony_ci  auto enabled_features = native_module->enabled_features();
11491cb0ef41Sopenharmony_ci  Counters* counters = isolate->counters();
11501cb0ef41Sopenharmony_ci
11511cb0ef41Sopenharmony_ci  // Put the timer scope around everything, including the {CodeSpaceWriteScope}
11521cb0ef41Sopenharmony_ci  // and its destruction, to measure complete overhead (apart from the runtime
11531cb0ef41Sopenharmony_ci  // function itself, which has constant overhead).
11541cb0ef41Sopenharmony_ci  base::Optional<TimedHistogramScope> lazy_compile_time_scope;
11551cb0ef41Sopenharmony_ci  if (base::TimeTicks::IsHighResolution()) {
11561cb0ef41Sopenharmony_ci    lazy_compile_time_scope.emplace(counters->wasm_lazy_compile_time());
11571cb0ef41Sopenharmony_ci  }
11581cb0ef41Sopenharmony_ci
11591cb0ef41Sopenharmony_ci  DCHECK(!native_module->lazy_compile_frozen());
11601cb0ef41Sopenharmony_ci
11611cb0ef41Sopenharmony_ci  TRACE_LAZY("Compiling wasm-function#%d.\n", func_index);
11621cb0ef41Sopenharmony_ci
11631cb0ef41Sopenharmony_ci  base::ThreadTicks thread_ticks = base::ThreadTicks::IsSupported()
11641cb0ef41Sopenharmony_ci                                       ? base::ThreadTicks::Now()
11651cb0ef41Sopenharmony_ci                                       : base::ThreadTicks();
11661cb0ef41Sopenharmony_ci
11671cb0ef41Sopenharmony_ci  CompilationStateImpl* compilation_state =
11681cb0ef41Sopenharmony_ci      Impl(native_module->compilation_state());
11691cb0ef41Sopenharmony_ci  ExecutionTierPair tiers =
11701cb0ef41Sopenharmony_ci      GetRequestedExecutionTiers(native_module, enabled_features, func_index);
11711cb0ef41Sopenharmony_ci
11721cb0ef41Sopenharmony_ci  DCHECK_LE(native_module->num_imported_functions(), func_index);
11731cb0ef41Sopenharmony_ci  DCHECK_LT(func_index, native_module->num_functions());
11741cb0ef41Sopenharmony_ci  WasmCompilationUnit baseline_unit{func_index, tiers.baseline_tier,
11751cb0ef41Sopenharmony_ci                                    kNoDebugging};
11761cb0ef41Sopenharmony_ci  CompilationEnv env = native_module->CreateCompilationEnv();
11771cb0ef41Sopenharmony_ci  WasmEngine* engine = GetWasmEngine();
11781cb0ef41Sopenharmony_ci  WasmFeatures detected_features;
11791cb0ef41Sopenharmony_ci  WasmCompilationResult result = baseline_unit.ExecuteCompilation(
11801cb0ef41Sopenharmony_ci      &env, compilation_state->GetWireBytesStorage().get(), counters,
11811cb0ef41Sopenharmony_ci      &detected_features);
11821cb0ef41Sopenharmony_ci  compilation_state->OnCompilationStopped(detected_features);
11831cb0ef41Sopenharmony_ci  if (!thread_ticks.IsNull()) {
11841cb0ef41Sopenharmony_ci    native_module->UpdateCPUDuration(
11851cb0ef41Sopenharmony_ci        (base::ThreadTicks::Now() - thread_ticks).InMicroseconds(),
11861cb0ef41Sopenharmony_ci        tiers.baseline_tier);
11871cb0ef41Sopenharmony_ci  }
11881cb0ef41Sopenharmony_ci
11891cb0ef41Sopenharmony_ci  // During lazy compilation, we can only get compilation errors when
11901cb0ef41Sopenharmony_ci  // {--wasm-lazy-validation} is enabled. Otherwise, the module was fully
11911cb0ef41Sopenharmony_ci  // verified before starting its execution.
11921cb0ef41Sopenharmony_ci  CHECK_IMPLIES(result.failed(), FLAG_wasm_lazy_validation);
11931cb0ef41Sopenharmony_ci  const WasmFunction* func = &module->functions[func_index];
11941cb0ef41Sopenharmony_ci  if (result.failed()) {
11951cb0ef41Sopenharmony_ci    ErrorThrower thrower(isolate, nullptr);
11961cb0ef41Sopenharmony_ci    base::Vector<const uint8_t> code =
11971cb0ef41Sopenharmony_ci        compilation_state->GetWireBytesStorage()->GetCode(func->code);
11981cb0ef41Sopenharmony_ci    DecodeResult decode_result =
11991cb0ef41Sopenharmony_ci        ValidateSingleFunction(module, func_index, code, counters,
12001cb0ef41Sopenharmony_ci                               engine->allocator(), enabled_features);
12011cb0ef41Sopenharmony_ci    CHECK(decode_result.failed());
12021cb0ef41Sopenharmony_ci    SetCompileError(&thrower, ModuleWireBytes(native_module->wire_bytes()),
12031cb0ef41Sopenharmony_ci                    func, module, decode_result.error());
12041cb0ef41Sopenharmony_ci    return false;
12051cb0ef41Sopenharmony_ci  }
12061cb0ef41Sopenharmony_ci
12071cb0ef41Sopenharmony_ci  // Allocate feedback vector if needed.
12081cb0ef41Sopenharmony_ci  if (result.feedback_vector_slots > 0) {
12091cb0ef41Sopenharmony_ci    DCHECK(FLAG_wasm_speculative_inlining);
12101cb0ef41Sopenharmony_ci    Handle<FixedArray> vector = isolate->factory()->NewFixedArrayWithZeroes(
12111cb0ef41Sopenharmony_ci        result.feedback_vector_slots);
12121cb0ef41Sopenharmony_ci    instance->feedback_vectors().set(
12131cb0ef41Sopenharmony_ci        declared_function_index(module, func_index), *vector);
12141cb0ef41Sopenharmony_ci  }
12151cb0ef41Sopenharmony_ci
12161cb0ef41Sopenharmony_ci  WasmCodeRefScope code_ref_scope;
12171cb0ef41Sopenharmony_ci  WasmCode* code;
12181cb0ef41Sopenharmony_ci  {
12191cb0ef41Sopenharmony_ci    CodeSpaceWriteScope code_space_write_scope(native_module);
12201cb0ef41Sopenharmony_ci    code = native_module->PublishCode(
12211cb0ef41Sopenharmony_ci        native_module->AddCompiledCode(std::move(result)));
12221cb0ef41Sopenharmony_ci  }
12231cb0ef41Sopenharmony_ci  DCHECK_EQ(func_index, code->index());
12241cb0ef41Sopenharmony_ci
12251cb0ef41Sopenharmony_ci  if (WasmCode::ShouldBeLogged(isolate)) {
12261cb0ef41Sopenharmony_ci    DisallowGarbageCollection no_gc;
12271cb0ef41Sopenharmony_ci    Object url_obj = module_object->script().name();
12281cb0ef41Sopenharmony_ci    DCHECK(url_obj.IsString() || url_obj.IsUndefined());
12291cb0ef41Sopenharmony_ci    std::unique_ptr<char[]> url =
12301cb0ef41Sopenharmony_ci        url_obj.IsString() ? String::cast(url_obj).ToCString() : nullptr;
12311cb0ef41Sopenharmony_ci    code->LogCode(isolate, url.get(), module_object->script().id());
12321cb0ef41Sopenharmony_ci  }
12331cb0ef41Sopenharmony_ci
12341cb0ef41Sopenharmony_ci  counters->wasm_lazily_compiled_functions()->Increment();
12351cb0ef41Sopenharmony_ci
12361cb0ef41Sopenharmony_ci  const bool lazy_module = IsLazyModule(module);
12371cb0ef41Sopenharmony_ci  if (GetCompileStrategy(module, enabled_features, func_index, lazy_module) ==
12381cb0ef41Sopenharmony_ci          CompileStrategy::kLazy &&
12391cb0ef41Sopenharmony_ci      tiers.baseline_tier < tiers.top_tier) {
12401cb0ef41Sopenharmony_ci    WasmCompilationUnit tiering_unit{func_index, tiers.top_tier, kNoDebugging};
12411cb0ef41Sopenharmony_ci    compilation_state->CommitTopTierCompilationUnit(tiering_unit);
12421cb0ef41Sopenharmony_ci  }
12431cb0ef41Sopenharmony_ci
12441cb0ef41Sopenharmony_ci  return true;
12451cb0ef41Sopenharmony_ci}
12461cb0ef41Sopenharmony_ci
12471cb0ef41Sopenharmony_ciclass TransitiveTypeFeedbackProcessor {
12481cb0ef41Sopenharmony_ci public:
12491cb0ef41Sopenharmony_ci  TransitiveTypeFeedbackProcessor(const WasmModule* module,
12501cb0ef41Sopenharmony_ci                                  Handle<WasmInstanceObject> instance,
12511cb0ef41Sopenharmony_ci                                  int func_index)
12521cb0ef41Sopenharmony_ci      : instance_(instance),
12531cb0ef41Sopenharmony_ci        feedback_for_function_(module->type_feedback.feedback_for_function) {
12541cb0ef41Sopenharmony_ci    base::MutexGuard mutex_guard(&module->type_feedback.mutex);
12551cb0ef41Sopenharmony_ci    queue_.insert(func_index);
12561cb0ef41Sopenharmony_ci    while (!queue_.empty()) {
12571cb0ef41Sopenharmony_ci      auto next = queue_.cbegin();
12581cb0ef41Sopenharmony_ci      Process(*next);
12591cb0ef41Sopenharmony_ci      queue_.erase(next);
12601cb0ef41Sopenharmony_ci    }
12611cb0ef41Sopenharmony_ci  }
12621cb0ef41Sopenharmony_ci
12631cb0ef41Sopenharmony_ci private:
12641cb0ef41Sopenharmony_ci  void Process(int func_index);
12651cb0ef41Sopenharmony_ci
12661cb0ef41Sopenharmony_ci  void EnqueueCallees(std::vector<CallSiteFeedback> feedback) {
12671cb0ef41Sopenharmony_ci    for (size_t i = 0; i < feedback.size(); i++) {
12681cb0ef41Sopenharmony_ci      int func = feedback[i].function_index;
12691cb0ef41Sopenharmony_ci      // TODO(jkummerow): Find a way to get the target function ID for
12701cb0ef41Sopenharmony_ci      // direct calls (which currently requires decoding the function).
12711cb0ef41Sopenharmony_ci      if (func == -1) continue;
12721cb0ef41Sopenharmony_ci      // Don't spend time on calls that have never been executed.
12731cb0ef41Sopenharmony_ci      if (feedback[i].absolute_call_frequency == 0) continue;
12741cb0ef41Sopenharmony_ci      // Don't recompute feedback that has already been processed.
12751cb0ef41Sopenharmony_ci      auto existing = feedback_for_function_.find(func);
12761cb0ef41Sopenharmony_ci      if (existing != feedback_for_function_.end() &&
12771cb0ef41Sopenharmony_ci          existing->second.feedback_vector.size() > 0) {
12781cb0ef41Sopenharmony_ci        continue;
12791cb0ef41Sopenharmony_ci      }
12801cb0ef41Sopenharmony_ci      queue_.insert(func);
12811cb0ef41Sopenharmony_ci    }
12821cb0ef41Sopenharmony_ci  }
12831cb0ef41Sopenharmony_ci
12841cb0ef41Sopenharmony_ci  Handle<WasmInstanceObject> instance_;
12851cb0ef41Sopenharmony_ci  std::map<uint32_t, FunctionTypeFeedback>& feedback_for_function_;
12861cb0ef41Sopenharmony_ci  std::unordered_set<int> queue_;
12871cb0ef41Sopenharmony_ci};
12881cb0ef41Sopenharmony_ci
12891cb0ef41Sopenharmony_civoid TransitiveTypeFeedbackProcessor::Process(int func_index) {
12901cb0ef41Sopenharmony_ci  int which_vector = declared_function_index(instance_->module(), func_index);
12911cb0ef41Sopenharmony_ci  Object maybe_feedback = instance_->feedback_vectors().get(which_vector);
12921cb0ef41Sopenharmony_ci  if (!maybe_feedback.IsFixedArray()) return;
12931cb0ef41Sopenharmony_ci  FixedArray feedback = FixedArray::cast(maybe_feedback);
12941cb0ef41Sopenharmony_ci  std::vector<CallSiteFeedback> result(feedback.length() / 2);
12951cb0ef41Sopenharmony_ci  int imported_functions =
12961cb0ef41Sopenharmony_ci      static_cast<int>(instance_->module()->num_imported_functions);
12971cb0ef41Sopenharmony_ci  for (int i = 0; i < feedback.length(); i += 2) {
12981cb0ef41Sopenharmony_ci    Object value = feedback.get(i);
12991cb0ef41Sopenharmony_ci    if (value.IsWasmInternalFunction() &&
13001cb0ef41Sopenharmony_ci        WasmExportedFunction::IsWasmExportedFunction(
13011cb0ef41Sopenharmony_ci            WasmInternalFunction::cast(value).external())) {
13021cb0ef41Sopenharmony_ci      // Monomorphic, and the internal function points to a wasm-generated
13031cb0ef41Sopenharmony_ci      // external function (WasmExportedFunction). Mark the target for inlining
13041cb0ef41Sopenharmony_ci      // if it's defined in the same module.
13051cb0ef41Sopenharmony_ci      WasmExportedFunction target = WasmExportedFunction::cast(
13061cb0ef41Sopenharmony_ci          WasmInternalFunction::cast(value).external());
13071cb0ef41Sopenharmony_ci      if (target.instance() == *instance_ &&
13081cb0ef41Sopenharmony_ci          target.function_index() >= imported_functions) {
13091cb0ef41Sopenharmony_ci        if (FLAG_trace_wasm_speculative_inlining) {
13101cb0ef41Sopenharmony_ci          PrintF("[Function #%d call_ref #%d inlineable (monomorphic)]\n",
13111cb0ef41Sopenharmony_ci                 func_index, i / 2);
13121cb0ef41Sopenharmony_ci        }
13131cb0ef41Sopenharmony_ci        int32_t count = Smi::cast(feedback.get(i + 1)).value();
13141cb0ef41Sopenharmony_ci        result[i / 2] = {target.function_index(), count};
13151cb0ef41Sopenharmony_ci        continue;
13161cb0ef41Sopenharmony_ci      }
13171cb0ef41Sopenharmony_ci    } else if (value.IsFixedArray()) {
13181cb0ef41Sopenharmony_ci      // Polymorphic. Pick a target for inlining if there is one that was
13191cb0ef41Sopenharmony_ci      // seen for most calls, and matches the requirements of the monomorphic
13201cb0ef41Sopenharmony_ci      // case.
13211cb0ef41Sopenharmony_ci      FixedArray polymorphic = FixedArray::cast(value);
13221cb0ef41Sopenharmony_ci      size_t total_count = 0;
13231cb0ef41Sopenharmony_ci      for (int j = 0; j < polymorphic.length(); j += 2) {
13241cb0ef41Sopenharmony_ci        total_count += Smi::cast(polymorphic.get(j + 1)).value();
13251cb0ef41Sopenharmony_ci      }
13261cb0ef41Sopenharmony_ci      int found_target = -1;
13271cb0ef41Sopenharmony_ci      int found_count = -1;
13281cb0ef41Sopenharmony_ci      double best_frequency = 0;
13291cb0ef41Sopenharmony_ci      for (int j = 0; j < polymorphic.length(); j += 2) {
13301cb0ef41Sopenharmony_ci        int32_t this_count = Smi::cast(polymorphic.get(j + 1)).value();
13311cb0ef41Sopenharmony_ci        double frequency = static_cast<double>(this_count) / total_count;
13321cb0ef41Sopenharmony_ci        if (frequency > best_frequency) best_frequency = frequency;
13331cb0ef41Sopenharmony_ci        if (frequency < 0.8) continue;
13341cb0ef41Sopenharmony_ci
13351cb0ef41Sopenharmony_ci        // We reject this polymorphic entry if:
13361cb0ef41Sopenharmony_ci        // - it is not defined,
13371cb0ef41Sopenharmony_ci        // - it is not a wasm-defined function (WasmExportedFunction)
13381cb0ef41Sopenharmony_ci        // - it was not defined in this module.
13391cb0ef41Sopenharmony_ci        if (!polymorphic.get(j).IsWasmInternalFunction()) continue;
13401cb0ef41Sopenharmony_ci        WasmInternalFunction internal =
13411cb0ef41Sopenharmony_ci            WasmInternalFunction::cast(polymorphic.get(j));
13421cb0ef41Sopenharmony_ci        if (!WasmExportedFunction::IsWasmExportedFunction(
13431cb0ef41Sopenharmony_ci                internal.external())) {
13441cb0ef41Sopenharmony_ci          continue;
13451cb0ef41Sopenharmony_ci        }
13461cb0ef41Sopenharmony_ci        WasmExportedFunction target =
13471cb0ef41Sopenharmony_ci            WasmExportedFunction::cast(internal.external());
13481cb0ef41Sopenharmony_ci        if (target.instance() != *instance_ ||
13491cb0ef41Sopenharmony_ci            target.function_index() < imported_functions) {
13501cb0ef41Sopenharmony_ci          continue;
13511cb0ef41Sopenharmony_ci        }
13521cb0ef41Sopenharmony_ci
13531cb0ef41Sopenharmony_ci        found_target = target.function_index();
13541cb0ef41Sopenharmony_ci        found_count = static_cast<int>(this_count);
13551cb0ef41Sopenharmony_ci        if (FLAG_trace_wasm_speculative_inlining) {
13561cb0ef41Sopenharmony_ci          PrintF("[Function #%d call_ref #%d inlineable (polymorphic %f)]\n",
13571cb0ef41Sopenharmony_ci                 func_index, i / 2, frequency);
13581cb0ef41Sopenharmony_ci        }
13591cb0ef41Sopenharmony_ci        break;
13601cb0ef41Sopenharmony_ci      }
13611cb0ef41Sopenharmony_ci      if (found_target >= 0) {
13621cb0ef41Sopenharmony_ci        result[i / 2] = {found_target, found_count};
13631cb0ef41Sopenharmony_ci        continue;
13641cb0ef41Sopenharmony_ci      } else if (FLAG_trace_wasm_speculative_inlining) {
13651cb0ef41Sopenharmony_ci        PrintF("[Function #%d call_ref #%d: best frequency %f]\n", func_index,
13661cb0ef41Sopenharmony_ci               i / 2, best_frequency);
13671cb0ef41Sopenharmony_ci      }
13681cb0ef41Sopenharmony_ci    } else if (value.IsSmi()) {
13691cb0ef41Sopenharmony_ci      // Direct call, just collecting call count.
13701cb0ef41Sopenharmony_ci      int count = Smi::cast(value).value();
13711cb0ef41Sopenharmony_ci      if (FLAG_trace_wasm_speculative_inlining) {
13721cb0ef41Sopenharmony_ci        PrintF("[Function #%d call_direct #%d: frequency %d]\n", func_index,
13731cb0ef41Sopenharmony_ci               i / 2, count);
13741cb0ef41Sopenharmony_ci      }
13751cb0ef41Sopenharmony_ci      result[i / 2] = {-1, count};
13761cb0ef41Sopenharmony_ci      continue;
13771cb0ef41Sopenharmony_ci    }
13781cb0ef41Sopenharmony_ci    // If we fall through to here, then this call isn't eligible for inlining.
13791cb0ef41Sopenharmony_ci    // Possible reasons: uninitialized or megamorphic feedback; or monomorphic
13801cb0ef41Sopenharmony_ci    // or polymorphic that didn't meet our requirements.
13811cb0ef41Sopenharmony_ci    if (FLAG_trace_wasm_speculative_inlining) {
13821cb0ef41Sopenharmony_ci      PrintF("[Function #%d call_ref #%d *not* inlineable]\n", func_index,
13831cb0ef41Sopenharmony_ci             i / 2);
13841cb0ef41Sopenharmony_ci    }
13851cb0ef41Sopenharmony_ci    result[i / 2] = {-1, -1};
13861cb0ef41Sopenharmony_ci  }
13871cb0ef41Sopenharmony_ci  EnqueueCallees(result);
13881cb0ef41Sopenharmony_ci  feedback_for_function_[func_index].feedback_vector = std::move(result);
13891cb0ef41Sopenharmony_ci}
13901cb0ef41Sopenharmony_ci
13911cb0ef41Sopenharmony_civoid TriggerTierUp(Isolate* isolate, NativeModule* native_module,
13921cb0ef41Sopenharmony_ci                   int func_index, Handle<WasmInstanceObject> instance) {
13931cb0ef41Sopenharmony_ci  CompilationStateImpl* compilation_state =
13941cb0ef41Sopenharmony_ci      Impl(native_module->compilation_state());
13951cb0ef41Sopenharmony_ci  WasmCompilationUnit tiering_unit{func_index, ExecutionTier::kTurbofan,
13961cb0ef41Sopenharmony_ci                                   kNoDebugging};
13971cb0ef41Sopenharmony_ci
13981cb0ef41Sopenharmony_ci  const WasmModule* module = native_module->module();
13991cb0ef41Sopenharmony_ci  size_t priority;
14001cb0ef41Sopenharmony_ci  {
14011cb0ef41Sopenharmony_ci    base::MutexGuard mutex_guard(&module->type_feedback.mutex);
14021cb0ef41Sopenharmony_ci    int saved_priority =
14031cb0ef41Sopenharmony_ci        module->type_feedback.feedback_for_function[func_index].tierup_priority;
14041cb0ef41Sopenharmony_ci    saved_priority++;
14051cb0ef41Sopenharmony_ci    module->type_feedback.feedback_for_function[func_index].tierup_priority =
14061cb0ef41Sopenharmony_ci        saved_priority;
14071cb0ef41Sopenharmony_ci    // Continue to creating a compilation unit if this is the first time
14081cb0ef41Sopenharmony_ci    // we detect this function as hot, and create a new higher-priority unit
14091cb0ef41Sopenharmony_ci    // if the number of tierup checks is a power of two (at least 4).
14101cb0ef41Sopenharmony_ci    if (saved_priority > 1 &&
14111cb0ef41Sopenharmony_ci        (saved_priority < 4 || (saved_priority & (saved_priority - 1)) != 0)) {
14121cb0ef41Sopenharmony_ci      return;
14131cb0ef41Sopenharmony_ci    }
14141cb0ef41Sopenharmony_ci    priority = saved_priority;
14151cb0ef41Sopenharmony_ci  }
14161cb0ef41Sopenharmony_ci  if (FLAG_wasm_speculative_inlining) {
14171cb0ef41Sopenharmony_ci    // TODO(jkummerow): we could have collisions here if different instances
14181cb0ef41Sopenharmony_ci    // of the same module have collected different feedback. If that ever
14191cb0ef41Sopenharmony_ci    // becomes a problem, figure out a solution.
14201cb0ef41Sopenharmony_ci    TransitiveTypeFeedbackProcessor process(module, instance, func_index);
14211cb0ef41Sopenharmony_ci  }
14221cb0ef41Sopenharmony_ci
14231cb0ef41Sopenharmony_ci  compilation_state->AddTopTierPriorityCompilationUnit(tiering_unit, priority);
14241cb0ef41Sopenharmony_ci}
14251cb0ef41Sopenharmony_ci
14261cb0ef41Sopenharmony_cinamespace {
14271cb0ef41Sopenharmony_ci
14281cb0ef41Sopenharmony_civoid RecordStats(const Code code, Counters* counters) {
14291cb0ef41Sopenharmony_ci  counters->wasm_generated_code_size()->Increment(code.raw_body_size());
14301cb0ef41Sopenharmony_ci  counters->wasm_reloc_size()->Increment(code.relocation_info().length());
14311cb0ef41Sopenharmony_ci}
14321cb0ef41Sopenharmony_ci
14331cb0ef41Sopenharmony_cienum CompilationExecutionResult : int8_t { kNoMoreUnits, kYield };
14341cb0ef41Sopenharmony_ci
14351cb0ef41Sopenharmony_ciCompilationExecutionResult ExecuteJSToWasmWrapperCompilationUnits(
14361cb0ef41Sopenharmony_ci    std::weak_ptr<NativeModule> native_module, JobDelegate* delegate) {
14371cb0ef41Sopenharmony_ci  std::shared_ptr<JSToWasmWrapperCompilationUnit> wrapper_unit = nullptr;
14381cb0ef41Sopenharmony_ci  int num_processed_wrappers = 0;
14391cb0ef41Sopenharmony_ci
14401cb0ef41Sopenharmony_ci  OperationsBarrier::Token wrapper_compilation_token;
14411cb0ef41Sopenharmony_ci  Isolate* isolate;
14421cb0ef41Sopenharmony_ci
14431cb0ef41Sopenharmony_ci  {
14441cb0ef41Sopenharmony_ci    BackgroundCompileScope compile_scope(native_module);
14451cb0ef41Sopenharmony_ci    if (compile_scope.cancelled()) return kYield;
14461cb0ef41Sopenharmony_ci    wrapper_unit = compile_scope.compilation_state()
14471cb0ef41Sopenharmony_ci                       ->GetNextJSToWasmWrapperCompilationUnit();
14481cb0ef41Sopenharmony_ci    if (!wrapper_unit) return kNoMoreUnits;
14491cb0ef41Sopenharmony_ci    isolate = wrapper_unit->isolate();
14501cb0ef41Sopenharmony_ci    wrapper_compilation_token =
14511cb0ef41Sopenharmony_ci        wasm::GetWasmEngine()->StartWrapperCompilation(isolate);
14521cb0ef41Sopenharmony_ci    if (!wrapper_compilation_token) return kNoMoreUnits;
14531cb0ef41Sopenharmony_ci  }
14541cb0ef41Sopenharmony_ci
14551cb0ef41Sopenharmony_ci  TRACE_EVENT0("v8.wasm", "wasm.JSToWasmWrapperCompilation");
14561cb0ef41Sopenharmony_ci  while (true) {
14571cb0ef41Sopenharmony_ci    DCHECK_EQ(isolate, wrapper_unit->isolate());
14581cb0ef41Sopenharmony_ci    wrapper_unit->Execute();
14591cb0ef41Sopenharmony_ci    ++num_processed_wrappers;
14601cb0ef41Sopenharmony_ci    bool yield = delegate && delegate->ShouldYield();
14611cb0ef41Sopenharmony_ci    BackgroundCompileScope compile_scope(native_module);
14621cb0ef41Sopenharmony_ci    if (compile_scope.cancelled()) return kYield;
14631cb0ef41Sopenharmony_ci    if (yield ||
14641cb0ef41Sopenharmony_ci        !(wrapper_unit = compile_scope.compilation_state()
14651cb0ef41Sopenharmony_ci                             ->GetNextJSToWasmWrapperCompilationUnit())) {
14661cb0ef41Sopenharmony_ci      compile_scope.compilation_state()->OnFinishedJSToWasmWrapperUnits(
14671cb0ef41Sopenharmony_ci          num_processed_wrappers);
14681cb0ef41Sopenharmony_ci      return yield ? kYield : kNoMoreUnits;
14691cb0ef41Sopenharmony_ci    }
14701cb0ef41Sopenharmony_ci  }
14711cb0ef41Sopenharmony_ci}
14721cb0ef41Sopenharmony_ci
14731cb0ef41Sopenharmony_cinamespace {
14741cb0ef41Sopenharmony_ciconst char* GetCompilationEventName(const WasmCompilationUnit& unit,
14751cb0ef41Sopenharmony_ci                                    const CompilationEnv& env) {
14761cb0ef41Sopenharmony_ci  ExecutionTier tier = unit.tier();
14771cb0ef41Sopenharmony_ci  if (tier == ExecutionTier::kLiftoff) {
14781cb0ef41Sopenharmony_ci    return "wasm.BaselineCompilation";
14791cb0ef41Sopenharmony_ci  }
14801cb0ef41Sopenharmony_ci  if (tier == ExecutionTier::kTurbofan) {
14811cb0ef41Sopenharmony_ci    return "wasm.TopTierCompilation";
14821cb0ef41Sopenharmony_ci  }
14831cb0ef41Sopenharmony_ci  if (unit.func_index() <
14841cb0ef41Sopenharmony_ci      static_cast<int>(env.module->num_imported_functions)) {
14851cb0ef41Sopenharmony_ci    return "wasm.WasmToJSWrapperCompilation";
14861cb0ef41Sopenharmony_ci  }
14871cb0ef41Sopenharmony_ci  return "wasm.OtherCompilation";
14881cb0ef41Sopenharmony_ci}
14891cb0ef41Sopenharmony_ci}  // namespace
14901cb0ef41Sopenharmony_ci
14911cb0ef41Sopenharmony_ciconstexpr uint8_t kMainTaskId = 0;
14921cb0ef41Sopenharmony_ci
14931cb0ef41Sopenharmony_ci// Run by the {BackgroundCompileJob} (on any thread).
14941cb0ef41Sopenharmony_ciCompilationExecutionResult ExecuteCompilationUnits(
14951cb0ef41Sopenharmony_ci    std::weak_ptr<NativeModule> native_module, Counters* counters,
14961cb0ef41Sopenharmony_ci    JobDelegate* delegate, CompileBaselineOnly baseline_only) {
14971cb0ef41Sopenharmony_ci  TRACE_EVENT0("v8.wasm", "wasm.ExecuteCompilationUnits");
14981cb0ef41Sopenharmony_ci
14991cb0ef41Sopenharmony_ci  // Execute JS to Wasm wrapper units first, so that they are ready to be
15001cb0ef41Sopenharmony_ci  // finalized by the main thread when the kFinishedBaselineCompilation event is
15011cb0ef41Sopenharmony_ci  // triggered.
15021cb0ef41Sopenharmony_ci  if (ExecuteJSToWasmWrapperCompilationUnits(native_module, delegate) ==
15031cb0ef41Sopenharmony_ci      kYield) {
15041cb0ef41Sopenharmony_ci    return kYield;
15051cb0ef41Sopenharmony_ci  }
15061cb0ef41Sopenharmony_ci
15071cb0ef41Sopenharmony_ci  // These fields are initialized in a {BackgroundCompileScope} before
15081cb0ef41Sopenharmony_ci  // starting compilation.
15091cb0ef41Sopenharmony_ci  base::Optional<CompilationEnv> env;
15101cb0ef41Sopenharmony_ci  std::shared_ptr<WireBytesStorage> wire_bytes;
15111cb0ef41Sopenharmony_ci  std::shared_ptr<const WasmModule> module;
15121cb0ef41Sopenharmony_ci  // Task 0 is any main thread (there might be multiple from multiple isolates),
15131cb0ef41Sopenharmony_ci  // worker threads start at 1 (thus the "+ 1").
15141cb0ef41Sopenharmony_ci  STATIC_ASSERT(kMainTaskId == 0);
15151cb0ef41Sopenharmony_ci  int task_id = delegate ? (int{delegate->GetTaskId()} + 1) : kMainTaskId;
15161cb0ef41Sopenharmony_ci  DCHECK_LE(0, task_id);
15171cb0ef41Sopenharmony_ci  CompilationUnitQueues::Queue* queue;
15181cb0ef41Sopenharmony_ci  base::Optional<WasmCompilationUnit> unit;
15191cb0ef41Sopenharmony_ci
15201cb0ef41Sopenharmony_ci  WasmFeatures detected_features = WasmFeatures::None();
15211cb0ef41Sopenharmony_ci
15221cb0ef41Sopenharmony_ci  base::ThreadTicks thread_ticks = base::ThreadTicks::IsSupported()
15231cb0ef41Sopenharmony_ci                                       ? base::ThreadTicks::Now()
15241cb0ef41Sopenharmony_ci                                       : base::ThreadTicks();
15251cb0ef41Sopenharmony_ci
15261cb0ef41Sopenharmony_ci  // Preparation (synchronized): Initialize the fields above and get the first
15271cb0ef41Sopenharmony_ci  // compilation unit.
15281cb0ef41Sopenharmony_ci  {
15291cb0ef41Sopenharmony_ci    BackgroundCompileScope compile_scope(native_module);
15301cb0ef41Sopenharmony_ci    if (compile_scope.cancelled()) return kYield;
15311cb0ef41Sopenharmony_ci    env.emplace(compile_scope.native_module()->CreateCompilationEnv());
15321cb0ef41Sopenharmony_ci    wire_bytes = compile_scope.compilation_state()->GetWireBytesStorage();
15331cb0ef41Sopenharmony_ci    module = compile_scope.native_module()->shared_module();
15341cb0ef41Sopenharmony_ci    queue = compile_scope.compilation_state()->GetQueueForCompileTask(task_id);
15351cb0ef41Sopenharmony_ci    unit = compile_scope.compilation_state()->GetNextCompilationUnit(
15361cb0ef41Sopenharmony_ci        queue, baseline_only);
15371cb0ef41Sopenharmony_ci    if (!unit) return kNoMoreUnits;
15381cb0ef41Sopenharmony_ci  }
15391cb0ef41Sopenharmony_ci  TRACE_COMPILE("ExecuteCompilationUnits (task id %d)\n", task_id);
15401cb0ef41Sopenharmony_ci
15411cb0ef41Sopenharmony_ci  std::vector<WasmCompilationResult> results_to_publish;
15421cb0ef41Sopenharmony_ci  while (true) {
15431cb0ef41Sopenharmony_ci    ExecutionTier current_tier = unit->tier();
15441cb0ef41Sopenharmony_ci    const char* event_name = GetCompilationEventName(unit.value(), env.value());
15451cb0ef41Sopenharmony_ci    TRACE_EVENT0("v8.wasm", event_name);
15461cb0ef41Sopenharmony_ci    while (unit->tier() == current_tier) {
15471cb0ef41Sopenharmony_ci      // (asynchronous): Execute the compilation.
15481cb0ef41Sopenharmony_ci      WasmCompilationResult result = unit->ExecuteCompilation(
15491cb0ef41Sopenharmony_ci          &env.value(), wire_bytes.get(), counters, &detected_features);
15501cb0ef41Sopenharmony_ci      results_to_publish.emplace_back(std::move(result));
15511cb0ef41Sopenharmony_ci
15521cb0ef41Sopenharmony_ci      bool yield = delegate && delegate->ShouldYield();
15531cb0ef41Sopenharmony_ci
15541cb0ef41Sopenharmony_ci      // (synchronized): Publish the compilation result and get the next unit.
15551cb0ef41Sopenharmony_ci      BackgroundCompileScope compile_scope(native_module);
15561cb0ef41Sopenharmony_ci      if (compile_scope.cancelled()) return kYield;
15571cb0ef41Sopenharmony_ci
15581cb0ef41Sopenharmony_ci      if (!results_to_publish.back().succeeded()) {
15591cb0ef41Sopenharmony_ci        compile_scope.compilation_state()->SetError();
15601cb0ef41Sopenharmony_ci        return kNoMoreUnits;
15611cb0ef41Sopenharmony_ci      }
15621cb0ef41Sopenharmony_ci
15631cb0ef41Sopenharmony_ci      if (!unit->for_debugging() && result.result_tier != current_tier) {
15641cb0ef41Sopenharmony_ci        compile_scope.native_module()->AddLiftoffBailout();
15651cb0ef41Sopenharmony_ci      }
15661cb0ef41Sopenharmony_ci
15671cb0ef41Sopenharmony_ci      // Yield or get next unit.
15681cb0ef41Sopenharmony_ci      if (yield ||
15691cb0ef41Sopenharmony_ci          !(unit = compile_scope.compilation_state()->GetNextCompilationUnit(
15701cb0ef41Sopenharmony_ci                queue, baseline_only))) {
15711cb0ef41Sopenharmony_ci        if (!thread_ticks.IsNull()) {
15721cb0ef41Sopenharmony_ci          compile_scope.native_module()->UpdateCPUDuration(
15731cb0ef41Sopenharmony_ci              (base::ThreadTicks::Now() - thread_ticks).InMicroseconds(),
15741cb0ef41Sopenharmony_ci              current_tier);
15751cb0ef41Sopenharmony_ci        }
15761cb0ef41Sopenharmony_ci        std::vector<std::unique_ptr<WasmCode>> unpublished_code =
15771cb0ef41Sopenharmony_ci            compile_scope.native_module()->AddCompiledCode(
15781cb0ef41Sopenharmony_ci                base::VectorOf(std::move(results_to_publish)));
15791cb0ef41Sopenharmony_ci        results_to_publish.clear();
15801cb0ef41Sopenharmony_ci        compile_scope.compilation_state()->SchedulePublishCompilationResults(
15811cb0ef41Sopenharmony_ci            std::move(unpublished_code));
15821cb0ef41Sopenharmony_ci        compile_scope.compilation_state()->OnCompilationStopped(
15831cb0ef41Sopenharmony_ci            detected_features);
15841cb0ef41Sopenharmony_ci        return yield ? kYield : kNoMoreUnits;
15851cb0ef41Sopenharmony_ci      }
15861cb0ef41Sopenharmony_ci
15871cb0ef41Sopenharmony_ci      // Publish after finishing a certain amount of units, to avoid contention
15881cb0ef41Sopenharmony_ci      // when all threads publish at the end.
15891cb0ef41Sopenharmony_ci      bool batch_full =
15901cb0ef41Sopenharmony_ci          queue->ShouldPublish(static_cast<int>(results_to_publish.size()));
15911cb0ef41Sopenharmony_ci      // Also publish each time the compilation tier changes from Liftoff to
15921cb0ef41Sopenharmony_ci      // TurboFan, such that we immediately publish the baseline compilation
15931cb0ef41Sopenharmony_ci      // results to start execution, and do not wait for a batch to fill up.
15941cb0ef41Sopenharmony_ci      bool liftoff_finished = unit->tier() != current_tier &&
15951cb0ef41Sopenharmony_ci                              unit->tier() == ExecutionTier::kTurbofan;
15961cb0ef41Sopenharmony_ci      if (batch_full || liftoff_finished) {
15971cb0ef41Sopenharmony_ci        if (!thread_ticks.IsNull()) {
15981cb0ef41Sopenharmony_ci          base::ThreadTicks thread_ticks_now = base::ThreadTicks::Now();
15991cb0ef41Sopenharmony_ci          compile_scope.native_module()->UpdateCPUDuration(
16001cb0ef41Sopenharmony_ci              (thread_ticks_now - thread_ticks).InMicroseconds(), current_tier);
16011cb0ef41Sopenharmony_ci          thread_ticks = thread_ticks_now;
16021cb0ef41Sopenharmony_ci        }
16031cb0ef41Sopenharmony_ci        std::vector<std::unique_ptr<WasmCode>> unpublished_code =
16041cb0ef41Sopenharmony_ci            compile_scope.native_module()->AddCompiledCode(
16051cb0ef41Sopenharmony_ci                base::VectorOf(std::move(results_to_publish)));
16061cb0ef41Sopenharmony_ci        results_to_publish.clear();
16071cb0ef41Sopenharmony_ci        compile_scope.compilation_state()->SchedulePublishCompilationResults(
16081cb0ef41Sopenharmony_ci            std::move(unpublished_code));
16091cb0ef41Sopenharmony_ci      }
16101cb0ef41Sopenharmony_ci    }
16111cb0ef41Sopenharmony_ci  }
16121cb0ef41Sopenharmony_ci  UNREACHABLE();
16131cb0ef41Sopenharmony_ci}
16141cb0ef41Sopenharmony_ci
16151cb0ef41Sopenharmony_ciusing JSToWasmWrapperKey = std::pair<bool, FunctionSig>;
16161cb0ef41Sopenharmony_ci
16171cb0ef41Sopenharmony_ci// Returns the number of units added.
16181cb0ef41Sopenharmony_ciint AddExportWrapperUnits(Isolate* isolate, NativeModule* native_module,
16191cb0ef41Sopenharmony_ci                          CompilationUnitBuilder* builder) {
16201cb0ef41Sopenharmony_ci  std::unordered_set<JSToWasmWrapperKey, base::hash<JSToWasmWrapperKey>> keys;
16211cb0ef41Sopenharmony_ci  for (auto exp : native_module->module()->export_table) {
16221cb0ef41Sopenharmony_ci    if (exp.kind != kExternalFunction) continue;
16231cb0ef41Sopenharmony_ci    auto& function = native_module->module()->functions[exp.index];
16241cb0ef41Sopenharmony_ci    JSToWasmWrapperKey key(function.imported, *function.sig);
16251cb0ef41Sopenharmony_ci    if (keys.insert(key).second) {
16261cb0ef41Sopenharmony_ci      auto unit = std::make_shared<JSToWasmWrapperCompilationUnit>(
16271cb0ef41Sopenharmony_ci          isolate, function.sig, native_module->module(), function.imported,
16281cb0ef41Sopenharmony_ci          native_module->enabled_features(),
16291cb0ef41Sopenharmony_ci          JSToWasmWrapperCompilationUnit::kAllowGeneric);
16301cb0ef41Sopenharmony_ci      builder->AddJSToWasmWrapperUnit(std::move(unit));
16311cb0ef41Sopenharmony_ci    }
16321cb0ef41Sopenharmony_ci  }
16331cb0ef41Sopenharmony_ci
16341cb0ef41Sopenharmony_ci  return static_cast<int>(keys.size());
16351cb0ef41Sopenharmony_ci}
16361cb0ef41Sopenharmony_ci
16371cb0ef41Sopenharmony_ci// Returns the number of units added.
16381cb0ef41Sopenharmony_ciint AddImportWrapperUnits(NativeModule* native_module,
16391cb0ef41Sopenharmony_ci                          CompilationUnitBuilder* builder) {
16401cb0ef41Sopenharmony_ci  std::unordered_set<WasmImportWrapperCache::CacheKey,
16411cb0ef41Sopenharmony_ci                     WasmImportWrapperCache::CacheKeyHash>
16421cb0ef41Sopenharmony_ci      keys;
16431cb0ef41Sopenharmony_ci  int num_imported_functions = native_module->num_imported_functions();
16441cb0ef41Sopenharmony_ci  for (int func_index = 0; func_index < num_imported_functions; func_index++) {
16451cb0ef41Sopenharmony_ci    const FunctionSig* sig = native_module->module()->functions[func_index].sig;
16461cb0ef41Sopenharmony_ci    if (!IsJSCompatibleSignature(sig, native_module->module(),
16471cb0ef41Sopenharmony_ci                                 native_module->enabled_features())) {
16481cb0ef41Sopenharmony_ci      continue;
16491cb0ef41Sopenharmony_ci    }
16501cb0ef41Sopenharmony_ci    WasmImportWrapperCache::CacheKey key(
16511cb0ef41Sopenharmony_ci        compiler::kDefaultImportCallKind, sig,
16521cb0ef41Sopenharmony_ci        static_cast<int>(sig->parameter_count()), kNoSuspend);
16531cb0ef41Sopenharmony_ci    auto it = keys.insert(key);
16541cb0ef41Sopenharmony_ci    if (it.second) {
16551cb0ef41Sopenharmony_ci      // Ensure that all keys exist in the cache, so that we can populate the
16561cb0ef41Sopenharmony_ci      // cache later without locking.
16571cb0ef41Sopenharmony_ci      (*native_module->import_wrapper_cache())[key] = nullptr;
16581cb0ef41Sopenharmony_ci      builder->AddUnits(func_index);
16591cb0ef41Sopenharmony_ci    }
16601cb0ef41Sopenharmony_ci  }
16611cb0ef41Sopenharmony_ci  return static_cast<int>(keys.size());
16621cb0ef41Sopenharmony_ci}
16631cb0ef41Sopenharmony_ci
16641cb0ef41Sopenharmony_civoid InitializeLazyCompilation(NativeModule* native_module) {
16651cb0ef41Sopenharmony_ci  const bool lazy_module = IsLazyModule(native_module->module());
16661cb0ef41Sopenharmony_ci  auto* module = native_module->module();
16671cb0ef41Sopenharmony_ci
16681cb0ef41Sopenharmony_ci  uint32_t start = module->num_imported_functions;
16691cb0ef41Sopenharmony_ci  uint32_t end = start + module->num_declared_functions;
16701cb0ef41Sopenharmony_ci  base::Optional<CodeSpaceWriteScope> lazy_code_space_write_scope;
16711cb0ef41Sopenharmony_ci  for (uint32_t func_index = start; func_index < end; func_index++) {
16721cb0ef41Sopenharmony_ci    CompileStrategy strategy = GetCompileStrategy(
16731cb0ef41Sopenharmony_ci        module, native_module->enabled_features(), func_index, lazy_module);
16741cb0ef41Sopenharmony_ci    if (strategy == CompileStrategy::kLazy ||
16751cb0ef41Sopenharmony_ci        strategy == CompileStrategy::kLazyBaselineEagerTopTier) {
16761cb0ef41Sopenharmony_ci      // Open a single scope for all following calls to {UseLazyStub()}, instead
16771cb0ef41Sopenharmony_ci      // of flipping page permissions for each {func_index} individually.
16781cb0ef41Sopenharmony_ci      if (!lazy_code_space_write_scope.has_value()) {
16791cb0ef41Sopenharmony_ci        lazy_code_space_write_scope.emplace(native_module);
16801cb0ef41Sopenharmony_ci      }
16811cb0ef41Sopenharmony_ci      native_module->UseLazyStub(func_index);
16821cb0ef41Sopenharmony_ci    }
16831cb0ef41Sopenharmony_ci  }
16841cb0ef41Sopenharmony_ci}
16851cb0ef41Sopenharmony_ci
16861cb0ef41Sopenharmony_cistd::unique_ptr<CompilationUnitBuilder> InitializeCompilation(
16871cb0ef41Sopenharmony_ci    Isolate* isolate, NativeModule* native_module) {
16881cb0ef41Sopenharmony_ci  InitializeLazyCompilation(native_module);
16891cb0ef41Sopenharmony_ci  CompilationStateImpl* compilation_state =
16901cb0ef41Sopenharmony_ci      Impl(native_module->compilation_state());
16911cb0ef41Sopenharmony_ci  const bool lazy_module = IsLazyModule(native_module->module());
16921cb0ef41Sopenharmony_ci  auto builder = std::make_unique<CompilationUnitBuilder>(native_module);
16931cb0ef41Sopenharmony_ci  int num_import_wrappers = AddImportWrapperUnits(native_module, builder.get());
16941cb0ef41Sopenharmony_ci  int num_export_wrappers =
16951cb0ef41Sopenharmony_ci      AddExportWrapperUnits(isolate, native_module, builder.get());
16961cb0ef41Sopenharmony_ci  compilation_state->InitializeCompilationProgress(
16971cb0ef41Sopenharmony_ci      lazy_module, num_import_wrappers, num_export_wrappers);
16981cb0ef41Sopenharmony_ci  return builder;
16991cb0ef41Sopenharmony_ci}
17001cb0ef41Sopenharmony_ci
17011cb0ef41Sopenharmony_cibool MayCompriseLazyFunctions(const WasmModule* module,
17021cb0ef41Sopenharmony_ci                              const WasmFeatures& enabled_features,
17031cb0ef41Sopenharmony_ci                              bool lazy_module) {
17041cb0ef41Sopenharmony_ci  if (lazy_module || enabled_features.has_compilation_hints()) return true;
17051cb0ef41Sopenharmony_ci#ifdef ENABLE_SLOW_DCHECKS
17061cb0ef41Sopenharmony_ci  int start = module->num_imported_functions;
17071cb0ef41Sopenharmony_ci  int end = start + module->num_declared_functions;
17081cb0ef41Sopenharmony_ci  for (int func_index = start; func_index < end; func_index++) {
17091cb0ef41Sopenharmony_ci    SLOW_DCHECK(GetCompileStrategy(module, enabled_features, func_index,
17101cb0ef41Sopenharmony_ci                                   lazy_module) != CompileStrategy::kLazy);
17111cb0ef41Sopenharmony_ci  }
17121cb0ef41Sopenharmony_ci#endif
17131cb0ef41Sopenharmony_ci  return false;
17141cb0ef41Sopenharmony_ci}
17151cb0ef41Sopenharmony_ci
17161cb0ef41Sopenharmony_ciclass CompilationTimeCallback : public CompilationEventCallback {
17171cb0ef41Sopenharmony_ci public:
17181cb0ef41Sopenharmony_ci  enum CompileMode { kSynchronous, kAsync, kStreaming };
17191cb0ef41Sopenharmony_ci  explicit CompilationTimeCallback(
17201cb0ef41Sopenharmony_ci      std::shared_ptr<Counters> async_counters,
17211cb0ef41Sopenharmony_ci      std::shared_ptr<metrics::Recorder> metrics_recorder,
17221cb0ef41Sopenharmony_ci      v8::metrics::Recorder::ContextId context_id,
17231cb0ef41Sopenharmony_ci      std::weak_ptr<NativeModule> native_module, CompileMode compile_mode)
17241cb0ef41Sopenharmony_ci      : start_time_(base::TimeTicks::Now()),
17251cb0ef41Sopenharmony_ci        async_counters_(std::move(async_counters)),
17261cb0ef41Sopenharmony_ci        metrics_recorder_(std::move(metrics_recorder)),
17271cb0ef41Sopenharmony_ci        context_id_(context_id),
17281cb0ef41Sopenharmony_ci        native_module_(std::move(native_module)),
17291cb0ef41Sopenharmony_ci        compile_mode_(compile_mode) {}
17301cb0ef41Sopenharmony_ci
17311cb0ef41Sopenharmony_ci  // Keep this callback alive to be able to record caching metrics.
17321cb0ef41Sopenharmony_ci  ReleaseAfterFinalEvent release_after_final_event() override {
17331cb0ef41Sopenharmony_ci    return CompilationEventCallback::ReleaseAfterFinalEvent::kKeep;
17341cb0ef41Sopenharmony_ci  }
17351cb0ef41Sopenharmony_ci
17361cb0ef41Sopenharmony_ci  void call(CompilationEvent compilation_event) override {
17371cb0ef41Sopenharmony_ci    DCHECK(base::TimeTicks::IsHighResolution());
17381cb0ef41Sopenharmony_ci    std::shared_ptr<NativeModule> native_module = native_module_.lock();
17391cb0ef41Sopenharmony_ci    if (!native_module) return;
17401cb0ef41Sopenharmony_ci    auto now = base::TimeTicks::Now();
17411cb0ef41Sopenharmony_ci    auto duration = now - start_time_;
17421cb0ef41Sopenharmony_ci    if (compilation_event == CompilationEvent::kFinishedBaselineCompilation) {
17431cb0ef41Sopenharmony_ci      // Reset {start_time_} to measure tier-up time.
17441cb0ef41Sopenharmony_ci      start_time_ = now;
17451cb0ef41Sopenharmony_ci      if (compile_mode_ != kSynchronous) {
17461cb0ef41Sopenharmony_ci        TimedHistogram* histogram =
17471cb0ef41Sopenharmony_ci            compile_mode_ == kAsync
17481cb0ef41Sopenharmony_ci                ? async_counters_->wasm_async_compile_wasm_module_time()
17491cb0ef41Sopenharmony_ci                : async_counters_->wasm_streaming_compile_wasm_module_time();
17501cb0ef41Sopenharmony_ci        histogram->AddSample(static_cast<int>(duration.InMicroseconds()));
17511cb0ef41Sopenharmony_ci      }
17521cb0ef41Sopenharmony_ci
17531cb0ef41Sopenharmony_ci      v8::metrics::WasmModuleCompiled event{
17541cb0ef41Sopenharmony_ci          (compile_mode_ != kSynchronous),         // async
17551cb0ef41Sopenharmony_ci          (compile_mode_ == kStreaming),           // streamed
17561cb0ef41Sopenharmony_ci          false,                                   // cached
17571cb0ef41Sopenharmony_ci          false,                                   // deserialized
17581cb0ef41Sopenharmony_ci          FLAG_wasm_lazy_compilation,              // lazy
17591cb0ef41Sopenharmony_ci          true,                                    // success
17601cb0ef41Sopenharmony_ci          native_module->liftoff_code_size(),      // code_size_in_bytes
17611cb0ef41Sopenharmony_ci          native_module->liftoff_bailout_count(),  // liftoff_bailout_count
17621cb0ef41Sopenharmony_ci          duration.InMicroseconds(),               // wall_clock_duration_in_us
17631cb0ef41Sopenharmony_ci          static_cast<int64_t>(                    // cpu_time_duration_in_us
17641cb0ef41Sopenharmony_ci              native_module->baseline_compilation_cpu_duration())};
17651cb0ef41Sopenharmony_ci      metrics_recorder_->DelayMainThreadEvent(event, context_id_);
17661cb0ef41Sopenharmony_ci    }
17671cb0ef41Sopenharmony_ci    if (compilation_event == CompilationEvent::kFinishedTopTierCompilation) {
17681cb0ef41Sopenharmony_ci      TimedHistogram* histogram = async_counters_->wasm_tier_up_module_time();
17691cb0ef41Sopenharmony_ci      histogram->AddSample(static_cast<int>(duration.InMicroseconds()));
17701cb0ef41Sopenharmony_ci
17711cb0ef41Sopenharmony_ci      v8::metrics::WasmModuleTieredUp event{
17721cb0ef41Sopenharmony_ci          FLAG_wasm_lazy_compilation,           // lazy
17731cb0ef41Sopenharmony_ci          native_module->turbofan_code_size(),  // code_size_in_bytes
17741cb0ef41Sopenharmony_ci          duration.InMicroseconds(),            // wall_clock_duration_in_us
17751cb0ef41Sopenharmony_ci          static_cast<int64_t>(                 // cpu_time_duration_in_us
17761cb0ef41Sopenharmony_ci              native_module->tier_up_cpu_duration())};
17771cb0ef41Sopenharmony_ci      metrics_recorder_->DelayMainThreadEvent(event, context_id_);
17781cb0ef41Sopenharmony_ci    }
17791cb0ef41Sopenharmony_ci    if (compilation_event == CompilationEvent::kFailedCompilation) {
17801cb0ef41Sopenharmony_ci      v8::metrics::WasmModuleCompiled event{
17811cb0ef41Sopenharmony_ci          (compile_mode_ != kSynchronous),         // async
17821cb0ef41Sopenharmony_ci          (compile_mode_ == kStreaming),           // streamed
17831cb0ef41Sopenharmony_ci          false,                                   // cached
17841cb0ef41Sopenharmony_ci          false,                                   // deserialized
17851cb0ef41Sopenharmony_ci          FLAG_wasm_lazy_compilation,              // lazy
17861cb0ef41Sopenharmony_ci          false,                                   // success
17871cb0ef41Sopenharmony_ci          native_module->liftoff_code_size(),      // code_size_in_bytes
17881cb0ef41Sopenharmony_ci          native_module->liftoff_bailout_count(),  // liftoff_bailout_count
17891cb0ef41Sopenharmony_ci          duration.InMicroseconds(),               // wall_clock_duration_in_us
17901cb0ef41Sopenharmony_ci          static_cast<int64_t>(                    // cpu_time_duration_in_us
17911cb0ef41Sopenharmony_ci              native_module->baseline_compilation_cpu_duration())};
17921cb0ef41Sopenharmony_ci      metrics_recorder_->DelayMainThreadEvent(event, context_id_);
17931cb0ef41Sopenharmony_ci    }
17941cb0ef41Sopenharmony_ci  }
17951cb0ef41Sopenharmony_ci
17961cb0ef41Sopenharmony_ci private:
17971cb0ef41Sopenharmony_ci  base::TimeTicks start_time_;
17981cb0ef41Sopenharmony_ci  const std::shared_ptr<Counters> async_counters_;
17991cb0ef41Sopenharmony_ci  std::shared_ptr<metrics::Recorder> metrics_recorder_;
18001cb0ef41Sopenharmony_ci  v8::metrics::Recorder::ContextId context_id_;
18011cb0ef41Sopenharmony_ci  std::weak_ptr<NativeModule> native_module_;
18021cb0ef41Sopenharmony_ci  const CompileMode compile_mode_;
18031cb0ef41Sopenharmony_ci};
18041cb0ef41Sopenharmony_ci
18051cb0ef41Sopenharmony_civoid CompileNativeModule(Isolate* isolate,
18061cb0ef41Sopenharmony_ci                         v8::metrics::Recorder::ContextId context_id,
18071cb0ef41Sopenharmony_ci                         ErrorThrower* thrower, const WasmModule* wasm_module,
18081cb0ef41Sopenharmony_ci                         std::shared_ptr<NativeModule> native_module,
18091cb0ef41Sopenharmony_ci                         Handle<FixedArray>* export_wrappers_out) {
18101cb0ef41Sopenharmony_ci  CHECK(!FLAG_jitless);
18111cb0ef41Sopenharmony_ci  ModuleWireBytes wire_bytes(native_module->wire_bytes());
18121cb0ef41Sopenharmony_ci  const bool lazy_module = IsLazyModule(wasm_module);
18131cb0ef41Sopenharmony_ci  if (!FLAG_wasm_lazy_validation && wasm_module->origin == kWasmOrigin &&
18141cb0ef41Sopenharmony_ci      MayCompriseLazyFunctions(wasm_module, native_module->enabled_features(),
18151cb0ef41Sopenharmony_ci                               lazy_module)) {
18161cb0ef41Sopenharmony_ci    // Validate wasm modules for lazy compilation if requested. Never validate
18171cb0ef41Sopenharmony_ci    // asm.js modules as these are valid by construction (additionally a CHECK
18181cb0ef41Sopenharmony_ci    // will catch this during lazy compilation).
18191cb0ef41Sopenharmony_ci    ValidateSequentially(wasm_module, native_module.get(), isolate->counters(),
18201cb0ef41Sopenharmony_ci                         isolate->allocator(), thrower, lazy_module,
18211cb0ef41Sopenharmony_ci                         kOnlyLazyFunctions);
18221cb0ef41Sopenharmony_ci    // On error: Return and leave the module in an unexecutable state.
18231cb0ef41Sopenharmony_ci    if (thrower->error()) return;
18241cb0ef41Sopenharmony_ci  }
18251cb0ef41Sopenharmony_ci
18261cb0ef41Sopenharmony_ci  DCHECK_GE(kMaxInt, native_module->module()->num_declared_functions);
18271cb0ef41Sopenharmony_ci
18281cb0ef41Sopenharmony_ci  // The callback captures a shared ptr to the semaphore.
18291cb0ef41Sopenharmony_ci  auto* compilation_state = Impl(native_module->compilation_state());
18301cb0ef41Sopenharmony_ci  if (base::TimeTicks::IsHighResolution()) {
18311cb0ef41Sopenharmony_ci    compilation_state->AddCallback(std::make_unique<CompilationTimeCallback>(
18321cb0ef41Sopenharmony_ci        isolate->async_counters(), isolate->metrics_recorder(), context_id,
18331cb0ef41Sopenharmony_ci        native_module, CompilationTimeCallback::kSynchronous));
18341cb0ef41Sopenharmony_ci  }
18351cb0ef41Sopenharmony_ci
18361cb0ef41Sopenharmony_ci  // Initialize the compilation units and kick off background compile tasks.
18371cb0ef41Sopenharmony_ci  std::unique_ptr<CompilationUnitBuilder> builder =
18381cb0ef41Sopenharmony_ci      InitializeCompilation(isolate, native_module.get());
18391cb0ef41Sopenharmony_ci  compilation_state->InitializeCompilationUnits(std::move(builder));
18401cb0ef41Sopenharmony_ci
18411cb0ef41Sopenharmony_ci  compilation_state->WaitForCompilationEvent(
18421cb0ef41Sopenharmony_ci      CompilationEvent::kFinishedExportWrappers);
18431cb0ef41Sopenharmony_ci
18441cb0ef41Sopenharmony_ci  if (compilation_state->failed()) {
18451cb0ef41Sopenharmony_ci    DCHECK_IMPLIES(lazy_module, !FLAG_wasm_lazy_validation);
18461cb0ef41Sopenharmony_ci    ValidateSequentially(wasm_module, native_module.get(), isolate->counters(),
18471cb0ef41Sopenharmony_ci                         isolate->allocator(), thrower, lazy_module);
18481cb0ef41Sopenharmony_ci    CHECK(thrower->error());
18491cb0ef41Sopenharmony_ci    return;
18501cb0ef41Sopenharmony_ci  }
18511cb0ef41Sopenharmony_ci
18521cb0ef41Sopenharmony_ci  compilation_state->FinalizeJSToWasmWrappers(isolate, native_module->module(),
18531cb0ef41Sopenharmony_ci                                              export_wrappers_out);
18541cb0ef41Sopenharmony_ci
18551cb0ef41Sopenharmony_ci  compilation_state->WaitForCompilationEvent(
18561cb0ef41Sopenharmony_ci      CompilationEvent::kFinishedBaselineCompilation);
18571cb0ef41Sopenharmony_ci
18581cb0ef41Sopenharmony_ci  compilation_state->PublishDetectedFeatures(isolate);
18591cb0ef41Sopenharmony_ci
18601cb0ef41Sopenharmony_ci  if (compilation_state->failed()) {
18611cb0ef41Sopenharmony_ci    DCHECK_IMPLIES(lazy_module, !FLAG_wasm_lazy_validation);
18621cb0ef41Sopenharmony_ci    ValidateSequentially(wasm_module, native_module.get(), isolate->counters(),
18631cb0ef41Sopenharmony_ci                         isolate->allocator(), thrower, lazy_module);
18641cb0ef41Sopenharmony_ci    CHECK(thrower->error());
18651cb0ef41Sopenharmony_ci  }
18661cb0ef41Sopenharmony_ci}
18671cb0ef41Sopenharmony_ci
18681cb0ef41Sopenharmony_ciclass BackgroundCompileJob final : public JobTask {
18691cb0ef41Sopenharmony_ci public:
18701cb0ef41Sopenharmony_ci  explicit BackgroundCompileJob(std::weak_ptr<NativeModule> native_module,
18711cb0ef41Sopenharmony_ci                                std::shared_ptr<Counters> async_counters)
18721cb0ef41Sopenharmony_ci      : native_module_(std::move(native_module)),
18731cb0ef41Sopenharmony_ci        engine_barrier_(GetWasmEngine()->GetBarrierForBackgroundCompile()),
18741cb0ef41Sopenharmony_ci        async_counters_(std::move(async_counters)) {}
18751cb0ef41Sopenharmony_ci
18761cb0ef41Sopenharmony_ci  void Run(JobDelegate* delegate) override {
18771cb0ef41Sopenharmony_ci    auto engine_scope = engine_barrier_->TryLock();
18781cb0ef41Sopenharmony_ci    if (!engine_scope) return;
18791cb0ef41Sopenharmony_ci    ExecuteCompilationUnits(native_module_, async_counters_.get(), delegate,
18801cb0ef41Sopenharmony_ci                            kBaselineOrTopTier);
18811cb0ef41Sopenharmony_ci  }
18821cb0ef41Sopenharmony_ci
18831cb0ef41Sopenharmony_ci  size_t GetMaxConcurrency(size_t worker_count) const override {
18841cb0ef41Sopenharmony_ci    BackgroundCompileScope compile_scope(native_module_);
18851cb0ef41Sopenharmony_ci    if (compile_scope.cancelled()) return 0;
18861cb0ef41Sopenharmony_ci    // NumOutstandingCompilations() does not reflect the units that running
18871cb0ef41Sopenharmony_ci    // workers are processing, thus add the current worker count to that number.
18881cb0ef41Sopenharmony_ci    return std::min(
18891cb0ef41Sopenharmony_ci        static_cast<size_t>(FLAG_wasm_num_compilation_tasks),
18901cb0ef41Sopenharmony_ci        worker_count +
18911cb0ef41Sopenharmony_ci            compile_scope.compilation_state()->NumOutstandingCompilations());
18921cb0ef41Sopenharmony_ci  }
18931cb0ef41Sopenharmony_ci
18941cb0ef41Sopenharmony_ci private:
18951cb0ef41Sopenharmony_ci  std::weak_ptr<NativeModule> native_module_;
18961cb0ef41Sopenharmony_ci  std::shared_ptr<OperationsBarrier> engine_barrier_;
18971cb0ef41Sopenharmony_ci  const std::shared_ptr<Counters> async_counters_;
18981cb0ef41Sopenharmony_ci};
18991cb0ef41Sopenharmony_ci
19001cb0ef41Sopenharmony_ci}  // namespace
19011cb0ef41Sopenharmony_ci
19021cb0ef41Sopenharmony_cistd::shared_ptr<NativeModule> CompileToNativeModule(
19031cb0ef41Sopenharmony_ci    Isolate* isolate, const WasmFeatures& enabled, ErrorThrower* thrower,
19041cb0ef41Sopenharmony_ci    std::shared_ptr<const WasmModule> module, const ModuleWireBytes& wire_bytes,
19051cb0ef41Sopenharmony_ci    Handle<FixedArray>* export_wrappers_out, int compilation_id,
19061cb0ef41Sopenharmony_ci    v8::metrics::Recorder::ContextId context_id) {
19071cb0ef41Sopenharmony_ci  const WasmModule* wasm_module = module.get();
19081cb0ef41Sopenharmony_ci  WasmEngine* engine = GetWasmEngine();
19091cb0ef41Sopenharmony_ci  base::OwnedVector<uint8_t> wire_bytes_copy =
19101cb0ef41Sopenharmony_ci      base::OwnedVector<uint8_t>::Of(wire_bytes.module_bytes());
19111cb0ef41Sopenharmony_ci  // Prefer {wire_bytes_copy} to {wire_bytes.module_bytes()} for the temporary
19121cb0ef41Sopenharmony_ci  // cache key. When we eventually install the module in the cache, the wire
19131cb0ef41Sopenharmony_ci  // bytes of the temporary key and the new key have the same base pointer and
19141cb0ef41Sopenharmony_ci  // we can skip the full bytes comparison.
19151cb0ef41Sopenharmony_ci  std::shared_ptr<NativeModule> native_module = engine->MaybeGetNativeModule(
19161cb0ef41Sopenharmony_ci      wasm_module->origin, wire_bytes_copy.as_vector(), isolate);
19171cb0ef41Sopenharmony_ci  if (native_module) {
19181cb0ef41Sopenharmony_ci    // TODO(thibaudm): Look into sharing export wrappers.
19191cb0ef41Sopenharmony_ci    CompileJsToWasmWrappers(isolate, wasm_module, export_wrappers_out);
19201cb0ef41Sopenharmony_ci    return native_module;
19211cb0ef41Sopenharmony_ci  }
19221cb0ef41Sopenharmony_ci
19231cb0ef41Sopenharmony_ci  TimedHistogramScope wasm_compile_module_time_scope(SELECT_WASM_COUNTER(
19241cb0ef41Sopenharmony_ci      isolate->counters(), wasm_module->origin, wasm_compile, module_time));
19251cb0ef41Sopenharmony_ci
19261cb0ef41Sopenharmony_ci  // Embedder usage count for declared shared memories.
19271cb0ef41Sopenharmony_ci  if (wasm_module->has_shared_memory) {
19281cb0ef41Sopenharmony_ci    isolate->CountUsage(v8::Isolate::UseCounterFeature::kWasmSharedMemory);
19291cb0ef41Sopenharmony_ci  }
19301cb0ef41Sopenharmony_ci
19311cb0ef41Sopenharmony_ci  // Create a new {NativeModule} first.
19321cb0ef41Sopenharmony_ci  const bool include_liftoff = module->origin == kWasmOrigin && FLAG_liftoff;
19331cb0ef41Sopenharmony_ci  DynamicTiering dynamic_tiering = isolate->IsWasmDynamicTieringEnabled()
19341cb0ef41Sopenharmony_ci                                       ? DynamicTiering::kEnabled
19351cb0ef41Sopenharmony_ci                                       : DynamicTiering::kDisabled;
19361cb0ef41Sopenharmony_ci  size_t code_size_estimate =
19371cb0ef41Sopenharmony_ci      wasm::WasmCodeManager::EstimateNativeModuleCodeSize(
19381cb0ef41Sopenharmony_ci          module.get(), include_liftoff, dynamic_tiering);
19391cb0ef41Sopenharmony_ci  native_module =
19401cb0ef41Sopenharmony_ci      engine->NewNativeModule(isolate, enabled, module, code_size_estimate);
19411cb0ef41Sopenharmony_ci  native_module->SetWireBytes(std::move(wire_bytes_copy));
19421cb0ef41Sopenharmony_ci  native_module->compilation_state()->set_compilation_id(compilation_id);
19431cb0ef41Sopenharmony_ci  // Sync compilation is user blocking, so we increase the priority.
19441cb0ef41Sopenharmony_ci  native_module->compilation_state()->SetHighPriority();
19451cb0ef41Sopenharmony_ci
19461cb0ef41Sopenharmony_ci  CompileNativeModule(isolate, context_id, thrower, wasm_module, native_module,
19471cb0ef41Sopenharmony_ci                      export_wrappers_out);
19481cb0ef41Sopenharmony_ci  bool cache_hit = !engine->UpdateNativeModuleCache(thrower->error(),
19491cb0ef41Sopenharmony_ci                                                    &native_module, isolate);
19501cb0ef41Sopenharmony_ci  if (thrower->error()) return {};
19511cb0ef41Sopenharmony_ci
19521cb0ef41Sopenharmony_ci  if (cache_hit) {
19531cb0ef41Sopenharmony_ci    CompileJsToWasmWrappers(isolate, wasm_module, export_wrappers_out);
19541cb0ef41Sopenharmony_ci    return native_module;
19551cb0ef41Sopenharmony_ci  }
19561cb0ef41Sopenharmony_ci
19571cb0ef41Sopenharmony_ci  // Ensure that the code objects are logged before returning.
19581cb0ef41Sopenharmony_ci  engine->LogOutstandingCodesForIsolate(isolate);
19591cb0ef41Sopenharmony_ci
19601cb0ef41Sopenharmony_ci  return native_module;
19611cb0ef41Sopenharmony_ci}
19621cb0ef41Sopenharmony_ci
19631cb0ef41Sopenharmony_civoid RecompileNativeModule(NativeModule* native_module,
19641cb0ef41Sopenharmony_ci                           TieringState tiering_state) {
19651cb0ef41Sopenharmony_ci  // Install a callback to notify us once background recompilation finished.
19661cb0ef41Sopenharmony_ci  auto recompilation_finished_semaphore = std::make_shared<base::Semaphore>(0);
19671cb0ef41Sopenharmony_ci  auto* compilation_state = Impl(native_module->compilation_state());
19681cb0ef41Sopenharmony_ci
19691cb0ef41Sopenharmony_ci  class RecompilationFinishedCallback : public CompilationEventCallback {
19701cb0ef41Sopenharmony_ci   public:
19711cb0ef41Sopenharmony_ci    explicit RecompilationFinishedCallback(
19721cb0ef41Sopenharmony_ci        std::shared_ptr<base::Semaphore> recompilation_finished_semaphore)
19731cb0ef41Sopenharmony_ci        : recompilation_finished_semaphore_(
19741cb0ef41Sopenharmony_ci              std::move(recompilation_finished_semaphore)) {}
19751cb0ef41Sopenharmony_ci
19761cb0ef41Sopenharmony_ci    void call(CompilationEvent event) override {
19771cb0ef41Sopenharmony_ci      DCHECK_NE(CompilationEvent::kFailedCompilation, event);
19781cb0ef41Sopenharmony_ci      if (event == CompilationEvent::kFinishedRecompilation) {
19791cb0ef41Sopenharmony_ci        recompilation_finished_semaphore_->Signal();
19801cb0ef41Sopenharmony_ci      }
19811cb0ef41Sopenharmony_ci    }
19821cb0ef41Sopenharmony_ci
19831cb0ef41Sopenharmony_ci   private:
19841cb0ef41Sopenharmony_ci    std::shared_ptr<base::Semaphore> recompilation_finished_semaphore_;
19851cb0ef41Sopenharmony_ci  };
19861cb0ef41Sopenharmony_ci
19871cb0ef41Sopenharmony_ci  // The callback captures a shared ptr to the semaphore.
19881cb0ef41Sopenharmony_ci  // Initialize the compilation units and kick off background compile tasks.
19891cb0ef41Sopenharmony_ci  compilation_state->InitializeRecompilation(
19901cb0ef41Sopenharmony_ci      tiering_state, std::make_unique<RecompilationFinishedCallback>(
19911cb0ef41Sopenharmony_ci                         recompilation_finished_semaphore));
19921cb0ef41Sopenharmony_ci
19931cb0ef41Sopenharmony_ci  constexpr JobDelegate* kNoDelegate = nullptr;
19941cb0ef41Sopenharmony_ci  ExecuteCompilationUnits(compilation_state->native_module_weak(),
19951cb0ef41Sopenharmony_ci                          compilation_state->counters(), kNoDelegate,
19961cb0ef41Sopenharmony_ci                          kBaselineOnly);
19971cb0ef41Sopenharmony_ci  recompilation_finished_semaphore->Wait();
19981cb0ef41Sopenharmony_ci  DCHECK(!compilation_state->failed());
19991cb0ef41Sopenharmony_ci}
20001cb0ef41Sopenharmony_ci
20011cb0ef41Sopenharmony_ciAsyncCompileJob::AsyncCompileJob(
20021cb0ef41Sopenharmony_ci    Isolate* isolate, const WasmFeatures& enabled,
20031cb0ef41Sopenharmony_ci    std::unique_ptr<byte[]> bytes_copy, size_t length, Handle<Context> context,
20041cb0ef41Sopenharmony_ci    Handle<Context> incumbent_context, const char* api_method_name,
20051cb0ef41Sopenharmony_ci    std::shared_ptr<CompilationResultResolver> resolver, int compilation_id)
20061cb0ef41Sopenharmony_ci    : isolate_(isolate),
20071cb0ef41Sopenharmony_ci      api_method_name_(api_method_name),
20081cb0ef41Sopenharmony_ci      enabled_features_(enabled),
20091cb0ef41Sopenharmony_ci      dynamic_tiering_(isolate_->IsWasmDynamicTieringEnabled()
20101cb0ef41Sopenharmony_ci                           ? DynamicTiering::kEnabled
20111cb0ef41Sopenharmony_ci                           : DynamicTiering::kDisabled),
20121cb0ef41Sopenharmony_ci      wasm_lazy_compilation_(FLAG_wasm_lazy_compilation),
20131cb0ef41Sopenharmony_ci      start_time_(base::TimeTicks::Now()),
20141cb0ef41Sopenharmony_ci      bytes_copy_(std::move(bytes_copy)),
20151cb0ef41Sopenharmony_ci      wire_bytes_(bytes_copy_.get(), bytes_copy_.get() + length),
20161cb0ef41Sopenharmony_ci      resolver_(std::move(resolver)),
20171cb0ef41Sopenharmony_ci      compilation_id_(compilation_id) {
20181cb0ef41Sopenharmony_ci  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed"),
20191cb0ef41Sopenharmony_ci               "wasm.AsyncCompileJob");
20201cb0ef41Sopenharmony_ci  CHECK(FLAG_wasm_async_compilation);
20211cb0ef41Sopenharmony_ci  CHECK(!FLAG_jitless);
20221cb0ef41Sopenharmony_ci  v8::Isolate* v8_isolate = reinterpret_cast<v8::Isolate*>(isolate);
20231cb0ef41Sopenharmony_ci  v8::Platform* platform = V8::GetCurrentPlatform();
20241cb0ef41Sopenharmony_ci  foreground_task_runner_ = platform->GetForegroundTaskRunner(v8_isolate);
20251cb0ef41Sopenharmony_ci  native_context_ =
20261cb0ef41Sopenharmony_ci      isolate->global_handles()->Create(context->native_context());
20271cb0ef41Sopenharmony_ci  incumbent_context_ = isolate->global_handles()->Create(*incumbent_context);
20281cb0ef41Sopenharmony_ci  DCHECK(native_context_->IsNativeContext());
20291cb0ef41Sopenharmony_ci  context_id_ = isolate->GetOrRegisterRecorderContextId(native_context_);
20301cb0ef41Sopenharmony_ci  metrics_event_.async = true;
20311cb0ef41Sopenharmony_ci}
20321cb0ef41Sopenharmony_ci
20331cb0ef41Sopenharmony_civoid AsyncCompileJob::Start() {
20341cb0ef41Sopenharmony_ci  DoAsync<DecodeModule>(isolate_->counters(),
20351cb0ef41Sopenharmony_ci                        isolate_->metrics_recorder());  // --
20361cb0ef41Sopenharmony_ci}
20371cb0ef41Sopenharmony_ci
20381cb0ef41Sopenharmony_civoid AsyncCompileJob::Abort() {
20391cb0ef41Sopenharmony_ci  // Removing this job will trigger the destructor, which will cancel all
20401cb0ef41Sopenharmony_ci  // compilation.
20411cb0ef41Sopenharmony_ci  GetWasmEngine()->RemoveCompileJob(this);
20421cb0ef41Sopenharmony_ci}
20431cb0ef41Sopenharmony_ci
20441cb0ef41Sopenharmony_ciclass AsyncStreamingProcessor final : public StreamingProcessor {
20451cb0ef41Sopenharmony_ci public:
20461cb0ef41Sopenharmony_ci  explicit AsyncStreamingProcessor(AsyncCompileJob* job,
20471cb0ef41Sopenharmony_ci                                   std::shared_ptr<Counters> counters,
20481cb0ef41Sopenharmony_ci                                   AccountingAllocator* allocator);
20491cb0ef41Sopenharmony_ci
20501cb0ef41Sopenharmony_ci  ~AsyncStreamingProcessor() override;
20511cb0ef41Sopenharmony_ci
20521cb0ef41Sopenharmony_ci  bool ProcessModuleHeader(base::Vector<const uint8_t> bytes,
20531cb0ef41Sopenharmony_ci                           uint32_t offset) override;
20541cb0ef41Sopenharmony_ci
20551cb0ef41Sopenharmony_ci  bool ProcessSection(SectionCode section_code,
20561cb0ef41Sopenharmony_ci                      base::Vector<const uint8_t> bytes,
20571cb0ef41Sopenharmony_ci                      uint32_t offset) override;
20581cb0ef41Sopenharmony_ci
20591cb0ef41Sopenharmony_ci  bool ProcessCodeSectionHeader(int num_functions,
20601cb0ef41Sopenharmony_ci                                uint32_t functions_mismatch_error_offset,
20611cb0ef41Sopenharmony_ci                                std::shared_ptr<WireBytesStorage>,
20621cb0ef41Sopenharmony_ci                                int code_section_start,
20631cb0ef41Sopenharmony_ci                                int code_section_length) override;
20641cb0ef41Sopenharmony_ci
20651cb0ef41Sopenharmony_ci  bool ProcessFunctionBody(base::Vector<const uint8_t> bytes,
20661cb0ef41Sopenharmony_ci                           uint32_t offset) override;
20671cb0ef41Sopenharmony_ci
20681cb0ef41Sopenharmony_ci  void OnFinishedChunk() override;
20691cb0ef41Sopenharmony_ci
20701cb0ef41Sopenharmony_ci  void OnFinishedStream(base::OwnedVector<uint8_t> bytes) override;
20711cb0ef41Sopenharmony_ci
20721cb0ef41Sopenharmony_ci  void OnError(const WasmError&) override;
20731cb0ef41Sopenharmony_ci
20741cb0ef41Sopenharmony_ci  void OnAbort() override;
20751cb0ef41Sopenharmony_ci
20761cb0ef41Sopenharmony_ci  bool Deserialize(base::Vector<const uint8_t> wire_bytes,
20771cb0ef41Sopenharmony_ci                   base::Vector<const uint8_t> module_bytes) override;
20781cb0ef41Sopenharmony_ci
20791cb0ef41Sopenharmony_ci private:
20801cb0ef41Sopenharmony_ci  // Finishes the AsyncCompileJob with an error.
20811cb0ef41Sopenharmony_ci  void FinishAsyncCompileJobWithError(const WasmError&);
20821cb0ef41Sopenharmony_ci
20831cb0ef41Sopenharmony_ci  void CommitCompilationUnits();
20841cb0ef41Sopenharmony_ci
20851cb0ef41Sopenharmony_ci  ModuleDecoder decoder_;
20861cb0ef41Sopenharmony_ci  AsyncCompileJob* job_;
20871cb0ef41Sopenharmony_ci  std::unique_ptr<CompilationUnitBuilder> compilation_unit_builder_;
20881cb0ef41Sopenharmony_ci  int num_functions_ = 0;
20891cb0ef41Sopenharmony_ci  bool prefix_cache_hit_ = false;
20901cb0ef41Sopenharmony_ci  bool before_code_section_ = true;
20911cb0ef41Sopenharmony_ci  std::shared_ptr<Counters> async_counters_;
20921cb0ef41Sopenharmony_ci  AccountingAllocator* allocator_;
20931cb0ef41Sopenharmony_ci
20941cb0ef41Sopenharmony_ci  // Running hash of the wire bytes up to code section size, but excluding the
20951cb0ef41Sopenharmony_ci  // code section itself. Used by the {NativeModuleCache} to detect potential
20961cb0ef41Sopenharmony_ci  // duplicate modules.
20971cb0ef41Sopenharmony_ci  size_t prefix_hash_;
20981cb0ef41Sopenharmony_ci};
20991cb0ef41Sopenharmony_ci
21001cb0ef41Sopenharmony_cistd::shared_ptr<StreamingDecoder> AsyncCompileJob::CreateStreamingDecoder() {
21011cb0ef41Sopenharmony_ci  DCHECK_NULL(stream_);
21021cb0ef41Sopenharmony_ci  stream_ = StreamingDecoder::CreateAsyncStreamingDecoder(
21031cb0ef41Sopenharmony_ci      std::make_unique<AsyncStreamingProcessor>(
21041cb0ef41Sopenharmony_ci          this, isolate_->async_counters(), isolate_->allocator()));
21051cb0ef41Sopenharmony_ci  return stream_;
21061cb0ef41Sopenharmony_ci}
21071cb0ef41Sopenharmony_ci
21081cb0ef41Sopenharmony_ciAsyncCompileJob::~AsyncCompileJob() {
21091cb0ef41Sopenharmony_ci  // Note: This destructor always runs on the foreground thread of the isolate.
21101cb0ef41Sopenharmony_ci  background_task_manager_.CancelAndWait();
21111cb0ef41Sopenharmony_ci  // If initial compilation did not finish yet we can abort it.
21121cb0ef41Sopenharmony_ci  if (native_module_) {
21131cb0ef41Sopenharmony_ci    Impl(native_module_->compilation_state())
21141cb0ef41Sopenharmony_ci        ->CancelCompilation(CompilationStateImpl::kCancelInitialCompilation);
21151cb0ef41Sopenharmony_ci  }
21161cb0ef41Sopenharmony_ci  // Tell the streaming decoder that the AsyncCompileJob is not available
21171cb0ef41Sopenharmony_ci  // anymore.
21181cb0ef41Sopenharmony_ci  // TODO(ahaas): Is this notification really necessary? Check
21191cb0ef41Sopenharmony_ci  // https://crbug.com/888170.
21201cb0ef41Sopenharmony_ci  if (stream_) stream_->NotifyCompilationEnded();
21211cb0ef41Sopenharmony_ci  CancelPendingForegroundTask();
21221cb0ef41Sopenharmony_ci  isolate_->global_handles()->Destroy(native_context_.location());
21231cb0ef41Sopenharmony_ci  isolate_->global_handles()->Destroy(incumbent_context_.location());
21241cb0ef41Sopenharmony_ci  if (!module_object_.is_null()) {
21251cb0ef41Sopenharmony_ci    isolate_->global_handles()->Destroy(module_object_.location());
21261cb0ef41Sopenharmony_ci  }
21271cb0ef41Sopenharmony_ci}
21281cb0ef41Sopenharmony_ci
21291cb0ef41Sopenharmony_civoid AsyncCompileJob::CreateNativeModule(
21301cb0ef41Sopenharmony_ci    std::shared_ptr<const WasmModule> module, size_t code_size_estimate) {
21311cb0ef41Sopenharmony_ci  // Embedder usage count for declared shared memories.
21321cb0ef41Sopenharmony_ci  if (module->has_shared_memory) {
21331cb0ef41Sopenharmony_ci    isolate_->CountUsage(v8::Isolate::UseCounterFeature::kWasmSharedMemory);
21341cb0ef41Sopenharmony_ci  }
21351cb0ef41Sopenharmony_ci
21361cb0ef41Sopenharmony_ci  // TODO(wasm): Improve efficiency of storing module wire bytes. Only store
21371cb0ef41Sopenharmony_ci  // relevant sections, not function bodies
21381cb0ef41Sopenharmony_ci
21391cb0ef41Sopenharmony_ci  // Create the module object and populate with compiled functions and
21401cb0ef41Sopenharmony_ci  // information needed at instantiation time.
21411cb0ef41Sopenharmony_ci
21421cb0ef41Sopenharmony_ci  native_module_ = GetWasmEngine()->NewNativeModule(
21431cb0ef41Sopenharmony_ci      isolate_, enabled_features_, std::move(module), code_size_estimate);
21441cb0ef41Sopenharmony_ci  native_module_->SetWireBytes({std::move(bytes_copy_), wire_bytes_.length()});
21451cb0ef41Sopenharmony_ci  native_module_->compilation_state()->set_compilation_id(compilation_id_);
21461cb0ef41Sopenharmony_ci}
21471cb0ef41Sopenharmony_ci
21481cb0ef41Sopenharmony_cibool AsyncCompileJob::GetOrCreateNativeModule(
21491cb0ef41Sopenharmony_ci    std::shared_ptr<const WasmModule> module, size_t code_size_estimate) {
21501cb0ef41Sopenharmony_ci  native_module_ = GetWasmEngine()->MaybeGetNativeModule(
21511cb0ef41Sopenharmony_ci      module->origin, wire_bytes_.module_bytes(), isolate_);
21521cb0ef41Sopenharmony_ci  if (native_module_ == nullptr) {
21531cb0ef41Sopenharmony_ci    CreateNativeModule(std::move(module), code_size_estimate);
21541cb0ef41Sopenharmony_ci    return false;
21551cb0ef41Sopenharmony_ci  }
21561cb0ef41Sopenharmony_ci  return true;
21571cb0ef41Sopenharmony_ci}
21581cb0ef41Sopenharmony_ci
21591cb0ef41Sopenharmony_civoid AsyncCompileJob::PrepareRuntimeObjects() {
21601cb0ef41Sopenharmony_ci  // Create heap objects for script and module bytes to be stored in the
21611cb0ef41Sopenharmony_ci  // module object. Asm.js is not compiled asynchronously.
21621cb0ef41Sopenharmony_ci  DCHECK(module_object_.is_null());
21631cb0ef41Sopenharmony_ci  auto source_url = stream_ ? stream_->url() : base::Vector<const char>();
21641cb0ef41Sopenharmony_ci  auto script =
21651cb0ef41Sopenharmony_ci      GetWasmEngine()->GetOrCreateScript(isolate_, native_module_, source_url);
21661cb0ef41Sopenharmony_ci  Handle<WasmModuleObject> module_object =
21671cb0ef41Sopenharmony_ci      WasmModuleObject::New(isolate_, native_module_, script);
21681cb0ef41Sopenharmony_ci
21691cb0ef41Sopenharmony_ci  module_object_ = isolate_->global_handles()->Create(*module_object);
21701cb0ef41Sopenharmony_ci}
21711cb0ef41Sopenharmony_ci
21721cb0ef41Sopenharmony_ci// This function assumes that it is executed in a HandleScope, and that a
21731cb0ef41Sopenharmony_ci// context is set on the isolate.
21741cb0ef41Sopenharmony_civoid AsyncCompileJob::FinishCompile(bool is_after_cache_hit) {
21751cb0ef41Sopenharmony_ci  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed"),
21761cb0ef41Sopenharmony_ci               "wasm.FinishAsyncCompile");
21771cb0ef41Sopenharmony_ci  bool is_after_deserialization = !module_object_.is_null();
21781cb0ef41Sopenharmony_ci  auto compilation_state = Impl(native_module_->compilation_state());
21791cb0ef41Sopenharmony_ci  if (!is_after_deserialization) {
21801cb0ef41Sopenharmony_ci    if (stream_) {
21811cb0ef41Sopenharmony_ci      stream_->NotifyNativeModuleCreated(native_module_);
21821cb0ef41Sopenharmony_ci    }
21831cb0ef41Sopenharmony_ci    PrepareRuntimeObjects();
21841cb0ef41Sopenharmony_ci  }
21851cb0ef41Sopenharmony_ci
21861cb0ef41Sopenharmony_ci  // Measure duration of baseline compilation or deserialization from cache.
21871cb0ef41Sopenharmony_ci  if (base::TimeTicks::IsHighResolution()) {
21881cb0ef41Sopenharmony_ci    base::TimeDelta duration = base::TimeTicks::Now() - start_time_;
21891cb0ef41Sopenharmony_ci    int duration_usecs = static_cast<int>(duration.InMicroseconds());
21901cb0ef41Sopenharmony_ci    isolate_->counters()->wasm_streaming_finish_wasm_module_time()->AddSample(
21911cb0ef41Sopenharmony_ci        duration_usecs);
21921cb0ef41Sopenharmony_ci
21931cb0ef41Sopenharmony_ci    if (is_after_cache_hit || is_after_deserialization) {
21941cb0ef41Sopenharmony_ci      v8::metrics::WasmModuleCompiled event{
21951cb0ef41Sopenharmony_ci          true,                                     // async
21961cb0ef41Sopenharmony_ci          true,                                     // streamed
21971cb0ef41Sopenharmony_ci          is_after_cache_hit,                       // cached
21981cb0ef41Sopenharmony_ci          is_after_deserialization,                 // deserialized
21991cb0ef41Sopenharmony_ci          wasm_lazy_compilation_,                   // lazy
22001cb0ef41Sopenharmony_ci          !compilation_state->failed(),             // success
22011cb0ef41Sopenharmony_ci          native_module_->turbofan_code_size(),     // code_size_in_bytes
22021cb0ef41Sopenharmony_ci          native_module_->liftoff_bailout_count(),  // liftoff_bailout_count
22031cb0ef41Sopenharmony_ci          duration.InMicroseconds(),                // wall_clock_duration_in_us
22041cb0ef41Sopenharmony_ci          static_cast<int64_t>(                     // cpu_time_duration_in_us
22051cb0ef41Sopenharmony_ci              native_module_->baseline_compilation_cpu_duration())};
22061cb0ef41Sopenharmony_ci      isolate_->metrics_recorder()->DelayMainThreadEvent(event, context_id_);
22071cb0ef41Sopenharmony_ci    }
22081cb0ef41Sopenharmony_ci  }
22091cb0ef41Sopenharmony_ci
22101cb0ef41Sopenharmony_ci  DCHECK(!isolate_->context().is_null());
22111cb0ef41Sopenharmony_ci  // Finish the wasm script now and make it public to the debugger.
22121cb0ef41Sopenharmony_ci  Handle<Script> script(module_object_->script(), isolate_);
22131cb0ef41Sopenharmony_ci  const WasmModule* module = module_object_->module();
22141cb0ef41Sopenharmony_ci  if (script->type() == Script::TYPE_WASM &&
22151cb0ef41Sopenharmony_ci      module->debug_symbols.type == WasmDebugSymbols::Type::SourceMap &&
22161cb0ef41Sopenharmony_ci      !module->debug_symbols.external_url.is_empty()) {
22171cb0ef41Sopenharmony_ci    ModuleWireBytes wire_bytes(module_object_->native_module()->wire_bytes());
22181cb0ef41Sopenharmony_ci    MaybeHandle<String> src_map_str = isolate_->factory()->NewStringFromUtf8(
22191cb0ef41Sopenharmony_ci        wire_bytes.GetNameOrNull(module->debug_symbols.external_url),
22201cb0ef41Sopenharmony_ci        AllocationType::kOld);
22211cb0ef41Sopenharmony_ci    script->set_source_mapping_url(*src_map_str.ToHandleChecked());
22221cb0ef41Sopenharmony_ci  }
22231cb0ef41Sopenharmony_ci  {
22241cb0ef41Sopenharmony_ci    TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed"),
22251cb0ef41Sopenharmony_ci                 "wasm.Debug.OnAfterCompile");
22261cb0ef41Sopenharmony_ci    isolate_->debug()->OnAfterCompile(script);
22271cb0ef41Sopenharmony_ci  }
22281cb0ef41Sopenharmony_ci
22291cb0ef41Sopenharmony_ci  // TODO(bbudge) Allow deserialization without wrapper compilation, so we can
22301cb0ef41Sopenharmony_ci  // just compile wrappers here.
22311cb0ef41Sopenharmony_ci  if (!is_after_deserialization) {
22321cb0ef41Sopenharmony_ci    Handle<FixedArray> export_wrappers;
22331cb0ef41Sopenharmony_ci    if (is_after_cache_hit) {
22341cb0ef41Sopenharmony_ci      // TODO(thibaudm): Look into sharing wrappers.
22351cb0ef41Sopenharmony_ci      CompileJsToWasmWrappers(isolate_, module, &export_wrappers);
22361cb0ef41Sopenharmony_ci    } else {
22371cb0ef41Sopenharmony_ci      compilation_state->FinalizeJSToWasmWrappers(isolate_, module,
22381cb0ef41Sopenharmony_ci                                                  &export_wrappers);
22391cb0ef41Sopenharmony_ci    }
22401cb0ef41Sopenharmony_ci    module_object_->set_export_wrappers(*export_wrappers);
22411cb0ef41Sopenharmony_ci  }
22421cb0ef41Sopenharmony_ci  // We can only update the feature counts once the entire compile is done.
22431cb0ef41Sopenharmony_ci  compilation_state->PublishDetectedFeatures(isolate_);
22441cb0ef41Sopenharmony_ci
22451cb0ef41Sopenharmony_ci  // We might need to recompile the module for debugging, if the debugger was
22461cb0ef41Sopenharmony_ci  // enabled while streaming compilation was running. Since handling this while
22471cb0ef41Sopenharmony_ci  // compiling via streaming is tricky, we just tier down now, before publishing
22481cb0ef41Sopenharmony_ci  // the module.
22491cb0ef41Sopenharmony_ci  if (native_module_->IsTieredDown()) native_module_->RecompileForTiering();
22501cb0ef41Sopenharmony_ci
22511cb0ef41Sopenharmony_ci  // Finally, log all generated code (it does not matter if this happens
22521cb0ef41Sopenharmony_ci  // repeatedly in case the script is shared).
22531cb0ef41Sopenharmony_ci  native_module_->LogWasmCodes(isolate_, module_object_->script());
22541cb0ef41Sopenharmony_ci
22551cb0ef41Sopenharmony_ci  FinishModule();
22561cb0ef41Sopenharmony_ci}
22571cb0ef41Sopenharmony_ci
22581cb0ef41Sopenharmony_civoid AsyncCompileJob::DecodeFailed(const WasmError& error) {
22591cb0ef41Sopenharmony_ci  ErrorThrower thrower(isolate_, api_method_name_);
22601cb0ef41Sopenharmony_ci  thrower.CompileFailed(error);
22611cb0ef41Sopenharmony_ci  // {job} keeps the {this} pointer alive.
22621cb0ef41Sopenharmony_ci  std::shared_ptr<AsyncCompileJob> job =
22631cb0ef41Sopenharmony_ci      GetWasmEngine()->RemoveCompileJob(this);
22641cb0ef41Sopenharmony_ci  resolver_->OnCompilationFailed(thrower.Reify());
22651cb0ef41Sopenharmony_ci}
22661cb0ef41Sopenharmony_ci
22671cb0ef41Sopenharmony_civoid AsyncCompileJob::AsyncCompileFailed() {
22681cb0ef41Sopenharmony_ci  ErrorThrower thrower(isolate_, api_method_name_);
22691cb0ef41Sopenharmony_ci  DCHECK_EQ(native_module_->module()->origin, kWasmOrigin);
22701cb0ef41Sopenharmony_ci  const bool lazy_module = wasm_lazy_compilation_;
22711cb0ef41Sopenharmony_ci  ValidateSequentially(native_module_->module(), native_module_.get(),
22721cb0ef41Sopenharmony_ci                       isolate_->counters(), isolate_->allocator(), &thrower,
22731cb0ef41Sopenharmony_ci                       lazy_module);
22741cb0ef41Sopenharmony_ci  DCHECK(thrower.error());
22751cb0ef41Sopenharmony_ci  // {job} keeps the {this} pointer alive.
22761cb0ef41Sopenharmony_ci  std::shared_ptr<AsyncCompileJob> job =
22771cb0ef41Sopenharmony_ci      GetWasmEngine()->RemoveCompileJob(this);
22781cb0ef41Sopenharmony_ci  resolver_->OnCompilationFailed(thrower.Reify());
22791cb0ef41Sopenharmony_ci}
22801cb0ef41Sopenharmony_ci
22811cb0ef41Sopenharmony_civoid AsyncCompileJob::AsyncCompileSucceeded(Handle<WasmModuleObject> result) {
22821cb0ef41Sopenharmony_ci  TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed"),
22831cb0ef41Sopenharmony_ci               "wasm.OnCompilationSucceeded");
22841cb0ef41Sopenharmony_ci  // We have to make sure that an "incumbent context" is available in case
22851cb0ef41Sopenharmony_ci  // the module's start function calls out to Blink.
22861cb0ef41Sopenharmony_ci  Local<v8::Context> backup_incumbent_context =
22871cb0ef41Sopenharmony_ci      Utils::ToLocal(incumbent_context_);
22881cb0ef41Sopenharmony_ci  v8::Context::BackupIncumbentScope incumbent(backup_incumbent_context);
22891cb0ef41Sopenharmony_ci  resolver_->OnCompilationSucceeded(result);
22901cb0ef41Sopenharmony_ci}
22911cb0ef41Sopenharmony_ci
22921cb0ef41Sopenharmony_ciclass AsyncCompileJob::CompilationStateCallback
22931cb0ef41Sopenharmony_ci    : public CompilationEventCallback {
22941cb0ef41Sopenharmony_ci public:
22951cb0ef41Sopenharmony_ci  explicit CompilationStateCallback(AsyncCompileJob* job) : job_(job) {}
22961cb0ef41Sopenharmony_ci
22971cb0ef41Sopenharmony_ci  void call(CompilationEvent event) override {
22981cb0ef41Sopenharmony_ci    // This callback is only being called from a foreground task.
22991cb0ef41Sopenharmony_ci    switch (event) {
23001cb0ef41Sopenharmony_ci      case CompilationEvent::kFinishedExportWrappers:
23011cb0ef41Sopenharmony_ci        // Even if baseline compilation units finish first, we trigger the
23021cb0ef41Sopenharmony_ci        // "kFinishedExportWrappers" event first.
23031cb0ef41Sopenharmony_ci        DCHECK(!last_event_.has_value());
23041cb0ef41Sopenharmony_ci        break;
23051cb0ef41Sopenharmony_ci      case CompilationEvent::kFinishedBaselineCompilation:
23061cb0ef41Sopenharmony_ci        DCHECK_EQ(CompilationEvent::kFinishedExportWrappers, last_event_);
23071cb0ef41Sopenharmony_ci        if (job_->DecrementAndCheckFinisherCount()) {
23081cb0ef41Sopenharmony_ci          // Install the native module in the cache, or reuse a conflicting one.
23091cb0ef41Sopenharmony_ci          // If we get a conflicting module, wait until we are back in the
23101cb0ef41Sopenharmony_ci          // main thread to update {job_->native_module_} to avoid a data race.
23111cb0ef41Sopenharmony_ci          std::shared_ptr<NativeModule> native_module = job_->native_module_;
23121cb0ef41Sopenharmony_ci          bool cache_hit = !GetWasmEngine()->UpdateNativeModuleCache(
23131cb0ef41Sopenharmony_ci              false, &native_module, job_->isolate_);
23141cb0ef41Sopenharmony_ci          DCHECK_EQ(cache_hit, native_module != job_->native_module_);
23151cb0ef41Sopenharmony_ci          job_->DoSync<CompileFinished>(cache_hit ? std::move(native_module)
23161cb0ef41Sopenharmony_ci                                                  : nullptr);
23171cb0ef41Sopenharmony_ci        }
23181cb0ef41Sopenharmony_ci        break;
23191cb0ef41Sopenharmony_ci      case CompilationEvent::kFinishedCompilationChunk:
23201cb0ef41Sopenharmony_ci        DCHECK(CompilationEvent::kFinishedBaselineCompilation == last_event_ ||
23211cb0ef41Sopenharmony_ci               CompilationEvent::kFinishedCompilationChunk == last_event_);
23221cb0ef41Sopenharmony_ci        break;
23231cb0ef41Sopenharmony_ci      case CompilationEvent::kFinishedTopTierCompilation:
23241cb0ef41Sopenharmony_ci        DCHECK(CompilationEvent::kFinishedBaselineCompilation == last_event_);
23251cb0ef41Sopenharmony_ci        // At this point, the job will already be gone, thus do not access it
23261cb0ef41Sopenharmony_ci        // here.
23271cb0ef41Sopenharmony_ci        break;
23281cb0ef41Sopenharmony_ci      case CompilationEvent::kFailedCompilation:
23291cb0ef41Sopenharmony_ci        DCHECK(!last_event_.has_value() ||
23301cb0ef41Sopenharmony_ci               last_event_ == CompilationEvent::kFinishedExportWrappers);
23311cb0ef41Sopenharmony_ci        if (job_->DecrementAndCheckFinisherCount()) {
23321cb0ef41Sopenharmony_ci          // Don't update {job_->native_module_} to avoid data races with other
23331cb0ef41Sopenharmony_ci          // compilation threads. Use a copy of the shared pointer instead.
23341cb0ef41Sopenharmony_ci          std::shared_ptr<NativeModule> native_module = job_->native_module_;
23351cb0ef41Sopenharmony_ci          GetWasmEngine()->UpdateNativeModuleCache(true, &native_module,
23361cb0ef41Sopenharmony_ci                                                   job_->isolate_);
23371cb0ef41Sopenharmony_ci          job_->DoSync<CompileFailed>();
23381cb0ef41Sopenharmony_ci        }
23391cb0ef41Sopenharmony_ci        break;
23401cb0ef41Sopenharmony_ci      case CompilationEvent::kFinishedRecompilation:
23411cb0ef41Sopenharmony_ci        // This event can happen either before or after
23421cb0ef41Sopenharmony_ci        // {kFinishedTopTierCompilation}, hence don't remember this in
23431cb0ef41Sopenharmony_ci        // {last_event_}.
23441cb0ef41Sopenharmony_ci        return;
23451cb0ef41Sopenharmony_ci    }
23461cb0ef41Sopenharmony_ci#ifdef DEBUG
23471cb0ef41Sopenharmony_ci    last_event_ = event;
23481cb0ef41Sopenharmony_ci#endif
23491cb0ef41Sopenharmony_ci  }
23501cb0ef41Sopenharmony_ci
23511cb0ef41Sopenharmony_ci private:
23521cb0ef41Sopenharmony_ci  AsyncCompileJob* job_;
23531cb0ef41Sopenharmony_ci#ifdef DEBUG
23541cb0ef41Sopenharmony_ci  // This will be modified by different threads, but they externally
23551cb0ef41Sopenharmony_ci  // synchronize, so no explicit synchronization (currently) needed here.
23561cb0ef41Sopenharmony_ci  base::Optional<CompilationEvent> last_event_;
23571cb0ef41Sopenharmony_ci#endif
23581cb0ef41Sopenharmony_ci};
23591cb0ef41Sopenharmony_ci
23601cb0ef41Sopenharmony_ci// A closure to run a compilation step (either as foreground or background
23611cb0ef41Sopenharmony_ci// task) and schedule the next step(s), if any.
23621cb0ef41Sopenharmony_ciclass AsyncCompileJob::CompileStep {
23631cb0ef41Sopenharmony_ci public:
23641cb0ef41Sopenharmony_ci  virtual ~CompileStep() = default;
23651cb0ef41Sopenharmony_ci
23661cb0ef41Sopenharmony_ci  void Run(AsyncCompileJob* job, bool on_foreground) {
23671cb0ef41Sopenharmony_ci    if (on_foreground) {
23681cb0ef41Sopenharmony_ci      HandleScope scope(job->isolate_);
23691cb0ef41Sopenharmony_ci      SaveAndSwitchContext saved_context(job->isolate_, *job->native_context_);
23701cb0ef41Sopenharmony_ci      RunInForeground(job);
23711cb0ef41Sopenharmony_ci    } else {
23721cb0ef41Sopenharmony_ci      RunInBackground(job);
23731cb0ef41Sopenharmony_ci    }
23741cb0ef41Sopenharmony_ci  }
23751cb0ef41Sopenharmony_ci
23761cb0ef41Sopenharmony_ci  virtual void RunInForeground(AsyncCompileJob*) { UNREACHABLE(); }
23771cb0ef41Sopenharmony_ci  virtual void RunInBackground(AsyncCompileJob*) { UNREACHABLE(); }
23781cb0ef41Sopenharmony_ci};
23791cb0ef41Sopenharmony_ci
23801cb0ef41Sopenharmony_ciclass AsyncCompileJob::CompileTask : public CancelableTask {
23811cb0ef41Sopenharmony_ci public:
23821cb0ef41Sopenharmony_ci  CompileTask(AsyncCompileJob* job, bool on_foreground)
23831cb0ef41Sopenharmony_ci      // We only manage the background tasks with the {CancelableTaskManager} of
23841cb0ef41Sopenharmony_ci      // the {AsyncCompileJob}. Foreground tasks are managed by the system's
23851cb0ef41Sopenharmony_ci      // {CancelableTaskManager}. Background tasks cannot spawn tasks managed by
23861cb0ef41Sopenharmony_ci      // their own task manager.
23871cb0ef41Sopenharmony_ci      : CancelableTask(on_foreground ? job->isolate_->cancelable_task_manager()
23881cb0ef41Sopenharmony_ci                                     : &job->background_task_manager_),
23891cb0ef41Sopenharmony_ci        job_(job),
23901cb0ef41Sopenharmony_ci        on_foreground_(on_foreground) {}
23911cb0ef41Sopenharmony_ci
23921cb0ef41Sopenharmony_ci  ~CompileTask() override {
23931cb0ef41Sopenharmony_ci    if (job_ != nullptr && on_foreground_) ResetPendingForegroundTask();
23941cb0ef41Sopenharmony_ci  }
23951cb0ef41Sopenharmony_ci
23961cb0ef41Sopenharmony_ci  void RunInternal() final {
23971cb0ef41Sopenharmony_ci    if (!job_) return;
23981cb0ef41Sopenharmony_ci    if (on_foreground_) ResetPendingForegroundTask();
23991cb0ef41Sopenharmony_ci    job_->step_->Run(job_, on_foreground_);
24001cb0ef41Sopenharmony_ci    // After execution, reset {job_} such that we don't try to reset the pending
24011cb0ef41Sopenharmony_ci    // foreground task when the task is deleted.
24021cb0ef41Sopenharmony_ci    job_ = nullptr;
24031cb0ef41Sopenharmony_ci  }
24041cb0ef41Sopenharmony_ci
24051cb0ef41Sopenharmony_ci  void Cancel() {
24061cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(job_);
24071cb0ef41Sopenharmony_ci    job_ = nullptr;
24081cb0ef41Sopenharmony_ci  }
24091cb0ef41Sopenharmony_ci
24101cb0ef41Sopenharmony_ci private:
24111cb0ef41Sopenharmony_ci  // {job_} will be cleared to cancel a pending task.
24121cb0ef41Sopenharmony_ci  AsyncCompileJob* job_;
24131cb0ef41Sopenharmony_ci  bool on_foreground_;
24141cb0ef41Sopenharmony_ci
24151cb0ef41Sopenharmony_ci  void ResetPendingForegroundTask() const {
24161cb0ef41Sopenharmony_ci    DCHECK_EQ(this, job_->pending_foreground_task_);
24171cb0ef41Sopenharmony_ci    job_->pending_foreground_task_ = nullptr;
24181cb0ef41Sopenharmony_ci  }
24191cb0ef41Sopenharmony_ci};
24201cb0ef41Sopenharmony_ci
24211cb0ef41Sopenharmony_civoid AsyncCompileJob::StartForegroundTask() {
24221cb0ef41Sopenharmony_ci  DCHECK_NULL(pending_foreground_task_);
24231cb0ef41Sopenharmony_ci
24241cb0ef41Sopenharmony_ci  auto new_task = std::make_unique<CompileTask>(this, true);
24251cb0ef41Sopenharmony_ci  pending_foreground_task_ = new_task.get();
24261cb0ef41Sopenharmony_ci  foreground_task_runner_->PostTask(std::move(new_task));
24271cb0ef41Sopenharmony_ci}
24281cb0ef41Sopenharmony_ci
24291cb0ef41Sopenharmony_civoid AsyncCompileJob::ExecuteForegroundTaskImmediately() {
24301cb0ef41Sopenharmony_ci  DCHECK_NULL(pending_foreground_task_);
24311cb0ef41Sopenharmony_ci
24321cb0ef41Sopenharmony_ci  auto new_task = std::make_unique<CompileTask>(this, true);
24331cb0ef41Sopenharmony_ci  pending_foreground_task_ = new_task.get();
24341cb0ef41Sopenharmony_ci  new_task->Run();
24351cb0ef41Sopenharmony_ci}
24361cb0ef41Sopenharmony_ci
24371cb0ef41Sopenharmony_civoid AsyncCompileJob::CancelPendingForegroundTask() {
24381cb0ef41Sopenharmony_ci  if (!pending_foreground_task_) return;
24391cb0ef41Sopenharmony_ci  pending_foreground_task_->Cancel();
24401cb0ef41Sopenharmony_ci  pending_foreground_task_ = nullptr;
24411cb0ef41Sopenharmony_ci}
24421cb0ef41Sopenharmony_ci
24431cb0ef41Sopenharmony_civoid AsyncCompileJob::StartBackgroundTask() {
24441cb0ef41Sopenharmony_ci  auto task = std::make_unique<CompileTask>(this, false);
24451cb0ef41Sopenharmony_ci
24461cb0ef41Sopenharmony_ci  // If --wasm-num-compilation-tasks=0 is passed, do only spawn foreground
24471cb0ef41Sopenharmony_ci  // tasks. This is used to make timing deterministic.
24481cb0ef41Sopenharmony_ci  if (FLAG_wasm_num_compilation_tasks > 0) {
24491cb0ef41Sopenharmony_ci    V8::GetCurrentPlatform()->CallOnWorkerThread(std::move(task));
24501cb0ef41Sopenharmony_ci  } else {
24511cb0ef41Sopenharmony_ci    foreground_task_runner_->PostTask(std::move(task));
24521cb0ef41Sopenharmony_ci  }
24531cb0ef41Sopenharmony_ci}
24541cb0ef41Sopenharmony_ci
24551cb0ef41Sopenharmony_citemplate <typename Step,
24561cb0ef41Sopenharmony_ci          AsyncCompileJob::UseExistingForegroundTask use_existing_fg_task,
24571cb0ef41Sopenharmony_ci          typename... Args>
24581cb0ef41Sopenharmony_civoid AsyncCompileJob::DoSync(Args&&... args) {
24591cb0ef41Sopenharmony_ci  NextStep<Step>(std::forward<Args>(args)...);
24601cb0ef41Sopenharmony_ci  if (use_existing_fg_task && pending_foreground_task_ != nullptr) return;
24611cb0ef41Sopenharmony_ci  StartForegroundTask();
24621cb0ef41Sopenharmony_ci}
24631cb0ef41Sopenharmony_ci
24641cb0ef41Sopenharmony_citemplate <typename Step, typename... Args>
24651cb0ef41Sopenharmony_civoid AsyncCompileJob::DoImmediately(Args&&... args) {
24661cb0ef41Sopenharmony_ci  NextStep<Step>(std::forward<Args>(args)...);
24671cb0ef41Sopenharmony_ci  ExecuteForegroundTaskImmediately();
24681cb0ef41Sopenharmony_ci}
24691cb0ef41Sopenharmony_ci
24701cb0ef41Sopenharmony_citemplate <typename Step, typename... Args>
24711cb0ef41Sopenharmony_civoid AsyncCompileJob::DoAsync(Args&&... args) {
24721cb0ef41Sopenharmony_ci  NextStep<Step>(std::forward<Args>(args)...);
24731cb0ef41Sopenharmony_ci  StartBackgroundTask();
24741cb0ef41Sopenharmony_ci}
24751cb0ef41Sopenharmony_ci
24761cb0ef41Sopenharmony_citemplate <typename Step, typename... Args>
24771cb0ef41Sopenharmony_civoid AsyncCompileJob::NextStep(Args&&... args) {
24781cb0ef41Sopenharmony_ci  step_.reset(new Step(std::forward<Args>(args)...));
24791cb0ef41Sopenharmony_ci}
24801cb0ef41Sopenharmony_ci
24811cb0ef41Sopenharmony_ci//==========================================================================
24821cb0ef41Sopenharmony_ci// Step 1: (async) Decode the module.
24831cb0ef41Sopenharmony_ci//==========================================================================
24841cb0ef41Sopenharmony_ciclass AsyncCompileJob::DecodeModule : public AsyncCompileJob::CompileStep {
24851cb0ef41Sopenharmony_ci public:
24861cb0ef41Sopenharmony_ci  explicit DecodeModule(Counters* counters,
24871cb0ef41Sopenharmony_ci                        std::shared_ptr<metrics::Recorder> metrics_recorder)
24881cb0ef41Sopenharmony_ci      : counters_(counters), metrics_recorder_(std::move(metrics_recorder)) {}
24891cb0ef41Sopenharmony_ci
24901cb0ef41Sopenharmony_ci  void RunInBackground(AsyncCompileJob* job) override {
24911cb0ef41Sopenharmony_ci    ModuleResult result;
24921cb0ef41Sopenharmony_ci    {
24931cb0ef41Sopenharmony_ci      DisallowHandleAllocation no_handle;
24941cb0ef41Sopenharmony_ci      DisallowGarbageCollection no_gc;
24951cb0ef41Sopenharmony_ci      // Decode the module bytes.
24961cb0ef41Sopenharmony_ci      TRACE_COMPILE("(1) Decoding module...\n");
24971cb0ef41Sopenharmony_ci      TRACE_EVENT0(TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed"),
24981cb0ef41Sopenharmony_ci                   "wasm.DecodeModule");
24991cb0ef41Sopenharmony_ci      auto enabled_features = job->enabled_features_;
25001cb0ef41Sopenharmony_ci      result = DecodeWasmModule(
25011cb0ef41Sopenharmony_ci          enabled_features, job->wire_bytes_.start(), job->wire_bytes_.end(),
25021cb0ef41Sopenharmony_ci          false, kWasmOrigin, counters_, metrics_recorder_, job->context_id(),
25031cb0ef41Sopenharmony_ci          DecodingMethod::kAsync, GetWasmEngine()->allocator());
25041cb0ef41Sopenharmony_ci
25051cb0ef41Sopenharmony_ci      // Validate lazy functions here if requested.
25061cb0ef41Sopenharmony_ci      if (!FLAG_wasm_lazy_validation && result.ok()) {
25071cb0ef41Sopenharmony_ci        const WasmModule* module = result.value().get();
25081cb0ef41Sopenharmony_ci        DCHECK_EQ(module->origin, kWasmOrigin);
25091cb0ef41Sopenharmony_ci        const bool lazy_module = job->wasm_lazy_compilation_;
25101cb0ef41Sopenharmony_ci        if (MayCompriseLazyFunctions(module, enabled_features, lazy_module)) {
25111cb0ef41Sopenharmony_ci          auto allocator = GetWasmEngine()->allocator();
25121cb0ef41Sopenharmony_ci          int start = module->num_imported_functions;
25131cb0ef41Sopenharmony_ci          int end = start + module->num_declared_functions;
25141cb0ef41Sopenharmony_ci
25151cb0ef41Sopenharmony_ci          for (int func_index = start; func_index < end; func_index++) {
25161cb0ef41Sopenharmony_ci            const WasmFunction* func = &module->functions[func_index];
25171cb0ef41Sopenharmony_ci            base::Vector<const uint8_t> code =
25181cb0ef41Sopenharmony_ci                job->wire_bytes_.GetFunctionBytes(func);
25191cb0ef41Sopenharmony_ci
25201cb0ef41Sopenharmony_ci            CompileStrategy strategy = GetCompileStrategy(
25211cb0ef41Sopenharmony_ci                module, enabled_features, func_index, lazy_module);
25221cb0ef41Sopenharmony_ci            bool validate_lazily_compiled_function =
25231cb0ef41Sopenharmony_ci                strategy == CompileStrategy::kLazy ||
25241cb0ef41Sopenharmony_ci                strategy == CompileStrategy::kLazyBaselineEagerTopTier;
25251cb0ef41Sopenharmony_ci            if (validate_lazily_compiled_function) {
25261cb0ef41Sopenharmony_ci              DecodeResult function_result =
25271cb0ef41Sopenharmony_ci                  ValidateSingleFunction(module, func_index, code, counters_,
25281cb0ef41Sopenharmony_ci                                         allocator, enabled_features);
25291cb0ef41Sopenharmony_ci              if (function_result.failed()) {
25301cb0ef41Sopenharmony_ci                result = ModuleResult(function_result.error());
25311cb0ef41Sopenharmony_ci                break;
25321cb0ef41Sopenharmony_ci              }
25331cb0ef41Sopenharmony_ci            }
25341cb0ef41Sopenharmony_ci          }
25351cb0ef41Sopenharmony_ci        }
25361cb0ef41Sopenharmony_ci      }
25371cb0ef41Sopenharmony_ci    }
25381cb0ef41Sopenharmony_ci    if (result.failed()) {
25391cb0ef41Sopenharmony_ci      // Decoding failure; reject the promise and clean up.
25401cb0ef41Sopenharmony_ci      job->DoSync<DecodeFail>(std::move(result).error());
25411cb0ef41Sopenharmony_ci    } else {
25421cb0ef41Sopenharmony_ci      // Decode passed.
25431cb0ef41Sopenharmony_ci      std::shared_ptr<WasmModule> module = std::move(result).value();
25441cb0ef41Sopenharmony_ci      const bool include_liftoff = FLAG_liftoff;
25451cb0ef41Sopenharmony_ci      size_t code_size_estimate =
25461cb0ef41Sopenharmony_ci          wasm::WasmCodeManager::EstimateNativeModuleCodeSize(
25471cb0ef41Sopenharmony_ci              module.get(), include_liftoff, job->dynamic_tiering_);
25481cb0ef41Sopenharmony_ci      job->DoSync<PrepareAndStartCompile>(std::move(module), true,
25491cb0ef41Sopenharmony_ci                                          code_size_estimate);
25501cb0ef41Sopenharmony_ci    }
25511cb0ef41Sopenharmony_ci  }
25521cb0ef41Sopenharmony_ci
25531cb0ef41Sopenharmony_ci private:
25541cb0ef41Sopenharmony_ci  Counters* const counters_;
25551cb0ef41Sopenharmony_ci  std::shared_ptr<metrics::Recorder> metrics_recorder_;
25561cb0ef41Sopenharmony_ci};
25571cb0ef41Sopenharmony_ci
25581cb0ef41Sopenharmony_ci//==========================================================================
25591cb0ef41Sopenharmony_ci// Step 1b: (sync) Fail decoding the module.
25601cb0ef41Sopenharmony_ci//==========================================================================
25611cb0ef41Sopenharmony_ciclass AsyncCompileJob::DecodeFail : public CompileStep {
25621cb0ef41Sopenharmony_ci public:
25631cb0ef41Sopenharmony_ci  explicit DecodeFail(WasmError error) : error_(std::move(error)) {}
25641cb0ef41Sopenharmony_ci
25651cb0ef41Sopenharmony_ci private:
25661cb0ef41Sopenharmony_ci  WasmError error_;
25671cb0ef41Sopenharmony_ci
25681cb0ef41Sopenharmony_ci  void RunInForeground(AsyncCompileJob* job) override {
25691cb0ef41Sopenharmony_ci    TRACE_COMPILE("(1b) Decoding failed.\n");
25701cb0ef41Sopenharmony_ci    // {job_} is deleted in DecodeFailed, therefore the {return}.
25711cb0ef41Sopenharmony_ci    return job->DecodeFailed(error_);
25721cb0ef41Sopenharmony_ci  }
25731cb0ef41Sopenharmony_ci};
25741cb0ef41Sopenharmony_ci
25751cb0ef41Sopenharmony_ci//==========================================================================
25761cb0ef41Sopenharmony_ci// Step 2 (sync): Create heap-allocated data and start compile.
25771cb0ef41Sopenharmony_ci//==========================================================================
25781cb0ef41Sopenharmony_ciclass AsyncCompileJob::PrepareAndStartCompile : public CompileStep {
25791cb0ef41Sopenharmony_ci public:
25801cb0ef41Sopenharmony_ci  PrepareAndStartCompile(std::shared_ptr<const WasmModule> module,
25811cb0ef41Sopenharmony_ci                         bool start_compilation, size_t code_size_estimate)
25821cb0ef41Sopenharmony_ci      : module_(std::move(module)),
25831cb0ef41Sopenharmony_ci        start_compilation_(start_compilation),
25841cb0ef41Sopenharmony_ci        code_size_estimate_(code_size_estimate) {}
25851cb0ef41Sopenharmony_ci
25861cb0ef41Sopenharmony_ci private:
25871cb0ef41Sopenharmony_ci  void RunInForeground(AsyncCompileJob* job) override {
25881cb0ef41Sopenharmony_ci    TRACE_COMPILE("(2) Prepare and start compile...\n");
25891cb0ef41Sopenharmony_ci
25901cb0ef41Sopenharmony_ci    const bool streaming = job->wire_bytes_.length() == 0;
25911cb0ef41Sopenharmony_ci    if (streaming) {
25921cb0ef41Sopenharmony_ci      // Streaming compilation already checked for cache hits.
25931cb0ef41Sopenharmony_ci      job->CreateNativeModule(module_, code_size_estimate_);
25941cb0ef41Sopenharmony_ci    } else if (job->GetOrCreateNativeModule(std::move(module_),
25951cb0ef41Sopenharmony_ci                                            code_size_estimate_)) {
25961cb0ef41Sopenharmony_ci      job->FinishCompile(true);
25971cb0ef41Sopenharmony_ci      return;
25981cb0ef41Sopenharmony_ci    }
25991cb0ef41Sopenharmony_ci
26001cb0ef41Sopenharmony_ci    // Make sure all compilation tasks stopped running. Decoding (async step)
26011cb0ef41Sopenharmony_ci    // is done.
26021cb0ef41Sopenharmony_ci    job->background_task_manager_.CancelAndWait();
26031cb0ef41Sopenharmony_ci
26041cb0ef41Sopenharmony_ci    CompilationStateImpl* compilation_state =
26051cb0ef41Sopenharmony_ci        Impl(job->native_module_->compilation_state());
26061cb0ef41Sopenharmony_ci    compilation_state->AddCallback(
26071cb0ef41Sopenharmony_ci        std::make_unique<CompilationStateCallback>(job));
26081cb0ef41Sopenharmony_ci    if (base::TimeTicks::IsHighResolution()) {
26091cb0ef41Sopenharmony_ci      auto compile_mode = job->stream_ == nullptr
26101cb0ef41Sopenharmony_ci                              ? CompilationTimeCallback::kAsync
26111cb0ef41Sopenharmony_ci                              : CompilationTimeCallback::kStreaming;
26121cb0ef41Sopenharmony_ci      compilation_state->AddCallback(std::make_unique<CompilationTimeCallback>(
26131cb0ef41Sopenharmony_ci          job->isolate_->async_counters(), job->isolate_->metrics_recorder(),
26141cb0ef41Sopenharmony_ci          job->context_id_, job->native_module_, compile_mode));
26151cb0ef41Sopenharmony_ci    }
26161cb0ef41Sopenharmony_ci
26171cb0ef41Sopenharmony_ci    if (start_compilation_) {
26181cb0ef41Sopenharmony_ci      std::unique_ptr<CompilationUnitBuilder> builder =
26191cb0ef41Sopenharmony_ci          InitializeCompilation(job->isolate(), job->native_module_.get());
26201cb0ef41Sopenharmony_ci      compilation_state->InitializeCompilationUnits(std::move(builder));
26211cb0ef41Sopenharmony_ci      // We are in single-threaded mode, so there are no worker tasks that will
26221cb0ef41Sopenharmony_ci      // do the compilation. We call {WaitForCompilationEvent} here so that the
26231cb0ef41Sopenharmony_ci      // main thread paticipates and finishes the compilation.
26241cb0ef41Sopenharmony_ci      if (FLAG_wasm_num_compilation_tasks == 0) {
26251cb0ef41Sopenharmony_ci        compilation_state->WaitForCompilationEvent(
26261cb0ef41Sopenharmony_ci            CompilationEvent::kFinishedBaselineCompilation);
26271cb0ef41Sopenharmony_ci      }
26281cb0ef41Sopenharmony_ci    }
26291cb0ef41Sopenharmony_ci  }
26301cb0ef41Sopenharmony_ci
26311cb0ef41Sopenharmony_ci  const std::shared_ptr<const WasmModule> module_;
26321cb0ef41Sopenharmony_ci  const bool start_compilation_;
26331cb0ef41Sopenharmony_ci  const size_t code_size_estimate_;
26341cb0ef41Sopenharmony_ci};
26351cb0ef41Sopenharmony_ci
26361cb0ef41Sopenharmony_ci//==========================================================================
26371cb0ef41Sopenharmony_ci// Step 3a (sync): Compilation failed.
26381cb0ef41Sopenharmony_ci//==========================================================================
26391cb0ef41Sopenharmony_ciclass AsyncCompileJob::CompileFailed : public CompileStep {
26401cb0ef41Sopenharmony_ci private:
26411cb0ef41Sopenharmony_ci  void RunInForeground(AsyncCompileJob* job) override {
26421cb0ef41Sopenharmony_ci    TRACE_COMPILE("(3a) Compilation failed\n");
26431cb0ef41Sopenharmony_ci    DCHECK(job->native_module_->compilation_state()->failed());
26441cb0ef41Sopenharmony_ci
26451cb0ef41Sopenharmony_ci    // {job_} is deleted in AsyncCompileFailed, therefore the {return}.
26461cb0ef41Sopenharmony_ci    return job->AsyncCompileFailed();
26471cb0ef41Sopenharmony_ci  }
26481cb0ef41Sopenharmony_ci};
26491cb0ef41Sopenharmony_ci
26501cb0ef41Sopenharmony_cinamespace {
26511cb0ef41Sopenharmony_ciclass SampleTopTierCodeSizeCallback : public CompilationEventCallback {
26521cb0ef41Sopenharmony_ci public:
26531cb0ef41Sopenharmony_ci  explicit SampleTopTierCodeSizeCallback(
26541cb0ef41Sopenharmony_ci      std::weak_ptr<NativeModule> native_module)
26551cb0ef41Sopenharmony_ci      : native_module_(std::move(native_module)) {}
26561cb0ef41Sopenharmony_ci
26571cb0ef41Sopenharmony_ci  void call(CompilationEvent event) override {
26581cb0ef41Sopenharmony_ci    if (event != CompilationEvent::kFinishedTopTierCompilation) return;
26591cb0ef41Sopenharmony_ci    if (std::shared_ptr<NativeModule> native_module = native_module_.lock()) {
26601cb0ef41Sopenharmony_ci      GetWasmEngine()->SampleTopTierCodeSizeInAllIsolates(native_module);
26611cb0ef41Sopenharmony_ci    }
26621cb0ef41Sopenharmony_ci  }
26631cb0ef41Sopenharmony_ci
26641cb0ef41Sopenharmony_ci private:
26651cb0ef41Sopenharmony_ci  std::weak_ptr<NativeModule> native_module_;
26661cb0ef41Sopenharmony_ci};
26671cb0ef41Sopenharmony_ci}  // namespace
26681cb0ef41Sopenharmony_ci
26691cb0ef41Sopenharmony_ci//==========================================================================
26701cb0ef41Sopenharmony_ci// Step 3b (sync): Compilation finished.
26711cb0ef41Sopenharmony_ci//==========================================================================
26721cb0ef41Sopenharmony_ciclass AsyncCompileJob::CompileFinished : public CompileStep {
26731cb0ef41Sopenharmony_ci public:
26741cb0ef41Sopenharmony_ci  explicit CompileFinished(std::shared_ptr<NativeModule> cached_native_module)
26751cb0ef41Sopenharmony_ci      : cached_native_module_(std::move(cached_native_module)) {}
26761cb0ef41Sopenharmony_ci
26771cb0ef41Sopenharmony_ci private:
26781cb0ef41Sopenharmony_ci  void RunInForeground(AsyncCompileJob* job) override {
26791cb0ef41Sopenharmony_ci    TRACE_COMPILE("(3b) Compilation finished\n");
26801cb0ef41Sopenharmony_ci    if (cached_native_module_) {
26811cb0ef41Sopenharmony_ci      job->native_module_ = cached_native_module_;
26821cb0ef41Sopenharmony_ci    } else {
26831cb0ef41Sopenharmony_ci      DCHECK(!job->native_module_->compilation_state()->failed());
26841cb0ef41Sopenharmony_ci      // Sample the generated code size when baseline compilation finished.
26851cb0ef41Sopenharmony_ci      job->native_module_->SampleCodeSize(job->isolate_->counters(),
26861cb0ef41Sopenharmony_ci                                          NativeModule::kAfterBaseline);
26871cb0ef41Sopenharmony_ci      // Also, set a callback to sample the code size after top-tier compilation
26881cb0ef41Sopenharmony_ci      // finished. This callback will *not* keep the NativeModule alive.
26891cb0ef41Sopenharmony_ci      job->native_module_->compilation_state()->AddCallback(
26901cb0ef41Sopenharmony_ci          std::make_unique<SampleTopTierCodeSizeCallback>(job->native_module_));
26911cb0ef41Sopenharmony_ci    }
26921cb0ef41Sopenharmony_ci    // Then finalize and publish the generated module.
26931cb0ef41Sopenharmony_ci    job->FinishCompile(cached_native_module_ != nullptr);
26941cb0ef41Sopenharmony_ci  }
26951cb0ef41Sopenharmony_ci
26961cb0ef41Sopenharmony_ci  std::shared_ptr<NativeModule> cached_native_module_;
26971cb0ef41Sopenharmony_ci};
26981cb0ef41Sopenharmony_ci
26991cb0ef41Sopenharmony_civoid AsyncCompileJob::FinishModule() {
27001cb0ef41Sopenharmony_ci  TRACE_COMPILE("(4) Finish module...\n");
27011cb0ef41Sopenharmony_ci  AsyncCompileSucceeded(module_object_);
27021cb0ef41Sopenharmony_ci  GetWasmEngine()->RemoveCompileJob(this);
27031cb0ef41Sopenharmony_ci}
27041cb0ef41Sopenharmony_ci
27051cb0ef41Sopenharmony_ciAsyncStreamingProcessor::AsyncStreamingProcessor(
27061cb0ef41Sopenharmony_ci    AsyncCompileJob* job, std::shared_ptr<Counters> async_counters,
27071cb0ef41Sopenharmony_ci    AccountingAllocator* allocator)
27081cb0ef41Sopenharmony_ci    : decoder_(job->enabled_features_),
27091cb0ef41Sopenharmony_ci      job_(job),
27101cb0ef41Sopenharmony_ci      compilation_unit_builder_(nullptr),
27111cb0ef41Sopenharmony_ci      async_counters_(async_counters),
27121cb0ef41Sopenharmony_ci      allocator_(allocator) {}
27131cb0ef41Sopenharmony_ci
27141cb0ef41Sopenharmony_ciAsyncStreamingProcessor::~AsyncStreamingProcessor() {
27151cb0ef41Sopenharmony_ci  if (job_->native_module_ && job_->native_module_->wire_bytes().empty()) {
27161cb0ef41Sopenharmony_ci    // Clean up the temporary cache entry.
27171cb0ef41Sopenharmony_ci    GetWasmEngine()->StreamingCompilationFailed(prefix_hash_);
27181cb0ef41Sopenharmony_ci  }
27191cb0ef41Sopenharmony_ci}
27201cb0ef41Sopenharmony_ci
27211cb0ef41Sopenharmony_civoid AsyncStreamingProcessor::FinishAsyncCompileJobWithError(
27221cb0ef41Sopenharmony_ci    const WasmError& error) {
27231cb0ef41Sopenharmony_ci  DCHECK(error.has_error());
27241cb0ef41Sopenharmony_ci  // Make sure all background tasks stopped executing before we change the state
27251cb0ef41Sopenharmony_ci  // of the AsyncCompileJob to DecodeFail.
27261cb0ef41Sopenharmony_ci  job_->background_task_manager_.CancelAndWait();
27271cb0ef41Sopenharmony_ci
27281cb0ef41Sopenharmony_ci  // Record event metrics.
27291cb0ef41Sopenharmony_ci  auto duration = base::TimeTicks::Now() - job_->start_time_;
27301cb0ef41Sopenharmony_ci  job_->metrics_event_.success = false;
27311cb0ef41Sopenharmony_ci  job_->metrics_event_.streamed = true;
27321cb0ef41Sopenharmony_ci  job_->metrics_event_.module_size_in_bytes = job_->wire_bytes_.length();
27331cb0ef41Sopenharmony_ci  job_->metrics_event_.function_count = num_functions_;
27341cb0ef41Sopenharmony_ci  job_->metrics_event_.wall_clock_duration_in_us = duration.InMicroseconds();
27351cb0ef41Sopenharmony_ci  job_->isolate_->metrics_recorder()->DelayMainThreadEvent(job_->metrics_event_,
27361cb0ef41Sopenharmony_ci                                                           job_->context_id_);
27371cb0ef41Sopenharmony_ci
27381cb0ef41Sopenharmony_ci  // Check if there is already a CompiledModule, in which case we have to clean
27391cb0ef41Sopenharmony_ci  // up the CompilationStateImpl as well.
27401cb0ef41Sopenharmony_ci  if (job_->native_module_) {
27411cb0ef41Sopenharmony_ci    Impl(job_->native_module_->compilation_state())
27421cb0ef41Sopenharmony_ci        ->CancelCompilation(CompilationStateImpl::kCancelUnconditionally);
27431cb0ef41Sopenharmony_ci
27441cb0ef41Sopenharmony_ci    job_->DoSync<AsyncCompileJob::DecodeFail,
27451cb0ef41Sopenharmony_ci                 AsyncCompileJob::kUseExistingForegroundTask>(error);
27461cb0ef41Sopenharmony_ci
27471cb0ef41Sopenharmony_ci    // Clear the {compilation_unit_builder_} if it exists. This is needed
27481cb0ef41Sopenharmony_ci    // because there is a check in the destructor of the
27491cb0ef41Sopenharmony_ci    // {CompilationUnitBuilder} that it is empty.
27501cb0ef41Sopenharmony_ci    if (compilation_unit_builder_) compilation_unit_builder_->Clear();
27511cb0ef41Sopenharmony_ci  } else {
27521cb0ef41Sopenharmony_ci    job_->DoSync<AsyncCompileJob::DecodeFail>(error);
27531cb0ef41Sopenharmony_ci  }
27541cb0ef41Sopenharmony_ci}
27551cb0ef41Sopenharmony_ci
27561cb0ef41Sopenharmony_ci// Process the module header.
27571cb0ef41Sopenharmony_cibool AsyncStreamingProcessor::ProcessModuleHeader(
27581cb0ef41Sopenharmony_ci    base::Vector<const uint8_t> bytes, uint32_t offset) {
27591cb0ef41Sopenharmony_ci  TRACE_STREAMING("Process module header...\n");
27601cb0ef41Sopenharmony_ci  decoder_.StartDecoding(job_->isolate()->counters(),
27611cb0ef41Sopenharmony_ci                         job_->isolate()->metrics_recorder(),
27621cb0ef41Sopenharmony_ci                         job_->context_id(), GetWasmEngine()->allocator());
27631cb0ef41Sopenharmony_ci  decoder_.DecodeModuleHeader(bytes, offset);
27641cb0ef41Sopenharmony_ci  if (!decoder_.ok()) {
27651cb0ef41Sopenharmony_ci    FinishAsyncCompileJobWithError(decoder_.FinishDecoding(false).error());
27661cb0ef41Sopenharmony_ci    return false;
27671cb0ef41Sopenharmony_ci  }
27681cb0ef41Sopenharmony_ci  prefix_hash_ = NativeModuleCache::WireBytesHash(bytes);
27691cb0ef41Sopenharmony_ci  return true;
27701cb0ef41Sopenharmony_ci}
27711cb0ef41Sopenharmony_ci
27721cb0ef41Sopenharmony_ci// Process all sections except for the code section.
27731cb0ef41Sopenharmony_cibool AsyncStreamingProcessor::ProcessSection(SectionCode section_code,
27741cb0ef41Sopenharmony_ci                                             base::Vector<const uint8_t> bytes,
27751cb0ef41Sopenharmony_ci                                             uint32_t offset) {
27761cb0ef41Sopenharmony_ci  TRACE_STREAMING("Process section %d ...\n", section_code);
27771cb0ef41Sopenharmony_ci  if (compilation_unit_builder_) {
27781cb0ef41Sopenharmony_ci    // We reached a section after the code section, we do not need the
27791cb0ef41Sopenharmony_ci    // compilation_unit_builder_ anymore.
27801cb0ef41Sopenharmony_ci    CommitCompilationUnits();
27811cb0ef41Sopenharmony_ci    compilation_unit_builder_.reset();
27821cb0ef41Sopenharmony_ci  }
27831cb0ef41Sopenharmony_ci  if (before_code_section_) {
27841cb0ef41Sopenharmony_ci    // Combine section hashes until code section.
27851cb0ef41Sopenharmony_ci    prefix_hash_ = base::hash_combine(prefix_hash_,
27861cb0ef41Sopenharmony_ci                                      NativeModuleCache::WireBytesHash(bytes));
27871cb0ef41Sopenharmony_ci  }
27881cb0ef41Sopenharmony_ci  if (section_code == SectionCode::kUnknownSectionCode) {
27891cb0ef41Sopenharmony_ci    size_t bytes_consumed = ModuleDecoder::IdentifyUnknownSection(
27901cb0ef41Sopenharmony_ci        &decoder_, bytes, offset, &section_code);
27911cb0ef41Sopenharmony_ci    if (!decoder_.ok()) {
27921cb0ef41Sopenharmony_ci      FinishAsyncCompileJobWithError(decoder_.FinishDecoding(false).error());
27931cb0ef41Sopenharmony_ci      return false;
27941cb0ef41Sopenharmony_ci    }
27951cb0ef41Sopenharmony_ci    if (section_code == SectionCode::kUnknownSectionCode) {
27961cb0ef41Sopenharmony_ci      // Skip unknown sections that we do not know how to handle.
27971cb0ef41Sopenharmony_ci      return true;
27981cb0ef41Sopenharmony_ci    }
27991cb0ef41Sopenharmony_ci    // Remove the unknown section tag from the payload bytes.
28001cb0ef41Sopenharmony_ci    offset += bytes_consumed;
28011cb0ef41Sopenharmony_ci    bytes = bytes.SubVector(bytes_consumed, bytes.size());
28021cb0ef41Sopenharmony_ci  }
28031cb0ef41Sopenharmony_ci  constexpr bool verify_functions = false;
28041cb0ef41Sopenharmony_ci  decoder_.DecodeSection(section_code, bytes, offset, verify_functions);
28051cb0ef41Sopenharmony_ci  if (!decoder_.ok()) {
28061cb0ef41Sopenharmony_ci    FinishAsyncCompileJobWithError(decoder_.FinishDecoding(false).error());
28071cb0ef41Sopenharmony_ci    return false;
28081cb0ef41Sopenharmony_ci  }
28091cb0ef41Sopenharmony_ci  return true;
28101cb0ef41Sopenharmony_ci}
28111cb0ef41Sopenharmony_ci
28121cb0ef41Sopenharmony_ci// Start the code section.
28131cb0ef41Sopenharmony_cibool AsyncStreamingProcessor::ProcessCodeSectionHeader(
28141cb0ef41Sopenharmony_ci    int num_functions, uint32_t functions_mismatch_error_offset,
28151cb0ef41Sopenharmony_ci    std::shared_ptr<WireBytesStorage> wire_bytes_storage,
28161cb0ef41Sopenharmony_ci    int code_section_start, int code_section_length) {
28171cb0ef41Sopenharmony_ci  DCHECK_LE(0, code_section_length);
28181cb0ef41Sopenharmony_ci  before_code_section_ = false;
28191cb0ef41Sopenharmony_ci  TRACE_STREAMING("Start the code section with %d functions...\n",
28201cb0ef41Sopenharmony_ci                  num_functions);
28211cb0ef41Sopenharmony_ci  decoder_.StartCodeSection();
28221cb0ef41Sopenharmony_ci  if (!decoder_.CheckFunctionsCount(static_cast<uint32_t>(num_functions),
28231cb0ef41Sopenharmony_ci                                    functions_mismatch_error_offset)) {
28241cb0ef41Sopenharmony_ci    FinishAsyncCompileJobWithError(decoder_.FinishDecoding(false).error());
28251cb0ef41Sopenharmony_ci    return false;
28261cb0ef41Sopenharmony_ci  }
28271cb0ef41Sopenharmony_ci
28281cb0ef41Sopenharmony_ci  decoder_.set_code_section(code_section_start,
28291cb0ef41Sopenharmony_ci                            static_cast<uint32_t>(code_section_length));
28301cb0ef41Sopenharmony_ci
28311cb0ef41Sopenharmony_ci  prefix_hash_ = base::hash_combine(prefix_hash_,
28321cb0ef41Sopenharmony_ci                                    static_cast<uint32_t>(code_section_length));
28331cb0ef41Sopenharmony_ci  if (!GetWasmEngine()->GetStreamingCompilationOwnership(prefix_hash_)) {
28341cb0ef41Sopenharmony_ci    // Known prefix, wait until the end of the stream and check the cache.
28351cb0ef41Sopenharmony_ci    prefix_cache_hit_ = true;
28361cb0ef41Sopenharmony_ci    return true;
28371cb0ef41Sopenharmony_ci  }
28381cb0ef41Sopenharmony_ci
28391cb0ef41Sopenharmony_ci  // Execute the PrepareAndStartCompile step immediately and not in a separate
28401cb0ef41Sopenharmony_ci  // task.
28411cb0ef41Sopenharmony_ci  int num_imported_functions =
28421cb0ef41Sopenharmony_ci      static_cast<int>(decoder_.module()->num_imported_functions);
28431cb0ef41Sopenharmony_ci  DCHECK_EQ(kWasmOrigin, decoder_.module()->origin);
28441cb0ef41Sopenharmony_ci  const bool include_liftoff = FLAG_liftoff;
28451cb0ef41Sopenharmony_ci  size_t code_size_estimate =
28461cb0ef41Sopenharmony_ci      wasm::WasmCodeManager::EstimateNativeModuleCodeSize(
28471cb0ef41Sopenharmony_ci          num_functions, num_imported_functions, code_section_length,
28481cb0ef41Sopenharmony_ci          include_liftoff, job_->dynamic_tiering_);
28491cb0ef41Sopenharmony_ci  job_->DoImmediately<AsyncCompileJob::PrepareAndStartCompile>(
28501cb0ef41Sopenharmony_ci      decoder_.shared_module(), false, code_size_estimate);
28511cb0ef41Sopenharmony_ci
28521cb0ef41Sopenharmony_ci  auto* compilation_state = Impl(job_->native_module_->compilation_state());
28531cb0ef41Sopenharmony_ci  compilation_state->SetWireBytesStorage(std::move(wire_bytes_storage));
28541cb0ef41Sopenharmony_ci  DCHECK_EQ(job_->native_module_->module()->origin, kWasmOrigin);
28551cb0ef41Sopenharmony_ci
28561cb0ef41Sopenharmony_ci  // Set outstanding_finishers_ to 2, because both the AsyncCompileJob and the
28571cb0ef41Sopenharmony_ci  // AsyncStreamingProcessor have to finish.
28581cb0ef41Sopenharmony_ci  job_->outstanding_finishers_.store(2);
28591cb0ef41Sopenharmony_ci  compilation_unit_builder_ =
28601cb0ef41Sopenharmony_ci      InitializeCompilation(job_->isolate(), job_->native_module_.get());
28611cb0ef41Sopenharmony_ci  return true;
28621cb0ef41Sopenharmony_ci}
28631cb0ef41Sopenharmony_ci
28641cb0ef41Sopenharmony_ci// Process a function body.
28651cb0ef41Sopenharmony_cibool AsyncStreamingProcessor::ProcessFunctionBody(
28661cb0ef41Sopenharmony_ci    base::Vector<const uint8_t> bytes, uint32_t offset) {
28671cb0ef41Sopenharmony_ci  TRACE_STREAMING("Process function body %d ...\n", num_functions_);
28681cb0ef41Sopenharmony_ci
28691cb0ef41Sopenharmony_ci  decoder_.DecodeFunctionBody(
28701cb0ef41Sopenharmony_ci      num_functions_, static_cast<uint32_t>(bytes.length()), offset, false);
28711cb0ef41Sopenharmony_ci
28721cb0ef41Sopenharmony_ci  const WasmModule* module = decoder_.module();
28731cb0ef41Sopenharmony_ci  auto enabled_features = job_->enabled_features_;
28741cb0ef41Sopenharmony_ci  uint32_t func_index =
28751cb0ef41Sopenharmony_ci      num_functions_ + decoder_.module()->num_imported_functions;
28761cb0ef41Sopenharmony_ci  DCHECK_EQ(module->origin, kWasmOrigin);
28771cb0ef41Sopenharmony_ci  const bool lazy_module = job_->wasm_lazy_compilation_;
28781cb0ef41Sopenharmony_ci  CompileStrategy strategy =
28791cb0ef41Sopenharmony_ci      GetCompileStrategy(module, enabled_features, func_index, lazy_module);
28801cb0ef41Sopenharmony_ci  bool validate_lazily_compiled_function =
28811cb0ef41Sopenharmony_ci      !FLAG_wasm_lazy_validation &&
28821cb0ef41Sopenharmony_ci      (strategy == CompileStrategy::kLazy ||
28831cb0ef41Sopenharmony_ci       strategy == CompileStrategy::kLazyBaselineEagerTopTier);
28841cb0ef41Sopenharmony_ci  if (validate_lazily_compiled_function) {
28851cb0ef41Sopenharmony_ci    // The native module does not own the wire bytes until {SetWireBytes} is
28861cb0ef41Sopenharmony_ci    // called in {OnFinishedStream}. Validation must use {bytes} parameter.
28871cb0ef41Sopenharmony_ci    DecodeResult result =
28881cb0ef41Sopenharmony_ci        ValidateSingleFunction(module, func_index, bytes, async_counters_.get(),
28891cb0ef41Sopenharmony_ci                               allocator_, enabled_features);
28901cb0ef41Sopenharmony_ci
28911cb0ef41Sopenharmony_ci    if (result.failed()) {
28921cb0ef41Sopenharmony_ci      FinishAsyncCompileJobWithError(result.error());
28931cb0ef41Sopenharmony_ci      return false;
28941cb0ef41Sopenharmony_ci    }
28951cb0ef41Sopenharmony_ci  }
28961cb0ef41Sopenharmony_ci
28971cb0ef41Sopenharmony_ci  // Don't compile yet if we might have a cache hit.
28981cb0ef41Sopenharmony_ci  if (prefix_cache_hit_) {
28991cb0ef41Sopenharmony_ci    num_functions_++;
29001cb0ef41Sopenharmony_ci    return true;
29011cb0ef41Sopenharmony_ci  }
29021cb0ef41Sopenharmony_ci
29031cb0ef41Sopenharmony_ci  auto* compilation_state = Impl(job_->native_module_->compilation_state());
29041cb0ef41Sopenharmony_ci  compilation_state->AddCompilationUnit(compilation_unit_builder_.get(),
29051cb0ef41Sopenharmony_ci                                        func_index);
29061cb0ef41Sopenharmony_ci  ++num_functions_;
29071cb0ef41Sopenharmony_ci
29081cb0ef41Sopenharmony_ci  return true;
29091cb0ef41Sopenharmony_ci}
29101cb0ef41Sopenharmony_ci
29111cb0ef41Sopenharmony_civoid AsyncStreamingProcessor::CommitCompilationUnits() {
29121cb0ef41Sopenharmony_ci  DCHECK(compilation_unit_builder_);
29131cb0ef41Sopenharmony_ci  compilation_unit_builder_->Commit();
29141cb0ef41Sopenharmony_ci}
29151cb0ef41Sopenharmony_ci
29161cb0ef41Sopenharmony_civoid AsyncStreamingProcessor::OnFinishedChunk() {
29171cb0ef41Sopenharmony_ci  TRACE_STREAMING("FinishChunk...\n");
29181cb0ef41Sopenharmony_ci  if (compilation_unit_builder_) CommitCompilationUnits();
29191cb0ef41Sopenharmony_ci}
29201cb0ef41Sopenharmony_ci
29211cb0ef41Sopenharmony_ci// Finish the processing of the stream.
29221cb0ef41Sopenharmony_civoid AsyncStreamingProcessor::OnFinishedStream(
29231cb0ef41Sopenharmony_ci    base::OwnedVector<uint8_t> bytes) {
29241cb0ef41Sopenharmony_ci  TRACE_STREAMING("Finish stream...\n");
29251cb0ef41Sopenharmony_ci  DCHECK_EQ(NativeModuleCache::PrefixHash(bytes.as_vector()), prefix_hash_);
29261cb0ef41Sopenharmony_ci  ModuleResult result = decoder_.FinishDecoding(false);
29271cb0ef41Sopenharmony_ci  if (result.failed()) {
29281cb0ef41Sopenharmony_ci    FinishAsyncCompileJobWithError(result.error());
29291cb0ef41Sopenharmony_ci    return;
29301cb0ef41Sopenharmony_ci  }
29311cb0ef41Sopenharmony_ci
29321cb0ef41Sopenharmony_ci  job_->wire_bytes_ = ModuleWireBytes(bytes.as_vector());
29331cb0ef41Sopenharmony_ci  job_->bytes_copy_ = bytes.ReleaseData();
29341cb0ef41Sopenharmony_ci
29351cb0ef41Sopenharmony_ci  // Record event metrics.
29361cb0ef41Sopenharmony_ci  auto duration = base::TimeTicks::Now() - job_->start_time_;
29371cb0ef41Sopenharmony_ci  job_->metrics_event_.success = true;
29381cb0ef41Sopenharmony_ci  job_->metrics_event_.streamed = true;
29391cb0ef41Sopenharmony_ci  job_->metrics_event_.module_size_in_bytes = job_->wire_bytes_.length();
29401cb0ef41Sopenharmony_ci  job_->metrics_event_.function_count = num_functions_;
29411cb0ef41Sopenharmony_ci  job_->metrics_event_.wall_clock_duration_in_us = duration.InMicroseconds();
29421cb0ef41Sopenharmony_ci  job_->isolate_->metrics_recorder()->DelayMainThreadEvent(job_->metrics_event_,
29431cb0ef41Sopenharmony_ci                                                           job_->context_id_);
29441cb0ef41Sopenharmony_ci
29451cb0ef41Sopenharmony_ci  if (prefix_cache_hit_) {
29461cb0ef41Sopenharmony_ci    // Restart as an asynchronous, non-streaming compilation. Most likely
29471cb0ef41Sopenharmony_ci    // {PrepareAndStartCompile} will get the native module from the cache.
29481cb0ef41Sopenharmony_ci    const bool include_liftoff = FLAG_liftoff;
29491cb0ef41Sopenharmony_ci    size_t code_size_estimate =
29501cb0ef41Sopenharmony_ci        wasm::WasmCodeManager::EstimateNativeModuleCodeSize(
29511cb0ef41Sopenharmony_ci            result.value().get(), include_liftoff, job_->dynamic_tiering_);
29521cb0ef41Sopenharmony_ci    job_->DoSync<AsyncCompileJob::PrepareAndStartCompile>(
29531cb0ef41Sopenharmony_ci        std::move(result).value(), true, code_size_estimate);
29541cb0ef41Sopenharmony_ci    return;
29551cb0ef41Sopenharmony_ci  }
29561cb0ef41Sopenharmony_ci
29571cb0ef41Sopenharmony_ci  // We have to open a HandleScope and prepare the Context for
29581cb0ef41Sopenharmony_ci  // CreateNativeModule, PrepareRuntimeObjects and FinishCompile as this is a
29591cb0ef41Sopenharmony_ci  // callback from the embedder.
29601cb0ef41Sopenharmony_ci  HandleScope scope(job_->isolate_);
29611cb0ef41Sopenharmony_ci  SaveAndSwitchContext saved_context(job_->isolate_, *job_->native_context_);
29621cb0ef41Sopenharmony_ci
29631cb0ef41Sopenharmony_ci  // Record the size of the wire bytes. In synchronous and asynchronous
29641cb0ef41Sopenharmony_ci  // (non-streaming) compilation, this happens in {DecodeWasmModule}.
29651cb0ef41Sopenharmony_ci  auto* histogram = job_->isolate_->counters()->wasm_wasm_module_size_bytes();
29661cb0ef41Sopenharmony_ci  histogram->AddSample(job_->wire_bytes_.module_bytes().length());
29671cb0ef41Sopenharmony_ci
29681cb0ef41Sopenharmony_ci  const bool has_code_section = job_->native_module_ != nullptr;
29691cb0ef41Sopenharmony_ci  bool cache_hit = false;
29701cb0ef41Sopenharmony_ci  if (!has_code_section) {
29711cb0ef41Sopenharmony_ci    // We are processing a WebAssembly module without code section. Create the
29721cb0ef41Sopenharmony_ci    // native module now (would otherwise happen in {PrepareAndStartCompile} or
29731cb0ef41Sopenharmony_ci    // {ProcessCodeSectionHeader}).
29741cb0ef41Sopenharmony_ci    constexpr size_t kCodeSizeEstimate = 0;
29751cb0ef41Sopenharmony_ci    cache_hit = job_->GetOrCreateNativeModule(std::move(result).value(),
29761cb0ef41Sopenharmony_ci                                              kCodeSizeEstimate);
29771cb0ef41Sopenharmony_ci  } else {
29781cb0ef41Sopenharmony_ci    job_->native_module_->SetWireBytes(
29791cb0ef41Sopenharmony_ci        {std::move(job_->bytes_copy_), job_->wire_bytes_.length()});
29801cb0ef41Sopenharmony_ci  }
29811cb0ef41Sopenharmony_ci  const bool needs_finish = job_->DecrementAndCheckFinisherCount();
29821cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(!has_code_section, needs_finish);
29831cb0ef41Sopenharmony_ci  if (needs_finish) {
29841cb0ef41Sopenharmony_ci    const bool failed = job_->native_module_->compilation_state()->failed();
29851cb0ef41Sopenharmony_ci    if (!cache_hit) {
29861cb0ef41Sopenharmony_ci      cache_hit = !GetWasmEngine()->UpdateNativeModuleCache(
29871cb0ef41Sopenharmony_ci          failed, &job_->native_module_, job_->isolate_);
29881cb0ef41Sopenharmony_ci    }
29891cb0ef41Sopenharmony_ci    if (failed) {
29901cb0ef41Sopenharmony_ci      job_->AsyncCompileFailed();
29911cb0ef41Sopenharmony_ci    } else {
29921cb0ef41Sopenharmony_ci      job_->FinishCompile(cache_hit);
29931cb0ef41Sopenharmony_ci    }
29941cb0ef41Sopenharmony_ci  }
29951cb0ef41Sopenharmony_ci}
29961cb0ef41Sopenharmony_ci
29971cb0ef41Sopenharmony_ci// Report an error detected in the StreamingDecoder.
29981cb0ef41Sopenharmony_civoid AsyncStreamingProcessor::OnError(const WasmError& error) {
29991cb0ef41Sopenharmony_ci  TRACE_STREAMING("Stream error...\n");
30001cb0ef41Sopenharmony_ci  FinishAsyncCompileJobWithError(error);
30011cb0ef41Sopenharmony_ci}
30021cb0ef41Sopenharmony_ci
30031cb0ef41Sopenharmony_civoid AsyncStreamingProcessor::OnAbort() {
30041cb0ef41Sopenharmony_ci  TRACE_STREAMING("Abort stream...\n");
30051cb0ef41Sopenharmony_ci  job_->Abort();
30061cb0ef41Sopenharmony_ci}
30071cb0ef41Sopenharmony_ci
30081cb0ef41Sopenharmony_cibool AsyncStreamingProcessor::Deserialize(
30091cb0ef41Sopenharmony_ci    base::Vector<const uint8_t> module_bytes,
30101cb0ef41Sopenharmony_ci    base::Vector<const uint8_t> wire_bytes) {
30111cb0ef41Sopenharmony_ci  TRACE_EVENT0("v8.wasm", "wasm.Deserialize");
30121cb0ef41Sopenharmony_ci  TimedHistogramScope time_scope(
30131cb0ef41Sopenharmony_ci      job_->isolate()->counters()->wasm_deserialization_time(),
30141cb0ef41Sopenharmony_ci      job_->isolate());
30151cb0ef41Sopenharmony_ci  // DeserializeNativeModule and FinishCompile assume that they are executed in
30161cb0ef41Sopenharmony_ci  // a HandleScope, and that a context is set on the isolate.
30171cb0ef41Sopenharmony_ci  HandleScope scope(job_->isolate_);
30181cb0ef41Sopenharmony_ci  SaveAndSwitchContext saved_context(job_->isolate_, *job_->native_context_);
30191cb0ef41Sopenharmony_ci
30201cb0ef41Sopenharmony_ci  MaybeHandle<WasmModuleObject> result = DeserializeNativeModule(
30211cb0ef41Sopenharmony_ci      job_->isolate_, module_bytes, wire_bytes, job_->stream_->url());
30221cb0ef41Sopenharmony_ci
30231cb0ef41Sopenharmony_ci  if (result.is_null()) return false;
30241cb0ef41Sopenharmony_ci
30251cb0ef41Sopenharmony_ci  job_->module_object_ =
30261cb0ef41Sopenharmony_ci      job_->isolate_->global_handles()->Create(*result.ToHandleChecked());
30271cb0ef41Sopenharmony_ci  job_->native_module_ = job_->module_object_->shared_native_module();
30281cb0ef41Sopenharmony_ci  job_->wire_bytes_ = ModuleWireBytes(job_->native_module_->wire_bytes());
30291cb0ef41Sopenharmony_ci  job_->FinishCompile(false);
30301cb0ef41Sopenharmony_ci  return true;
30311cb0ef41Sopenharmony_ci}
30321cb0ef41Sopenharmony_ci
30331cb0ef41Sopenharmony_ciCompilationStateImpl::CompilationStateImpl(
30341cb0ef41Sopenharmony_ci    const std::shared_ptr<NativeModule>& native_module,
30351cb0ef41Sopenharmony_ci    std::shared_ptr<Counters> async_counters, DynamicTiering dynamic_tiering)
30361cb0ef41Sopenharmony_ci    : native_module_(native_module.get()),
30371cb0ef41Sopenharmony_ci      native_module_weak_(std::move(native_module)),
30381cb0ef41Sopenharmony_ci      async_counters_(std::move(async_counters)),
30391cb0ef41Sopenharmony_ci      compilation_unit_queues_(native_module->num_functions()),
30401cb0ef41Sopenharmony_ci      dynamic_tiering_(dynamic_tiering) {}
30411cb0ef41Sopenharmony_ci
30421cb0ef41Sopenharmony_civoid CompilationStateImpl::InitCompileJob() {
30431cb0ef41Sopenharmony_ci  DCHECK_NULL(compile_job_);
30441cb0ef41Sopenharmony_ci  compile_job_ = V8::GetCurrentPlatform()->PostJob(
30451cb0ef41Sopenharmony_ci      TaskPriority::kUserVisible, std::make_unique<BackgroundCompileJob>(
30461cb0ef41Sopenharmony_ci                                      native_module_weak_, async_counters_));
30471cb0ef41Sopenharmony_ci}
30481cb0ef41Sopenharmony_ci
30491cb0ef41Sopenharmony_civoid CompilationStateImpl::CancelCompilation(
30501cb0ef41Sopenharmony_ci    CompilationStateImpl::CancellationPolicy cancellation_policy) {
30511cb0ef41Sopenharmony_ci  base::MutexGuard callbacks_guard(&callbacks_mutex_);
30521cb0ef41Sopenharmony_ci
30531cb0ef41Sopenharmony_ci  if (cancellation_policy == kCancelInitialCompilation &&
30541cb0ef41Sopenharmony_ci      finished_events_.contains(
30551cb0ef41Sopenharmony_ci          CompilationEvent::kFinishedBaselineCompilation)) {
30561cb0ef41Sopenharmony_ci    // Initial compilation already finished; cannot be cancelled.
30571cb0ef41Sopenharmony_ci    return;
30581cb0ef41Sopenharmony_ci  }
30591cb0ef41Sopenharmony_ci
30601cb0ef41Sopenharmony_ci  // std::memory_order_relaxed is sufficient because no other state is
30611cb0ef41Sopenharmony_ci  // synchronized with |compile_cancelled_|.
30621cb0ef41Sopenharmony_ci  compile_cancelled_.store(true, std::memory_order_relaxed);
30631cb0ef41Sopenharmony_ci
30641cb0ef41Sopenharmony_ci  // No more callbacks after abort.
30651cb0ef41Sopenharmony_ci  callbacks_.clear();
30661cb0ef41Sopenharmony_ci}
30671cb0ef41Sopenharmony_ci
30681cb0ef41Sopenharmony_cibool CompilationStateImpl::cancelled() const {
30691cb0ef41Sopenharmony_ci  return compile_cancelled_.load(std::memory_order_relaxed);
30701cb0ef41Sopenharmony_ci}
30711cb0ef41Sopenharmony_ci
30721cb0ef41Sopenharmony_ciuint8_t CompilationStateImpl::SetupCompilationProgressForFunction(
30731cb0ef41Sopenharmony_ci    bool lazy_function, NativeModule* native_module,
30741cb0ef41Sopenharmony_ci    const WasmFeatures& enabled_features, int func_index) {
30751cb0ef41Sopenharmony_ci  ExecutionTierPair requested_tiers =
30761cb0ef41Sopenharmony_ci      GetRequestedExecutionTiers(native_module, enabled_features, func_index);
30771cb0ef41Sopenharmony_ci  CompileStrategy strategy = GetCompileStrategy(
30781cb0ef41Sopenharmony_ci      native_module->module(), enabled_features, func_index, lazy_function);
30791cb0ef41Sopenharmony_ci
30801cb0ef41Sopenharmony_ci  bool required_for_baseline = strategy == CompileStrategy::kEager;
30811cb0ef41Sopenharmony_ci  bool required_for_top_tier = strategy != CompileStrategy::kLazy;
30821cb0ef41Sopenharmony_ci  DCHECK_EQ(required_for_top_tier,
30831cb0ef41Sopenharmony_ci            strategy == CompileStrategy::kEager ||
30841cb0ef41Sopenharmony_ci                strategy == CompileStrategy::kLazyBaselineEagerTopTier);
30851cb0ef41Sopenharmony_ci
30861cb0ef41Sopenharmony_ci  // Count functions to complete baseline and top tier compilation.
30871cb0ef41Sopenharmony_ci  if (required_for_baseline) outstanding_baseline_units_++;
30881cb0ef41Sopenharmony_ci  if (required_for_top_tier) outstanding_top_tier_functions_++;
30891cb0ef41Sopenharmony_ci
30901cb0ef41Sopenharmony_ci  // Initialize function's compilation progress.
30911cb0ef41Sopenharmony_ci  ExecutionTier required_baseline_tier = required_for_baseline
30921cb0ef41Sopenharmony_ci                                             ? requested_tiers.baseline_tier
30931cb0ef41Sopenharmony_ci                                             : ExecutionTier::kNone;
30941cb0ef41Sopenharmony_ci  ExecutionTier required_top_tier =
30951cb0ef41Sopenharmony_ci      required_for_top_tier ? requested_tiers.top_tier : ExecutionTier::kNone;
30961cb0ef41Sopenharmony_ci  uint8_t function_progress =
30971cb0ef41Sopenharmony_ci      ReachedTierField::encode(ExecutionTier::kNone) |
30981cb0ef41Sopenharmony_ci      RequiredBaselineTierField::encode(required_baseline_tier) |
30991cb0ef41Sopenharmony_ci      RequiredTopTierField::encode(required_top_tier);
31001cb0ef41Sopenharmony_ci
31011cb0ef41Sopenharmony_ci  return function_progress;
31021cb0ef41Sopenharmony_ci}
31031cb0ef41Sopenharmony_ci
31041cb0ef41Sopenharmony_civoid CompilationStateImpl::InitializeCompilationProgress(
31051cb0ef41Sopenharmony_ci    bool lazy_module, int num_import_wrappers, int num_export_wrappers) {
31061cb0ef41Sopenharmony_ci  DCHECK(!failed());
31071cb0ef41Sopenharmony_ci  auto enabled_features = native_module_->enabled_features();
31081cb0ef41Sopenharmony_ci  auto* module = native_module_->module();
31091cb0ef41Sopenharmony_ci
31101cb0ef41Sopenharmony_ci  base::MutexGuard guard(&callbacks_mutex_);
31111cb0ef41Sopenharmony_ci  DCHECK_EQ(0, outstanding_baseline_units_);
31121cb0ef41Sopenharmony_ci  DCHECK_EQ(0, outstanding_export_wrappers_);
31131cb0ef41Sopenharmony_ci  DCHECK_EQ(0, outstanding_top_tier_functions_);
31141cb0ef41Sopenharmony_ci  compilation_progress_.reserve(module->num_declared_functions);
31151cb0ef41Sopenharmony_ci  int start = module->num_imported_functions;
31161cb0ef41Sopenharmony_ci  int end = start + module->num_declared_functions;
31171cb0ef41Sopenharmony_ci
31181cb0ef41Sopenharmony_ci  const bool prefer_liftoff = native_module_->IsTieredDown();
31191cb0ef41Sopenharmony_ci  for (int func_index = start; func_index < end; func_index++) {
31201cb0ef41Sopenharmony_ci    if (prefer_liftoff) {
31211cb0ef41Sopenharmony_ci      constexpr uint8_t kLiftoffOnlyFunctionProgress =
31221cb0ef41Sopenharmony_ci          RequiredTopTierField::encode(ExecutionTier::kLiftoff) |
31231cb0ef41Sopenharmony_ci          RequiredBaselineTierField::encode(ExecutionTier::kLiftoff) |
31241cb0ef41Sopenharmony_ci          ReachedTierField::encode(ExecutionTier::kNone);
31251cb0ef41Sopenharmony_ci      compilation_progress_.push_back(kLiftoffOnlyFunctionProgress);
31261cb0ef41Sopenharmony_ci      outstanding_baseline_units_++;
31271cb0ef41Sopenharmony_ci      outstanding_top_tier_functions_++;
31281cb0ef41Sopenharmony_ci      continue;
31291cb0ef41Sopenharmony_ci    }
31301cb0ef41Sopenharmony_ci    uint8_t function_progress = SetupCompilationProgressForFunction(
31311cb0ef41Sopenharmony_ci        lazy_module, native_module_, enabled_features, func_index);
31321cb0ef41Sopenharmony_ci    compilation_progress_.push_back(function_progress);
31331cb0ef41Sopenharmony_ci  }
31341cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(lazy_module, outstanding_baseline_units_ == 0);
31351cb0ef41Sopenharmony_ci  DCHECK_IMPLIES(lazy_module, outstanding_top_tier_functions_ == 0);
31361cb0ef41Sopenharmony_ci  DCHECK_LE(0, outstanding_baseline_units_);
31371cb0ef41Sopenharmony_ci  DCHECK_LE(outstanding_baseline_units_, outstanding_top_tier_functions_);
31381cb0ef41Sopenharmony_ci  outstanding_baseline_units_ += num_import_wrappers;
31391cb0ef41Sopenharmony_ci  outstanding_export_wrappers_ = num_export_wrappers;
31401cb0ef41Sopenharmony_ci
31411cb0ef41Sopenharmony_ci  // Trigger callbacks if module needs no baseline or top tier compilation. This
31421cb0ef41Sopenharmony_ci  // can be the case for an empty or fully lazy module.
31431cb0ef41Sopenharmony_ci  TriggerCallbacks();
31441cb0ef41Sopenharmony_ci}
31451cb0ef41Sopenharmony_ci
31461cb0ef41Sopenharmony_ciuint8_t CompilationStateImpl::AddCompilationUnitInternal(
31471cb0ef41Sopenharmony_ci    CompilationUnitBuilder* builder, int function_index,
31481cb0ef41Sopenharmony_ci    uint8_t function_progress) {
31491cb0ef41Sopenharmony_ci  ExecutionTier required_baseline_tier =
31501cb0ef41Sopenharmony_ci      CompilationStateImpl::RequiredBaselineTierField::decode(
31511cb0ef41Sopenharmony_ci          function_progress);
31521cb0ef41Sopenharmony_ci  ExecutionTier required_top_tier =
31531cb0ef41Sopenharmony_ci      CompilationStateImpl::RequiredTopTierField::decode(function_progress);
31541cb0ef41Sopenharmony_ci  ExecutionTier reached_tier =
31551cb0ef41Sopenharmony_ci      CompilationStateImpl::ReachedTierField::decode(function_progress);
31561cb0ef41Sopenharmony_ci
31571cb0ef41Sopenharmony_ci  if (FLAG_experimental_wasm_gc) {
31581cb0ef41Sopenharmony_ci    // The Turbofan optimizations we enable for WasmGC code can (for now)
31591cb0ef41Sopenharmony_ci    // take a very long time, so skip Turbofan compilation for super-large
31601cb0ef41Sopenharmony_ci    // functions.
31611cb0ef41Sopenharmony_ci    // Besides, module serialization currently requires that all functions
31621cb0ef41Sopenharmony_ci    // have been TF-compiled. By enabling this limit only for WasmGC, we
31631cb0ef41Sopenharmony_ci    // make sure that non-experimental modules can be serialize as usual.
31641cb0ef41Sopenharmony_ci    // TODO(jkummerow): This is a stop-gap solution to avoid excessive
31651cb0ef41Sopenharmony_ci    // compile times. We would like to replace this hard threshold with
31661cb0ef41Sopenharmony_ci    // a better solution (TBD) eventually.
31671cb0ef41Sopenharmony_ci    constexpr uint32_t kMaxWasmFunctionSizeForTurbofan = 500 * KB;
31681cb0ef41Sopenharmony_ci    uint32_t size = builder->module()->functions[function_index].code.length();
31691cb0ef41Sopenharmony_ci    if (size > kMaxWasmFunctionSizeForTurbofan) {
31701cb0ef41Sopenharmony_ci      required_baseline_tier = ExecutionTier::kLiftoff;
31711cb0ef41Sopenharmony_ci      if (required_top_tier == ExecutionTier::kTurbofan) {
31721cb0ef41Sopenharmony_ci        required_top_tier = ExecutionTier::kLiftoff;
31731cb0ef41Sopenharmony_ci        outstanding_top_tier_functions_--;
31741cb0ef41Sopenharmony_ci      }
31751cb0ef41Sopenharmony_ci    }
31761cb0ef41Sopenharmony_ci  }
31771cb0ef41Sopenharmony_ci
31781cb0ef41Sopenharmony_ci  if (reached_tier < required_baseline_tier) {
31791cb0ef41Sopenharmony_ci    builder->AddBaselineUnit(function_index, required_baseline_tier);
31801cb0ef41Sopenharmony_ci  }
31811cb0ef41Sopenharmony_ci  if (reached_tier < required_top_tier &&
31821cb0ef41Sopenharmony_ci      required_baseline_tier != required_top_tier) {
31831cb0ef41Sopenharmony_ci    builder->AddTopTierUnit(function_index, required_top_tier);
31841cb0ef41Sopenharmony_ci  }
31851cb0ef41Sopenharmony_ci  return CompilationStateImpl::RequiredBaselineTierField::encode(
31861cb0ef41Sopenharmony_ci             required_baseline_tier) |
31871cb0ef41Sopenharmony_ci         CompilationStateImpl::RequiredTopTierField::encode(required_top_tier) |
31881cb0ef41Sopenharmony_ci         CompilationStateImpl::ReachedTierField::encode(reached_tier);
31891cb0ef41Sopenharmony_ci}
31901cb0ef41Sopenharmony_ci
31911cb0ef41Sopenharmony_civoid CompilationStateImpl::InitializeCompilationUnits(
31921cb0ef41Sopenharmony_ci    std::unique_ptr<CompilationUnitBuilder> builder) {
31931cb0ef41Sopenharmony_ci  int offset = native_module_->module()->num_imported_functions;
31941cb0ef41Sopenharmony_ci  if (native_module_->IsTieredDown()) {
31951cb0ef41Sopenharmony_ci    for (size_t i = 0; i < compilation_progress_.size(); ++i) {
31961cb0ef41Sopenharmony_ci      int func_index = offset + static_cast<int>(i);
31971cb0ef41Sopenharmony_ci      builder->AddDebugUnit(func_index);
31981cb0ef41Sopenharmony_ci    }
31991cb0ef41Sopenharmony_ci  } else {
32001cb0ef41Sopenharmony_ci    base::MutexGuard guard(&callbacks_mutex_);
32011cb0ef41Sopenharmony_ci
32021cb0ef41Sopenharmony_ci    for (size_t i = 0; i < compilation_progress_.size(); ++i) {
32031cb0ef41Sopenharmony_ci      uint8_t function_progress = compilation_progress_[i];
32041cb0ef41Sopenharmony_ci      int func_index = offset + static_cast<int>(i);
32051cb0ef41Sopenharmony_ci      compilation_progress_[i] = AddCompilationUnitInternal(
32061cb0ef41Sopenharmony_ci          builder.get(), func_index, function_progress);
32071cb0ef41Sopenharmony_ci    }
32081cb0ef41Sopenharmony_ci  }
32091cb0ef41Sopenharmony_ci  builder->Commit();
32101cb0ef41Sopenharmony_ci}
32111cb0ef41Sopenharmony_ci
32121cb0ef41Sopenharmony_civoid CompilationStateImpl::AddCompilationUnit(CompilationUnitBuilder* builder,
32131cb0ef41Sopenharmony_ci                                              int func_index) {
32141cb0ef41Sopenharmony_ci  if (native_module_->IsTieredDown()) {
32151cb0ef41Sopenharmony_ci    builder->AddDebugUnit(func_index);
32161cb0ef41Sopenharmony_ci    return;
32171cb0ef41Sopenharmony_ci  }
32181cb0ef41Sopenharmony_ci  int offset = native_module_->module()->num_imported_functions;
32191cb0ef41Sopenharmony_ci  int progress_index = func_index - offset;
32201cb0ef41Sopenharmony_ci  uint8_t function_progress;
32211cb0ef41Sopenharmony_ci  {
32221cb0ef41Sopenharmony_ci    // TODO(ahaas): This lock may cause overhead. If so, we could get rid of the
32231cb0ef41Sopenharmony_ci    // lock as follows:
32241cb0ef41Sopenharmony_ci    // 1) Make compilation_progress_ an array of atomic<uint8_t>, and access it
32251cb0ef41Sopenharmony_ci    // lock-free.
32261cb0ef41Sopenharmony_ci    // 2) Have a copy of compilation_progress_ that we use for initialization.
32271cb0ef41Sopenharmony_ci    // 3) Just re-calculate the content of compilation_progress_.
32281cb0ef41Sopenharmony_ci    base::MutexGuard guard(&callbacks_mutex_);
32291cb0ef41Sopenharmony_ci    function_progress = compilation_progress_[progress_index];
32301cb0ef41Sopenharmony_ci  }
32311cb0ef41Sopenharmony_ci  uint8_t updated_function_progress =
32321cb0ef41Sopenharmony_ci      AddCompilationUnitInternal(builder, func_index, function_progress);
32331cb0ef41Sopenharmony_ci  if (updated_function_progress != function_progress) {
32341cb0ef41Sopenharmony_ci    // This should happen very rarely (only for super-large functions), so we're
32351cb0ef41Sopenharmony_ci    // not worried about overhead.
32361cb0ef41Sopenharmony_ci    base::MutexGuard guard(&callbacks_mutex_);
32371cb0ef41Sopenharmony_ci    compilation_progress_[progress_index] = updated_function_progress;
32381cb0ef41Sopenharmony_ci  }
32391cb0ef41Sopenharmony_ci}
32401cb0ef41Sopenharmony_ci
32411cb0ef41Sopenharmony_civoid CompilationStateImpl::InitializeCompilationProgressAfterDeserialization(
32421cb0ef41Sopenharmony_ci    base::Vector<const int> lazy_functions,
32431cb0ef41Sopenharmony_ci    base::Vector<const int> liftoff_functions) {
32441cb0ef41Sopenharmony_ci  TRACE_EVENT2("v8.wasm", "wasm.CompilationAfterDeserialization",
32451cb0ef41Sopenharmony_ci               "num_lazy_functions", lazy_functions.size(),
32461cb0ef41Sopenharmony_ci               "num_liftoff_functions", liftoff_functions.size());
32471cb0ef41Sopenharmony_ci  TimedHistogramScope lazy_compile_time_scope(
32481cb0ef41Sopenharmony_ci      counters()->wasm_compile_after_deserialize());
32491cb0ef41Sopenharmony_ci
32501cb0ef41Sopenharmony_ci  auto* module = native_module_->module();
32511cb0ef41Sopenharmony_ci  auto enabled_features = native_module_->enabled_features();
32521cb0ef41Sopenharmony_ci  const bool lazy_module = IsLazyModule(module);
32531cb0ef41Sopenharmony_ci  base::Optional<CodeSpaceWriteScope> lazy_code_space_write_scope;
32541cb0ef41Sopenharmony_ci  if (lazy_module || !lazy_functions.empty()) {
32551cb0ef41Sopenharmony_ci    lazy_code_space_write_scope.emplace(native_module_);
32561cb0ef41Sopenharmony_ci  }
32571cb0ef41Sopenharmony_ci  {
32581cb0ef41Sopenharmony_ci    base::MutexGuard guard(&callbacks_mutex_);
32591cb0ef41Sopenharmony_ci    DCHECK(compilation_progress_.empty());
32601cb0ef41Sopenharmony_ci    constexpr uint8_t kProgressAfterTurbofanDeserialization =
32611cb0ef41Sopenharmony_ci        RequiredBaselineTierField::encode(ExecutionTier::kTurbofan) |
32621cb0ef41Sopenharmony_ci        RequiredTopTierField::encode(ExecutionTier::kTurbofan) |
32631cb0ef41Sopenharmony_ci        ReachedTierField::encode(ExecutionTier::kTurbofan);
32641cb0ef41Sopenharmony_ci    finished_events_.Add(CompilationEvent::kFinishedExportWrappers);
32651cb0ef41Sopenharmony_ci    if (liftoff_functions.empty() || lazy_module) {
32661cb0ef41Sopenharmony_ci      // We have to trigger the compilation events to finish compilation.
32671cb0ef41Sopenharmony_ci      // Typically the events get triggered when a CompilationUnit finishes, but
32681cb0ef41Sopenharmony_ci      // with lazy compilation there are no compilation units.
32691cb0ef41Sopenharmony_ci      // The {kFinishedBaselineCompilation} event is needed for module
32701cb0ef41Sopenharmony_ci      // compilation to finish.
32711cb0ef41Sopenharmony_ci      finished_events_.Add(CompilationEvent::kFinishedBaselineCompilation);
32721cb0ef41Sopenharmony_ci      if (liftoff_functions.empty() && lazy_functions.empty()) {
32731cb0ef41Sopenharmony_ci        // All functions exist now as TurboFan functions, so we can trigger the
32741cb0ef41Sopenharmony_ci        // {kFinishedTopTierCompilation} event.
32751cb0ef41Sopenharmony_ci        // The {kFinishedTopTierCompilation} event is needed for the C-API so
32761cb0ef41Sopenharmony_ci        // that {serialize()} works after {deserialize()}.
32771cb0ef41Sopenharmony_ci        finished_events_.Add(CompilationEvent::kFinishedTopTierCompilation);
32781cb0ef41Sopenharmony_ci      }
32791cb0ef41Sopenharmony_ci    }
32801cb0ef41Sopenharmony_ci    compilation_progress_.assign(module->num_declared_functions,
32811cb0ef41Sopenharmony_ci                                 kProgressAfterTurbofanDeserialization);
32821cb0ef41Sopenharmony_ci    for (auto func_index : lazy_functions) {
32831cb0ef41Sopenharmony_ci      native_module_->UseLazyStub(func_index);
32841cb0ef41Sopenharmony_ci
32851cb0ef41Sopenharmony_ci      compilation_progress_[declared_function_index(module, func_index)] =
32861cb0ef41Sopenharmony_ci          SetupCompilationProgressForFunction(/*lazy_function =*/true,
32871cb0ef41Sopenharmony_ci                                              native_module_, enabled_features,
32881cb0ef41Sopenharmony_ci                                              func_index);
32891cb0ef41Sopenharmony_ci    }
32901cb0ef41Sopenharmony_ci    for (auto func_index : liftoff_functions) {
32911cb0ef41Sopenharmony_ci      if (lazy_module) {
32921cb0ef41Sopenharmony_ci        native_module_->UseLazyStub(func_index);
32931cb0ef41Sopenharmony_ci      }
32941cb0ef41Sopenharmony_ci      // Check that {func_index} is not contained in {lazy_functions}.
32951cb0ef41Sopenharmony_ci      DCHECK_EQ(
32961cb0ef41Sopenharmony_ci          compilation_progress_[declared_function_index(module, func_index)],
32971cb0ef41Sopenharmony_ci          kProgressAfterTurbofanDeserialization);
32981cb0ef41Sopenharmony_ci      compilation_progress_[declared_function_index(module, func_index)] =
32991cb0ef41Sopenharmony_ci          SetupCompilationProgressForFunction(lazy_module, native_module_,
33001cb0ef41Sopenharmony_ci                                              enabled_features, func_index);
33011cb0ef41Sopenharmony_ci    }
33021cb0ef41Sopenharmony_ci  }
33031cb0ef41Sopenharmony_ci  auto builder = std::make_unique<CompilationUnitBuilder>(native_module_);
33041cb0ef41Sopenharmony_ci  InitializeCompilationUnits(std::move(builder));
33051cb0ef41Sopenharmony_ci  WaitForCompilationEvent(CompilationEvent::kFinishedBaselineCompilation);
33061cb0ef41Sopenharmony_ci}
33071cb0ef41Sopenharmony_ci
33081cb0ef41Sopenharmony_civoid CompilationStateImpl::InitializeRecompilation(
33091cb0ef41Sopenharmony_ci    TieringState new_tiering_state,
33101cb0ef41Sopenharmony_ci    std::unique_ptr<CompilationEventCallback> recompilation_finished_callback) {
33111cb0ef41Sopenharmony_ci  DCHECK(!failed());
33121cb0ef41Sopenharmony_ci
33131cb0ef41Sopenharmony_ci  // Hold the mutex as long as possible, to synchronize between multiple
33141cb0ef41Sopenharmony_ci  // recompilations that are triggered at the same time (e.g. when the profiler
33151cb0ef41Sopenharmony_ci  // is disabled).
33161cb0ef41Sopenharmony_ci  base::Optional<base::MutexGuard> guard(&callbacks_mutex_);
33171cb0ef41Sopenharmony_ci
33181cb0ef41Sopenharmony_ci  // As long as there are outstanding recompilation functions, take part in
33191cb0ef41Sopenharmony_ci  // compilation. This is to avoid recompiling for the same tier or for
33201cb0ef41Sopenharmony_ci  // different tiers concurrently. Note that the compilation unit queues can run
33211cb0ef41Sopenharmony_ci  // empty before {outstanding_recompilation_functions_} drops to zero. In this
33221cb0ef41Sopenharmony_ci  // case, we do not wait for the last running compilation threads to finish
33231cb0ef41Sopenharmony_ci  // their units, but just start our own recompilation already.
33241cb0ef41Sopenharmony_ci  while (outstanding_recompilation_functions_ > 0 &&
33251cb0ef41Sopenharmony_ci         compilation_unit_queues_.GetTotalSize() > 0) {
33261cb0ef41Sopenharmony_ci    guard.reset();
33271cb0ef41Sopenharmony_ci    constexpr JobDelegate* kNoDelegate = nullptr;
33281cb0ef41Sopenharmony_ci    ExecuteCompilationUnits(native_module_weak_, async_counters_.get(),
33291cb0ef41Sopenharmony_ci                            kNoDelegate, kBaselineOrTopTier);
33301cb0ef41Sopenharmony_ci    guard.emplace(&callbacks_mutex_);
33311cb0ef41Sopenharmony_ci  }
33321cb0ef41Sopenharmony_ci
33331cb0ef41Sopenharmony_ci  // Information about compilation progress is shared between this class and the
33341cb0ef41Sopenharmony_ci  // NativeModule. Before updating information here, consult the NativeModule to
33351cb0ef41Sopenharmony_ci  // find all functions that need recompilation.
33361cb0ef41Sopenharmony_ci  // Since the current tiering state is updated on the NativeModule before
33371cb0ef41Sopenharmony_ci  // triggering recompilation, it's OK if the information is slightly outdated.
33381cb0ef41Sopenharmony_ci  // If we compile functions twice, the NativeModule will ignore all redundant
33391cb0ef41Sopenharmony_ci  // code (or code compiled for the wrong tier).
33401cb0ef41Sopenharmony_ci  std::vector<int> recompile_function_indexes =
33411cb0ef41Sopenharmony_ci      native_module_->FindFunctionsToRecompile(new_tiering_state);
33421cb0ef41Sopenharmony_ci
33431cb0ef41Sopenharmony_ci  callbacks_.emplace_back(std::move(recompilation_finished_callback));
33441cb0ef41Sopenharmony_ci  tiering_state_ = new_tiering_state;
33451cb0ef41Sopenharmony_ci
33461cb0ef41Sopenharmony_ci  // If compilation progress is not initialized yet, then compilation didn't
33471cb0ef41Sopenharmony_ci  // start yet, and new code will be kept tiered-down from the start. For
33481cb0ef41Sopenharmony_ci  // streaming compilation, there is a special path to tier down later, when
33491cb0ef41Sopenharmony_ci  // the module is complete. In any case, we don't need to recompile here.
33501cb0ef41Sopenharmony_ci  base::Optional<CompilationUnitBuilder> builder;
33511cb0ef41Sopenharmony_ci  if (compilation_progress_.size() > 0) {
33521cb0ef41Sopenharmony_ci    builder.emplace(native_module_);
33531cb0ef41Sopenharmony_ci    const WasmModule* module = native_module_->module();
33541cb0ef41Sopenharmony_ci    DCHECK_EQ(module->num_declared_functions, compilation_progress_.size());
33551cb0ef41Sopenharmony_ci    DCHECK_GE(module->num_declared_functions,
33561cb0ef41Sopenharmony_ci              recompile_function_indexes.size());
33571cb0ef41Sopenharmony_ci    outstanding_recompilation_functions_ =
33581cb0ef41Sopenharmony_ci        static_cast<int>(recompile_function_indexes.size());
33591cb0ef41Sopenharmony_ci    // Restart recompilation if another recompilation is already happening.
33601cb0ef41Sopenharmony_ci    for (auto& progress : compilation_progress_) {
33611cb0ef41Sopenharmony_ci      progress = MissingRecompilationField::update(progress, false);
33621cb0ef41Sopenharmony_ci    }
33631cb0ef41Sopenharmony_ci    auto new_tier = new_tiering_state == kTieredDown ? ExecutionTier::kLiftoff
33641cb0ef41Sopenharmony_ci                                                     : ExecutionTier::kTurbofan;
33651cb0ef41Sopenharmony_ci    int imported = module->num_imported_functions;
33661cb0ef41Sopenharmony_ci    // Generate necessary compilation units on the fly.
33671cb0ef41Sopenharmony_ci    for (int function_index : recompile_function_indexes) {
33681cb0ef41Sopenharmony_ci      DCHECK_LE(imported, function_index);
33691cb0ef41Sopenharmony_ci      int slot_index = function_index - imported;
33701cb0ef41Sopenharmony_ci      auto& progress = compilation_progress_[slot_index];
33711cb0ef41Sopenharmony_ci      progress = MissingRecompilationField::update(progress, true);
33721cb0ef41Sopenharmony_ci      builder->AddRecompilationUnit(function_index, new_tier);
33731cb0ef41Sopenharmony_ci    }
33741cb0ef41Sopenharmony_ci  }
33751cb0ef41Sopenharmony_ci
33761cb0ef41Sopenharmony_ci  // Trigger callback if module needs no recompilation.
33771cb0ef41Sopenharmony_ci  if (outstanding_recompilation_functions_ == 0) {
33781cb0ef41Sopenharmony_ci    TriggerCallbacks(base::EnumSet<CompilationEvent>(
33791cb0ef41Sopenharmony_ci        {CompilationEvent::kFinishedRecompilation}));
33801cb0ef41Sopenharmony_ci  }
33811cb0ef41Sopenharmony_ci
33821cb0ef41Sopenharmony_ci  if (builder.has_value()) {
33831cb0ef41Sopenharmony_ci    // Avoid holding lock while scheduling a compile job.
33841cb0ef41Sopenharmony_ci    guard.reset();
33851cb0ef41Sopenharmony_ci    builder->Commit();
33861cb0ef41Sopenharmony_ci  }
33871cb0ef41Sopenharmony_ci}
33881cb0ef41Sopenharmony_ci
33891cb0ef41Sopenharmony_civoid CompilationStateImpl::AddCallback(
33901cb0ef41Sopenharmony_ci    std::unique_ptr<CompilationEventCallback> callback) {
33911cb0ef41Sopenharmony_ci  base::MutexGuard callbacks_guard(&callbacks_mutex_);
33921cb0ef41Sopenharmony_ci  // Immediately trigger events that already happened.
33931cb0ef41Sopenharmony_ci  for (auto event : {CompilationEvent::kFinishedExportWrappers,
33941cb0ef41Sopenharmony_ci                     CompilationEvent::kFinishedBaselineCompilation,
33951cb0ef41Sopenharmony_ci                     CompilationEvent::kFinishedTopTierCompilation,
33961cb0ef41Sopenharmony_ci                     CompilationEvent::kFailedCompilation}) {
33971cb0ef41Sopenharmony_ci    if (finished_events_.contains(event)) {
33981cb0ef41Sopenharmony_ci      callback->call(event);
33991cb0ef41Sopenharmony_ci    }
34001cb0ef41Sopenharmony_ci  }
34011cb0ef41Sopenharmony_ci  constexpr base::EnumSet<CompilationEvent> kFinalEvents{
34021cb0ef41Sopenharmony_ci      CompilationEvent::kFinishedTopTierCompilation,
34031cb0ef41Sopenharmony_ci      CompilationEvent::kFailedCompilation};
34041cb0ef41Sopenharmony_ci  if (!finished_events_.contains_any(kFinalEvents)) {
34051cb0ef41Sopenharmony_ci    callbacks_.emplace_back(std::move(callback));
34061cb0ef41Sopenharmony_ci  }
34071cb0ef41Sopenharmony_ci}
34081cb0ef41Sopenharmony_ci
34091cb0ef41Sopenharmony_civoid CompilationStateImpl::CommitCompilationUnits(
34101cb0ef41Sopenharmony_ci    base::Vector<WasmCompilationUnit> baseline_units,
34111cb0ef41Sopenharmony_ci    base::Vector<WasmCompilationUnit> top_tier_units,
34121cb0ef41Sopenharmony_ci    base::Vector<std::shared_ptr<JSToWasmWrapperCompilationUnit>>
34131cb0ef41Sopenharmony_ci        js_to_wasm_wrapper_units) {
34141cb0ef41Sopenharmony_ci  if (!js_to_wasm_wrapper_units.empty()) {
34151cb0ef41Sopenharmony_ci    // |js_to_wasm_wrapper_units_| will only be initialized once.
34161cb0ef41Sopenharmony_ci    DCHECK_EQ(0, outstanding_js_to_wasm_wrappers_.load());
34171cb0ef41Sopenharmony_ci    js_to_wasm_wrapper_units_.insert(js_to_wasm_wrapper_units_.end(),
34181cb0ef41Sopenharmony_ci                                     js_to_wasm_wrapper_units.begin(),
34191cb0ef41Sopenharmony_ci                                     js_to_wasm_wrapper_units.end());
34201cb0ef41Sopenharmony_ci    // Use release semantics such that updates to {js_to_wasm_wrapper_units_}
34211cb0ef41Sopenharmony_ci    // are available to other threads doing an acquire load.
34221cb0ef41Sopenharmony_ci    outstanding_js_to_wasm_wrappers_.store(js_to_wasm_wrapper_units.size(),
34231cb0ef41Sopenharmony_ci                                           std::memory_order_release);
34241cb0ef41Sopenharmony_ci  }
34251cb0ef41Sopenharmony_ci  if (!baseline_units.empty() || !top_tier_units.empty()) {
34261cb0ef41Sopenharmony_ci    compilation_unit_queues_.AddUnits(baseline_units, top_tier_units,
34271cb0ef41Sopenharmony_ci                                      native_module_->module());
34281cb0ef41Sopenharmony_ci  }
34291cb0ef41Sopenharmony_ci  compile_job_->NotifyConcurrencyIncrease();
34301cb0ef41Sopenharmony_ci}
34311cb0ef41Sopenharmony_ci
34321cb0ef41Sopenharmony_civoid CompilationStateImpl::CommitTopTierCompilationUnit(
34331cb0ef41Sopenharmony_ci    WasmCompilationUnit unit) {
34341cb0ef41Sopenharmony_ci  CommitCompilationUnits({}, {&unit, 1}, {});
34351cb0ef41Sopenharmony_ci}
34361cb0ef41Sopenharmony_ci
34371cb0ef41Sopenharmony_civoid CompilationStateImpl::AddTopTierPriorityCompilationUnit(
34381cb0ef41Sopenharmony_ci    WasmCompilationUnit unit, size_t priority) {
34391cb0ef41Sopenharmony_ci  compilation_unit_queues_.AddTopTierPriorityUnit(unit, priority);
34401cb0ef41Sopenharmony_ci  {
34411cb0ef41Sopenharmony_ci    base::MutexGuard guard(&callbacks_mutex_);
34421cb0ef41Sopenharmony_ci    outstanding_top_tier_functions_++;
34431cb0ef41Sopenharmony_ci  }
34441cb0ef41Sopenharmony_ci  compile_job_->NotifyConcurrencyIncrease();
34451cb0ef41Sopenharmony_ci}
34461cb0ef41Sopenharmony_ci
34471cb0ef41Sopenharmony_cistd::shared_ptr<JSToWasmWrapperCompilationUnit>
34481cb0ef41Sopenharmony_ciCompilationStateImpl::GetNextJSToWasmWrapperCompilationUnit() {
34491cb0ef41Sopenharmony_ci  size_t outstanding_units =
34501cb0ef41Sopenharmony_ci      outstanding_js_to_wasm_wrappers_.load(std::memory_order_relaxed);
34511cb0ef41Sopenharmony_ci  // Use acquire semantics such that initialization of
34521cb0ef41Sopenharmony_ci  // {js_to_wasm_wrapper_units_} is available.
34531cb0ef41Sopenharmony_ci  while (outstanding_units &&
34541cb0ef41Sopenharmony_ci         !outstanding_js_to_wasm_wrappers_.compare_exchange_weak(
34551cb0ef41Sopenharmony_ci             outstanding_units, outstanding_units - 1,
34561cb0ef41Sopenharmony_ci             std::memory_order_acquire)) {
34571cb0ef41Sopenharmony_ci    // Retry with updated {outstanding_units}.
34581cb0ef41Sopenharmony_ci  }
34591cb0ef41Sopenharmony_ci  if (outstanding_units == 0) return nullptr;
34601cb0ef41Sopenharmony_ci  return js_to_wasm_wrapper_units_[outstanding_units - 1];
34611cb0ef41Sopenharmony_ci}
34621cb0ef41Sopenharmony_ci
34631cb0ef41Sopenharmony_civoid CompilationStateImpl::FinalizeJSToWasmWrappers(
34641cb0ef41Sopenharmony_ci    Isolate* isolate, const WasmModule* module,
34651cb0ef41Sopenharmony_ci    Handle<FixedArray>* export_wrappers_out) {
34661cb0ef41Sopenharmony_ci  *export_wrappers_out = isolate->factory()->NewFixedArray(
34671cb0ef41Sopenharmony_ci      MaxNumExportWrappers(module), AllocationType::kOld);
34681cb0ef41Sopenharmony_ci  // TODO(6792): Wrappers below are allocated with {Factory::NewCode}. As an
34691cb0ef41Sopenharmony_ci  // optimization we create a code memory modification scope that avoids
34701cb0ef41Sopenharmony_ci  // changing the page permissions back-and-forth between RWX and RX, because
34711cb0ef41Sopenharmony_ci  // many such wrapper are allocated in sequence below.
34721cb0ef41Sopenharmony_ci  TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed"),
34731cb0ef41Sopenharmony_ci               "wasm.FinalizeJSToWasmWrappers", "wrappers",
34741cb0ef41Sopenharmony_ci               js_to_wasm_wrapper_units_.size());
34751cb0ef41Sopenharmony_ci  CodePageCollectionMemoryModificationScope modification_scope(isolate->heap());
34761cb0ef41Sopenharmony_ci  for (auto& unit : js_to_wasm_wrapper_units_) {
34771cb0ef41Sopenharmony_ci    DCHECK_EQ(isolate, unit->isolate());
34781cb0ef41Sopenharmony_ci    Handle<Code> code = unit->Finalize();
34791cb0ef41Sopenharmony_ci    int wrapper_index =
34801cb0ef41Sopenharmony_ci        GetExportWrapperIndex(module, unit->sig(), unit->is_import());
34811cb0ef41Sopenharmony_ci    (*export_wrappers_out)->set(wrapper_index, ToCodeT(*code));
34821cb0ef41Sopenharmony_ci    RecordStats(*code, isolate->counters());
34831cb0ef41Sopenharmony_ci  }
34841cb0ef41Sopenharmony_ci}
34851cb0ef41Sopenharmony_ci
34861cb0ef41Sopenharmony_ciCompilationUnitQueues::Queue* CompilationStateImpl::GetQueueForCompileTask(
34871cb0ef41Sopenharmony_ci    int task_id) {
34881cb0ef41Sopenharmony_ci  return compilation_unit_queues_.GetQueueForTask(task_id);
34891cb0ef41Sopenharmony_ci}
34901cb0ef41Sopenharmony_ci
34911cb0ef41Sopenharmony_cibase::Optional<WasmCompilationUnit>
34921cb0ef41Sopenharmony_ciCompilationStateImpl::GetNextCompilationUnit(
34931cb0ef41Sopenharmony_ci    CompilationUnitQueues::Queue* queue, CompileBaselineOnly baseline_only) {
34941cb0ef41Sopenharmony_ci  return compilation_unit_queues_.GetNextUnit(queue, baseline_only);
34951cb0ef41Sopenharmony_ci}
34961cb0ef41Sopenharmony_ci
34971cb0ef41Sopenharmony_civoid CompilationStateImpl::OnFinishedUnits(
34981cb0ef41Sopenharmony_ci    base::Vector<WasmCode*> code_vector) {
34991cb0ef41Sopenharmony_ci  TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("v8.wasm.detailed"),
35001cb0ef41Sopenharmony_ci               "wasm.OnFinishedUnits", "units", code_vector.size());
35011cb0ef41Sopenharmony_ci
35021cb0ef41Sopenharmony_ci  base::MutexGuard guard(&callbacks_mutex_);
35031cb0ef41Sopenharmony_ci
35041cb0ef41Sopenharmony_ci  // In case of no outstanding compilation units we can return early.
35051cb0ef41Sopenharmony_ci  // This is especially important for lazy modules that were deserialized.
35061cb0ef41Sopenharmony_ci  // Compilation progress was not set up in these cases.
35071cb0ef41Sopenharmony_ci  if (outstanding_baseline_units_ == 0 && outstanding_export_wrappers_ == 0 &&
35081cb0ef41Sopenharmony_ci      outstanding_top_tier_functions_ == 0 &&
35091cb0ef41Sopenharmony_ci      outstanding_recompilation_functions_ == 0) {
35101cb0ef41Sopenharmony_ci    return;
35111cb0ef41Sopenharmony_ci  }
35121cb0ef41Sopenharmony_ci
35131cb0ef41Sopenharmony_ci  // Assume an order of execution tiers that represents the quality of their
35141cb0ef41Sopenharmony_ci  // generated code.
35151cb0ef41Sopenharmony_ci  static_assert(ExecutionTier::kNone < ExecutionTier::kLiftoff &&
35161cb0ef41Sopenharmony_ci                    ExecutionTier::kLiftoff < ExecutionTier::kTurbofan,
35171cb0ef41Sopenharmony_ci                "Assume an order on execution tiers");
35181cb0ef41Sopenharmony_ci
35191cb0ef41Sopenharmony_ci  DCHECK_EQ(compilation_progress_.size(),
35201cb0ef41Sopenharmony_ci            native_module_->module()->num_declared_functions);
35211cb0ef41Sopenharmony_ci
35221cb0ef41Sopenharmony_ci  base::EnumSet<CompilationEvent> triggered_events;
35231cb0ef41Sopenharmony_ci
35241cb0ef41Sopenharmony_ci  for (size_t i = 0; i < code_vector.size(); i++) {
35251cb0ef41Sopenharmony_ci    WasmCode* code = code_vector[i];
35261cb0ef41Sopenharmony_ci    DCHECK_NOT_NULL(code);
35271cb0ef41Sopenharmony_ci    DCHECK_LT(code->index(), native_module_->num_functions());
35281cb0ef41Sopenharmony_ci
35291cb0ef41Sopenharmony_ci    if (code->index() <
35301cb0ef41Sopenharmony_ci        static_cast<int>(native_module_->num_imported_functions())) {
35311cb0ef41Sopenharmony_ci      // Import wrapper.
35321cb0ef41Sopenharmony_ci      DCHECK_EQ(code->tier(), ExecutionTier::kTurbofan);
35331cb0ef41Sopenharmony_ci      outstanding_baseline_units_--;
35341cb0ef41Sopenharmony_ci    } else {
35351cb0ef41Sopenharmony_ci      // Function.
35361cb0ef41Sopenharmony_ci      DCHECK_NE(code->tier(), ExecutionTier::kNone);
35371cb0ef41Sopenharmony_ci
35381cb0ef41Sopenharmony_ci      // Read function's compilation progress.
35391cb0ef41Sopenharmony_ci      // This view on the compilation progress may differ from the actually
35401cb0ef41Sopenharmony_ci      // compiled code. Any lazily compiled function does not contribute to the
35411cb0ef41Sopenharmony_ci      // compilation progress but may publish code to the code manager.
35421cb0ef41Sopenharmony_ci      int slot_index =
35431cb0ef41Sopenharmony_ci          declared_function_index(native_module_->module(), code->index());
35441cb0ef41Sopenharmony_ci      uint8_t function_progress = compilation_progress_[slot_index];
35451cb0ef41Sopenharmony_ci      ExecutionTier required_baseline_tier =
35461cb0ef41Sopenharmony_ci          RequiredBaselineTierField::decode(function_progress);
35471cb0ef41Sopenharmony_ci      ExecutionTier required_top_tier =
35481cb0ef41Sopenharmony_ci          RequiredTopTierField::decode(function_progress);
35491cb0ef41Sopenharmony_ci      ExecutionTier reached_tier = ReachedTierField::decode(function_progress);
35501cb0ef41Sopenharmony_ci
35511cb0ef41Sopenharmony_ci      // Check whether required baseline or top tier are reached.
35521cb0ef41Sopenharmony_ci      if (reached_tier < required_baseline_tier &&
35531cb0ef41Sopenharmony_ci          required_baseline_tier <= code->tier()) {
35541cb0ef41Sopenharmony_ci        DCHECK_GT(outstanding_baseline_units_, 0);
35551cb0ef41Sopenharmony_ci        outstanding_baseline_units_--;
35561cb0ef41Sopenharmony_ci      }
35571cb0ef41Sopenharmony_ci      if (code->tier() == ExecutionTier::kTurbofan) {
35581cb0ef41Sopenharmony_ci        bytes_since_last_chunk_ += code->instructions().size();
35591cb0ef41Sopenharmony_ci      }
35601cb0ef41Sopenharmony_ci      if (reached_tier < required_top_tier &&
35611cb0ef41Sopenharmony_ci          required_top_tier <= code->tier()) {
35621cb0ef41Sopenharmony_ci        DCHECK_GT(outstanding_top_tier_functions_, 0);
35631cb0ef41Sopenharmony_ci        outstanding_top_tier_functions_--;
35641cb0ef41Sopenharmony_ci      }
35651cb0ef41Sopenharmony_ci
35661cb0ef41Sopenharmony_ci      if (V8_UNLIKELY(MissingRecompilationField::decode(function_progress))) {
35671cb0ef41Sopenharmony_ci        DCHECK_LT(0, outstanding_recompilation_functions_);
35681cb0ef41Sopenharmony_ci        // If tiering up, accept any TurboFan code. For tiering down, look at
35691cb0ef41Sopenharmony_ci        // the {for_debugging} flag. The tier can be Liftoff or TurboFan and is
35701cb0ef41Sopenharmony_ci        // irrelevant here. In particular, we want to ignore any outstanding
35711cb0ef41Sopenharmony_ci        // non-debugging units.
35721cb0ef41Sopenharmony_ci        bool matches = tiering_state_ == kTieredDown
35731cb0ef41Sopenharmony_ci                           ? code->for_debugging()
35741cb0ef41Sopenharmony_ci                           : code->tier() == ExecutionTier::kTurbofan;
35751cb0ef41Sopenharmony_ci        if (matches) {
35761cb0ef41Sopenharmony_ci          outstanding_recompilation_functions_--;
35771cb0ef41Sopenharmony_ci          compilation_progress_[slot_index] = MissingRecompilationField::update(
35781cb0ef41Sopenharmony_ci              compilation_progress_[slot_index], false);
35791cb0ef41Sopenharmony_ci          if (outstanding_recompilation_functions_ == 0) {
35801cb0ef41Sopenharmony_ci            triggered_events.Add(CompilationEvent::kFinishedRecompilation);
35811cb0ef41Sopenharmony_ci          }
35821cb0ef41Sopenharmony_ci        }
35831cb0ef41Sopenharmony_ci      }
35841cb0ef41Sopenharmony_ci
35851cb0ef41Sopenharmony_ci      // Update function's compilation progress.
35861cb0ef41Sopenharmony_ci      if (code->tier() > reached_tier) {
35871cb0ef41Sopenharmony_ci        compilation_progress_[slot_index] = ReachedTierField::update(
35881cb0ef41Sopenharmony_ci            compilation_progress_[slot_index], code->tier());
35891cb0ef41Sopenharmony_ci      }
35901cb0ef41Sopenharmony_ci      DCHECK_LE(0, outstanding_baseline_units_);
35911cb0ef41Sopenharmony_ci    }
35921cb0ef41Sopenharmony_ci  }
35931cb0ef41Sopenharmony_ci
35941cb0ef41Sopenharmony_ci  TriggerCallbacks(triggered_events);
35951cb0ef41Sopenharmony_ci}
35961cb0ef41Sopenharmony_ci
35971cb0ef41Sopenharmony_civoid CompilationStateImpl::OnFinishedJSToWasmWrapperUnits(int num) {
35981cb0ef41Sopenharmony_ci  if (num == 0) return;
35991cb0ef41Sopenharmony_ci  base::MutexGuard guard(&callbacks_mutex_);
36001cb0ef41Sopenharmony_ci  DCHECK_GE(outstanding_export_wrappers_, num);
36011cb0ef41Sopenharmony_ci  outstanding_export_wrappers_ -= num;
36021cb0ef41Sopenharmony_ci  TriggerCallbacks();
36031cb0ef41Sopenharmony_ci}
36041cb0ef41Sopenharmony_ci
36051cb0ef41Sopenharmony_civoid CompilationStateImpl::TriggerCallbacks(
36061cb0ef41Sopenharmony_ci    base::EnumSet<CompilationEvent> triggered_events) {
36071cb0ef41Sopenharmony_ci  DCHECK(!callbacks_mutex_.TryLock());
36081cb0ef41Sopenharmony_ci
36091cb0ef41Sopenharmony_ci  if (outstanding_export_wrappers_ == 0) {
36101cb0ef41Sopenharmony_ci    triggered_events.Add(CompilationEvent::kFinishedExportWrappers);
36111cb0ef41Sopenharmony_ci    if (outstanding_baseline_units_ == 0) {
36121cb0ef41Sopenharmony_ci      triggered_events.Add(CompilationEvent::kFinishedBaselineCompilation);
36131cb0ef41Sopenharmony_ci      if (dynamic_tiering_ == DynamicTiering::kDisabled &&
36141cb0ef41Sopenharmony_ci          outstanding_top_tier_functions_ == 0) {
36151cb0ef41Sopenharmony_ci        triggered_events.Add(CompilationEvent::kFinishedTopTierCompilation);
36161cb0ef41Sopenharmony_ci      }
36171cb0ef41Sopenharmony_ci    }
36181cb0ef41Sopenharmony_ci  }
36191cb0ef41Sopenharmony_ci
36201cb0ef41Sopenharmony_ci  if (dynamic_tiering_ == DynamicTiering::kEnabled &&
36211cb0ef41Sopenharmony_ci      static_cast<size_t>(FLAG_wasm_caching_threshold) <
36221cb0ef41Sopenharmony_ci          bytes_since_last_chunk_) {
36231cb0ef41Sopenharmony_ci    triggered_events.Add(CompilationEvent::kFinishedCompilationChunk);
36241cb0ef41Sopenharmony_ci    bytes_since_last_chunk_ = 0;
36251cb0ef41Sopenharmony_ci  }
36261cb0ef41Sopenharmony_ci  if (compile_failed_.load(std::memory_order_relaxed)) {
36271cb0ef41Sopenharmony_ci    // *Only* trigger the "failed" event.
36281cb0ef41Sopenharmony_ci    triggered_events =
36291cb0ef41Sopenharmony_ci        base::EnumSet<CompilationEvent>({CompilationEvent::kFailedCompilation});
36301cb0ef41Sopenharmony_ci  }
36311cb0ef41Sopenharmony_ci
36321cb0ef41Sopenharmony_ci  if (triggered_events.empty()) return;
36331cb0ef41Sopenharmony_ci
36341cb0ef41Sopenharmony_ci  // Don't trigger past events again.
36351cb0ef41Sopenharmony_ci  triggered_events -= finished_events_;
36361cb0ef41Sopenharmony_ci  // Recompilation can happen multiple times, thus do not store this. There can
36371cb0ef41Sopenharmony_ci  // also be multiple compilation chunks.
36381cb0ef41Sopenharmony_ci  finished_events_ |= triggered_events -
36391cb0ef41Sopenharmony_ci                      CompilationEvent::kFinishedRecompilation -
36401cb0ef41Sopenharmony_ci                      CompilationEvent::kFinishedCompilationChunk;
36411cb0ef41Sopenharmony_ci
36421cb0ef41Sopenharmony_ci  for (auto event :
36431cb0ef41Sopenharmony_ci       {std::make_pair(CompilationEvent::kFailedCompilation,
36441cb0ef41Sopenharmony_ci                       "wasm.CompilationFailed"),
36451cb0ef41Sopenharmony_ci        std::make_pair(CompilationEvent::kFinishedExportWrappers,
36461cb0ef41Sopenharmony_ci                       "wasm.ExportWrappersFinished"),
36471cb0ef41Sopenharmony_ci        std::make_pair(CompilationEvent::kFinishedBaselineCompilation,
36481cb0ef41Sopenharmony_ci                       "wasm.BaselineFinished"),
36491cb0ef41Sopenharmony_ci        std::make_pair(CompilationEvent::kFinishedTopTierCompilation,
36501cb0ef41Sopenharmony_ci                       "wasm.TopTierFinished"),
36511cb0ef41Sopenharmony_ci        std::make_pair(CompilationEvent::kFinishedCompilationChunk,
36521cb0ef41Sopenharmony_ci                       "wasm.CompilationChunkFinished"),
36531cb0ef41Sopenharmony_ci        std::make_pair(CompilationEvent::kFinishedRecompilation,
36541cb0ef41Sopenharmony_ci                       "wasm.RecompilationFinished")}) {
36551cb0ef41Sopenharmony_ci    if (!triggered_events.contains(event.first)) continue;
36561cb0ef41Sopenharmony_ci    DCHECK_NE(compilation_id_, kInvalidCompilationID);
36571cb0ef41Sopenharmony_ci    TRACE_EVENT1("v8.wasm", event.second, "id", compilation_id_);
36581cb0ef41Sopenharmony_ci    for (auto& callback : callbacks_) {
36591cb0ef41Sopenharmony_ci      callback->call(event.first);
36601cb0ef41Sopenharmony_ci    }
36611cb0ef41Sopenharmony_ci  }
36621cb0ef41Sopenharmony_ci
36631cb0ef41Sopenharmony_ci  if (outstanding_baseline_units_ == 0 && outstanding_export_wrappers_ == 0 &&
36641cb0ef41Sopenharmony_ci      outstanding_top_tier_functions_ == 0 &&
36651cb0ef41Sopenharmony_ci      outstanding_recompilation_functions_ == 0) {
36661cb0ef41Sopenharmony_ci    callbacks_.erase(
36671cb0ef41Sopenharmony_ci        std::remove_if(
36681cb0ef41Sopenharmony_ci            callbacks_.begin(), callbacks_.end(),
36691cb0ef41Sopenharmony_ci            [](std::unique_ptr<CompilationEventCallback>& event) {
36701cb0ef41Sopenharmony_ci              return event->release_after_final_event() ==
36711cb0ef41Sopenharmony_ci                     CompilationEventCallback::ReleaseAfterFinalEvent::kRelease;
36721cb0ef41Sopenharmony_ci            }),
36731cb0ef41Sopenharmony_ci        callbacks_.end());
36741cb0ef41Sopenharmony_ci  }
36751cb0ef41Sopenharmony_ci}
36761cb0ef41Sopenharmony_ci
36771cb0ef41Sopenharmony_civoid CompilationStateImpl::OnCompilationStopped(WasmFeatures detected) {
36781cb0ef41Sopenharmony_ci  base::MutexGuard guard(&mutex_);
36791cb0ef41Sopenharmony_ci  detected_features_.Add(detected);
36801cb0ef41Sopenharmony_ci}
36811cb0ef41Sopenharmony_ci
36821cb0ef41Sopenharmony_civoid CompilationStateImpl::PublishDetectedFeatures(Isolate* isolate) {
36831cb0ef41Sopenharmony_ci  // Notifying the isolate of the feature counts must take place under
36841cb0ef41Sopenharmony_ci  // the mutex, because even if we have finished baseline compilation,
36851cb0ef41Sopenharmony_ci  // tiering compilations may still occur in the background.
36861cb0ef41Sopenharmony_ci  base::MutexGuard guard(&mutex_);
36871cb0ef41Sopenharmony_ci  UpdateFeatureUseCounts(isolate, detected_features_);
36881cb0ef41Sopenharmony_ci}
36891cb0ef41Sopenharmony_ci
36901cb0ef41Sopenharmony_civoid CompilationStateImpl::PublishCompilationResults(
36911cb0ef41Sopenharmony_ci    std::vector<std::unique_ptr<WasmCode>> unpublished_code) {
36921cb0ef41Sopenharmony_ci  if (unpublished_code.empty()) return;
36931cb0ef41Sopenharmony_ci
36941cb0ef41Sopenharmony_ci  // For import wrapper compilation units, add result to the cache.
36951cb0ef41Sopenharmony_ci  int num_imported_functions = native_module_->num_imported_functions();
36961cb0ef41Sopenharmony_ci  WasmImportWrapperCache* cache = native_module_->import_wrapper_cache();
36971cb0ef41Sopenharmony_ci  for (const auto& code : unpublished_code) {
36981cb0ef41Sopenharmony_ci    int func_index = code->index();
36991cb0ef41Sopenharmony_ci    DCHECK_LE(0, func_index);
37001cb0ef41Sopenharmony_ci    DCHECK_LT(func_index, native_module_->num_functions());
37011cb0ef41Sopenharmony_ci    if (func_index < num_imported_functions) {
37021cb0ef41Sopenharmony_ci      const FunctionSig* sig =
37031cb0ef41Sopenharmony_ci          native_module_->module()->functions[func_index].sig;
37041cb0ef41Sopenharmony_ci      WasmImportWrapperCache::CacheKey key(
37051cb0ef41Sopenharmony_ci          compiler::kDefaultImportCallKind, sig,
37061cb0ef41Sopenharmony_ci          static_cast<int>(sig->parameter_count()), kNoSuspend);
37071cb0ef41Sopenharmony_ci      // If two imported functions have the same key, only one of them should
37081cb0ef41Sopenharmony_ci      // have been added as a compilation unit. So it is always the first time
37091cb0ef41Sopenharmony_ci      // we compile a wrapper for this key here.
37101cb0ef41Sopenharmony_ci      DCHECK_NULL((*cache)[key]);
37111cb0ef41Sopenharmony_ci      (*cache)[key] = code.get();
37121cb0ef41Sopenharmony_ci      code->IncRef();
37131cb0ef41Sopenharmony_ci    }
37141cb0ef41Sopenharmony_ci  }
37151cb0ef41Sopenharmony_ci  PublishCode(base::VectorOf(unpublished_code));
37161cb0ef41Sopenharmony_ci}
37171cb0ef41Sopenharmony_ci
37181cb0ef41Sopenharmony_civoid CompilationStateImpl::PublishCode(
37191cb0ef41Sopenharmony_ci    base::Vector<std::unique_ptr<WasmCode>> code) {
37201cb0ef41Sopenharmony_ci  WasmCodeRefScope code_ref_scope;
37211cb0ef41Sopenharmony_ci  std::vector<WasmCode*> published_code =
37221cb0ef41Sopenharmony_ci      native_module_->PublishCode(std::move(code));
37231cb0ef41Sopenharmony_ci  // Defer logging code in case wire bytes were not fully received yet.
37241cb0ef41Sopenharmony_ci  if (native_module_->HasWireBytes()) {
37251cb0ef41Sopenharmony_ci    GetWasmEngine()->LogCode(base::VectorOf(published_code));
37261cb0ef41Sopenharmony_ci  }
37271cb0ef41Sopenharmony_ci
37281cb0ef41Sopenharmony_ci  OnFinishedUnits(base::VectorOf(std::move(published_code)));
37291cb0ef41Sopenharmony_ci}
37301cb0ef41Sopenharmony_ci
37311cb0ef41Sopenharmony_civoid CompilationStateImpl::SchedulePublishCompilationResults(
37321cb0ef41Sopenharmony_ci    std::vector<std::unique_ptr<WasmCode>> unpublished_code) {
37331cb0ef41Sopenharmony_ci  {
37341cb0ef41Sopenharmony_ci    base::MutexGuard guard(&publish_mutex_);
37351cb0ef41Sopenharmony_ci    if (publisher_running_) {
37361cb0ef41Sopenharmony_ci      // Add new code to the queue and return.
37371cb0ef41Sopenharmony_ci      publish_queue_.reserve(publish_queue_.size() + unpublished_code.size());
37381cb0ef41Sopenharmony_ci      for (auto& c : unpublished_code) {
37391cb0ef41Sopenharmony_ci        publish_queue_.emplace_back(std::move(c));
37401cb0ef41Sopenharmony_ci      }
37411cb0ef41Sopenharmony_ci      return;
37421cb0ef41Sopenharmony_ci    }
37431cb0ef41Sopenharmony_ci    publisher_running_ = true;
37441cb0ef41Sopenharmony_ci  }
37451cb0ef41Sopenharmony_ci  CodeSpaceWriteScope code_space_write_scope(native_module_);
37461cb0ef41Sopenharmony_ci  while (true) {
37471cb0ef41Sopenharmony_ci    PublishCompilationResults(std::move(unpublished_code));
37481cb0ef41Sopenharmony_ci    unpublished_code.clear();
37491cb0ef41Sopenharmony_ci
37501cb0ef41Sopenharmony_ci    // Keep publishing new code that came in.
37511cb0ef41Sopenharmony_ci    base::MutexGuard guard(&publish_mutex_);
37521cb0ef41Sopenharmony_ci    DCHECK(publisher_running_);
37531cb0ef41Sopenharmony_ci    if (publish_queue_.empty()) {
37541cb0ef41Sopenharmony_ci      publisher_running_ = false;
37551cb0ef41Sopenharmony_ci      return;
37561cb0ef41Sopenharmony_ci    }
37571cb0ef41Sopenharmony_ci    unpublished_code.swap(publish_queue_);
37581cb0ef41Sopenharmony_ci  }
37591cb0ef41Sopenharmony_ci}
37601cb0ef41Sopenharmony_ci
37611cb0ef41Sopenharmony_cisize_t CompilationStateImpl::NumOutstandingCompilations() const {
37621cb0ef41Sopenharmony_ci  size_t outstanding_wrappers =
37631cb0ef41Sopenharmony_ci      outstanding_js_to_wasm_wrappers_.load(std::memory_order_relaxed);
37641cb0ef41Sopenharmony_ci  size_t outstanding_functions = compilation_unit_queues_.GetTotalSize();
37651cb0ef41Sopenharmony_ci  return outstanding_wrappers + outstanding_functions;
37661cb0ef41Sopenharmony_ci}
37671cb0ef41Sopenharmony_ci
37681cb0ef41Sopenharmony_civoid CompilationStateImpl::SetError() {
37691cb0ef41Sopenharmony_ci  compile_cancelled_.store(true, std::memory_order_relaxed);
37701cb0ef41Sopenharmony_ci  if (compile_failed_.exchange(true, std::memory_order_relaxed)) {
37711cb0ef41Sopenharmony_ci    return;  // Already failed before.
37721cb0ef41Sopenharmony_ci  }
37731cb0ef41Sopenharmony_ci
37741cb0ef41Sopenharmony_ci  base::MutexGuard callbacks_guard(&callbacks_mutex_);
37751cb0ef41Sopenharmony_ci  TriggerCallbacks();
37761cb0ef41Sopenharmony_ci  callbacks_.clear();
37771cb0ef41Sopenharmony_ci}
37781cb0ef41Sopenharmony_ci
37791cb0ef41Sopenharmony_civoid CompilationStateImpl::WaitForCompilationEvent(
37801cb0ef41Sopenharmony_ci    CompilationEvent expect_event) {
37811cb0ef41Sopenharmony_ci  class WaitForCompilationEventCallback : public CompilationEventCallback {
37821cb0ef41Sopenharmony_ci   public:
37831cb0ef41Sopenharmony_ci    WaitForCompilationEventCallback(std::shared_ptr<base::Semaphore> semaphore,
37841cb0ef41Sopenharmony_ci                                    std::shared_ptr<std::atomic<bool>> done,
37851cb0ef41Sopenharmony_ci                                    base::EnumSet<CompilationEvent> events)
37861cb0ef41Sopenharmony_ci        : semaphore_(std::move(semaphore)),
37871cb0ef41Sopenharmony_ci          done_(std::move(done)),
37881cb0ef41Sopenharmony_ci          events_(events) {}
37891cb0ef41Sopenharmony_ci
37901cb0ef41Sopenharmony_ci    void call(CompilationEvent event) override {
37911cb0ef41Sopenharmony_ci      if (!events_.contains(event)) return;
37921cb0ef41Sopenharmony_ci      done_->store(true, std::memory_order_relaxed);
37931cb0ef41Sopenharmony_ci      semaphore_->Signal();
37941cb0ef41Sopenharmony_ci    }
37951cb0ef41Sopenharmony_ci
37961cb0ef41Sopenharmony_ci   private:
37971cb0ef41Sopenharmony_ci    std::shared_ptr<base::Semaphore> semaphore_;
37981cb0ef41Sopenharmony_ci    std::shared_ptr<std::atomic<bool>> done_;
37991cb0ef41Sopenharmony_ci    base::EnumSet<CompilationEvent> events_;
38001cb0ef41Sopenharmony_ci  };
38011cb0ef41Sopenharmony_ci
38021cb0ef41Sopenharmony_ci  auto semaphore = std::make_shared<base::Semaphore>(0);
38031cb0ef41Sopenharmony_ci  auto done = std::make_shared<std::atomic<bool>>(false);
38041cb0ef41Sopenharmony_ci  base::EnumSet<CompilationEvent> events{expect_event,
38051cb0ef41Sopenharmony_ci                                         CompilationEvent::kFailedCompilation};
38061cb0ef41Sopenharmony_ci  {
38071cb0ef41Sopenharmony_ci    base::MutexGuard callbacks_guard(&callbacks_mutex_);
38081cb0ef41Sopenharmony_ci    if (finished_events_.contains_any(events)) return;
38091cb0ef41Sopenharmony_ci    callbacks_.emplace_back(std::make_unique<WaitForCompilationEventCallback>(
38101cb0ef41Sopenharmony_ci        semaphore, done, events));
38111cb0ef41Sopenharmony_ci  }
38121cb0ef41Sopenharmony_ci
38131cb0ef41Sopenharmony_ci  class WaitForEventDelegate final : public JobDelegate {
38141cb0ef41Sopenharmony_ci   public:
38151cb0ef41Sopenharmony_ci    explicit WaitForEventDelegate(std::shared_ptr<std::atomic<bool>> done)
38161cb0ef41Sopenharmony_ci        : done_(std::move(done)) {}
38171cb0ef41Sopenharmony_ci
38181cb0ef41Sopenharmony_ci    bool ShouldYield() override {
38191cb0ef41Sopenharmony_ci      return done_->load(std::memory_order_relaxed);
38201cb0ef41Sopenharmony_ci    }
38211cb0ef41Sopenharmony_ci
38221cb0ef41Sopenharmony_ci    bool IsJoiningThread() const override { return true; }
38231cb0ef41Sopenharmony_ci
38241cb0ef41Sopenharmony_ci    void NotifyConcurrencyIncrease() override { UNIMPLEMENTED(); }
38251cb0ef41Sopenharmony_ci
38261cb0ef41Sopenharmony_ci    uint8_t GetTaskId() override { return kMainTaskId; }
38271cb0ef41Sopenharmony_ci
38281cb0ef41Sopenharmony_ci   private:
38291cb0ef41Sopenharmony_ci    std::shared_ptr<std::atomic<bool>> done_;
38301cb0ef41Sopenharmony_ci  };
38311cb0ef41Sopenharmony_ci
38321cb0ef41Sopenharmony_ci  WaitForEventDelegate delegate{done};
38331cb0ef41Sopenharmony_ci  // Everything except for top-tier units will be processed with kBaselineOnly
38341cb0ef41Sopenharmony_ci  // (including wrappers). Hence we choose this for any event except
38351cb0ef41Sopenharmony_ci  // {kFinishedTopTierCompilation}.
38361cb0ef41Sopenharmony_ci  auto compile_tiers =
38371cb0ef41Sopenharmony_ci      expect_event == CompilationEvent::kFinishedTopTierCompilation
38381cb0ef41Sopenharmony_ci          ? kBaselineOrTopTier
38391cb0ef41Sopenharmony_ci          : kBaselineOnly;
38401cb0ef41Sopenharmony_ci  ExecuteCompilationUnits(native_module_weak_, async_counters_.get(), &delegate,
38411cb0ef41Sopenharmony_ci                          compile_tiers);
38421cb0ef41Sopenharmony_ci  semaphore->Wait();
38431cb0ef41Sopenharmony_ci}
38441cb0ef41Sopenharmony_ci
38451cb0ef41Sopenharmony_cinamespace {
38461cb0ef41Sopenharmony_ciusing JSToWasmWrapperQueue =
38471cb0ef41Sopenharmony_ci    WrapperQueue<JSToWasmWrapperKey, base::hash<JSToWasmWrapperKey>>;
38481cb0ef41Sopenharmony_ciusing JSToWasmWrapperUnitMap =
38491cb0ef41Sopenharmony_ci    std::unordered_map<JSToWasmWrapperKey,
38501cb0ef41Sopenharmony_ci                       std::unique_ptr<JSToWasmWrapperCompilationUnit>,
38511cb0ef41Sopenharmony_ci                       base::hash<JSToWasmWrapperKey>>;
38521cb0ef41Sopenharmony_ci
38531cb0ef41Sopenharmony_ciclass CompileJSToWasmWrapperJob final : public JobTask {
38541cb0ef41Sopenharmony_ci public:
38551cb0ef41Sopenharmony_ci  CompileJSToWasmWrapperJob(JSToWasmWrapperQueue* queue,
38561cb0ef41Sopenharmony_ci                            JSToWasmWrapperUnitMap* compilation_units)
38571cb0ef41Sopenharmony_ci      : queue_(queue),
38581cb0ef41Sopenharmony_ci        compilation_units_(compilation_units),
38591cb0ef41Sopenharmony_ci        outstanding_units_(queue->size()) {}
38601cb0ef41Sopenharmony_ci
38611cb0ef41Sopenharmony_ci  void Run(JobDelegate* delegate) override {
38621cb0ef41Sopenharmony_ci    while (base::Optional<JSToWasmWrapperKey> key = queue_->pop()) {
38631cb0ef41Sopenharmony_ci      JSToWasmWrapperCompilationUnit* unit = (*compilation_units_)[*key].get();
38641cb0ef41Sopenharmony_ci      unit->Execute();
38651cb0ef41Sopenharmony_ci      outstanding_units_.fetch_sub(1, std::memory_order_relaxed);
38661cb0ef41Sopenharmony_ci      if (delegate && delegate->ShouldYield()) return;
38671cb0ef41Sopenharmony_ci    }
38681cb0ef41Sopenharmony_ci  }
38691cb0ef41Sopenharmony_ci
38701cb0ef41Sopenharmony_ci  size_t GetMaxConcurrency(size_t /* worker_count */) const override {
38711cb0ef41Sopenharmony_ci    DCHECK_GE(FLAG_wasm_num_compilation_tasks, 1);
38721cb0ef41Sopenharmony_ci    // {outstanding_units_} includes the units that other workers are currently
38731cb0ef41Sopenharmony_ci    // working on, so we can safely ignore the {worker_count} and just return
38741cb0ef41Sopenharmony_ci    // the current number of outstanding units.
38751cb0ef41Sopenharmony_ci    return std::min(static_cast<size_t>(FLAG_wasm_num_compilation_tasks),
38761cb0ef41Sopenharmony_ci                    outstanding_units_.load(std::memory_order_relaxed));
38771cb0ef41Sopenharmony_ci  }
38781cb0ef41Sopenharmony_ci
38791cb0ef41Sopenharmony_ci private:
38801cb0ef41Sopenharmony_ci  JSToWasmWrapperQueue* const queue_;
38811cb0ef41Sopenharmony_ci  JSToWasmWrapperUnitMap* const compilation_units_;
38821cb0ef41Sopenharmony_ci  std::atomic<size_t> outstanding_units_;
38831cb0ef41Sopenharmony_ci};
38841cb0ef41Sopenharmony_ci}  // namespace
38851cb0ef41Sopenharmony_ci
38861cb0ef41Sopenharmony_civoid CompileJsToWasmWrappers(Isolate* isolate, const WasmModule* module,
38871cb0ef41Sopenharmony_ci                             Handle<FixedArray>* export_wrappers_out) {
38881cb0ef41Sopenharmony_ci  TRACE_EVENT0("v8.wasm", "wasm.CompileJsToWasmWrappers");
38891cb0ef41Sopenharmony_ci  *export_wrappers_out = isolate->factory()->NewFixedArray(
38901cb0ef41Sopenharmony_ci      MaxNumExportWrappers(module), AllocationType::kOld);
38911cb0ef41Sopenharmony_ci
38921cb0ef41Sopenharmony_ci  JSToWasmWrapperQueue queue;
38931cb0ef41Sopenharmony_ci  JSToWasmWrapperUnitMap compilation_units;
38941cb0ef41Sopenharmony_ci  WasmFeatures enabled_features = WasmFeatures::FromIsolate(isolate);
38951cb0ef41Sopenharmony_ci
38961cb0ef41Sopenharmony_ci  // Prepare compilation units in the main thread.
38971cb0ef41Sopenharmony_ci  for (auto exp : module->export_table) {
38981cb0ef41Sopenharmony_ci    if (exp.kind != kExternalFunction) continue;
38991cb0ef41Sopenharmony_ci    auto& function = module->functions[exp.index];
39001cb0ef41Sopenharmony_ci    JSToWasmWrapperKey key(function.imported, *function.sig);
39011cb0ef41Sopenharmony_ci    if (queue.insert(key)) {
39021cb0ef41Sopenharmony_ci      auto unit = std::make_unique<JSToWasmWrapperCompilationUnit>(
39031cb0ef41Sopenharmony_ci          isolate, function.sig, module, function.imported, enabled_features,
39041cb0ef41Sopenharmony_ci          JSToWasmWrapperCompilationUnit::kAllowGeneric);
39051cb0ef41Sopenharmony_ci      compilation_units.emplace(key, std::move(unit));
39061cb0ef41Sopenharmony_ci    }
39071cb0ef41Sopenharmony_ci  }
39081cb0ef41Sopenharmony_ci
39091cb0ef41Sopenharmony_ci  {
39101cb0ef41Sopenharmony_ci    // This is nested inside the event above, so the name can be less
39111cb0ef41Sopenharmony_ci    // descriptive. It's mainly to log the number of wrappers.
39121cb0ef41Sopenharmony_ci    TRACE_EVENT1("v8.wasm", "wasm.JsToWasmWrapperCompilation", "num_wrappers",
39131cb0ef41Sopenharmony_ci                 compilation_units.size());
39141cb0ef41Sopenharmony_ci    auto job =
39151cb0ef41Sopenharmony_ci        std::make_unique<CompileJSToWasmWrapperJob>(&queue, &compilation_units);
39161cb0ef41Sopenharmony_ci    if (FLAG_wasm_num_compilation_tasks > 0) {
39171cb0ef41Sopenharmony_ci      auto job_handle = V8::GetCurrentPlatform()->PostJob(
39181cb0ef41Sopenharmony_ci          TaskPriority::kUserVisible, std::move(job));
39191cb0ef41Sopenharmony_ci
39201cb0ef41Sopenharmony_ci      // Wait for completion, while contributing to the work.
39211cb0ef41Sopenharmony_ci      job_handle->Join();
39221cb0ef41Sopenharmony_ci    } else {
39231cb0ef41Sopenharmony_ci      job->Run(nullptr);
39241cb0ef41Sopenharmony_ci    }
39251cb0ef41Sopenharmony_ci  }
39261cb0ef41Sopenharmony_ci
39271cb0ef41Sopenharmony_ci  // Finalize compilation jobs in the main thread.
39281cb0ef41Sopenharmony_ci  // TODO(6792): Wrappers below are allocated with {Factory::NewCode}. As an
39291cb0ef41Sopenharmony_ci  // optimization we create a code memory modification scope that avoids
39301cb0ef41Sopenharmony_ci  // changing the page permissions back-and-forth between RWX and RX, because
39311cb0ef41Sopenharmony_ci  // many such wrapper are allocated in sequence below.
39321cb0ef41Sopenharmony_ci  CodePageCollectionMemoryModificationScope modification_scope(isolate->heap());
39331cb0ef41Sopenharmony_ci  for (auto& pair : compilation_units) {
39341cb0ef41Sopenharmony_ci    JSToWasmWrapperKey key = pair.first;
39351cb0ef41Sopenharmony_ci    JSToWasmWrapperCompilationUnit* unit = pair.second.get();
39361cb0ef41Sopenharmony_ci    DCHECK_EQ(isolate, unit->isolate());
39371cb0ef41Sopenharmony_ci    Handle<Code> code = unit->Finalize();
39381cb0ef41Sopenharmony_ci    int wrapper_index = GetExportWrapperIndex(module, &key.second, key.first);
39391cb0ef41Sopenharmony_ci    (*export_wrappers_out)->set(wrapper_index, ToCodeT(*code));
39401cb0ef41Sopenharmony_ci    RecordStats(*code, isolate->counters());
39411cb0ef41Sopenharmony_ci  }
39421cb0ef41Sopenharmony_ci}
39431cb0ef41Sopenharmony_ci
39441cb0ef41Sopenharmony_ciWasmCode* CompileImportWrapper(
39451cb0ef41Sopenharmony_ci    NativeModule* native_module, Counters* counters,
39461cb0ef41Sopenharmony_ci    compiler::WasmImportCallKind kind, const FunctionSig* sig,
39471cb0ef41Sopenharmony_ci    int expected_arity, Suspend suspend,
39481cb0ef41Sopenharmony_ci    WasmImportWrapperCache::ModificationScope* cache_scope) {
39491cb0ef41Sopenharmony_ci  // Entry should exist, so that we don't insert a new one and invalidate
39501cb0ef41Sopenharmony_ci  // other threads' iterators/references, but it should not have been compiled
39511cb0ef41Sopenharmony_ci  // yet.
39521cb0ef41Sopenharmony_ci  WasmImportWrapperCache::CacheKey key(kind, sig, expected_arity, suspend);
39531cb0ef41Sopenharmony_ci  DCHECK_NULL((*cache_scope)[key]);
39541cb0ef41Sopenharmony_ci  bool source_positions = is_asmjs_module(native_module->module());
39551cb0ef41Sopenharmony_ci  // Keep the {WasmCode} alive until we explicitly call {IncRef}.
39561cb0ef41Sopenharmony_ci  WasmCodeRefScope code_ref_scope;
39571cb0ef41Sopenharmony_ci  CompilationEnv env = native_module->CreateCompilationEnv();
39581cb0ef41Sopenharmony_ci  WasmCompilationResult result = compiler::CompileWasmImportCallWrapper(
39591cb0ef41Sopenharmony_ci      &env, kind, sig, source_positions, expected_arity, suspend);
39601cb0ef41Sopenharmony_ci  WasmCode* published_code;
39611cb0ef41Sopenharmony_ci  {
39621cb0ef41Sopenharmony_ci    CodeSpaceWriteScope code_space_write_scope(native_module);
39631cb0ef41Sopenharmony_ci    std::unique_ptr<WasmCode> wasm_code = native_module->AddCode(
39641cb0ef41Sopenharmony_ci        result.func_index, result.code_desc, result.frame_slot_count,
39651cb0ef41Sopenharmony_ci        result.tagged_parameter_slots,
39661cb0ef41Sopenharmony_ci        result.protected_instructions_data.as_vector(),
39671cb0ef41Sopenharmony_ci        result.source_positions.as_vector(), GetCodeKind(result),
39681cb0ef41Sopenharmony_ci        ExecutionTier::kNone, kNoDebugging);
39691cb0ef41Sopenharmony_ci    published_code = native_module->PublishCode(std::move(wasm_code));
39701cb0ef41Sopenharmony_ci  }
39711cb0ef41Sopenharmony_ci  (*cache_scope)[key] = published_code;
39721cb0ef41Sopenharmony_ci  published_code->IncRef();
39731cb0ef41Sopenharmony_ci  counters->wasm_generated_code_size()->Increment(
39741cb0ef41Sopenharmony_ci      published_code->instructions().length());
39751cb0ef41Sopenharmony_ci  counters->wasm_reloc_size()->Increment(published_code->reloc_info().length());
39761cb0ef41Sopenharmony_ci  return published_code;
39771cb0ef41Sopenharmony_ci}
39781cb0ef41Sopenharmony_ci
39791cb0ef41Sopenharmony_ci}  // namespace wasm
39801cb0ef41Sopenharmony_ci}  // namespace internal
39811cb0ef41Sopenharmony_ci}  // namespace v8
39821cb0ef41Sopenharmony_ci
39831cb0ef41Sopenharmony_ci#undef TRACE_COMPILE
39841cb0ef41Sopenharmony_ci#undef TRACE_STREAMING
39851cb0ef41Sopenharmony_ci#undef TRACE_LAZY
3986