fix gc and volatile tests

This commit is contained in:
Niko Matsakis 2019-03-22 16:24:37 -04:00
parent 6cf1ffd24a
commit c040b0c673
4 changed files with 100 additions and 10 deletions

View file

@ -942,15 +942,6 @@ where
fn sweep(&self, db: &DB, strategy: SweepStrategy) {
let mut map_write = self.map.write();
let revision_now = db.salsa_runtime().current_revision();
match (strategy.discard_if, strategy.discard_what) {
(DiscardIf::Always, DiscardWhat::Everything) => {
debug!("sweep({:?}): clearing the table", Q::default());
map_write.clear();
return;
}
(DiscardIf::Never, _) | (_, DiscardWhat::Nothing) => return,
_ => {}
}
map_write.retain(|key, query_state| {
match query_state {
// Leave stuff that is currently being computed -- the
@ -972,6 +963,19 @@ where
revision_now
);
// Check if this memo read something "untracked"
// -- meaning non-deterministic. In this case, we
// can only collect "outdated" data that wasn't
// used in the current revision. This is because
// if we collected something from the current
// revision, we might wind up re-executing the
// query later in the revision and getting a
// distinct result.
let is_volatile = match memo.inputs {
MemoInputs::Untracked => true,
_ => false,
};
// Since we don't acquire a query lock in this
// method, it *is* possible for the revision to
// change while we are executing. However, it is
@ -982,7 +986,19 @@ where
assert!(memo.verified_at <= revision_now);
match strategy.discard_if {
DiscardIf::Never => unreachable!(),
// If we are only discarding outdated things,
// and this is not outdated, keep it.
DiscardIf::Outdated if memo.verified_at == revision_now => true,
// As explained on the `is_volatile` variable
// definition, if this is a volatile entry, we
// can't discard it unless it is outdated.
DiscardIf::Always if is_volatile && memo.verified_at == revision_now => {
true
}
// Otherwise, we can discard -- discard whatever the user requested.
DiscardIf::Outdated | DiscardIf::Always => match strategy.discard_what {
DiscardWhat::Nothing => unreachable!(),
DiscardWhat::Values => {

View file

@ -1,8 +1,9 @@
use crate::group;
use crate::interned;
use crate::log::{HasLog, Log};
use crate::volatile_tests;
#[salsa::database(group::Gc, interned::Intern)]
#[salsa::database(group::Gc, interned::Intern, volatile_tests::Volatile)]
#[derive(Default)]
pub(crate) struct DatabaseImpl {
runtime: salsa::Runtime<DatabaseImpl>,

View file

@ -16,3 +16,4 @@ mod group;
mod interned;
mod log;
mod shallow_constant_tests;
mod volatile_tests;

View file

@ -0,0 +1,72 @@
use crate::db;
use salsa::{Database, SweepStrategy};
use std::sync::atomic::{AtomicU32, Ordering};
use std::sync::Arc;
/// Query group for tests for how interned keys interact with GC.
#[salsa::query_group(Volatile)]
pub(crate) trait VolatileDatabase {
#[salsa::input]
fn atomic_cell(&self) -> Arc<AtomicU32>;
/// Underlying volatile query.
#[salsa::volatile]
fn volatile(&self) -> u32;
/// This just executes the intern query and returns the result.
fn repeat1(&self) -> u32;
/// Same as `repeat_intern1`. =)
fn repeat2(&self) -> u32;
}
fn volatile(db: &impl VolatileDatabase) -> u32 {
db.atomic_cell().load(Ordering::SeqCst)
}
fn repeat1(db: &impl VolatileDatabase) -> u32 {
db.volatile()
}
fn repeat2(db: &impl VolatileDatabase) -> u32 {
db.volatile()
}
#[test]
fn consistency_no_gc() {
let mut db = db::DatabaseImpl::default();
let cell = Arc::new(AtomicU32::new(22));
db.set_atomic_cell(cell.clone());
let v1 = db.repeat1();
cell.store(23, Ordering::SeqCst);
let v2 = db.repeat2();
assert_eq!(v1, v2);
}
#[test]
fn consistency_with_gc() {
let mut db = db::DatabaseImpl::default();
let cell = Arc::new(AtomicU32::new(22));
db.set_atomic_cell(cell.clone());
let v1 = db.repeat1();
cell.store(23, Ordering::SeqCst);
db.query(VolatileQuery).sweep(
SweepStrategy::default()
.discard_everything()
.sweep_all_revisions(),
);
let v2 = db.repeat2();
assert_eq!(v1, v2);
}