@@ -1827,7 +1827,8 @@ void CompileNativeModule(Isolate* isolate,
18271827class BaseCompileJSToWasmWrapperJob : public JobTask {
18281828 public:
18291829 explicit BaseCompileJSToWasmWrapperJob (size_t compilation_units)
1830- : outstanding_units_(compilation_units) {}
1830+ : outstanding_units_(compilation_units),
1831+ total_units_(compilation_units) {}
18311832
18321833 size_t GetMaxConcurrency (size_t worker_count) const override {
18331834 size_t flag_limit = static_cast <size_t >(
@@ -1840,12 +1841,20 @@ class BaseCompileJSToWasmWrapperJob : public JobTask {
18401841 }
18411842
18421843 protected:
1843- // Returns the index of the next unit to process.
1844- size_t GetNextUnitIndex () {
1845- // |unit_index_| may exceeed |compilation_units|, but only by the number of
1846- // workers at worst, thus it can't exceed 2 * |compilation_units| and
1847- // overflow shouldn't happen.
1848- return unit_index_.fetch_add (1 , std::memory_order_relaxed);
1844+ // Returns {true} and places the index of the next unit to process in
1845+ // {index_out} if there are still units to be processed. Returns {false}
1846+ // otherwise.
1847+ bool GetNextUnitIndex (size_t * index_out) {
1848+ size_t next_index = unit_index_.fetch_add (1 , std::memory_order_relaxed);
1849+ if (next_index >= total_units_) {
1850+ // {unit_index_} may exceeed {total_units_}, but only by the number of
1851+ // workers at worst, thus it can't exceed 2 * {total_units_} and overflow
1852+ // shouldn't happen.
1853+ DCHECK_GE (2 * total_units_, next_index);
1854+ return false ;
1855+ }
1856+ *index_out = next_index;
1857+ return true ;
18491858 }
18501859
18511860 // Returns true if the last unit was completed.
@@ -1856,9 +1865,29 @@ class BaseCompileJSToWasmWrapperJob : public JobTask {
18561865 return outstanding_units == 1 ;
18571866 }
18581867
1868+ // When external cancellation is detected, call this method to bump
1869+ // {unit_index_} and reset {outstanding_units_} such that no more tasks are
1870+ // being scheduled for this job and all tasks exit as soon as possible.
1871+ void FlushRemainingUnits () {
1872+ // After being cancelled, make sure to reduce outstanding_units_ to
1873+ // *basically* zero, but leave the count positive if other workers are still
1874+ // running, to avoid underflow in {CompleteUnit}.
1875+ size_t next_undone_unit =
1876+ unit_index_.exchange (total_units_, std::memory_order_relaxed);
1877+ size_t undone_units =
1878+ next_undone_unit >= total_units_ ? 0 : total_units_ - next_undone_unit;
1879+ // Note that the caller requested one unit that we also still need to remove
1880+ // from {outstanding_units_}.
1881+ ++undone_units;
1882+ size_t previous_outstanding_units =
1883+ outstanding_units_.fetch_sub (undone_units, std::memory_order_relaxed);
1884+ CHECK_LE (undone_units, previous_outstanding_units);
1885+ }
1886+
18591887 private:
18601888 std::atomic<size_t > unit_index_{0 };
18611889 std::atomic<size_t > outstanding_units_;
1890+ const size_t total_units_;
18621891};
18631892
18641893class AsyncCompileJSToWasmWrapperJob final
@@ -1868,8 +1897,7 @@ class AsyncCompileJSToWasmWrapperJob final
18681897 std::weak_ptr<NativeModule> native_module, size_t compilation_units)
18691898 : BaseCompileJSToWasmWrapperJob(compilation_units),
18701899 native_module_(std::move(native_module)),
1871- engine_barrier_(GetWasmEngine()->GetBarrierForBackgroundCompile()),
1872- compilation_units_size_(compilation_units) {}
1900+ engine_barrier_(GetWasmEngine()->GetBarrierForBackgroundCompile()) {}
18731901
18741902 void Run (JobDelegate* delegate) override {
18751903 auto engine_scope = engine_barrier_->TryLock ();
@@ -1879,18 +1907,18 @@ class AsyncCompileJSToWasmWrapperJob final
18791907 OperationsBarrier::Token wrapper_compilation_token;
18801908 Isolate* isolate;
18811909
1882- size_t index = GetNextUnitIndex () ;
1883- if (index >= compilation_units_size_ ) return ;
1910+ size_t index;
1911+ if (! GetNextUnitIndex (& index) ) return ;
18841912 {
18851913 BackgroundCompileScope compile_scope (native_module_);
1886- if (compile_scope.cancelled ()) return ;
1914+ if (compile_scope.cancelled ()) return FlushRemainingUnits () ;
18871915 wrapper_unit =
18881916 compile_scope.compilation_state ()->GetJSToWasmWrapperCompilationUnit (
18891917 index);
18901918 isolate = wrapper_unit->isolate ();
18911919 wrapper_compilation_token =
18921920 wasm::GetWasmEngine ()->StartWrapperCompilation (isolate);
1893- if (!wrapper_compilation_token) return ;
1921+ if (!wrapper_compilation_token) return FlushRemainingUnits () ;
18941922 }
18951923
18961924 TRACE_EVENT0 (" v8.wasm" , " wasm.JSToWasmWrapperCompilation" );
@@ -1903,11 +1931,11 @@ class AsyncCompileJSToWasmWrapperJob final
19031931
19041932 BackgroundCompileScope compile_scope (native_module_);
19051933 if (compile_scope.cancelled ()) return ;
1906- if (complete_last_unit)
1934+ if (complete_last_unit) {
19071935 compile_scope.compilation_state ()->OnFinishedJSToWasmWrapperUnits ();
1936+ }
19081937 if (yield) return ;
1909- size_t index = GetNextUnitIndex ();
1910- if (index >= compilation_units_size_) return ;
1938+ if (!GetNextUnitIndex (&index)) return ;
19111939 wrapper_unit =
19121940 compile_scope.compilation_state ()->GetJSToWasmWrapperCompilationUnit (
19131941 index);
@@ -1917,8 +1945,6 @@ class AsyncCompileJSToWasmWrapperJob final
19171945 private:
19181946 std::weak_ptr<NativeModule> native_module_;
19191947 std::shared_ptr<OperationsBarrier> engine_barrier_;
1920- // Number of wrappers to be compiled.
1921- const size_t compilation_units_size_;
19221948};
19231949
19241950class BackgroundCompileJob final : public JobTask {
@@ -3726,8 +3752,9 @@ void CompilationStateImpl::WaitForCompilationEvent(
37263752 // Waiting on other CompilationEvent doesn't make sense.
37273753 UNREACHABLE ();
37283754 }
3729- if (js_to_wasm_wrapper_job_ && js_to_wasm_wrapper_job_->IsValid ())
3755+ if (js_to_wasm_wrapper_job_ && js_to_wasm_wrapper_job_->IsValid ()) {
37303756 js_to_wasm_wrapper_job_->Join ();
3757+ }
37313758#ifdef DEBUG
37323759 base::EnumSet<CompilationEvent> events{expect_event,
37333760 CompilationEvent::kFailedCompilation };
@@ -3789,9 +3816,8 @@ class CompileJSToWasmWrapperJob final : public BaseCompileJSToWasmWrapperJob {
37893816 compilation_units_(compilation_units) {}
37903817
37913818 void Run (JobDelegate* delegate) override {
3792- while (true ) {
3793- size_t index = GetNextUnitIndex ();
3794- if (index >= compilation_units_->size ()) return ;
3819+ size_t index;
3820+ while (GetNextUnitIndex (&index)) {
37953821 JSToWasmWrapperCompilationUnit* unit =
37963822 (*compilation_units_)[index].second .get ();
37973823 unit->Execute ();
0 commit comments