@@ -1826,7 +1826,8 @@ void CompileNativeModule(Isolate* isolate,
1826
1826
class BaseCompileJSToWasmWrapperJob : public JobTask {
1827
1827
public:
1828
1828
explicit BaseCompileJSToWasmWrapperJob (size_t compilation_units)
1829
- : outstanding_units_(compilation_units) {}
1829
+ : outstanding_units_(compilation_units),
1830
+ total_units_(compilation_units) {}
1830
1831
1831
1832
size_t GetMaxConcurrency (size_t worker_count) const override {
1832
1833
size_t flag_limit = static_cast <size_t >(
@@ -1839,12 +1840,20 @@ class BaseCompileJSToWasmWrapperJob : public JobTask {
1839
1840
}
1840
1841
1841
1842
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 ;
1848
1857
}
1849
1858
1850
1859
// Returns true if the last unit was completed.
@@ -1855,9 +1864,29 @@ class BaseCompileJSToWasmWrapperJob : public JobTask {
1855
1864
return outstanding_units == 1 ;
1856
1865
}
1857
1866
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
+
1858
1886
private:
1859
1887
std::atomic<size_t > unit_index_{0 };
1860
1888
std::atomic<size_t > outstanding_units_;
1889
+ const size_t total_units_;
1861
1890
};
1862
1891
1863
1892
class AsyncCompileJSToWasmWrapperJob final
@@ -1867,8 +1896,7 @@ class AsyncCompileJSToWasmWrapperJob final
1867
1896
std::weak_ptr<NativeModule> native_module, size_t compilation_units)
1868
1897
: BaseCompileJSToWasmWrapperJob(compilation_units),
1869
1898
native_module_(std::move(native_module)),
1870
- engine_barrier_(GetWasmEngine()->GetBarrierForBackgroundCompile()),
1871
- compilation_units_size_(compilation_units) {}
1899
+ engine_barrier_(GetWasmEngine()->GetBarrierForBackgroundCompile()) {}
1872
1900
1873
1901
void Run (JobDelegate* delegate) override {
1874
1902
auto engine_scope = engine_barrier_->TryLock ();
@@ -1878,18 +1906,18 @@ class AsyncCompileJSToWasmWrapperJob final
1878
1906
OperationsBarrier::Token wrapper_compilation_token;
1879
1907
Isolate* isolate;
1880
1908
1881
- size_t index = GetNextUnitIndex () ;
1882
- if (index >= compilation_units_size_ ) return ;
1909
+ size_t index ;
1910
+ if (! GetNextUnitIndex (& index ) ) return ;
1883
1911
{
1884
1912
BackgroundCompileScope compile_scope (native_module_);
1885
- if (compile_scope.cancelled ()) return ;
1913
+ if (compile_scope.cancelled ()) return FlushRemainingUnits () ;
1886
1914
wrapper_unit =
1887
1915
compile_scope.compilation_state ()->GetJSToWasmWrapperCompilationUnit (
1888
1916
index );
1889
1917
isolate = wrapper_unit->isolate ();
1890
1918
wrapper_compilation_token =
1891
1919
wasm::GetWasmEngine ()->StartWrapperCompilation (isolate);
1892
- if (!wrapper_compilation_token) return ;
1920
+ if (!wrapper_compilation_token) return FlushRemainingUnits () ;
1893
1921
}
1894
1922
1895
1923
TRACE_EVENT0 (" v8.wasm" , " wasm.JSToWasmWrapperCompilation" );
@@ -1902,11 +1930,11 @@ class AsyncCompileJSToWasmWrapperJob final
1902
1930
1903
1931
BackgroundCompileScope compile_scope (native_module_);
1904
1932
if (compile_scope.cancelled ()) return ;
1905
- if (complete_last_unit)
1933
+ if (complete_last_unit) {
1906
1934
compile_scope.compilation_state ()->OnFinishedJSToWasmWrapperUnits ();
1935
+ }
1907
1936
if (yield) return ;
1908
- size_t index = GetNextUnitIndex ();
1909
- if (index >= compilation_units_size_) return ;
1937
+ if (!GetNextUnitIndex (&index )) return ;
1910
1938
wrapper_unit =
1911
1939
compile_scope.compilation_state ()->GetJSToWasmWrapperCompilationUnit (
1912
1940
index );
@@ -1916,8 +1944,6 @@ class AsyncCompileJSToWasmWrapperJob final
1916
1944
private:
1917
1945
std::weak_ptr<NativeModule> native_module_;
1918
1946
std::shared_ptr<OperationsBarrier> engine_barrier_;
1919
- // Number of wrappers to be compiled.
1920
- const size_t compilation_units_size_;
1921
1947
};
1922
1948
1923
1949
class BackgroundCompileJob final : public JobTask {
@@ -3723,8 +3749,9 @@ void CompilationStateImpl::WaitForCompilationEvent(
3723
3749
// Waiting on other CompilationEvent doesn't make sense.
3724
3750
UNREACHABLE ();
3725
3751
}
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 ()) {
3727
3753
js_to_wasm_wrapper_job_->Join ();
3754
+ }
3728
3755
#ifdef DEBUG
3729
3756
base::EnumSet<CompilationEvent> events{expect_event,
3730
3757
CompilationEvent::kFailedCompilation };
@@ -3786,9 +3813,8 @@ class CompileJSToWasmWrapperJob final : public BaseCompileJSToWasmWrapperJob {
3786
3813
compilation_units_(compilation_units) {}
3787
3814
3788
3815
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 )) {
3792
3818
JSToWasmWrapperCompilationUnit* unit =
3793
3819
(*compilation_units_)[index ].second .get ();
3794
3820
unit->Execute ();
0 commit comments