@@ -15,326 +15,319 @@ use rustc_span::symbol::Symbol;
15
15
16
16
use super :: PartitioningCx ;
17
17
use crate :: collector:: InliningMap ;
18
- use crate :: partitioning:: { MonoItemPlacement , Partition , PlacedRootMonoItems } ;
19
-
20
- pub struct DefaultPartitioning ;
21
-
22
- impl < ' tcx > Partition < ' tcx > for DefaultPartitioning {
23
- fn place_root_mono_items < I > (
24
- & mut self ,
25
- cx : & PartitioningCx < ' _ , ' tcx > ,
26
- mono_items : & mut I ,
27
- ) -> PlacedRootMonoItems < ' tcx >
28
- where
29
- I : Iterator < Item = MonoItem < ' tcx > > ,
30
- {
31
- let mut roots = FxHashSet :: default ( ) ;
32
- let mut codegen_units = FxHashMap :: default ( ) ;
33
- let is_incremental_build = cx. tcx . sess . opts . incremental . is_some ( ) ;
34
- let mut internalization_candidates = FxHashSet :: default ( ) ;
35
-
36
- // Determine if monomorphizations instantiated in this crate will be made
37
- // available to downstream crates. This depends on whether we are in
38
- // share-generics mode and whether the current crate can even have
39
- // downstream crates.
40
- let export_generics =
41
- cx. tcx . sess . opts . share_generics ( ) && cx. tcx . local_crate_exports_generics ( ) ;
42
-
43
- let cgu_name_builder = & mut CodegenUnitNameBuilder :: new ( cx. tcx ) ;
44
- let cgu_name_cache = & mut FxHashMap :: default ( ) ;
45
-
46
- for mono_item in mono_items {
47
- match mono_item. instantiation_mode ( cx. tcx ) {
48
- InstantiationMode :: GloballyShared { .. } => { }
49
- InstantiationMode :: LocalCopy => continue ,
50
- }
18
+ use crate :: partitioning:: { MonoItemPlacement , PlacedRootMonoItems } ;
19
+
20
+ // This modules implements the default (and only) partitioning strategy.
21
+
22
+ pub ( super ) fn place_root_mono_items < ' tcx , I > (
23
+ cx : & PartitioningCx < ' _ , ' tcx > ,
24
+ mono_items : & mut I ,
25
+ ) -> PlacedRootMonoItems < ' tcx >
26
+ where
27
+ I : Iterator < Item = MonoItem < ' tcx > > ,
28
+ {
29
+ let mut roots = FxHashSet :: default ( ) ;
30
+ let mut codegen_units = FxHashMap :: default ( ) ;
31
+ let is_incremental_build = cx. tcx . sess . opts . incremental . is_some ( ) ;
32
+ let mut internalization_candidates = FxHashSet :: default ( ) ;
33
+
34
+ // Determine if monomorphizations instantiated in this crate will be made
35
+ // available to downstream crates. This depends on whether we are in
36
+ // share-generics mode and whether the current crate can even have
37
+ // downstream crates.
38
+ let export_generics =
39
+ cx. tcx . sess . opts . share_generics ( ) && cx. tcx . local_crate_exports_generics ( ) ;
51
40
52
- let characteristic_def_id = characteristic_def_id_of_mono_item ( cx. tcx , mono_item) ;
53
- let is_volatile = is_incremental_build && mono_item. is_generic_fn ( ) ;
54
-
55
- let codegen_unit_name = match characteristic_def_id {
56
- Some ( def_id) => compute_codegen_unit_name (
57
- cx. tcx ,
58
- cgu_name_builder,
59
- def_id,
60
- is_volatile,
61
- cgu_name_cache,
62
- ) ,
63
- None => fallback_cgu_name ( cgu_name_builder) ,
64
- } ;
41
+ let cgu_name_builder = & mut CodegenUnitNameBuilder :: new ( cx. tcx ) ;
42
+ let cgu_name_cache = & mut FxHashMap :: default ( ) ;
43
+
44
+ for mono_item in mono_items {
45
+ match mono_item. instantiation_mode ( cx. tcx ) {
46
+ InstantiationMode :: GloballyShared { .. } => { }
47
+ InstantiationMode :: LocalCopy => continue ,
48
+ }
65
49
66
- let codegen_unit = codegen_units
67
- . entry ( codegen_unit_name)
68
- . or_insert_with ( || CodegenUnit :: new ( codegen_unit_name) ) ;
50
+ let characteristic_def_id = characteristic_def_id_of_mono_item ( cx. tcx , mono_item) ;
51
+ let is_volatile = is_incremental_build && mono_item. is_generic_fn ( ) ;
69
52
70
- let mut can_be_internalized = true ;
71
- let ( linkage , visibility ) = mono_item_linkage_and_visibility (
53
+ let codegen_unit_name = match characteristic_def_id {
54
+ Some ( def_id ) => compute_codegen_unit_name (
72
55
cx. tcx ,
73
- & mono_item,
74
- & mut can_be_internalized,
75
- export_generics,
76
- ) ;
77
- if visibility == Visibility :: Hidden && can_be_internalized {
78
- internalization_candidates. insert ( mono_item) ;
79
- }
80
-
81
- codegen_unit. items_mut ( ) . insert ( mono_item, ( linkage, visibility) ) ;
82
- roots. insert ( mono_item) ;
83
- }
56
+ cgu_name_builder,
57
+ def_id,
58
+ is_volatile,
59
+ cgu_name_cache,
60
+ ) ,
61
+ None => fallback_cgu_name ( cgu_name_builder) ,
62
+ } ;
84
63
85
- // Always ensure we have at least one CGU; otherwise, if we have a
86
- // crate with just types (for example), we could wind up with no CGU.
87
- if codegen_units. is_empty ( ) {
88
- let codegen_unit_name = fallback_cgu_name ( cgu_name_builder) ;
89
- codegen_units. insert ( codegen_unit_name, CodegenUnit :: new ( codegen_unit_name) ) ;
64
+ let codegen_unit = codegen_units
65
+ . entry ( codegen_unit_name)
66
+ . or_insert_with ( || CodegenUnit :: new ( codegen_unit_name) ) ;
67
+
68
+ let mut can_be_internalized = true ;
69
+ let ( linkage, visibility) = mono_item_linkage_and_visibility (
70
+ cx. tcx ,
71
+ & mono_item,
72
+ & mut can_be_internalized,
73
+ export_generics,
74
+ ) ;
75
+ if visibility == Visibility :: Hidden && can_be_internalized {
76
+ internalization_candidates. insert ( mono_item) ;
90
77
}
91
78
92
- let codegen_units = codegen_units . into_values ( ) . collect ( ) ;
93
- PlacedRootMonoItems { codegen_units , roots, internalization_candidates }
79
+ codegen_unit . items_mut ( ) . insert ( mono_item , ( linkage , visibility ) ) ;
80
+ roots. insert ( mono_item ) ;
94
81
}
95
82
96
- fn merge_codegen_units (
97
- & mut self ,
98
- cx : & PartitioningCx < ' _ , ' tcx > ,
99
- codegen_units : & mut Vec < CodegenUnit < ' tcx > > ,
100
- ) {
101
- assert ! ( cx . target_cgu_count >= 1 ) ;
83
+ // Always ensure we have at least one CGU; otherwise, if we have a
84
+ // crate with just types (for example), we could wind up with no CGU.
85
+ if codegen_units . is_empty ( ) {
86
+ let codegen_unit_name = fallback_cgu_name ( cgu_name_builder ) ;
87
+ codegen_units . insert ( codegen_unit_name , CodegenUnit :: new ( codegen_unit_name ) ) ;
88
+ }
102
89
103
- // Note that at this point in time the `codegen_units` here may not be
104
- // in a deterministic order (but we know they're deterministically the
105
- // same set). We want this merging to produce a deterministic ordering
106
- // of codegen units from the input.
107
- //
108
- // Due to basically how we've implemented the merging below (merge the
109
- // two smallest into each other) we're sure to start off with a
110
- // deterministic order (sorted by name). This'll mean that if two cgus
111
- // have the same size the stable sort below will keep everything nice
112
- // and deterministic.
113
- codegen_units. sort_by ( |a, b| a. name ( ) . as_str ( ) . cmp ( b. name ( ) . as_str ( ) ) ) ;
114
-
115
- // This map keeps track of what got merged into what.
116
- let mut cgu_contents: FxHashMap < Symbol , Vec < Symbol > > =
117
- codegen_units. iter ( ) . map ( |cgu| ( cgu. name ( ) , vec ! [ cgu. name( ) ] ) ) . collect ( ) ;
118
-
119
- // Merge the two smallest codegen units until the target size is
120
- // reached.
121
- while codegen_units. len ( ) > cx. target_cgu_count {
122
- // Sort small cgus to the back
123
- codegen_units. sort_by_cached_key ( |cgu| cmp:: Reverse ( cgu. size_estimate ( ) ) ) ;
124
- let mut smallest = codegen_units. pop ( ) . unwrap ( ) ;
125
- let second_smallest = codegen_units. last_mut ( ) . unwrap ( ) ;
126
-
127
- // Move the mono-items from `smallest` to `second_smallest`
128
- second_smallest. modify_size_estimate ( smallest. size_estimate ( ) ) ;
129
- for ( k, v) in smallest. items_mut ( ) . drain ( ) {
130
- second_smallest. items_mut ( ) . insert ( k, v) ;
131
- }
90
+ let codegen_units = codegen_units. into_values ( ) . collect ( ) ;
91
+ PlacedRootMonoItems { codegen_units, roots, internalization_candidates }
92
+ }
132
93
133
- // Record that `second_smallest` now contains all the stuff that was
134
- // in `smallest` before.
135
- let mut consumed_cgu_names = cgu_contents. remove ( & smallest. name ( ) ) . unwrap ( ) ;
136
- cgu_contents. get_mut ( & second_smallest. name ( ) ) . unwrap ( ) . append ( & mut consumed_cgu_names) ;
94
+ pub ( super ) fn merge_codegen_units < ' tcx > (
95
+ cx : & PartitioningCx < ' _ , ' tcx > ,
96
+ codegen_units : & mut Vec < CodegenUnit < ' tcx > > ,
97
+ ) {
98
+ assert ! ( cx. target_cgu_count >= 1 ) ;
137
99
138
- debug ! (
139
- "CodegenUnit {} merged into CodegenUnit {}" ,
140
- smallest. name( ) ,
141
- second_smallest. name( )
142
- ) ;
100
+ // Note that at this point in time the `codegen_units` here may not be
101
+ // in a deterministic order (but we know they're deterministically the
102
+ // same set). We want this merging to produce a deterministic ordering
103
+ // of codegen units from the input.
104
+ //
105
+ // Due to basically how we've implemented the merging below (merge the
106
+ // two smallest into each other) we're sure to start off with a
107
+ // deterministic order (sorted by name). This'll mean that if two cgus
108
+ // have the same size the stable sort below will keep everything nice
109
+ // and deterministic.
110
+ codegen_units. sort_by ( |a, b| a. name ( ) . as_str ( ) . cmp ( b. name ( ) . as_str ( ) ) ) ;
111
+
112
+ // This map keeps track of what got merged into what.
113
+ let mut cgu_contents: FxHashMap < Symbol , Vec < Symbol > > =
114
+ codegen_units. iter ( ) . map ( |cgu| ( cgu. name ( ) , vec ! [ cgu. name( ) ] ) ) . collect ( ) ;
115
+
116
+ // Merge the two smallest codegen units until the target size is
117
+ // reached.
118
+ while codegen_units. len ( ) > cx. target_cgu_count {
119
+ // Sort small cgus to the back
120
+ codegen_units. sort_by_cached_key ( |cgu| cmp:: Reverse ( cgu. size_estimate ( ) ) ) ;
121
+ let mut smallest = codegen_units. pop ( ) . unwrap ( ) ;
122
+ let second_smallest = codegen_units. last_mut ( ) . unwrap ( ) ;
123
+
124
+ // Move the mono-items from `smallest` to `second_smallest`
125
+ second_smallest. modify_size_estimate ( smallest. size_estimate ( ) ) ;
126
+ for ( k, v) in smallest. items_mut ( ) . drain ( ) {
127
+ second_smallest. items_mut ( ) . insert ( k, v) ;
143
128
}
144
129
145
- let cgu_name_builder = & mut CodegenUnitNameBuilder :: new ( cx. tcx ) ;
146
-
147
- if cx. tcx . sess . opts . incremental . is_some ( ) {
148
- // If we are doing incremental compilation, we want CGU names to
149
- // reflect the path of the source level module they correspond to.
150
- // For CGUs that contain the code of multiple modules because of the
151
- // merging done above, we use a concatenation of the names of all
152
- // contained CGUs.
153
- let new_cgu_names: FxHashMap < Symbol , String > = cgu_contents
154
- . into_iter ( )
155
- // This `filter` makes sure we only update the name of CGUs that
156
- // were actually modified by merging.
157
- . filter ( |( _, cgu_contents) | cgu_contents. len ( ) > 1 )
158
- . map ( |( current_cgu_name, cgu_contents) | {
159
- let mut cgu_contents: Vec < & str > =
160
- cgu_contents. iter ( ) . map ( |s| s. as_str ( ) ) . collect ( ) ;
161
-
162
- // Sort the names, so things are deterministic and easy to
163
- // predict. We are sorting primitive `&str`s here so we can
164
- // use unstable sort.
165
- cgu_contents. sort_unstable ( ) ;
166
-
167
- ( current_cgu_name, cgu_contents. join ( "--" ) )
168
- } )
169
- . collect ( ) ;
170
-
171
- for cgu in codegen_units. iter_mut ( ) {
172
- if let Some ( new_cgu_name) = new_cgu_names. get ( & cgu. name ( ) ) {
173
- if cx. tcx . sess . opts . unstable_opts . human_readable_cgu_names {
174
- cgu. set_name ( Symbol :: intern ( & new_cgu_name) ) ;
175
- } else {
176
- // If we don't require CGU names to be human-readable,
177
- // we use a fixed length hash of the composite CGU name
178
- // instead.
179
- let new_cgu_name = CodegenUnit :: mangle_name ( & new_cgu_name) ;
180
- cgu. set_name ( Symbol :: intern ( & new_cgu_name) ) ;
181
- }
130
+ // Record that `second_smallest` now contains all the stuff that was
131
+ // in `smallest` before.
132
+ let mut consumed_cgu_names = cgu_contents. remove ( & smallest. name ( ) ) . unwrap ( ) ;
133
+ cgu_contents. get_mut ( & second_smallest. name ( ) ) . unwrap ( ) . append ( & mut consumed_cgu_names) ;
134
+
135
+ debug ! (
136
+ "CodegenUnit {} merged into CodegenUnit {}" ,
137
+ smallest. name( ) ,
138
+ second_smallest. name( )
139
+ ) ;
140
+ }
141
+
142
+ let cgu_name_builder = & mut CodegenUnitNameBuilder :: new ( cx. tcx ) ;
143
+
144
+ if cx. tcx . sess . opts . incremental . is_some ( ) {
145
+ // If we are doing incremental compilation, we want CGU names to
146
+ // reflect the path of the source level module they correspond to.
147
+ // For CGUs that contain the code of multiple modules because of the
148
+ // merging done above, we use a concatenation of the names of all
149
+ // contained CGUs.
150
+ let new_cgu_names: FxHashMap < Symbol , String > = cgu_contents
151
+ . into_iter ( )
152
+ // This `filter` makes sure we only update the name of CGUs that
153
+ // were actually modified by merging.
154
+ . filter ( |( _, cgu_contents) | cgu_contents. len ( ) > 1 )
155
+ . map ( |( current_cgu_name, cgu_contents) | {
156
+ let mut cgu_contents: Vec < & str > = cgu_contents. iter ( ) . map ( |s| s. as_str ( ) ) . collect ( ) ;
157
+
158
+ // Sort the names, so things are deterministic and easy to
159
+ // predict. We are sorting primitive `&str`s here so we can
160
+ // use unstable sort.
161
+ cgu_contents. sort_unstable ( ) ;
162
+
163
+ ( current_cgu_name, cgu_contents. join ( "--" ) )
164
+ } )
165
+ . collect ( ) ;
166
+
167
+ for cgu in codegen_units. iter_mut ( ) {
168
+ if let Some ( new_cgu_name) = new_cgu_names. get ( & cgu. name ( ) ) {
169
+ if cx. tcx . sess . opts . unstable_opts . human_readable_cgu_names {
170
+ cgu. set_name ( Symbol :: intern ( & new_cgu_name) ) ;
171
+ } else {
172
+ // If we don't require CGU names to be human-readable,
173
+ // we use a fixed length hash of the composite CGU name
174
+ // instead.
175
+ let new_cgu_name = CodegenUnit :: mangle_name ( & new_cgu_name) ;
176
+ cgu. set_name ( Symbol :: intern ( & new_cgu_name) ) ;
182
177
}
183
178
}
184
- } else {
185
- // If we are compiling non-incrementally we just generate simple CGU
186
- // names containing an index.
187
- for ( index, cgu ) in codegen_units . iter_mut ( ) . enumerate ( ) {
188
- let numbered_codegen_unit_name =
189
- cgu_name_builder . build_cgu_name_no_mangle ( LOCAL_CRATE , & [ "cgu" ] , Some ( index ) ) ;
190
- cgu . set_name ( numbered_codegen_unit_name ) ;
191
- }
179
+ }
180
+ } else {
181
+ // If we are compiling non-incrementally we just generate simple CGU
182
+ // names containing an index.
183
+ for ( index , cgu ) in codegen_units . iter_mut ( ) . enumerate ( ) {
184
+ let numbered_codegen_unit_name =
185
+ cgu_name_builder . build_cgu_name_no_mangle ( LOCAL_CRATE , & [ "cgu" ] , Some ( index ) ) ;
186
+ cgu . set_name ( numbered_codegen_unit_name ) ;
192
187
}
193
188
}
189
+ }
194
190
195
- fn place_inlined_mono_items (
196
- & mut self ,
197
- cx : & PartitioningCx < ' _ , ' tcx > ,
198
- codegen_units : & mut [ CodegenUnit < ' tcx > ] ,
199
- roots : FxHashSet < MonoItem < ' tcx > > ,
200
- ) -> FxHashMap < MonoItem < ' tcx > , MonoItemPlacement > {
201
- let mut mono_item_placements = FxHashMap :: default ( ) ;
202
-
203
- let single_codegen_unit = codegen_units. len ( ) == 1 ;
204
-
205
- for old_codegen_unit in codegen_units. iter_mut ( ) {
206
- // Collect all items that need to be available in this codegen unit.
207
- let mut reachable = FxHashSet :: default ( ) ;
208
- for root in old_codegen_unit. items ( ) . keys ( ) {
209
- follow_inlining ( * root, cx. inlining_map , & mut reachable) ;
210
- }
191
+ pub ( super ) fn place_inlined_mono_items < ' tcx > (
192
+ cx : & PartitioningCx < ' _ , ' tcx > ,
193
+ codegen_units : & mut [ CodegenUnit < ' tcx > ] ,
194
+ roots : FxHashSet < MonoItem < ' tcx > > ,
195
+ ) -> FxHashMap < MonoItem < ' tcx > , MonoItemPlacement > {
196
+ let mut mono_item_placements = FxHashMap :: default ( ) ;
211
197
212
- let mut new_codegen_unit = CodegenUnit :: new ( old_codegen_unit . name ( ) ) ;
198
+ let single_codegen_unit = codegen_units . len ( ) == 1 ;
213
199
214
- // Add all monomorphizations that are not already there.
215
- for mono_item in reachable {
216
- if let Some ( linkage) = old_codegen_unit. items ( ) . get ( & mono_item) {
217
- // This is a root, just copy it over.
218
- new_codegen_unit. items_mut ( ) . insert ( mono_item, * linkage) ;
219
- } else {
220
- if roots. contains ( & mono_item) {
221
- bug ! (
222
- "GloballyShared mono-item inlined into other CGU: \
223
- {:?}",
224
- mono_item
225
- ) ;
226
- }
200
+ for old_codegen_unit in codegen_units. iter_mut ( ) {
201
+ // Collect all items that need to be available in this codegen unit.
202
+ let mut reachable = FxHashSet :: default ( ) ;
203
+ for root in old_codegen_unit. items ( ) . keys ( ) {
204
+ follow_inlining ( * root, cx. inlining_map , & mut reachable) ;
205
+ }
206
+
207
+ let mut new_codegen_unit = CodegenUnit :: new ( old_codegen_unit. name ( ) ) ;
227
208
228
- // This is a CGU-private copy.
229
- new_codegen_unit
230
- . items_mut ( )
231
- . insert ( mono_item, ( Linkage :: Internal , Visibility :: Default ) ) ;
209
+ // Add all monomorphizations that are not already there.
210
+ for mono_item in reachable {
211
+ if let Some ( linkage) = old_codegen_unit. items ( ) . get ( & mono_item) {
212
+ // This is a root, just copy it over.
213
+ new_codegen_unit. items_mut ( ) . insert ( mono_item, * linkage) ;
214
+ } else {
215
+ if roots. contains ( & mono_item) {
216
+ bug ! (
217
+ "GloballyShared mono-item inlined into other CGU: \
218
+ {:?}",
219
+ mono_item
220
+ ) ;
232
221
}
233
222
234
- if !single_codegen_unit {
235
- // If there is more than one codegen unit, we need to keep track
236
- // in which codegen units each monomorphization is placed.
237
- match mono_item_placements. entry ( mono_item) {
238
- Entry :: Occupied ( e) => {
239
- let placement = e. into_mut ( ) ;
240
- debug_assert ! ( match * placement {
241
- MonoItemPlacement :: SingleCgu { cgu_name } => {
242
- cgu_name != new_codegen_unit. name( )
243
- }
244
- MonoItemPlacement :: MultipleCgus => true ,
245
- } ) ;
246
- * placement = MonoItemPlacement :: MultipleCgus ;
247
- }
248
- Entry :: Vacant ( e) => {
249
- e. insert ( MonoItemPlacement :: SingleCgu {
250
- cgu_name : new_codegen_unit. name ( ) ,
251
- } ) ;
252
- }
223
+ // This is a CGU-private copy.
224
+ new_codegen_unit
225
+ . items_mut ( )
226
+ . insert ( mono_item, ( Linkage :: Internal , Visibility :: Default ) ) ;
227
+ }
228
+
229
+ if !single_codegen_unit {
230
+ // If there is more than one codegen unit, we need to keep track
231
+ // in which codegen units each monomorphization is placed.
232
+ match mono_item_placements. entry ( mono_item) {
233
+ Entry :: Occupied ( e) => {
234
+ let placement = e. into_mut ( ) ;
235
+ debug_assert ! ( match * placement {
236
+ MonoItemPlacement :: SingleCgu { cgu_name } => {
237
+ cgu_name != new_codegen_unit. name( )
238
+ }
239
+ MonoItemPlacement :: MultipleCgus => true ,
240
+ } ) ;
241
+ * placement = MonoItemPlacement :: MultipleCgus ;
242
+ }
243
+ Entry :: Vacant ( e) => {
244
+ e. insert ( MonoItemPlacement :: SingleCgu {
245
+ cgu_name : new_codegen_unit. name ( ) ,
246
+ } ) ;
253
247
}
254
248
}
255
249
}
256
-
257
- * old_codegen_unit = new_codegen_unit;
258
250
}
259
251
260
- return mono_item_placements;
261
-
262
- fn follow_inlining < ' tcx > (
263
- mono_item : MonoItem < ' tcx > ,
264
- inlining_map : & InliningMap < ' tcx > ,
265
- visited : & mut FxHashSet < MonoItem < ' tcx > > ,
266
- ) {
267
- if !visited. insert ( mono_item) {
268
- return ;
269
- }
270
-
271
- inlining_map. with_inlining_candidates ( mono_item, |target| {
272
- follow_inlining ( target, inlining_map, visited) ;
273
- } ) ;
274
- }
252
+ * old_codegen_unit = new_codegen_unit;
275
253
}
276
254
277
- fn internalize_symbols (
278
- & mut self ,
279
- cx : & PartitioningCx < ' _ , ' tcx > ,
280
- codegen_units : & mut [ CodegenUnit < ' tcx > ] ,
281
- mono_item_placements : FxHashMap < MonoItem < ' tcx > , MonoItemPlacement > ,
282
- internalization_candidates : FxHashSet < MonoItem < ' tcx > > ,
283
- ) {
284
- if codegen_units. len ( ) == 1 {
285
- // Fast path for when there is only one codegen unit. In this case we
286
- // can internalize all candidates, since there is nowhere else they
287
- // could be accessed from.
288
- for cgu in codegen_units {
289
- for candidate in & internalization_candidates {
290
- cgu. items_mut ( ) . insert ( * candidate, ( Linkage :: Internal , Visibility :: Default ) ) ;
291
- }
292
- }
255
+ return mono_item_placements;
293
256
257
+ fn follow_inlining < ' tcx > (
258
+ mono_item : MonoItem < ' tcx > ,
259
+ inlining_map : & InliningMap < ' tcx > ,
260
+ visited : & mut FxHashSet < MonoItem < ' tcx > > ,
261
+ ) {
262
+ if !visited. insert ( mono_item) {
294
263
return ;
295
264
}
296
265
297
- // Build a map from every monomorphization to all the monomorphizations that
298
- // reference it.
299
- let mut accessor_map: FxHashMap < MonoItem < ' tcx > , Vec < MonoItem < ' tcx > > > = Default :: default ( ) ;
300
- cx. inlining_map . iter_accesses ( |accessor, accessees| {
301
- for accessee in accessees {
302
- accessor_map. entry ( * accessee) . or_default ( ) . push ( accessor) ;
303
- }
266
+ inlining_map. with_inlining_candidates ( mono_item, |target| {
267
+ follow_inlining ( target, inlining_map, visited) ;
304
268
} ) ;
269
+ }
270
+ }
305
271
306
- // For each internalization candidates in each codegen unit, check if it is
307
- // accessed from outside its defining codegen unit.
272
+ pub ( super ) fn internalize_symbols < ' tcx > (
273
+ cx : & PartitioningCx < ' _ , ' tcx > ,
274
+ codegen_units : & mut [ CodegenUnit < ' tcx > ] ,
275
+ mono_item_placements : FxHashMap < MonoItem < ' tcx > , MonoItemPlacement > ,
276
+ internalization_candidates : FxHashSet < MonoItem < ' tcx > > ,
277
+ ) {
278
+ if codegen_units. len ( ) == 1 {
279
+ // Fast path for when there is only one codegen unit. In this case we
280
+ // can internalize all candidates, since there is nowhere else they
281
+ // could be accessed from.
308
282
for cgu in codegen_units {
309
- let home_cgu = MonoItemPlacement :: SingleCgu { cgu_name : cgu. name ( ) } ;
283
+ for candidate in & internalization_candidates {
284
+ cgu. items_mut ( ) . insert ( * candidate, ( Linkage :: Internal , Visibility :: Default ) ) ;
285
+ }
286
+ }
287
+
288
+ return ;
289
+ }
290
+
291
+ // Build a map from every monomorphization to all the monomorphizations that
292
+ // reference it.
293
+ let mut accessor_map: FxHashMap < MonoItem < ' tcx > , Vec < MonoItem < ' tcx > > > = Default :: default ( ) ;
294
+ cx. inlining_map . iter_accesses ( |accessor, accessees| {
295
+ for accessee in accessees {
296
+ accessor_map. entry ( * accessee) . or_default ( ) . push ( accessor) ;
297
+ }
298
+ } ) ;
310
299
311
- for ( accessee, linkage_and_visibility) in cgu. items_mut ( ) {
312
- if !internalization_candidates. contains ( accessee) {
313
- // This item is no candidate for internalizing, so skip it.
300
+ // For each internalization candidates in each codegen unit, check if it is
301
+ // accessed from outside its defining codegen unit.
302
+ for cgu in codegen_units {
303
+ let home_cgu = MonoItemPlacement :: SingleCgu { cgu_name : cgu. name ( ) } ;
304
+
305
+ for ( accessee, linkage_and_visibility) in cgu. items_mut ( ) {
306
+ if !internalization_candidates. contains ( accessee) {
307
+ // This item is no candidate for internalizing, so skip it.
308
+ continue ;
309
+ }
310
+ debug_assert_eq ! ( mono_item_placements[ accessee] , home_cgu) ;
311
+
312
+ if let Some ( accessors) = accessor_map. get ( accessee) {
313
+ if accessors
314
+ . iter ( )
315
+ . filter_map ( |accessor| {
316
+ // Some accessors might not have been
317
+ // instantiated. We can safely ignore those.
318
+ mono_item_placements. get ( accessor)
319
+ } )
320
+ . any ( |placement| * placement != home_cgu)
321
+ {
322
+ // Found an accessor from another CGU, so skip to the next
323
+ // item without marking this one as internal.
314
324
continue ;
315
325
}
316
- debug_assert_eq ! ( mono_item_placements[ accessee] , home_cgu) ;
317
-
318
- if let Some ( accessors) = accessor_map. get ( accessee) {
319
- if accessors
320
- . iter ( )
321
- . filter_map ( |accessor| {
322
- // Some accessors might not have been
323
- // instantiated. We can safely ignore those.
324
- mono_item_placements. get ( accessor)
325
- } )
326
- . any ( |placement| * placement != home_cgu)
327
- {
328
- // Found an accessor from another CGU, so skip to the next
329
- // item without marking this one as internal.
330
- continue ;
331
- }
332
- }
333
-
334
- // If we got here, we did not find any accesses from other CGUs,
335
- // so it's fine to make this monomorphization internal.
336
- * linkage_and_visibility = ( Linkage :: Internal , Visibility :: Default ) ;
337
326
}
327
+
328
+ // If we got here, we did not find any accesses from other CGUs,
329
+ // so it's fine to make this monomorphization internal.
330
+ * linkage_and_visibility = ( Linkage :: Internal , Visibility :: Default ) ;
338
331
}
339
332
}
340
333
}
0 commit comments