@@ -52,7 +52,7 @@ use crate::{
52
52
AggregatedDataUpdate , AggregationUpdateJob , AggregationUpdateQueue ,
53
53
CleanupOldEdgesOperation , ConnectChildOperation , ExecuteContext , ExecuteContextImpl ,
54
54
Operation , OutdatedEdge , TaskGuard , connect_children, get_aggregation_number,
55
- get_uppers, is_root_node, prepare_new_children,
55
+ get_uppers, is_root_node, make_task_dirty_internal , prepare_new_children,
56
56
} ,
57
57
storage:: {
58
58
InnerStorageSnapshot , Storage , count, get, get_many, get_mut, get_mut_or_insert_with,
@@ -420,6 +420,8 @@ struct TaskExecutionCompletePrepareResult {
420
420
pub new_children : FxHashSet < TaskId > ,
421
421
pub removed_data : Vec < CachedDataItem > ,
422
422
pub is_now_immutable : bool ,
423
+ pub new_output : Option < OutputValue > ,
424
+ pub output_dependent_tasks : SmallVec < [ TaskId ; 4 ] > ,
423
425
}
424
426
425
427
// Operations
@@ -493,16 +495,8 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
493
495
Some ( Ok ( Err ( listen_to_done_event ( this, reader, done_event) ) ) )
494
496
}
495
497
Some ( InProgressState :: InProgress ( box InProgressStateInner {
496
- done,
497
- done_event,
498
- ..
499
- } ) ) => {
500
- if !* done {
501
- Some ( Ok ( Err ( listen_to_done_event ( this, reader, done_event) ) ) )
502
- } else {
503
- None
504
- }
505
- }
498
+ done_event, ..
499
+ } ) ) => Some ( Ok ( Err ( listen_to_done_event ( this, reader, done_event) ) ) ) ,
506
500
Some ( InProgressState :: Canceled ) => Some ( Err ( anyhow:: anyhow!(
507
501
"{} was canceled" ,
508
502
ctx. get_task_description( task. id( ) )
@@ -1596,7 +1590,6 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
1596
1590
done_event,
1597
1591
session_dependent : false ,
1598
1592
marked_as_completed : false ,
1599
- done : false ,
1600
1593
new_children : Default :: default ( ) ,
1601
1594
} ) ) ,
1602
1595
} ) ;
@@ -1695,20 +1688,12 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
1695
1688
Some ( TaskExecutionSpec { future, span } )
1696
1689
}
1697
1690
1698
- fn task_execution_result (
1699
- & self ,
1700
- task_id : TaskId ,
1701
- result : Result < RawVc , TurboTasksExecutionError > ,
1702
- turbo_tasks : & dyn TurboTasksBackendApi < TurboTasksBackend < B > > ,
1703
- ) {
1704
- operation:: UpdateOutputOperation :: run ( task_id, result, self . execute_context ( turbo_tasks) ) ;
1705
- }
1706
-
1707
1691
fn task_execution_completed (
1708
1692
& self ,
1709
1693
task_id : TaskId ,
1710
1694
duration : Duration ,
1711
1695
_memory_usage : usize ,
1696
+ result : Result < RawVc , TurboTasksExecutionError > ,
1712
1697
cell_counters : & AutoMap < ValueTypeId , u32 , BuildHasherDefault < FxHasher > , 8 > ,
1713
1698
stateful : bool ,
1714
1699
has_invalidator : bool ,
@@ -1737,10 +1722,13 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
1737
1722
new_children,
1738
1723
mut removed_data,
1739
1724
is_now_immutable,
1725
+ new_output,
1726
+ output_dependent_tasks,
1740
1727
} ) = self . task_execution_completed_prepare (
1741
1728
& mut ctx,
1742
1729
& span,
1743
1730
task_id,
1731
+ result,
1744
1732
cell_counters,
1745
1733
stateful,
1746
1734
has_invalidator,
@@ -1754,7 +1742,20 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
1754
1742
// suspend in `CleanupOldEdgesOperation`), but that's ok as the task is still dirty and
1755
1743
// would be executed again.
1756
1744
1745
+ if !output_dependent_tasks. is_empty ( ) {
1746
+ self . task_execution_completed_invalidate_output_dependent (
1747
+ & mut ctx,
1748
+ task_id,
1749
+ output_dependent_tasks,
1750
+ ) ;
1751
+ }
1752
+
1757
1753
let has_new_children = !new_children. is_empty ( ) ;
1754
+
1755
+ if has_new_children {
1756
+ self . task_execution_completed_unfinished_children_dirty ( & mut ctx, & new_children)
1757
+ }
1758
+
1758
1759
if has_new_children
1759
1760
&& self . task_execution_completed_connect ( & mut ctx, task_id, new_children)
1760
1761
{
@@ -1765,6 +1766,7 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
1765
1766
if self . task_execution_completed_finish (
1766
1767
& mut ctx,
1767
1768
task_id,
1769
+ new_output,
1768
1770
& mut removed_data,
1769
1771
is_now_immutable,
1770
1772
) {
@@ -1784,6 +1786,7 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
1784
1786
ctx : & mut impl ExecuteContext < ' _ > ,
1785
1787
span : & Span ,
1786
1788
task_id : TaskId ,
1789
+ result : Result < RawVc , TurboTasksExecutionError > ,
1787
1790
cell_counters : & AutoMap < ValueTypeId , u32 , BuildHasherDefault < FxHasher > , 8 > ,
1788
1791
stateful : bool ,
1789
1792
has_invalidator : bool ,
@@ -1797,12 +1800,12 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
1797
1800
new_children : Default :: default ( ) ,
1798
1801
removed_data : Default :: default ( ) ,
1799
1802
is_now_immutable : false ,
1803
+ new_output : None ,
1804
+ output_dependent_tasks : Default :: default ( ) ,
1800
1805
} ) ;
1801
1806
}
1802
1807
let & mut InProgressState :: InProgress ( box InProgressStateInner {
1803
1808
stale,
1804
- ref mut done,
1805
- ref done_event,
1806
1809
ref mut new_children,
1807
1810
session_dependent,
1808
1811
..
@@ -1846,12 +1849,6 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
1846
1849
return None ;
1847
1850
}
1848
1851
1849
- if cfg ! ( not( feature = "no_fast_stale" ) ) || !stale {
1850
- // mark the task as completed, so dependent tasks can continue working
1851
- * done = true ;
1852
- done_event. notify ( usize:: MAX ) ;
1853
- }
1854
-
1855
1852
// take the children from the task to process them
1856
1853
let mut new_children = take ( new_children) ;
1857
1854
@@ -1979,6 +1976,53 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
1979
1976
) ;
1980
1977
}
1981
1978
1979
+ // Check if output need to be updated
1980
+ let current_output = get ! ( task, Output ) ;
1981
+ let new_output = match result {
1982
+ Ok ( RawVc :: TaskOutput ( output_task_id) ) => {
1983
+ if let Some ( OutputValue :: Output ( current_task_id) ) = current_output
1984
+ && * current_task_id == output_task_id
1985
+ {
1986
+ None
1987
+ } else {
1988
+ Some ( OutputValue :: Output ( output_task_id) )
1989
+ }
1990
+ }
1991
+ Ok ( RawVc :: TaskCell ( output_task_id, cell) ) => {
1992
+ if let Some ( OutputValue :: Cell ( CellRef {
1993
+ task : current_task_id,
1994
+ cell : current_cell,
1995
+ } ) ) = current_output
1996
+ && * current_task_id == output_task_id
1997
+ && * current_cell == cell
1998
+ {
1999
+ None
2000
+ } else {
2001
+ Some ( OutputValue :: Cell ( CellRef {
2002
+ task : output_task_id,
2003
+ cell,
2004
+ } ) )
2005
+ }
2006
+ }
2007
+ Ok ( RawVc :: LocalOutput ( ..) ) => {
2008
+ panic ! ( "Non-local tasks must not return a local Vc" ) ;
2009
+ }
2010
+ Err ( err) => {
2011
+ if let Some ( OutputValue :: Error ( old_error) ) = current_output
2012
+ && old_error == & err
2013
+ {
2014
+ None
2015
+ } else {
2016
+ Some ( OutputValue :: Error ( err) )
2017
+ }
2018
+ }
2019
+ } ;
2020
+ let mut output_dependent_tasks = SmallVec :: < [ _ ; 4 ] > :: new ( ) ;
2021
+ // When output has changed, grab the dependent tasks
2022
+ if new_output. is_some ( ) && ctx. should_track_dependencies ( ) {
2023
+ output_dependent_tasks = get_many ! ( task, OutputDependent { task } => task) ;
2024
+ }
2025
+
1982
2026
drop ( task) ;
1983
2027
1984
2028
// Check if the task can be marked as immutable
@@ -2005,9 +2049,76 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
2005
2049
new_children,
2006
2050
removed_data,
2007
2051
is_now_immutable,
2052
+ new_output,
2053
+ output_dependent_tasks,
2008
2054
} )
2009
2055
}
2010
2056
2057
+ fn task_execution_completed_invalidate_output_dependent (
2058
+ & self ,
2059
+ ctx : & mut impl ExecuteContext < ' _ > ,
2060
+ task_id : TaskId ,
2061
+ output_dependent_tasks : SmallVec < [ TaskId ; 4 ] > ,
2062
+ ) {
2063
+ debug_assert ! ( !output_dependent_tasks. is_empty( ) ) ;
2064
+
2065
+ let mut queue = AggregationUpdateQueue :: new ( ) ;
2066
+ for dependent_task_id in output_dependent_tasks {
2067
+ if ctx. is_once_task ( dependent_task_id) {
2068
+ // once tasks are never invalidated
2069
+ continue ;
2070
+ }
2071
+ let dependent = ctx. task ( dependent_task_id, TaskDataCategory :: All ) ;
2072
+ if dependent. has_key ( & CachedDataItemKey :: OutdatedOutputDependency { target : task_id } ) {
2073
+ // output dependency is outdated, so it hasn't read the output yet
2074
+ // and doesn't need to be invalidated
2075
+ continue ;
2076
+ }
2077
+ if !dependent. has_key ( & CachedDataItemKey :: OutputDependency { target : task_id } ) {
2078
+ // output dependency has been removed, so the task doesn't depend on the
2079
+ // output anymore and doesn't need to be invalidated
2080
+ continue ;
2081
+ }
2082
+ make_task_dirty_internal (
2083
+ dependent,
2084
+ dependent_task_id,
2085
+ true ,
2086
+ #[ cfg( feature = "trace_task_dirty" ) ]
2087
+ TaskDirtyCause :: OutputChange { task_id } ,
2088
+ & mut queue,
2089
+ ctx,
2090
+ ) ;
2091
+ }
2092
+
2093
+ queue. execute ( ctx) ;
2094
+ }
2095
+
2096
+ fn task_execution_completed_unfinished_children_dirty (
2097
+ & self ,
2098
+ ctx : & mut impl ExecuteContext < ' _ > ,
2099
+ new_children : & FxHashSet < TaskId > ,
2100
+ ) {
2101
+ debug_assert ! ( !new_children. is_empty( ) ) ;
2102
+
2103
+ let mut queue = AggregationUpdateQueue :: new ( ) ;
2104
+ for & child_id in new_children {
2105
+ let child_task = ctx. task ( child_id, TaskDataCategory :: Meta ) ;
2106
+ if !child_task. has_key ( & CachedDataItemKey :: Output { } ) {
2107
+ make_task_dirty_internal (
2108
+ child_task,
2109
+ child_id,
2110
+ false ,
2111
+ #[ cfg( feature = "trace_task_dirty" ) ]
2112
+ TaskDirtyCause :: InitialDirty ,
2113
+ & mut queue,
2114
+ ctx,
2115
+ ) ;
2116
+ }
2117
+ }
2118
+
2119
+ queue. execute ( ctx) ;
2120
+ }
2121
+
2011
2122
fn task_execution_completed_connect (
2012
2123
& self ,
2013
2124
ctx : & mut impl ExecuteContext < ' _ > ,
@@ -2078,6 +2189,7 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
2078
2189
& self ,
2079
2190
ctx : & mut impl ExecuteContext < ' _ > ,
2080
2191
task_id : TaskId ,
2192
+ new_output : Option < OutputValue > ,
2081
2193
removed_data : & mut Vec < CachedDataItem > ,
2082
2194
is_now_immutable : bool ,
2083
2195
) -> bool {
@@ -2094,7 +2206,6 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
2094
2206
once_task : _,
2095
2207
stale,
2096
2208
session_dependent,
2097
- done : _,
2098
2209
marked_as_completed : _,
2099
2210
new_children,
2100
2211
} ) = in_progress
@@ -2114,6 +2225,12 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
2114
2225
return true ;
2115
2226
}
2116
2227
2228
+ // Set the output if it has changed
2229
+ let mut old_content = None ;
2230
+ if let Some ( value) = new_output {
2231
+ old_content = task. insert ( CachedDataItem :: Output { value } ) ;
2232
+ }
2233
+
2117
2234
// If the task is not stateful and has no mutable children, it does not have a way to be
2118
2235
// invalidated and we can mark it as immutable.
2119
2236
if is_now_immutable {
@@ -2194,6 +2311,10 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
2194
2311
} ;
2195
2312
2196
2313
drop ( task) ;
2314
+ drop ( old_content) ;
2315
+
2316
+ // Notify dependent tasks that are waiting for this task to finish
2317
+ done_event. notify ( usize:: MAX ) ;
2197
2318
2198
2319
if let Some ( data_update) = data_update {
2199
2320
AggregationUpdateQueue :: run ( data_update, ctx) ;
@@ -2981,20 +3102,12 @@ impl<B: BackingStorage> Backend for TurboTasksBackend<B> {
2981
3102
self . 0 . try_start_task_execution ( task_id, turbo_tasks)
2982
3103
}
2983
3104
2984
- fn task_execution_result (
2985
- & self ,
2986
- task_id : TaskId ,
2987
- result : Result < RawVc , TurboTasksExecutionError > ,
2988
- turbo_tasks : & dyn TurboTasksBackendApi < Self > ,
2989
- ) {
2990
- self . 0 . task_execution_result ( task_id, result, turbo_tasks) ;
2991
- }
2992
-
2993
3105
fn task_execution_completed (
2994
3106
& self ,
2995
3107
task_id : TaskId ,
2996
3108
_duration : Duration ,
2997
3109
_memory_usage : usize ,
3110
+ result : Result < RawVc , TurboTasksExecutionError > ,
2998
3111
cell_counters : & AutoMap < ValueTypeId , u32 , BuildHasherDefault < FxHasher > , 8 > ,
2999
3112
stateful : bool ,
3000
3113
has_invalidator : bool ,
@@ -3004,6 +3117,7 @@ impl<B: BackingStorage> Backend for TurboTasksBackend<B> {
3004
3117
task_id,
3005
3118
_duration,
3006
3119
_memory_usage,
3120
+ result,
3007
3121
cell_counters,
3008
3122
stateful,
3009
3123
has_invalidator,
0 commit comments