Skip to content

Commit 7d20b17

Browse files
committed
remove borrow checks from ZalsaLocal
1 parent f3dc2f3 commit 7d20b17

File tree

4 files changed

+253
-168
lines changed

4 files changed

+253
-168
lines changed

src/function/fetch.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ where
2020
let _span = crate::tracing::debug_span!("fetch", query = ?database_key_index).entered();
2121

2222
let memo = self.refresh_memo(db, zalsa, zalsa_local, id);
23+
2324
// SAFETY: We just refreshed the memo so it is guaranteed to contain a value now.
2425
let memo_value = unsafe { memo.value.as_ref().unwrap_unchecked() };
2526

@@ -162,13 +163,16 @@ where
162163
}
163164
// no provisional value; create/insert/return initial provisional value
164165
return match C::CYCLE_STRATEGY {
165-
CycleRecoveryStrategy::Panic => zalsa_local.with_query_stack(|stack| {
166-
panic!(
167-
"dependency graph cycle when querying {database_key_index:#?}, \
166+
// SAFETY: We do not access the query stack reentrantly.
167+
CycleRecoveryStrategy::Panic => unsafe {
168+
zalsa_local.with_query_stack_unchecked(|stack| {
169+
panic!(
170+
"dependency graph cycle when querying {database_key_index:#?}, \
168171
set cycle_fn/cycle_initial to fixpoint iterate.\n\
169172
Query stack:\n{stack:#?}",
170-
);
171-
}),
173+
);
174+
})
175+
},
172176
CycleRecoveryStrategy::Fixpoint => {
173177
crate::tracing::debug!(
174178
"hit cycle at {database_key_index:#?}, \

src/function/maybe_changed_after.rs

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -108,13 +108,16 @@ where
108108
return None;
109109
}
110110
ClaimResult::Cycle { .. } => match C::CYCLE_STRATEGY {
111-
CycleRecoveryStrategy::Panic => db.zalsa_local().with_query_stack(|stack| {
112-
panic!(
113-
"dependency graph cycle when validating {database_key_index:#?}, \
111+
// SAFETY: We do not access the query stack reentrantly.
112+
CycleRecoveryStrategy::Panic => unsafe {
113+
db.zalsa_local().with_query_stack_unchecked(|stack| {
114+
panic!(
115+
"dependency graph cycle when validating {database_key_index:#?}, \
114116
set cycle_fn/cycle_initial to fixpoint iterate.\n\
115117
Query stack:\n{stack:#?}",
116-
);
117-
}),
118+
);
119+
})
120+
},
118121
CycleRecoveryStrategy::FallbackImmediate => {
119122
return Some(VerifyResult::unchanged());
120123
}
@@ -336,32 +339,38 @@ where
336339
return true;
337340
}
338341

339-
zalsa_local.with_query_stack(|stack| {
340-
cycle_heads.iter().all(|cycle_head| {
341-
stack
342-
.iter()
343-
.rev()
344-
.find(|query| query.database_key_index == cycle_head.database_key_index)
345-
.map(|query| query.iteration_count())
346-
.or_else(|| {
347-
// If this is a cycle head is owned by another thread that is blocked by this ingredient,
348-
// check if it has the same iteration count.
349-
let ingredient = zalsa
350-
.lookup_ingredient(cycle_head.database_key_index.ingredient_index());
351-
let wait_result =
352-
ingredient.wait_for(zalsa, cycle_head.database_key_index.key_index());
353-
354-
if !wait_result.is_cycle_with_other_thread() {
355-
return None;
356-
}
342+
// SAFETY: We do not access the query stack reentrantly.
343+
unsafe {
344+
zalsa_local.with_query_stack_unchecked(|stack| {
345+
cycle_heads.iter().all(|cycle_head| {
346+
stack
347+
.iter()
348+
.rev()
349+
.find(|query| query.database_key_index == cycle_head.database_key_index)
350+
.map(|query| query.iteration_count())
351+
.or_else(|| {
352+
// If this is a cycle head is owned by another thread that is blocked by this ingredient,
353+
// check if it has the same iteration count.
354+
let ingredient = zalsa.lookup_ingredient(
355+
cycle_head.database_key_index.ingredient_index(),
356+
);
357+
let wait_result = ingredient
358+
.wait_for(zalsa, cycle_head.database_key_index.key_index());
359+
360+
if !wait_result.is_cycle_with_other_thread() {
361+
return None;
362+
}
357363

358-
let provisional_status = ingredient
359-
.provisional_status(zalsa, cycle_head.database_key_index.key_index())?;
360-
provisional_status.iteration()
361-
})
362-
== Some(cycle_head.iteration_count)
364+
let provisional_status = ingredient.provisional_status(
365+
zalsa,
366+
cycle_head.database_key_index.key_index(),
367+
)?;
368+
provisional_status.iteration()
369+
})
370+
== Some(cycle_head.iteration_count)
371+
})
363372
})
364-
})
373+
}
365374
}
366375

367376
/// VerifyResult::Unchanged if the memo's value and `changed_at` time is up-to-date in the

src/function/memo.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -236,14 +236,17 @@ impl<'db, C: Configuration> Memo<'db, C> {
236236
return true;
237237
}
238238

239-
zalsa_local.with_query_stack(|stack| {
240-
cycle_heads.iter().all(|cycle_head| {
241-
stack
242-
.iter()
243-
.rev()
244-
.any(|query| query.database_key_index == cycle_head.database_key_index)
239+
// SAFETY: We do not access the query stack reentrantly.
240+
unsafe {
241+
zalsa_local.with_query_stack_unchecked(|stack| {
242+
cycle_heads.iter().all(|cycle_head| {
243+
stack
244+
.iter()
245+
.rev()
246+
.any(|query| query.database_key_index == cycle_head.database_key_index)
247+
})
245248
})
246-
})
249+
}
247250
}
248251

249252
/// Cycle heads that should be propagated to dependent queries.

0 commit comments

Comments
 (0)