@@ -48,8 +48,8 @@ use crate::backend::operation::TaskDirtyCause;
4848use crate :: {
4949 backend:: {
5050 operation:: {
51- AggregatedDataUpdate , AggregationUpdateJob , AggregationUpdateQueue ,
52- CleanupOldEdgesOperation , ConnectChildOperation , ExecuteContext , ExecuteContextImpl ,
51+ AggregationUpdateJob , AggregationUpdateQueue , CleanupOldEdgesOperation ,
52+ ComputeDirtyAndCleanUpdate , ConnectChildOperation , ExecuteContext , ExecuteContextImpl ,
5353 Operation , OutdatedEdge , TaskGuard , connect_children, get_aggregation_number,
5454 get_uppers, is_root_node, make_task_dirty_internal, prepare_new_children,
5555 } ,
@@ -560,10 +560,7 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
560560 let is_dirty = task. is_dirty ( self . session_id ) ;
561561
562562 // Check the dirty count of the root node
563- let dirty_tasks = get ! ( task, AggregatedDirtyContainerCount )
564- . cloned ( )
565- . unwrap_or_default ( )
566- . get ( self . session_id ) ;
563+ let dirty_tasks = task. dirty_container_count ( self . session_id ) ;
567564 if dirty_tasks > 0 || is_dirty {
568565 let activeness = get_mut ! ( task, Activeness ) ;
569566 let mut task_ids_to_schedule: Vec < _ > = Vec :: new ( ) ;
@@ -627,10 +624,7 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
627624 } ;
628625
629626 // Check the dirty count of the root node
630- let dirty_tasks = get ! ( task, AggregatedDirtyContainerCount )
631- . cloned ( )
632- . unwrap_or_default ( )
633- . get ( ctx. session_id ( ) ) ;
627+ let dirty_tasks = task. dirty_container_count ( ctx. session_id ( ) ) ;
634628
635629 let task_description = ctx. get_task_description ( task_id) ;
636630 let is_dirty = if is_dirty { ", dirty" } else { "" } ;
@@ -2292,72 +2286,96 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
22922286 } ,
22932287 ) ) ;
22942288
2295- // Update the dirty state
2296- let old_dirtyness = task. dirtyness_and_session ( ) ;
2297-
2298- let new_dirtyness = if session_dependent {
2299- Some ( ( Dirtyness :: SessionDependent , Some ( self . session_id ) ) )
2300- } else {
2301- None
2289+ // Grab the old dirty state
2290+ let old_dirtyness = get ! ( task, Dirty ) . cloned ( ) ;
2291+ let ( was_dirty, was_current_session_clean, old_clean_in_session) = match old_dirtyness {
2292+ None => ( false , false , None ) ,
2293+ Some ( Dirtyness :: Dirty ) => ( true , false , None ) ,
2294+ Some ( Dirtyness :: SessionDependent ) => {
2295+ let clean_in_session = get ! ( task, CleanInSession ) . copied ( ) ;
2296+ (
2297+ true ,
2298+ clean_in_session == Some ( self . session_id ) ,
2299+ clean_in_session,
2300+ )
2301+ }
23022302 } ;
2303+ let old_dirty_value = if was_dirty { 1 } else { 0 } ;
2304+ let old_current_session_clean_value = if was_current_session_clean { 1 } else { 0 } ;
23032305
2304- let dirty_changed = old_dirtyness != new_dirtyness;
2305- let data_update = if dirty_changed {
2306- if let Some ( ( value, _) ) = new_dirtyness {
2306+ // Compute the new dirty state
2307+ let ( new_dirtyness, new_clean_in_session, new_dirty_value, new_current_session_clean_value) =
2308+ if session_dependent {
2309+ (
2310+ Some ( Dirtyness :: SessionDependent ) ,
2311+ Some ( self . session_id ) ,
2312+ 1 ,
2313+ 1 ,
2314+ )
2315+ } else {
2316+ ( None , None , 0 , 0 )
2317+ } ;
2318+
2319+ // Update the dirty state
2320+ if old_dirtyness != new_dirtyness {
2321+ if let Some ( value) = new_dirtyness {
23072322 task. insert ( CachedDataItem :: Dirty { value } ) ;
23082323 } else if old_dirtyness. is_some ( ) {
23092324 task. remove ( & CachedDataItemKey :: Dirty { } ) ;
23102325 }
2311- if let Some ( session_id) = new_dirtyness. and_then ( |t| t. 1 ) {
2326+ }
2327+ if old_clean_in_session != new_clean_in_session {
2328+ if let Some ( session_id) = new_clean_in_session {
23122329 task. insert ( CachedDataItem :: CleanInSession { value : session_id } ) ;
2313- } else if old_dirtyness . is_some_and ( |t| t . 1 . is_some ( ) ) {
2330+ } else if old_clean_in_session . is_some ( ) {
23142331 task. remove ( & CachedDataItemKey :: CleanInSession { } ) ;
23152332 }
2333+ }
23162334
2317- let mut dirty_containers = get ! ( task, AggregatedDirtyContainerCount )
2335+ // Propagate dirtyness changes
2336+ let data_update = if old_dirty_value != new_dirty_value
2337+ || old_current_session_clean_value != new_current_session_clean_value
2338+ {
2339+ let dirty_container_count = get ! ( task, AggregatedDirtyContainerCount )
23182340 . cloned ( )
23192341 . unwrap_or_default ( ) ;
2320- if let Some ( ( old_dirtyness, old_clean_in_session) ) = old_dirtyness {
2321- dirty_containers
2322- . update_with_dirtyness_and_session ( old_dirtyness, old_clean_in_session) ;
2323- }
2324- let aggregated_update = match ( old_dirtyness, new_dirtyness) {
2325- ( None , None ) => unreachable ! ( ) ,
2326- ( Some ( old) , None ) => {
2327- dirty_containers. undo_update_with_dirtyness_and_session ( old. 0 , old. 1 )
2328- }
2329- ( None , Some ( new) ) => {
2330- dirty_containers. update_with_dirtyness_and_session ( new. 0 , new. 1 )
2331- }
2332- ( Some ( old) , Some ( new) ) => {
2333- dirty_containers. replace_dirtyness_and_session ( old. 0 , old. 1 , new. 0 , new. 1 )
2334- }
2335- } ;
2336- if !aggregated_update. is_zero ( ) {
2337- if aggregated_update. get ( self . session_id ) < 0
2338- && let Some ( activeness_state) = get_mut ! ( task, Activeness )
2339- {
2340- activeness_state. all_clean_event . notify ( usize:: MAX ) ;
2341- activeness_state. unset_active_until_clean ( ) ;
2342- if activeness_state. is_empty ( ) {
2343- task. remove ( & CachedDataItemKey :: Activeness { } ) ;
2344- }
2342+ let current_session_clean_container_count = get ! (
2343+ task,
2344+ AggregatedSessionDependentCleanContainerCount {
2345+ session_id: self . session_id
23452346 }
2346- AggregationUpdateJob :: data_update (
2347- & mut task,
2348- AggregatedDataUpdate :: new ( ) . dirty_container_update (
2349- task_id,
2350- aggregated_update. count ,
2351- aggregated_update. current_session_clean ( ctx. session_id ( ) ) ,
2352- ) ,
2353- )
2354- } else {
2355- None
2356- }
2347+ )
2348+ . copied ( )
2349+ . unwrap_or_default ( ) ;
2350+ let result = ComputeDirtyAndCleanUpdate {
2351+ old_dirty_container_count : dirty_container_count,
2352+ new_dirty_container_count : dirty_container_count,
2353+ old_current_session_clean_container_count : current_session_clean_container_count,
2354+ new_current_session_clean_container_count : current_session_clean_container_count,
2355+ old_dirty_value,
2356+ new_dirty_value,
2357+ old_current_session_clean_value,
2358+ new_current_session_clean_value,
2359+ }
2360+ . compute ( ) ;
2361+ result
2362+ . aggregated_update ( task_id)
2363+ . and_then ( |aggregated_update| {
2364+ AggregationUpdateJob :: data_update ( & mut task, aggregated_update)
2365+ } )
23572366 } else {
23582367 None
23592368 } ;
23602369
2370+ if let Some ( activeness_state) = get_mut ! ( task, Activeness ) {
2371+ // The task is clean now
2372+ activeness_state. all_clean_event . notify ( usize:: MAX ) ;
2373+ activeness_state. unset_active_until_clean ( ) ;
2374+ if activeness_state. is_empty ( ) {
2375+ task. remove ( & CachedDataItemKey :: Activeness { } ) ;
2376+ }
2377+ }
2378+
23612379 #[ cfg( feature = "verify_determinism" ) ]
23622380 let reschedule = ( dirty_changed || no_output_set) && !task_id. is_transient ( ) ;
23632381 #[ cfg( not( feature = "verify_determinism" ) ) ]
@@ -2820,10 +2838,7 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
28202838 let mut ctx = self . execute_context ( turbo_tasks) ;
28212839 let mut task = ctx. task ( task_id, TaskDataCategory :: All ) ;
28222840 let is_dirty = task. is_dirty ( self . session_id ) ;
2823- let has_dirty_containers = get ! ( task, AggregatedDirtyContainerCount )
2824- . map_or ( false , |dirty_containers| {
2825- dirty_containers. get ( self . session_id ) > 0
2826- } ) ;
2841+ let has_dirty_containers = task. dirty_container_count ( self . session_id ) > 0 ;
28272842 if is_dirty || has_dirty_containers {
28282843 if let Some ( activeness_state) = get_mut ! ( task, Activeness ) {
28292844 // We will finish the task, but it would be removed after the task is done
@@ -2913,8 +2928,7 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
29132928 }
29142929
29152930 let is_dirty = get ! ( task, Dirty ) . is_some ( ) ;
2916- let has_dirty_container =
2917- get ! ( task, AggregatedDirtyContainerCount ) . is_some_and ( |count| count. count > 0 ) ;
2931+ let has_dirty_container = task. dirty_container_count ( self . session_id ) > 0 ;
29182932 let should_be_in_upper = is_dirty || has_dirty_container;
29192933
29202934 let aggregation_number = get_aggregation_number ( & task) ;
@@ -2937,17 +2951,19 @@ impl<B: BackingStorage> TurboTasksBackendInner<B> {
29372951
29382952 if should_be_in_upper {
29392953 for upper_id in uppers {
2940- let task = ctx. task ( task_id , TaskDataCategory :: All ) ;
2954+ let task = ctx. task ( upper_id , TaskDataCategory :: All ) ;
29412955 let in_upper = get ! ( task, AggregatedDirtyContainer { task: task_id } )
29422956 . is_some_and ( |& dirty| dirty > 0 ) ;
29432957 if !in_upper {
2958+ let containers: Vec < _ > = get_many ! ( task, AggregatedDirtyContainer { task: task_id } value => ( task_id, * value) ) ;
29442959 panic ! (
29452960 "Task {} ({}) is dirty, but is not listed in the upper task {} \
2946- ({})",
2961+ ({})\n These dirty containers are present: \n {:#?} ",
29472962 task_id,
29482963 ctx. get_task_description( task_id) ,
29492964 upper_id,
2950- ctx. get_task_description( upper_id)
2965+ ctx. get_task_description( upper_id) ,
2966+ containers,
29512967 ) ;
29522968 }
29532969 }
0 commit comments