Refactor various queries out of ty and into trans/common

This commit is contained in:
Niko Matsakis 2014-12-16 15:00:05 -05:00
parent d2368c3c11
commit c08d004545
12 changed files with 75 additions and 64 deletions

View file

@ -682,7 +682,6 @@ pub struct ctxt<'tcx> {
pub tcache: RefCell<DefIdMap<Polytype<'tcx>>>,
pub rcache: RefCell<FnvHashMap<creader_cache_key, Ty<'tcx>>>,
pub short_names_cache: RefCell<FnvHashMap<Ty<'tcx>, String>>,
pub needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
pub tc_cache: RefCell<FnvHashMap<Ty<'tcx>, TypeContents>>,
pub ast_ty_to_ty_cache: RefCell<NodeMap<ast_ty_to_ty_cache_entry<'tcx>>>,
pub enum_var_cache: RefCell<DefIdMap<Rc<Vec<Rc<VariantInfo<'tcx>>>>>>,
@ -2108,7 +2107,6 @@ pub fn mk_ctxt<'tcx>(s: Session,
tcache: RefCell::new(DefIdMap::new()),
rcache: RefCell::new(FnvHashMap::new()),
short_names_cache: RefCell::new(FnvHashMap::new()),
needs_unwind_cleanup_cache: RefCell::new(FnvHashMap::new()),
tc_cache: RefCell::new(FnvHashMap::new()),
ast_ty_to_ty_cache: RefCell::new(NodeMap::new()),
enum_var_cache: RefCell::new(DefIdMap::new()),
@ -2824,48 +2822,6 @@ pub fn type_is_floating_point(ty: Ty) -> bool {
}
}
pub fn type_needs_drop<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
type_contents(cx, ty).needs_drop(cx)
}
// Some things don't need cleanups during unwinding because the
// task can free them all at once later. Currently only things
// that only contain scalars and shared boxes can avoid unwind
// cleanups.
pub fn type_needs_unwind_cleanup<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
return memoized(&cx.needs_unwind_cleanup_cache, ty, |ty| {
type_needs_unwind_cleanup_(cx, ty, &mut FnvHashSet::new())
});
fn type_needs_unwind_cleanup_<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>,
tycache: &mut FnvHashSet<Ty<'tcx>>) -> bool {
// Prevent infinite recursion
if !tycache.insert(ty) {
return false;
}
let mut needs_unwind_cleanup = false;
maybe_walk_ty(ty, |ty| {
needs_unwind_cleanup |= match ty.sty {
ty_bool | ty_int(_) | ty_uint(_) |
ty_float(_) | ty_tup(_) | ty_ptr(_) => false,
ty_enum(did, substs) =>
enum_variants(cx, did).iter().any(|v|
v.args.iter().any(|aty| {
let t = aty.subst(cx, substs);
type_needs_unwind_cleanup_(cx, t, tycache)
})
),
_ => true
};
!needs_unwind_cleanup
});
needs_unwind_cleanup
}
}
/// Type contents is how the type checker reasons about kinds.
/// They track what kinds of things are found within a type. You can
/// think of them as kind of an "anti-kind". They track the kinds of values

View file

@ -722,7 +722,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
};
if !is_rust_fn ||
type_of::return_uses_outptr(ccx, ret_ty) ||
ty::type_needs_drop(bcx.tcx(), ret_ty) {
type_needs_drop(bcx.tcx(), ret_ty) {
// Push the out-pointer if we use an out-pointer for this
// return type, otherwise push "undef".
if type_is_zero_size(ccx, ret_ty) {

View file

@ -279,10 +279,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
cleanup_scope: ScopeId,
val: ValueRef,
ty: Ty<'tcx>) {
if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; }
if !common::type_needs_drop(self.ccx.tcx(), ty) { return; }
let drop = box DropValue {
is_immediate: false,
must_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
val: val,
ty: ty,
zero: false
@ -301,10 +301,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
cleanup_scope: ScopeId,
val: ValueRef,
ty: Ty<'tcx>) {
if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; }
if !common::type_needs_drop(self.ccx.tcx(), ty) { return; }
let drop = box DropValue {
is_immediate: false,
must_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
val: val,
ty: ty,
zero: true
@ -325,10 +325,10 @@ impl<'blk, 'tcx> CleanupMethods<'blk, 'tcx> for FunctionContext<'blk, 'tcx> {
val: ValueRef,
ty: Ty<'tcx>) {
if !ty::type_needs_drop(self.ccx.tcx(), ty) { return; }
if !common::type_needs_drop(self.ccx.tcx(), ty) { return; }
let drop = box DropValue {
is_immediate: true,
must_unwind: ty::type_needs_unwind_cleanup(self.ccx.tcx(), ty),
must_unwind: common::type_needs_unwind_cleanup(self.ccx, ty),
val: val,
ty: ty,
zero: false

View file

@ -53,9 +53,58 @@ use syntax::ast_map::{PathElem, PathName};
use syntax::codemap::Span;
use syntax::parse::token::InternedString;
use syntax::parse::token;
use util::common::memoized;
use util::nodemap::FnvHashSet;
pub use trans::context::CrateContext;
// Some things don't need cleanups during unwinding because the
// task can free them all at once later. Currently only things
// that only contain scalars and shared boxes can avoid unwind
// cleanups.
pub fn type_needs_unwind_cleanup<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
return memoized(ccx.needs_unwind_cleanup_cache(), ty, |ty| {
type_needs_unwind_cleanup_(ccx.tcx(), ty, &mut FnvHashSet::new())
});
fn type_needs_unwind_cleanup_<'tcx>(tcx: &ty::ctxt<'tcx>,
ty: Ty<'tcx>,
tycache: &mut FnvHashSet<Ty<'tcx>>)
-> bool
{
// Prevent infinite recursion
if !tycache.insert(ty) {
return false;
}
let mut needs_unwind_cleanup = false;
ty::maybe_walk_ty(ty, |ty| {
needs_unwind_cleanup |= match ty.sty {
ty::ty_bool | ty::ty_int(_) | ty::ty_uint(_) |
ty::ty_float(_) | ty::ty_tup(_) | ty::ty_ptr(_) => false,
ty::ty_enum(did, substs) =>
ty::enum_variants(tcx, did).iter().any(|v|
v.args.iter().any(|aty| {
let t = aty.subst(tcx, substs);
type_needs_unwind_cleanup_(tcx, t, tycache)
})
),
_ => true
};
!needs_unwind_cleanup
});
needs_unwind_cleanup
}
}
pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>,
ty: Ty<'tcx>)
-> bool {
ty::type_contents(cx, ty).needs_drop(cx)
}
fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
ty: Ty<'tcx>) -> bool {
match ty.sty {

View file

@ -84,6 +84,7 @@ pub struct LocalCrateContext<'tcx> {
tn: TypeNames,
externs: RefCell<ExternMap>,
item_vals: RefCell<NodeMap<ValueRef>>,
needs_unwind_cleanup_cache: RefCell<FnvHashMap<Ty<'tcx>, bool>>,
fn_pointer_shims: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
drop_glues: RefCell<FnvHashMap<Ty<'tcx>, ValueRef>>,
tydescs: RefCell<FnvHashMap<Ty<'tcx>, Rc<tydesc_info<'tcx>>>>,
@ -389,6 +390,7 @@ impl<'tcx> LocalCrateContext<'tcx> {
tn: TypeNames::new(),
externs: RefCell::new(FnvHashMap::new()),
item_vals: RefCell::new(NodeMap::new()),
needs_unwind_cleanup_cache: RefCell::new(FnvHashMap::new()),
fn_pointer_shims: RefCell::new(FnvHashMap::new()),
drop_glues: RefCell::new(FnvHashMap::new()),
tydescs: RefCell::new(FnvHashMap::new()),
@ -569,6 +571,10 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
&self.shared.link_meta
}
pub fn needs_unwind_cleanup_cache(&self) -> &RefCell<FnvHashMap<Ty<'tcx>, bool>> {
&self.local.needs_unwind_cleanup_cache
}
pub fn fn_pointer_shims(&self) -> &RefCell<FnvHashMap<Ty<'tcx>, ValueRef>> {
&self.local.fn_pointer_shims
}

View file

@ -87,7 +87,7 @@ pub fn trans_stmt_semi<'blk, 'tcx>(cx: Block<'blk, 'tcx>, e: &ast::Expr)
-> Block<'blk, 'tcx> {
let _icx = push_ctxt("trans_stmt_semi");
let ty = expr_ty(cx, e);
if ty::type_needs_drop(cx.tcx(), ty) {
if type_needs_drop(cx.tcx(), ty) {
expr::trans_to_lvalue(cx, e, "stmt").bcx
} else {
expr::trans_into(cx, e, expr::Ignore)

View file

@ -218,7 +218,7 @@ impl KindOps for Lvalue {
val: ValueRef,
ty: Ty<'tcx>)
-> Block<'blk, 'tcx> {
if ty::type_needs_drop(bcx.tcx(), ty) {
if type_needs_drop(bcx.tcx(), ty) {
// cancel cleanup of affine values by zeroing out
let () = zero_mem(bcx, val, ty);
bcx
@ -567,7 +567,7 @@ impl<'tcx, K: KindOps + fmt::Show> Datum<'tcx, K> {
/// scalar-ish (like an int or a pointer) which (1) does not require drop glue and (2) is
/// naturally passed around by value, and not by reference.
pub fn to_llscalarish<'blk>(self, bcx: Block<'blk, 'tcx>) -> ValueRef {
assert!(!ty::type_needs_drop(bcx.tcx(), self.ty));
assert!(!type_needs_drop(bcx.tcx(), self.ty));
assert!(self.appropriate_rvalue_mode(bcx.ccx()) == ByValue);
if self.kind.is_by_ref() {
load_ty(bcx, self.val, self.ty)

View file

@ -976,7 +976,7 @@ fn trans_rvalue_stmt_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let src_datum = unpack_datum!(bcx, trans(bcx, &**src));
let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, &**dst, "assign"));
if ty::type_needs_drop(bcx.tcx(), dst_datum.ty) {
if type_needs_drop(bcx.tcx(), dst_datum.ty) {
// If there are destructors involved, make sure we
// are copying from an rvalue, since that cannot possible
// alias an lvalue. We are concerned about code like:
@ -1513,7 +1513,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
assert_eq!(discr, 0);
match ty::expr_kind(bcx.tcx(), &*base.expr) {
ty::RvalueDpsExpr | ty::RvalueDatumExpr if !ty::type_needs_drop(bcx.tcx(), ty) => {
ty::RvalueDpsExpr | ty::RvalueDatumExpr if !type_needs_drop(bcx.tcx(), ty) => {
bcx = trans_into(bcx, &*base.expr, SaveIn(addr));
},
ty::RvalueStmtExpr => bcx.tcx().sess.bug("unexpected expr kind for struct base expr"),
@ -2117,7 +2117,7 @@ fn trans_assign_op<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// Evaluate LHS (destination), which should be an lvalue
let dst_datum = unpack_datum!(bcx, trans_to_lvalue(bcx, dst, "assign_op"));
assert!(!ty::type_needs_drop(bcx.tcx(), dst_datum.ty));
assert!(!type_needs_drop(bcx.tcx(), dst_datum.ty));
let dst_ty = dst_datum.ty;
let dst = load_ty(bcx, dst_datum.val, dst_datum.ty);

View file

@ -84,11 +84,11 @@ pub fn get_drop_glue_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
if !ty::type_is_sized(tcx, t) {
return t
}
if !ty::type_needs_drop(tcx, t) {
if !type_needs_drop(tcx, t) {
return ty::mk_i8();
}
match t.sty {
ty::ty_uniq(typ) if !ty::type_needs_drop(tcx, typ)
ty::ty_uniq(typ) if !type_needs_drop(tcx, typ)
&& ty::type_is_sized(tcx, typ) => {
let llty = sizing_type_of(ccx, typ);
// `Box<ZeroSizeType>` does not allocate.
@ -110,7 +110,7 @@ pub fn drop_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
// NB: v is an *alias* of type t here, not a direct value.
debug!("drop_ty(t={})", t.repr(bcx.tcx()));
let _icx = push_ctxt("drop_ty");
if ty::type_needs_drop(bcx.tcx(), t) {
if type_needs_drop(bcx.tcx(), t) {
let ccx = bcx.ccx();
let glue = get_drop_glue(ccx, t);
let glue_type = get_drop_glue_type(ccx, t);
@ -469,7 +469,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, t: Ty<'tcx>)
ty::ty_vec(ty, None) => tvec::make_drop_glue_unboxed(bcx, v0, ty, false),
_ => {
assert!(ty::type_is_sized(bcx.tcx(), t));
if ty::type_needs_drop(bcx.tcx(), t) &&
if type_needs_drop(bcx.tcx(), t) &&
ty::type_is_structural(t) {
iter_structural_ty(bcx, v0, t, |bb, vv, tt| drop_ty(bb, vv, tt, None))
} else {

View file

@ -365,7 +365,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
}
(_, "needs_drop") => {
let tp_ty = *substs.types.get(FnSpace, 0);
C_bool(ccx, ty::type_needs_drop(ccx.tcx(), tp_ty))
C_bool(ccx, type_needs_drop(ccx.tcx(), tp_ty))
}
(_, "owns_managed") => {
let tp_ty = *substs.types.get(FnSpace, 0);

View file

@ -436,7 +436,7 @@ fn trans_trait_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let self_datum = unpack_datum!(
bcx, expr::trans(bcx, self_expr));
let llval = if ty::type_needs_drop(bcx.tcx(), self_datum.ty) {
let llval = if type_needs_drop(bcx.tcx(), self_datum.ty) {
let self_datum = unpack_datum!(
bcx, self_datum.to_rvalue_datum(bcx, "trait_callee"));

View file

@ -62,7 +62,7 @@ pub fn make_drop_glue_unboxed<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
let _icx = push_ctxt("tvec::make_drop_glue_unboxed");
let dataptr = get_dataptr(bcx, vptr);
let bcx = if ty::type_needs_drop(tcx, unit_ty) {
let bcx = if type_needs_drop(tcx, unit_ty) {
let len = get_len(bcx, vptr);
iter_vec_raw(bcx, dataptr, unit_ty, len, |bb, vv, tt| glue::drop_ty(bb, vv, tt, None))
} else {