Skip to content

Commit b07fd48

Browse files
committed
Remove OpenSnapshot and CommittedSnapshot markers from SnapshotMap.
They're not strictly necessary, and they result in the `Vec` being allocated even for the trivial (and common) case where a `start_snapshot` is immediately followed by a `commit` or `rollback_to`.
1 parent da19783 commit b07fd48

File tree

2 files changed

+25
-34
lines changed

2 files changed

+25
-34
lines changed

src/librustc_data_structures/snapshot_map/mod.rs

+18-30
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ pub struct SnapshotMap<K, V>
2121
{
2222
map: FxHashMap<K, V>,
2323
undo_log: Vec<UndoLog<K, V>>,
24+
num_open_snapshots: usize,
2425
}
2526

2627
// HACK(eddyb) manual impl avoids `Default` bounds on `K` and `V`.
@@ -31,6 +32,7 @@ impl<K, V> Default for SnapshotMap<K, V>
3132
SnapshotMap {
3233
map: Default::default(),
3334
undo_log: Default::default(),
35+
num_open_snapshots: 0,
3436
}
3537
}
3638
}
@@ -40,8 +42,6 @@ pub struct Snapshot {
4042
}
4143

4244
enum UndoLog<K, V> {
43-
OpenSnapshot,
44-
CommittedSnapshot,
4545
Inserted(K),
4646
Overwrite(K, V),
4747
Purged,
@@ -53,10 +53,11 @@ impl<K, V> SnapshotMap<K, V>
5353
pub fn clear(&mut self) {
5454
self.map.clear();
5555
self.undo_log.clear();
56+
self.num_open_snapshots = 0;
5657
}
5758

5859
fn in_snapshot(&self) -> bool {
59-
!self.undo_log.is_empty()
60+
self.num_open_snapshots > 0
6061
}
6162

6263
pub fn insert(&mut self, key: K, value: V) -> bool {
@@ -93,27 +94,27 @@ impl<K, V> SnapshotMap<K, V>
9394
}
9495

9596
pub fn snapshot(&mut self) -> Snapshot {
96-
self.undo_log.push(UndoLog::OpenSnapshot);
97-
let len = self.undo_log.len() - 1;
97+
let len = self.undo_log.len();
98+
self.num_open_snapshots += 1;
9899
Snapshot { len }
99100
}
100101

101102
fn assert_open_snapshot(&self, snapshot: &Snapshot) {
102-
assert!(snapshot.len < self.undo_log.len());
103-
assert!(match self.undo_log[snapshot.len] {
104-
UndoLog::OpenSnapshot => true,
105-
_ => false,
106-
});
103+
assert!(self.undo_log.len() >= snapshot.len);
104+
assert!(self.num_open_snapshots > 0);
107105
}
108106

109107
pub fn commit(&mut self, snapshot: Snapshot) {
110108
self.assert_open_snapshot(&snapshot);
111-
if snapshot.len == 0 {
112-
// The root snapshot.
109+
if self.num_open_snapshots == 1 {
110+
// The root snapshot. It's safe to clear the undo log because
111+
// there's no snapshot further out that we might need to roll back
112+
// to.
113+
assert!(snapshot.len == 0);
113114
self.undo_log.clear();
114-
} else {
115-
self.undo_log[snapshot.len] = UndoLog::CommittedSnapshot;
116115
}
116+
117+
self.num_open_snapshots -= 1;
117118
}
118119

119120
pub fn partial_rollback<F>(&mut self,
@@ -122,10 +123,8 @@ impl<K, V> SnapshotMap<K, V>
122123
where F: Fn(&K) -> bool
123124
{
124125
self.assert_open_snapshot(snapshot);
125-
for i in (snapshot.len + 1..self.undo_log.len()).rev() {
126+
for i in (snapshot.len .. self.undo_log.len()).rev() {
126127
let reverse = match self.undo_log[i] {
127-
UndoLog::OpenSnapshot => false,
128-
UndoLog::CommittedSnapshot => false,
129128
UndoLog::Purged => false,
130129
UndoLog::Inserted(ref k) => should_revert_key(k),
131130
UndoLog::Overwrite(ref k, _) => should_revert_key(k),
@@ -140,27 +139,16 @@ impl<K, V> SnapshotMap<K, V>
140139

141140
pub fn rollback_to(&mut self, snapshot: Snapshot) {
142141
self.assert_open_snapshot(&snapshot);
143-
while self.undo_log.len() > snapshot.len + 1 {
142+
while self.undo_log.len() > snapshot.len {
144143
let entry = self.undo_log.pop().unwrap();
145144
self.reverse(entry);
146145
}
147146

148-
let v = self.undo_log.pop().unwrap();
149-
assert!(match v {
150-
UndoLog::OpenSnapshot => true,
151-
_ => false,
152-
});
153-
assert!(self.undo_log.len() == snapshot.len);
147+
self.num_open_snapshots -= 1;
154148
}
155149

156150
fn reverse(&mut self, entry: UndoLog<K, V>) {
157151
match entry {
158-
UndoLog::OpenSnapshot => {
159-
panic!("cannot rollback an uncommitted snapshot");
160-
}
161-
162-
UndoLog::CommittedSnapshot => {}
163-
164152
UndoLog::Inserted(key) => {
165153
self.map.remove(&key);
166154
}

src/librustc_data_structures/snapshot_map/test.rs

+7-4
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ fn basic() {
1717
let snapshot = map.snapshot();
1818
map.insert(22, "thirty-three");
1919
assert_eq!(map[&22], "thirty-three");
20-
map.insert(44, "fourty-four");
21-
assert_eq!(map[&44], "fourty-four");
20+
map.insert(44, "forty-four");
21+
assert_eq!(map[&44], "forty-four");
2222
assert_eq!(map.get(&33), None);
2323
map.rollback_to(snapshot);
2424
assert_eq!(map[&22], "twenty-two");
@@ -32,8 +32,11 @@ fn out_of_order() {
3232
let mut map = SnapshotMap::default();
3333
map.insert(22, "twenty-two");
3434
let snapshot1 = map.snapshot();
35-
let _snapshot2 = map.snapshot();
36-
map.rollback_to(snapshot1);
35+
map.insert(33, "thirty-three");
36+
let snapshot2 = map.snapshot();
37+
map.insert(44, "forty-four");
38+
map.rollback_to(snapshot1); // bogus, but accepted
39+
map.rollback_to(snapshot2); // asserts
3740
}
3841

3942
#[test]

0 commit comments

Comments
 (0)