diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 4fa475e99b56..a3f5dc4257b9 100644 --- a/src/librustc/driver/driver.rs +++ b/src/librustc/driver/driver.rs @@ -212,7 +212,7 @@ pub struct CrateAnalysis { exported_items: middle::privacy::ExportedItems, ty_cx: ty::ctxt, maps: astencode::Maps, - reachable: @mut HashSet + reachable: @RefCell> } /// Run the resolution, typechecking, region checking and other @@ -309,9 +309,16 @@ pub fn phase_3_run_analysis_passes(sess: Session, time(time_passes, "reachability checking", (), |_| reachable::find_reachable(ty_cx, method_map, &exported_items)); - time(time_passes, "death checking", (), |_| - middle::dead::check_crate(ty_cx, method_map, - &exported_items, reachable_map, crate)); + { + let reachable_map = reachable_map.borrow(); + time(time_passes, "death checking", (), |_| { + middle::dead::check_crate(ty_cx, + method_map, + &exported_items, + reachable_map.get(), + crate) + }); + } time(time_passes, "lint checking", (), |_| lint::check_crate(ty_cx, method_map, &exported_items, crate)); diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs index 33bf24fcbc66..140a53880db7 100644 --- a/src/librustc/metadata/encoder.rs +++ b/src/librustc/metadata/encoder.rs @@ -65,7 +65,7 @@ pub struct EncodeParams<'a> { link_meta: &'a LinkMeta, cstore: @cstore::CStore, encode_inlined_item: encode_inlined_item<'a>, - reachable: @mut HashSet, + reachable: @RefCell>, } struct Stats { @@ -95,11 +95,12 @@ pub struct EncodeContext<'a> { cstore: &'a cstore::CStore, encode_inlined_item: encode_inlined_item<'a>, type_abbrevs: abbrev_map, - reachable: @mut HashSet, + reachable: @RefCell>, } pub fn reachable(ecx: &EncodeContext, id: NodeId) -> bool { - ecx.reachable.contains(&id) + let reachable = ecx.reachable.borrow(); + reachable.get().contains(&id) } fn encode_name(ecx: &EncodeContext, diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index 61442e190956..50407ecb0913 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -19,6 +19,7 @@ use middle::ty; use middle::typeck; use middle::privacy; +use std::cell::RefCell; use std::hashmap::HashSet; use syntax::ast; use syntax::ast_map; @@ -84,7 +85,7 @@ struct ReachableContext { // methods they've been resolved to. method_map: typeck::method_map, // The set of items which must be exported in the linkage sense. - reachable_symbols: @mut HashSet, + reachable_symbols: @RefCell>, // A worklist of item IDs. Each item ID in this worklist will be inlined // and will be scanned for further references. worklist: @mut ~[ast::NodeId], @@ -94,7 +95,7 @@ struct MarkSymbolVisitor { worklist: @mut ~[ast::NodeId], method_map: typeck::method_map, tcx: ty::ctxt, - reachable_symbols: @mut HashSet, + reachable_symbols: @RefCell>, } impl Visitor<()> for MarkSymbolVisitor { @@ -129,7 +130,9 @@ impl Visitor<()> for MarkSymbolVisitor { // If this wasn't a static, then this destination is // surely reachable. _ => { - self.reachable_symbols.insert(def_id.node); + let mut reachable_symbols = + self.reachable_symbols.borrow_mut(); + reachable_symbols.get().insert(def_id.node); } } } @@ -146,9 +149,13 @@ impl Visitor<()> for MarkSymbolVisitor { def_id_represents_local_inlined_item( self.tcx, def_id) { - self.worklist.push(def_id.node) - } - self.reachable_symbols.insert(def_id.node); + self.worklist.push(def_id.node) + } + { + let mut reachable_symbols = + self.reachable_symbols.borrow_mut(); + reachable_symbols.get().insert(def_id.node); + } } } Some(_) => {} @@ -177,7 +184,7 @@ impl ReachableContext { ReachableContext { tcx: tcx, method_map: method_map, - reachable_symbols: @mut HashSet::new(), + reachable_symbols: @RefCell::new(HashSet::new()), worklist: @mut ~[], } } @@ -289,7 +296,9 @@ impl ReachableContext { ast_map::node_item(item, _) => { match item.node { ast::item_fn(_, ast::extern_fn, _, _, _) => { - self.reachable_symbols.insert(search_item); + let mut reachable_symbols = + self.reachable_symbols.borrow_mut(); + reachable_symbols.get().insert(search_item); } _ => {} } @@ -301,7 +310,8 @@ impl ReachableContext { // continue to participate in linkage after this product is // produced. In this case, we traverse the ast node, recursing on // all reachable nodes from this one. - self.reachable_symbols.insert(search_item); + let mut reachable_symbols = self.reachable_symbols.borrow_mut(); + reachable_symbols.get().insert(search_item); } match *node { @@ -318,7 +328,9 @@ impl ReachableContext { ast::item_static(..) => { if attr::contains_name(item.attrs, "address_insignificant") { - self.reachable_symbols.remove(&search_item); + let mut reachable_symbols = + self.reachable_symbols.borrow_mut(); + reachable_symbols.get().remove(&search_item); } } @@ -377,7 +389,9 @@ impl ReachableContext { let destructor_for_type = self.tcx.destructor_for_type.borrow(); for (_, destructor_def_id) in destructor_for_type.get().iter() { if destructor_def_id.crate == ast::LOCAL_CRATE { - self.reachable_symbols.insert(destructor_def_id.node); + let mut reachable_symbols = self.reachable_symbols + .borrow_mut(); + reachable_symbols.get().insert(destructor_def_id.node); } } } @@ -386,7 +400,7 @@ impl ReachableContext { pub fn find_reachable(tcx: ty::ctxt, method_map: typeck::method_map, exported_items: &privacy::ExportedItems) - -> @mut HashSet { + -> @RefCell> { let reachable_context = ReachableContext::new(tcx, method_map); // Step 1: Seed the worklist with all nodes which were found to be public as diff --git a/src/librustc/middle/trans/base.rs b/src/librustc/middle/trans/base.rs index dfd5743201cf..e4dc991938b7 100644 --- a/src/librustc/middle/trans/base.rs +++ b/src/librustc/middle/trans/base.rs @@ -2318,8 +2318,11 @@ fn finish_register_fn(ccx: @CrateContext, sp: Span, sym: ~str, node_id: ast::Nod item_symbols.get().insert(node_id, sym); } - if !ccx.reachable.contains(&node_id) { - lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage); + { + let reachable = ccx.reachable.borrow(); + if !reachable.get().contains(&node_id) { + lib::llvm::SetLinkage(llfn, lib::llvm::InternalLinkage); + } } if is_entry_fn(&ccx.sess, node_id) && !*ccx.sess.building_library { @@ -2531,18 +2534,27 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef { llvm::LLVMAddGlobal(ccx.llmod, llty, buf) }); - if !ccx.reachable.contains(&id) { - lib::llvm::SetLinkage(g, lib::llvm::InternalLinkage); + { + let reachable = ccx.reachable.borrow(); + if !reachable.get().contains(&id) { + lib::llvm::SetLinkage( + g, + lib::llvm::InternalLinkage); + } } // Apply the `unnamed_addr` attribute if // requested if attr::contains_name(i.attrs, "address_insignificant"){ - if ccx.reachable.contains(&id) { - ccx.sess.span_bug(i.span, - "insignificant static is \ - reachable"); + { + let reachable = + ccx.reachable.borrow(); + if reachable.get().contains(&id) { + ccx.sess.span_bug(i.span, + "insignificant static is \ + reachable"); + } } lib::llvm::SetUnnamedAddr(g, true); @@ -2731,8 +2743,11 @@ pub fn get_item_val(ccx: @CrateContext, id: ast::NodeId) -> ValueRef { // foreign items (extern fns and extern statics) don't have internal // linkage b/c that doesn't quite make sense. Otherwise items can // have internal linkage if they're not reachable. - if !foreign && !ccx.reachable.contains(&id) { - lib::llvm::SetLinkage(val, lib::llvm::InternalLinkage); + { + let reachable = ccx.reachable.borrow(); + if !foreign && !reachable.get().contains(&id) { + lib::llvm::SetLinkage(val, lib::llvm::InternalLinkage); + } } let mut item_vals = ccx.item_vals.borrow_mut(); @@ -3245,10 +3260,14 @@ pub fn trans_crate(sess: session::Session, let llcx = ccx.llcx; let link_meta = ccx.link_meta.clone(); let llmod = ccx.llmod; - let mut reachable = ccx.reachable.iter().filter_map(|id| { - let item_symbols = ccx.item_symbols.borrow(); - item_symbols.get().find(id).map(|s| s.to_owned()) - }).to_owned_vec(); + + let mut reachable = { + let reachable_map = ccx.reachable.borrow(); + reachable_map.get().iter().filter_map(|id| { + let item_symbols = ccx.item_symbols.borrow(); + item_symbols.get().find(id).map(|s| s.to_owned()) + }).to_owned_vec() + }; // Make sure that some other crucial symbols are not eliminated from the // module. This includes the main function, the crate map (used for debug diff --git a/src/librustc/middle/trans/context.rs b/src/librustc/middle/trans/context.rs index 0c492eac6250..a9d18cfa034a 100644 --- a/src/librustc/middle/trans/context.rs +++ b/src/librustc/middle/trans/context.rs @@ -49,7 +49,7 @@ pub struct CrateContext { intrinsics: HashMap<&'static str, ValueRef>, item_vals: RefCell>, exp_map2: resolve::ExportMap2, - reachable: @mut HashSet, + reachable: @RefCell>, item_symbols: RefCell>, link_meta: LinkMeta, tydescs: RefCell>, @@ -123,7 +123,7 @@ impl CrateContext { maps: astencode::Maps, symbol_hasher: Sha256, link_meta: LinkMeta, - reachable: @mut HashSet) + reachable: @RefCell>) -> CrateContext { unsafe { let llcx = llvm::LLVMContextCreate(); diff --git a/src/librustc/middle/trans/debuginfo.rs b/src/librustc/middle/trans/debuginfo.rs index c1b47488f2ee..68ba597f01d1 100644 --- a/src/librustc/middle/trans/debuginfo.rs +++ b/src/librustc/middle/trans/debuginfo.rs @@ -732,7 +732,10 @@ pub fn create_function_debug_context(cx: &CrateContext, // (by being externally visible or by being inlined into something externally visible). It might // better to use the `exported_items` set from `driver::CrateAnalysis` in the future, but (atm) // this set is not available in the translation pass. - let is_local_to_unit = !cx.reachable.contains(&fn_ast_id); + let is_local_to_unit = { + let reachable = cx.reachable.borrow(); + !reachable.get().contains(&fn_ast_id) + }; let fn_metadata = function_name.with_c_str(|function_name| { linkage_name.with_c_str(|linkage_name| {