Skip to content

Commit

Permalink
Allocate numerical values of DefIndexes from two seperate ranges.
Browse files Browse the repository at this point in the history
This way we can have all item-likes occupy a dense range of
DefIndexes, which is good for making fast, array-based
dictionaries.
  • Loading branch information
michaelwoerister committed Mar 22, 2017
1 parent bc259ee commit 090767b
Show file tree
Hide file tree
Showing 7 changed files with 237 additions and 72 deletions.
53 changes: 53 additions & 0 deletions src/librustc/hir/def_id.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,33 +78,86 @@ impl serialize::UseSpecializedDecodable for CrateNum {
/// A DefIndex is an index into the hir-map for a crate, identifying a
/// particular definition. It should really be considered an interned
/// shorthand for a particular DefPath.
///
/// At the moment we are allocating the numerical values of DefIndexes into two
/// ranges: the "low" range (starting at zero) and the "high" range (starting at
/// DEF_INDEX_HI_START). This allows us to allocate the DefIndexes of all
/// item-likes (Items, TraitItems, and ImplItems) into one of these ranges and
/// consequently use a simple array for lookup tables keyed by DefIndex and
/// known to be densely populated. This is especially important for the HIR map.
///
/// Since the DefIndex is mostly treated as an opaque ID, you probably
/// don't have to care about these ranges.
#[derive(Clone, Debug, Eq, Ord, PartialOrd, PartialEq, RustcEncodable,
RustcDecodable, Hash, Copy)]
pub struct DefIndex(u32);

impl DefIndex {
#[inline]
pub fn new(x: usize) -> DefIndex {
assert!(x < (u32::MAX as usize));
DefIndex(x as u32)
}

#[inline]
pub fn from_u32(x: u32) -> DefIndex {
DefIndex(x)
}

#[inline]
pub fn as_usize(&self) -> usize {
self.0 as usize
}

#[inline]
pub fn as_u32(&self) -> u32 {
self.0
}

#[inline]
pub fn address_space(&self) -> DefIndexAddressSpace {
if self.0 < DEF_INDEX_HI_START.0 {
DefIndexAddressSpace::Low
} else {
DefIndexAddressSpace::High
}
}

/// Converts this DefIndex into a zero-based array index.
/// This index is the offset within the given "range" of the DefIndex,
/// that is, if the DefIndex is part of the "high" range, the resulting
/// index will be (DefIndex - DEF_INDEX_HI_START).
#[inline]
pub fn as_array_index(&self) -> usize {
(self.0 & !DEF_INDEX_HI_START.0) as usize
}
}

/// The start of the "high" range of DefIndexes.
const DEF_INDEX_HI_START: DefIndex = DefIndex(1 << 31);

/// The crate root is always assigned index 0 by the AST Map code,
/// thanks to `NodeCollector::new`.
pub const CRATE_DEF_INDEX: DefIndex = DefIndex(0);

#[derive(Copy, Clone, Eq, PartialEq, Hash)]
pub enum DefIndexAddressSpace {
Low = 0,
High = 1,
}

impl DefIndexAddressSpace {
#[inline]
pub fn index(&self) -> usize {
*self as usize
}

#[inline]
pub fn start(&self) -> usize {
self.index() * DEF_INDEX_HI_START.as_usize()
}
}

/// A DefId identifies a particular *definition*, by combining a crate
/// index and a def index.
#[derive(Clone, Eq, Ord, PartialOrd, PartialEq, RustcEncodable, RustcDecodable, Hash, Copy)]
Expand Down
7 changes: 5 additions & 2 deletions src/librustc/hir/lowering.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
// in the HIR, especially for multiple identifiers.

use hir;
use hir::map::{Definitions, DefKey};
use hir::map::{Definitions, DefKey, REGULAR_SPACE};
use hir::map::definitions::DefPathData;
use hir::def_id::{DefIndex, DefId, CRATE_DEF_INDEX};
use hir::def::{Def, PathResolution};
Expand Down Expand Up @@ -2711,7 +2711,10 @@ impl<'a> LoweringContext<'a> {
let def_id = {
let defs = self.resolver.definitions();
let def_path_data = DefPathData::Binding(name.as_str());
let def_index = defs.create_def_with_parent(parent_def, id, def_path_data);
let def_index = defs.create_def_with_parent(parent_def,
id,
def_path_data,
REGULAR_SPACE);
DefId::local(def_index)
};

Expand Down
67 changes: 46 additions & 21 deletions src/librustc/hir/map/def_collector.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,15 @@
// except according to those terms.

use hir::map::definitions::*;
use hir::def_id::{CRATE_DEF_INDEX, DefIndex};
use hir::def_id::{CRATE_DEF_INDEX, DefIndex, DefIndexAddressSpace};

use syntax::ast::*;
use syntax::ext::hygiene::Mark;
use syntax::visit;
use syntax::symbol::{Symbol, keywords};

use hir::map::{ITEM_LIKE_SPACE, REGULAR_SPACE};

/// Creates def ids for nodes in the AST.
pub struct DefCollector<'a> {
definitions: &'a mut Definitions,
Expand All @@ -39,23 +41,31 @@ impl<'a> DefCollector<'a> {
}

pub fn collect_root(&mut self) {
let root = self.create_def_with_parent(None, CRATE_NODE_ID, DefPathData::CrateRoot);
let root = self.create_def_with_parent(None,
CRATE_NODE_ID,
DefPathData::CrateRoot,
ITEM_LIKE_SPACE);
assert_eq!(root, CRATE_DEF_INDEX);
self.parent_def = Some(root);
}

fn create_def(&mut self, node_id: NodeId, data: DefPathData) -> DefIndex {
fn create_def(&mut self,
node_id: NodeId,
data: DefPathData,
address_space: DefIndexAddressSpace)
-> DefIndex {
let parent_def = self.parent_def;
debug!("create_def(node_id={:?}, data={:?}, parent_def={:?})", node_id, data, parent_def);
self.definitions.create_def_with_parent(parent_def, node_id, data)
self.definitions.create_def_with_parent(parent_def, node_id, data, address_space)
}

fn create_def_with_parent(&mut self,
parent: Option<DefIndex>,
node_id: NodeId,
data: DefPathData)
data: DefPathData,
address_space: DefIndexAddressSpace)
-> DefIndex {
self.definitions.create_def_with_parent(parent, node_id, data)
self.definitions.create_def_with_parent(parent, node_id, data, address_space)
}

pub fn with_parent<F: FnOnce(&mut Self)>(&mut self, parent_def: DefIndex, f: F) {
Expand All @@ -76,7 +86,7 @@ impl<'a> DefCollector<'a> {
_ => {}
}

self.create_def(expr.id, DefPathData::Initializer);
self.create_def(expr.id, DefPathData::Initializer, REGULAR_SPACE);
}

fn visit_macro_invoc(&mut self, id: NodeId, const_expr: bool) {
Expand Down Expand Up @@ -118,27 +128,32 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
ViewPathSimple(..) => {}
ViewPathList(_, ref imports) => {
for import in imports {
self.create_def(import.node.id, DefPathData::Misc);
self.create_def(import.node.id,
DefPathData::Misc,
ITEM_LIKE_SPACE);
}
}
}
DefPathData::Misc
}
};
let def = self.create_def(i.id, def_data);
let def = self.create_def(i.id, def_data, ITEM_LIKE_SPACE);

self.with_parent(def, |this| {
match i.node {
ItemKind::Enum(ref enum_definition, _) => {
for v in &enum_definition.variants {
let variant_def_index =
this.create_def(v.node.data.id(),
DefPathData::EnumVariant(v.node.name.name.as_str()));
DefPathData::EnumVariant(v.node.name.name.as_str()),
REGULAR_SPACE);
this.with_parent(variant_def_index, |this| {
for (index, field) in v.node.data.fields().iter().enumerate() {
let name = field.ident.map(|ident| ident.name)
.unwrap_or_else(|| Symbol::intern(&index.to_string()));
this.create_def(field.id, DefPathData::Field(name.as_str()));
this.create_def(field.id,
DefPathData::Field(name.as_str()),
REGULAR_SPACE);
}

if let Some(ref expr) = v.node.disr_expr {
Expand All @@ -151,13 +166,14 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
// If this is a tuple-like struct, register the constructor.
if !struct_def.is_struct() {
this.create_def(struct_def.id(),
DefPathData::StructCtor);
DefPathData::StructCtor,
REGULAR_SPACE);
}

for (index, field) in struct_def.fields().iter().enumerate() {
let name = field.ident.map(|ident| ident.name.as_str())
.unwrap_or(Symbol::intern(&index.to_string()).as_str());
this.create_def(field.id, DefPathData::Field(name));
this.create_def(field.id, DefPathData::Field(name), REGULAR_SPACE);
}
}
_ => {}
Expand All @@ -168,7 +184,8 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {

fn visit_foreign_item(&mut self, foreign_item: &'a ForeignItem) {
let def = self.create_def(foreign_item.id,
DefPathData::ValueNs(foreign_item.ident.name.as_str()));
DefPathData::ValueNs(foreign_item.ident.name.as_str()),
REGULAR_SPACE);

self.with_parent(def, |this| {
visit::walk_foreign_item(this, foreign_item);
Expand All @@ -177,7 +194,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {

fn visit_generics(&mut self, generics: &'a Generics) {
for ty_param in generics.ty_params.iter() {
self.create_def(ty_param.id, DefPathData::TypeParam(ty_param.ident.name.as_str()));
self.create_def(ty_param.id,
DefPathData::TypeParam(ty_param.ident.name.as_str()),
REGULAR_SPACE);
}

visit::walk_generics(self, generics);
Expand All @@ -191,7 +210,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
TraitItemKind::Macro(..) => return self.visit_macro_invoc(ti.id, false),
};

let def = self.create_def(ti.id, def_data);
let def = self.create_def(ti.id, def_data, ITEM_LIKE_SPACE);
self.with_parent(def, |this| {
if let TraitItemKind::Const(_, Some(ref expr)) = ti.node {
this.visit_const_expr(expr);
Expand All @@ -209,7 +228,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
ImplItemKind::Macro(..) => return self.visit_macro_invoc(ii.id, false),
};

let def = self.create_def(ii.id, def_data);
let def = self.create_def(ii.id, def_data, ITEM_LIKE_SPACE);
self.with_parent(def, |this| {
if let ImplItemKind::Const(_, ref expr) = ii.node {
this.visit_const_expr(expr);
Expand All @@ -225,7 +244,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
match pat.node {
PatKind::Mac(..) => return self.visit_macro_invoc(pat.id, false),
PatKind::Ident(_, id, _) => {
let def = self.create_def(pat.id, DefPathData::Binding(id.node.name.as_str()));
let def = self.create_def(pat.id,
DefPathData::Binding(id.node.name.as_str()),
REGULAR_SPACE);
self.parent_def = Some(def);
}
_ => {}
Expand All @@ -242,7 +263,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
ExprKind::Mac(..) => return self.visit_macro_invoc(expr.id, false),
ExprKind::Repeat(_, ref count) => self.visit_const_expr(count),
ExprKind::Closure(..) => {
let def = self.create_def(expr.id, DefPathData::ClosureExpr);
let def = self.create_def(expr.id,
DefPathData::ClosureExpr,
REGULAR_SPACE);
self.parent_def = Some(def);
}
_ => {}
Expand All @@ -257,7 +280,7 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
TyKind::Mac(..) => return self.visit_macro_invoc(ty.id, false),
TyKind::Array(_, ref length) => self.visit_const_expr(length),
TyKind::ImplTrait(..) => {
self.create_def(ty.id, DefPathData::ImplTrait);
self.create_def(ty.id, DefPathData::ImplTrait, REGULAR_SPACE);
}
TyKind::Typeof(ref expr) => self.visit_const_expr(expr),
_ => {}
Expand All @@ -266,7 +289,9 @@ impl<'a> visit::Visitor<'a> for DefCollector<'a> {
}

fn visit_lifetime_def(&mut self, def: &'a LifetimeDef) {
self.create_def(def.lifetime.id, DefPathData::LifetimeDef(def.lifetime.name.as_str()));
self.create_def(def.lifetime.id,
DefPathData::LifetimeDef(def.lifetime.name.as_str()),
REGULAR_SPACE);
}

fn visit_stmt(&mut self, stmt: &'a Stmt) {
Expand Down
Loading

0 comments on commit 090767b

Please sign in to comment.