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,76 @@ 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
+ // Maps a source translation item to a range of target translation items.
261
+ // The two numbers in the tuple are the start (inclusive) and
262
+ // end index (exclusive) within the `targets` and the `inlined` vecs.
263
+ index : FnvHashMap < TransItem < ' tcx > , ( usize , usize ) > ,
264
+ targets : Vec < TransItem < ' tcx > > ,
265
+ inlined : BitVector
266
+ }
267
+
268
+ impl < ' tcx > ReferenceMap < ' tcx > {
269
+
270
+ fn new ( ) -> ReferenceMap < ' tcx > {
271
+ ReferenceMap {
272
+ index : FnvHashMap ( ) ,
273
+ targets : Vec :: new ( ) ,
274
+ inlined : BitVector :: new ( 64 * 256 ) ,
275
+ }
276
+ }
277
+
278
+ fn record_references < I > ( & mut self , source : TransItem < ' tcx > , targets : I )
279
+ where I : Iterator < Item =( TransItem < ' tcx > , bool ) >
280
+ {
281
+ assert ! ( !self . index. contains_key( & source) ) ;
282
+
283
+ let start_index = self . targets . len ( ) ;
284
+
285
+ for ( target, inlined) in targets {
286
+ let index = self . targets . len ( ) ;
287
+ self . targets . push ( target) ;
288
+ self . inlined . grow ( index + 1 ) ;
289
+
290
+ if inlined {
291
+ self . inlined . insert ( index) ;
292
+ }
293
+ }
294
+
295
+ let end_index = self . targets . len ( ) ;
296
+ self . index . insert ( source, ( start_index, end_index) ) ;
297
+ }
298
+
299
+ // Internally iterate over all items referenced by `source` which will be
300
+ // made available for inlining.
301
+ pub fn with_inlining_candidates < F > ( & self , source : TransItem < ' tcx > , mut f : F )
302
+ where F : FnMut ( TransItem < ' tcx > ) {
303
+ if let Some ( & ( start_index, end_index) ) = self . index . get ( & source)
304
+ {
305
+ for index in start_index .. end_index {
306
+ if self . inlined . contains ( index) {
307
+ f ( self . targets [ index] )
308
+ }
309
+ }
310
+ }
311
+ }
312
+
313
+ pub fn get_direct_references_from ( & self , source : TransItem < ' tcx > ) -> & [ TransItem < ' tcx > ]
314
+ {
315
+ if let Some ( & ( start_index, end_index) ) = self . index . get ( & source) {
316
+ & self . targets [ start_index .. end_index]
317
+ } else {
318
+ & self . targets [ 0 .. 0 ]
319
+ }
320
+ }
321
+ }
256
322
257
323
pub fn collect_crate_translation_items < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
258
324
mode : TransItemCollectionMode )
259
325
-> ( FnvHashSet < TransItem < ' tcx > > ,
260
- InliningMap < ' tcx > ) {
326
+ ReferenceMap < ' tcx > ) {
261
327
// We are not tracking dependencies of this pass as it has to be re-executed
262
328
// every time no matter what.
263
329
ccx. tcx ( ) . dep_graph . with_ignore ( || {
@@ -266,17 +332,17 @@ pub fn collect_crate_translation_items<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
266
332
debug ! ( "Building translation item graph, beginning at roots" ) ;
267
333
let mut visited = FnvHashSet ( ) ;
268
334
let mut recursion_depths = DefIdMap ( ) ;
269
- let mut inlining_map = FnvHashMap ( ) ;
335
+ let mut reference_map = ReferenceMap :: new ( ) ;
270
336
271
337
for root in roots {
272
338
collect_items_rec ( ccx,
273
339
root,
274
340
& mut visited,
275
341
& mut recursion_depths,
276
- & mut inlining_map ) ;
342
+ & mut reference_map ) ;
277
343
}
278
344
279
- ( visited, inlining_map )
345
+ ( visited, reference_map )
280
346
} )
281
347
}
282
348
@@ -307,7 +373,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
307
373
starting_point : TransItem < ' tcx > ,
308
374
visited : & mut FnvHashSet < TransItem < ' tcx > > ,
309
375
recursion_depths : & mut DefIdMap < usize > ,
310
- inlining_map : & mut InliningMap < ' tcx > ) {
376
+ reference_map : & mut ReferenceMap < ' tcx > ) {
311
377
if !visited. insert ( starting_point. clone ( ) ) {
312
378
// We've been here already, no need to search again.
313
379
return ;
@@ -351,9 +417,10 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
351
417
}
352
418
}
353
419
420
+ record_references ( ccx, starting_point, & neighbors[ ..] , reference_map) ;
421
+
354
422
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) ;
423
+ collect_items_rec ( ccx, neighbour, visited, recursion_depths, reference_map) ;
357
424
}
358
425
359
426
if let Some ( ( def_id, depth) ) = recursion_depth_reset {
@@ -363,16 +430,17 @@ fn collect_items_rec<'a, 'tcx: 'a>(ccx: &CrateContext<'a, 'tcx>,
363
430
debug ! ( "END collect_items_rec({})" , starting_point. to_string( ccx) ) ;
364
431
}
365
432
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
- }
433
+ fn record_references < ' a , ' tcx > ( ccx : & CrateContext < ' a , ' tcx > ,
434
+ caller : TransItem < ' tcx > ,
435
+ callees : & [ TransItem < ' tcx > ] ,
436
+ reference_map : & mut ReferenceMap < ' tcx > ) {
437
+ let iter = callees. into_iter ( )
438
+ . map ( |callee| {
439
+ let is_inlining_candidate = callee. is_from_extern_crate ( ) ||
440
+ callee. requests_inline ( ccx. tcx ( ) ) ;
441
+ ( * callee, is_inlining_candidate)
442
+ } ) ;
443
+ reference_map. record_references ( caller, iter) ;
376
444
}
377
445
378
446
fn check_recursion_limit < ' a , ' tcx : ' a > ( ccx : & CrateContext < ' a , ' tcx > ,
0 commit comments