@@ -129,7 +129,8 @@ class CompilationStateImpl {
129
129
void SetNumberOfFunctionsToCompile (int num_functions);
130
130
131
131
// Add the callback function to be called on compilation events. Needs to be
132
- // set before {AddCompilationUnits} is run.
132
+ // set before {AddCompilationUnits} is run to ensure that it receives all
133
+ // events. The callback object must support being deleted from any thread.
133
134
void AddCallback (CompilationState::callback_t );
134
135
135
136
// Inserts new functions to compile and kicks off compilation.
@@ -153,7 +154,7 @@ class CompilationStateImpl {
153
154
}
154
155
155
156
bool baseline_compilation_finished () const {
156
- base::MutexGuard guard (&mutex_ );
157
+ base::MutexGuard guard (&callbacks_mutex_ );
157
158
return outstanding_baseline_units_ == 0 ||
158
159
(compile_mode_ == CompileMode::kTiering &&
159
160
outstanding_tiering_units_ == 0 );
@@ -203,8 +204,6 @@ class CompilationStateImpl {
203
204
: func_index(func_index), error(std::move(error)) {}
204
205
};
205
206
206
- void NotifyOnEvent (CompilationEvent event);
207
-
208
207
NativeModule* const native_module_;
209
208
const std::shared_ptr<BackgroundCompileToken> background_compile_token_;
210
209
const CompileMode compile_mode_;
@@ -236,16 +235,26 @@ class CompilationStateImpl {
236
235
// compiling.
237
236
std::shared_ptr<WireBytesStorage> wire_bytes_storage_;
238
237
239
- int outstanding_baseline_units_ = 0 ;
240
- int outstanding_tiering_units_ = 0 ;
241
-
242
238
// End of fields protected by {mutex_}.
243
239
// ////////////////////////////////////////////////////////////////////////////
244
240
245
- // Callback functions to be called on compilation events. Only accessible from
246
- // the foreground thread.
241
+ // This mutex protects the callbacks vector, and the counters used to
242
+ // determine which callbacks to call. The counters plus the callbacks
243
+ // themselves need to be synchronized to ensure correct order of events.
244
+ mutable base::Mutex callbacks_mutex_;
245
+
246
+ // ////////////////////////////////////////////////////////////////////////////
247
+ // Protected by {callbacks_mutex_}:
248
+
249
+ // Callback functions to be called on compilation events.
247
250
std::vector<CompilationState::callback_t > callbacks_;
248
251
252
+ int outstanding_baseline_units_ = 0 ;
253
+ int outstanding_tiering_units_ = 0 ;
254
+
255
+ // End of fields protected by {callbacks_mutex_}.
256
+ // ////////////////////////////////////////////////////////////////////////////
257
+
249
258
const int max_background_tasks_ = 0 ;
250
259
};
251
260
@@ -852,6 +861,7 @@ std::shared_ptr<StreamingDecoder> AsyncCompileJob::CreateStreamingDecoder() {
852
861
}
853
862
854
863
AsyncCompileJob::~AsyncCompileJob () {
864
+ // Note: This destructor always runs on the foreground thread of the isolate.
855
865
background_task_manager_.CancelAndWait ();
856
866
// If the runtime objects were not created yet, then initial compilation did
857
867
// not finish yet. In this case we can abort compilation.
@@ -1473,12 +1483,13 @@ CompilationStateImpl::~CompilationStateImpl() {
1473
1483
void CompilationStateImpl::AbortCompilation () {
1474
1484
background_compile_token_->Cancel ();
1475
1485
// No more callbacks after abort.
1486
+ base::MutexGuard callbacks_guard (&callbacks_mutex_);
1476
1487
callbacks_.clear ();
1477
1488
}
1478
1489
1479
1490
void CompilationStateImpl::SetNumberOfFunctionsToCompile (int num_functions) {
1480
1491
DCHECK (!failed ());
1481
- base::MutexGuard guard (&mutex_ );
1492
+ base::MutexGuard guard (&callbacks_mutex_ );
1482
1493
outstanding_baseline_units_ = num_functions;
1483
1494
1484
1495
if (compile_mode_ == CompileMode::kTiering ) {
@@ -1487,6 +1498,7 @@ void CompilationStateImpl::SetNumberOfFunctionsToCompile(int num_functions) {
1487
1498
}
1488
1499
1489
1500
void CompilationStateImpl::AddCallback (CompilationState::callback_t callback) {
1501
+ base::MutexGuard callbacks_guard (&callbacks_mutex_);
1490
1502
callbacks_.emplace_back (std::move (callback));
1491
1503
}
1492
1504
@@ -1536,7 +1548,7 @@ CompilationStateImpl::GetNextCompilationUnit() {
1536
1548
1537
1549
void CompilationStateImpl::OnFinishedUnit (ExecutionTier tier, WasmCode* code) {
1538
1550
// This mutex guarantees that events happen in the right order.
1539
- base::MutexGuard guard (&mutex_ );
1551
+ base::MutexGuard guard (&callbacks_mutex_ );
1540
1552
1541
1553
// If we are *not* compiling in tiering mode, then all units are counted as
1542
1554
// baseline units.
@@ -1547,28 +1559,36 @@ void CompilationStateImpl::OnFinishedUnit(ExecutionTier tier, WasmCode* code) {
1547
1559
// tiering units.
1548
1560
DCHECK_IMPLIES (!is_tiering_mode, outstanding_tiering_units_ == 0 );
1549
1561
1562
+ bool baseline_finished = false ;
1563
+ bool tiering_finished = false ;
1550
1564
if (is_tiering_unit) {
1551
1565
DCHECK_LT (0 , outstanding_tiering_units_);
1552
1566
--outstanding_tiering_units_;
1553
- if (outstanding_tiering_units_ == 0 ) {
1554
- // If baseline compilation has not finished yet, then also trigger
1555
- // {kFinishedBaselineCompilation}.
1556
- if (outstanding_baseline_units_ > 0 ) {
1557
- NotifyOnEvent (CompilationEvent::kFinishedBaselineCompilation );
1558
- }
1559
- NotifyOnEvent (CompilationEvent::kFinishedTopTierCompilation );
1560
- }
1567
+ tiering_finished = outstanding_tiering_units_ == 0 ;
1568
+ // If baseline compilation has not finished yet, then also trigger
1569
+ // {kFinishedBaselineCompilation}.
1570
+ baseline_finished = tiering_finished && outstanding_baseline_units_ > 0 ;
1561
1571
} else {
1562
1572
DCHECK_LT (0 , outstanding_baseline_units_);
1563
1573
--outstanding_baseline_units_;
1564
- if (outstanding_baseline_units_ == 0 ) {
1565
- NotifyOnEvent (CompilationEvent::kFinishedBaselineCompilation );
1566
- // If we are not tiering, then we also trigger the "top tier finished"
1567
- // event when baseline compilation is finished.
1568
- if (!is_tiering_mode) {
1569
- NotifyOnEvent (CompilationEvent::kFinishedTopTierCompilation );
1570
- }
1571
- }
1574
+ // If we are in tiering mode and tiering finished before, then do not
1575
+ // trigger baseline finished.
1576
+ baseline_finished = outstanding_baseline_units_ == 0 &&
1577
+ (!is_tiering_mode || outstanding_tiering_units_ > 0 );
1578
+ // If we are not tiering, then we also trigger the "top tier finished"
1579
+ // event when baseline compilation is finished.
1580
+ tiering_finished = baseline_finished && !is_tiering_mode;
1581
+ }
1582
+
1583
+ if (baseline_finished) {
1584
+ for (auto & callback : callbacks_)
1585
+ callback (CompilationEvent::kFinishedBaselineCompilation );
1586
+ }
1587
+ if (tiering_finished) {
1588
+ for (auto & callback : callbacks_)
1589
+ callback (CompilationEvent::kFinishedTopTierCompilation );
1590
+ // Clear the callbacks because no more events will be delivered.
1591
+ callbacks_.clear ();
1572
1592
}
1573
1593
1574
1594
if (code != nullptr ) native_module_->engine ()->LogCode (code);
@@ -1648,17 +1668,12 @@ void CompilationStateImpl::SetError(uint32_t func_index,
1648
1668
if (!set) return ;
1649
1669
// If set successfully, give up ownership.
1650
1670
compile_error.release ();
1651
- // Schedule a foreground task to call the callback and notify users about the
1652
- // compile error.
1653
- NotifyOnEvent (CompilationEvent::kFailedCompilation );
1654
- }
1655
-
1656
- void CompilationStateImpl::NotifyOnEvent (CompilationEvent event) {
1657
- for (auto & callback : callbacks_) callback (event);
1658
- // If no more events are expected after this one, clear the callbacks to free
1659
- // memory. We can safely do this here, as this method is only called from
1660
- // foreground tasks.
1661
- if (event >= CompilationEvent::kFirstFinalEvent ) callbacks_.clear ();
1671
+ base::MutexGuard callbacks_guard (&callbacks_mutex_);
1672
+ for (auto & callback : callbacks_) {
1673
+ callback (CompilationEvent::kFailedCompilation );
1674
+ }
1675
+ // No more callbacks after an error.
1676
+ callbacks_.clear ();
1662
1677
}
1663
1678
1664
1679
void CompileJsToWasmWrappers (Isolate* isolate, const WasmModule* module,
0 commit comments