1
1
use crate :: borrow_check:: nll:: region_infer:: values:: { PointIndex , RegionValueElements } ;
2
- use crate :: borrow_check:: nll:: type_check:: liveness:: liveness_map:: { LiveVar , NllLivenessMap } ;
3
- use crate :: util:: liveness:: { categorize, DefUse , LiveVariableMap } ;
2
+ use crate :: util:: liveness:: { categorize, DefUse } ;
4
3
use rustc:: mir:: visit:: { PlaceContext , Visitor } ;
5
4
use rustc:: mir:: { Local , Location , Mir } ;
6
5
use rustc_data_structures:: indexed_vec:: { Idx , IndexVec } ;
@@ -9,26 +8,33 @@ use rustc_data_structures::vec_linked_list as vll;
9
8
/// A map that cross references each local with the locations where it
10
9
/// is defined (assigned), used, or dropped. Used during liveness
11
10
/// computation.
12
- crate struct LocalUseMap < ' me > {
13
- liveness_map : & ' me NllLivenessMap ,
14
-
11
+ ///
12
+ /// We keep track only of `Local`s we'll do the liveness analysis later,
13
+ /// this means that our internal `IndexVec`s will only be sparsely populated.
14
+ /// In the time-memory trade-off between keeping compact vectors with new
15
+ /// indexes (and needing to continuously map the `Local` index to its compact
16
+ /// counterpart) and having `IndexVec`s that we only use a fraction of, time
17
+ /// (and code simplicity) was favored. The rationale is that we only keep
18
+ /// a small number of `IndexVec`s throughout the entire analysis while, in
19
+ /// contrast, we're accessing each `Local` *many* times.
20
+ crate struct LocalUseMap {
15
21
/// Head of a linked list of **definitions** of each variable --
16
22
/// definition in this context means assignment, e.g., `x` is
17
23
/// defined in `x = y` but not `y`; that first def is the head of
18
24
/// a linked list that lets you enumerate all places the variable
19
25
/// is assigned.
20
- first_def_at : IndexVec < LiveVar , Option < AppearanceIndex > > ,
26
+ first_def_at : IndexVec < Local , Option < AppearanceIndex > > ,
21
27
22
28
/// Head of a linked list of **uses** of each variable -- use in
23
29
/// this context means that the existing value of the variable is
24
30
/// read or modified. e.g., `y` is used in `x = y` but not `x`.
25
31
/// Note that `DROP(x)` terminators are excluded from this list.
26
- first_use_at : IndexVec < LiveVar , Option < AppearanceIndex > > ,
32
+ first_use_at : IndexVec < Local , Option < AppearanceIndex > > ,
27
33
28
34
/// Head of a linked list of **drops** of each variable -- these
29
35
/// are a special category of uses corresponding to the drop that
30
36
/// we add for each local variable.
31
- first_drop_at : IndexVec < LiveVar , Option < AppearanceIndex > > ,
37
+ first_drop_at : IndexVec < Local , Option < AppearanceIndex > > ,
32
38
33
39
appearances : IndexVec < AppearanceIndex , Appearance > ,
34
40
}
@@ -50,55 +56,68 @@ impl vll::LinkElem for Appearance {
50
56
}
51
57
}
52
58
53
- impl LocalUseMap < ' me > {
59
+ impl LocalUseMap {
54
60
crate fn build (
55
- liveness_map : & ' me NllLivenessMap ,
61
+ live_locals : & Vec < Local > ,
56
62
elements : & RegionValueElements ,
57
63
mir : & Mir < ' _ > ,
58
64
) -> Self {
59
- let nones = IndexVec :: from_elem_n ( None , liveness_map . num_variables ( ) ) ;
65
+ let nones = IndexVec :: from_elem_n ( None , mir . local_decls . len ( ) ) ;
60
66
let mut local_use_map = LocalUseMap {
61
- liveness_map,
62
67
first_def_at : nones. clone ( ) ,
63
68
first_use_at : nones. clone ( ) ,
64
69
first_drop_at : nones,
65
70
appearances : IndexVec :: new ( ) ,
66
71
} ;
67
72
73
+ let mut locals_with_use_data: IndexVec < Local , bool > =
74
+ IndexVec :: from_elem_n ( false , mir. local_decls . len ( ) ) ;
75
+ live_locals
76
+ . iter ( )
77
+ . for_each ( |& local| locals_with_use_data[ local] = true ) ;
78
+
68
79
LocalUseMapBuild {
69
80
local_use_map : & mut local_use_map,
70
81
elements,
71
- } . visit_mir ( mir) ;
82
+ locals_with_use_data,
83
+ }
84
+ . visit_mir ( mir) ;
72
85
73
86
local_use_map
74
87
}
75
88
76
89
crate fn defs ( & self , local : Local ) -> impl Iterator < Item = PointIndex > + ' _ {
77
- let live_var = self . liveness_map . from_local ( local) . unwrap ( ) ;
78
- vll:: iter ( self . first_def_at [ live_var] , & self . appearances )
90
+ vll:: iter ( self . first_def_at [ local] , & self . appearances )
79
91
. map ( move |aa| self . appearances [ aa] . point_index )
80
92
}
81
93
82
94
crate fn uses ( & self , local : Local ) -> impl Iterator < Item = PointIndex > + ' _ {
83
- let live_var = self . liveness_map . from_local ( local) . unwrap ( ) ;
84
- vll:: iter ( self . first_use_at [ live_var] , & self . appearances )
95
+ vll:: iter ( self . first_use_at [ local] , & self . appearances )
85
96
. map ( move |aa| self . appearances [ aa] . point_index )
86
97
}
87
98
88
99
crate fn drops ( & self , local : Local ) -> impl Iterator < Item = PointIndex > + ' _ {
89
- let live_var = self . liveness_map . from_local ( local) . unwrap ( ) ;
90
- vll:: iter ( self . first_drop_at [ live_var] , & self . appearances )
100
+ vll:: iter ( self . first_drop_at [ local] , & self . appearances )
91
101
. map ( move |aa| self . appearances [ aa] . point_index )
92
102
}
93
103
}
94
104
95
- struct LocalUseMapBuild < ' me , ' map : ' me > {
96
- local_use_map : & ' me mut LocalUseMap < ' map > ,
105
+ struct LocalUseMapBuild < ' me > {
106
+ local_use_map : & ' me mut LocalUseMap ,
97
107
elements : & ' me RegionValueElements ,
108
+
109
+ // Vector used in `visit_local` to signal which `Local`s do we need
110
+ // def/use/drop information on, constructed from `live_locals` (that
111
+ // contains the variables we'll do the liveness analysis for).
112
+ // This vector serves optimization purposes only: we could have
113
+ // obtained the same information from `live_locals` but we want to
114
+ // avoid repeatedly calling `Vec::contains()` (see `LocalUseMap` for
115
+ // the rationale on the time-memory trade-off we're favoring here).
116
+ locals_with_use_data : IndexVec < Local , bool > ,
98
117
}
99
118
100
- impl LocalUseMapBuild < ' _ , ' _ > {
101
- fn insert_def ( & mut self , local : LiveVar , location : Location ) {
119
+ impl LocalUseMapBuild < ' _ > {
120
+ fn insert_def ( & mut self , local : Local , location : Location ) {
102
121
Self :: insert (
103
122
self . elements ,
104
123
& mut self . local_use_map . first_def_at [ local] ,
@@ -107,7 +126,7 @@ impl LocalUseMapBuild<'_, '_> {
107
126
) ;
108
127
}
109
128
110
- fn insert_use ( & mut self , local : LiveVar , location : Location ) {
129
+ fn insert_use ( & mut self , local : Local , location : Location ) {
111
130
Self :: insert (
112
131
self . elements ,
113
132
& mut self . local_use_map . first_use_at [ local] ,
@@ -116,7 +135,7 @@ impl LocalUseMapBuild<'_, '_> {
116
135
) ;
117
136
}
118
137
119
- fn insert_drop ( & mut self , local : LiveVar , location : Location ) {
138
+ fn insert_drop ( & mut self , local : Local , location : Location ) {
120
139
Self :: insert (
121
140
self . elements ,
122
141
& mut self . local_use_map . first_drop_at [ local] ,
@@ -140,13 +159,13 @@ impl LocalUseMapBuild<'_, '_> {
140
159
}
141
160
}
142
161
143
- impl Visitor < ' tcx > for LocalUseMapBuild < ' _ , ' _ > {
162
+ impl Visitor < ' tcx > for LocalUseMapBuild < ' _ > {
144
163
fn visit_local ( & mut self , & local: & Local , context : PlaceContext < ' tcx > , location : Location ) {
145
- if let Some ( local_with_region ) = self . local_use_map . liveness_map . from_local ( local) {
164
+ if self . locals_with_use_data [ local] {
146
165
match categorize ( context) {
147
- Some ( DefUse :: Def ) => self . insert_def ( local_with_region , location) ,
148
- Some ( DefUse :: Use ) => self . insert_use ( local_with_region , location) ,
149
- Some ( DefUse :: Drop ) => self . insert_drop ( local_with_region , location) ,
166
+ Some ( DefUse :: Def ) => self . insert_def ( local , location) ,
167
+ Some ( DefUse :: Use ) => self . insert_use ( local , location) ,
168
+ Some ( DefUse :: Drop ) => self . insert_drop ( local , location) ,
150
169
_ => ( ) ,
151
170
}
152
171
}
0 commit comments