Skip to content

Commit

Permalink
Rollup merge of rust-lang#65315 - spastorino:intern-place-projection,…
Browse files Browse the repository at this point in the history
… r=oli-obk

Intern place projection

This should sit on top of rust-lang#65197. After that one merged, I'm gonna rebase on top of it.

The important commits are the last three and there's a bunch of code repetition that I'm going to remove but for that I need to refactor some things that probably need to be added before this PR.

Anyway this work helps as is because we can run perf tests :).

r? @oli-obk /cc @nikomatsakis
  • Loading branch information
Centril authored Oct 25, 2019
2 parents 1f93be1 + 5f5903d commit 8bb039f
Show file tree
Hide file tree
Showing 57 changed files with 1,147 additions and 1,057 deletions.
97 changes: 39 additions & 58 deletions src/librustc/mir/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,7 @@ use crate::ty::layout::VariantIdx;
use crate::ty::print::{FmtPrinter, Printer};
use crate::ty::subst::{Subst, SubstsRef};
use crate::ty::{
self, AdtDef, CanonicalUserTypeAnnotations, Region, Ty, TyCtxt,
UserTypeAnnotationIndex,
self, AdtDef, CanonicalUserTypeAnnotations, List, Region, Ty, TyCtxt, UserTypeAnnotationIndex,
};

use polonius_engine::Atom;
Expand Down Expand Up @@ -1712,15 +1711,17 @@ impl Debug for Statement<'_> {
/// A path to a value; something that can be evaluated without
/// changing or disturbing program state.
#[derive(
Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, HashStable,
)]
pub struct Place<'tcx> {
pub base: PlaceBase<'tcx>,

/// projection out of a place (access a field, deref a pointer, etc)
pub projection: Box<[PlaceElem<'tcx>]>,
pub projection: &'tcx List<PlaceElem<'tcx>>,
}

impl<'tcx> rustc_serialize::UseSpecializedDecodable for Place<'tcx> {}

#[derive(
Clone, PartialEq, Eq, PartialOrd, Ord, Hash, RustcEncodable, RustcDecodable, HashStable,
)]
Expand Down Expand Up @@ -1824,6 +1825,8 @@ impl<V, T> ProjectionElem<V, T> {
/// and the index is a local.
pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;

impl<'tcx> Copy for PlaceElem<'tcx> { }

// At least on 64 bit systems, `PlaceElem` should not be larger than two pointers.
#[cfg(target_arch = "x86_64")]
static_assert_size!(PlaceElem<'_>, 16);
Expand All @@ -1846,50 +1849,11 @@ pub struct PlaceRef<'a, 'tcx> {
}

impl<'tcx> Place<'tcx> {
// FIXME change this back to a const when projection is a shared slice.
//
// pub const RETURN_PLACE: Place<'tcx> = Place {
// base: PlaceBase::Local(RETURN_PLACE),
// projection: &[],
// };
// FIXME change this to a const fn by also making List::empty a const fn.
pub fn return_place() -> Place<'tcx> {
Place {
base: PlaceBase::Local(RETURN_PLACE),
projection: Box::new([]),
}
}

pub fn field(self, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
self.elem(ProjectionElem::Field(f, ty))
}

pub fn deref(self) -> Place<'tcx> {
self.elem(ProjectionElem::Deref)
}

pub fn downcast(self, adt_def: &'tcx AdtDef, variant_index: VariantIdx) -> Place<'tcx> {
self.elem(ProjectionElem::Downcast(
Some(adt_def.variants[variant_index].ident.name),
variant_index,
))
}

pub fn downcast_unnamed(self, variant_index: VariantIdx) -> Place<'tcx> {
self.elem(ProjectionElem::Downcast(None, variant_index))
}

pub fn index(self, index: Local) -> Place<'tcx> {
self.elem(ProjectionElem::Index(index))
}

pub fn elem(self, elem: PlaceElem<'tcx>) -> Place<'tcx> {
// FIXME(spastorino): revisit this again once projection is not a Box<[T]> anymore
let mut projection = self.projection.into_vec();
projection.push(elem);

Place {
base: self.base,
projection: projection.into_boxed_slice(),
projection: List::empty(),
}
}

Expand All @@ -1906,26 +1870,23 @@ impl<'tcx> Place<'tcx> {
//
// FIXME: can we safely swap the semantics of `fn base_local` below in here instead?
pub fn local_or_deref_local(&self) -> Option<Local> {
match self {
Place {
base: PlaceBase::Local(local),
projection: box [],
match self.as_ref() {
PlaceRef {
base: &PlaceBase::Local(local),
projection: &[],
} |
Place {
base: PlaceBase::Local(local),
projection: box [ProjectionElem::Deref],
} => Some(*local),
PlaceRef {
base: &PlaceBase::Local(local),
projection: &[ProjectionElem::Deref],
} => Some(local),
_ => None,
}
}

/// If this place represents a local variable like `_X` with no
/// projections, return `Some(_X)`.
pub fn as_local(&self) -> Option<Local> {
match self {
Place { projection: box [], base: PlaceBase::Local(l) } => Some(*l),
_ => None,
}
self.as_ref().as_local()
}

pub fn as_ref(&self) -> PlaceRef<'_, 'tcx> {
Expand All @@ -1940,7 +1901,7 @@ impl From<Local> for Place<'_> {
fn from(local: Local) -> Self {
Place {
base: local.into(),
projection: Box::new([]),
projection: List::empty(),
}
}
}
Expand Down Expand Up @@ -1969,6 +1930,15 @@ impl<'a, 'tcx> PlaceRef<'a, 'tcx> {
_ => None,
}
}

/// If this place represents a local variable like `_X` with no
/// projections, return `Some(_X)`.
pub fn as_local(&self) -> Option<Local> {
match self {
PlaceRef { base: PlaceBase::Local(l), projection: [] } => Some(*l),
_ => None,
}
}
}

impl Debug for Place<'_> {
Expand Down Expand Up @@ -3182,6 +3152,17 @@ impl<'tcx> TypeFoldable<'tcx> for PlaceBase<'tcx> {
}
}

impl<'tcx> TypeFoldable<'tcx> for &'tcx ty::List<PlaceElem<'tcx>> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
let v = self.iter().map(|t| t.fold_with(folder)).collect::<Vec<_>>();
folder.tcx().intern_place_elems(&v)
}

fn super_visit_with<V: TypeVisitor<'tcx>>(&self, visitor: &mut V) -> bool {
self.iter().any(|t| t.visit_with(visitor))
}
}

impl<'tcx> TypeFoldable<'tcx> for Static<'tcx> {
fn super_fold_with<F: TypeFolder<'tcx>>(&self, folder: &mut F) -> Self {
Static {
Expand Down
10 changes: 7 additions & 3 deletions src/librustc/mir/visit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -784,6 +784,8 @@ macro_rules! make_mir_visitor {

macro_rules! visit_place_fns {
(mut) => (
fn tcx<'a>(&'a self) -> TyCtxt<'tcx>;

fn super_place(
&mut self,
place: &mut Place<'tcx>,
Expand All @@ -793,19 +795,21 @@ macro_rules! visit_place_fns {
self.visit_place_base(&mut place.base, context, location);

if let Some(new_projection) = self.process_projection(&place.projection) {
place.projection = new_projection;
place.projection = self.tcx().intern_place_elems(&new_projection);
}
}

fn process_projection(
&mut self,
projection: &'a [PlaceElem<'tcx>],
) -> Option<Box<[PlaceElem<'tcx>]>> {
) -> Option<Vec<PlaceElem<'tcx>>> {
let mut projection = Cow::Borrowed(projection);

for i in 0..projection.len() {
if let Some(elem) = projection.get(i) {
if let Some(elem) = self.process_projection_elem(elem) {
// This converts the borrowed projection into `Cow::Owned(_)` and returns a
// clone of the projection so we can mutate and reintern later.
let vec = projection.to_mut();
vec[i] = elem;
}
Expand All @@ -814,7 +818,7 @@ macro_rules! visit_place_fns {

match projection {
Cow::Borrowed(_) => None,
Cow::Owned(vec) => Some(vec.into_boxed_slice()),
Cow::Owned(vec) => Some(vec),
}
}

Expand Down
25 changes: 23 additions & 2 deletions src/librustc/ty/codec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,9 @@ use rustc_data_structures::fx::FxHashMap;
use rustc_serialize::{Decodable, Decoder, Encoder, Encodable, opaque};
use std::hash::Hash;
use std::intrinsics;
use crate::ty::{self, Ty, TyCtxt};
use crate::ty::{self, List, Ty, TyCtxt};
use crate::ty::subst::SubstsRef;
use crate::mir::interpret::Allocation;
use crate::mir::{self, interpret::Allocation};
use syntax_pos::Span;

/// The shorthand encoding uses an enum's variant index `usize`
Expand Down Expand Up @@ -218,6 +218,18 @@ where
Ok(tcx.mk_substs((0..len).map(|_| Decodable::decode(decoder)))?)
}

#[inline]
pub fn decode_place<D>(decoder: &mut D) -> Result<mir::Place<'tcx>, D::Error>
where
D: TyDecoder<'tcx>,
{
let base: mir::PlaceBase<'tcx> = Decodable::decode(decoder)?;
let len = decoder.read_usize()?;
let projection: &'tcx List<mir::PlaceElem<'tcx>> =
decoder.tcx().mk_place_elems((0..len).map(|_| Decodable::decode(decoder)))?;
Ok(mir::Place { base, projection })
}

#[inline]
pub fn decode_region<D>(decoder: &mut D) -> Result<ty::Region<'tcx>, D::Error>
where
Expand Down Expand Up @@ -413,6 +425,15 @@ macro_rules! implement_ty_decoder {
}
}

impl<$($typaram),*> SpecializedDecoder<$crate::mir::Place<'tcx>>
for $DecoderName<$($typaram),*> {
fn specialized_decode(
&mut self
) -> Result<$crate::mir::Place<'tcx>, Self::Error> {
decode_place(self)
}
}

impl<$($typaram),*> SpecializedDecoder<ty::Region<'tcx>>
for $DecoderName<$($typaram),*> {
fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
Expand Down
70 changes: 68 additions & 2 deletions src/librustc/ty/context.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
// ignore-tidy-filelength
//! Type context book-keeping.

use crate::arena::Arena;
Expand All @@ -21,7 +22,7 @@ use crate::middle::cstore::EncodedMetadata;
use crate::middle::lang_items;
use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault};
use crate::middle::stability;
use crate::mir::{Body, interpret, ProjectionKind, Promoted};
use crate::mir::{Body, Field, interpret, Local, Place, PlaceElem, ProjectionKind, Promoted};
use crate::mir::interpret::{ConstValue, Allocation, Scalar};
use crate::ty::subst::{GenericArg, InternalSubsts, SubstsRef, Subst};
use crate::ty::ReprOptions;
Expand Down Expand Up @@ -106,6 +107,7 @@ pub struct CtxtInterners<'tcx> {
goal: InternedSet<'tcx, GoalKind<'tcx>>,
goal_list: InternedSet<'tcx, List<Goal<'tcx>>>,
projs: InternedSet<'tcx, List<ProjectionKind>>,
place_elems: InternedSet<'tcx, List<PlaceElem<'tcx>>>,
const_: InternedSet<'tcx, Const<'tcx>>,
}

Expand All @@ -124,6 +126,7 @@ impl<'tcx> CtxtInterners<'tcx> {
goal: Default::default(),
goal_list: Default::default(),
projs: Default::default(),
place_elems: Default::default(),
const_: Default::default(),
}
}
Expand Down Expand Up @@ -2142,6 +2145,13 @@ impl<'tcx> Borrow<[ProjectionKind]>
}
}

impl<'tcx> Borrow<[PlaceElem<'tcx>]>
for Interned<'tcx, List<PlaceElem<'tcx>>> {
fn borrow(&self) -> &[PlaceElem<'tcx>] {
&self.0[..]
}
}

impl<'tcx> Borrow<RegionKind> for Interned<'tcx, RegionKind> {
fn borrow(&self) -> &RegionKind {
&self.0
Expand Down Expand Up @@ -2242,7 +2252,8 @@ slice_interners!(
predicates: _intern_predicates(Predicate<'tcx>),
clauses: _intern_clauses(Clause<'tcx>),
goal_list: _intern_goals(Goal<'tcx>),
projs: _intern_projs(ProjectionKind)
projs: _intern_projs(ProjectionKind),
place_elems: _intern_place_elems(PlaceElem<'tcx>)
);

impl<'tcx> TyCtxt<'tcx> {
Expand Down Expand Up @@ -2584,6 +2595,48 @@ impl<'tcx> TyCtxt<'tcx> {
self.mk_ty(Opaque(def_id, substs))
}

pub fn mk_place_field(self, place: Place<'tcx>, f: Field, ty: Ty<'tcx>) -> Place<'tcx> {
self.mk_place_elem(place, PlaceElem::Field(f, ty))
}

pub fn mk_place_deref(self, place: Place<'tcx>) -> Place<'tcx> {
self.mk_place_elem(place, PlaceElem::Deref)
}

pub fn mk_place_downcast(
self,
place: Place<'tcx>,
adt_def: &'tcx AdtDef,
variant_index: VariantIdx,
) -> Place<'tcx> {
self.mk_place_elem(
place,
PlaceElem::Downcast(Some(adt_def.variants[variant_index].ident.name), variant_index),
)
}

pub fn mk_place_downcast_unnamed(
self,
place: Place<'tcx>,
variant_index: VariantIdx,
) -> Place<'tcx> {
self.mk_place_elem(place, PlaceElem::Downcast(None, variant_index))
}

pub fn mk_place_index(self, place: Place<'tcx>, index: Local) -> Place<'tcx> {
self.mk_place_elem(place, PlaceElem::Index(index))
}

/// This method copies `Place`'s projection, add an element and reintern it. Should not be used
/// to build a full `Place` it's just a convenient way to grab a projection and modify it in
/// flight.
pub fn mk_place_elem(self, place: Place<'tcx>, elem: PlaceElem<'tcx>) -> Place<'tcx> {
let mut projection = place.projection.to_vec();
projection.push(elem);

Place { base: place.base, projection: self.intern_place_elems(&projection) }
}

pub fn intern_existential_predicates(self, eps: &[ExistentialPredicate<'tcx>])
-> &'tcx List<ExistentialPredicate<'tcx>> {
assert!(!eps.is_empty());
Expand Down Expand Up @@ -2628,6 +2681,14 @@ impl<'tcx> TyCtxt<'tcx> {
}
}

pub fn intern_place_elems(self, ts: &[PlaceElem<'tcx>]) -> &'tcx List<PlaceElem<'tcx>> {
if ts.len() == 0 {
List::empty()
} else {
self._intern_place_elems(ts)
}
}

pub fn intern_canonical_var_infos(self, ts: &[CanonicalVarInfo]) -> CanonicalVarInfos<'tcx> {
if ts.len() == 0 {
List::empty()
Expand Down Expand Up @@ -2690,6 +2751,11 @@ impl<'tcx> TyCtxt<'tcx> {
iter.intern_with(|xs| self.intern_substs(xs))
}

pub fn mk_place_elems<I: InternAs<[PlaceElem<'tcx>],
&'tcx List<PlaceElem<'tcx>>>>(self, iter: I) -> I::Output {
iter.intern_with(|xs| self.intern_place_elems(xs))
}

pub fn mk_substs_trait(self,
self_ty: Ty<'tcx>,
rest: &[GenericArg<'tcx>])
Expand Down
Loading

0 comments on commit 8bb039f

Please sign in to comment.