mirror of
https://github.com/salsa-rs/salsa.git
synced 2025-01-15 01:39:25 +00:00
Revert "track both inputs/outputs for each query"
This reverts commit 49ccac5d3d
.
This commit is contained in:
parent
afefcdf335
commit
cb0b53caa7
16 changed files with 46 additions and 92 deletions
|
@ -136,7 +136,7 @@ fn has_jars_dyn_impl(input: &syn::ItemStruct, storage: &syn::Ident) -> syn::Item
|
|||
fn inputs(
|
||||
&self,
|
||||
index: salsa::DatabaseKeyIndex,
|
||||
) -> Option<salsa::runtime::local_state::QueryEdges> {
|
||||
) -> Option<salsa::runtime::local_state::QueryInputs> {
|
||||
let ingredient = self.#storage.ingredient(index.ingredient_index());
|
||||
ingredient.inputs(index.key_index())
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
|||
hash::FxDashMap,
|
||||
ingredient::{Ingredient, MutIngredient},
|
||||
key::DependencyIndex,
|
||||
runtime::{local_state::QueryEdges, StampedValue},
|
||||
runtime::{local_state::QueryInputs, StampedValue},
|
||||
storage::HasJar,
|
||||
DatabaseKeyIndex, Durability, IngredientIndex, Revision, Runtime,
|
||||
};
|
||||
|
@ -78,7 +78,7 @@ where
|
|||
CycleRecoveryStrategy::Panic
|
||||
}
|
||||
|
||||
fn inputs(&self, _key_index: crate::Id) -> Option<QueryEdges> {
|
||||
fn inputs(&self, _key_index: crate::Id) -> Option<QueryInputs> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::{
|
|||
ingredient::MutIngredient,
|
||||
jar::Jar,
|
||||
key::{DatabaseKeyIndex, DependencyIndex},
|
||||
runtime::local_state::QueryEdges,
|
||||
runtime::local_state::QueryInputs,
|
||||
salsa_struct::SalsaStructInDb,
|
||||
Cycle, DbWithJar, Id, Revision,
|
||||
};
|
||||
|
@ -198,7 +198,7 @@ where
|
|||
C::CYCLE_STRATEGY
|
||||
}
|
||||
|
||||
fn inputs(&self, key_index: Id) -> Option<QueryEdges> {
|
||||
fn inputs(&self, key_index: Id) -> Option<QueryInputs> {
|
||||
let key = C::key_from_id(key_index);
|
||||
self.inputs(key)
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crate::{
|
||||
hash::FxHashSet,
|
||||
key::DependencyIndex,
|
||||
runtime::local_state::QueryEdges,
|
||||
runtime::local_state::QueryInputs,
|
||||
storage::{HasJar, HasJarsDyn},
|
||||
Database, DatabaseKeyIndex,
|
||||
};
|
||||
|
@ -55,7 +55,7 @@ impl Stack {
|
|||
self.v.pop()
|
||||
}
|
||||
|
||||
fn extend(&mut self, inputs: Option<QueryEdges>) {
|
||||
fn extend(&mut self, inputs: Option<QueryInputs>) {
|
||||
let inputs = match inputs {
|
||||
None => return,
|
||||
Some(v) => v,
|
||||
|
@ -64,7 +64,7 @@ impl Stack {
|
|||
for DependencyIndex {
|
||||
ingredient_index,
|
||||
key_index,
|
||||
} in inputs.inputs().iter().copied()
|
||||
} in inputs.tracked.iter().copied()
|
||||
{
|
||||
if let Some(key_index) = key_index {
|
||||
let i = DatabaseKeyIndex {
|
||||
|
|
|
@ -93,7 +93,7 @@ where
|
|||
if let Some(memo) = self.memo_map.get(key) {
|
||||
// Careful: we can't evict memos with untracked inputs
|
||||
// as their values cannot be reconstructed.
|
||||
if memo.revisions.edges.untracked {
|
||||
if memo.revisions.inputs.untracked {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use crate::runtime::local_state::QueryEdges;
|
||||
use crate::runtime::local_state::QueryInputs;
|
||||
|
||||
use super::{Configuration, FunctionIngredient};
|
||||
|
||||
|
@ -6,7 +6,7 @@ impl<C> FunctionIngredient<C>
|
|||
where
|
||||
C: Configuration,
|
||||
{
|
||||
pub(super) fn inputs(&self, key: C::Key) -> Option<QueryEdges> {
|
||||
self.memo_map.get(key).map(|m| m.revisions.edges.clone())
|
||||
pub(super) fn inputs(&self, key: C::Key) -> Option<QueryInputs> {
|
||||
self.memo_map.get(key).map(|m| m.revisions.inputs.clone())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -158,13 +158,13 @@ where
|
|||
return true;
|
||||
}
|
||||
|
||||
if old_memo.revisions.edges.untracked {
|
||||
if old_memo.revisions.inputs.untracked {
|
||||
// Untracked inputs? Have to assume that it changed.
|
||||
return false;
|
||||
}
|
||||
|
||||
let last_verified_at = old_memo.verified_at.load();
|
||||
for &input in old_memo.revisions.edges.inputs().iter() {
|
||||
for &input in old_memo.revisions.inputs.tracked.iter() {
|
||||
if db.maybe_changed_after(input, last_verified_at) {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
use crossbeam::atomic::AtomicCell;
|
||||
|
||||
use crate::{
|
||||
runtime::local_state::{QueryEdges, QueryRevisions},
|
||||
runtime::local_state::{QueryInputs, QueryRevisions},
|
||||
tracked_struct::TrackedStructInDb,
|
||||
Database,
|
||||
};
|
||||
|
@ -49,17 +49,16 @@ where
|
|||
//
|
||||
// - a result that is verified in the current revision, because it was set, which will use the set value
|
||||
// - a result that is NOT verified and has untracked inputs, which will re-execute (and likely panic)
|
||||
let edges = QueryEdges {
|
||||
let inputs = QueryInputs {
|
||||
untracked: false,
|
||||
separator: 0,
|
||||
input_outputs: runtime.empty_dependencies(),
|
||||
tracked: runtime.empty_dependencies(),
|
||||
};
|
||||
|
||||
let revision = runtime.current_revision();
|
||||
let mut revisions = QueryRevisions {
|
||||
changed_at: current_deps.changed_at,
|
||||
durability: current_deps.durability,
|
||||
edges,
|
||||
inputs,
|
||||
};
|
||||
|
||||
if let Some(old_memo) = self.memo_map.get(key) {
|
||||
|
|
|
@ -4,7 +4,7 @@ use crossbeam::atomic::AtomicCell;
|
|||
|
||||
use crate::{
|
||||
durability::Durability,
|
||||
runtime::local_state::{QueryEdges, QueryRevisions},
|
||||
runtime::local_state::{QueryInputs, QueryRevisions},
|
||||
Runtime,
|
||||
};
|
||||
|
||||
|
@ -28,10 +28,9 @@ where
|
|||
revisions: QueryRevisions {
|
||||
changed_at: revision,
|
||||
durability,
|
||||
edges: QueryEdges {
|
||||
inputs: QueryInputs {
|
||||
untracked: false,
|
||||
separator: 0,
|
||||
input_outputs: runtime.empty_dependencies(),
|
||||
tracked: runtime.empty_dependencies(),
|
||||
},
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
use crate::{
|
||||
cycle::CycleRecoveryStrategy, key::DependencyIndex, runtime::local_state::QueryEdges, Id,
|
||||
cycle::CycleRecoveryStrategy, key::DependencyIndex, runtime::local_state::QueryInputs, Id,
|
||||
};
|
||||
|
||||
use super::Revision;
|
||||
|
@ -21,7 +21,7 @@ pub trait Ingredient<DB: ?Sized> {
|
|||
fn maybe_changed_after(&self, db: &DB, input: DependencyIndex, revision: Revision) -> bool;
|
||||
|
||||
/// What were the inputs (if any) that were used to create the value at `key_index`.
|
||||
fn inputs(&self, key_index: Id) -> Option<QueryEdges>;
|
||||
fn inputs(&self, key_index: Id) -> Option<QueryInputs>;
|
||||
}
|
||||
|
||||
/// Optional trait for ingredients that wish to be notified when new revisions are
|
||||
|
|
|
@ -2,7 +2,7 @@ use crate::{
|
|||
cycle::CycleRecoveryStrategy,
|
||||
ingredient::Ingredient,
|
||||
key::{DatabaseKeyIndex, DependencyIndex},
|
||||
runtime::{local_state::QueryEdges, Runtime},
|
||||
runtime::{local_state::QueryInputs, Runtime},
|
||||
AsId, IngredientIndex, Revision,
|
||||
};
|
||||
|
||||
|
@ -58,7 +58,7 @@ where
|
|||
CycleRecoveryStrategy::Panic
|
||||
}
|
||||
|
||||
fn inputs(&self, _key_index: crate::Id) -> Option<QueryEdges> {
|
||||
fn inputs(&self, _key_index: crate::Id) -> Option<QueryInputs> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ use std::marker::PhantomData;
|
|||
use crate::durability::Durability;
|
||||
use crate::id::AsId;
|
||||
use crate::key::DependencyIndex;
|
||||
use crate::runtime::local_state::QueryEdges;
|
||||
use crate::runtime::local_state::QueryInputs;
|
||||
use crate::runtime::Runtime;
|
||||
|
||||
use super::hash::FxDashMap;
|
||||
|
@ -194,7 +194,7 @@ where
|
|||
crate::cycle::CycleRecoveryStrategy::Panic
|
||||
}
|
||||
|
||||
fn inputs(&self, _key_index: crate::Id) -> Option<QueryEdges> {
|
||||
fn inputs(&self, _key_index: crate::Id) -> Option<QueryInputs> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,7 +8,7 @@ use crate::{
|
|||
Cycle, Revision, Runtime,
|
||||
};
|
||||
|
||||
use super::local_state::{QueryEdges, QueryRevisions};
|
||||
use super::local_state::{QueryInputs, QueryRevisions};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(super) struct ActiveQuery {
|
||||
|
@ -95,27 +95,18 @@ impl ActiveQuery {
|
|||
}
|
||||
|
||||
pub(crate) fn revisions(&self, runtime: &Runtime) -> QueryRevisions {
|
||||
let separator = u32::try_from(self.dependencies.len()).unwrap();
|
||||
|
||||
let input_outputs = if self.dependencies.is_empty() && self.outputs.is_empty() {
|
||||
runtime.empty_dependencies()
|
||||
} else {
|
||||
self.dependencies
|
||||
.iter()
|
||||
.copied()
|
||||
.chain(self.outputs.iter().map(|&o| o.into()))
|
||||
.collect()
|
||||
};
|
||||
|
||||
let edges = QueryEdges {
|
||||
let inputs = QueryInputs {
|
||||
untracked: self.untracked_read,
|
||||
separator,
|
||||
input_outputs,
|
||||
tracked: if self.dependencies.is_empty() {
|
||||
runtime.empty_dependencies()
|
||||
} else {
|
||||
self.dependencies.iter().copied().collect()
|
||||
},
|
||||
};
|
||||
|
||||
QueryRevisions {
|
||||
changed_at: self.changed_at,
|
||||
edges,
|
||||
inputs,
|
||||
durability: self.durability,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,7 +40,7 @@ pub(crate) struct QueryRevisions {
|
|||
pub(crate) durability: Durability,
|
||||
|
||||
/// The inputs that went into our query, if we are tracking them.
|
||||
pub(crate) edges: QueryEdges,
|
||||
pub(crate) inputs: QueryInputs,
|
||||
}
|
||||
|
||||
impl QueryRevisions {
|
||||
|
@ -53,53 +53,18 @@ impl QueryRevisions {
|
|||
}
|
||||
}
|
||||
|
||||
/// The edges between a memoized value and other queries in the dependency graph.
|
||||
/// These edges include both dependency edges
|
||||
/// e.g., when creating the memoized value for Q0 executed another function Q1)
|
||||
/// and output edges
|
||||
/// (e.g., when Q0 specified the value for another query Q2).
|
||||
/// Every input.
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct QueryEdges {
|
||||
/// The list of outgoing edges from this node.
|
||||
/// This list combines *both* inputs and outputs.
|
||||
/// The inputs are defined from the indices `0..S` where
|
||||
/// `S` is the value of the `separator` field.
|
||||
///
|
||||
/// Note that we always track input dependencies even when there are untracked reads.
|
||||
/// Untracked reads mean that we can't verify values, so we don't use the list of inputs for that,
|
||||
/// but we still use it for finding the transitive inputs to an accumulator.
|
||||
///
|
||||
/// You can access the input/output list via the methods [`inputs`] and [`outputs`] respectively.
|
||||
///
|
||||
/// Important:
|
||||
///
|
||||
/// * The inputs must be in **execution order** for the red-green algorithm to work.
|
||||
/// * The outputs must be in **sorted order** so that we can easily "diff" them between revisions.
|
||||
pub(crate) input_outputs: Arc<[DependencyIndex]>,
|
||||
|
||||
/// The index that separates inputs from outputs in the `tracked` field.
|
||||
pub(crate) separator: u32,
|
||||
pub struct QueryInputs {
|
||||
/// Inputs that are fully known.
|
||||
/// We track these even if there are unknown inputs so that the accumulator code
|
||||
/// can walk all the inputs even for tracked functions that read untracked values.
|
||||
pub(crate) tracked: Arc<[DependencyIndex]>,
|
||||
|
||||
/// Where there any *unknown* inputs?
|
||||
pub(crate) untracked: bool,
|
||||
}
|
||||
|
||||
impl QueryEdges {
|
||||
/// Returns the (tracked) inputs that were executed in computing this memoized value.
|
||||
///
|
||||
/// These will always be in execution order.
|
||||
pub(crate) fn inputs(&self) -> &[DependencyIndex] {
|
||||
&self.input_outputs[0..self.separator as usize]
|
||||
}
|
||||
|
||||
/// Returns the queries whose values were assigned while computing this memoized value.
|
||||
///
|
||||
/// These will always be in sorted order.
|
||||
pub(crate) fn outputs(&self) -> &[DependencyIndex] {
|
||||
&self.input_outputs[self.separator as usize..]
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for LocalState {
|
||||
fn default() -> Self {
|
||||
LocalState {
|
||||
|
|
|
@ -6,7 +6,7 @@ use crate::cycle::CycleRecoveryStrategy;
|
|||
use crate::ingredient::Ingredient;
|
||||
use crate::jar::Jar;
|
||||
use crate::key::DependencyIndex;
|
||||
use crate::runtime::local_state::QueryEdges;
|
||||
use crate::runtime::local_state::QueryInputs;
|
||||
use crate::runtime::Runtime;
|
||||
use crate::{Database, DatabaseKeyIndex, IngredientIndex};
|
||||
|
||||
|
@ -178,7 +178,7 @@ pub trait HasJarsDyn {
|
|||
|
||||
fn cycle_recovery_strategy(&self, input: IngredientIndex) -> CycleRecoveryStrategy;
|
||||
|
||||
fn inputs(&self, input: DatabaseKeyIndex) -> Option<QueryEdges>;
|
||||
fn inputs(&self, input: DatabaseKeyIndex) -> Option<QueryInputs>;
|
||||
}
|
||||
|
||||
pub trait HasIngredientsFor<I>
|
||||
|
|
|
@ -3,7 +3,7 @@ use crate::{
|
|||
ingredient::{Ingredient, MutIngredient},
|
||||
interned::{InternedData, InternedId, InternedIngredient},
|
||||
key::{DatabaseKeyIndex, DependencyIndex},
|
||||
runtime::{local_state::QueryEdges, Runtime},
|
||||
runtime::{local_state::QueryInputs, Runtime},
|
||||
salsa_struct::SalsaStructInDb,
|
||||
Database, IngredientIndex, Revision,
|
||||
};
|
||||
|
@ -114,7 +114,7 @@ where
|
|||
<_ as Ingredient<DB>>::cycle_recovery_strategy(&self.interned)
|
||||
}
|
||||
|
||||
fn inputs(&self, _key_index: crate::Id) -> Option<QueryEdges> {
|
||||
fn inputs(&self, _key_index: crate::Id) -> Option<QueryInputs> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue