Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make ReadRef using VcCellMode semantics, add VcCellMode::raw_cell API #8847

Closed
wants to merge 1 commit into from

Conversation

bgw
Copy link
Member

@bgw bgw commented Jul 26, 2024

Description

More fixes to ReadRef on top of #8845. There's a bit of a cascade of changes that needed to happen here:

  • ReadRef::cell should actually use VcCellMode so that it supports new/shared semantics correctly.
  • ... however, VcCellMode needs to expose an API (raw_cell) for working with SharedReference so that we can reuse the SharedReference/Arc inside of ReadRef instead of cloning the data inside of it.
  • ... however, CurrentCellRef needs to expose a compare_and_update method that works for SharedReference (compare_and_update_with_shared_reference).
  • ... however, the naming conventions for the CurrentCellRef methods are a bit confusing at this point, so rename them.

Bigger Picture

This my sneaky way of introducing the raw_cell API as part of a smaller PR, since that API will be needed for converting a local Vc to a resolved Vc. That's a similar problem of needing to reuse a SharedReference along with VcCellMode semantics.

Testing Instructions

cargo nextest r -p turbo-tasks -p turbo-tasks-memory

Copy link

vercel bot commented Jul 26, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
examples-nonmonorepo ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 29, 2024 9:05pm
rust-docs ✅ Ready (Inspect) Visit Preview 💬 Add feedback Jul 29, 2024 9:05pm
8 Skipped Deployments
Name Status Preview Comments Updated (UTC)
examples-basic-web ⬜️ Ignored (Inspect) Visit Preview Jul 29, 2024 9:05pm
examples-designsystem-docs ⬜️ Ignored (Inspect) Visit Preview Jul 29, 2024 9:05pm
examples-gatsby-web ⬜️ Ignored (Inspect) Visit Preview Jul 29, 2024 9:05pm
examples-kitchensink-blog ⬜️ Ignored (Inspect) Visit Preview Jul 29, 2024 9:05pm
examples-native-web ⬜️ Ignored (Inspect) Visit Preview Jul 29, 2024 9:05pm
examples-svelte-web ⬜️ Ignored (Inspect) Visit Preview Jul 29, 2024 9:05pm
examples-tailwind-web ⬜️ Ignored (Inspect) Visit Preview Jul 29, 2024 9:05pm
examples-vite-web ⬜️ Ignored (Inspect) Visit Preview Jul 29, 2024 9:05pm

Copy link
Contributor

github-actions bot commented Jul 26, 2024

🟢 Turbopack Benchmark CI successful 🟢

Thanks

Copy link
Contributor

✅ This change can build next-swc

Copy link
Contributor

github-actions bot commented Jul 26, 2024

⚠️ CI failed ⚠️

The following steps have failed in CI:

  • Turbopack Rust tests (mac/win, non-blocking)

See workflow summary for details

Comment on lines 245 to 258
pub fn cell(read_ref: ReadRef<T>) -> Vc<T> {
let type_id = T::get_value_type_id();
let local_cell = find_cell_by_type(type_id);
// SAFETY: `T` and `T::Read::Repr` must have equivalent memory representations,
// guaranteed by the unsafe implementation of `VcValueType`.
local_cell.update_shared_reference(SharedReference::new(unsafe {
let value = unsafe {
unchecked_sidecast_triomphe_arc::<T, <T::Read as VcRead<T>>::Repr>(read_ref.0)
}));
};
Vc {
node: local_cell.into(),
node: <T::CellMode as VcCellMode<T>>::raw_cell(
SharedReference::new(value).typed(type_id),
),
_t: PhantomData,
}
}
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Essentially the problem here was that ReadRef can't/shouldn't implement cell itself. It must defer to VcCellMode's implementation, as only that trait's implementation knows how to correctly construct a cell.

Comment on lines -30 to -42
Ok(
// Safety: the `VcValueType` implementor must guarantee that both `T` and
// `Repr` are #[repr(transparent)].
unsafe {
// Downcast the cell content to the expected representation type, then
// transmute it to the expected type.
// See https://users.rust-lang.org/t/transmute-doesnt-work-on-generic-types/87272/9
std::mem::transmute_copy::<
ManuallyDrop<ReadRef<<T::Read as VcRead<T>>::Repr>>,
Self::Output,
>(&ManuallyDrop::new(content.cast()?))
},
)
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It turns out that this transmute wasn't entirely correct. You can't do a straight transmute between two ReadRef<T>s because it contains a triomphe::Arc<T>, and the vtable half of triomphe::Arc<T>'s fat pointer is different depending on the type of T.

You need to use something like unchecked_sidecast_triomphe_arc so that the fat pointer is constructed correctly. I modified the TypedCellContent::cast method in this PR to do the cast of Arc for us before constructing the ReadRef.

Comment on lines +20 to +22
/// Create a type-erased `RawVc` cell given a pre-existing type-erased
/// `SharedReference`. In some cases, we will re-use the shared value.
fn raw_cell(value: TypedSharedReference) -> RawVc;
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Local Vc resolution needs this VcCellMode::raw_cell method too because we need to be able to construct a new cell inside of RawVc where we don't have compile-time information about the concrete type T (but we do have the type id).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In some cases, we will re-use the shared value.

When is this the case?

Copy link
Member Author

@bgw bgw Jul 31, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When constructing a Vc from a ReadRef or when converting a local Vc to a global resolved Vc we already have a SharedReference or triomphe::Arc, so we can re-use that value and avoid any need to clone the underlying value.

(I'll update the comment in the code here to provide this context)

Comment on lines 102 to 108
// See Safety clause above.
let TypedSharedReference(ty, shared_ref) = trait_ref.shared_reference;
let local_cell = find_cell_by_type(ty);
local_cell.update_shared_reference(shared_ref);
local_cell.update_with_shared_reference(shared_ref);
let raw_vc: RawVc = local_cell.into();
raw_vc.into()
}
Copy link
Member Author

@bgw bgw Jul 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TraitRef::cell has similar problems to ReadRef::cell here, and needs to also call VcCellMode::raw_cell, but that's a bit more complicated as I need a mapping of type ids to raw_vc function pointers. I'll do that in a subsequent PR.

Edit: Fixed in #8870

@bgw bgw marked this pull request as ready for review July 26, 2024 19:43
@bgw bgw requested a review from a team as a code owner July 26, 2024 19:43
@bgw bgw requested review from sokra and wbinnssmith July 26, 2024 19:45
/// Replace the current cell's content with `new_shared_reference` if the
/// current content is not equal by value with the existing content.
///
/// If you already have a `SharedReference`, this is a faster version of
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps it is useful to have the reciprocal comment?

@bgw
Copy link
Member Author

bgw commented Aug 2, 2024

Migrated to the next.js repo: vercel/next.js#68467

@bgw bgw closed this Aug 2, 2024
@bgw bgw deleted the bgw/cell-mode-raw branch August 4, 2024 19:50
bgw added a commit to vercel/next.js that referenced this pull request Aug 5, 2024
…e::raw_cell` API (#68467)

*This is a migrated PR. This was in the turbo repository before the
next.js merge.*
**Migrated From:** vercel/turborepo#8847

## Description

More fixes to `ReadRef` on top of
vercel/turborepo#8845. There's a bit of a cascade of
changes that needed to happen here:

- `ReadRef::cell` should actually use `VcCellMode` so that it supports
new/shared semantics correctly.
- ... however, `VcCellMode` needs to expose an API (`raw_cell`) for
working with `SharedReference` so that we can reuse the
`SharedReference`/`Arc` inside of `ReadRef` instead of cloning the data
inside of it.
- ... however, `CurrentCellRef` needs to expose a `compare_and_update`
method that works for `SharedReference`
(`compare_and_update_with_shared_reference`).
- ... however, the naming conventions for the `CurrentCellRef` methods
are a bit confusing at this point, so rename them.

## Bigger Picture

This my sneaky way of introducing the `raw_cell` API as part of a
smaller PR, since that API will be needed for converting a local `Vc` to
a resolved `Vc`. That's a similar problem of needing to reuse a
`SharedReference` along with `VcCellMode` semantics.

## Testing Instructions

```
cargo nextest r -p turbo-tasks -p turbo-tasks-memory
```
ForsakenHarmony pushed a commit to vercel/next.js that referenced this pull request Aug 14, 2024
…e::raw_cell` API (#68467)

*This is a migrated PR. This was in the turbo repository before the
next.js merge.*
**Migrated From:** vercel/turborepo#8847

## Description

More fixes to `ReadRef` on top of
vercel/turborepo#8845. There's a bit of a cascade of
changes that needed to happen here:

- `ReadRef::cell` should actually use `VcCellMode` so that it supports
new/shared semantics correctly.
- ... however, `VcCellMode` needs to expose an API (`raw_cell`) for
working with `SharedReference` so that we can reuse the
`SharedReference`/`Arc` inside of `ReadRef` instead of cloning the data
inside of it.
- ... however, `CurrentCellRef` needs to expose a `compare_and_update`
method that works for `SharedReference`
(`compare_and_update_with_shared_reference`).
- ... however, the naming conventions for the `CurrentCellRef` methods
are a bit confusing at this point, so rename them.

## Bigger Picture

This my sneaky way of introducing the `raw_cell` API as part of a
smaller PR, since that API will be needed for converting a local `Vc` to
a resolved `Vc`. That's a similar problem of needing to reuse a
`SharedReference` along with `VcCellMode` semantics.

## Testing Instructions

```
cargo nextest r -p turbo-tasks -p turbo-tasks-memory
```
ForsakenHarmony pushed a commit to vercel/next.js that referenced this pull request Aug 15, 2024
…e::raw_cell` API (#68467)

*This is a migrated PR. This was in the turbo repository before the
next.js merge.*
**Migrated From:** vercel/turborepo#8847

## Description

More fixes to `ReadRef` on top of
vercel/turborepo#8845. There's a bit of a cascade of
changes that needed to happen here:

- `ReadRef::cell` should actually use `VcCellMode` so that it supports
new/shared semantics correctly.
- ... however, `VcCellMode` needs to expose an API (`raw_cell`) for
working with `SharedReference` so that we can reuse the
`SharedReference`/`Arc` inside of `ReadRef` instead of cloning the data
inside of it.
- ... however, `CurrentCellRef` needs to expose a `compare_and_update`
method that works for `SharedReference`
(`compare_and_update_with_shared_reference`).
- ... however, the naming conventions for the `CurrentCellRef` methods
are a bit confusing at this point, so rename them.

## Bigger Picture

This my sneaky way of introducing the `raw_cell` API as part of a
smaller PR, since that API will be needed for converting a local `Vc` to
a resolved `Vc`. That's a similar problem of needing to reuse a
`SharedReference` along with `VcCellMode` semantics.

## Testing Instructions

```
cargo nextest r -p turbo-tasks -p turbo-tasks-memory
```
ForsakenHarmony pushed a commit to vercel/next.js that referenced this pull request Aug 16, 2024
…e::raw_cell` API (#68467)

*This is a migrated PR. This was in the turbo repository before the
next.js merge.*
**Migrated From:** vercel/turborepo#8847

## Description

More fixes to `ReadRef` on top of
vercel/turborepo#8845. There's a bit of a cascade of
changes that needed to happen here:

- `ReadRef::cell` should actually use `VcCellMode` so that it supports
new/shared semantics correctly.
- ... however, `VcCellMode` needs to expose an API (`raw_cell`) for
working with `SharedReference` so that we can reuse the
`SharedReference`/`Arc` inside of `ReadRef` instead of cloning the data
inside of it.
- ... however, `CurrentCellRef` needs to expose a `compare_and_update`
method that works for `SharedReference`
(`compare_and_update_with_shared_reference`).
- ... however, the naming conventions for the `CurrentCellRef` methods
are a bit confusing at this point, so rename them.

## Bigger Picture

This my sneaky way of introducing the `raw_cell` API as part of a
smaller PR, since that API will be needed for converting a local `Vc` to
a resolved `Vc`. That's a similar problem of needing to reuse a
`SharedReference` along with `VcCellMode` semantics.

## Testing Instructions

```
cargo nextest r -p turbo-tasks -p turbo-tasks-memory
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants