encode region::Scope using fewer bytes

Now that region::Scope is no longer interned, its size is more
important. This PR encodes region::Scope in 8 bytes instead of 12, which
should speed up region inference somewhat (perf testing needed) and
should improve the margins on #36799 by 64MB (that's not a lot, I did
this PR mostly to speed up region inference).
This commit is contained in:
Ariel Ben-Yehuda 2017-09-24 17:20:37 +03:00
parent 8214ab1662
commit c10b23e2e0
2 changed files with 29 additions and 33 deletions

View File

@ -515,22 +515,7 @@ impl_stable_hash_for!(enum ty::cast::CastKind {
});
impl_stable_hash_for!(struct ::middle::region::FirstStatementIndex { idx });
impl<'gcx> HashStable<StableHashingContext<'gcx>> for ::middle::region::Scope {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) {
self.data().hash_stable(hcx, hasher)
}
}
impl_stable_hash_for!(enum ::middle::region::ScopeData {
Node(local_id),
Destruction(local_id),
CallSite(local_id),
Arguments(local_id),
Remainder(block_remainder)
});
impl_stable_hash_for!(struct ::middle::region::Scope { id, code });
impl<'gcx> ToStableHashKey<StableHashingContext<'gcx>> for region::Scope {
type KeyType = region::Scope;

View File

@ -98,9 +98,16 @@ use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
/// generated via deriving here.
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)]
pub struct Scope {
pub scope_data: ScopeData
pub(crate) id: hir::ItemLocalId,
pub(crate) code: u32
}
const SCOPE_DATA_NODE: u32 = !0;
const SCOPE_DATA_CALLSITE: u32 = !1;
const SCOPE_DATA_ARGUMENTS: u32 = !2;
const SCOPE_DATA_DESTRUCTION: u32 = !3;
const SCOPE_DATA_REMAINDER_MAX: u32 = !4;
#[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)]
pub enum ScopeData {
Node(hir::ItemLocalId),
@ -148,11 +155,9 @@ pub struct BlockRemainder {
RustcDecodable, Debug, Copy)]
pub struct FirstStatementIndex { pub idx: u32 }
pub const FIRST_STATEMENT_MAX: usize = !0u32 as usize;
impl Idx for FirstStatementIndex {
fn new(idx: usize) -> Self {
assert!(idx <= FIRST_STATEMENT_MAX);
assert!(idx <= SCOPE_DATA_REMAINDER_MAX as usize);
FirstStatementIndex { idx: idx as u32 }
}
@ -164,7 +169,14 @@ impl Idx for FirstStatementIndex {
impl From<ScopeData> for Scope {
#[inline]
fn from(scope_data: ScopeData) -> Self {
Self { scope_data }
let (id, code) = match scope_data {
ScopeData::Node(id) => (id, SCOPE_DATA_NODE),
ScopeData::CallSite(id) => (id, SCOPE_DATA_CALLSITE),
ScopeData::Arguments(id) => (id, SCOPE_DATA_ARGUMENTS),
ScopeData::Destruction(id) => (id, SCOPE_DATA_DESTRUCTION),
ScopeData::Remainder(r) => (r.block, r.first_statement_index.index() as u32)
};
Self { id, code }
}
}
@ -172,7 +184,16 @@ impl From<ScopeData> for Scope {
impl Scope {
#[inline]
pub fn data(self) -> ScopeData {
self.scope_data
match self.code {
SCOPE_DATA_NODE => ScopeData::Node(self.id),
SCOPE_DATA_CALLSITE => ScopeData::CallSite(self.id),
SCOPE_DATA_ARGUMENTS => ScopeData::Arguments(self.id),
SCOPE_DATA_DESTRUCTION => ScopeData::Destruction(self.id),
idx => ScopeData::Remainder(BlockRemainder {
block: self.id,
first_statement_index: FirstStatementIndex { idx }
})
}
}
#[inline]
@ -207,17 +228,7 @@ impl Scope {
/// NB: likely to be replaced as API is refined; e.g. pnkfelix
/// anticipates `fn entry_node_id` and `fn each_exit_node_id`.
pub fn item_local_id(&self) -> hir::ItemLocalId {
// TODO: killme
match self.data() {
ScopeData::Node(id) => id,
// These cases all return rough approximations to the
// precise scope denoted by `self`.
ScopeData::Remainder(br) => br.block,
ScopeData::Destruction(id) |
ScopeData::CallSite(id) |
ScopeData::Arguments(id) => id,
}
self.id
}
pub fn node_id(&self, tcx: TyCtxt, scope_tree: &ScopeTree) -> ast::NodeId {