Skip to content

Cleanup refactoring around DefPath handling #38418

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
Dec 21, 2016
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
Definitions: Extract DefPath interning into its own data structure.
  • Loading branch information
michaelwoerister committed Dec 17, 2016
commit 8e34a8e4223a744bcc4fb2d77c06fb6c183dcc26
108 changes: 85 additions & 23 deletions src/librustc/hir/map/definitions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,28 +8,92 @@
// option. This file may not be copied, modified, or distributed
// except according to those terms.


//! For each definition, we track the following data. A definition
//! here is defined somewhat circularly as "something with a def-id",
//! but it generally corresponds to things like structs, enums, etc.
//! There are also some rather random cases (like const initializer
//! expressions) that are mostly just leftovers.



use hir::def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::stable_hasher::StableHasher;
use serialize::{Encodable, Decodable, Encoder, Decoder};
use std::fmt::Write;
use std::hash::{Hash, Hasher};
use syntax::ast;
use syntax::symbol::{Symbol, InternedString};
use ty::TyCtxt;
use util::nodemap::NodeMap;

//! For each definition, we track the following data. A definition
//! here is defined somewhat circularly as "something with a def-id",
//! but it generally corresponds to things like structs, enums, etc.
//! There are also some rather random cases (like const initializer
//! expressions) that are mostly just leftovers.
#[derive(Clone)]
pub struct DefPathTable {
index_to_key: Vec<DefKey>,
key_to_index: FxHashMap<DefKey, DefIndex>,
}

impl DefPathTable {
fn insert(&mut self, key: DefKey) -> DefIndex {
let index = DefIndex::new(self.index_to_key.len());
debug!("DefPathTable::insert() - {:?} <-> {:?}", key, index);
self.index_to_key.push(key.clone());
self.key_to_index.insert(key, index);
index
}

#[inline(always)]
pub fn def_key(&self, index: DefIndex) -> DefKey {
self.index_to_key[index.as_usize()].clone()
}

#[inline(always)]
pub fn def_index_for_def_key(&self, key: &DefKey) -> Option<DefIndex> {
self.key_to_index.get(key).cloned()
}

#[inline(always)]
pub fn contains_key(&self, key: &DefKey) -> bool {
self.key_to_index.contains_key(key)
}

/// Returns the path from the crate root to `index`. The root
/// nodes are not included in the path (i.e., this will be an
/// empty vector for the crate root). For an inlined item, this
/// will be the path of the item in the external crate (but the
/// path will begin with the path to the external crate).
pub fn def_path(&self, index: DefIndex) -> DefPath {
DefPath::make(LOCAL_CRATE, index, |p| self.def_key(p))
}
}


impl Encodable for DefPathTable {
fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
self.index_to_key.encode(s)
}
}

impl Decodable for DefPathTable {
fn decode<D: Decoder>(d: &mut D) -> Result<DefPathTable, D::Error> {
let index_to_key: Vec<DefKey> = Decodable::decode(d)?;
let key_to_index = index_to_key.iter()
.enumerate()
.map(|(index, key)| (key.clone(), DefIndex::new(index)))
.collect();
Ok(DefPathTable {
index_to_key: index_to_key,
key_to_index: key_to_index,
})
}
}


/// The definition table containing node definitions
#[derive(Clone)]
pub struct Definitions {
data: Vec<DefKey>,
key_map: FxHashMap<DefKey, DefIndex>,
table: DefPathTable,
node_to_def_index: NodeMap<DefIndex>,
def_index_to_node: Vec<ast::NodeId>,
}
Expand Down Expand Up @@ -214,24 +278,26 @@ impl Definitions {
/// Create new empty definition map.
pub fn new() -> Definitions {
Definitions {
data: vec![],
key_map: FxHashMap(),
table: DefPathTable {
index_to_key: vec![],
key_to_index: FxHashMap(),
},
node_to_def_index: NodeMap(),
def_index_to_node: vec![],
}
}

/// Get the number of definitions.
pub fn len(&self) -> usize {
self.data.len()
self.def_index_to_node.len()
}

pub fn def_key(&self, index: DefIndex) -> DefKey {
self.data[index.as_usize()].key.clone()
self.table.def_key(index)
}

pub fn def_index_for_def_key(&self, key: DefKey) -> Option<DefIndex> {
self.key_map.get(&key).cloned()
self.table.def_index_for_def_key(&key)
}

/// Returns the path from the crate root to `index`. The root
Expand All @@ -257,8 +323,7 @@ impl Definitions {

pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
if def_id.krate == LOCAL_CRATE {
assert!(def_id.index.as_usize() < self.data.len());
// Some(self.data[def_id.index.as_usize()].node_id)
assert!(def_id.index.as_usize() < self.def_index_to_node.len());
Some(self.def_index_to_node[def_id.index.as_usize()])
} else {
None
Expand All @@ -278,7 +343,7 @@ impl Definitions {
"adding a def'n for node-id {:?} and data {:?} but a previous def'n exists: {:?}",
node_id,
data,
self.data[self.node_to_def_index[&node_id].as_usize()]);
self.table.def_key(self.node_to_def_index[&node_id]));

assert!(parent.is_some() ^ match data {
DefPathData::CrateRoot | DefPathData::InlinedRoot(_) => true,
Expand All @@ -295,21 +360,18 @@ impl Definitions {
}
};

while self.key_map.contains_key(&key) {
while self.table.contains_key(&key) {
key.disambiguated_data.disambiguator += 1;
}

debug!("create_def_with_parent: after disambiguation, key = {:?}", key);

// Create the definition.
let index = DefIndex::new(self.data.len());
self.data.push(DefData { key: key.clone() });
self.def_index_to_node.push(node_id);
debug!("create_def_with_parent: node_to_def_index[{:?}] = {:?}", node_id, index);
let index = self.table.insert(key);
debug!("create_def_with_parent: def_index_to_node[{:?} <-> {:?}", index, node_id);
self.node_to_def_index.insert(node_id, index);
debug!("create_def_with_parent: key_map[{:?}] = {:?}", key, index);
self.key_map.insert(key, index);

assert_eq!(index.as_usize(), self.def_index_to_node.len());
self.def_index_to_node.push(node_id);

index
}
Expand Down