Skip to content

Commit 4657ac3

Browse files
committed
Revert "introduce Table and use for interned values"
This reverts commit 9a3111c.
1 parent 9a3111c commit 4657ac3

File tree

7 files changed

+73
-222
lines changed

7 files changed

+73
-222
lines changed

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

+9-9
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ macro_rules! setup_interned_struct {
5252
$(#[$attr])*
5353
#[derive(Copy, Clone, PartialEq, PartialOrd, Eq, Ord, Hash)]
5454
$vis struct $Struct<$db_lt>(
55-
salsa::Id,
55+
std::ptr::NonNull<salsa::plumbing::interned::Value < $Struct<'static> >>,
5656
std::marker::PhantomData < & $db_lt salsa::plumbing::interned::Value < $Struct<'static> > >
5757
);
5858

@@ -66,11 +66,11 @@ macro_rules! setup_interned_struct {
6666
const DEBUG_NAME: &'static str = stringify!($Struct);
6767
type Data<$db_lt> = ($($field_ty,)*);
6868
type Struct<$db_lt> = $Struct<$db_lt>;
69-
fn struct_from_id<'db>(id: salsa::Id) -> Self::Struct<'db> {
70-
$Struct(id, std::marker::PhantomData)
69+
unsafe fn struct_from_raw<'db>(ptr: std::ptr::NonNull<$zalsa_struct::Value<Self>>) -> Self::Struct<'db> {
70+
$Struct(ptr, std::marker::PhantomData)
7171
}
72-
fn deref_struct(s: Self::Struct<'_>) -> salsa::Id {
73-
s.0
72+
fn deref_struct(s: Self::Struct<'_>) -> &$zalsa_struct::Value<Self> {
73+
unsafe { s.0.as_ref() }
7474
}
7575
}
7676

@@ -89,13 +89,13 @@ macro_rules! setup_interned_struct {
8989

9090
impl $zalsa::AsId for $Struct<'_> {
9191
fn as_id(&self) -> salsa::Id {
92-
self.0
92+
unsafe { self.0.as_ref() }.as_id()
9393
}
9494
}
9595

9696
impl<$db_lt> $zalsa::LookupId<$db_lt> for $Struct<$db_lt> {
9797
fn lookup_id(id: salsa::Id, db: &$db_lt dyn $zalsa::Database) -> Self {
98-
Self(id, std::marker::PhantomData)
98+
$Configuration::ingredient(db).interned_value(id)
9999
}
100100
}
101101

@@ -144,7 +144,7 @@ macro_rules! setup_interned_struct {
144144
// FIXME(rust-lang/rust#65991): The `db` argument *should* have the type `dyn Database`
145145
$Db: ?Sized + $zalsa::Database,
146146
{
147-
let fields = $Configuration::ingredient(db).fields(db.as_dyn_database(), self);
147+
let fields = $Configuration::ingredient(db).fields(self);
148148
$zalsa::maybe_clone!(
149149
$field_option,
150150
$field_ty,
@@ -156,7 +156,7 @@ macro_rules! setup_interned_struct {
156156
/// Default debug formatting for this struct (may be useful if you define your own `Debug` impl)
157157
pub fn default_debug_fmt(this: Self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
158158
$zalsa::with_attached_database(|db| {
159-
let fields = $Configuration::ingredient(db).fields(db.as_dyn_database(), this);
159+
let fields = $Configuration::ingredient(db).fields(this);
160160
let mut f = f.debug_struct(stringify!($Struct));
161161
$(
162162
let f = f.field(stringify!($field_id), &fields.$field_index);

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

+7-7
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ macro_rules! setup_tracked_fn {
9696
if $needs_interner {
9797
#[derive(Copy, Clone)]
9898
struct $InternedData<$db_lt>(
99-
salsa::Id,
99+
std::ptr::NonNull<$zalsa::interned::Value<$Configuration>>,
100100
std::marker::PhantomData<&$db_lt $zalsa::interned::Value<$Configuration>>,
101101
);
102102

@@ -114,14 +114,14 @@ macro_rules! setup_tracked_fn {
114114

115115
type Struct<$db_lt> = $InternedData<$db_lt>;
116116

117-
fn struct_from_id<$db_lt>(
118-
id: salsa::Id,
117+
unsafe fn struct_from_raw<$db_lt>(
118+
ptr: std::ptr::NonNull<$zalsa::interned::Value<Self>>,
119119
) -> Self::Struct<$db_lt> {
120-
$InternedData(id, std::marker::PhantomData)
120+
$InternedData(ptr, std::marker::PhantomData)
121121
}
122122

123-
fn deref_struct(s: Self::Struct<'_>) -> salsa::Id {
124-
s.0
123+
fn deref_struct(s: Self::Struct<'_>) -> &$zalsa::interned::Value<Self> {
124+
unsafe { s.0.as_ref() }
125125
}
126126
}
127127
} else {
@@ -191,7 +191,7 @@ macro_rules! setup_tracked_fn {
191191
fn id_to_input<$db_lt>(db: &$db_lt Self::DbView, key: salsa::Id) -> Self::Input<$db_lt> {
192192
$zalsa::macro_if! {
193193
if $needs_interner {
194-
$Configuration::intern_ingredient(db).data(db, key).clone()
194+
$Configuration::intern_ingredient(db).data(key).clone()
195195
} else {
196196
$zalsa::LookupId::lookup_id(key, db.as_dyn_database())
197197
}

src/interned.rs

+57-20
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
use crossbeam::atomic::AtomicCell;
12
use std::fmt;
23
use std::hash::Hash;
34
use std::marker::PhantomData;
5+
use std::ptr::NonNull;
46

7+
use crate::alloc::Alloc;
58
use crate::durability::Durability;
69
use crate::id::AsId;
710
use crate::ingredient::fmt_index;
@@ -24,16 +27,24 @@ pub trait Configuration: Sized + 'static {
2427
/// The end user struct
2528
type Struct<'db>: Copy;
2629

27-
/// Create an end-user struct from the salsa id
30+
/// Create an end-user struct from the underlying raw pointer.
2831
///
2932
/// This call is an "end-step" to the tracked struct lookup/creation
3033
/// process in a given revision: it occurs only when the struct is newly
3134
/// created or, if a struct is being reused, after we have updated its
3235
/// fields (or confirmed it is green and no updates are required).
33-
fn struct_from_id<'db>(id: Id) -> Self::Struct<'db>;
34-
35-
/// Deref the struct to yield the underlying id.
36-
fn deref_struct(s: Self::Struct<'_>) -> Id;
36+
///
37+
/// # Safety
38+
///
39+
/// Requires that `ptr` represents a "confirmed" value in this revision,
40+
/// which means that it will remain valid and immutable for the remainder of this
41+
/// revision, represented by the lifetime `'db`.
42+
unsafe fn struct_from_raw<'db>(ptr: NonNull<Value<Self>>) -> Self::Struct<'db>;
43+
44+
/// Deref the struct to yield the underlying value struct.
45+
/// Since we are still part of the `'db` lifetime in which the struct was created,
46+
/// this deref is safe, and the value-struct fields are immutable and verified.
47+
fn deref_struct(s: Self::Struct<'_>) -> &Value<Self>;
3748
}
3849

3950
pub trait InternedData: Sized + Eq + Hash + Clone {}
@@ -55,6 +66,14 @@ pub struct IngredientImpl<C: Configuration> {
5566
/// Deadlock requirement: We access `value_map` while holding lock on `key_map`, but not vice versa.
5667
key_map: FxDashMap<C::Data<'static>, Id>,
5768

69+
/// Maps from an interned id to its data.
70+
///
71+
/// Deadlock requirement: We access `value_map` while holding lock on `key_map`, but not vice versa.
72+
value_map: FxDashMap<Id, Alloc<Value<C>>>,
73+
74+
/// counter for the next id.
75+
counter: AtomicCell<u32>,
76+
5877
/// Stores the revision when this interned ingredient was last cleared.
5978
/// You can clear an interned table at any point, deleting all its entries,
6079
/// but that will make anything dependent on those entries dirty and in need
@@ -93,6 +112,8 @@ where
93112
Self {
94113
ingredient_index,
95114
key_map: Default::default(),
115+
value_map: Default::default(),
116+
counter: AtomicCell::default(),
96117
reset_at: Revision::start(),
97118
}
98119
}
@@ -101,10 +122,6 @@ where
101122
unsafe { std::mem::transmute(data) }
102123
}
103124

104-
unsafe fn from_internal_data<'db>(&'db self, data: &C::Data<'static>) -> &C::Data<'db> {
105-
unsafe { std::mem::transmute(data) }
106-
}
107-
108125
pub fn intern_id<'db>(
109126
&'db self,
110127
db: &'db dyn crate::Database,
@@ -132,46 +149,66 @@ where
132149
if let Some(guard) = self.key_map.get(&internal_data) {
133150
let id = *guard;
134151
drop(guard);
135-
return C::struct_from_id(id);
152+
return self.interned_value(id);
136153
}
137154

138155
match self.key_map.entry(internal_data.clone()) {
139156
// Data has been interned by a racing call, use that ID instead
140157
dashmap::mapref::entry::Entry::Occupied(entry) => {
141158
let id = *entry.get();
142159
drop(entry);
143-
C::struct_from_id(id)
160+
self.interned_value(id)
144161
}
145162

146163
// We won any races so should intern the data
147164
dashmap::mapref::entry::Entry::Vacant(entry) => {
148-
let zalsa = db.zalsa();
149-
let table = zalsa.table();
150-
let next_id = zalsa_local.allocate(table, self.ingredient_index, internal_data);
165+
let next_id = self.counter.fetch_add(1);
166+
let next_id = crate::id::Id::from_u32(next_id);
167+
let value = self.value_map.entry(next_id).or_insert(Alloc::new(Value {
168+
id: next_id,
169+
fields: internal_data,
170+
}));
171+
let value_raw = value.as_raw();
172+
drop(value);
151173
entry.insert(next_id);
152-
C::struct_from_id(next_id)
174+
// SAFETY: Items are only removed from the `value_map` with an `&mut self` reference.
175+
unsafe { C::struct_from_raw(value_raw) }
153176
}
154177
}
155178
}
156179

180+
pub fn interned_value(&self, id: Id) -> C::Struct<'_> {
181+
let r = self.value_map.get(&id).unwrap();
182+
183+
// SAFETY: Items are only removed from the `value_map` with an `&mut self` reference.
184+
unsafe { C::struct_from_raw(r.as_raw()) }
185+
}
186+
157187
/// Lookup the data for an interned value based on its id.
158188
/// Rarely used since end-users generally carry a struct with a pointer directly
159189
/// to the interned item.
160-
pub fn data<'db>(&'db self, db: &'db dyn Database, id: Id) -> &'db C::Data<'db> {
161-
let internal_data = db.zalsa().table().get::<C::Data<'static>>(id);
162-
unsafe { self.from_internal_data(internal_data) }
190+
pub fn data(&self, id: Id) -> &C::Data<'_> {
191+
C::deref_struct(self.interned_value(id)).data()
163192
}
164193

165194
/// Lookup the fields from an interned struct.
166195
/// Note that this is not "leaking" since no dependency edge is required.
167-
pub fn fields<'db>(&'db self, db: &'db dyn Database, s: C::Struct<'db>) -> &'db C::Data<'db> {
168-
self.data(db, C::deref_struct(s))
196+
pub fn fields<'db>(&'db self, s: C::Struct<'db>) -> &'db C::Data<'db> {
197+
C::deref_struct(s).data()
198+
}
199+
200+
/// Variant of `data` that takes a (unnecessary) database argument.
201+
/// This exists because tracked functions sometimes use true interning and sometimes use
202+
/// [`IdentityInterner`][], which requires the database argument.
203+
pub fn data_with_db<'db, DB: ?Sized>(&'db self, id: Id, _db: &'db DB) -> &'db C::Data<'db> {
204+
self.data(id)
169205
}
170206

171207
pub fn reset(&mut self, revision: Revision) {
172208
assert!(revision > self.reset_at);
173209
self.reset_at = revision;
174210
self.key_map.clear();
211+
self.value_map.clear();
175212
}
176213
}
177214

src/lib.rs

-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@ mod revision;
2222
mod runtime;
2323
mod salsa_struct;
2424
mod storage;
25-
mod table;
2625
mod tracked_struct;
2726
mod update;
2827
mod views;

src/table.rs

-133
This file was deleted.

0 commit comments

Comments
 (0)