Skip to content

Commit 39a58c3

Browse files
committed
introduce the rather simpler symbol-cache in place of symbol-map
The symbol map is not good for incremental: it has inputs from every fn in existence, and it will change if anything changes. One could imagine cheating with the symbol-map and exempting it from the usual dependency tracking, since the results are fully deterministic. Instead, I opted to just add a per-CGU cache, on the premise that recomputing some symbol names is not going to be so very expensive.
1 parent 4c31750 commit 39a58c3

File tree

8 files changed

+95
-58
lines changed

8 files changed

+95
-58
lines changed

src/librustc_trans/base.rs

+8-9
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ use meth;
6565
use mir;
6666
use monomorphize::{self, Instance};
6767
use partitioning::{self, PartitioningStrategy, CodegenUnit};
68+
use symbol_cache::SymbolCache;
6869
use symbol_map::SymbolMap;
6970
use symbol_names_test;
7071
use trans_item::{TransItem, DefPathBasedNames};
@@ -75,7 +76,6 @@ use util::nodemap::{NodeSet, FxHashMap, FxHashSet};
7576

7677
use libc::c_uint;
7778
use std::ffi::{CStr, CString};
78-
use std::rc::Rc;
7979
use std::str;
8080
use std::i32;
8181
use syntax_pos::Span;
@@ -1113,8 +1113,6 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
11131113
let (translation_items, codegen_units, symbol_map) =
11141114
collect_and_partition_translation_items(&shared_ccx);
11151115

1116-
let symbol_map = Rc::new(symbol_map);
1117-
11181116
let mut all_stats = Stats::default();
11191117
let modules: Vec<ModuleTranslation> = codegen_units
11201118
.into_iter()
@@ -1123,7 +1121,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
11231121
let (stats, module) =
11241122
tcx.dep_graph.with_task(dep_node,
11251123
AssertDepGraphSafe(&shared_ccx),
1126-
AssertDepGraphSafe((cgu, symbol_map.clone())),
1124+
AssertDepGraphSafe(cgu),
11271125
module_translation);
11281126
all_stats.extend(stats);
11291127
module
@@ -1132,16 +1130,17 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
11321130

11331131
fn module_translation<'a, 'tcx>(
11341132
scx: AssertDepGraphSafe<&SharedCrateContext<'a, 'tcx>>,
1135-
args: AssertDepGraphSafe<(CodegenUnit<'tcx>, Rc<SymbolMap<'tcx>>)>)
1133+
args: AssertDepGraphSafe<CodegenUnit<'tcx>>)
11361134
-> (Stats, ModuleTranslation)
11371135
{
11381136
// FIXME(#40304): We ought to be using the id as a key and some queries, I think.
11391137
let AssertDepGraphSafe(scx) = scx;
1140-
let AssertDepGraphSafe((cgu, symbol_map)) = args;
1138+
let AssertDepGraphSafe(cgu) = args;
11411139

11421140
let cgu_name = String::from(cgu.name());
11431141
let cgu_id = cgu.work_product_id();
1144-
let symbol_name_hash = cgu.compute_symbol_name_hash(scx, &symbol_map);
1142+
let symbol_cache = SymbolCache::new(scx);
1143+
let symbol_name_hash = cgu.compute_symbol_name_hash(scx, &symbol_cache);
11451144

11461145
// Check whether there is a previous work-product we can
11471146
// re-use. Not only must the file exist, and the inputs not
@@ -1176,11 +1175,11 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
11761175
}
11771176

11781177
// Instantiate translation items without filling out definitions yet...
1179-
let lcx = LocalCrateContext::new(scx, cgu, symbol_map.clone());
1178+
let lcx = LocalCrateContext::new(scx, cgu, &symbol_cache);
11801179
let module = {
11811180
let ccx = CrateContext::new(scx, &lcx);
11821181
let trans_items = ccx.codegen_unit()
1183-
.items_in_deterministic_order(ccx.tcx(), &symbol_map);
1182+
.items_in_deterministic_order(ccx.tcx(), &symbol_cache);
11841183
for &(trans_item, linkage) in &trans_items {
11851184
trans_item.predefine(&ccx, linkage);
11861185
}

src/librustc_trans/callee.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ pub fn get_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
5151
return llfn;
5252
}
5353

54-
let sym = ccx.symbol_map().get_or_compute(ccx.shared(),
55-
TransItem::Fn(instance));
54+
let sym = ccx.symbol_cache().get(TransItem::Fn(instance));
5655
debug!("get_fn({:?}: {:?}) => {}", instance, fn_ty, sym);
5756

5857
// This is subtle and surprising, but sometimes we have to bitcast

src/librustc_trans/consts.rs

+4-5
Original file line numberDiff line numberDiff line change
@@ -93,20 +93,19 @@ pub fn get_static(ccx: &CrateContext, def_id: DefId) -> ValueRef {
9393
hir_map::NodeItem(&hir::Item {
9494
ref attrs, span, node: hir::ItemStatic(..), ..
9595
}) => {
96-
let sym = ccx.symbol_map()
97-
.get(TransItem::Static(id))
98-
.expect("Local statics should always be in the SymbolMap");
96+
let sym = ccx.symbol_cache()
97+
.get(TransItem::Static(id));
9998

10099
let defined_in_current_codegen_unit = ccx.codegen_unit()
101100
.items()
102101
.contains_key(&TransItem::Static(id));
103102
assert!(!defined_in_current_codegen_unit);
104103

105-
if declare::get_declared_value(ccx, sym).is_some() {
104+
if declare::get_declared_value(ccx, &sym[..]).is_some() {
106105
span_bug!(span, "trans: Conflicting symbol names for static?");
107106
}
108107

109-
let g = declare::define_global(ccx, sym, llty).unwrap();
108+
let g = declare::define_global(ccx, &sym[..], llty).unwrap();
110109

111110
(g, attrs)
112111
}

src/librustc_trans/context.rs

+19-20
Original file line numberDiff line numberDiff line change
@@ -29,15 +29,14 @@ use rustc::ty::layout::{LayoutTyper, TyLayout};
2929
use session::config::NoDebugInfo;
3030
use session::Session;
3131
use session::config;
32-
use symbol_map::SymbolMap;
32+
use symbol_cache::SymbolCache;
3333
use util::nodemap::{NodeSet, DefIdMap, FxHashMap};
3434

3535
use std::ffi::{CStr, CString};
3636
use std::cell::{Cell, RefCell};
3737
use std::marker::PhantomData;
3838
use std::ptr;
3939
use std::iter;
40-
use std::rc::Rc;
4140
use std::str;
4241
use syntax::ast;
4342
use syntax::symbol::InternedString;
@@ -94,7 +93,7 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
9493
/// per compilation unit. Each one has its own LLVM `ContextRef` so that
9594
/// several compilation units may be optimized in parallel. All other LLVM
9695
/// data structures in the `LocalCrateContext` are tied to that `ContextRef`.
97-
pub struct LocalCrateContext<'tcx> {
96+
pub struct LocalCrateContext<'a, 'tcx: 'a> {
9897
llmod: ModuleRef,
9998
llcx: ContextRef,
10099
stats: Stats,
@@ -166,10 +165,10 @@ pub struct LocalCrateContext<'tcx> {
166165
/// Depth of the current type-of computation - used to bail out
167166
type_of_depth: Cell<usize>,
168167

169-
symbol_map: Rc<SymbolMap<'tcx>>,
170-
171168
/// A counter that is used for generating local symbol names
172169
local_gen_sym_counter: Cell<usize>,
170+
171+
symbol_cache: &'a SymbolCache<'a, 'tcx>,
173172
}
174173

175174
// Implement DepTrackingMapConfig for `trait_cache`
@@ -227,12 +226,12 @@ impl<'gcx> DepTrackingMapConfig for ProjectionCache<'gcx> {
227226
/// pass around (SharedCrateContext, LocalCrateContext) tuples all over trans.
228227
pub struct CrateContext<'a, 'tcx: 'a> {
229228
shared: &'a SharedCrateContext<'a, 'tcx>,
230-
local_ccx: &'a LocalCrateContext<'tcx>,
229+
local_ccx: &'a LocalCrateContext<'a, 'tcx>,
231230
}
232231

233232
impl<'a, 'tcx> CrateContext<'a, 'tcx> {
234233
pub fn new(shared: &'a SharedCrateContext<'a, 'tcx>,
235-
local_ccx: &'a LocalCrateContext<'tcx>)
234+
local_ccx: &'a LocalCrateContext<'a, 'tcx>)
236235
-> Self {
237236
CrateContext { shared, local_ccx }
238237
}
@@ -429,11 +428,11 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
429428
}
430429
}
431430

432-
impl<'tcx> LocalCrateContext<'tcx> {
433-
pub fn new<'a>(shared: &SharedCrateContext<'a, 'tcx>,
434-
codegen_unit: CodegenUnit<'tcx>,
435-
symbol_map: Rc<SymbolMap<'tcx>>)
436-
-> LocalCrateContext<'tcx> {
431+
impl<'a, 'tcx> LocalCrateContext<'a, 'tcx> {
432+
pub fn new(shared: &SharedCrateContext<'a, 'tcx>,
433+
codegen_unit: CodegenUnit<'tcx>,
434+
symbol_cache: &'a SymbolCache<'a, 'tcx>)
435+
-> LocalCrateContext<'a, 'tcx> {
437436
unsafe {
438437
// Append ".rs" to LLVM module identifier.
439438
//
@@ -487,8 +486,8 @@ impl<'tcx> LocalCrateContext<'tcx> {
487486
rust_try_fn: Cell::new(None),
488487
intrinsics: RefCell::new(FxHashMap()),
489488
type_of_depth: Cell::new(0),
490-
symbol_map: symbol_map,
491489
local_gen_sym_counter: Cell::new(0),
490+
symbol_cache: symbol_cache,
492491
};
493492

494493
let (int_type, opaque_vec_type, str_slice_ty, mut local_ccx) = {
@@ -522,9 +521,9 @@ impl<'tcx> LocalCrateContext<'tcx> {
522521
/// This is used in the `LocalCrateContext` constructor to allow calling
523522
/// functions that expect a complete `CrateContext`, even before the local
524523
/// portion is fully initialized and attached to the `SharedCrateContext`.
525-
fn dummy_ccx<'a>(shared: &'a SharedCrateContext<'a, 'tcx>,
526-
local_ccxs: &'a [LocalCrateContext<'tcx>])
527-
-> CrateContext<'a, 'tcx> {
524+
fn dummy_ccx(shared: &'a SharedCrateContext<'a, 'tcx>,
525+
local_ccxs: &'a [LocalCrateContext<'a, 'tcx>])
526+
-> CrateContext<'a, 'tcx> {
528527
assert!(local_ccxs.len() == 1);
529528
CrateContext {
530529
shared: shared,
@@ -542,7 +541,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
542541
self.shared
543542
}
544543

545-
fn local(&self) -> &'b LocalCrateContext<'tcx> {
544+
fn local(&self) -> &'b LocalCrateContext<'b, 'tcx> {
546545
self.local_ccx
547546
}
548547

@@ -709,8 +708,8 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
709708
self.shared.use_dll_storage_attrs()
710709
}
711710

712-
pub fn symbol_map(&self) -> &SymbolMap<'tcx> {
713-
&*self.local().symbol_map
711+
pub fn symbol_cache(&self) -> &'b SymbolCache<'b, 'tcx> {
712+
self.local().symbol_cache
714713
}
715714

716715
/// Given the def-id of some item that has no type parameters, make
@@ -856,7 +855,7 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a CrateContext<'a, 'tcx> {
856855
}
857856
}
858857

859-
pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'tcx>);
858+
pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'a, 'tcx>);
860859

861860
impl<'a, 'tcx> Drop for TypeOfDepthLock<'a, 'tcx> {
862861
fn drop(&mut self) {

src/librustc_trans/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,7 @@ mod meth;
124124
mod mir;
125125
mod monomorphize;
126126
mod partitioning;
127+
mod symbol_cache;
127128
mod symbol_map;
128129
mod symbol_names_test;
129130
mod trans_item;

src/librustc_trans/partitioning.rs

+19-20
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ use rustc_incremental::IchHasher;
116116
use std::cmp::Ordering;
117117
use std::hash::Hash;
118118
use std::sync::Arc;
119-
use symbol_map::SymbolMap;
119+
use symbol_cache::SymbolCache;
120120
use syntax::ast::NodeId;
121121
use syntax::symbol::{Symbol, InternedString};
122122
use trans_item::{TransItem, InstantiationMode};
@@ -174,14 +174,15 @@ impl<'tcx> CodegenUnit<'tcx> {
174174
DepNode::WorkProduct(self.work_product_id())
175175
}
176176

177-
pub fn compute_symbol_name_hash(&self,
178-
scx: &SharedCrateContext,
179-
symbol_map: &SymbolMap) -> u64 {
177+
pub fn compute_symbol_name_hash<'a>(&self,
178+
scx: &SharedCrateContext<'a, 'tcx>,
179+
symbol_cache: &SymbolCache<'a, 'tcx>)
180+
-> u64 {
180181
let mut state = IchHasher::new();
181182
let exported_symbols = scx.exported_symbols();
182-
let all_items = self.items_in_deterministic_order(scx.tcx(), symbol_map);
183+
let all_items = self.items_in_deterministic_order(scx.tcx(), symbol_cache);
183184
for (item, _) in all_items {
184-
let symbol_name = symbol_map.get(item).unwrap();
185+
let symbol_name = symbol_cache.get(item);
185186
symbol_name.len().hash(&mut state);
186187
symbol_name.hash(&mut state);
187188
let exported = match item {
@@ -201,10 +202,10 @@ impl<'tcx> CodegenUnit<'tcx> {
201202
state.finish().to_smaller_hash()
202203
}
203204

204-
pub fn items_in_deterministic_order(&self,
205-
tcx: TyCtxt,
206-
symbol_map: &SymbolMap)
207-
-> Vec<(TransItem<'tcx>, llvm::Linkage)> {
205+
pub fn items_in_deterministic_order<'a>(&self,
206+
tcx: TyCtxt,
207+
symbol_cache: &SymbolCache<'a, 'tcx>)
208+
-> Vec<(TransItem<'tcx>, llvm::Linkage)> {
208209
let mut items: Vec<(TransItem<'tcx>, llvm::Linkage)> =
209210
self.items.iter().map(|(item, linkage)| (*item, *linkage)).collect();
210211

@@ -216,9 +217,9 @@ impl<'tcx> CodegenUnit<'tcx> {
216217

217218
match (node_id1, node_id2) {
218219
(None, None) => {
219-
let symbol_name1 = symbol_map.get(trans_item1).unwrap();
220-
let symbol_name2 = symbol_map.get(trans_item2).unwrap();
221-
symbol_name1.cmp(symbol_name2)
220+
let symbol_name1 = symbol_cache.get(trans_item1);
221+
let symbol_name2 = symbol_cache.get(trans_item2);
222+
symbol_name1.cmp(&symbol_name2)
222223
}
223224
// In the following two cases we can avoid looking up the symbol
224225
(None, Some(_)) => Ordering::Less,
@@ -230,9 +231,9 @@ impl<'tcx> CodegenUnit<'tcx> {
230231
return ordering;
231232
}
232233

233-
let symbol_name1 = symbol_map.get(trans_item1).unwrap();
234-
let symbol_name2 = symbol_map.get(trans_item2).unwrap();
235-
symbol_name1.cmp(symbol_name2)
234+
let symbol_name1 = symbol_cache.get(trans_item1);
235+
let symbol_name2 = symbol_cache.get(trans_item2);
236+
symbol_name1.cmp(&symbol_name2)
236237
}
237238
}
238239
});
@@ -536,14 +537,12 @@ fn debug_dump<'a, 'b, 'tcx, I>(scx: &SharedCrateContext<'a, 'tcx>,
536537
{
537538
if cfg!(debug_assertions) {
538539
debug!("{}", label);
540+
let symbol_cache = SymbolCache::new(scx);
539541
for cgu in cgus {
540-
let symbol_map = SymbolMap::build(scx, cgu.items
541-
.iter()
542-
.map(|(&trans_item, _)| trans_item));
543542
debug!("CodegenUnit {}:", cgu.name);
544543

545544
for (trans_item, linkage) in &cgu.items {
546-
let symbol_name = symbol_map.get_or_compute(scx, *trans_item);
545+
let symbol_name = symbol_cache.get(*trans_item);
547546
let symbol_hash_start = symbol_name.rfind('h');
548547
let symbol_hash = symbol_hash_start.map(|i| &symbol_name[i ..])
549548
.unwrap_or("<no hash>");

src/librustc_trans/symbol_cache.rs

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Copyright 2016 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
use context::SharedCrateContext;
12+
use std::cell::RefCell;
13+
use std::rc::Rc;
14+
use trans_item::TransItem;
15+
use util::nodemap::FxHashMap;
16+
17+
// In the SymbolCache we collect the symbol names of translation items
18+
// and cache them for later reference. This is just a performance
19+
// optimization and the cache is populated lazilly; symbol names of
20+
// translation items are deterministic and fully defined by the item.
21+
// Thus they can always be recomputed if needed.
22+
23+
pub struct SymbolCache<'a, 'tcx: 'a> {
24+
scx: &'a SharedCrateContext<'a, 'tcx>,
25+
index: RefCell<FxHashMap<TransItem<'tcx>, Rc<String>>>,
26+
}
27+
28+
impl<'a, 'tcx> SymbolCache<'a, 'tcx> {
29+
pub fn new(scx: &'a SharedCrateContext<'a, 'tcx>) -> Self {
30+
SymbolCache {
31+
scx,
32+
index: RefCell::new(FxHashMap())
33+
}
34+
}
35+
36+
pub fn get(&self, trans_item: TransItem<'tcx>) -> Rc<String> {
37+
let mut index = self.index.borrow_mut();
38+
index.entry(trans_item)
39+
.or_insert_with(|| Rc::new(trans_item.compute_symbol_name(self.scx)))
40+
.clone()
41+
}
42+
}

src/librustc_trans/trans_item.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -118,8 +118,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
118118
self.to_raw_string(),
119119
ccx.codegen_unit().name());
120120

121-
let symbol_name = ccx.symbol_map()
122-
.get_or_compute(ccx.shared(), *self);
121+
let symbol_name = ccx.symbol_cache().get(*self);
123122

124123
debug!("symbol {}", &symbol_name);
125124

0 commit comments

Comments
 (0)