@@ -1826,7 +1826,8 @@ void CompileNativeModule(Isolate* isolate,
18261826class BaseCompileJSToWasmWrapperJob : public JobTask {
18271827 public:
18281828 explicit BaseCompileJSToWasmWrapperJob (size_t compilation_units)
1829- : outstanding_units_(compilation_units) {}
1829+ : outstanding_units_(compilation_units),
1830+ total_units_(compilation_units) {}
18301831
18311832 size_t GetMaxConcurrency (size_t worker_count) const override {
18321833 size_t flag_limit = static_cast <size_t >(
@@ -1839,12 +1840,20 @@ class BaseCompileJSToWasmWrapperJob : public JobTask {
18391840 }
18401841
18411842 protected:
1842- // Returns the index of the next unit to process.
1843- size_t GetNextUnitIndex () {
1844- // |unit_index_| may exceeed |compilation_units|, but only by the number of
1845- // workers at worst, thus it can't exceed 2 * |compilation_units| and
1846- // overflow shouldn't happen.
1847- return unit_index_.fetch_add (1 , std::memory_order_relaxed);
1843+ // Returns {true} and places the index of the next unit to process in
1844+ // {index_out} if there are still units to be processed. Returns {false}
1845+ // otherwise.
1846+ bool GetNextUnitIndex (size_t * index_out) {
1847+ size_t next_index = unit_index_.fetch_add (1 , std::memory_order_relaxed);
1848+ if (next_index >= total_units_) {
1849+ // {unit_index_} may exceeed {total_units_}, but only by the number of
1850+ // workers at worst, thus it can't exceed 2 * {total_units_} and overflow
1851+ // shouldn't happen.
1852+ DCHECK_GE (2 * total_units_, next_index);
1853+ return false ;
1854+ }
1855+ *index_out = next_index;
1856+ return true ;
18481857 }
18491858
18501859 // Returns true if the last unit was completed.
@@ -1855,9 +1864,29 @@ class BaseCompileJSToWasmWrapperJob : public JobTask {
18551864 return outstanding_units == 1 ;
18561865 }
18571866
1867+ // When external cancellation is detected, call this method to bump
1868+ // {unit_index_} and reset {outstanding_units_} such that no more tasks are
1869+ // being scheduled for this job and all tasks exit as soon as possible.
1870+ void FlushRemainingUnits () {
1871+ // After being cancelled, make sure to reduce outstanding_units_ to
1872+ // *basically* zero, but leave the count positive if other workers are still
1873+ // running, to avoid underflow in {CompleteUnit}.
1874+ size_t next_undone_unit =
1875+ unit_index_.exchange (total_units_, std::memory_order_relaxed);
1876+ size_t undone_units =
1877+ next_undone_unit >= total_units_ ? 0 : total_units_ - next_undone_unit;
1878+ // Note that the caller requested one unit that we also still need to remove
1879+ // from {outstanding_units_}.
1880+ ++undone_units;
1881+ size_t previous_outstanding_units =
1882+ outstanding_units_.fetch_sub (undone_units, std::memory_order_relaxed);
1883+ CHECK_LE (undone_units, previous_outstanding_units);
1884+ }
1885+
18581886 private:
18591887 std::atomic<size_t > unit_index_{0 };
18601888 std::atomic<size_t > outstanding_units_;
1889+ const size_t total_units_;
18611890};
18621891
18631892class AsyncCompileJSToWasmWrapperJob final
@@ -1867,8 +1896,7 @@ class AsyncCompileJSToWasmWrapperJob final
18671896 std::weak_ptr<NativeModule> native_module, size_t compilation_units)
18681897 : BaseCompileJSToWasmWrapperJob(compilation_units),
18691898 native_module_(std::move(native_module)),
1870- engine_barrier_(GetWasmEngine()->GetBarrierForBackgroundCompile()),
1871- compilation_units_size_(compilation_units) {}
1899+ engine_barrier_(GetWasmEngine()->GetBarrierForBackgroundCompile()) {}
18721900
18731901 void Run (JobDelegate* delegate) override {
18741902 auto engine_scope = engine_barrier_->TryLock ();
@@ -1878,18 +1906,18 @@ class AsyncCompileJSToWasmWrapperJob final
18781906 OperationsBarrier::Token wrapper_compilation_token;
18791907 Isolate* isolate;
18801908
1881- size_t index = GetNextUnitIndex () ;
1882- if (index >= compilation_units_size_ ) return ;
1909+ size_t index;
1910+ if (! GetNextUnitIndex (& index) ) return ;
18831911 {
18841912 BackgroundCompileScope compile_scope (native_module_);
1885- if (compile_scope.cancelled ()) return ;
1913+ if (compile_scope.cancelled ()) return FlushRemainingUnits () ;
18861914 wrapper_unit =
18871915 compile_scope.compilation_state ()->GetJSToWasmWrapperCompilationUnit (
18881916 index);
18891917 isolate = wrapper_unit->isolate ();
18901918 wrapper_compilation_token =
18911919 wasm::GetWasmEngine ()->StartWrapperCompilation (isolate);
1892- if (!wrapper_compilation_token) return ;
1920+ if (!wrapper_compilation_token) return FlushRemainingUnits () ;
18931921 }
18941922
18951923 TRACE_EVENT0 (" v8.wasm" , " wasm.JSToWasmWrapperCompilation" );
@@ -1902,11 +1930,11 @@ class AsyncCompileJSToWasmWrapperJob final
19021930
19031931 BackgroundCompileScope compile_scope (native_module_);
19041932 if (compile_scope.cancelled ()) return ;
1905- if (complete_last_unit)
1933+ if (complete_last_unit) {
19061934 compile_scope.compilation_state ()->OnFinishedJSToWasmWrapperUnits ();
1935+ }
19071936 if (yield) return ;
1908- size_t index = GetNextUnitIndex ();
1909- if (index >= compilation_units_size_) return ;
1937+ if (!GetNextUnitIndex (&index)) return ;
19101938 wrapper_unit =
19111939 compile_scope.compilation_state ()->GetJSToWasmWrapperCompilationUnit (
19121940 index);
@@ -1916,8 +1944,6 @@ class AsyncCompileJSToWasmWrapperJob final
19161944 private:
19171945 std::weak_ptr<NativeModule> native_module_;
19181946 std::shared_ptr<OperationsBarrier> engine_barrier_;
1919- // Number of wrappers to be compiled.
1920- const size_t compilation_units_size_;
19211947};
19221948
19231949class BackgroundCompileJob final : public JobTask {
@@ -3723,8 +3749,9 @@ void CompilationStateImpl::WaitForCompilationEvent(
37233749 // Waiting on other CompilationEvent doesn't make sense.
37243750 UNREACHABLE ();
37253751 }
3726- if (js_to_wasm_wrapper_job_ && js_to_wasm_wrapper_job_->IsValid ())
3752+ if (js_to_wasm_wrapper_job_ && js_to_wasm_wrapper_job_->IsValid ()) {
37273753 js_to_wasm_wrapper_job_->Join ();
3754+ }
37283755#ifdef DEBUG
37293756 base::EnumSet<CompilationEvent> events{expect_event,
37303757 CompilationEvent::kFailedCompilation };
@@ -3786,9 +3813,8 @@ class CompileJSToWasmWrapperJob final : public BaseCompileJSToWasmWrapperJob {
37863813 compilation_units_(compilation_units) {}
37873814
37883815 void Run (JobDelegate* delegate) override {
3789- while (true ) {
3790- size_t index = GetNextUnitIndex ();
3791- if (index >= compilation_units_->size ()) return ;
3816+ size_t index;
3817+ while (GetNextUnitIndex (&index)) {
37923818 JSToWasmWrapperCompilationUnit* unit =
37933819 (*compilation_units_)[index].second .get ();
37943820 unit->Execute ();
0 commit comments