|
1 | 1 | use std::borrow::Cow;
|
| 2 | +use std::cmp::Ordering; |
2 | 3 | use std::fmt;
|
3 | 4 | use std::hash::Hash;
|
4 | 5 |
|
5 | 6 | use rustc_ast::expand::autodiff_attrs::AutoDiffItem;
|
6 | 7 | use rustc_attr_data_structures::InlineAttr;
|
7 | 8 | use rustc_data_structures::base_n::{BaseNString, CASE_INSENSITIVE, ToBaseN};
|
8 | 9 | use rustc_data_structures::fingerprint::Fingerprint;
|
9 |
| -use rustc_data_structures::fx::FxIndexMap; |
| 10 | +use rustc_data_structures::fx::{FxHashMap, FxIndexMap}; |
10 | 11 | use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
|
11 | 12 | use rustc_data_structures::unord::UnordMap;
|
12 | 13 | use rustc_hashes::Hash128;
|
@@ -526,23 +527,77 @@ impl<'tcx> CodegenUnit<'tcx> {
|
526 | 527 | ) -> Vec<(MonoItem<'tcx>, MonoItemData)> {
|
527 | 528 | // The codegen tests rely on items being process in the same order as
|
528 | 529 | // they appear in the file, so for local items, we sort by span and def_path first
|
529 |
| - #[derive(PartialEq, Eq, PartialOrd, Ord)] |
530 |
| - struct ItemSortKey<'tcx>(Option<Span>, Option<String>, SymbolName<'tcx>); |
531 |
| - |
532 |
| - fn item_sort_key<'tcx>(tcx: TyCtxt<'tcx>, item: MonoItem<'tcx>) -> ItemSortKey<'tcx> { |
533 |
| - ItemSortKey( |
534 |
| - // For codegen tests purposes, we don't care about non-local items' order, |
535 |
| - // so we just sort non-local items by symbol names. |
536 |
| - item.local_span(tcx), |
537 |
| - item.def_id() |
538 |
| - .as_local() |
539 |
| - .map(|_| tcx.def_path(item.def_id()).to_string_no_crate_verbose()), |
540 |
| - item.symbol_name(tcx), |
541 |
| - ) |
| 530 | + struct ItemSortKey<'tcx>(Option<Span>, Option<String>, Option<SymbolName<'tcx>>); |
| 531 | + |
| 532 | + // Avoids def_path querying for items that have different spans |
| 533 | + fn item_sort<'tcx>( |
| 534 | + tcx: TyCtxt<'tcx>, |
| 535 | + cached_keys_map: &'_ mut FxHashMap<MonoItem<'tcx>, ItemSortKey<'tcx>>, |
| 536 | + item1: MonoItem<'tcx>, |
| 537 | + item2: MonoItem<'tcx>, |
| 538 | + ) -> Ordering { |
| 539 | + let is_local1 = item1.def_id().is_local(); |
| 540 | + let is_local2 = item2.def_id().is_local(); |
| 541 | + |
| 542 | + match (is_local1, is_local2) { |
| 543 | + (false, false) => { |
| 544 | + cached_keys_map |
| 545 | + .entry(item1) |
| 546 | + .or_insert_with(|| ItemSortKey(None, None, Some(item1.symbol_name(tcx)))); |
| 547 | + cached_keys_map |
| 548 | + .entry(item2) |
| 549 | + .or_insert_with(|| ItemSortKey(None, None, Some(item2.symbol_name(tcx)))); |
| 550 | + let ItemSortKey(_, _, name1) = &cached_keys_map[&item1]; |
| 551 | + let ItemSortKey(_, _, name2) = &cached_keys_map[&item2]; |
| 552 | + name1.cmp(name2) |
| 553 | + } |
| 554 | + (false, true) => Ordering::Less, |
| 555 | + (true, false) => Ordering::Greater, |
| 556 | + (true, true) => { |
| 557 | + cached_keys_map |
| 558 | + .entry(item1) |
| 559 | + .or_insert_with(|| ItemSortKey(item1.local_span(tcx), None, None)); |
| 560 | + cached_keys_map |
| 561 | + .entry(item2) |
| 562 | + .or_insert_with(|| ItemSortKey(item2.local_span(tcx), None, None)); |
| 563 | + let ItemSortKey(span1, _, _) = &cached_keys_map[&item1]; |
| 564 | + let ItemSortKey(span2, _, _) = &cached_keys_map[&item2]; |
| 565 | + let ord = span1.cmp(span2); |
| 566 | + if ord != Ordering::Equal { |
| 567 | + return ord; |
| 568 | + } |
| 569 | + |
| 570 | + cached_keys_map.entry(item1).and_modify( |
| 571 | + |ItemSortKey(_, def_path, symbol_name)| { |
| 572 | + def_path.get_or_insert_with(|| { |
| 573 | + tcx.def_path(item1.def_id()).to_string_no_crate_verbose() |
| 574 | + }); |
| 575 | + symbol_name.get_or_insert_with(|| item1.symbol_name(tcx)); |
| 576 | + }, |
| 577 | + ); |
| 578 | + cached_keys_map.entry(item2).and_modify( |
| 579 | + |ItemSortKey(_, def_path, symbol_name)| { |
| 580 | + def_path.get_or_insert_with(|| { |
| 581 | + tcx.def_path(item2.def_id()).to_string_no_crate_verbose() |
| 582 | + }); |
| 583 | + symbol_name.get_or_insert_with(|| item2.symbol_name(tcx)); |
| 584 | + }, |
| 585 | + ); |
| 586 | + let ItemSortKey(_, def_path1, name1) = &cached_keys_map[&item1]; |
| 587 | + let ItemSortKey(_, def_path2, name2) = &cached_keys_map[&item2]; |
| 588 | + match def_path1.cmp(def_path2) { |
| 589 | + Ordering::Equal => name1.cmp(name2), |
| 590 | + other => other, |
| 591 | + } |
| 592 | + } |
| 593 | + } |
542 | 594 | }
|
543 | 595 |
|
544 | 596 | let mut items: Vec<_> = self.items().iter().map(|(&i, &data)| (i, data)).collect();
|
545 |
| - items.sort_by_cached_key(|&(i, _)| item_sort_key(tcx, i)); |
| 597 | + let mut cached_keys_map = |
| 598 | + FxHashMap::with_capacity_and_hasher(items.len(), Default::default()); |
| 599 | + items |
| 600 | + .sort_by(|&(item1, _), &(item2, _)| item_sort(tcx, &mut cached_keys_map, item1, item2)); |
546 | 601 | items
|
547 | 602 | }
|
548 | 603 |
|
|
0 commit comments