43#define TRACE_COMPILE(...) \
45 if (v8_flags.trace_wasm_compiler) PrintF(__VA_ARGS__); \
48#define TRACE_STREAMING(...) \
50 if (v8_flags.trace_wasm_streaming) PrintF(__VA_ARGS__); \
53#define TRACE_LAZY(...) \
55 if (v8_flags.trace_wasm_lazy_compilation) PrintF(__VA_ARGS__); \
62enum class CompileStrategy : uint8_t {
82class CompilationStateImpl;
83class CompilationUnitBuilder;
87 explicit BackgroundCompileScope(std::weak_ptr<NativeModule> native_module)
90 NativeModule* native_module()
const {
94 inline CompilationStateImpl* compilation_state()
const;
96 bool cancelled()
const;
103enum CompilationTier {
kBaseline = 0, kTopTier = 1, kNumTiers = kTopTier + 1 };
108class CompilationUnitQueues {
112 bool ShouldPublish(
int num_processed_units)
const;
115 explicit CompilationUnitQueues(
int num_imported_functions,
116 int num_declared_functions)
120 queues_.emplace_back(std::make_unique<QueueImpl>(0));
122#if !defined(__cpp_lib_atomic_value_initialization) || \
123 __cpp_lib_atomic_value_initialization < 201911L
124 for (
auto& atomic_counter : num_units_) {
125 std::atomic_init(&atomic_counter,
size_t{0});
130 std::make_unique<std::atomic<bool>[]>(num_declared_functions);
132#if !defined(__cpp_lib_atomic_value_initialization) || \
133 __cpp_lib_atomic_value_initialization < 201911L
134 for (
int i = 0;
i < num_declared_functions;
i++) {
140 Queue* GetQueueForTask(
int task_id) {
141 int required_queues = task_id + 1;
151 int num_queues =
static_cast<int>(
queues_.size());
152 while (num_queues < required_queues) {
153 int steal_from = num_queues + 1;
154 queues_.emplace_back(std::make_unique<QueueImpl>(steal_from));
167 int min = std::max(10, units_per_thread / 8);
169 for (
auto& queue : queues_) {
171 int limit = min + (min * queue_id / num_queues);
172 queue->publish_limit.store(limit, std::memory_order_relaxed);
179 std::optional<WasmCompilationUnit> GetNextUnit(Queue* queue,
180 CompilationTier tier) {
181 DCHECK_LT(tier, CompilationTier::kNumTiers);
182 if (
auto unit = GetNextUnitOfTier(queue, tier)) {
183 [[maybe_unused]]
size_t old_units_count =
184 num_units_[tier].fetch_sub(1, std::memory_order_relaxed);
191 void AddUnits(base::Vector<WasmCompilationUnit> baseline_units,
192 base::Vector<WasmCompilationUnit> top_tier_units,
194 DCHECK_LT(0, baseline_units.size() + top_tier_units.size());
202 queue_to_add, next_task_id(queue_to_add,
queues_.size()),
203 std::memory_order_relaxed)) {
206 queue =
queues_[queue_to_add].get();
210 std::optional<base::MutexGuard> big_units_guard;
212 {std::make_pair(CompilationTier::kBaseline, baseline_units),
213 std::make_pair(CompilationTier::kTopTier, top_tier_units)}) {
214 int tier = pair.first;
215 base::Vector<WasmCompilationUnit>
units = pair.second;
216 if (
units.empty())
continue;
219 size_t func_size =
module->functions[unit.func_index()].code.length();
221 queue->units[tier].push_back(
unit);
223 if (!big_units_guard) {
227 std::memory_order_relaxed);
234 void AddTopTierPriorityUnit(WasmCompilationUnit
unit,
size_t priority) {
247 queue_to_add, next_task_id(queue_to_add,
queues_.size()),
248 std::memory_order_relaxed)) {
253 auto* queue =
queues_[queue_to_add].get();
257 num_units_[CompilationTier::kTopTier].fetch_add(
258 1, std::memory_order_relaxed);
265 size_t GetSizeForTier(CompilationTier tier)
const {
266 DCHECK_LT(tier, CompilationTier::kNumTiers);
267 return num_units_[tier].load(std::memory_order_relaxed);
270 void AllowAnotherTopTierJob(uint32_t func_index) {
272 false, std::memory_order_relaxed);
275 size_t EstimateCurrentMemoryConsumption()
const;
289 bool operator<(
const BigUnit& other)
const {
294 struct TopTierPriorityUnit {
295 TopTierPriorityUnit(
int priority, WasmCompilationUnit unit)
299 WasmCompilationUnit
unit;
301 bool operator<(
const TopTierPriorityUnit& other)
const {
306 struct BigUnitsQueue {
308#if !defined(__cpp_lib_atomic_value_initialization) || \
309 __cpp_lib_atomic_value_initialization < 201911L
310 for (
auto& atomic : has_units) std::atomic_init(&atomic,
false);
317 std::atomic<bool>
has_units[CompilationTier::kNumTiers];
320 std::priority_queue<BigUnit>
units[CompilationTier::kNumTiers];
323 struct QueueImpl :
public Queue {
336 std::vector<WasmCompilationUnit>
units[CompilationTier::kNumTiers];
341 int next_task_id(
int task_id,
size_t num_queues)
const {
342 int next = task_id + 1;
343 return next ==
static_cast<int>(num_queues) ? 0 : next;
346 std::optional<WasmCompilationUnit> GetNextUnitOfTier(Queue* public_queue,
348 QueueImpl* queue =
static_cast<QueueImpl*
>(public_queue);
351 if (tier == CompilationTier::kTopTier) {
352 if (
auto unit = GetTopTierPriorityUnit(queue)) {
358 if (
auto unit = GetBigUnitOfTier(tier))
return unit;
365 if (!queue->units[tier].empty()) {
366 auto unit = queue->units[tier].back();
367 queue->units[tier].pop_back();
370 steal_task_id = queue->next_steal_task_id;
377 for (
size_t steal_trials = 0; steal_trials <
queues_.size();
378 ++steal_trials, ++steal_task_id) {
379 if (steal_task_id >=
static_cast<int>(
queues_.size())) {
382 if (
auto unit = StealUnitsAndGetFirst(queue, steal_task_id, tier)) {
392 std::optional<WasmCompilationUnit> GetBigUnitOfTier(
int tier) {
407 std::optional<WasmCompilationUnit> GetTopTierPriorityUnit(QueueImpl* queue) {
416 while (!queue->top_tier_priority_units.empty()) {
417 auto unit = queue->top_tier_priority_units.top().unit;
418 queue->top_tier_priority_units.pop();
422 .exchange(
true, std::memory_order_relaxed)) {
425 num_units_[CompilationTier::kTopTier].fetch_sub(
426 1, std::memory_order_relaxed);
428 steal_task_id = queue->next_steal_task_id;
435 for (
size_t steal_trials = 0; steal_trials <
queues_.size();
436 ++steal_trials, ++steal_task_id) {
437 if (steal_task_id >=
static_cast<int>(
queues_.size())) {
440 if (
auto unit = StealTopTierPriorityUnit(queue, steal_task_id)) {
453 std::optional<WasmCompilationUnit> StealUnitsAndGetFirst(
454 QueueImpl* queue,
int steal_from_task_id,
int wanted_tier) {
455 auto* steal_queue =
queues_[steal_from_task_id].get();
457 if (steal_queue == queue)
return {};
458 std::vector<WasmCompilationUnit> stolen;
459 std::optional<WasmCompilationUnit> returned_unit;
462 auto* steal_from_vector = &steal_queue->units[wanted_tier];
463 if (steal_from_vector->empty())
return {};
464 size_t remaining = steal_from_vector->size() / 2;
465 auto steal_begin = steal_from_vector->begin() + remaining;
466 returned_unit = *steal_begin;
467 stolen.assign(steal_begin + 1, steal_from_vector->end());
468 steal_from_vector->erase(steal_begin, steal_from_vector->end());
471 auto* target_queue = &queue->units[wanted_tier];
472 target_queue->insert(target_queue->end(), stolen.begin(), stolen.end());
473 queue->next_steal_task_id = steal_from_task_id + 1;
474 return returned_unit;
480 std::optional<WasmCompilationUnit> StealTopTierPriorityUnit(
481 QueueImpl* queue,
int steal_from_task_id) {
482 auto* steal_queue =
queues_[steal_from_task_id].get();
484 if (steal_queue == queue)
return {};
485 std::optional<WasmCompilationUnit> returned_unit;
489 if (steal_queue->top_tier_priority_units.empty())
return {};
491 auto unit = steal_queue->top_tier_priority_units.top().unit;
492 steal_queue->top_tier_priority_units.pop();
496 .exchange(
true, std::memory_order_relaxed)) {
497 returned_unit =
unit;
500 num_units_[CompilationTier::kTopTier].fetch_sub(
501 1, std::memory_order_relaxed);
505 queue->next_steal_task_id = steal_from_task_id + 1;
506 return returned_unit;
510 DCHECK_LE(num_imported_functions_, func_index);
511 DCHECK_LT(func_index, num_imported_functions_ + num_declared_functions_);
517 std::vector<std::unique_ptr<QueueImpl>>
queues_;
530size_t CompilationUnitQueues::EstimateCurrentMemoryConsumption()
const {
540 for (
const auto& q :
queues_) {
541 base::MutexGuard guard(&q->mutex);
543 result += q->top_tier_priority_units.size() *
sizeof(TopTierPriorityUnit);
556bool CompilationUnitQueues::Queue::ShouldPublish(
557 int num_processed_units)
const {
558 auto* queue =
static_cast<const QueueImpl*
>(
this);
559 return num_processed_units >=
560 queue->publish_limit.load(std::memory_order_relaxed);
568class CompilationStateImpl {
570 CompilationStateImpl(
const std::shared_ptr<NativeModule>& native_module,
571 std::shared_ptr<Counters> async_counters,
572 WasmDetectedFeatures detected_features);
573 ~CompilationStateImpl() {
584 void InitCompileJob();
589 enum CancellationPolicy { kCancelUnconditionally, kCancelInitialCompilation };
590 void CancelCompilation(CancellationPolicy);
592 bool cancelled()
const;
596 void ApplyCompilationHintToInitialProgress(
const WasmCompilationHint& hint,
601 void ApplyPgoInfoToInitialProgress(ProfileInformation* pgo_info);
605 void ApplyPgoInfoLate(ProfileInformation* pgo_info);
610 void InitializeCompilationProgress(ProfileInformation* pgo_info);
612 void InitializeCompilationProgressAfterDeserialization(
613 base::Vector<const int> lazy_functions,
614 base::Vector<const int> eager_functions);
618 void InitializeCompilationUnits(
619 std::unique_ptr<CompilationUnitBuilder> builder);
624 void AddCompilationUnit(CompilationUnitBuilder* builder,
int func_index);
629 void AddCallback(std::unique_ptr<CompilationEventCallback>
callback);
632 void CommitCompilationUnits(base::Vector<WasmCompilationUnit> baseline_units,
633 base::Vector<WasmCompilationUnit> top_tier_units);
634 void CommitTopTierCompilationUnit(WasmCompilationUnit);
635 void AddTopTierPriorityCompilationUnit(WasmCompilationUnit,
size_t);
637 CompilationUnitQueues::Queue* GetQueueForCompileTask(
int task_id);
639 std::optional<WasmCompilationUnit> GetNextCompilationUnit(
640 CompilationUnitQueues::Queue*, CompilationTier tier);
642 void OnFinishedUnits(base::Vector<WasmCode*>);
644 void OnCompilationStopped(WasmDetectedFeatures detected);
645 void SchedulePublishCompilationResults(
646 std::vector<UnpublishedWasmCode> unpublished_code, CompilationTier tier);
648 WasmDetectedFeatures detected_features()
const {
655 UpdateDetectedFeatures(WasmDetectedFeatures);
657 size_t NumOutstandingCompilations(CompilationTier tier)
const;
661 void WaitForCompilationEvent(CompilationEvent event);
663 void TierUpAllFunctions();
665 void AllowAnotherTopTierJob(uint32_t func_index) {
669 TypeFeedbackStorage* feedback = &
native_module_->module()->type_feedback;
670 base::MutexGuard mutex_guard(&feedback->mutex);
671 feedback->feedback_for_function[func_index].tierup_priority = 0;
674 void AllowAnotherTopTierJobForAllFunctions() {
676 uint32_t fn_start =
module->num_imported_functions;
677 uint32_t fn_end = fn_start + module->num_declared_functions;
678 base::MutexGuard mutex_guard(&module->type_feedback.mutex);
679 std::unordered_map<uint32_t, FunctionTypeFeedback>& feedback_map =
680 module->type_feedback.feedback_for_function;
681 for (uint32_t
i = fn_start;
i < fn_end;
i++) {
685 if (
auto it = feedback_map.find(
i); it != feedback_map.end()) {
686 it->second.tierup_priority = 0;
691 bool failed()
const {
695 bool baseline_compilation_finished()
const {
702 void SetWireBytesStorage(
703 std::shared_ptr<WireBytesStorage> wire_bytes_storage) {
704 base::MutexGuard guard(&
mutex_);
708 std::shared_ptr<WireBytesStorage> GetWireBytesStorage()
const {
709 base::MutexGuard guard(&
mutex_);
714 void set_compilation_id(
int compilation_id) {
719 size_t EstimateCurrentMemoryConsumption()
const;
725 void TriggerCachingAfterTimeout();
727 std::vector<WasmCode*> PublishCode(base::Vector<UnpublishedWasmCode> codes);
730 void AddCompilationUnitInternal(CompilationUnitBuilder* builder,
732 uint8_t function_progress);
737 void TriggerOutstandingCallbacks();
740 void TriggerCallbacks(base::EnumSet<CompilationEvent>);
742 void PublishCompilationResults(
743 std::vector<UnpublishedWasmCode> unpublished_code);
796 std::vector<std::unique_ptr<CompilationEventCallback>>
callbacks_;
816 struct PublishState {
825 using RequiredBaselineTierField = base::BitField8<ExecutionTier, 0, 2>;
826 using RequiredTopTierField = base::BitField8<ExecutionTier, 2, 2>;
827 using ReachedTierField = base::BitField8<ExecutionTier, 4, 2>;
830CompilationStateImpl* Impl(CompilationState* compilation_state) {
831 return reinterpret_cast<CompilationStateImpl*
>(compilation_state);
833const CompilationStateImpl* Impl(
const CompilationState* compilation_state) {
834 return reinterpret_cast<const CompilationStateImpl*
>(compilation_state);
837CompilationStateImpl* BackgroundCompileScope::compilation_state()
const {
842size_t CompilationStateImpl::EstimateCurrentMemoryConsumption()
const {
844 size_t result =
sizeof(CompilationStateImpl);
847 base::MutexGuard guard{&
mutex_};
859 constexpr size_t kAssumedNumberOfCallbacks = 4;
860 constexpr size_t size_of_vector =
861 kAssumedNumberOfCallbacks *
862 sizeof(std::unique_ptr<CompilationEventCallback>);
865 constexpr size_t size_of_payload =
866 kAssumedNumberOfCallbacks *
sizeof(CompilationEventCallback);
867 result += size_of_vector + size_of_payload;
869 if (
v8_flags.trace_wasm_offheap_memory) {
875bool BackgroundCompileScope::cancelled()
const {
885CompilationState::~CompilationState() { Impl(
this)->~CompilationStateImpl(); }
887void CompilationState::InitCompileJob() { Impl(
this)->InitCompileJob(); }
889void CompilationState::CancelCompilation() {
890 Impl(
this)->CancelCompilation(CompilationStateImpl::kCancelUnconditionally);
893void CompilationState::CancelInitialCompilation() {
894 Impl(
this)->CancelCompilation(
895 CompilationStateImpl::kCancelInitialCompilation);
898void CompilationState::SetError() { Impl(
this)->SetError(); }
900void CompilationState::SetWireBytesStorage(
901 std::shared_ptr<WireBytesStorage> wire_bytes_storage) {
902 Impl(
this)->SetWireBytesStorage(std::move(wire_bytes_storage));
905std::shared_ptr<WireBytesStorage> CompilationState::GetWireBytesStorage()
907 return Impl(
this)->GetWireBytesStorage();
910void CompilationState::AddCallback(
911 std::unique_ptr<CompilationEventCallback>
callback) {
912 return Impl(
this)->AddCallback(std::move(
callback));
915void CompilationState::TierUpAllFunctions() {
916 Impl(
this)->TierUpAllFunctions();
919void CompilationState::AllowAnotherTopTierJob(uint32_t func_index) {
920 Impl(
this)->AllowAnotherTopTierJob(func_index);
923void CompilationState::AllowAnotherTopTierJobForAllFunctions() {
924 Impl(
this)->AllowAnotherTopTierJobForAllFunctions();
927void CompilationState::InitializeAfterDeserialization(
930 Impl(
this)->InitializeCompilationProgressAfterDeserialization(
931 lazy_functions, eager_functions);
934bool CompilationState::failed()
const {
return Impl(
this)->failed(); }
936bool CompilationState::baseline_compilation_finished()
const {
937 return Impl(
this)->baseline_compilation_finished();
940void CompilationState::set_compilation_id(
int compilation_id) {
941 Impl(
this)->set_compilation_id(compilation_id);
944size_t CompilationState::EstimateCurrentMemoryConsumption()
const {
945 return Impl(
this)->EstimateCurrentMemoryConsumption();
948std::vector<WasmCode*> CompilationState::PublishCode(
950 return Impl(
this)->PublishCode(unpublished_code);
954std::unique_ptr<CompilationState> CompilationState::New(
955 const std::shared_ptr<NativeModule>& native_module,
956 std::shared_ptr<Counters> async_counters,
958 return std::unique_ptr<CompilationState>(
reinterpret_cast<CompilationState*
>(
959 new CompilationStateImpl(std::move(native_module),
960 std::move(async_counters), detected_features)));
964 return Impl(
this)->detected_features();
969 return Impl(
this)->UpdateDetectedFeatures(detected_features);
980 case WasmCompilationHintTier::kDefault:
982 case WasmCompilationHintTier::kBaseline:
983 return ExecutionTier::kLiftoff;
984 case WasmCompilationHintTier::kOptimized:
985 return ExecutionTier::kTurbofan;
990const WasmCompilationHint* GetCompilationHint(
const WasmModule* module,
991 uint32_t func_index) {
992 DCHECK_LE(module->num_imported_functions, func_index);
993 uint32_t hint_index = declared_function_index(module, func_index);
994 const std::vector<WasmCompilationHint>& compilation_hints =
995 module->compilation_hints;
996 if (hint_index < compilation_hints.size()) {
997 return &compilation_hints[hint_index];
1002CompileStrategy GetCompileStrategy(
const WasmModule* module,
1003 WasmEnabledFeatures enabled_features,
1004 uint32_t func_index,
bool lazy_module) {
1005 if (lazy_module)
return CompileStrategy::kLazy;
1006 if (!enabled_features.has_compilation_hints()) {
1007 return CompileStrategy::kDefault;
1009 auto* hint = GetCompilationHint(module, func_index);
1010 if (hint ==
nullptr)
return CompileStrategy::kDefault;
1011 switch (hint->strategy) {
1012 case WasmCompilationHintStrategy::kLazy:
1013 return CompileStrategy::kLazy;
1014 case WasmCompilationHintStrategy::kEager:
1015 return CompileStrategy::kEager;
1016 case WasmCompilationHintStrategy::kLazyBaselineEagerTopTier:
1017 return CompileStrategy::kLazyBaselineEagerTopTier;
1018 case WasmCompilationHintStrategy::kDefault:
1019 return CompileStrategy::kDefault;
1023struct ExecutionTierPair {
1032ExecutionTierPair GetDefaultTiersPerModule(NativeModule* native_module,
1033 DebugState is_in_debug_state,
1035 const WasmModule* module = native_module->module();
1037 return {ExecutionTier::kNone, ExecutionTier::kNone};
1040 DCHECK(!is_in_debug_state);
1041 return {ExecutionTier::kTurbofan, ExecutionTier::kTurbofan};
1043 if (is_in_debug_state) {
1044 return {ExecutionTier::kLiftoff, ExecutionTier::kLiftoff};
1047 v8_flags.liftoff ? ExecutionTier::kLiftoff : ExecutionTier::kTurbofan;
1048 bool eager_tier_up = !
v8_flags.wasm_dynamic_tiering &&
v8_flags.wasm_tier_up;
1054ExecutionTierPair GetLazyCompilationTiers(NativeModule* native_module,
1055 uint32_t func_index,
1056 DebugState is_in_debug_state) {
1059 constexpr bool kNotLazy =
false;
1060 ExecutionTierPair tiers =
1061 GetDefaultTiersPerModule(native_module, is_in_debug_state, kNotLazy);
1063 if (is_in_debug_state)
return tiers;
1066 if (native_module->enabled_features().has_compilation_hints()) {
1067 if (
auto* hint = GetCompilationHint(native_module->module(), func_index)) {
1068 tiers.baseline_tier =
1069 ApplyHintToExecutionTier(hint->baseline_tier, tiers.baseline_tier);
1070 tiers.top_tier = ApplyHintToExecutionTier(hint->top_tier, tiers.top_tier);
1076 static_cast<uint32_t
>(
v8_flags.wasm_tier_up_filter))) {
1077 tiers.top_tier = tiers.baseline_tier;
1081 static_assert(ExecutionTier::kLiftoff < ExecutionTier::kTurbofan,
1082 "Assume an order on execution tiers");
1083 if (tiers.baseline_tier > tiers.top_tier) {
1084 tiers.top_tier = tiers.baseline_tier;
1092class CompilationUnitBuilder {
1094 explicit CompilationUnitBuilder(NativeModule* native_module)
1097 void AddBaselineUnit(
int func_index, ExecutionTier tier) {
1101 void AddTopTierUnit(
int func_index, ExecutionTier tier) {
1107 compilation_state()->CommitCompilationUnits(base::VectorOf(
baseline_units_),
1120 CompilationStateImpl* compilation_state()
const {
1131 base::Vector<const uint8_t> code,
1132 WasmEnabledFeatures enabled_features,
1133 WasmDetectedFeatures* detected_features) {
1137 if (module->function_was_validated(func_index))
return {};
1138 const WasmFunction* func = &
module->functions[func_index];
1139 bool is_shared =
module->type(func->sig_index).is_shared;
1140 FunctionBody body{func->sig, func->code.offset(), code.begin(), code.end(),
1143 detected_features, body);
1144 if (
result.ok())
module->set_function_validated(func_index);
1148enum OnlyLazyFunctions :
bool {
1149 kAllFunctions =
false,
1150 kOnlyLazyFunctions =
true,
1153bool IsLazyModule(
const WasmModule* module) {
1154 return v8_flags.wasm_lazy_compilation ||
1158class CompileLazyTimingScope {
1160 CompileLazyTimingScope(Counters* counters, NativeModule* native_module)
1165 ~CompileLazyTimingScope() {
1166 base::TimeDelta elapsed =
timer_.Elapsed();
1167 native_module_->AddLazyCompilationTimeSample(elapsed.InMicroseconds());
1168 counters_->wasm_lazy_compile_time()->AddTimedSample(elapsed);
1183 NativeModule* native_module = trusted_instance_data->native_module();
1184 Counters* counters = isolate->counters();
1189 std::optional<CompileLazyTimingScope> lazy_compile_time_scope;
1190 if (base::TimeTicks::IsHighResolution()) {
1191 lazy_compile_time_scope.emplace(counters, native_module);
1196 TRACE_LAZY(
"Compiling wasm-function#%d.\n", func_index);
1198 CompilationStateImpl* compilation_state =
1201 ExecutionTierPair tiers =
1202 GetLazyCompilationTiers(native_module, func_index, is_in_debug_state);
1207 func_index, tiers.baseline_tier,
1212 &env, compilation_state->GetWireBytesStorage().get(), counters,
1213 &detected_features);
1214 compilation_state->OnCompilationStopped(detected_features);
1235 counters->wasm_lazily_compiled_functions()->Increment();
1238 const bool lazy_module = IsLazyModule(module);
1239 if (GetCompileStrategy(module, native_module->
enabled_features(), func_index,
1240 lazy_module) == CompileStrategy::kLazy &&
1241 tiers.baseline_tier < tiers.top_tier) {
1244 compilation_state->CommitTopTierCompilationUnit(tiering_unit);
1254 CompilationStateImpl* compilation_state =
1256 const WasmFunction* func = &
module->functions[func_index];
1258 compilation_state->GetWireBytesStorage()->GetCode(func->
code);
1266 ValidateSingleFunction(&validation_zone, module, func_index, code,
1267 enabled_features, &unused_detected_features);
1273 std::move(decode_result).error()));
1296 instance_data_(trusted_instance_data),
1297 module_(trusted_instance_data->module()),
1299 feedback_for_function_(
module_->type_feedback.feedback_for_function) {
1300 queue_.insert(func_index);
1306 while (!queue_.empty()) {
1307 auto next = queue_.cbegin();
1308 ProcessFunction(*next);
1313 void ProcessFunction(
int func_index);
1317 for (
int j = 0; j < csf.num_cases(); j++) {
1318 int func = csf.function_index(j);
1320 if (csf.call_count(j) == 0)
continue;
1322 auto existing = feedback_for_function_.find(func);
1323 if (existing != feedback_for_function_.end() &&
1324 !existing->second.feedback_vector.empty()) {
1325 if (!existing->second.needs_reprocessing_after_deopt) {
1329 existing->second.needs_reprocessing_after_deopt =
false;
1331 queue_.insert(func);
1348 return obj ==
ReadOnlyRoots{isolate}.wasm_cross_instance_call_symbol();
1355 int func_index,
int num_calls)
1357 instance_data_(trusted_instance_data),
1361 trusted_instance_data->module()->num_imported_functions)),
1366 Cast<WasmFuncRef>(funcref)->internal(
isolate_);
1368 if (internal_function->implicit_arg() != instance_data_) {
1369 has_non_inlineable_targets_ =
true;
1374 has_non_inlineable_targets_ =
true;
1377 AddCall(internal_function->function_index(),
count);
1384 has_non_inlineable_targets_ =
true;
1387 Tagged<Smi> target_truncated_smi = Cast<Smi>(target_truncated_obj);
1402 wasm::GetWasmCodeManager()->LookupCode(
nullptr, entry);
1403 if (!code || code->native_module() != instance_data_->native_module() ||
1404 code->IsAnonymous()) {
1406 has_non_inlineable_targets_ =
true;
1409 DCHECK_EQ(code->kind(), WasmCode::Kind::kWasmFunction);
1410 uint32_t func_idx = code->index();
1411 AddCall(func_idx,
count);
1416 if (
static_cast<size_t>(cache_usage_) == targets_cache_.size() ||
1418 is_megamorphic_ =
true;
1422 int insertion_index = 0;
1423 while (insertion_index < cache_usage_ &&
1424 counts_cache_[insertion_index] >=
count) {
1427 for (
int shifted_index = cache_usage_ - 1; shifted_index >= insertion_index;
1429 targets_cache_[shifted_index + 1] = targets_cache_[shifted_index];
1430 counts_cache_[shifted_index + 1] = counts_cache_[shifted_index];
1432 targets_cache_[insertion_index] =
target;
1433 counts_cache_[insertion_index] =
count;
1438 auto end = targets_cache_.begin() + cache_usage_;
1440 return std::find(targets_cache_.begin(),
end, target) !=
end;
1445 result_[seen_calls_] = feedback;
1450 if (is_megamorphic_) {
1451 if (
v8_flags.trace_wasm_inlining) {
1455 AddResult(CallSiteFeedback::CreateMegamorphic());
1456 }
else if (cache_usage_ == 0) {
1458 }
else if (cache_usage_ == 1) {
1459 if (
v8_flags.trace_wasm_inlining) {
1460 PrintF(
"[function %d: call #%d inlineable (monomorphic)]\n",
1465 if (
v8_flags.trace_wasm_inlining) {
1466 PrintF(
"[function %d: call #%d inlineable (polymorphic %d)]\n",
1472 for (
int i = 0;
i < cache_usage_;
i++) {
1473 polymorphic[
i].function_index = targets_cache_[
i];
1474 polymorphic[
i].absolute_call_frequency = counts_cache_[
i];
1478 result_[seen_calls_ - 1].set_has_non_inlineable_targets(
1479 has_non_inlineable_targets_);
1482 has_non_inlineable_targets_ =
false;
1483 is_megamorphic_ =
false;
1500 int seen_calls_ = 0;
1503 int cache_usage_{0};
1506 bool has_non_inlineable_targets_ =
false;
1509 bool is_megamorphic_ =
false;
1512void TransitiveTypeFeedbackProcessor::ProcessFunction(
int func_index) {
1515 instance_data_->feedback_vectors()->get(which_vector);
1516 if (!IsFixedArray(maybe_feedback))
return;
1519 module_->type_feedback.feedback_for_function[func_index]
1520 .call_targets.as_vector();
1546 int checked_feedback_length = feedback->length();
1549 checked_feedback_length / 2);
1550 for (
int i = 0;
i < checked_feedback_length;
i += 2) {
1551 uint32_t sentinel_or_target = call_targets[
i / 2];
1555 if (sentinel_or_target != FunctionTypeFeedback::kCallRef &&
1556 sentinel_or_target != FunctionTypeFeedback::kCallIndirect) {
1558 int count = Smi::ToInt(first_slot);
1563 fm.
AddCall(
static_cast<int>(sentinel_or_target),
count);
1564 }
else if (
IsSmi(second_slot) && Smi::ToInt(second_slot) == 0) {
1567 if (
v8_flags.trace_wasm_inlining) {
1568 PrintF(
"[function %d: call #%d: uninitialized]\n", func_index,
i / 2);
1570 }
else if (IsWasmFuncRef(first_slot)) {
1572 DCHECK_EQ(sentinel_or_target, FunctionTypeFeedback::kCallRef);
1573 int count = Smi::ToInt(second_slot);
1577 DCHECK_EQ(sentinel_or_target, FunctionTypeFeedback::kCallIndirect);
1578 int count = Smi::ToInt(second_slot);
1580 }
else if (IsFixedArray(first_slot)) {
1583 DCHECK(IsUndefined(second_slot));
1584 int checked_polymorphic_length = polymorphic->length();
1586 if (sentinel_or_target == FunctionTypeFeedback::kCallRef) {
1587 for (
int j = 0; j < checked_polymorphic_length; j += 2) {
1589 int count = Smi::ToInt(polymorphic->get(j + 1));
1593 DCHECK_EQ(sentinel_or_target, FunctionTypeFeedback::kCallIndirect);
1594 for (
int j = 0; j < checked_polymorphic_length; j += 2) {
1596 int count = Smi::ToInt(polymorphic->get(j + 1));
1601 DCHECK(IsUndefined(second_slot));
1608 first_slot !=
ReadOnlyRoots{isolate_}.megamorphic_symbol()) {
1614 feedback_for_function_[func_index].feedback_vector;
1615 size_t feedback_index =
i / 2;
1616 if (feedback_index < existing.
size()) {
1624 for (
int j = 0; j < old_feedback.
num_cases(); ++j) {
1634 DCHECK_GE(
static_cast<uint32_t
>(old_target_function_index),
1635 instance_data_->module()->num_imported_functions);
1644 EnqueueCallees(
result.as_vector());
1646 feedback_for_function_[func_index].call_targets.size());
1647 feedback_for_function_[func_index].feedback_vector = std::move(
result);
1653 NativeModule* native_module = trusted_instance_data->native_module();
1654 CompilationStateImpl* compilation_state =
1663 int array_index = wasm::declared_function_index(module, func_index);
1664 trusted_instance_data->tiering_budget_array()[array_index].store(
1665 v8_flags.wasm_tiering_budget, std::memory_order_relaxed);
1666 int& stored_priority =
1667 module->type_feedback.feedback_for_function[func_index].tierup_priority;
1668 if (stored_priority <
kMaxInt) ++stored_priority;
1683 TransitiveTypeFeedbackProcessor::Process(isolate, trusted_instance_data,
1687 compilation_state->AddTopTierPriorityCompilationUnit(tiering_unit,
priority);
1693 NativeModule* native_module = trusted_instance_data->native_module();
1695 TransitiveTypeFeedbackProcessor::Process(isolate, trusted_instance_data,
1698 wasm::GetWasmEngine()->CompileFunction(isolate->counters(), native_module,
1700 wasm::ExecutionTier::kTurbofan);
1706 NativeModule* native_module = trusted_instance_data->native_module();
1712 for (uint32_t func_index =
start; func_index <
end; func_index++) {
1713 if (!native_module->
HasCodeWithTier(func_index, ExecutionTier::kTurbofan)) {
1721 ->InitializeCompilationProgress(
nullptr);
1725 Isolate* isolate,
bool is_initial_compilation) {
1727 static constexpr std::pair<WasmDetectedFeature, Feature> kUseCounters[] = {
1728 {WasmDetectedFeature::shared_memory, Feature::kWasmSharedMemory},
1729 {WasmDetectedFeature::reftypes, Feature::kWasmRefTypes},
1730 {WasmDetectedFeature::simd, Feature::kWasmSimdOpcodes},
1731 {WasmDetectedFeature::threads, Feature::kWasmThreadOpcodes},
1732 {WasmDetectedFeature::legacy_eh, Feature::kWasmExceptionHandling},
1733 {WasmDetectedFeature::memory64, Feature::kWasmMemory64},
1734 {WasmDetectedFeature::multi_memory, Feature::kWasmMultiMemory},
1735 {WasmDetectedFeature::gc, Feature::kWasmGC},
1736 {WasmDetectedFeature::imported_strings, Feature::kWasmImportedStrings},
1737 {WasmDetectedFeature::imported_strings_utf8,
1738 Feature::kWasmImportedStringsUtf8},
1739 {WasmDetectedFeature::return_call, Feature::kWasmReturnCall},
1740 {WasmDetectedFeature::extended_const, Feature::kWasmExtendedConst},
1741 {WasmDetectedFeature::relaxed_simd, Feature::kWasmRelaxedSimd},
1742 {WasmDetectedFeature::type_reflection, Feature::kWasmTypeReflection},
1743 {WasmDetectedFeature::exnref, Feature::kWasmExnRef},
1744 {WasmDetectedFeature::typed_funcref, Feature::kWasmTypedFuncRef},
1745 {WasmDetectedFeature::jspi, Feature::kWasmJavaScriptPromiseIntegration},
1746 {WasmDetectedFeature::branch_hinting, Feature::kWasmBranchHinting},
1754 WasmDetectedFeature::stringref,
1756 for (
auto no_use_counter_feature : kIntentionallyNoUseCounter) {
1757 if (feat == no_use_counter_feature)
return true;
1759 for (
auto [feature, use_counter] : kUseCounters) {
1760 if (feat == feature)
return true;
1764#define CHECK_USE_COUNTER(feat, ...) \
1765 static_assert(check_use_counter(WasmDetectedFeature::feat));
1769#undef CHECK_USE_COUNTER
1771 static constexpr size_t kMaxFeatures =
arraysize(kUseCounters) + 1;
1773 if (is_initial_compilation) {
1777 use_counter_features.
push_back(Feature::kWasmModuleCompilation);
1780 for (
auto [wasm_feature, feature] : kUseCounters) {
1781 if (!detected_features.
contains(wasm_feature))
continue;
1782 use_counter_features.
push_back(feature);
1784 if (use_counter_features.
empty())
return;
1786 isolate->CountUsage(base::VectorOf(use_counter_features));
1790 if (
v8_flags.correctness_fuzzer_suppressions) {
1791 if (detected_features.has_relaxed_simd()) {
1792 PrintF(
"Warning: This run cannot be compared across architectures.\n");
1800 if (!type.is_object_reference() || !type.has_index())
return false;
1801 ModuleTypeIndex reftype = type.ref_index();
1802 if (!module->
has_array(reftype))
return false;
1803 return module->canonical_type_id(reftype) ==
1804 TypeCanonicalizer::kPredefinedArrayI16Index;
1807bool IsI8Array(wasm::ValueType type,
const WasmModule* module,
1808 bool allow_nullable) {
1809 if (!type.is_object_reference() || !type.has_index())
return false;
1810 if (!allow_nullable && type.is_nullable())
return false;
1811 ModuleTypeIndex reftype = type.ref_index();
1812 if (!module->has_array(reftype))
return false;
1813 return module->canonical_type_id(reftype) ==
1814 TypeCanonicalizer::kPredefinedArrayI8Index;
1822uint32_t ImportStartOffset(base::Vector<const uint8_t> wire_bytes,
1823 uint32_t module_name_start) {
1825 uint32_t
offset = module_name_start - 1;
1827 while (
offset > 0 && (wire_bytes[
offset - 1] & 0x80) != 0) {
1842 if (imports.
empty())
return {};
1849 static constexpr ValueType kReps_e_i[] = {kRefExtern,
kI32};
1850 static constexpr ValueType kReps_e_rr[] = {kRefExtern, kExternRef,
1852 static constexpr ValueType kReps_e_rii[] = {kRefExtern, kExternRef,
kI32,
1855 static constexpr ValueType kReps_i_rr[] = {
kI32, kExternRef, kExternRef};
1857 static constexpr FunctionSig kSig_e_i(1, 1, kReps_e_i);
1858 static constexpr FunctionSig kSig_e_r(1, 1, kReps_e_rr);
1859 static constexpr FunctionSig kSig_e_rr(1, 2, kReps_e_rr);
1860 static constexpr FunctionSig kSig_e_rii(1, 3, kReps_e_rii);
1862 static constexpr FunctionSig kSig_i_r(1, 1, kReps_i_ri);
1863 static constexpr FunctionSig kSig_i_ri(1, 2, kReps_i_ri);
1864 static constexpr FunctionSig kSig_i_rr(1, 2, kReps_i_rr);
1866 std::vector<WellKnownImport> statuses;
1869 const WasmImport&
import = module->import_table[i];
1874 import.module_name.offset(),
import.module_name.end_offset()))) {
1876 !module->
globals[
import.index].type.is_reference_to(
1877 HeapType::kExtern) ||
1878 module->
globals[
import.index].mutability !=
false) {
1880 wire_bytes.
data() +
import.field_name.offset(),
1881 import.field_name.length());
1883 ImportStartOffset(wire_bytes,
import.module_name.offset()),
1884 "String constant import #%zu \"%.*s\" must be an immutable global "
1885 "subtyping externref",
1886 i, name.
length(), name.start());
1893 import.module_name.offset(),
import.module_name.end_offset());
1894 constexpr size_t kMinInterestingLength = 10;
1895 if (module_name.
size() < kMinInterestingLength ||
1896 module_name.
SubVector(0, 5) != base::StaticOneByteVector(
"wasm:")) {
1897 statuses.push_back(WellKnownImport::kUninstantiated);
1902 const WasmFunction& func =
module->functions[import.index];
1907 if (collection == base::StaticOneByteVector(
"js-string") &&
1908 imports.
contains(CompileTimeImport::kJsString)) {
1909#define RETURN_ERROR(module_name_string, import_name) \
1910 uint32_t error_offset = \
1911 ImportStartOffset(wire_bytes, import.module_name.offset()); \
1912 return WasmError(error_offset, \
1913 "Imported builtin function \"wasm:" module_name_string \
1914 "\" \"" import_name "\" has incorrect signature")
1916#define CHECK_SIG(import_name, kSigName, kEnumName) \
1917 if (name == base::StaticOneByteVector(#import_name)) { \
1918 if (*sig != kSigName) { \
1919 RETURN_ERROR("js-string", #import_name); \
1921 status = WellKnownImport::kEnumName; \
1922 detected->add_imported_strings(); \
1936 if (name == base::StaticOneByteVector(
"fromCharCodeArray")) {
1937 if (
sig->parameter_count() != 3 ||
sig->return_count() != 1 ||
1938 !IsI16Array(
sig->GetParam(0), module) ||
1941 sig->GetReturn() != kRefExtern) {
1944 detected->add_imported_strings();
1945 status = WellKnownImport::kStringFromWtf16Array;
1946 }
else if (name == base::StaticOneByteVector(
"intoCharCodeArray")) {
1947 if (
sig->parameter_count() != 3 ||
sig->return_count() != 1 ||
1948 sig->GetParam(0) != kExternRef ||
1949 !IsI16Array(
sig->GetParam(1), module) ||
1954 status = WellKnownImport::kStringToWtf16Array;
1955 detected->add_imported_strings();
1958 }
else if (collection == base::StaticOneByteVector(
"text-encoder") &&
1959 imports.
contains(CompileTimeImport::kTextEncoder)) {
1960 if (name == base::StaticOneByteVector(
"measureStringAsUTF8")) {
1961 if (*
sig != kSig_i_r) {
1964 status = WellKnownImport::kStringMeasureUtf8;
1965 detected->add_imported_strings_utf8();
1967 base::StaticOneByteVector(
"encodeStringIntoUTF8Array")) {
1968 if (
sig->parameter_count() != 3 ||
sig->return_count() != 1 ||
1969 sig->GetParam(0) != kExternRef ||
1970 !IsI8Array(
sig->GetParam(1), module,
true) ||
1973 RETURN_ERROR(
"text-encoder",
"encodeStringIntoUTF8Array");
1975 status = WellKnownImport::kStringIntoUtf8Array;
1976 detected->add_imported_strings_utf8();
1977 }
else if (name == base::StaticOneByteVector(
"encodeStringToUTF8Array")) {
1978 if (
sig->parameter_count() != 1 ||
sig->return_count() != 1 ||
1979 sig->GetParam(0) != kExternRef ||
1980 !IsI8Array(
sig->GetReturn(), module,
false)) {
1981 RETURN_ERROR(
"text-encoder",
"encodeStringToUTF8Array");
1983 status = WellKnownImport::kStringToUtf8Array;
1984 detected->add_imported_strings_utf8();
1986 }
else if (collection == base::StaticOneByteVector(
"text-decoder") &&
1987 imports.
contains(CompileTimeImport::kTextDecoder)) {
1988 if (name == base::StaticOneByteVector(
"decodeStringFromUTF8Array")) {
1989 if (
sig->parameter_count() != 3 ||
sig->return_count() != 1 ||
1990 !IsI8Array(
sig->GetParam(0), module,
true) ||
1993 sig->GetReturn() != kRefExtern) {
1994 RETURN_ERROR(
"text-decoder",
"decodeStringFromUTF8Array");
1996 status = WellKnownImport::kStringFromUtf8Array;
1997 detected->add_imported_strings_utf8();
2001 statuses.push_back(status);
2009 module->type_feedback.well_known_imports.Initialize(
2010 base::VectorOf(statuses));
2017enum CompilationExecutionResult : int8_t { kNoMoreUnits, kYield };
2019const char* GetCompilationEventName(
const WasmCompilationUnit&
unit,
2020 const CompilationEnv& env) {
2021 ExecutionTier tier =
unit.tier();
2022 if (tier == ExecutionTier::kLiftoff) {
2023 return "wasm.BaselineCompilation";
2025 if (tier == ExecutionTier::kTurbofan) {
2026 return "wasm.TopTierCompilation";
2028 if (
unit.func_index() <
2029 static_cast<int>(env.module->num_imported_functions)) {
2030 return "wasm.WasmToJSWrapperCompilation";
2032 return "wasm.OtherCompilation";
2035constexpr uint8_t kMainTaskId = 0;
2038CompilationExecutionResult ExecuteCompilationUnits(
2039 std::weak_ptr<NativeModule> native_module, Counters* counters,
2040 JobDelegate* delegate, CompilationTier tier) {
2041 TRACE_EVENT0(
"v8.wasm",
"wasm.ExecuteCompilationUnits");
2048 std::optional<CompilationEnv> env;
2049 std::optional<base::FlushDenormalsScope> disable_denormals;
2050 std::shared_ptr<WireBytesStorage> wire_bytes;
2051 std::shared_ptr<const WasmModule> module;
2054 static_assert(kMainTaskId == 0);
2055 int task_id = delegate ? (
int{delegate->GetTaskId()} + 1) : kMainTaskId;
2057 CompilationUnitQueues::Queue* queue;
2058 std::optional<WasmCompilationUnit>
unit;
2060 WasmDetectedFeatures global_detected_features;
2065 BackgroundCompileScope compile_scope(native_module);
2066 if (compile_scope.cancelled())
return kYield;
2067 env.emplace(CompilationEnv::ForModule(compile_scope.native_module()));
2070 disable_denormals.emplace(
2071 compile_scope.native_module()->compile_imports().contains(
2072 CompileTimeImport::kDisableDenormalFloats));
2073 wire_bytes = compile_scope.compilation_state()->GetWireBytesStorage();
2074 module = compile_scope.native_module()->shared_module();
2075 queue = compile_scope.compilation_state()->GetQueueForCompileTask(task_id);
2077 compile_scope.compilation_state()->GetNextCompilationUnit(queue, tier);
2078 if (!
unit)
return kNoMoreUnits;
2080 TRACE_COMPILE(
"ExecuteCompilationUnits (task id %d)\n", task_id);
2082 std::vector<WasmCompilationResult> results_to_publish;
2085 const char* event_name = GetCompilationEventName(
unit.value(), env.value());
2087 while (
unit->tier() == current_tier) {
2090 WasmDetectedFeatures per_function_detected_features;
2092 WasmCompilationResult
result =
2093 unit->ExecuteCompilation(&env.value(), wire_bytes.get(), counters,
2094 &per_function_detected_features);
2095 global_detected_features.Add(per_function_detected_features);
2096 bool compilation_succeeded =
result.succeeded();
2099 DCHECK_GE(
unit->func_index(), env->module->num_imported_functions);
2100 results_to_publish.emplace_back(std::move(
result));
2102 bool yield = delegate && delegate->ShouldYield();
2105 BackgroundCompileScope compile_scope(native_module);
2106 if (compile_scope.cancelled())
return kYield;
2108 if (!compilation_succeeded) {
2109 compile_scope.compilation_state()->SetError();
2110 return kNoMoreUnits;
2113 if (!
unit->for_debugging() && result_tier != current_tier) {
2114 compile_scope.native_module()->AddLiftoffBailout();
2119 !(
unit = compile_scope.compilation_state()->GetNextCompilationUnit(
2121 std::vector<UnpublishedWasmCode> unpublished_code =
2122 compile_scope.native_module()->AddCompiledCode(
2123 base::VectorOf(results_to_publish));
2124 results_to_publish.clear();
2125 compile_scope.compilation_state()->SchedulePublishCompilationResults(
2126 std::move(unpublished_code), tier);
2127 compile_scope.compilation_state()->OnCompilationStopped(
2128 global_detected_features);
2129 return yield ? kYield : kNoMoreUnits;
2135 queue->ShouldPublish(
static_cast<int>(results_to_publish.size()));
2139 bool liftoff_finished =
unit->tier() != current_tier &&
2140 unit->tier() == ExecutionTier::kTurbofan;
2141 if (batch_full || liftoff_finished) {
2142 std::vector<UnpublishedWasmCode> unpublished_code =
2143 compile_scope.native_module()->AddCompiledCode(
2144 base::VectorOf(results_to_publish));
2145 results_to_publish.clear();
2146 compile_scope.compilation_state()->SchedulePublishCompilationResults(
2147 std::move(unpublished_code), tier);
2154std::unique_ptr<CompilationUnitBuilder> InitializeCompilation(
2155 Isolate* isolate, NativeModule* native_module,
2156 ProfileInformation* pgo_info) {
2157 CompilationStateImpl* compilation_state =
2158 Impl(native_module->compilation_state());
2159 auto builder = std::make_unique<CompilationUnitBuilder>(native_module);
2160 compilation_state->InitializeCompilationProgress(pgo_info);
2164bool MayCompriseLazyFunctions(
const WasmModule* module,
2165 WasmEnabledFeatures enabled_features) {
2166 if (IsLazyModule(module))
return true;
2167 if (enabled_features.has_compilation_hints())
return true;
2168#ifdef ENABLE_SLOW_DCHECKS
2169 int start =
module->num_imported_functions;
2170 int end =
start + module->num_declared_functions;
2171 for (
int func_index =
start; func_index <
end; func_index++) {
2172 SLOW_DCHECK(GetCompileStrategy(module, enabled_features, func_index,
2173 false) != CompileStrategy::kLazy);
2179class CompilationTimeCallback :
public CompilationEventCallback {
2182 explicit CompilationTimeCallback(
2183 std::shared_ptr<Counters> async_counters,
2184 std::shared_ptr<metrics::Recorder> metrics_recorder,
2186 std::weak_ptr<NativeModule> native_module, CompileMode compile_mode)
2194 void call(CompilationEvent compilation_event)
override {
2195 DCHECK(base::TimeTicks::IsHighResolution());
2196 std::shared_ptr<NativeModule> native_module =
native_module_.lock();
2197 if (!native_module)
return;
2198 auto now = base::TimeTicks::Now();
2200 if (compilation_event == CompilationEvent::kFinishedBaselineCompilation) {
2204 TimedHistogram* histogram =
2208 histogram->AddSample(
static_cast<int>(duration.InMicroseconds()));
2218 native_module->liftoff_code_size(),
2219 native_module->liftoff_bailout_count(),
2220 duration.InMicroseconds()};
2223 if (compilation_event == CompilationEvent::kFailedCompilation) {
2231 native_module->liftoff_code_size(),
2232 native_module->liftoff_bailout_count(),
2233 duration.InMicroseconds()};
2248 base::Vector<const uint8_t> wire_bytes,
2249 WasmEnabledFeatures enabled_features,
2250 OnlyLazyFunctions only_lazy_functions,
2251 WasmDetectedFeatures* detected_features) {
2253 if (only_lazy_functions &&
2254 !MayCompriseLazyFunctions(module, enabled_features)) {
2258 std::function<
bool(
int)> filter;
2259 if (only_lazy_functions) {
2260 const bool is_lazy_module = IsLazyModule(module);
2261 filter = [module, enabled_features, is_lazy_module](
int func_index) {
2262 CompileStrategy strategy = GetCompileStrategy(module, enabled_features,
2263 func_index, is_lazy_module);
2264 return strategy == CompileStrategy::kLazy ||
2265 strategy == CompileStrategy::kLazyBaselineEagerTopTier;
2274 OnlyLazyFunctions only_lazy_functions) {
2275 WasmDetectedFeatures detected_features;
2278 native_module.enabled_features(), only_lazy_functions,
2279 &detected_features);
2280 if (!
result.has_error()) {
2284 USE(native_module.compilation_state()->UpdateDetectedFeatures(
2285 detected_features));
2290void CompileNativeModule(Isolate* isolate,
2292 ErrorThrower* thrower,
2293 std::shared_ptr<NativeModule> native_module,
2294 ProfileInformation* pgo_info) {
2296 const WasmModule* module = native_module->module();
2299 auto* compilation_state = Impl(native_module->compilation_state());
2300 if (base::TimeTicks::IsHighResolution()) {
2301 compilation_state->AddCallback(std::make_unique<CompilationTimeCallback>(
2302 isolate->async_counters(), isolate->metrics_recorder(), context_id,
2303 native_module, CompilationTimeCallback::kSynchronous));
2307 std::unique_ptr<CompilationUnitBuilder> builder =
2308 InitializeCompilation(isolate, native_module.get(), pgo_info);
2309 compilation_state->InitializeCompilationUnits(std::move(builder));
2314 if (!
v8_flags.wasm_lazy_validation && module->origin == kWasmOrigin) {
2315 DCHECK(!thrower->error());
2316 if (WasmError validation_error =
2318 thrower->CompileFailed(std::move(validation_error));
2323 if (!compilation_state->failed()) {
2324 compilation_state->WaitForCompilationEvent(
2325 CompilationEvent::kFinishedBaselineCompilation);
2328 if (compilation_state->failed()) {
2330 WasmError validation_error =
2332 CHECK(validation_error.has_error());
2333 thrower->CompileFailed(std::move(validation_error));
2337class BackgroundCompileJob final :
public JobTask {
2339 explicit BackgroundCompileJob(std::weak_ptr<NativeModule> native_module,
2340 std::shared_ptr<Counters> async_counters,
2341 CompilationTier tier)
2347 void Run(JobDelegate* delegate)
override {
2349 if (!engine_scope)
return;
2354 size_t GetMaxConcurrency(
size_t worker_count)
const override {
2356 if (compile_scope.cancelled())
return 0;
2357 size_t flag_limit =
static_cast<size_t>(
2358 std::max(1,
v8_flags.wasm_num_compilation_tasks.value()));
2361 return std::min(flag_limit,
2362 worker_count + compile_scope.compilation_state()
2363 ->NumOutstandingCompilations(
tier_));
2373std::shared_ptr<NativeModule> GetOrCompileNewNativeModule(
2374 Isolate* isolate, WasmEnabledFeatures enabled_features,
2375 WasmDetectedFeatures detected_features, CompileTimeImports compile_imports,
2376 ErrorThrower* thrower, std::shared_ptr<const WasmModule> module,
2377 base::OwnedVector<const uint8_t> wire_bytes,
int compilation_id,
2379 std::shared_ptr<NativeModule> native_module =
2381 module->origin, wire_bytes.as_vector(), compile_imports, isolate);
2382 if (native_module)
return native_module;
2385 std::optional<TimedHistogramScope> wasm_compile_module_time_scope;
2386 if (base::TimeTicks::IsHighResolution()) {
2388 isolate->counters(), module->origin, wasm_compile, module_time));
2391 size_t code_size_estimate =
2392 wasm::WasmCodeManager::EstimateNativeModuleCodeSize(module.get());
2394 isolate, enabled_features, detected_features, std::move(compile_imports),
2395 module, code_size_estimate);
2396 native_module->SetWireBytes(std::move(wire_bytes));
2397 native_module->compilation_state()->set_compilation_id(compilation_id);
2401 CompileNativeModule(isolate, context_id, thrower, native_module, pgo_info);
2404 if (thrower->error()) {
2421 ErrorThrower* thrower, std::shared_ptr<const WasmModule> module,
2424 std::shared_ptr<NativeModule> native_module = GetOrCompileNewNativeModule(
2425 isolate, enabled_features, detected_features, std::move(compile_imports),
2426 thrower, module, std::move(wire_bytes), compilation_id, context_id,
2428 if (!native_module)
return {};
2435 native_module->compilation_state()->detected_features(), isolate,
true);
2437 return native_module;
2440AsyncCompileJob::AsyncCompileJob(
2445 std::shared_ptr<CompilationResultResolver> resolver,
int compilation_id)
2447 api_method_name_(api_method_name),
2449 compile_imports_(
std::move(compile_imports)),
2451 bytes_copy_(
std::move(bytes)),
2456 "wasm.AsyncCompileJob");
2463 isolate->global_handles()->Create(context->native_context());
2513 *ptr++ = {declared_func_index, code};
2517 size_t total_units_added = ptr -
units.begin();
2526 if ((total_units_added >= 16 &&
2528 (total_units_added % (16 * 1024)) == 0 || ptr ==
units.end()) {
2547 while (next <
end) {
2549 next, next + 1, std::memory_order_relaxed)) {
2561 old_features, old_features | new_detected_features,
2562 std::memory_order_relaxed)) {
2582 TRACE_EVENT0(
"v8.wasm",
"wasm.ValidateFunctionsStreaming");
2587 validation_zone.Reset();
2621 uint32_t
offset)
override;
2624 uint32_t functions_mismatch_error_offset,
2625 std::shared_ptr<WireBytesStorage>,
2626 int code_section_start,
2627 int code_section_length)
override;
2630 uint32_t
offset)
override;
2635 bool after_error)
override;
2663 std::make_unique<AsyncStreamingProcessor>(
this));
2673 ->CancelCompilation(CompilationStateImpl::kCancelInitialCompilation);
2687 std::shared_ptr<const WasmModule> module,
size_t code_size_estimate) {
2689 const bool has_shared_memory =
2690 std::any_of(module->memories.begin(), module->memories.end(),
2691 [](
auto& memory) { return memory.is_shared; });
2692 if (has_shared_memory) {
2707 std::shared_ptr<const WasmModule> module,
size_t code_size_estimate) {
2735 "wasm.FinishAsyncCompile");
2740 auto compilation_state = Impl(
native_module_->compilation_state());
2750 std::unique_ptr<ProfileInformation> pgo_info =
2753 compilation_state->ApplyPgoInfoLate(pgo_info.get());
2758 if (!is_after_deserialization) {
2765 int duration_usecs =
static_cast<int>(duration.
InMicroseconds());
2769 if (is_after_cache_hit || is_after_deserialization) {
2774 is_after_deserialization,
2776 !compilation_state->failed(),
2787 auto sourcemap_symbol =
2788 module->debug_symbols[WasmDebugSymbols::Type::SourceMap];
2789 if (script->type() == Script::Type::kWasm &&
2791 !sourcemap_symbol.external_url.is_empty()) {
2801 "wasm.Debug.OnAfterCompile");
2830 std::unique_ptr<AsyncCompileJob> job =
2834 constexpr bool kValidate =
true;
2845 CHECK(!job->compile_imports_.empty());
2848 &unused_detected_features);
2849 CHECK(error.has_error());
2850 thrower.CompileError(
"%s", error.message().c_str());
2864 DCHECK(!last_event_.has_value());
2869 std::shared_ptr<NativeModule> cached_native_module =
2874 cached_native_module =
nullptr;
2884 DCHECK(!last_event_.has_value());
2895 last_event_ = event;
2904 std::optional<CompilationEvent> last_event_;
2915 if (on_foreground) {
2972 auto new_task = std::make_unique<CompileTask>(
this,
true);
2980 auto new_task = std::make_unique<CompileTask>(
this,
true);
2992 auto task = std::make_unique<CompileTask>(
this,
false);
2996 if (
v8_flags.wasm_num_compilation_tasks > 0) {
3004template <
typename Step,
3013template <
typename Step,
typename... Args>
3019template <
typename Step,
typename... Args>
3025template <
typename Step,
typename... Args>
3027 step_.reset(
new Step(std::forward<Args>(
args)...));
3036 std::shared_ptr<metrics::Recorder> metrics_recorder)
3047 "wasm.DecodeModule");
3077 std::shared_ptr<WasmModule> module = std::move(
result).value();
3078 size_t code_size_estimate =
3081 std::move(module),
true ,
3082 true , code_size_estimate);
3097 bool start_compilation,
3098 bool lazy_functions_are_validated,
3099 size_t code_size_estimate)
3127 if (!
v8_flags.wasm_lazy_validation &&
3139 CompilationStateImpl* compilation_state =
3141 compilation_state->AddCallback(
3142 std::make_unique<CompilationStateCallback>(job));
3144 auto compile_mode = job->
stream_ ==
nullptr
3145 ? CompilationTimeCallback::kAsync
3146 : CompilationTimeCallback::kStreaming;
3147 compilation_state->AddCallback(std::make_unique<CompilationTimeCallback>(
3155 std::unique_ptr<CompilationUnitBuilder> builder = InitializeCompilation(
3157 compilation_state->InitializeCompilationUnits(std::move(builder));
3162 compilation_state->WaitForCompilationEvent(
3211 "wasm.OnCompilationSucceeded");
3225 compilation_unit_builder_(nullptr) {}
3262 offset += bytes_consumed;
3263 bytes = bytes.SubVector(bytes_consumed, bytes.size());
3271 int num_functions, uint32_t functions_mismatch_error_offset,
3272 std::shared_ptr<WireBytesStorage> wire_bytes_storage,
3273 int code_section_start,
int code_section_length) {
3280 functions_mismatch_error_offset)) {
3285 static_cast<uint32_t
>(code_section_length)});
3297 size_t code_size_estimate =
3299 code_section_length);
3305 false, code_size_estimate);
3308 compilation_state->SetWireBytesStorage(std::move(wire_bytes_storage));
3325 uint32_t func_index =
3341 const bool lazy_module =
v8_flags.wasm_lazy_compilation;
3342 CompileStrategy strategy =
3343 GetCompileStrategy(module, enabled_features, func_index, lazy_module);
3345 bool validate_lazily_compiled_function =
3348 (strategy == CompileStrategy::kLazy ||
3349 strategy == CompileStrategy::kLazyBaselineEagerTopTier));
3350 if (validate_lazily_compiled_function) {
3358 std::make_unique<ValidateFunctionsStreamingJob>(
3386 if (module_result.
failed()) after_error =
true;
3398 std::memory_order_relaxed);
3436 std::shared_ptr<WasmModule> module = std::move(module_result).value();
3448 &detected_module_features)
3459 size_t code_size_estimate =
3462 std::move(module),
true ,
3463 false , code_size_estimate);
3476 auto* module_size_histogram =
3479 auto* num_functions_histogram =
3481 num_functions_histogram->AddSample(
static_cast<int>(
num_functions_));
3484 bool cache_hit =
false;
3485 if (!has_code_section) {
3489 constexpr size_t kCodeSizeEstimate = 0;
3534 std::optional<TimedHistogramScope> time_scope;
3548 if (
result.is_null())
return false;
3559CompilationStateImpl::CompilationStateImpl(
3560 const std::shared_ptr<NativeModule>& native_module,
3561 std::shared_ptr<Counters> async_counters,
3567 native_module->num_declared_functions()),
3570void CompilationStateImpl::InitCompileJob() {
3576 TaskPriority::kUserVisible,
3577 std::make_unique<BackgroundCompileJob>(
3580 TaskPriority::kUserVisible,
3581 std::make_unique<BackgroundCompileJob>(
3585void CompilationStateImpl::CancelCompilation(
3586 CompilationStateImpl::CancellationPolicy cancellation_policy) {
3589 if (cancellation_policy == kCancelInitialCompilation &&
3591 CompilationEvent::kFinishedBaselineCompilation)) {
3604bool CompilationStateImpl::cancelled()
const {
3608void CompilationStateImpl::ApplyCompilationHintToInitialProgress(
3609 const WasmCompilationHint& hint,
size_t hint_idx) {
3612 ExecutionTier old_baseline_tier = RequiredBaselineTierField::decode(progress);
3613 ExecutionTier old_top_tier = RequiredTopTierField::decode(progress);
3617 ApplyHintToExecutionTier(hint.baseline_tier, old_baseline_tier);
3619 ApplyHintToExecutionTier(hint.top_tier, old_top_tier);
3620 switch (hint.strategy) {
3621 case WasmCompilationHintStrategy::kDefault:
3623 if (old_baseline_tier == ExecutionTier::kNone) {
3624 new_baseline_tier = ExecutionTier::kNone;
3626 if (old_top_tier == ExecutionTier::kNone) {
3627 new_top_tier = ExecutionTier::kNone;
3630 case WasmCompilationHintStrategy::kLazy:
3631 new_baseline_tier = ExecutionTier::kNone;
3632 new_top_tier = ExecutionTier::kNone;
3634 case WasmCompilationHintStrategy::kEager:
3637 case WasmCompilationHintStrategy::kLazyBaselineEagerTopTier:
3638 new_baseline_tier = ExecutionTier::kNone;
3642 progress = RequiredBaselineTierField::update(progress, new_baseline_tier);
3643 progress = RequiredTopTierField::update(progress, new_top_tier);
3647 (old_baseline_tier != ExecutionTier::kNone);
3650void CompilationStateImpl::ApplyPgoInfoToInitialProgress(
3651 ProfileInformation* pgo_info) {
3655 for (
int func_index : pgo_info->executed_functions()) {
3659 RequiredBaselineTierField::decode(progress);
3661 if (old_baseline_tier != ExecutionTier::kNone)
continue;
3667 RequiredBaselineTierField::update(progress, ExecutionTier::kLiftoff);
3673 for (
int func_index : pgo_info->tiered_up_functions()) {
3677 RequiredBaselineTierField::decode(progress);
3678 ExecutionTier old_top_tier = RequiredTopTierField::decode(progress);
3681 if (old_baseline_tier == ExecutionTier::kTurbofan)
continue;
3682 if (old_top_tier == ExecutionTier::kTurbofan)
continue;
3686 progress = RequiredTopTierField::update(progress, ExecutionTier::kTurbofan);
3690void CompilationStateImpl::ApplyPgoInfoLate(ProfileInformation* pgo_info) {
3698 for (
int func_index : pgo_info->executed_functions()) {
3702 RequiredBaselineTierField::decode(progress);
3704 if (old_baseline_tier != ExecutionTier::kNone)
continue;
3707 ExecutionTier reached_tier = ReachedTierField::decode(progress);
3708 if (reached_tier >= ExecutionTier::kLiftoff)
continue;
3712 RequiredBaselineTierField::update(progress, ExecutionTier::kLiftoff);
3718 builder.AddTopTierUnit(func_index, ExecutionTier::kLiftoff);
3723 for (
int func_index : pgo_info->tiered_up_functions()) {
3727 RequiredBaselineTierField::decode(progress);
3728 ExecutionTier old_top_tier = RequiredTopTierField::decode(progress);
3731 if (old_baseline_tier == ExecutionTier::kTurbofan)
continue;
3732 if (old_top_tier == ExecutionTier::kTurbofan)
continue;
3735 ExecutionTier reached_tier = ReachedTierField::decode(progress);
3736 if (reached_tier == ExecutionTier::kTurbofan)
continue;
3739 progress = RequiredTopTierField::update(progress, ExecutionTier::kTurbofan);
3740 builder.AddTopTierUnit(func_index, ExecutionTier::kTurbofan);
3745void CompilationStateImpl::InitializeCompilationProgress(
3746 ProfileInformation* pgo_info) {
3752 auto*
module = native_module_->module();
3757 const ExecutionTierPair default_tiers = GetDefaultTiersPerModule(
3759 const uint8_t default_progress =
3760 RequiredBaselineTierField::encode(default_tiers.baseline_tier) |
3761 RequiredTopTierField::encode(default_tiers.top_tier) |
3762 ReachedTierField::encode(ExecutionTier::kNone);
3765 if (default_tiers.baseline_tier != ExecutionTier::kNone) {
3770 if (
native_module_->enabled_features().has_compilation_hints()) {
3771 size_t num_hints = std::min(module->compilation_hints.size(),
3772 size_t{module->num_declared_functions});
3773 for (
size_t hint_idx = 0; hint_idx < num_hints; ++hint_idx) {
3774 const auto& hint =
module->compilation_hints[hint_idx];
3775 ApplyCompilationHintToInitialProgress(hint, hint_idx);
3782 v8_flags.wasm_eager_tier_up_function >= 0 &&
3783 static_cast<uint32_t
>(
v8_flags.wasm_eager_tier_up_function) >=
3784 module->num_imported_functions &&
3785 static_cast<uint32_t
>(
v8_flags.wasm_eager_tier_up_function) <
3786 module->functions.size())) {
3788 v8_flags.wasm_eager_tier_up_function -
module->num_imported_functions;
3789 WasmCompilationHint hint{WasmCompilationHintStrategy::kEager,
3790 WasmCompilationHintTier::kOptimized,
3791 WasmCompilationHintTier::kOptimized};
3792 ApplyCompilationHintToInitialProgress(hint, func_idx);
3797 if (pgo_info) ApplyPgoInfoToInitialProgress(pgo_info);
3801 TriggerOutstandingCallbacks();
3804void CompilationStateImpl::AddCompilationUnitInternal(
3805 CompilationUnitBuilder* builder,
int function_index,
3806 uint8_t function_progress) {
3808 CompilationStateImpl::RequiredBaselineTierField::decode(
3811 CompilationStateImpl::RequiredTopTierField::decode(function_progress);
3813 CompilationStateImpl::ReachedTierField::decode(function_progress);
3815 if (reached_tier < required_baseline_tier) {
3816 builder->AddBaselineUnit(function_index, required_baseline_tier);
3818 if (reached_tier < required_top_tier &&
3819 required_baseline_tier != required_top_tier) {
3820 builder->AddTopTierUnit(function_index, required_top_tier);
3824void CompilationStateImpl::InitializeCompilationUnits(
3825 std::unique_ptr<CompilationUnitBuilder> builder) {
3833 int func_index =
offset +
static_cast<int>(
i);
3834 AddCompilationUnitInternal(builder.get(), func_index,
3842void CompilationStateImpl::AddCompilationUnit(CompilationUnitBuilder* builder,
3845 int progress_index = func_index -
offset;
3846 uint8_t function_progress = 0;
3857 AddCompilationUnitInternal(builder, func_index, function_progress);
3860void CompilationStateImpl::InitializeCompilationProgressAfterDeserialization(
3861 base::Vector<const int> lazy_functions,
3862 base::Vector<const int> eager_functions) {
3863 TRACE_EVENT2(
"v8.wasm",
"wasm.CompilationAfterDeserialization",
3864 "num_lazy_functions", lazy_functions.size(),
3865 "num_eager_functions", eager_functions.size());
3866 std::optional<TimedHistogramScope> lazy_compile_time_scope;
3867 if (base::TimeTicks::IsHighResolution()) {
3868 lazy_compile_time_scope.emplace(
3869 counters()->wasm_compile_after_deserialize());
3872 auto*
module = native_module_->module();
3879 constexpr uint8_t kProgressAfterTurbofanDeserialization =
3880 RequiredBaselineTierField::encode(ExecutionTier::kLiftoff) |
3881 RequiredTopTierField::encode(ExecutionTier::kTurbofan) |
3882 ReachedTierField::encode(ExecutionTier::kTurbofan);
3884 kProgressAfterTurbofanDeserialization);
3887 constexpr uint8_t kProgressForLazyFunctions =
3888 RequiredBaselineTierField::encode(ExecutionTier::kNone) |
3889 RequiredTopTierField::encode(ExecutionTier::kNone) |
3890 ReachedTierField::encode(ExecutionTier::kNone);
3891 for (
auto func_index : lazy_functions) {
3893 kProgressForLazyFunctions;
3897 constexpr bool kNotLazy =
false;
3898 ExecutionTierPair default_tiers = GetDefaultTiersPerModule(
3900 uint8_t progress_for_eager_functions =
3901 RequiredBaselineTierField::encode(default_tiers.baseline_tier) |
3902 RequiredTopTierField::encode(default_tiers.top_tier) |
3903 ReachedTierField::encode(ExecutionTier::kNone);
3904 for (
auto func_index : eager_functions) {
3908 kProgressAfterTurbofanDeserialization);
3910 progress_for_eager_functions;
3912 DCHECK_NE(ExecutionTier::kNone, default_tiers.baseline_tier);
3917 if (eager_functions.empty() ||
v8_flags.wasm_lazy_compilation) {
3921 auto builder = std::make_unique<CompilationUnitBuilder>(
native_module_);
3922 InitializeCompilationUnits(std::move(builder));
3923 if (!
v8_flags.wasm_lazy_compilation) {
3924 WaitForCompilationEvent(CompilationEvent::kFinishedBaselineCompilation);
3928void CompilationStateImpl::AddCallback(
3929 std::unique_ptr<CompilationEventCallback>
callback) {
3932 for (
auto event : {CompilationEvent::kFinishedBaselineCompilation,
3933 CompilationEvent::kFailedCompilation}) {
3938 constexpr base::EnumSet<CompilationEvent> kFinalEvents{
3939 CompilationEvent::kFailedCompilation};
3945void CompilationStateImpl::CommitCompilationUnits(
3946 base::Vector<WasmCompilationUnit> baseline_units,
3947 base::Vector<WasmCompilationUnit> top_tier_units) {
3948 base::MutexGuard guard{&
mutex_};
3949 if (!baseline_units.empty() || !top_tier_units.empty()) {
3953 if (!baseline_units.empty()) {
3957 if (!top_tier_units.empty()) {
3963void CompilationStateImpl::CommitTopTierCompilationUnit(
3964 WasmCompilationUnit
unit) {
3965 CommitCompilationUnits({}, {&
unit, 1});
3968void CompilationStateImpl::AddTopTierPriorityCompilationUnit(
3977CompilationUnitQueues::Queue* CompilationStateImpl::GetQueueForCompileTask(
3982std::optional<WasmCompilationUnit> CompilationStateImpl::GetNextCompilationUnit(
3983 CompilationUnitQueues::Queue* queue, CompilationTier tier) {
3987void CompilationStateImpl::OnFinishedUnits(
3988 base::Vector<WasmCode*> code_vector) {
3990 "wasm.OnFinishedUnits",
"units", code_vector.size());
3996 static_assert(ExecutionTier::kNone < ExecutionTier::kLiftoff &&
3997 ExecutionTier::kLiftoff < ExecutionTier::kTurbofan,
3998 "Assume an order on execution tiers");
4005 bool has_top_tier_code =
false;
4007 for (
size_t i = 0;
i < code_vector.
size();
i++) {
4008 WasmCode* code = code_vector[
i];
4012 has_top_tier_code |= code->tier() == ExecutionTier::kTurbofan;
4017 DCHECK_EQ(code->tier(), ExecutionTier::kTurbofan);
4021 DCHECK_NE(code->tier(), ExecutionTier::kNone);
4031 RequiredBaselineTierField::decode(function_progress);
4032 ExecutionTier reached_tier = ReachedTierField::decode(function_progress);
4035 if (reached_tier < required_baseline_tier &&
4036 required_baseline_tier <= code->tier()) {
4040 if (code->tier() == ExecutionTier::kTurbofan) {
4045 if (code->tier() > reached_tier) {
4061 const bool is_liftoff = code->tier() == ExecutionTier::kLiftoff;
4062 auto published_code_is_liftoff = [
this](
int index) {
4064 if (code ==
nullptr)
return false;
4065 return code->is_liftoff();
4068 (is_liftoff || published_code_is_liftoff(code->index()))) {
4072 DCHECK_LE(required_baseline_tier, ExecutionTier::kLiftoff);
4087 TriggerOutstandingCallbacks();
4091class TriggerCodeCachingAfterTimeoutTask :
public v8::Task {
4093 explicit TriggerCodeCachingAfterTimeoutTask(
4094 std::weak_ptr<NativeModule> native_module)
4097 void Run()
override {
4098 if (std::shared_ptr<NativeModule> native_module =
native_module_.lock()) {
4099 Impl(native_module->compilation_state())->TriggerCachingAfterTimeout();
4108void CompilationStateImpl::TriggerOutstandingCallbacks() {
4111 base::EnumSet<CompilationEvent> triggered_events;
4113 triggered_events.Add(CompilationEvent::kFinishedBaselineCompilation);
4118 if (
v8_flags.wasm_dynamic_tiering &&
4119 static_cast<size_t>(
v8_flags.wasm_caching_threshold) <=
4126 static_cast<size_t>(
v8_flags.wasm_caching_hard_threshold) <=
4128 triggered_events.Add(CompilationEvent::kFinishedCompilationChunk);
4134 V8::GetCurrentPlatform()->PostDelayedTaskOnWorkerThread(
4135 TaskPriority::kUserVisible,
4136 std::make_unique<TriggerCodeCachingAfterTimeoutTask>(
4138 1e-3 *
v8_flags.wasm_caching_timeout_ms);
4149 base::EnumSet<CompilationEvent>({CompilationEvent::kFailedCompilation});
4152 TriggerCallbacks(triggered_events);
4155void CompilationStateImpl::TriggerCallbacks(
4156 base::EnumSet<CompilationEvent> events) {
4157 if (events.empty())
return;
4165 {std::make_pair(CompilationEvent::kFailedCompilation,
4166 "wasm.CompilationFailed"),
4167 std::make_pair(CompilationEvent::kFinishedBaselineCompilation,
4168 "wasm.BaselineFinished"),
4169 std::make_pair(CompilationEvent::kFinishedCompilationChunk,
4170 "wasm.CompilationChunkFinished")}) {
4171 if (!events.contains(event.first))
continue;
4180 auto new_end = std::remove_if(
4182 return callback->release_after_final_event();
4188void CompilationStateImpl::TriggerCachingAfterTimeout() {
4197 base::TimeTicks caching_time =
4199 base::TimeDelta::FromMilliseconds(
v8_flags.wasm_caching_timeout_ms);
4200 base::TimeDelta time_until_caching = caching_time - base::TimeTicks::Now();
4203 if (time_until_caching >= base::TimeDelta::FromMicroseconds(500)) {
4205 static_cast<int>(time_until_caching.InMillisecondsRoundedUp());
4207 V8::GetCurrentPlatform()->PostDelayedTaskOnWorkerThread(
4208 TaskPriority::kUserVisible,
4209 std::make_unique<TriggerCodeCachingAfterTimeoutTask>(
4215 TriggerCallbacks({CompilationEvent::kFinishedCompilationChunk});
4220void CompilationStateImpl::OnCompilationStopped(
4221 WasmDetectedFeatures detected_features) {
4222 WasmDetectedFeatures new_detected_features =
4223 UpdateDetectedFeatures(detected_features);
4224 if (new_detected_features.empty())
return;
4231 (new_detected_features -
4232 WasmDetectedFeatures{{WasmDetectedFeature::stringref,
4233 WasmDetectedFeature::imported_strings_utf8,
4234 WasmDetectedFeature::imported_strings}})
4240WasmDetectedFeatures CompilationStateImpl::UpdateDetectedFeatures(
4241 WasmDetectedFeatures detected_features) {
4242 WasmDetectedFeatures old_features =
4245 old_features, old_features | detected_features,
4246 std::memory_order_relaxed)) {
4249 return detected_features - old_features;
4252void CompilationStateImpl::PublishCompilationResults(
4253 std::vector<UnpublishedWasmCode> unpublished_code) {
4254 if (unpublished_code.empty())
return;
4258 for (
const auto& [code, assumptions] : unpublished_code) {
4259 int func_index = code->index();
4264 PublishCode(base::VectorOf(unpublished_code));
4267std::vector<WasmCode*> CompilationStateImpl::PublishCode(
4268 base::Vector<UnpublishedWasmCode> code) {
4269 WasmCodeRefScope code_ref_scope;
4270 std::vector<WasmCode*> published_code =
4277 OnFinishedUnits(base::VectorOf(published_code));
4278 return published_code;
4281void CompilationStateImpl::SchedulePublishCompilationResults(
4282 std::vector<UnpublishedWasmCode> unpublished_code, CompilationTier tier) {
4285 base::MutexGuard guard(&state.mutex_);
4286 if (state.publisher_running_) {
4288 state.publish_queue_.reserve(state.publish_queue_.size() +
4289 unpublished_code.size());
4290 for (
auto& c : unpublished_code) {
4291 state.publish_queue_.emplace_back(std::move(c));
4295 state.publisher_running_ =
true;
4298 PublishCompilationResults(std::move(unpublished_code));
4299 unpublished_code.clear();
4302 base::MutexGuard guard(&state.mutex_);
4303 DCHECK(state.publisher_running_);
4304 if (state.publish_queue_.empty()) {
4305 state.publisher_running_ =
false;
4308 unpublished_code.swap(state.publish_queue_);
4312size_t CompilationStateImpl::NumOutstandingCompilations(
4313 CompilationTier tier)
const {
4317void CompilationStateImpl::SetError() {
4324 TriggerOutstandingCallbacks();
4328void CompilationStateImpl::WaitForCompilationEvent(
4330 switch (expect_event) {
4331 case CompilationEvent::kFinishedBaselineCompilation:
4339 base::EnumSet<CompilationEvent> events{expect_event,
4340 CompilationEvent::kFailedCompilation};
4346void CompilationStateImpl::TierUpAllFunctions() {
4348 uint32_t num_wasm_functions =
module->num_declared_functions;
4349 WasmCodeRefScope code_ref_scope;
4351 for (uint32_t
i = 0;
i < num_wasm_functions; ++
i) {
4352 int func_index =
module->num_imported_functions + i;
4354 if (!code || !code->is_turbofan()) {
4355 builder.AddTopTierUnit(func_index, ExecutionTier::kTurbofan);
4362 bool ShouldYield()
override {
return false; }
4363 bool IsJoiningThread()
const override {
return true; }
4364 void NotifyConcurrencyIncrease()
override {
UNIMPLEMENTED(); }
4365 uint8_t GetTaskId()
override {
return kMainTaskId; }
4368 DummyDelegate delegate;
4370 CompilationTier::kTopTier);
4374 for (uint32_t
i = 0;
i < num_wasm_functions; ++
i) {
4375 uint32_t func_index =
module->num_imported_functions + i;
4377 if (!code || !code->is_turbofan()) {
4380 wasm::ExecutionTier::kTurbofan);
4390 int expected_arity,
Suspend suspend) {
4409#undef TRACE_STREAMING
#define SBXCHECK_LE(lhs, rhs)
#define SBXCHECK_EQ(lhs, rhs)
#define SLOW_DCHECK(condition)
virtual bool ShouldYield()=0
virtual void NotifyConcurrencyIncrease()=0
void PostTask(std::unique_ptr< Task > task, const SourceLocation &location=SourceLocation::Current())
constexpr bool contains_all(EnumSet set) const
constexpr bool contains(E element) const
Hasher & AddRange(Iterator first, Iterator last)
constexpr size_t hash() const
constexpr size_t size() const
Vector< T > as_vector() const
static OwnedVector< T > NewForOverwrite(size_t size)
int64_t InMicroseconds() const
static bool IsHighResolution()
Vector< T > SubVector(size_t from, size_t to) const
constexpr size_t size() const
Vector< T > SubVectorFrom(size_t from) const
constexpr T * data() const
void OnAfterCompile(DirectHandle< Script > script)
V8_WARN_UNUSED_RESULT MaybeHandle< String > NewStringFromUtf8(base::Vector< const char > str, AllocationType allocation=AllocationType::kYoung)
static void Destroy(Address *location)
IndirectHandle< Object > Create(Tagged< Object > value)
GlobalHandles * global_handles() const
const std::shared_ptr< Counters > & async_counters()
void CountUsage(v8::Isolate::UseCounterFeature feature)
Tagged< Context > context() const
v8::internal::Factory * factory()
const std::shared_ptr< metrics::Recorder > & metrics_recorder()
V8_INLINE DirectHandle< T > ToHandleChecked() const
static V8_EXPORT_PRIVATE v8::Platform * GetCurrentPlatform()
static V8_EXPORT_PRIVATE DirectHandle< WasmModuleObject > New(Isolate *isolate, std::shared_ptr< wasm::NativeModule > native_module, DirectHandle< Script > script)
CompilationStateCallback(AsyncCompileJob *job)
void call(CompilationEvent event) override
virtual ~CompileStep()=default
virtual void RunInBackground(AsyncCompileJob *)
void Run(AsyncCompileJob *job, bool on_foreground)
virtual void RunInForeground(AsyncCompileJob *)
void ResetPendingForegroundTask() const
CompileTask(AsyncCompileJob *job, bool on_foreground)
void RunInBackground(AsyncCompileJob *job) override
DecodeModule(Counters *counters, std::shared_ptr< metrics::Recorder > metrics_recorder)
std::shared_ptr< metrics::Recorder > metrics_recorder_
Counters *const counters_
void RunInForeground(AsyncCompileJob *job) override
FinishCompilation(std::shared_ptr< NativeModule > cached_native_module)
std::shared_ptr< NativeModule > cached_native_module_
void RunInForeground(AsyncCompileJob *job) override
const size_t code_size_estimate_
const bool start_compilation_
void RunInForeground(AsyncCompileJob *job) override
PrepareAndStartCompile(std::shared_ptr< const WasmModule > module, bool start_compilation, bool lazy_functions_are_validated, size_t code_size_estimate)
const std::shared_ptr< const WasmModule > module_
const bool lazy_functions_are_validated_
CompileTimeImports compile_imports_
const char *const api_method_name_
Isolate * isolate() const
V8_WARN_UNUSED_RESULT bool DecrementAndCheckFinisherCount()
const WasmEnabledFeatures enabled_features_
void NextStep(Args &&... args)
void FinishCompile(bool is_after_cache_hit)
CancelableTaskManager background_task_manager_
IndirectHandle< WasmModuleObject > module_object_
const std::shared_ptr< CompilationResultResolver > resolver_
WasmDetectedFeatures detected_features_
IndirectHandle< NativeContext > incumbent_context_
std::shared_ptr< StreamingDecoder > CreateStreamingDecoder()
v8::metrics::Recorder::ContextId context_id_
std::shared_ptr< v8::TaskRunner > foreground_task_runner_
IndirectHandle< NativeContext > native_context_
std::shared_ptr< StreamingDecoder > stream_
std::shared_ptr< NativeModule > native_module_
void FinishSuccessfully()
v8::metrics::Recorder::ContextId context_id() const
void CancelPendingForegroundTask()
void StartBackgroundTask()
void StartForegroundTask()
base::TimeTicks start_time_
void DoImmediately(Args &&... args)
std::atomic< int32_t > outstanding_finishers_
const int compilation_id_
bool GetOrCreateNativeModule(std::shared_ptr< const WasmModule > module, size_t code_size_estimate)
void ExecuteForegroundTaskImmediately()
v8::metrics::WasmModuleDecoded metrics_event_
void DoAsync(Args &&... args)
void CreateNativeModule(std::shared_ptr< const WasmModule > module, size_t code_size_estimate)
CompileTask * pending_foreground_task_
base::OwnedVector< const uint8_t > bytes_copy_
void PrepareRuntimeObjects()
std::unique_ptr< CompileStep > step_
void DoSync(Args &&... args)
ModuleWireBytes wire_bytes_
UseExistingForegroundTask
void OnFinishedStream(base::OwnedVector< const uint8_t > bytes, bool after_error) override
void OnFinishedChunk() override
bool before_code_section_
base::Hasher prefix_hasher_
std::unique_ptr< JobHandle > validate_functions_job_handle_
bool ProcessCodeSectionHeader(int num_functions, uint32_t functions_mismatch_error_offset, std::shared_ptr< WireBytesStorage >, int code_section_start, int code_section_length) override
AsyncStreamingProcessor(AsyncCompileJob *job)
bool ProcessFunctionBody(base::Vector< const uint8_t > bytes, uint32_t offset) override
bool ProcessSection(SectionCode section_code, base::Vector< const uint8_t > bytes, uint32_t offset) override
ValidateFunctionsStreamingJobData validate_functions_job_data_
bool Deserialize(base::Vector< const uint8_t > wire_bytes, base::Vector< const uint8_t > module_bytes) override
std::unique_ptr< CompilationUnitBuilder > compilation_unit_builder_
void CommitCompilationUnits()
bool ProcessModuleHeader(base::Vector< const uint8_t > bytes) override
bool is_megamorphic() const
int call_count(int i) const
bool has_non_inlineable_targets() const
int function_index(int i) const
bool has_string_constants(base::Vector< const uint8_t > name) const
bool contains(CompileTimeImport imp) const
void CompileFailed(const WasmError &error)
V8_WARN_UNUSED_RESULT DirectHandle< JSObject > Reify()
void AddCall(int target, int count)
void AddCallRefCandidate(Tagged< WasmFuncRef > funcref, int count)
const Tagged< WasmTrustedInstanceData > instance_data_
void AddCallIndirectCandidate(Tagged< Object > target_truncated_obj, int count)
bool HasTargetCached(int target)
void set_has_non_inlineable_targets()
FeedbackMaker(Isolate *const isolate, Tagged< WasmTrustedInstanceData > trusted_instance_data, int func_index, int num_calls)
base::OwnedVector< CallSiteFeedback > GetResult() &&
base::OwnedVector< CallSiteFeedback > result_
void AddResult(CallSiteFeedback feedback)
std::array< int, kMaxPolymorphism > targets_cache_
std::array< int, kMaxPolymorphism > counts_cache_
const int num_imported_functions_
WasmModule * module() const
void DecodeSection(SectionCode section_code, base::Vector< const uint8_t > bytes, uint32_t offset)
void StartCodeSection(WireBytesRef section_bytes)
const std::shared_ptr< WasmModule > & shared_module() const
ModuleResult FinishDecoding()
void DecodeModuleHeader(base::Vector< const uint8_t > bytes)
static size_t IdentifyUnknownSection(ModuleDecoder *decoder, base::Vector< const uint8_t > bytes, uint32_t offset, SectionCode *result)
void DecodeFunctionBody(uint32_t index, uint32_t size, uint32_t offset)
bool CheckFunctionsCount(uint32_t functions_count, uint32_t error_offset)
static size_t PrefixHash(base::Vector< const uint8_t > wire_bytes)
CompilationState * compilation_state() const
uint32_t num_functions() const
const WasmModule * module() const
base::Vector< const uint8_t > wire_bytes() const
bool HasCodeWithTier(uint32_t index, ExecutionTier tier) const
WasmCode * PublishCode(UnpublishedWasmCode)
DebugState IsInDebugState() const
bool lazy_compile_frozen() const
V8_WARN_UNUSED_RESULT UnpublishedWasmCode AddCompiledCode(WasmCompilationResult &)
WasmEnabledFeatures enabled_features() const
uint32_t num_imported_functions() const
const T & value() const &
static std::unique_ptr< StreamingDecoder > CreateAsyncStreamingDecoder(std::unique_ptr< StreamingProcessor > processor)
const Tagged< WasmTrustedInstanceData > instance_data_
void EnqueueCallees(base::Vector< CallSiteFeedback > feedback)
std::unordered_map< uint32_t, FunctionTypeFeedback > & feedback_for_function_
TransitiveTypeFeedbackProcessor(Isolate *isolate, Tagged< WasmTrustedInstanceData > trusted_instance_data, int func_index)
DisallowGarbageCollection no_gc_scope_
static void Process(Isolate *isolate, Tagged< WasmTrustedInstanceData > trusted_instance_data, int func_index)
const WasmModule *const module_
~TransitiveTypeFeedbackProcessor()
base::MutexGuard mutex_guard
const WasmEnabledFeatures enabled_features_
void Run(JobDelegate *delegate) override
ValidateFunctionsStreamingJob(const WasmModule *module, WasmEnabledFeatures enabled_features, ValidateFunctionsStreamingJobData *data)
ValidateFunctionsStreamingJobData * data_
const WasmModule *const module_
size_t GetMaxConcurrency(size_t worker_count) const override
static size_t EstimateNativeModuleCodeSize(const WasmModule *)
Address GetEntrypointWithoutSignatureCheck(WasmCodePointer index) const
std::shared_ptr< NativeModule > MaybeGetNativeModule(ModuleOrigin origin, base::Vector< const uint8_t > wire_bytes, const CompileTimeImports &compile_imports, Isolate *isolate)
void LogCode(base::Vector< WasmCode * >)
AccountingAllocator * allocator()
void LogOutstandingCodesForIsolate(Isolate *)
std::unique_ptr< AsyncCompileJob > RemoveCompileJob(AsyncCompileJob *job)
DirectHandle< Script > GetOrCreateScript(Isolate *, const std::shared_ptr< NativeModule > &, base::Vector< const char > source_url)
void StreamingCompilationFailed(size_t prefix_hash, const CompileTimeImports &compile_imports)
std::shared_ptr< NativeModule > NewNativeModule(Isolate *isolate, WasmEnabledFeatures enabled_features, WasmDetectedFeatures detected_features, CompileTimeImports compile_imports, std::shared_ptr< const WasmModule > module, size_t code_size_estimate)
std::shared_ptr< NativeModule > UpdateNativeModuleCache(bool has_error, std::shared_ptr< NativeModule > native_module, Isolate *isolate)
WasmCode * CompileWasmImportCallWrapper(Isolate *isolate, ImportCallKind kind, const CanonicalSig *sig, CanonicalTypeIndex sig_index, bool source_positions, int expected_arity, Suspend suspend)
uint32_t end_offset() const
base::Vector< const DirectHandle< Object > > args
v8::Global< v8::Promise::Resolver > resolver_
SourcePositionTable * source_positions
ZoneVector< RpoNumber > & result
size_t bytes_since_last_chunk_
std::shared_ptr< NativeModule > native_module_
base::ElapsedTimer timer_
#define CHECK_SIG(import_name, kSigName, kEnumName)
std::atomic< size_t > num_units_[CompilationTier::kNumTiers]
v8::metrics::Recorder::ContextId context_id_
const int num_imported_functions_
std::priority_queue< TopTierPriorityUnit > top_tier_priority_units
base::TimeTicks last_top_tier_compilation_timestamp_
std::unique_ptr< std::atomic< bool >[]> top_tier_compiled_
std::atomic< bool > compile_failed_
PublishState publish_state_[CompilationTier::kNumTiers]
std::shared_ptr< OperationsBarrier > engine_barrier_
base::Mutex queues_mutex_
std::atomic< size_t > num_priority_units_
const CompileMode compile_mode_
static constexpr size_t kBigUnitsLimit
std::shared_ptr< metrics::Recorder > metrics_recorder_
int outstanding_baseline_units_
std::vector< uint8_t > compilation_progress_
const CompilationTier tier_
std::unique_ptr< JobHandle > top_tier_compile_job_
#define TRACE_COMPILE(...)
std::shared_ptr< WireBytesStorage > wire_bytes_storage_
base::TimeTicks start_time_
std::unique_ptr< JobHandle > baseline_compile_job_
std::atomic< WasmDetectedFeatures > detected_features_
CompilationUnitQueues compilation_unit_queues_
std::atomic< bool > compile_cancelled_
BigUnitsQueue big_units_queue_
std::weak_ptr< NativeModule > const native_module_weak_
const std::shared_ptr< Counters > async_counters_
std::vector< std::unique_ptr< QueueImpl > > queues_
ExecutionTier baseline_tier
std::vector< WasmCompilationUnit > baseline_units_
base::Mutex callbacks_mutex_
std::atomic< bool > has_units[CompilationTier::kNumTiers]
#define RETURN_ERROR(module_name_string, import_name)
const int num_declared_functions_
#define TRACE_STREAMING(...)
std::vector< std::unique_ptr< CompilationEventCallback > > callbacks_
std::vector< WasmCompilationUnit > tiering_units_
std::priority_queue< BigUnit > units[CompilationTier::kNumTiers]
static constexpr int kInvalidCompilationID
std::atomic< int > next_queue_to_add
base::EnumSet< CompilationEvent > finished_events_
std::vector< UnpublishedWasmCode > publish_queue_
std::atomic< int > publish_limit
#define CHECK_USE_COUNTER(feat,...)
const base::Vector< const uint8_t > wire_bytes_
const WasmEnabledFeatures enabled_features_
v8::JobDelegate JobDelegate
constexpr bool IsPowerOfTwo(T value)
constexpr Vector< T > VectorOf(T *start, size_t size)
LockGuard< Mutex > MutexGuard
template const Signature< wasm::ValueType > bool
@ kFinishedBaselineCompilation
@ kFinishedCompilationChunk
V8_EXPORT_PRIVATE WasmCodePointerTable * GetProcessWideWasmCodePointerTable()
void TierUpNowForTesting(Isolate *isolate, Tagged< WasmTrustedInstanceData > trusted_instance_data, int func_index)
WasmImportWrapperCache * GetWasmImportWrapperCache()
constexpr IndependentHeapType kWasmRefExtern
void TriggerTierUp(Isolate *isolate, Tagged< WasmTrustedInstanceData > trusted_instance_data, int func_index)
void TierUpAllForTesting(Isolate *isolate, Tagged< WasmTrustedInstanceData > trusted_instance_data)
void InitializeCompilationForTesting(NativeModule *native_module)
bool is_asmjs_module(const WasmModule *module)
constexpr IndependentHeapType kWasmExternRef
constexpr IndependentValueType kWasmI32
ModuleResult DecodeWasmModule(WasmEnabledFeatures enabled_features, base::Vector< const uint8_t > wire_bytes, bool validate_functions, ModuleOrigin origin, Counters *counters, std::shared_ptr< metrics::Recorder > metrics_recorder, v8::metrics::Recorder::ContextId context_id, DecodingMethod decoding_method, WasmDetectedFeatures *detected_features)
WasmCode * CompileImportWrapperForTest(Isolate *isolate, NativeModule *native_module, ImportCallKind kind, const CanonicalSig *sig, CanonicalTypeIndex type_index, int expected_arity, Suspend suspend)
void ThrowLazyCompilationError(Isolate *isolate, const NativeModule *native_module, int func_index)
MaybeDirectHandle< WasmModuleObject > DeserializeNativeModule(Isolate *isolate, base::Vector< const uint8_t > data, base::Vector< const uint8_t > wire_bytes_vec, const CompileTimeImports &compile_imports, base::Vector< const char > source_url)
std::shared_ptr< NativeModule > CompileToNativeModule(Isolate *isolate, WasmEnabledFeatures enabled_features, WasmDetectedFeatures detected_features, CompileTimeImports compile_imports, ErrorThrower *thrower, std::shared_ptr< const WasmModule > module, base::OwnedVector< const uint8_t > wire_bytes, int compilation_id, v8::metrics::Recorder::ContextId context_id, ProfileInformation *pgo_info)
WasmError ValidateAndSetBuiltinImports(const WasmModule *module, base::Vector< const uint8_t > wire_bytes, const CompileTimeImports &imports, WasmDetectedFeatures *detected)
size_t ContentSize(const std::vector< T > &vector)
constexpr int kMaxPolymorphism
WasmError ValidateFunctions(const WasmModule *module, WasmEnabledFeatures enabled_features, base::Vector< const uint8_t > wire_bytes, std::function< bool(int)> filter, WasmDetectedFeatures *detected_features_out)
DecodeResult ValidateFunctionBody(Zone *zone, WasmEnabledFeatures enabled, const WasmModule *module, WasmDetectedFeatures *detected, const FunctionBody &body)
WasmEngine * GetWasmEngine()
int declared_function_index(const WasmModule *module, int func_index)
std::unique_ptr< ProfileInformation > LoadProfileFromFile(const WasmModule *module, base::Vector< const uint8_t > wire_bytes)
@ kLazyBaselineEagerTopTier
bool IsCrossInstanceCall(Tagged< Object > obj, Isolate *const isolate)
void PublishDetectedFeatures(WasmDetectedFeatures detected_features, Isolate *isolate, bool is_initial_compilation)
bool CompileLazy(Isolate *isolate, Tagged< WasmTrustedInstanceData > trusted_instance_data, int func_index)
WasmError GetWasmErrorWithName(base::Vector< const uint8_t > wire_bytes, int func_index, const WasmModule *module, WasmError error)
V8_INLINE IndirectHandle< T > handle(Tagged< T > object, Isolate *isolate)
void PrintF(const char *format,...)
wasm::WasmModule WasmModule
V8_INLINE constexpr bool IsSmi(TaggedImpl< kRefType, StorageType > obj)
kWasmInternalFunctionIndirectPointerTag kProtectedInstanceDataOffset sig
V8_INLINE constexpr bool operator<(Builtin a, Builtin b)
V8_EXPORT_PRIVATE FlagValues v8_flags
JSArrayBuffer::IsDetachableBit is_shared
wasm::WasmFunction WasmFunction
kInterpreterTrampolineOffset script
#define DCHECK_LE(v1, v2)
#define CHECK_IMPLIES(lhs, rhs)
#define DCHECK_NOT_NULL(val)
#define DCHECK_IMPLIES(v1, v2)
#define DCHECK_NE(v1, v2)
#define DCHECK_GE(v1, v2)
#define DCHECK(condition)
#define DCHECK_LT(v1, v2)
#define DCHECK_EQ(v1, v2)
#define DCHECK_GT(v1, v2)
#define UPDATE_WHEN_CLASS_CHANGES(classname, size)
WasmName GetNameOrNull(WireBytesRef ref) const
base::Vector< const uint8_t > module_bytes() const
base::Vector< const uint8_t > code
base::OwnedVector< Unit > units
void Initialize(int num_declared_functions)
std::atomic< Unit * > end_of_available_units
std::atomic< Unit * > next_available_unit
void UpdateDetectedFeatures(WasmDetectedFeatures new_detected_features)
size_t NumOutstandingUnits() const
std::atomic< bool > found_error
std::atomic< WasmDetectedFeatures > detected_features
void AddUnit(int declared_func_index, base::Vector< const uint8_t > code, JobHandle *job_handle)
bool has_array(ModuleTypeIndex index) const
std::vector< WasmImport > import_table
uint32_t num_declared_functions
const ModuleOrigin origin
uint32_t num_imported_functions
std::vector< WasmGlobal > globals
TypeFeedbackStorage type_feedback
size_t module_size_in_bytes
int64_t wall_clock_duration_in_us
#define TRACE_EVENT0(category_group, name)
#define TRACE_EVENT2(category_group, name, arg1_name, arg1_val, arg2_name, arg2_val)
#define TRACE_DISABLED_BY_DEFAULT(name)
#define TRACE_EVENT1(category_group, name, arg1_name, arg1_val)
#define V8_LIKELY(condition)
#define V8_WARN_UNUSED_RESULT
#define V8_UNLIKELY(condition)
#define FOREACH_WASM_STAGING_FEATURE_FLAG(V)
#define FOREACH_WASM_SHIPPED_FEATURE_FLAG(V)
#define FOREACH_WASM_NON_FLAG_FEATURE(V)
const wasm::WasmModule * module_
#define SELECT_WASM_COUNTER(counters, origin, prefix, suffix)