Skip to content

Commit acd0e40

Browse files
Ariel Ben-Yehudaarielb1
authored andcommitted
short-cut SharedCrateContext::layout_of
That method is *incredibly* hot, so this ends up saving 10% of trans time. BTW, we really should be doing dependency tracking there - and possibly be taking the respective perf hit (got to find a way to make DTMs fast), but `layout_cache` is a non-dep-tracking map.
1 parent e1377a4 commit acd0e40

File tree

2 files changed

+38
-28
lines changed

2 files changed

+38
-28
lines changed

src/librustc/ty/layout.rs

Lines changed: 26 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -822,7 +822,7 @@ impl<'a, 'gcx, 'tcx> Struct {
822822
}
823823

824824
(_, &ty::TyProjection(_)) | (_, &ty::TyAnon(..)) => {
825-
let normalized = normalize_associated_type(infcx, ty);
825+
let normalized = infcx.normalize_projections(ty);
826826
if ty == normalized {
827827
return Ok(None);
828828
}
@@ -1067,28 +1067,6 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
10671067
}
10681068
}
10691069

1070-
/// Helper function for normalizing associated types in an inference context.
1071-
fn normalize_associated_type<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
1072-
ty: Ty<'gcx>)
1073-
-> Ty<'gcx> {
1074-
if !ty.has_projection_types() {
1075-
return ty;
1076-
}
1077-
1078-
let mut selcx = traits::SelectionContext::new(infcx);
1079-
let cause = traits::ObligationCause::dummy();
1080-
let traits::Normalized { value: result, obligations } =
1081-
traits::normalize(&mut selcx, cause, &ty);
1082-
1083-
let mut fulfill_cx = traits::FulfillmentContext::new();
1084-
1085-
for obligation in obligations {
1086-
fulfill_cx.register_predicate_obligation(infcx, obligation);
1087-
}
1088-
1089-
infcx.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
1090-
}
1091-
10921070
impl<'a, 'gcx, 'tcx> Layout {
10931071
pub fn compute_uncached(ty: Ty<'gcx>,
10941072
infcx: &InferCtxt<'a, 'gcx, 'tcx>)
@@ -1100,7 +1078,7 @@ impl<'a, 'gcx, 'tcx> Layout {
11001078

11011079
let ptr_layout = |pointee: Ty<'gcx>| {
11021080
let non_zero = !ty.is_unsafe_ptr();
1103-
let pointee = normalize_associated_type(infcx, pointee);
1081+
let pointee = infcx.normalize_projections(pointee);
11041082
if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) {
11051083
Ok(Scalar { value: Pointer, non_zero: non_zero })
11061084
} else {
@@ -1494,7 +1472,7 @@ impl<'a, 'gcx, 'tcx> Layout {
14941472

14951473
// Types with no meaningful known layout.
14961474
ty::TyProjection(_) | ty::TyAnon(..) => {
1497-
let normalized = normalize_associated_type(infcx, ty);
1475+
let normalized = infcx.normalize_projections(ty);
14981476
if ty == normalized {
14991477
return Err(LayoutError::Unknown(ty));
15001478
}
@@ -1812,7 +1790,7 @@ impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> {
18121790
}
18131791

18141792
ty::TyProjection(_) | ty::TyAnon(..) => {
1815-
let normalized = normalize_associated_type(infcx, ty);
1793+
let normalized = infcx.normalize_projections(ty);
18161794
if ty == normalized {
18171795
Err(err)
18181796
} else {
@@ -1882,20 +1860,40 @@ pub trait LayoutTyper<'tcx>: HasTyCtxt<'tcx> {
18821860
type TyLayout;
18831861

18841862
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout;
1863+
fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx>;
18851864
}
18861865

18871866
impl<'a, 'gcx, 'tcx> LayoutTyper<'gcx> for &'a InferCtxt<'a, 'gcx, 'tcx> {
18881867
type TyLayout = Result<TyLayout<'gcx>, LayoutError<'gcx>>;
18891868

18901869
fn layout_of(self, ty: Ty<'gcx>) -> Self::TyLayout {
1891-
let ty = normalize_associated_type(self, ty);
1870+
let ty = self.normalize_projections(ty);
18921871

18931872
Ok(TyLayout {
18941873
ty: ty,
18951874
layout: ty.layout(self)?,
18961875
variant_index: None
18971876
})
18981877
}
1878+
1879+
fn normalize_projections(self, ty: Ty<'gcx>) -> Ty<'gcx> {
1880+
if !ty.has_projection_types() {
1881+
return ty;
1882+
}
1883+
1884+
let mut selcx = traits::SelectionContext::new(self);
1885+
let cause = traits::ObligationCause::dummy();
1886+
let traits::Normalized { value: result, obligations } =
1887+
traits::normalize(&mut selcx, cause, &ty);
1888+
1889+
let mut fulfill_cx = traits::FulfillmentContext::new();
1890+
1891+
for obligation in obligations {
1892+
fulfill_cx.register_predicate_obligation(self, obligation);
1893+
}
1894+
1895+
self.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
1896+
}
18991897
}
19001898

19011899
impl<'a, 'tcx> TyLayout<'tcx> {
@@ -2019,6 +2017,6 @@ impl<'a, 'tcx> TyLayout<'tcx> {
20192017
}
20202018

20212019
pub fn field<C: LayoutTyper<'tcx>>(&self, cx: C, i: usize) -> C::TyLayout {
2022-
cx.layout_of(self.field_type(cx, i))
2020+
cx.layout_of(cx.normalize_projections(self.field_type(cx, i)))
20232021
}
20242022
}

src/librustc_trans/context.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,10 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> {
771771
type TyLayout = TyLayout<'tcx>;
772772

773773
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
774+
if let Some(&layout) = self.tcx().layout_cache.borrow().get(&ty) {
775+
return TyLayout { ty: ty, layout: layout, variant_index: None };
776+
}
777+
774778
self.tcx().infer_ctxt((), traits::Reveal::All).enter(|infcx| {
775779
infcx.layout_of(ty).unwrap_or_else(|e| {
776780
match e {
@@ -781,6 +785,10 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> {
781785
})
782786
})
783787
}
788+
789+
fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> {
790+
self.tcx().normalize_associated_type(&ty)
791+
}
784792
}
785793

786794
impl<'a, 'tcx> LayoutTyper<'tcx> for &'a CrateContext<'a, 'tcx> {
@@ -789,6 +797,10 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a CrateContext<'a, 'tcx> {
789797
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
790798
self.shared.layout_of(ty)
791799
}
800+
801+
fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> {
802+
self.shared.normalize_projections(ty)
803+
}
792804
}
793805

794806
pub struct TypeOfDepthLock<'a, 'tcx: 'a>(&'a LocalCrateContext<'a, 'tcx>);

0 commit comments

Comments
 (0)