Skip to content

Commit caf7925

Browse files
committed
persistent caching prototype
1 parent b121ee4 commit caf7925

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+2690
-103
lines changed

Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ parking_lot = "0.12"
2323
portable-atomic = "1"
2424
rustc-hash = "2"
2525
smallvec = "1"
26+
thin-vec = { version = "0.2.14", features = ["serde"] }
2627
tracing = { version = "0.1", default-features = false, features = ["std"] }
2728

2829
# Automatic ingredient registration.
@@ -33,10 +34,13 @@ rayon = { version = "1.10.0", optional = true }
3334

3435
# Stuff we want Update impls for by default
3536
compact_str = { version = "0.9", optional = true }
36-
thin-vec = "0.2.14"
3737

3838
shuttle = { version = "0.8.1", optional = true }
3939

40+
# Persistent caching
41+
erased-serde = "0.4.6"
42+
serde = { version = "1.0.219", features = ["derive"] }
43+
4044
[features]
4145
default = ["salsa_unstable", "rayon", "macros", "inventory", "accumulator"]
4246
inventory = ["dep:inventory"]
@@ -68,6 +72,7 @@ expect-test = "1.5.1"
6872
rustversion = "1.0"
6973
test-log = { version = "0.2.18", features = ["trace"] }
7074
trybuild = "1.0"
75+
serde_json = "1.0.140"
7176

7277
[target.'cfg(all(not(target_os = "windows"), not(target_os = "openbsd"), any(target_arch = "x86_64", target_arch = "aarch64", target_arch = "powerpc64")))'.dev-dependencies]
7378
tikv-jemallocator = "0.6.0"

components/salsa-macro-rules/src/setup_input_struct.rs

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,12 @@ macro_rules! setup_input_struct {
5353
// The function used to implement `C::heap_size`.
5454
heap_size_fn: $($heap_size_fn:path)?,
5555

56+
// If `true`, a `serde_fn` has been provided.
57+
serializable: $serializable:tt,
58+
59+
// The path to the `serialize` and `deserialize` functions for the value's fields.
60+
serde_fn: $(($serialize_fn:path, $deserialize_fn:path))?,
61+
5662
// Annoyingly macro-rules hygiene does not extend to items defined in the macro.
5763
// We have the procedural macro generate names for those items that are
5864
// not used elsewhere in the user's code.
@@ -93,6 +99,9 @@ macro_rules! setup_input_struct {
9399
};
94100
const DEBUG_NAME: &'static str = stringify!($Struct);
95101
const FIELD_DEBUG_NAMES: &'static [&'static str] = &[$(stringify!($field_id)),*];
102+
103+
const SERIALIZABLE: bool = $serializable;
104+
96105
type Singleton = $zalsa::macro_if! {if $is_singleton {$zalsa::input::Singleton} else {$zalsa::input::NotSingleton}};
97106

98107
type Struct = $Struct;
@@ -107,6 +116,32 @@ macro_rules! setup_input_struct {
107116
Some($heap_size_fn(value))
108117
}
109118
)?
119+
120+
fn serialize<S: $zalsa::serde::Serializer>(
121+
fields: &Self::Fields,
122+
serializer: S,
123+
) -> Result<S::Ok, S::Error> {
124+
$zalsa::macro_if! {
125+
if $serializable {
126+
$($serialize_fn(fields, serializer))?
127+
} else {
128+
panic!("attempted to serialize value not marked with `serialize` attribute")
129+
}
130+
}
131+
}
132+
133+
fn deserialize<'de, D: $zalsa::serde::Deserializer<'de>>(
134+
deserializer: D,
135+
) -> Result<Self::Fields, D::Error> {
136+
$zalsa::macro_if! {
137+
if $serializable {
138+
$($deserialize_fn(deserializer))?
139+
} else {
140+
panic!("attempted to deserialize value not marked with `serialize` attribute")
141+
}
142+
}
143+
}
144+
110145
}
111146

112147
impl $Configuration {
@@ -174,6 +209,13 @@ macro_rules! setup_input_struct {
174209
aux.lookup_jar_by_type::<$zalsa_struct::JarImpl<$Configuration>>().into()
175210
}
176211

212+
fn instances(
213+
zalsa: &$zalsa::Zalsa
214+
) -> impl Iterator<Item = $zalsa::DatabaseKeyIndex> + '_ {
215+
let ingredient_index = zalsa.lookup_jar_by_type::<$zalsa_struct::JarImpl<$Configuration>>();
216+
<$Configuration>::ingredient_(zalsa).instances(zalsa)
217+
}
218+
177219
#[inline]
178220
fn cast(id: $zalsa::Id, type_id: $zalsa::TypeId) -> $zalsa::Option<Self> {
179221
if type_id == $zalsa::TypeId::of::<$Struct>() {
@@ -194,6 +236,26 @@ macro_rules! setup_input_struct {
194236
}
195237
}
196238

239+
$zalsa::macro_if! { $serializable =>
240+
impl $zalsa::serde::Serialize for $Struct {
241+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
242+
where
243+
S: $zalsa::serde::Serializer,
244+
{
245+
$zalsa::serde::Serialize::serialize(&$zalsa::AsId::as_id(self), serializer)
246+
}
247+
}
248+
249+
impl<'de> $zalsa::serde::Deserialize<'de> for $Struct {
250+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
251+
where
252+
D: $zalsa::serde::Deserializer<'de>,
253+
{
254+
let id = $zalsa::Id::deserialize(deserializer)?;
255+
Ok($zalsa::FromId::from_id(id))
256+
}
257+
}
258+
}
197259
impl $Struct {
198260
#[inline]
199261
pub fn $new_fn<$Db>(db: &$Db, $($required_field_id: $required_field_ty),*) -> Self

components/salsa-macro-rules/src/setup_interned_struct.rs

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,12 @@ macro_rules! setup_interned_struct {
6969
// The function used to implement `C::heap_size`.
7070
heap_size_fn: $($heap_size_fn:path)?,
7171

72+
// If `true`, a `serde_fn` has been provided.
73+
serializable: $serializable:tt,
74+
75+
// The path to the `serialize` and `deserialize` functions for the value's fields.
76+
serde_fn: $(($serialize_fn:path, $deserialize_fn:path))?,
77+
7278
// Annoyingly macro-rules hygiene does not extend to items defined in the macro.
7379
// We have the procedural macro generate names for those items that are
7480
// not used elsewhere in the user's code.
@@ -144,9 +150,12 @@ macro_rules! setup_interned_struct {
144150
line: line!(),
145151
};
146152
const DEBUG_NAME: &'static str = stringify!($Struct);
153+
const SERIALIZABLE: bool = $serializable;
154+
147155
$(
148156
const REVISIONS: ::core::num::NonZeroUsize = ::core::num::NonZeroUsize::new($revisions).unwrap();
149157
)?
158+
150159
type Fields<'a> = $StructDataIdent<'a>;
151160
type Struct<'db> = $Struct< $($db_lt_arg)? >;
152161

@@ -155,11 +164,35 @@ macro_rules! setup_interned_struct {
155164
Some($heap_size_fn(value))
156165
}
157166
)?
167+
168+
fn serialize<S: $zalsa::serde::Serializer>(
169+
fields: &Self::Fields<'_>,
170+
serializer: S,
171+
) -> Result<S::Ok, S::Error> {
172+
$zalsa::macro_if! {
173+
if $serializable {
174+
$($serialize_fn(fields, serializer))?
175+
} else {
176+
panic!("attempted to serialize value not marked with `serialize` attribute")
177+
}
178+
}
179+
}
180+
181+
fn deserialize<'de, D: $zalsa::serde::Deserializer<'de>>(
182+
deserializer: D,
183+
) -> Result<Self::Fields<'static>, D::Error> {
184+
$zalsa::macro_if! {
185+
if $serializable {
186+
$($deserialize_fn(deserializer))?
187+
} else {
188+
panic!("attempted to deserialize value not marked with `serialize` attribute")
189+
}
190+
}
191+
}
158192
}
159193

160194
impl $Configuration {
161-
pub fn ingredient(zalsa: &$zalsa::Zalsa) -> &$zalsa_struct::IngredientImpl<Self>
162-
{
195+
pub fn ingredient(zalsa: &$zalsa::Zalsa) -> &$zalsa_struct::IngredientImpl<Self> {
163196
static CACHE: $zalsa::IngredientCache<$zalsa_struct::IngredientImpl<$Configuration>> =
164197
$zalsa::IngredientCache::new();
165198

@@ -204,6 +237,13 @@ macro_rules! setup_interned_struct {
204237
aux.lookup_jar_by_type::<$zalsa_struct::JarImpl<$Configuration>>().into()
205238
}
206239

240+
fn instances(
241+
zalsa: &$zalsa::Zalsa
242+
) -> impl Iterator<Item = $zalsa::DatabaseKeyIndex> + '_ {
243+
let ingredient_index = zalsa.lookup_jar_by_type::<$zalsa_struct::JarImpl<$Configuration>>();
244+
<$Configuration>::ingredient(zalsa).instances(zalsa)
245+
}
246+
207247
#[inline]
208248
fn cast(id: $zalsa::Id, type_id: $zalsa::TypeId) -> $zalsa::Option<Self> {
209249
if type_id == $zalsa::TypeId::of::<$Struct>() {
@@ -224,6 +264,28 @@ macro_rules! setup_interned_struct {
224264
}
225265
}
226266

267+
$zalsa::macro_if! { $serializable =>
268+
impl<$($db_lt_arg)?> $zalsa::serde::Serialize for $Struct<$($db_lt_arg)?> {
269+
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
270+
where
271+
S: $zalsa::serde::Serializer,
272+
{
273+
$zalsa::serde::Serialize::serialize(&$zalsa::AsId::as_id(self), serializer)
274+
}
275+
}
276+
277+
impl<'de, $($db_lt_arg)?> $zalsa::serde::Deserialize<'de> for $Struct<$($db_lt_arg)?> {
278+
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
279+
where
280+
D: $zalsa::serde::Deserializer<'de>,
281+
{
282+
let id = $zalsa::Id::deserialize(deserializer)?;
283+
Ok($zalsa::FromId::from_id(id))
284+
}
285+
}
286+
}
287+
288+
227289
unsafe impl< $($db_lt_arg)? > $zalsa::Update for $Struct< $($db_lt_arg)? > {
228290
unsafe fn maybe_update(old_pointer: *mut Self, new_value: Self) -> bool {
229291
if unsafe { *old_pointer } != new_value {

components/salsa-macro-rules/src/setup_tracked_fn.rs

Lines changed: 73 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,9 @@ macro_rules! setup_tracked_fn {
6464
// The return mode for the function, see `salsa_macros::options::Option::returns`
6565
return_mode: $return_mode:tt,
6666

67+
// If true, the return value implements `serde::{Serialize, Deserialize}`.
68+
serializable: $serializable:tt,
69+
6770
assert_return_type_is_update: {$($assert_return_type_is_update:tt)*},
6871

6972
$(self_ty: $self_ty:ty,)?
@@ -122,6 +125,13 @@ macro_rules! setup_tracked_fn {
122125
$zalsa::IngredientIndices::empty()
123126
}
124127

128+
fn instances(
129+
zalsa: &$zalsa::Zalsa
130+
) -> impl Iterator<Item = $zalsa::DatabaseKeyIndex> + '_ {
131+
let ingredient_index = zalsa.lookup_jar_by_type::<$fn_name>().successor(0);
132+
<$Configuration>::intern_ingredient(zalsa).instances(zalsa)
133+
}
134+
125135
#[inline]
126136
fn cast(id: $zalsa::Id, type_id: ::core::any::TypeId) -> Option<Self> {
127137
if type_id == ::core::any::TypeId::of::<$InternedData>() {
@@ -162,13 +172,47 @@ macro_rules! setup_tracked_fn {
162172
line: line!(),
163173
};
164174
const DEBUG_NAME: &'static str = concat!($(stringify!($self_ty), "::",)? stringify!($fn_name), "::interned_arguments");
175+
const SERIALIZABLE: bool = true;
165176

166177
type Fields<$db_lt> = ($($interned_input_ty),*);
167178

168179
type Struct<$db_lt> = $InternedData<$db_lt>;
180+
181+
fn serialize<'db, S: $zalsa::serde::Serializer>(
182+
fields: &Self::Fields<'db>,
183+
serializer: S,
184+
) -> Result<S::Ok, S::Error> {
185+
$zalsa::macro_if! {
186+
if $serializable {
187+
$zalsa::serde::Serialize::serialize(fields, serializer)
188+
} else {
189+
panic!("attempted to serialize value not marked with `serialize` attribute")
190+
}
191+
}
192+
}
193+
194+
fn deserialize<'de, D: $zalsa::serde::Deserializer<'de>>(
195+
deserializer: D,
196+
) -> Result<Self::Fields<'static>, D::Error> {
197+
$zalsa::macro_if! {
198+
if $serializable {
199+
$zalsa::serde::Deserialize::deserialize(deserializer)
200+
} else {
201+
panic!("attempted to deserialize value not marked with `serialize` attribute")
202+
}
203+
}
204+
}
169205
}
170206
} else {
171207
type $InternedData<$db_lt> = ($($interned_input_ty),*);
208+
209+
$zalsa::macro_if! { $serializable =>
210+
const fn query_input_is_serializable<T: $zalsa::serde::Serialize + $zalsa::serde::de::DeserializeOwned>() {}
211+
212+
fn assert_query_input_is_serializable<$db_lt>() {
213+
query_input_is_serializable::<$($interned_input_ty),*>();
214+
}
215+
}
172216
}
173217
}
174218

@@ -200,11 +244,11 @@ macro_rules! setup_tracked_fn {
200244

201245
$zalsa::macro_if! { $needs_interner =>
202246
fn intern_ingredient(
203-
db: &dyn $Db,
247+
zalsa: &$zalsa::Zalsa,
204248
) -> &$zalsa::interned::IngredientImpl<$Configuration> {
205-
let zalsa = db.zalsa();
206249
Self::intern_ingredient_(zalsa)
207250
}
251+
208252
#[inline]
209253
fn intern_ingredient_<'z>(
210254
zalsa: &'z $zalsa::Zalsa
@@ -226,6 +270,7 @@ macro_rules! setup_tracked_fn {
226270
line: line!(),
227271
};
228272
const DEBUG_NAME: &'static str = concat!($(stringify!($self_ty), "::", )? stringify!($fn_name));
273+
const SERIALIZABLE: bool = $serializable;
229274

230275
type DbView = dyn $Db;
231276

@@ -275,6 +320,31 @@ macro_rules! setup_tracked_fn {
275320
}
276321
}
277322
}
323+
324+
fn serialize<'db, S: $zalsa::serde::Serializer>(
325+
value: &Self::Output<'db>,
326+
serializer: S,
327+
) -> Result<S::Ok, S::Error> {
328+
$zalsa::macro_if! {
329+
if $serializable {
330+
$zalsa::serde::Serialize::serialize(value, serializer)
331+
} else {
332+
panic!("attempted to serialize value not marked with `serialize` attribute")
333+
}
334+
}
335+
}
336+
337+
fn deserialize<'de, D: $zalsa::serde::Deserializer<'de>>(
338+
deserializer: D,
339+
) -> Result<Self::Output<'static>, D::Error> {
340+
$zalsa::macro_if! {
341+
if $serializable {
342+
$zalsa::serde::Deserialize::deserialize(deserializer)
343+
} else {
344+
panic!("attempted to deserialize value not marked with `serialize` attribute")
345+
}
346+
}
347+
}
278348
}
279349

280350
#[allow(non_local_definitions)]
@@ -352,7 +422,7 @@ macro_rules! setup_tracked_fn {
352422
let key = $zalsa::macro_if! {
353423
if $needs_interner {{
354424
let (zalsa, zalsa_local) = $db.zalsas();
355-
$Configuration::intern_ingredient($db).intern_id(zalsa, zalsa_local, ($($input_id),*), |_, data| data)
425+
$Configuration::intern_ingredient(zalsa).intern_id(zalsa, zalsa_local, ($($input_id),*), |_, data| data)
356426
}} else {
357427
$zalsa::AsId::as_id(&($($input_id),*))
358428
}

0 commit comments

Comments
 (0)