188
188
//! this is not implemented however: a translation item will be produced
189
189
//! regardless of whether it is actually needed or not.
190
190
191
+ use rustc_data_structures:: bitvec:: BitVector ;
192
+
191
193
use rustc:: hir;
192
194
use rustc:: hir:: intravisit as hir_visit;
193
195
@@ -252,12 +254,74 @@ impl<'tcx> Hash for TransItem<'tcx> {
252
254
}
253
255
}
254
256
255
- pub type InliningMap < ' tcx > = FnvHashMap < TransItem < ' tcx > , FnvHashSet < TransItem < ' tcx > > > ;
257
+ /// Maps every translation item to all translation items it references in its
258
+ /// body.
259
+ pub struct ReferenceMap < ' tcx > {
260
+ index : FnvHashMap < TransItem < ' tcx > , ( usize , usize ) > ,
261
+ targets : Vec < TransItem < ' tcx > > ,
262
+ inlined : BitVector
263
+ }
264
+
265
+ impl < ' tcx > ReferenceMap < ' tcx > {
266
+
267
+ fn new ( ) -> ReferenceMap < ' tcx > {
268
+ ReferenceMap {
269
+ index : FnvHashMap ( ) ,
270
+ targets : Vec :: new ( ) ,
271
+ inlined : BitVector :: new ( 64 * 256 ) ,
272
+ }
273
+ }
274
+
275
+ fn record_references < I > ( & mut self , source : TransItem < ' tcx > , targets : I )
276
+ where I : Iterator < Item =( TransItem < ' tcx > , bool ) >
277
+ {
278
+ assert ! ( !self . index. contains_key( & source) ) ;
279
+
280
+ let start_index = self . targets . len ( ) ;
281
+
282
+ for ( target, inlined) in targets {
283
+ let index = self . targets . len ( ) ;
284
+ self . targets . push ( target) ;
285
+ self . inlined . grow ( index + 1 ) ;
286
+
287
+ if inlined {
288
+ self . inlined . insert ( index) ;
289
+ }
290
+ }
291
+
292
+ let end_index = self . targets . len ( ) ;
293
+ self . index . insert ( source, ( start_index, end_index) ) ;
294
+ }
295
+
296
+ // Internally iterate over all items referenced by `source` which will be
297
+ // made available for inlining.
298
+ pub fn with_inlining_candidates < F > ( & self , source : TransItem < ' tcx > , mut f : F )
299
+ where F : FnMut ( TransItem < ' tcx > )
300
+ {
301
+ if let Some ( & ( start_index, end_index) ) = self . index . get ( & source)
302
+ {
303
+ for index in start_index .. end_index {
304
+ if self . inlined . contains ( index) {
305
+ f ( self . targets [ index] )
306
+ }
307
+ }
308
+ }
309
+ }
310
+
311
+ pub fn get_direct_references_from ( & self , source : TransItem < ' tcx > ) -> & [ TransItem < ' tcx > ]
312
+ {
313
+ if let Some ( & ( start_index, end_index) ) = self . index . get ( & source) {
314
+ & self . targets [ start_index .. end_index]
315
+ } else {
316
+ & self . targets [ 0 .. 0 ]
317
+ }
318
+ }
319
+ }
256
320
257
321
pub fn collect_crate_translation_items < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
258
322
mode : TransItemCollectionMode )
259
323
-> ( FnvHashSet < TransItem < ' tcx > > ,
260
- InliningMap < ' tcx > ) {
324
+ ReferenceMap < ' tcx > ) {
261
325
// We are not tracking dependencies of this pass as it has to be re-executed
262
326
// every time no matter what.
263
327
ccx. tcx ( ) . dep_graph . with_ignore ( || {
@@ -266,17 +330,17 @@ pub fn collect_crate_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
266
330
debug ! ( "Building translation item graph, beginning at roots" ) ;
267
331
let mut visited = FnvHashSet ( ) ;
268
332
let mut recursion_depths = DefIdMap ( ) ;
269
- let mut inlining_map = FnvHashMap ( ) ;
333
+ let mut reference_map = ReferenceMap :: new ( ) ;
270
334
271
335
for root in roots {
272
336
collect_items_rec ( ccx,
273
337
root,
274
338
& mut visited,
275
339
& mut recursion_depths,
276
- & mut inlining_map ) ;
340
+ & mut reference_map ) ;
277
341
}
278
342
279
- ( visited, inlining_map )
343
+ ( visited, reference_map )
280
344
} )
281
345
}
282
346
@@ -307,7 +371,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
307
371
starting_point : TransItem < ' tcx > ,
308
372
visited : & mut FnvHashSet < TransItem < ' tcx > > ,
309
373
recursion_depths : & mut DefIdMap < usize > ,
310
- inlining_map : & mut InliningMap < ' tcx > ) {
374
+ reference_map : & mut ReferenceMap < ' tcx > ) {
311
375
if !visited. insert ( starting_point. clone ( ) ) {
312
376
// We've been here already, no need to search again.
313
377
return ;
@@ -351,9 +415,10 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
351
415
}
352
416
}
353
417
418
+ record_references ( ccx, starting_point, & neighbors[ ..] , reference_map) ;
419
+
354
420
for neighbour in neighbors {
355
- record_inlined_use ( ccx, starting_point, neighbour, inlining_map) ;
356
- collect_items_rec ( ccx, neighbour, visited, recursion_depths, inlining_map) ;
421
+ collect_items_rec ( ccx, neighbour, visited, recursion_depths, reference_map) ;
357
422
}
358
423
359
424
if let Some ( ( def_id, depth) ) = recursion_depth_reset {
@@ -363,16 +428,17 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
363
428
debug ! ( "END collect_items_rec({})" , starting_point. to_string( ccx) ) ;
364
429
}
365
430
366
- fn record_inlined_use < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
367
- caller : TransItem < ' tcx > ,
368
- callee : TransItem < ' tcx > ,
369
- inlining_map : & mut InliningMap < ' tcx > ) {
370
- if callee. is_from_extern_crate ( ) ||
371
- callee. requests_inline ( ccx. tcx ( ) ) {
372
- inlining_map. entry ( caller)
373
- . or_insert_with ( || FnvHashSet ( ) )
374
- . insert ( callee) ;
375
- }
431
+ fn record_references < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
432
+ caller : TransItem < ' tcx > ,
433
+ callees : & [ TransItem < ' tcx > ] ,
434
+ reference_map : & mut ReferenceMap < ' tcx > ) {
435
+ let iter = callees. into_iter ( )
436
+ . map ( |callee| {
437
+ let is_inlining_candidate = callee. is_from_extern_crate ( ) ||
438
+ callee. requests_inline ( ccx. tcx ( ) ) ;
439
+ ( * callee, is_inlining_candidate)
440
+ } ) ;
441
+ reference_map. record_references ( caller, iter) ;
376
442
}
377
443
378
444
fn check_recursion_limit < ' a , ' tcx : ' a > ( ccx : & CrateContext < ' a , ' tcx > ,
0 commit comments