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

introduce slots #176

Merged
merged 16 commits into from
Jul 2, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,20 @@ description = "A generic framework for on-demand, incrementalized computation (e
readme = "README.md"

[dependencies]
crossbeam = "0.7.1"
derive-new = "0.5.5"
rustc-hash = "1.0"
parking_lot = "0.8.0"
lock_api = "0.2.0"
indexmap = "1.0.1"
lock_api = "0.2.0"
log = "0.4.5"
parking_lot = "0.8.0"
rustc-hash = "1.0"
smallvec = "0.6.5"
salsa-macros = { version = "0.13.0", path = "components/salsa-macros" }
linked-hash-map = "0.5.2"
rand = "0.6"

[dev-dependencies]
diff = "0.1.0"
env_logger = "0.5.13"
rand = "0.5.5"
linked-hash-map = "0.5.2"

[workspace]
30 changes: 9 additions & 21 deletions components/salsa-macros/src/database_storage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -114,11 +114,20 @@ pub(crate) fn database(args: TokenStream, input: TokenStream) -> TokenStream {
}
});

// Create a tuple (D1, D2, ...) where Di is the data for a given query group.
let mut database_data = vec![];
for QueryGroup { group_path } in query_groups {
database_data.push(quote! {
<#group_path as salsa::plumbing::QueryGroup<#database_name>>::GroupData
});
}

//
output.extend(quote! {
impl salsa::plumbing::DatabaseStorageTypes for #database_name {
type DatabaseKey = __SalsaDatabaseKey;
type DatabaseStorage = __SalsaDatabaseStorage;
type DatabaseData = (#(#database_data),*);
}
});

Expand All @@ -144,29 +153,8 @@ pub(crate) fn database(args: TokenStream, input: TokenStream) -> TokenStream {
}
});

let mut for_each_query_desc = proc_macro2::TokenStream::new();
for query_group in query_groups {
let group_name = query_group.name();
for_each_query_desc.extend(quote! {
__SalsaDatabaseKeyKind::#group_name(database_key) => database_key.maybe_changed_since(
db,
self,
revision,
),
});
}

output.extend(quote! {
impl salsa::plumbing::DatabaseKey<#database_name> for __SalsaDatabaseKey {
fn maybe_changed_since(
&self,
db: &#database_name,
revision: salsa::plumbing::Revision,
) -> bool {
match &self.kind {
#for_each_query_desc
}
}
}
});

Expand Down
61 changes: 21 additions & 40 deletions components/salsa-macros/src/query_group.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ use proc_macro2::Span;
use quote::ToTokens;
use syn::punctuated::Punctuated;
use syn::{
parse_macro_input, parse_quote, Attribute, FnArg, Ident, ItemTrait, Path,
ReturnType, Token, TraitBound, TraitBoundModifier, TraitItem, Type, TypeParamBound,
parse_macro_input, parse_quote, Attribute, FnArg, Ident, ItemTrait, Path, ReturnType, Token,
TraitBound, TraitBoundModifier, TraitItem, Type, TypeParamBound,
};

/// Implementation for `[salsa::query_group]` decorator.
Expand Down Expand Up @@ -184,7 +184,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
let mut query_fn_declarations = proc_macro2::TokenStream::new();
let mut query_fn_definitions = proc_macro2::TokenStream::new();
let mut query_descriptor_variants = proc_macro2::TokenStream::new();
let mut query_descriptor_maybe_change = proc_macro2::TokenStream::new();
let mut group_data_elements = vec![];
let mut storage_fields = proc_macro2::TokenStream::new();
let mut storage_defaults = proc_macro2::TokenStream::new();
for query in &queries {
Expand Down Expand Up @@ -226,17 +226,21 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
let set_constant_fn_name =
Ident::new(&format!("set_constant_{}", fn_name), fn_name.span());

let set_fn_docs = format!("
let set_fn_docs = format!(
"
Set the value of the `{fn_name}` input.

See `{fn_name}` for details.

*Note:* Setting values will trigger cancellation
of any ongoing queries; this method blocks until
those queries have been cancelled.
", fn_name = fn_name);
",
fn_name = fn_name
);

let set_constant_fn_docs = format!("
let set_constant_fn_docs = format!(
"
Set the value of the `{fn_name}` input and promise
that its value will never change again.

Expand All @@ -245,7 +249,9 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
*Note:* Setting values will trigger cancellation
of any ongoing queries; this method blocks until
those queries have been cancelled.
", fn_name = fn_name);
",
fn_name = fn_name
);

query_fn_declarations.extend(quote! {
# [doc = #set_fn_docs]
Expand All @@ -272,20 +278,9 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
#fn_name((#(#keys),*)),
});

// A variant for the group descriptor below
query_descriptor_maybe_change.extend(quote! {
#group_key::#fn_name(key) => {
let group_storage: &#group_storage<DB__> = salsa::plumbing::HasQueryGroup::group_storage(db);
let storage = &group_storage.#fn_name;

<_ as salsa::plumbing::QueryStorageOps<DB__, #qt>>::maybe_changed_since(
storage,
db,
revision,
key,
db_descriptor,
)
}
// Entry for the query group data tuple
group_data_elements.push(quote! {
(#(#keys,)* #value)
});

// A field for the storage struct
Expand Down Expand Up @@ -321,6 +316,7 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
{
type GroupStorage = #group_storage<DB__>;
type GroupKey = #group_key;
type GroupData = (#(#group_data_elements),*);
}
});

Expand Down Expand Up @@ -371,7 +367,9 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
#[derive(Default, Debug)]
#trait_vis struct #qt;

impl<#db> salsa::Query<#db> for #qt
// Unsafe proof obligation: that our key/value are a part
// of the `GroupData`.
unsafe impl<#db> salsa::Query<#db> for #qt
where
DB: #trait_name + #requires,
DB: salsa::plumbing::HasQueryGroup<#group_struct>,
Expand Down Expand Up @@ -429,23 +427,6 @@ pub(crate) fn query_group(args: TokenStream, input: TokenStream) -> TokenStream
#trait_vis enum #group_key {
#query_descriptor_variants
}

impl #group_key {
#trait_vis fn maybe_changed_since<DB__>(
&self,
db: &DB__,
db_descriptor: &<DB__ as salsa::plumbing::DatabaseStorageTypes>::DatabaseKey,
revision: salsa::plumbing::Revision,
) -> bool
where
DB__: #trait_name + #requires,
DB__: salsa::plumbing::HasQueryGroup<#group_struct>,
{
match self {
#query_descriptor_maybe_change
}
}
}
});

let mut for_each_ops = proc_macro2::TokenStream::new();
Expand Down Expand Up @@ -584,7 +565,7 @@ enum QueryStorage {
impl QueryStorage {
fn needs_query_function(&self) -> bool {
match self {
| QueryStorage::Input
QueryStorage::Input
| QueryStorage::Interned
| QueryStorage::InternedLookup { .. }
| QueryStorage::Transparent => false,
Expand Down
64 changes: 64 additions & 0 deletions src/dependency.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
use crate::runtime::Revision;
use crate::Database;
use std::fmt::Debug;
use std::hash::Hasher;
use std::sync::Arc;

/// Unsafe proof obligations:
///
/// - If `DB::DatabaseData: Send + Sync`, then `Self: Send + Sync`
/// - If `DB: 'static` and `DB::DatabaseData: 'static`, then `Self: 'static`
pub(crate) unsafe trait DatabaseSlot<DB: Database>: Debug {
/// Returns true if the value of this query may have changed since
/// the given revision.
fn maybe_changed_since(&self, db: &DB, revision: Revision) -> bool;
}

pub(crate) struct Dependency<DB: Database> {
slot: Arc<dyn DatabaseSlot<DB> + Send + Sync>,
phantom: std::marker::PhantomData<Arc<DB::DatabaseData>>,
}

impl<DB: Database> Dependency<DB> {
pub(crate) fn new(slot: Arc<dyn DatabaseSlot<DB> + '_>) -> Self {
// Unsafety note: It is safe to 'pretend' the trait object is
// Send+Sync+'static because the phantom-data will reflect the
// reality.
let slot: Arc<dyn DatabaseSlot<DB> + Send + Sync> = unsafe { std::mem::transmute(slot) };
Self {
slot,
phantom: std::marker::PhantomData,
}
}

fn raw_slot(&self) -> *const dyn DatabaseSlot<DB> {
&*self.slot
}

pub(crate) fn maybe_changed_since(&self, db: &DB, revision: Revision) -> bool {
self.slot.maybe_changed_since(db, revision)
}
}

impl<DB: Database> std::hash::Hash for Dependency<DB> {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
self.raw_slot().hash(state)
}
}

impl<DB: Database> std::cmp::PartialEq for Dependency<DB> {
fn eq(&self, other: &Self) -> bool {
self.raw_slot() == other.raw_slot()
}
}

impl<DB: Database> std::cmp::Eq for Dependency<DB> {}

impl<DB: Database> std::fmt::Debug for Dependency<DB> {
fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
self.slot.fmt(fmt)
}
}
Loading