diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/mod.rs b/turbopack/crates/turbo-tasks-backend/src/backend/mod.rs index bc0141f0f1b49a..6451b4bfe2e42e 100644 --- a/turbopack/crates/turbo-tasks-backend/src/backend/mod.rs +++ b/turbopack/crates/turbo-tasks-backend/src/backend/mod.rs @@ -817,9 +817,15 @@ impl TurboTasksBackendInner { } } + let ReadCellOptions { + is_serializable_cell_content, + tracking, + final_read_hint, + } = options; + let mut ctx = self.execute_context(turbo_tasks); let (mut task, reader_task) = if self.should_track_dependencies() - && !matches!(options.tracking, ReadTracking::Untracked) + && !matches!(tracking, ReadTracking::Untracked) && let Some(reader_id) = reader && reader_id != task_id { @@ -832,16 +838,13 @@ impl TurboTasksBackendInner { (ctx.task(task_id, TaskDataCategory::Data), None) }; - let content = if options.final_read_hint { - remove!(task, CellData { cell }) - } else if let Some(content) = get!(task, CellData { cell }) { - let content = content.clone(); - Some(content) + let content = if final_read_hint { + task.remove_cell_data(is_serializable_cell_content, cell) } else { - None + task.get_cell_data(is_serializable_cell_content, cell) }; if let Some(content) = content { - if options.tracking.should_track(false) { + if tracking.should_track(false) { add_cell_dependency(task_id, task, reader, reader_task, cell); } return Ok(Ok(TypedCellContent( @@ -868,7 +871,7 @@ impl TurboTasksBackendInner { ) .copied(); let Some(max_id) = max_id else { - if options.tracking.should_track(true) { + if tracking.should_track(true) { add_cell_dependency(task_id, task, reader, reader_task, cell); } bail!( @@ -877,7 +880,7 @@ impl TurboTasksBackendInner { ); }; if cell.index >= max_id { - if options.tracking.should_track(true) { + if tracking.should_track(true) { add_cell_dependency(task_id, task, reader, reader_task, cell); } bail!( @@ -2019,6 +2022,14 @@ impl TurboTasksBackendInner { .get(&cell.type_id).is_none_or(|start_index| cell.index >= *start_index)) })); } + if task_id.is_transient() || iter_many!(task, TransientCellData { cell } + if cell_counters.get(&cell.type_id).is_none_or(|start_index| cell.index >= *start_index) => cell + ).count() > 0 { + removed_data.extend(task.extract_if(CachedDataItemType::TransientCellData, |key, _| { + matches!(key, CachedDataItemKey::TransientCellData { cell } if cell_counters + .get(&cell.type_id).is_none_or(|start_index| cell.index >= *start_index)) + })); + } old_edges.extend( task.iter(CachedDataItemType::OutdatedCollectible) @@ -2459,6 +2470,7 @@ impl TurboTasksBackendInner { fn task_execution_completed_cleanup(&self, ctx: &mut impl ExecuteContext<'_>, task_id: TaskId) { let mut task = ctx.task(task_id, TaskDataCategory::All); task.shrink_to_fit(CachedDataItemType::CellData); + task.shrink_to_fit(CachedDataItemType::TransientCellData); task.shrink_to_fit(CachedDataItemType::CellTypeMaxIndex); task.shrink_to_fit(CachedDataItemType::CellDependency); task.shrink_to_fit(CachedDataItemType::OutputDependency); @@ -2594,13 +2606,14 @@ impl TurboTasksBackendInner { &self, task_id: TaskId, cell: CellId, - _options: ReadCellOptions, + options: ReadCellOptions, turbo_tasks: &dyn TurboTasksBackendApi>, ) -> Result { let mut ctx = self.execute_context(turbo_tasks); let task = ctx.task(task_id, TaskDataCategory::Data); - if let Some(content) = get!(task, CellData { cell }) { - Ok(CellContent(Some(content.reference.clone())).into_typed(cell.type_id)) + if let Some(content) = task.get_cell_data(options.is_serializable_cell_content, cell) { + debug_assert!(content.type_id == cell.type_id, "Cell type ID mismatch"); + Ok(CellContent(Some(content.reference)).into_typed(cell.type_id)) } else { Ok(CellContent(None).into_typed(cell.type_id)) } @@ -2741,6 +2754,7 @@ impl TurboTasksBackendInner { &self, task_id: TaskId, cell: CellId, + is_serializable_cell_content: bool, content: CellContent, verification_mode: VerificationMode, turbo_tasks: &dyn TurboTasksBackendApi>, @@ -2749,6 +2763,7 @@ impl TurboTasksBackendInner { task_id, cell, content, + is_serializable_cell_content, verification_mode, self.execute_context(turbo_tasks), ); @@ -3336,12 +3351,19 @@ impl Backend for TurboTasksBackend { &self, task_id: TaskId, cell: CellId, + is_serializable_cell_content: bool, content: CellContent, verification_mode: VerificationMode, turbo_tasks: &dyn TurboTasksBackendApi, ) { - self.0 - .update_task_cell(task_id, cell, content, verification_mode, turbo_tasks); + self.0.update_task_cell( + task_id, + cell, + is_serializable_cell_content, + content, + verification_mode, + turbo_tasks, + ); } fn mark_own_task_as_finished( diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/operation/mod.rs b/turbopack/crates/turbo-tasks-backend/src/backend/operation/mod.rs index 57d28b626375c8..32c0e45d3f75aa 100644 --- a/turbopack/crates/turbo-tasks-backend/src/backend/operation/mod.rs +++ b/turbopack/crates/turbo-tasks-backend/src/backend/operation/mod.rs @@ -14,13 +14,15 @@ use std::{ }; use serde::{Deserialize, Serialize}; -use turbo_tasks::{FxIndexMap, KeyValuePair, TaskId, TurboTasksBackendApi}; +use turbo_tasks::{ + CellId, FxIndexMap, KeyValuePair, TaskId, TurboTasksBackendApi, TypedSharedReference, +}; use crate::{ backend::{ OperationGuard, TaskDataCategory, TransientTask, TurboTasksBackend, TurboTasksBackendInner, TurboTasksBackendJob, - storage::{SpecificTaskDataCategory, StorageWriteGuard, get, iter_many}, + storage::{SpecificTaskDataCategory, StorageWriteGuard, get, iter_many, remove}, }, backing_storage::BackingStorage, data::{ @@ -467,6 +469,35 @@ pub trait TaskGuard: Debug { .unwrap_or_default(); dirty_count > clean_count } + fn remove_cell_data( + &mut self, + is_serializable_cell_content: bool, + cell: CellId, + ) -> Option { + if is_serializable_cell_content { + remove!(self, CellData { cell }) + } else { + remove!(self, TransientCellData { cell }).map(|sr| sr.into_typed(cell.type_id)) + } + } + fn get_cell_data( + &self, + is_serializable_cell_content: bool, + cell: CellId, + ) -> Option { + if is_serializable_cell_content { + get!(self, CellData { cell }).cloned() + } else { + get!(self, TransientCellData { cell }).map(|sr| sr.clone().into_typed(cell.type_id)) + } + } + fn has_cell_data(&self, is_serializable_cell_content: bool, cell: CellId) -> bool { + if is_serializable_cell_content { + self.has_key(&CachedDataItemKey::CellData { cell }) + } else { + self.has_key(&CachedDataItemKey::TransientCellData { cell }) + } + } } pub struct TaskGuardImpl<'a, B: BackingStorage> { diff --git a/turbopack/crates/turbo-tasks-backend/src/backend/operation/update_cell.rs b/turbopack/crates/turbo-tasks-backend/src/backend/operation/update_cell.rs index dd26a84615ec97..3a5b50b80c148c 100644 --- a/turbopack/crates/turbo-tasks-backend/src/backend/operation/update_cell.rs +++ b/turbopack/crates/turbo-tasks-backend/src/backend/operation/update_cell.rs @@ -15,7 +15,7 @@ use crate::{ AggregationUpdateQueue, ExecuteContext, Operation, TaskGuard, invalidate::make_task_dirty_internal, }, - storage::{get, get_many, remove}, + storage::{get_many, remove}, }, data::{CachedDataItem, CachedDataItemKey, CellRef}, }; @@ -24,12 +24,14 @@ use crate::{ #[allow(clippy::large_enum_variant)] pub enum UpdateCellOperation { InvalidateWhenCellDependency { + is_serializable_cell_content: bool, cell_ref: CellRef, dependent_tasks: SmallVec<[TaskId; 4]>, content: Option, queue: AggregationUpdateQueue, }, FinalCellChange { + is_serializable_cell_content: bool, cell_ref: CellRef, content: Option, queue: AggregationUpdateQueue, @@ -46,6 +48,7 @@ impl UpdateCellOperation { task_id: TaskId, cell: CellId, content: CellContent, + is_serializable_cell_content: bool, #[cfg(feature = "verify_determinism")] verification_mode: VerificationMode, #[cfg(not(feature = "verify_determinism"))] _verification_mode: VerificationMode, mut ctx: impl ExecuteContext, @@ -64,10 +67,9 @@ impl UpdateCellOperation { let assume_unchanged = !ctx.should_track_dependencies() || !task.has_key(&CachedDataItemKey::Dirty {}); - let old_content = get!(task, CellData { cell }); - if assume_unchanged { - if old_content.is_some() { + let has_old_content = task.has_cell_data(is_serializable_cell_content, cell); + if has_old_content { // Never update cells when recomputing if they already have a value. // It's not expected that content changes during recomputation. @@ -75,7 +77,7 @@ impl UpdateCellOperation { #[cfg(feature = "verify_determinism")] if !is_stateful && matches!(verification_mode, VerificationMode::EqualityCheck) - && content.as_ref() != old_content + && content != task.get_cell_data(is_serializable_cell_content, cell) { let task_description = ctx.get_task_description(task_id); let cell_type = turbo_tasks::registry::get_value_type(cell.type_id).global_name; @@ -115,12 +117,16 @@ impl UpdateCellOperation { // tasks and after that set the new cell content. When the cell content is unset, // readers will wait for it to be set via InProgressCell. - let old_content = task.remove(&CachedDataItemKey::CellData { cell }); + let old_content = task.remove(&CachedDataItemKey::cell_data( + is_serializable_cell_content, + cell, + )); drop(task); drop(old_content); UpdateCellOperation::InvalidateWhenCellDependency { + is_serializable_cell_content, cell_ref: CellRef { task: task_id, cell, @@ -138,12 +144,16 @@ impl UpdateCellOperation { // So we can just update the cell content. let old_content = if let Some(new_content) = content { - task.insert(CachedDataItem::CellData { + task.insert(CachedDataItem::cell_data( + is_serializable_cell_content, cell, - value: new_content, - }) + new_content, + )) } else { - task.remove(&CachedDataItemKey::CellData { cell }) + task.remove(&CachedDataItemKey::cell_data( + is_serializable_cell_content, + cell, + )) }; let in_progress_cell = remove!(task, InProgressCell { cell }); @@ -163,6 +173,7 @@ impl Operation for UpdateCellOperation { ctx.operation_suspend_point(&self); match self { UpdateCellOperation::InvalidateWhenCellDependency { + is_serializable_cell_content, cell_ref, ref mut dependent_tasks, ref mut content, @@ -203,6 +214,7 @@ impl Operation for UpdateCellOperation { } if dependent_tasks.is_empty() { self = UpdateCellOperation::FinalCellChange { + is_serializable_cell_content, cell_ref, content: take(content), queue: take(queue), @@ -210,6 +222,7 @@ impl Operation for UpdateCellOperation { } } UpdateCellOperation::FinalCellChange { + is_serializable_cell_content, cell_ref: CellRef { task, cell }, content, ref mut queue, @@ -217,10 +230,11 @@ impl Operation for UpdateCellOperation { let mut task = ctx.task(task, TaskDataCategory::Data); if let Some(content) = content { - task.add_new(CachedDataItem::CellData { + task.add_new(CachedDataItem::cell_data( + is_serializable_cell_content, cell, - value: content, - }) + content, + )); } let in_progress_cell = remove!(task, InProgressCell { cell }); diff --git a/turbopack/crates/turbo-tasks-backend/src/data.rs b/turbopack/crates/turbo-tasks-backend/src/data.rs index 197b9c7a30329c..b2c97a10791017 100644 --- a/turbopack/crates/turbo-tasks-backend/src/data.rs +++ b/turbopack/crates/turbo-tasks-backend/src/data.rs @@ -1,11 +1,10 @@ use rustc_hash::FxHashSet; use serde::{Deserialize, Serialize}; use turbo_tasks::{ - CellId, KeyValuePair, TaskExecutionReason, TaskId, TraitTypeId, TypedSharedReference, - ValueTypeId, + CellId, KeyValuePair, SharedReference, TaskExecutionReason, TaskId, TraitTypeId, + TypedSharedReference, ValueTypeId, backend::TurboTasksExecutionError, event::{Event, EventListener}, - registry, }; use crate::{ @@ -244,6 +243,11 @@ pub enum CachedDataItem { cell: CellId, value: TypedSharedReference, }, + #[serde(skip)] + TransientCellData { + cell: CellId, + value: SharedReference, + }, CellTypeMaxIndex { cell_type: ValueTypeId, value: u32, @@ -364,6 +368,21 @@ pub enum CachedDataItem { } impl CachedDataItem { + pub fn cell_data( + is_serializable_cell_content: bool, + cell: CellId, + value: TypedSharedReference, + ) -> Self { + if is_serializable_cell_content { + CachedDataItem::CellData { cell, value } + } else { + CachedDataItem::TransientCellData { + cell, + value: value.into_untyped(), + } + } + } + pub fn is_persistent(&self) -> bool { match self { CachedDataItem::Output { value } => value.is_transient(), @@ -374,6 +393,7 @@ impl CachedDataItem { CachedDataItem::CurrentSessionClean { .. } => false, CachedDataItem::Child { task, .. } => !task.is_transient(), CachedDataItem::CellData { .. } => true, + CachedDataItem::TransientCellData { .. } => false, CachedDataItem::CellTypeMaxIndex { .. } => true, CachedDataItem::OutputDependency { target, .. } => !target.is_transient(), CachedDataItem::CellDependency { target, .. } => !target.task.is_transient(), @@ -471,6 +491,7 @@ impl CachedDataItem { | Self::OutdatedOutputDependency { .. } | Self::OutdatedCellDependency { .. } | Self::OutdatedCollectiblesDependency { .. } + | Self::TransientCellData { .. } | Self::CurrentSessionClean { .. } | Self::AggregatedCurrentSessionCleanContainer { .. } | Self::AggregatedCurrentSessionCleanContainerCount { .. } @@ -486,6 +507,14 @@ impl CachedDataItem { } impl CachedDataItemKey { + pub fn cell_data(is_serializable_cell_content: bool, cell: CellId) -> Self { + if is_serializable_cell_content { + CachedDataItemKey::CellData { cell } + } else { + CachedDataItemKey::TransientCellData { cell } + } + } + pub fn is_persistent(&self) -> bool { match self { CachedDataItemKey::Output { .. } => true, @@ -496,6 +525,7 @@ impl CachedDataItemKey { CachedDataItemKey::CurrentSessionClean { .. } => false, CachedDataItemKey::Child { task, .. } => !task.is_transient(), CachedDataItemKey::CellData { .. } => true, + CachedDataItemKey::TransientCellData { .. } => false, CachedDataItemKey::CellTypeMaxIndex { .. } => true, CachedDataItemKey::OutputDependency { target, .. } => !target.is_transient(), CachedDataItemKey::CellDependency { target, .. } => !target.task.is_transient(), @@ -561,6 +591,7 @@ impl CachedDataItemType { | Self::OutdatedOutputDependency { .. } | Self::OutdatedCellDependency { .. } | Self::OutdatedCollectiblesDependency { .. } + | Self::TransientCellData { .. } | Self::CurrentSessionClean { .. } | Self::AggregatedCurrentSessionCleanContainer { .. } | Self::AggregatedCurrentSessionCleanContainerCount { .. } @@ -600,6 +631,7 @@ impl CachedDataItemType { | Self::CurrentSessionClean | Self::AggregatedCurrentSessionCleanContainer | Self::AggregatedCurrentSessionCleanContainerCount + | Self::TransientCellData | Self::OutdatedCollectible | Self::OutdatedOutputDependency | Self::OutdatedCellDependency @@ -621,9 +653,6 @@ impl CachedDataItemValueRef<'_> { pub fn is_persistent(&self) -> bool { match self { CachedDataItemValueRef::Output { value } => !value.is_transient(), - CachedDataItemValueRef::CellData { value } => { - registry::get_value_type(value.type_id).is_serializable() - } _ => true, } } diff --git a/turbopack/crates/turbo-tasks-macros/src/generic_type_macro.rs b/turbopack/crates/turbo-tasks-macros/src/generic_type_macro.rs index d455e34c2b65b8..156d7cb6863388 100644 --- a/turbopack/crates/turbo-tasks-macros/src/generic_type_macro.rs +++ b/turbopack/crates/turbo-tasks-macros/src/generic_type_macro.rs @@ -80,6 +80,7 @@ pub fn generic_type(input: TokenStream) -> TokenStream { quote! { turbo_tasks::ValueType::new_with_any_serialization::<#repr>(#name) }, + quote! { true }, ); quote! { diff --git a/turbopack/crates/turbo-tasks-macros/src/primitive_macro.rs b/turbopack/crates/turbo-tasks-macros/src/primitive_macro.rs index 35f537bf013529..dbd0011e695cbf 100644 --- a/turbopack/crates/turbo-tasks-macros/src/primitive_macro.rs +++ b/turbopack/crates/turbo-tasks-macros/src/primitive_macro.rs @@ -48,6 +48,7 @@ pub fn primitive(input: TokenStream) -> TokenStream { quote! { turbo_tasks::ValueType::new_with_any_serialization::<#ty>(#name) }, + quote! { true }, ); let value_default_impl = quote! { diff --git a/turbopack/crates/turbo-tasks-macros/src/value_macro.rs b/turbopack/crates/turbo-tasks-macros/src/value_macro.rs index 487180e55314cc..b028ed309dbcab 100644 --- a/turbopack/crates/turbo-tasks-macros/src/value_macro.rs +++ b/turbopack/crates/turbo-tasks-macros/src/value_macro.rs @@ -349,6 +349,10 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream { } } }; + let has_serialization = match serialization_mode { + SerializationMode::None => quote! { false }, + SerializationMode::Auto | SerializationMode::Custom => quote! { true }, + }; let value_debug_impl = if inner_type.is_some() { // For transparent values, we defer directly to the inner type's `ValueDebug` @@ -380,6 +384,7 @@ pub fn value(args: TokenStream, input: TokenStream) -> TokenStream { read, cell_mode, new_value_type, + has_serialization, ); let expanded = quote! { @@ -405,6 +410,7 @@ pub fn value_type_and_register( read: proc_macro2::TokenStream, cell_mode: proc_macro2::TokenStream, new_value_type: proc_macro2::TokenStream, + has_serialization: proc_macro2::TokenStream, ) -> proc_macro2::TokenStream { let value_type_ident = get_value_type_ident(ident); @@ -438,6 +444,10 @@ pub fn value_type_and_register( *ident } + + fn has_serialization() -> bool { + #has_serialization + } } } } diff --git a/turbopack/crates/turbo-tasks-testing/src/lib.rs b/turbopack/crates/turbo-tasks-testing/src/lib.rs index b298f282c07bdc..2ce5d7b3791e96 100644 --- a/turbopack/crates/turbo-tasks-testing/src/lib.rs +++ b/turbopack/crates/turbo-tasks-testing/src/lib.rs @@ -265,6 +265,7 @@ impl TurboTasksApi for VcStorage { &self, task: TaskId, index: CellId, + _is_serializable_cell_content: bool, content: CellContent, _verification_mode: VerificationMode, ) { diff --git a/turbopack/crates/turbo-tasks/src/backend.rs b/turbopack/crates/turbo-tasks/src/backend.rs index e15edf4eb68aff..2113ea7c89e390 100644 --- a/turbopack/crates/turbo-tasks/src/backend.rs +++ b/turbopack/crates/turbo-tasks/src/backend.rs @@ -634,6 +634,7 @@ pub trait Backend: Sync + Send { &self, task: TaskId, index: CellId, + is_serializable_cell_content: bool, content: CellContent, verification_mode: VerificationMode, turbo_tasks: &dyn TurboTasksBackendApi, diff --git a/turbopack/crates/turbo-tasks/src/macro_helpers.rs b/turbopack/crates/turbo-tasks/src/macro_helpers.rs index 10b3be172cb251..6987608d30603e 100644 --- a/turbopack/crates/turbo-tasks/src/macro_helpers.rs +++ b/turbopack/crates/turbo-tasks/src/macro_helpers.rs @@ -14,7 +14,7 @@ use crate::{ pub use crate::{ global_name, inventory_submit, magic_any::MagicAny, - manager::{find_cell_by_type, spawn_detached_for_testing}, + manager::{find_cell_by_id, find_cell_by_type, spawn_detached_for_testing}, native_function::{ CollectableFunction, NativeFunction, downcast_args_owned, downcast_args_ref, }, diff --git a/turbopack/crates/turbo-tasks/src/manager.rs b/turbopack/crates/turbo-tasks/src/manager.rs index 7c2e58e8e66596..270b97a53466eb 100644 --- a/turbopack/crates/turbo-tasks/src/manager.rs +++ b/turbopack/crates/turbo-tasks/src/manager.rs @@ -159,6 +159,7 @@ pub trait TurboTasksApi: TurboTasksCallApi + Sync + Send { &self, task: TaskId, index: CellId, + is_serializable_cell_content: bool, content: CellContent, verification_mode: VerificationMode, ); @@ -1355,11 +1356,18 @@ impl TurboTasksApi for TurboTasks { &self, task: TaskId, index: CellId, + is_serializable_cell_content: bool, content: CellContent, verification_mode: VerificationMode, ) { - self.backend - .update_task_cell(task, index, content, verification_mode, self); + self.backend.update_task_cell( + task, + index, + is_serializable_cell_content, + content, + verification_mode, + self, + ); } fn connect_task(&self, task: TaskId) { @@ -1733,6 +1741,7 @@ pub(crate) async fn read_task_cell( pub struct CurrentCellRef { current_task: TaskId, index: CellId, + is_serializable_cell_content: bool, } type VcReadRepr = <::Read as VcRead>::Repr; @@ -1767,7 +1776,8 @@ impl CurrentCellRef { ReadCellOptions { // INVALIDATION: Reading our own cell must be untracked tracking: ReadTracking::Untracked, - ..Default::default() + is_serializable_cell_content: self.is_serializable_cell_content, + final_read_hint: false, }, ) .ok(); @@ -1776,6 +1786,7 @@ impl CurrentCellRef { tt.update_own_task_cell( self.current_task, self.index, + self.is_serializable_cell_content, CellContent(Some(update)), VerificationMode::EqualityCheck, ) @@ -1868,6 +1879,7 @@ impl CurrentCellRef { tt.update_own_task_cell( self.current_task, self.index, + self.is_serializable_cell_content, CellContent(Some(SharedReference::new(triomphe::Arc::new( >::value_to_repr(new_value), )))), @@ -1897,7 +1909,8 @@ impl CurrentCellRef { ReadCellOptions { // INVALIDATION: Reading our own cell must be untracked tracking: ReadTracking::Untracked, - ..Default::default() + is_serializable_cell_content: self.is_serializable_cell_content, + final_read_hint: false, }, ) .ok(); @@ -1914,6 +1927,7 @@ impl CurrentCellRef { tt.update_own_task_cell( self.current_task, self.index, + self.is_serializable_cell_content, CellContent(Some(shared_ref)), verification_mode, ) @@ -1927,7 +1941,11 @@ impl From for RawVc { } } -pub fn find_cell_by_type(ty: ValueTypeId) -> CurrentCellRef { +pub fn find_cell_by_type() -> CurrentCellRef { + find_cell_by_id(T::get_value_type_id(), T::has_serialization()) +} + +pub fn find_cell_by_id(ty: ValueTypeId, is_serializable_cell_content: bool) -> CurrentCellRef { CURRENT_TASK_STATE.with(|ts| { let current_task = current_task("celling turbo_tasks values"); let mut ts = ts.write().unwrap(); @@ -1938,6 +1956,7 @@ pub fn find_cell_by_type(ty: ValueTypeId) -> CurrentCellRef { CurrentCellRef { current_task, index: CellId { type_id: ty, index }, + is_serializable_cell_content, } }) } diff --git a/turbopack/crates/turbo-tasks/src/raw_vc.rs b/turbopack/crates/turbo-tasks/src/raw_vc.rs index 60aaf0a0f86cb5..72b440c5519058 100644 --- a/turbopack/crates/turbo-tasks/src/raw_vc.rs +++ b/turbopack/crates/turbo-tasks/src/raw_vc.rs @@ -147,10 +147,16 @@ impl RawVc { } } - pub(crate) fn into_read(self) -> ReadRawVcFuture { + pub(crate) fn into_read(self, is_serializable_cell_content: bool) -> ReadRawVcFuture { // returns a custom future to have something concrete and sized // this avoids boxing in IntoFuture - ReadRawVcFuture::new(self) + ReadRawVcFuture::new(self, Some(is_serializable_cell_content)) + } + + pub(crate) fn into_read_with_unknown_is_serializable_cell_content(self) -> ReadRawVcFuture { + // returns a custom future to have something concrete and sized + // this avoids boxing in IntoFuture + ReadRawVcFuture::new(self, None) } pub(crate) async fn resolve_trait( @@ -193,15 +199,26 @@ impl RawVc { .map_err(|source| ResolveTypeError::TaskError { source })?; } RawVc::TaskCell(task, index) => { - let content = read_task_cell(&*tt, task, index, ReadCellOptions::default()) - .await - .map_err(|source| ResolveTypeError::ReadError { source })?; - if let TypedCellContent(value_type, CellContent(Some(_))) = content { - return Ok(if conditional(value_type).0 { - Some(RawVc::TaskCell(task, index)) - } else { - None - }); + let (ok, value_type) = conditional(index.type_id); + if !ok { + return Ok(None); + } + let value_type = + value_type.unwrap_or_else(|| registry::get_value_type(index.type_id)); + let content = read_task_cell( + &*tt, + task, + index, + ReadCellOptions { + is_serializable_cell_content: value_type.is_serializable(), + final_read_hint: false, + tracking: ReadTracking::default(), + }, + ) + .await + .map_err(|source| ResolveTypeError::ReadError { source })?; + if let TypedCellContent(_, CellContent(Some(_))) = content { + return Ok(Some(RawVc::TaskCell(task, index))); } else { return Err(ResolveTypeError::NoContent); } @@ -362,15 +379,20 @@ pub struct ReadRawVcFuture { current: RawVc, read_output_options: ReadOutputOptions, read_cell_options: ReadCellOptions, + is_serializable_cell_content_unknown: bool, listener: Option, } impl ReadRawVcFuture { - pub(crate) fn new(vc: RawVc) -> Self { + pub(crate) fn new(vc: RawVc, is_serializable_cell_content: Option) -> Self { ReadRawVcFuture { current: vc, read_output_options: ReadOutputOptions::default(), - read_cell_options: ReadCellOptions::default(), + read_cell_options: ReadCellOptions { + is_serializable_cell_content: is_serializable_cell_content.unwrap_or(false), + ..Default::default() + }, + is_serializable_cell_content_unknown: is_serializable_cell_content.is_none(), listener: None, } } @@ -441,6 +463,11 @@ impl Future for ReadRawVcFuture { } } RawVc::TaskCell(task, index) => { + if this.is_serializable_cell_content_unknown { + let value_type = registry::get_value_type(index.type_id); + this.read_cell_options.is_serializable_cell_content = + value_type.is_serializable(); + } let read_result = tt.try_read_task_cell(task, index, this.read_cell_options); match read_result { diff --git a/turbopack/crates/turbo-tasks/src/read_options.rs b/turbopack/crates/turbo-tasks/src/read_options.rs index 3c08fe3a3b72bb..49364688c95692 100644 --- a/turbopack/crates/turbo-tasks/src/read_options.rs +++ b/turbopack/crates/turbo-tasks/src/read_options.rs @@ -3,6 +3,7 @@ use crate::{ReadConsistency, ReadTracking}; #[derive(Clone, Copy, Debug, Default)] pub struct ReadCellOptions { pub tracking: ReadTracking, + pub is_serializable_cell_content: bool, pub final_read_hint: bool, } diff --git a/turbopack/crates/turbo-tasks/src/task/function.rs b/turbopack/crates/turbo-tasks/src/task/function.rs index da5c4fb4fcf350..d79f0ae8ad193b 100644 --- a/turbopack/crates/turbo-tasks/src/task/function.rs +++ b/turbopack/crates/turbo-tasks/src/task/function.rs @@ -416,6 +416,10 @@ mod tests { fn get_value_type_id() -> crate::ValueTypeId { todo!() } + + fn has_serialization() -> bool { + false + } } trait AsyncTrait { diff --git a/turbopack/crates/turbo-tasks/src/task/local_task.rs b/turbopack/crates/turbo-tasks/src/task/local_task.rs index 32288856862c0d..6180a31e1563dc 100644 --- a/turbopack/crates/turbo-tasks/src/task/local_task.rs +++ b/turbopack/crates/turbo-tasks/src/task/local_task.rs @@ -3,12 +3,8 @@ use std::{fmt, sync::Arc}; use anyhow::{Result, anyhow}; use crate::{ - MagicAny, OutputContent, RawVc, TaskPersistence, TraitMethod, TurboTasksBackendApi, - ValueTypeId, - backend::{Backend, TypedCellContent}, - event::Event, - macro_helpers::NativeFunction, - registry, + CellId, MagicAny, OutputContent, RawVc, TaskPersistence, TraitMethod, TurboTasksBackendApi, + ValueTypeId, backend::Backend, event::Event, macro_helpers::NativeFunction, registry, }; /// A potentially in-flight local task stored in `CurrentGlobalTaskState::local_tasks`. @@ -75,9 +71,11 @@ impl LocalTaskType { turbo_tasks: Arc>, ) -> Result { let this = this.resolve().await?; - let TypedCellContent(this_ty, _) = this.into_read().await?; + let RawVc::TaskCell(_, CellId { type_id, .. }) = this else { + return Err(anyhow!("Trait method receiver must be a cell")); + }; - let native_fn = Self::resolve_trait_method_from_value(trait_method, this_ty)?; + let native_fn = Self::resolve_trait_method_from_value(trait_method, type_id)?; let arg = native_fn.arg_meta.filter_and_resolve(arg).await?; Ok(turbo_tasks.native_call(native_fn, Some(this), arg, persistence)) } diff --git a/turbopack/crates/turbo-tasks/src/trait_ref.rs b/turbopack/crates/turbo-tasks/src/trait_ref.rs index 6ad8a49a142eb8..e583a2a4fb4f8c 100644 --- a/turbopack/crates/turbo-tasks/src/trait_ref.rs +++ b/turbopack/crates/turbo-tasks/src/trait_ref.rs @@ -157,6 +157,8 @@ where type Future = ReadVcFuture>; fn into_trait_ref(self) -> Self::Future { - self.node.into_read().into() + self.node + .into_read_with_unknown_is_serializable_cell_content() + .into() } } diff --git a/turbopack/crates/turbo-tasks/src/vc/cell_mode.rs b/turbopack/crates/turbo-tasks/src/vc/cell_mode.rs index cffeed9d67c237..cbcc030861044c 100644 --- a/turbopack/crates/turbo-tasks/src/vc/cell_mode.rs +++ b/turbopack/crates/turbo-tasks/src/vc/cell_mode.rs @@ -39,7 +39,7 @@ where T: VcValueType, { fn cell(inner: VcReadTarget) -> Vc { - let cell = find_cell_by_type(T::get_value_type_id()); + let cell = find_cell_by_type::(); cell.update( >::target_to_value(inner), VerificationMode::Skip, @@ -52,7 +52,7 @@ where fn raw_cell(content: TypedSharedReference) -> RawVc { debug_assert_repr::(&content); - let cell = find_cell_by_type(content.type_id); + let cell = find_cell_by_type::(); cell.update_with_shared_reference(content.reference, VerificationMode::Skip); cell.into() } @@ -69,7 +69,7 @@ where T: VcValueType + PartialEq, { fn cell(inner: VcReadTarget) -> Vc { - let cell = find_cell_by_type(T::get_value_type_id()); + let cell = find_cell_by_type::(); cell.compare_and_update(>::target_to_value(inner)); Vc { node: cell.into(), @@ -79,7 +79,7 @@ where fn raw_cell(content: TypedSharedReference) -> RawVc { debug_assert_repr::(&content); - let cell = find_cell_by_type(content.type_id); + let cell = find_cell_by_type::(); cell.compare_and_update_with_shared_reference::(content.reference); cell.into() } diff --git a/turbopack/crates/turbo-tasks/src/vc/mod.rs b/turbopack/crates/turbo-tasks/src/vc/mod.rs index 62c2b31ba2cd7b..81884a0827f9a8 100644 --- a/turbopack/crates/turbo-tasks/src/vc/mod.rs +++ b/turbopack/crates/turbo-tasks/src/vc/mod.rs @@ -611,7 +611,7 @@ macro_rules! into_future { type Output = as Future>::Output; type IntoFuture = ReadVcFuture; fn into_future(self) -> Self::IntoFuture { - self.node.into_read().into() + self.node.into_read(T::has_serialization()).into() } } }; @@ -629,21 +629,30 @@ where #[cfg(feature = "non_operation_vc_strongly_consistent")] #[must_use] pub fn strongly_consistent(self) -> ReadVcFuture { - self.node.into_read().strongly_consistent().into() + self.node + .into_read(T::has_serialization()) + .strongly_consistent() + .into() } /// Returns a untracked read of the value. This will not invalidate the current function when /// the read value changed. #[must_use] pub fn untracked(self) -> ReadVcFuture { - self.node.into_read().untracked().into() + self.node + .into_read(T::has_serialization()) + .untracked() + .into() } /// Read the value with the hint that this is the final read of the value. This might drop the /// cell content. Future reads might need to recompute the value. #[must_use] pub fn final_read_hint(self) -> ReadVcFuture { - self.node.into_read().final_read_hint().into() + self.node + .into_read(T::has_serialization()) + .final_read_hint() + .into() } } @@ -654,7 +663,7 @@ where { /// Read the value and returns a owned version of it. It might clone the value. pub fn owned(self) -> ReadOwnedVcFuture { - let future: ReadVcFuture = self.node.into_read().into(); + let future: ReadVcFuture = self.node.into_read(T::has_serialization()).into(); future.owned() } } diff --git a/turbopack/crates/turbo-tasks/src/vc/operation.rs b/turbopack/crates/turbo-tasks/src/vc/operation.rs index f423f798278c4c..fbaacffa173bd5 100644 --- a/turbopack/crates/turbo-tasks/src/vc/operation.rs +++ b/turbopack/crates/turbo-tasks/src/vc/operation.rs @@ -130,7 +130,11 @@ impl OperationVc { where T: VcValueType, { - self.connect().node.into_read().strongly_consistent().into() + self.connect() + .node + .into_read(T::has_serialization()) + .strongly_consistent() + .into() } } diff --git a/turbopack/crates/turbo-tasks/src/vc/traits.rs b/turbopack/crates/turbo-tasks/src/vc/traits.rs index 247336a12f2c38..c4c5cdd95b92c9 100644 --- a/turbopack/crates/turbo-tasks/src/vc/traits.rs +++ b/turbopack/crates/turbo-tasks/src/vc/traits.rs @@ -22,6 +22,8 @@ pub unsafe trait VcValueType: ShrinkToFit + Sized + Send + Sync + 'static { /// Returns the type id of the value type. fn get_value_type_id() -> ValueTypeId; + + fn has_serialization() -> bool; } /// A trait implemented on all values trait object references that can be put