Skip to content

Commit 9f8392e

Browse files
committed
remove layout_cache and fix -Z print-type-sizes
now we grow the type-sizes info during execution, rather than walking the cache after the fact
1 parent 0e05fc0 commit 9f8392e

File tree

7 files changed

+243
-203
lines changed

7 files changed

+243
-203
lines changed

src/librustc/ty/context.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -506,9 +506,6 @@ pub struct GlobalCtxt<'tcx> {
506506
/// Data layout specification for the current target.
507507
pub data_layout: TargetDataLayout,
508508

509-
/// Cache for layouts computed from types.
510-
pub layout_cache: RefCell<FxHashMap<Ty<'tcx>, &'tcx Layout>>,
511-
512509
/// Used to prevent layout from recursing too deeply.
513510
pub layout_depth: Cell<usize>,
514511

@@ -705,7 +702,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
705702
rvalue_promotable_to_static: RefCell::new(NodeMap()),
706703
crate_name: Symbol::intern(crate_name),
707704
data_layout: data_layout,
708-
layout_cache: RefCell::new(FxHashMap()),
709705
layout_interner: RefCell::new(FxHashSet()),
710706
layout_depth: Cell::new(0),
711707
derive_macros: RefCell::new(NodeMap()),

src/librustc/ty/layout.rs

Lines changed: 215 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,10 @@ pub use self::Integer::*;
1212
pub use self::Layout::*;
1313
pub use self::Primitive::*;
1414

15-
use session::Session;
15+
use session::{self, DataTypeKind, Session};
1616
use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions, ReprFlags};
1717

18-
use syntax::ast::{FloatTy, IntTy, UintTy};
18+
use syntax::ast::{self, FloatTy, IntTy, UintTy};
1919
use syntax::attr;
2020
use syntax_pos::DUMMY_SP;
2121

@@ -1690,6 +1690,219 @@ impl<'a, 'tcx> Layout {
16901690
}
16911691
}
16921692
}
1693+
1694+
/// This is invoked by the `layout_raw` query to record the final
1695+
/// layout of each type.
1696+
#[inline]
1697+
pub fn record_layout_for_printing(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1698+
ty: Ty<'tcx>,
1699+
param_env: ty::ParamEnv<'tcx>,
1700+
layout: &Layout) {
1701+
// If we are running with `-Zprint-type-sizes`, record layouts for
1702+
// dumping later. Ignore layouts that are done with non-empty
1703+
// environments or non-monomorphic layouts, as the user only wants
1704+
// to see the stuff resulting from the final trans session.
1705+
if
1706+
!tcx.sess.opts.debugging_opts.print_type_sizes ||
1707+
ty.has_param_types() ||
1708+
ty.has_self_ty() ||
1709+
!param_env.caller_bounds.is_empty()
1710+
{
1711+
return;
1712+
}
1713+
1714+
Self::record_layout_for_printing_outlined(tcx, ty, param_env, layout)
1715+
}
1716+
1717+
fn record_layout_for_printing_outlined(tcx: TyCtxt<'a, 'tcx, 'tcx>,
1718+
ty: Ty<'tcx>,
1719+
param_env: ty::ParamEnv<'tcx>,
1720+
layout: &Layout) {
1721+
// (delay format until we actually need it)
1722+
let record = |kind, opt_discr_size, variants| {
1723+
let type_desc = format!("{:?}", ty);
1724+
let overall_size = layout.size(tcx);
1725+
let align = layout.align(tcx);
1726+
tcx.sess.code_stats.borrow_mut().record_type_size(kind,
1727+
type_desc,
1728+
align,
1729+
overall_size,
1730+
opt_discr_size,
1731+
variants);
1732+
};
1733+
1734+
let (adt_def, substs) = match ty.sty {
1735+
ty::TyAdt(ref adt_def, substs) => {
1736+
debug!("print-type-size t: `{:?}` process adt", ty);
1737+
(adt_def, substs)
1738+
}
1739+
1740+
ty::TyClosure(..) => {
1741+
debug!("print-type-size t: `{:?}` record closure", ty);
1742+
record(DataTypeKind::Closure, None, vec![]);
1743+
return;
1744+
}
1745+
1746+
_ => {
1747+
debug!("print-type-size t: `{:?}` skip non-nominal", ty);
1748+
return;
1749+
}
1750+
};
1751+
1752+
let adt_kind = adt_def.adt_kind();
1753+
1754+
let build_field_info = |(field_name, field_ty): (ast::Name, Ty<'tcx>), offset: &Size| {
1755+
let layout = field_ty.layout(tcx, param_env);
1756+
match layout {
1757+
Err(_) => bug!("no layout found for field {} type: `{:?}`", field_name, field_ty),
1758+
Ok(field_layout) => {
1759+
session::FieldInfo {
1760+
name: field_name.to_string(),
1761+
offset: offset.bytes(),
1762+
size: field_layout.size(tcx).bytes(),
1763+
align: field_layout.align(tcx).abi(),
1764+
}
1765+
}
1766+
}
1767+
};
1768+
1769+
let build_primitive_info = |name: ast::Name, value: &Primitive| {
1770+
session::VariantInfo {
1771+
name: Some(name.to_string()),
1772+
kind: session::SizeKind::Exact,
1773+
align: value.align(tcx).abi(),
1774+
size: value.size(tcx).bytes(),
1775+
fields: vec![],
1776+
}
1777+
};
1778+
1779+
enum Fields<'a> {
1780+
WithDiscrim(&'a Struct),
1781+
NoDiscrim(&'a Struct),
1782+
}
1783+
1784+
let build_variant_info = |n: Option<ast::Name>,
1785+
flds: &[(ast::Name, Ty<'tcx>)],
1786+
layout: Fields| {
1787+
let (s, field_offsets) = match layout {
1788+
Fields::WithDiscrim(s) => (s, &s.offsets[1..]),
1789+
Fields::NoDiscrim(s) => (s, &s.offsets[0..]),
1790+
};
1791+
let field_info: Vec<_> = flds.iter()
1792+
.zip(field_offsets.iter())
1793+
.map(|(&field_name_ty, offset)| build_field_info(field_name_ty, offset))
1794+
.collect();
1795+
1796+
session::VariantInfo {
1797+
name: n.map(|n|n.to_string()),
1798+
kind: if s.sized {
1799+
session::SizeKind::Exact
1800+
} else {
1801+
session::SizeKind::Min
1802+
},
1803+
align: s.align.abi(),
1804+
size: s.min_size.bytes(),
1805+
fields: field_info,
1806+
}
1807+
};
1808+
1809+
match *layout {
1810+
Layout::StructWrappedNullablePointer { nonnull: ref variant_layout,
1811+
nndiscr,
1812+
discrfield: _,
1813+
discrfield_source: _ } => {
1814+
debug!("print-type-size t: `{:?}` adt struct-wrapped nullable nndiscr {} is {:?}",
1815+
ty, nndiscr, variant_layout);
1816+
let variant_def = &adt_def.variants[nndiscr as usize];
1817+
let fields: Vec<_> = variant_def.fields.iter()
1818+
.map(|field_def| (field_def.name, field_def.ty(tcx, substs)))
1819+
.collect();
1820+
record(adt_kind.into(),
1821+
None,
1822+
vec![build_variant_info(Some(variant_def.name),
1823+
&fields,
1824+
Fields::NoDiscrim(variant_layout))]);
1825+
}
1826+
Layout::RawNullablePointer { nndiscr, value } => {
1827+
debug!("print-type-size t: `{:?}` adt raw nullable nndiscr {} is {:?}",
1828+
ty, nndiscr, value);
1829+
let variant_def = &adt_def.variants[nndiscr as usize];
1830+
record(adt_kind.into(), None,
1831+
vec![build_primitive_info(variant_def.name, &value)]);
1832+
}
1833+
Layout::Univariant { variant: ref variant_layout, non_zero: _ } => {
1834+
let variant_names = || {
1835+
adt_def.variants.iter().map(|v|format!("{}", v.name)).collect::<Vec<_>>()
1836+
};
1837+
debug!("print-type-size t: `{:?}` adt univariant {:?} variants: {:?}",
1838+
ty, variant_layout, variant_names());
1839+
assert!(adt_def.variants.len() <= 1,
1840+
"univariant with variants {:?}", variant_names());
1841+
if adt_def.variants.len() == 1 {
1842+
let variant_def = &adt_def.variants[0];
1843+
let fields: Vec<_> = variant_def.fields.iter()
1844+
.map(|field_def| (field_def.name, field_def.ty(tcx, substs)))
1845+
.collect();
1846+
record(adt_kind.into(),
1847+
None,
1848+
vec![build_variant_info(Some(variant_def.name),
1849+
&fields,
1850+
Fields::NoDiscrim(variant_layout))]);
1851+
} else {
1852+
// (This case arises for *empty* enums; so give it
1853+
// zero variants.)
1854+
record(adt_kind.into(), None, vec![]);
1855+
}
1856+
}
1857+
1858+
Layout::General { ref variants, discr, .. } => {
1859+
debug!("print-type-size t: `{:?}` adt general variants def {} layouts {} {:?}",
1860+
ty, adt_def.variants.len(), variants.len(), variants);
1861+
let variant_infos: Vec<_> = adt_def.variants.iter()
1862+
.zip(variants.iter())
1863+
.map(|(variant_def, variant_layout)| {
1864+
let fields: Vec<_> = variant_def.fields.iter()
1865+
.map(|field_def| (field_def.name, field_def.ty(tcx, substs)))
1866+
.collect();
1867+
build_variant_info(Some(variant_def.name),
1868+
&fields,
1869+
Fields::WithDiscrim(variant_layout))
1870+
})
1871+
.collect();
1872+
record(adt_kind.into(), Some(discr.size()), variant_infos);
1873+
}
1874+
1875+
Layout::UntaggedUnion { ref variants } => {
1876+
debug!("print-type-size t: `{:?}` adt union variants {:?}",
1877+
ty, variants);
1878+
// layout does not currently store info about each
1879+
// variant...
1880+
record(adt_kind.into(), None, Vec::new());
1881+
}
1882+
1883+
Layout::CEnum { discr, .. } => {
1884+
debug!("print-type-size t: `{:?}` adt c-like enum", ty);
1885+
let variant_infos: Vec<_> =
1886+
adt_def.variants.iter()
1887+
.map(|variant_def| {
1888+
build_primitive_info(variant_def.name,
1889+
&Primitive::Int(discr))
1890+
})
1891+
.collect();
1892+
record(adt_kind.into(), Some(discr.size()), variant_infos);
1893+
}
1894+
1895+
// other cases provide little interesting (i.e. adjustable
1896+
// via representation tweaks) size info beyond total size.
1897+
Layout::Scalar { .. } |
1898+
Layout::Vector { .. } |
1899+
Layout::Array { .. } |
1900+
Layout::FatPointer { .. } => {
1901+
debug!("print-type-size t: `{:?}` adt other", ty);
1902+
record(adt_kind.into(), None, Vec::new())
1903+
}
1904+
}
1905+
}
16931906
}
16941907

16951908
/// Type size "skeleton", i.e. the only information determining a type's size.

src/librustc/ty/util.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,9 +800,22 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
800800
param_env: ty::ParamEnv<'tcx>)
801801
-> Result<&'tcx Layout, LayoutError<'tcx>> {
802802
let ty = tcx.erase_regions(&self);
803-
tcx.layout_raw(param_env.reveal_all().and(ty))
803+
let layout = tcx.layout_raw(param_env.reveal_all().and(ty));
804+
805+
// NB: This recording is normally disabled; when enabled, it
806+
// can however trigger recursive invocations of `layout()`.
807+
// Therefore, we execute it *after* the main query has
808+
// completed, to avoid problems around recursive structures
809+
// and the like. (Admitedly, I wasn't able to reproduce a problem
810+
// here, but it seems like the right thing to do. -nmatsakis)
811+
if let Ok(l) = layout {
812+
Layout::record_layout_for_printing(tcx, ty, param_env, l);
813+
}
814+
815+
layout
804816
}
805817

818+
806819
/// Check whether a type is representable. This means it cannot contain unboxed
807820
/// structural recursion. This check is needed for structs and enums.
808821
pub fn is_representable(&'tcx self,
@@ -1085,6 +1098,7 @@ fn layout_raw<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
10851098
tcx.layout_depth.set(depth+1);
10861099
let layout = Layout::compute_uncached(tcx, param_env, ty);
10871100
tcx.layout_depth.set(depth);
1101+
10881102
layout
10891103
}
10901104

0 commit comments

Comments
 (0)