Skip to content

Commit 81efa9d

Browse files
author
Ariel Ben-Yehuda
committed
Introduce a fast-path for type_is_sized/type_moves_by_default
This seems to improve performance by the same 2-3% of my selection fast-path.
1 parent b21e03c commit 81efa9d

File tree

4 files changed

+45
-40
lines changed

4 files changed

+45
-40
lines changed

src/librustc/middle/check_rvalues.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'tcx> {
6060
cmt: mc::cmt<'tcx>,
6161
_: euv::ConsumeMode) {
6262
debug!("consume; cmt: {:?}; type: {}", *cmt, ty_to_string(self.tcx, cmt.ty));
63-
if !ty::type_is_sized(self.param_env, span, cmt.ty) {
63+
if !ty::type_is_sized(Some(self.param_env), self.tcx, span, cmt.ty) {
6464
span_err!(self.tcx.sess, span, E0161,
6565
"cannot move a value of type {0}: the size of {0} cannot be statically determined",
6666
ty_to_string(self.tcx, cmt.ty));

src/librustc/middle/intrinsicck.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -212,7 +212,7 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
212212
debug!("with_each_combination: space={:?}, index={}, param_ty={}",
213213
space, index, param_ty.repr(self.tcx));
214214

215-
if !ty::type_is_sized(param_env, span, param_ty) {
215+
if !ty::type_is_sized(Some(param_env), self.tcx, span, param_ty) {
216216
debug!("with_each_combination: param_ty is not known to be sized");
217217

218218
substs.types.get_mut_slice(space)[index] = self.dummy_unsized_ty;

src/librustc/middle/ty.rs

Lines changed: 41 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -756,16 +756,6 @@ pub struct ctxt<'tcx> {
756756
/// Caches the representation hints for struct definitions.
757757
pub repr_hint_cache: RefCell<DefIdMap<Rc<Vec<attr::ReprAttr>>>>,
758758

759-
/// Caches whether types are known to impl Copy. Note that type
760-
/// parameters are never placed into this cache, because their
761-
/// results are dependent on the parameter environment.
762-
pub type_impls_copy_cache: RefCell<HashMap<Ty<'tcx>,bool>>,
763-
764-
/// Caches whether types are known to impl Sized. Note that type
765-
/// parameters are never placed into this cache, because their
766-
/// results are dependent on the parameter environment.
767-
pub type_impls_sized_cache: RefCell<HashMap<Ty<'tcx>,bool>>,
768-
769759
/// Maps Expr NodeId's to their constant qualification.
770760
pub const_qualif_map: RefCell<NodeMap<check_const::ConstQualif>>,
771761

@@ -828,6 +818,17 @@ bitflags! {
828818
TypeFlags::HAS_SELF.bits |
829819
TypeFlags::HAS_REGIONS.bits,
830820

821+
// Flags representing the nominal content of a type,
822+
// computed by FlagsComputetion
823+
const NOMINAL_FLAGS = TypeFlags::HAS_PARAMS.bits |
824+
TypeFlags::HAS_SELF.bits |
825+
TypeFlags::HAS_TY_INFER.bits |
826+
TypeFlags::HAS_RE_INFER.bits |
827+
TypeFlags::HAS_RE_LATE_BOUND.bits |
828+
TypeFlags::HAS_REGIONS.bits |
829+
TypeFlags::HAS_TY_ERR.bits |
830+
TypeFlags::HAS_PROJECTION.bits,
831+
831832
// Caches for type_is_sized, type_moves_by_default
832833
const SIZEDNESS_CACHED = 1 << 16,
833834
const IS_SIZED = 1 << 17,
@@ -2776,8 +2777,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
27762777
stability: RefCell::new(stability),
27772778
selection_cache: traits::SelectionCache::new(),
27782779
repr_hint_cache: RefCell::new(DefIdMap()),
2779-
type_impls_copy_cache: RefCell::new(HashMap::new()),
2780-
type_impls_sized_cache: RefCell::new(HashMap::new()),
27812780
const_qualif_map: RefCell::new(NodeMap()),
27822781
custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
27832782
cast_kinds: RefCell::new(NodeMap()),
@@ -2908,7 +2907,7 @@ impl FlagComputation {
29082907
}
29092908

29102909
fn add_flags(&mut self, flags: TypeFlags) {
2911-
self.flags = self.flags | flags;
2910+
self.flags = self.flags | (flags & TypeFlags::NOMINAL_FLAGS);
29122911
}
29132912

29142913
fn add_depth(&mut self, depth: u32) {
@@ -3917,18 +3916,27 @@ pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
39173916
}
39183917
}
39193918

3920-
fn type_impls_bound<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
3919+
fn type_impls_bound<'a,'tcx>(param_env: Option<&ParameterEnvironment<'a,'tcx>>,
3920+
tcx: &ty::ctxt<'tcx>,
39213921
ty: Ty<'tcx>,
39223922
bound: ty::BuiltinBound,
39233923
span: Span)
39243924
-> bool
39253925
{
3926-
let infcx = infer::new_infer_ctxt(param_env.tcx);
3926+
let pe;
3927+
let param_env = match param_env {
3928+
Some(e) => e,
3929+
None => {
3930+
pe = empty_parameter_environment(tcx);
3931+
&pe
3932+
}
3933+
};
3934+
let infcx = infer::new_infer_ctxt(tcx);
39273935

39283936
let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env, ty, bound, span);
39293937

39303938
debug!("type_impls_bound({}, {:?}) = {:?}",
3931-
ty.repr(param_env.tcx),
3939+
ty.repr(tcx),
39323940
bound,
39333941
is_impld);
39343942

@@ -3960,7 +3968,11 @@ pub fn type_moves_by_default<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
39603968
ty_vec(..) | ty_trait(..) | ty_tup(..) |
39613969
ty_closure(..) | ty_enum(..) | ty_struct(..) |
39623970
ty_projection(..) | ty_param(..) | ty_infer(..) | ty_err => None
3963-
}.unwrap_or(!type_impls_bound(param_env, ty, ty::BoundCopy, span));
3971+
}.unwrap_or_else(|| !type_impls_bound(Some(param_env),
3972+
param_env.tcx,
3973+
ty,
3974+
ty::BoundCopy,
3975+
span));
39643976

39653977
if !type_has_params(ty) && !type_has_self(ty) {
39663978
ty.flags.set(ty.flags.get() | if result {
@@ -3973,33 +3985,38 @@ pub fn type_moves_by_default<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
39733985
result
39743986
}
39753987

3976-
pub fn type_is_sized<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
3988+
#[inline]
3989+
pub fn type_is_sized<'a,'tcx>(param_env: Option<&ParameterEnvironment<'a,'tcx>>,
3990+
tcx: &ty::ctxt<'tcx>,
39773991
span: Span,
39783992
ty: Ty<'tcx>)
39793993
-> bool
39803994
{
39813995
if ty.flags.get().intersects(TypeFlags::SIZEDNESS_CACHED) {
39823996
let result = ty.flags.get().intersects(TypeFlags::IS_SIZED);
3983-
debug!("type_is_sized({}) = {} (cached)", ty.repr(param_env.tcx),
3984-
result);
39853997
return result;
39863998
}
39873999

4000+
type_is_sized_uncached(param_env, tcx, span, ty)
4001+
}
4002+
4003+
fn type_is_sized_uncached<'a,'tcx>(param_env: Option<&ParameterEnvironment<'a,'tcx>>,
4004+
tcx: &ty::ctxt<'tcx>,
4005+
span: Span,
4006+
ty: Ty<'tcx>) -> bool {
39884007
assert!(!ty::type_needs_infer(ty));
39894008

39904009
// Fast-path for primitive types
39914010
let result = match ty.sty {
39924011
ty_bool | ty_char | ty_int(..) | ty_uint(..) | ty_float(..) |
39934012
ty_uniq(..) | ty_ptr(..) | ty_rptr(..) | ty_bare_fn(..) |
3994-
ty_vec(_, Some(..)) | ty_tup(..) | ty_closure(..) => {
3995-
Some(true)
3996-
}
4013+
ty_vec(_, Some(..)) | ty_tup(..) | ty_closure(..) => Some(true),
39974014

39984015
ty_str | ty_trait(..) | ty_vec(_, None) => Some(false),
39994016

40004017
ty_enum(..) | ty_struct(..) | ty_projection(..) | ty_param(..) |
40014018
ty_infer(..) | ty_err => None
4002-
}.unwrap_or(type_impls_bound(param_env, ty, ty::BoundSized, span));
4019+
}.unwrap_or_else(|| type_impls_bound(param_env, tcx, ty, ty::BoundSized, span));
40034020

40044021
if !type_has_params(ty) && !type_has_self(ty) {
40054022
ty.flags.set(ty.flags.get() | if result {
@@ -4009,8 +4026,6 @@ pub fn type_is_sized<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
40094026
});
40104027
}
40114028

4012-
debug!("type_is_sized({}) = {}", ty.repr(param_env.tcx),
4013-
result);
40144029
result
40154030
}
40164031

src/librustc_trans/trans/common.rs

Lines changed: 2 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -118,19 +118,9 @@ pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
118118
}
119119
}
120120

121-
// Is the type's representation size known at compile time?
121+
/// Is the type's representation size known at compile time?
122122
pub fn type_is_sized<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
123-
let param_env = ty::empty_parameter_environment(tcx);
124-
// FIXME(#4287) This can cause errors due to polymorphic recursion,
125-
// a better span should be provided, if available.
126-
let err_count = tcx.sess.err_count();
127-
let is_sized = ty::type_is_sized(&param_env, DUMMY_SP, ty);
128-
// Those errors aren't fatal, but an incorrect result can later
129-
// trip over asserts in both rustc's trans and LLVM.
130-
if err_count < tcx.sess.err_count() {
131-
tcx.sess.abort_if_errors();
132-
}
133-
is_sized
123+
ty::type_is_sized(None, tcx, DUMMY_SP, ty)
134124
}
135125

136126
pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {

0 commit comments

Comments
 (0)