Skip to content

Commit f3682e5

Browse files
author
Ariel Ben-Yehuda
committed
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 02ad572 commit f3682e5

File tree

2 files changed

+38
-28
lines changed

2 files changed

+38
-28
lines changed

src/librustc/ty/layout.rs

+26-28
Original file line numberDiff line numberDiff line change
@@ -801,7 +801,7 @@ impl<'a, 'gcx, 'tcx> Struct {
801801
}
802802

803803
(_, &ty::TyProjection(_)) | (_, &ty::TyAnon(..)) => {
804-
let normalized = normalize_associated_type(infcx, ty);
804+
let normalized = infcx.normalize_projections(ty);
805805
if ty == normalized {
806806
return Ok(None);
807807
}
@@ -1020,28 +1020,6 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
10201020
}
10211021
}
10221022

1023-
/// Helper function for normalizing associated types in an inference context.
1024-
fn normalize_associated_type<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
1025-
ty: Ty<'gcx>)
1026-
-> Ty<'gcx> {
1027-
if !ty.has_projection_types() {
1028-
return ty;
1029-
}
1030-
1031-
let mut selcx = traits::SelectionContext::new(infcx);
1032-
let cause = traits::ObligationCause::dummy();
1033-
let traits::Normalized { value: result, obligations } =
1034-
traits::normalize(&mut selcx, cause, &ty);
1035-
1036-
let mut fulfill_cx = traits::FulfillmentContext::new();
1037-
1038-
for obligation in obligations {
1039-
fulfill_cx.register_predicate_obligation(infcx, obligation);
1040-
}
1041-
1042-
infcx.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
1043-
}
1044-
10451023
impl<'a, 'gcx, 'tcx> Layout {
10461024
pub fn compute_uncached(ty: Ty<'gcx>,
10471025
infcx: &InferCtxt<'a, 'gcx, 'tcx>)
@@ -1053,7 +1031,7 @@ impl<'a, 'gcx, 'tcx> Layout {
10531031

10541032
let ptr_layout = |pointee: Ty<'gcx>| {
10551033
let non_zero = !ty.is_unsafe_ptr();
1056-
let pointee = normalize_associated_type(infcx, pointee);
1034+
let pointee = infcx.normalize_projections(pointee);
10571035
if pointee.is_sized(tcx, &infcx.parameter_environment, DUMMY_SP) {
10581036
Ok(Scalar { value: Pointer, non_zero: non_zero })
10591037
} else {
@@ -1441,7 +1419,7 @@ impl<'a, 'gcx, 'tcx> Layout {
14411419

14421420
// Types with no meaningful known layout.
14431421
ty::TyProjection(_) | ty::TyAnon(..) => {
1444-
let normalized = normalize_associated_type(infcx, ty);
1422+
let normalized = infcx.normalize_projections(ty);
14451423
if ty == normalized {
14461424
return Err(LayoutError::Unknown(ty));
14471425
}
@@ -1735,7 +1713,7 @@ impl<'a, 'gcx, 'tcx> SizeSkeleton<'gcx> {
17351713
}
17361714

17371715
ty::TyProjection(_) | ty::TyAnon(..) => {
1738-
let normalized = normalize_associated_type(infcx, ty);
1716+
let normalized = infcx.normalize_projections(ty);
17391717
if ty == normalized {
17401718
Err(err)
17411719
} else {
@@ -1805,20 +1783,40 @@ pub trait LayoutTyper<'tcx>: HasTyCtxt<'tcx> {
18051783
type TyLayout;
18061784

18071785
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout;
1786+
fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx>;
18081787
}
18091788

18101789
impl<'a, 'gcx, 'tcx> LayoutTyper<'gcx> for &'a InferCtxt<'a, 'gcx, 'tcx> {
18111790
type TyLayout = Result<TyLayout<'gcx>, LayoutError<'gcx>>;
18121791

18131792
fn layout_of(self, ty: Ty<'gcx>) -> Self::TyLayout {
1814-
let ty = normalize_associated_type(self, ty);
1793+
let ty = self.normalize_projections(ty);
18151794

18161795
Ok(TyLayout {
18171796
ty: ty,
18181797
layout: ty.layout(self)?,
18191798
variant_index: None
18201799
})
18211800
}
1801+
1802+
fn normalize_projections(self, ty: Ty<'gcx>) -> Ty<'gcx> {
1803+
if !ty.has_projection_types() {
1804+
return ty;
1805+
}
1806+
1807+
let mut selcx = traits::SelectionContext::new(self);
1808+
let cause = traits::ObligationCause::dummy();
1809+
let traits::Normalized { value: result, obligations } =
1810+
traits::normalize(&mut selcx, cause, &ty);
1811+
1812+
let mut fulfill_cx = traits::FulfillmentContext::new();
1813+
1814+
for obligation in obligations {
1815+
fulfill_cx.register_predicate_obligation(self, obligation);
1816+
}
1817+
1818+
self.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
1819+
}
18221820
}
18231821

18241822
impl<'a, 'tcx> TyLayout<'tcx> {
@@ -1942,6 +1940,6 @@ impl<'a, 'tcx> TyLayout<'tcx> {
19421940
}
19431941

19441942
pub fn field<C: LayoutTyper<'tcx>>(&self, cx: C, i: usize) -> C::TyLayout {
1945-
cx.layout_of(self.field_type(cx, i))
1943+
cx.layout_of(cx.normalize_projections(self.field_type(cx, i)))
19461944
}
19471945
}

src/librustc_trans/context.rs

+12
Original file line numberDiff line numberDiff line change
@@ -843,6 +843,10 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> {
843843
type TyLayout = TyLayout<'tcx>;
844844

845845
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
846+
if let Some(&layout) = self.tcx().layout_cache.borrow().get(&ty) {
847+
return TyLayout { ty: ty, layout: layout, variant_index: None };
848+
}
849+
846850
self.tcx().infer_ctxt((), traits::Reveal::All).enter(|infcx| {
847851
infcx.layout_of(ty).unwrap_or_else(|e| {
848852
match e {
@@ -853,6 +857,10 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a SharedCrateContext<'a, 'tcx> {
853857
})
854858
})
855859
}
860+
861+
fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> {
862+
self.tcx().normalize_associated_type(&ty)
863+
}
856864
}
857865

858866
impl<'a, 'tcx> LayoutTyper<'tcx> for &'a CrateContext<'a, 'tcx> {
@@ -861,6 +869,10 @@ impl<'a, 'tcx> LayoutTyper<'tcx> for &'a CrateContext<'a, 'tcx> {
861869
fn layout_of(self, ty: Ty<'tcx>) -> Self::TyLayout {
862870
self.shared.layout_of(ty)
863871
}
872+
873+
fn normalize_projections(self, ty: Ty<'tcx>) -> Ty<'tcx> {
874+
self.shared.normalize_projections(ty)
875+
}
864876
}
865877

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

0 commit comments

Comments
 (0)