1
- use std:: ops:: Range ;
1
+ use std:: { marker :: PhantomData , ops:: Range } ;
2
2
3
3
use rustc_index:: vec:: Idx ;
4
4
5
5
use crate :: modified_set as ms;
6
+ use crate :: snapshot_vec as sv;
6
7
use crate :: unify as ut;
7
8
use crate :: unify_log as ul;
8
9
10
+ use ena:: undo_log:: { Rollback , Snapshots , UndoLogs } ;
11
+
12
+ enum UndoLog < K : ut:: UnifyKey , I > {
13
+ Relation ( sv:: UndoLog < ut:: Delegate < K > > ) ,
14
+ UnifyLog ( ul:: Undo < I > ) ,
15
+ ModifiedSet ( ms:: Undo ) ,
16
+ }
17
+
18
+ impl < K : ut:: UnifyKey , I > From < sv:: UndoLog < ut:: Delegate < K > > > for UndoLog < K , I > {
19
+ fn from ( l : sv:: UndoLog < ut:: Delegate < K > > ) -> Self {
20
+ UndoLog :: Relation ( l)
21
+ }
22
+ }
23
+
24
+ impl < K : ut:: UnifyKey , I > From < ul:: Undo < I > > for UndoLog < K , I > {
25
+ fn from ( l : ul:: Undo < I > ) -> Self {
26
+ UndoLog :: UnifyLog ( l)
27
+ }
28
+ }
29
+
30
+ impl < K : ut:: UnifyKey , I > From < ms:: Undo > for UndoLog < K , I > {
31
+ fn from ( l : ms:: Undo ) -> Self {
32
+ UndoLog :: ModifiedSet ( l)
33
+ }
34
+ }
35
+
36
+ struct Logs < K : ut:: UnifyKey , I > {
37
+ logs : Vec < UndoLog < K , I > > ,
38
+ num_open_snapshots : usize ,
39
+ }
40
+
41
+ impl < K : ut:: UnifyKey , I > Default for Logs < K , I > {
42
+ fn default ( ) -> Self {
43
+ Self { logs : Default :: default ( ) , num_open_snapshots : Default :: default ( ) }
44
+ }
45
+ }
46
+
47
+ impl < T , K : ut:: UnifyKey , I > UndoLogs < T > for Logs < K , I >
48
+ where
49
+ UndoLog < K , I > : From < T > ,
50
+ {
51
+ fn num_open_snapshots ( & self ) -> usize {
52
+ self . num_open_snapshots
53
+ }
54
+ fn push ( & mut self , undo : T ) {
55
+ if self . in_snapshot ( ) {
56
+ self . logs . push ( undo. into ( ) )
57
+ }
58
+ }
59
+ fn extend < J > ( & mut self , undos : J )
60
+ where
61
+ Self : Sized ,
62
+ J : IntoIterator < Item = T > ,
63
+ {
64
+ if self . in_snapshot ( ) {
65
+ self . logs . extend ( undos. into_iter ( ) . map ( UndoLog :: from) )
66
+ }
67
+ }
68
+ }
69
+
70
+ struct RollbackView < ' a , K : ut:: UnifyKey , I : Idx > {
71
+ relations : & ' a mut ut:: UnificationStorage < K > ,
72
+ unify_log : & ' a mut ul:: UnifyLog < I > ,
73
+ modified_set : & ' a mut ms:: ModifiedSet < I > ,
74
+ }
75
+
76
+ impl < K : ut:: UnifyKey , I : Idx > Rollback < UndoLog < K , I > > for RollbackView < ' _ , K , I > {
77
+ fn reverse ( & mut self , undo : UndoLog < K , I > ) {
78
+ match undo {
79
+ UndoLog :: Relation ( undo) => self . relations . reverse ( undo) ,
80
+ UndoLog :: UnifyLog ( undo) => self . unify_log . reverse ( undo) ,
81
+ UndoLog :: ModifiedSet ( undo) => self . modified_set . reverse ( undo) ,
82
+ }
83
+ }
84
+ }
85
+
86
+ impl < K : ut:: UnifyKey , I : Idx > Snapshots < UndoLog < K , I > > for Logs < K , I > {
87
+ type Snapshot = Snapshot < K , I > ;
88
+ fn actions_since_snapshot ( & self , snapshot : & Self :: Snapshot ) -> & [ UndoLog < K , I > ] {
89
+ & self . logs [ snapshot. undo_len ..]
90
+ }
91
+
92
+ fn start_snapshot ( & mut self ) -> Self :: Snapshot {
93
+ unreachable ! ( )
94
+ }
95
+
96
+ fn rollback_to ( & mut self , values : & mut impl Rollback < UndoLog < K , I > > , snapshot : Self :: Snapshot ) {
97
+ debug ! ( "rollback_to({})" , snapshot. undo_len) ;
98
+ self . assert_open_snapshot ( & snapshot) ;
99
+
100
+ while self . logs . len ( ) > snapshot. undo_len {
101
+ values. reverse ( self . logs . pop ( ) . unwrap ( ) ) ;
102
+ }
103
+
104
+ if self . num_open_snapshots == 1 {
105
+ // The root snapshot. It's safe to clear the undo log because
106
+ // there's no snapshot further out that we might need to roll back
107
+ // to.
108
+ assert ! ( snapshot. undo_len == 0 ) ;
109
+ self . logs . clear ( ) ;
110
+ }
111
+
112
+ self . num_open_snapshots -= 1 ;
113
+ }
114
+
115
+ fn commit ( & mut self , snapshot : Self :: Snapshot ) {
116
+ debug ! ( "commit({})" , snapshot. undo_len) ;
117
+
118
+ if self . num_open_snapshots == 1 {
119
+ // The root snapshot. It's safe to clear the undo log because
120
+ // there's no snapshot further out that we might need to roll back
121
+ // to.
122
+ assert ! ( snapshot. undo_len == 0 ) ;
123
+ self . logs . clear ( ) ;
124
+ }
125
+
126
+ self . num_open_snapshots -= 1 ;
127
+ }
128
+ }
129
+
130
+ impl < K : ut:: UnifyKey , I : Idx > Logs < K , I > {
131
+ fn assert_open_snapshot ( & self , snapshot : & Snapshot < K , I > ) {
132
+ // Failures here may indicate a failure to follow a stack discipline.
133
+ assert ! ( self . logs. len( ) >= snapshot. undo_len) ;
134
+ assert ! ( self . num_open_snapshots > 0 ) ;
135
+ }
136
+ }
137
+
9
138
pub struct LoggedUnificationTable < K : ut:: UnifyKey , I : Idx = K > {
10
- relations : ut:: UnificationTable < ut :: InPlace < K > > ,
139
+ relations : ut:: UnificationStorage < K > ,
11
140
unify_log : ul:: UnifyLog < I > ,
12
141
modified_set : ms:: ModifiedSet < I > ,
142
+ undo_log : Logs < K , I > ,
13
143
}
14
144
15
145
impl < K , I > LoggedUnificationTable < K , I >
@@ -19,12 +149,19 @@ where
19
149
{
20
150
pub fn new ( ) -> Self {
21
151
Self {
22
- relations : ut :: UnificationTable :: new ( ) ,
152
+ relations : Default :: default ( ) ,
23
153
unify_log : ul:: UnifyLog :: new ( ) ,
24
154
modified_set : ms:: ModifiedSet :: new ( ) ,
155
+ undo_log : Logs :: default ( ) ,
25
156
}
26
157
}
27
158
159
+ fn relations (
160
+ & mut self ,
161
+ ) -> ut:: UnificationTable < ut:: InPlace < K , & mut ut:: UnificationStorage < K > , & mut Logs < K , I > > > {
162
+ ut:: UnificationTable :: with_log ( & mut self . relations , & mut self . undo_log )
163
+ }
164
+
28
165
pub fn unify ( & mut self , a : I , b : I )
29
166
where
30
167
K :: Value : ut:: UnifyValue < Error = ut:: NoError > ,
@@ -38,17 +175,18 @@ where
38
175
{
39
176
if self . unify_log . needs_log ( vid) {
40
177
warn ! ( "ModifiedSet {:?} => {:?}" , vid, ty) ;
41
- self . modified_set . set ( vid) ;
178
+ self . modified_set . set ( & mut self . undo_log , vid) ;
42
179
}
43
180
let vid = vid. into ( ) ;
44
- debug_assert ! ( self . relations. find( vid) == vid) ;
45
- self . relations . union_value ( vid, ty) ;
181
+ let mut relations = self . relations ( ) ;
182
+ debug_assert ! ( relations. find( vid) == vid) ;
183
+ relations. union_value ( vid, ty) ;
46
184
47
185
vid
48
186
}
49
187
50
188
pub fn find ( & mut self , vid : I ) -> K {
51
- self . relations . find ( vid)
189
+ self . relations ( ) . find ( vid)
52
190
}
53
191
54
192
pub fn unify_var_value (
@@ -58,24 +196,25 @@ where
58
196
) -> Result < ( ) , <K :: Value as ut:: UnifyValue >:: Error > {
59
197
let vid = self . find ( vid) . into ( ) ;
60
198
if self . unify_log . needs_log ( vid) {
61
- self . modified_set . set ( vid) ;
199
+ self . modified_set . set ( & mut self . undo_log , vid) ;
62
200
}
63
- self . relations . unify_var_value ( vid, value)
201
+ self . relations ( ) . unify_var_value ( vid, value)
64
202
}
65
203
66
204
pub fn unify_var_var ( & mut self , a : I , b : I ) -> Result < ( ) , <K :: Value as ut:: UnifyValue >:: Error > {
67
- let a = self . relations . find ( a) ;
68
- let b = self . relations . find ( b) ;
205
+ let mut relations = self . relations ( ) ;
206
+ let a = relations. find ( a) ;
207
+ let b = relations. find ( b) ;
69
208
if a == b {
70
209
return Ok ( ( ) ) ;
71
210
}
72
211
73
- self . relations . unify_var_var ( a, b) ?;
212
+ relations. unify_var_var ( a, b) ?;
74
213
75
- if a == self . relations . find ( a) {
76
- self . unify_log . unify ( a. into ( ) , b. into ( ) ) ;
214
+ if a == relations. find ( a) {
215
+ self . unify_log . unify ( & mut self . undo_log , a. into ( ) , b. into ( ) ) ;
77
216
} else {
78
- self . unify_log . unify ( b. into ( ) , a. into ( ) ) ;
217
+ self . unify_log . unify ( & mut self . undo_log , b. into ( ) , a. into ( ) ) ;
79
218
}
80
219
Ok ( ( ) )
81
220
}
@@ -89,46 +228,52 @@ where
89
228
}
90
229
91
230
pub fn probe_value ( & mut self , vid : I ) -> K :: Value {
92
- self . relations . probe_value ( vid)
231
+ self . relations ( ) . probe_value ( vid)
93
232
}
94
233
95
234
#[ inline( always) ]
96
235
pub fn inlined_probe_value ( & mut self , vid : I ) -> K :: Value {
97
- self . relations . inlined_probe_value ( vid)
236
+ self . relations ( ) . inlined_probe_value ( vid)
98
237
}
99
238
100
239
pub fn new_key ( & mut self , value : K :: Value ) -> K {
101
- self . relations . new_key ( value)
240
+ self . relations ( ) . new_key ( value)
102
241
}
103
242
104
243
pub fn len ( & self ) -> usize {
105
244
self . relations . len ( )
106
245
}
107
246
247
+ pub fn vars_since_snapshot ( & mut self , s : & Snapshot < K , I > ) -> Range < K > {
248
+ K :: from ( I :: new ( s. value_count ) ) ..K :: from ( I :: new ( self . relations ( ) . len ( ) ) )
249
+ }
250
+
108
251
pub fn snapshot ( & mut self ) -> Snapshot < K , I > {
252
+ self . undo_log . num_open_snapshots += 1 ;
109
253
Snapshot {
110
- snapshot : self . relations . snapshot ( ) ,
111
- unify_log_snapshot : self . unify_log . snapshot ( ) ,
112
- modified_snapshot : self . modified_set . snapshot ( ) ,
254
+ undo_len : self . undo_log . logs . len ( ) ,
255
+ value_count : self . relations ( ) . len ( ) ,
256
+ _marker : PhantomData ,
113
257
}
114
258
}
115
259
116
- pub fn rollback_to ( & mut self , s : Snapshot < K , I > ) {
117
- let Snapshot { snapshot, unify_log_snapshot, modified_snapshot } = s;
118
- self . relations . rollback_to ( snapshot) ;
119
- self . unify_log . rollback_to ( unify_log_snapshot) ;
120
- self . modified_set . rollback_to ( modified_snapshot) ;
121
- }
260
+ pub fn rollback_to ( & mut self , snapshot : Snapshot < K , I > ) {
261
+ let Self { relations, unify_log, modified_set, .. } = self ;
262
+
263
+ self . undo_log
264
+ . rollback_to ( & mut RollbackView { relations, unify_log, modified_set } , snapshot) ;
122
265
123
- pub fn commit ( & mut self , s : Snapshot < K , I > ) {
124
- let Snapshot { snapshot, unify_log_snapshot, modified_snapshot } = s;
125
- self . relations . commit ( snapshot) ;
126
- self . unify_log . commit ( unify_log_snapshot) ;
127
- self . modified_set . commit ( modified_snapshot) ;
266
+ if self . undo_log . num_open_snapshots == 0 {
267
+ self . modified_set . clear ( ) ;
268
+ }
128
269
}
129
270
130
- pub fn vars_since_snapshot ( & mut self , s : & Snapshot < K , I > ) -> Range < K > {
131
- self . relations . vars_since_snapshot ( & s. snapshot )
271
+ pub fn commit ( & mut self , snapshot : Snapshot < K , I > ) {
272
+ self . undo_log . commit ( snapshot) ;
273
+
274
+ if self . undo_log . num_open_snapshots == 0 {
275
+ self . modified_set . clear ( ) ;
276
+ }
132
277
}
133
278
134
279
pub fn register ( & mut self ) -> ms:: Offset < I > {
@@ -140,7 +285,7 @@ where
140
285
}
141
286
142
287
pub fn watch_variable ( & mut self , index : I ) {
143
- debug_assert ! ( index == self . relations. find( index) . into( ) ) ;
288
+ debug_assert ! ( index == self . relations( ) . find( index) . into( ) ) ;
144
289
self . unify_log . watch_variable ( index)
145
290
}
146
291
@@ -150,7 +295,7 @@ where
150
295
151
296
pub fn drain_modified_set ( & mut self , offset : & ms:: Offset < I > , mut f : impl FnMut ( I ) -> bool ) {
152
297
let unify_log = & self . unify_log ;
153
- self . modified_set . drain ( offset, |vid| {
298
+ self . modified_set . drain ( & mut self . undo_log , offset, |vid| {
154
299
for & unified_vid in unify_log. get ( vid) {
155
300
f ( unified_vid) ;
156
301
}
@@ -161,7 +306,7 @@ where
161
306
}
162
307
163
308
pub struct Snapshot < K : ut:: UnifyKey , I : Idx = K > {
164
- snapshot : ut :: Snapshot < ut :: InPlace < K > > ,
165
- unify_log_snapshot : ul :: Snapshot < I > ,
166
- modified_snapshot : ms :: Snapshot < I > ,
309
+ undo_len : usize ,
310
+ value_count : usize ,
311
+ _marker : PhantomData < ( K , I ) > ,
167
312
}
0 commit comments