diff options
| author | Graydon Hoare <graydon@mozilla.com> | 2012-09-12 14:48:13 -0700 |
|---|---|---|
| committer | Graydon Hoare <graydon@mozilla.com> | 2012-09-12 14:48:18 -0700 |
| commit | 719a4750ba7d4c6e35f6a2d0579ab9fb79dbf1f3 (patch) | |
| tree | 92bfb74d14d82481b421c0e8b384dd0efeeda61e /src | |
| parent | 4ce2ee12beea76727fe2ced87748c31725ce4e98 (diff) | |
Add some monomorphizing instrumentation, simplify types before emitting glue.
Diffstat (limited to 'src')
| -rw-r--r-- | src/rustc/middle/trans/base.rs | 13 | ||||
| -rw-r--r-- | src/rustc/middle/trans/common.rs | 4 | ||||
| -rw-r--r-- | src/rustc/middle/trans/glue.rs | 98 | ||||
| -rw-r--r-- | src/rustc/middle/trans/inline.rs | 2 | ||||
| -rw-r--r-- | src/rustc/middle/trans/monomorphize.rs | 2 | ||||
| -rw-r--r-- | src/rustc/middle/ty.rs | 20 |
6 files changed, 135 insertions, 4 deletions
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 638ccca3dbe..6b89549e73c 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -1554,6 +1554,7 @@ fn trans_closure(ccx: @crate_ctxt, path: path, decl: ast::fn_decl, id: ast::node_id, maybe_load_env: fn(fn_ctxt), finish: fn(block)) { + ccx.stats.n_closures += 1; let _icx = ccx.insn_ctxt("trans_closure"); set_uwtable(llfndecl); @@ -1619,6 +1620,7 @@ fn trans_fn(ccx: @crate_ctxt, let start = if do_time { time::get_time() } else { {sec: 0i64, nsec: 0i32} }; let _icx = ccx.insn_ctxt("trans_fn"); + ccx.stats.n_fns += 1; trans_closure(ccx, path, decl, body, llfndecl, ty_self, param_substs, id, |fcx| { @@ -2651,6 +2653,10 @@ fn trans_crate(sess: session::session, mut n_glues_created: 0u, mut n_null_glues: 0u, mut n_real_glues: 0u, + mut n_fns: 0u, + mut n_monos: 0u, + mut n_inlines: 0u, + mut n_closures: 0u, llvm_insn_ctxt: @mut ~[], llvm_insns: str_hash(), fn_times: @mut ~[]}, @@ -2704,13 +2710,20 @@ fn trans_crate(sess: session::session, io::println(fmt!("n_null_glues: %u", ccx.stats.n_null_glues)); io::println(fmt!("n_real_glues: %u", ccx.stats.n_real_glues)); + io::println(fmt!("n_fns: %u", ccx.stats.n_fns)); + io::println(fmt!("n_monos: %u", ccx.stats.n_monos)); + io::println(fmt!("n_inlines: %u", ccx.stats.n_inlines)); + io::println(fmt!("n_closures: %u", ccx.stats.n_closures)); + // FIXME (#2280): this temporary shouldn't be // necessary, but seems to be, for borrowing. + /* let times = copy *ccx.stats.fn_times; for vec::each(times) |timing| { io::println(fmt!("time: %s took %d ms", timing.ident, timing.time)); } + */ } if ccx.sess.count_llvm_insns() { diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index 9d0579fa88f..0708d9f21a6 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -89,6 +89,10 @@ type stats = mut n_glues_created: uint, mut n_null_glues: uint, mut n_real_glues: uint, + mut n_fns: uint, + mut n_monos: uint, + mut n_inlines: uint, + mut n_closures: uint, llvm_insn_ctxt: @mut ~[~str], llvm_insns: HashMap<~str, uint>, fn_times: @mut ~[{ident: ~str, time: int}]}; diff --git a/src/rustc/middle/trans/glue.rs b/src/rustc/middle/trans/glue.rs index 282f890ef2a..fce38badf9a 100644 --- a/src/rustc/middle/trans/glue.rs +++ b/src/rustc/middle/trans/glue.rs @@ -121,10 +121,103 @@ fn lazily_emit_all_tydesc_glue(ccx: @crate_ctxt, lazily_emit_tydesc_glue(ccx, abi::tydesc_field_visit_glue, static_ti); } +fn simplified_glue_type(tcx: ty::ctxt, field: uint, t: ty::t) -> ty::t { + + if (field == abi::tydesc_field_take_glue || + field == abi::tydesc_field_drop_glue || + field == abi::tydesc_field_free_glue) && + ! ty::type_needs_drop(tcx, t) { + return ty::mk_u32(tcx); + } + + if field == abi::tydesc_field_take_glue { + match ty::get(t).sty { + ty::ty_unboxed_vec(*) => { return ty::mk_u32(tcx); } + _ => () + } + } + + if field == abi::tydesc_field_take_glue && + ty::type_is_boxed(t) { + return ty::mk_imm_box(tcx, ty::mk_u32(tcx)); + } + + if field == abi::tydesc_field_free_glue { + match ty::get(t).sty { + ty::ty_fn(*) | + ty::ty_box(*) | + ty::ty_opaque_box | + ty::ty_uniq(*) | + ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) | + ty::ty_evec(_, ty::vstore_box) | ty::ty_estr(ty::vstore_box) | + ty::ty_opaque_closure_ptr(*) => (), + _ => { return ty::mk_u32(tcx); } + } + } + + if (field == abi::tydesc_field_free_glue || + field == abi::tydesc_field_drop_glue) { + match ty::get(t).sty { + ty::ty_box(mt) | + ty::ty_evec(mt, ty::vstore_box) + if ! ty::type_needs_drop(tcx, mt.ty) => + return ty::mk_imm_box(tcx, ty::mk_u32(tcx)), + + ty::ty_uniq(mt) | + ty::ty_evec(mt, ty::vstore_uniq) + if ! ty::type_needs_drop(tcx, mt.ty) => + return ty::mk_imm_uniq(tcx, ty::mk_u32(tcx)), + + _ => () + } + } + + return t; +} + +pure fn cast_glue(ccx: @crate_ctxt, ti: @tydesc_info, v: ValueRef) + -> ValueRef { + unchecked { + let llfnty = type_of_glue_fn(ccx, ti.ty); + llvm::LLVMConstPointerCast(v, T_ptr(llfnty)) + } +} + +fn lazily_emit_simplified_tydesc_glue(ccx: @crate_ctxt, field: uint, + ti: @tydesc_info) -> bool { + let _icx = ccx.insn_ctxt("lazily_emit_simplified_tydesc_glue"); + let simpl = simplified_glue_type(ccx.tcx, field, ti.ty); + if simpl != ti.ty { + let simpl_ti = base::get_tydesc(ccx, simpl); + lazily_emit_tydesc_glue(ccx, field, simpl_ti); + if field == abi::tydesc_field_take_glue { + ti.take_glue = + simpl_ti.take_glue.map(|v| cast_glue(ccx, ti, v)); + } else if field == abi::tydesc_field_drop_glue { + ti.drop_glue = + simpl_ti.drop_glue.map(|v| cast_glue(ccx, ti, v)); + } else if field == abi::tydesc_field_free_glue { + ti.free_glue = + simpl_ti.free_glue.map(|v| cast_glue(ccx, ti, v)); + } else if field == abi::tydesc_field_visit_glue { + ti.visit_glue = + simpl_ti.visit_glue.map(|v| cast_glue(ccx, ti, v)); + } + return true; + } + return false; +} + + fn lazily_emit_tydesc_glue(ccx: @crate_ctxt, field: uint, ti: @tydesc_info) { let _icx = ccx.insn_ctxt("lazily_emit_tydesc_glue"); let llfnty = type_of_glue_fn(ccx, ti.ty); + + if lazily_emit_simplified_tydesc_glue(ccx, field, ti) { + return; + } + if field == abi::tydesc_field_take_glue { match ti.take_glue { Some(_) => (), @@ -502,7 +595,9 @@ fn declare_tydesc(ccx: @crate_ctxt, t: ty::t) -> @tydesc_info { //XXX this triggers duplicate LLVM symbols let name = if false /*ccx.sess.opts.debuginfo*/ { mangle_internal_name_by_type_only(ccx, t, ~"tydesc") - } else { mangle_internal_name_by_seq(ccx, ~"tydesc") }; + } else { + mangle_internal_name_by_seq(ccx, ~"tydesc") + }; note_unique_llvm_symbol(ccx, name); log(debug, fmt!("+++ declare_tydesc %s %s", ty_to_str(ccx.tcx, t), name)); let gvar = str::as_c_str(name, |buf| { @@ -535,6 +630,7 @@ fn declare_generic_glue(ccx: @crate_ctxt, t: ty::t, llfnty: TypeRef, } else { fn_nm = mangle_internal_name_by_seq(ccx, (~"glue_" + name)); } + debug!("%s is for type %s", fn_nm, ty_to_str(ccx.tcx, t)); note_unique_llvm_symbol(ccx, fn_nm); let llfn = decl_cdecl_fn(ccx.llmod, fn_nm, llfnty); set_glue_inlining(llfn, t); diff --git a/src/rustc/middle/trans/inline.rs b/src/rustc/middle/trans/inline.rs index 6de7e77a394..08e9cde6ac5 100644 --- a/src/rustc/middle/trans/inline.rs +++ b/src/rustc/middle/trans/inline.rs @@ -30,6 +30,7 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) } csearch::found(ast::ii_item(item)) => { ccx.external.insert(fn_id, Some(item.id)); + ccx.stats.n_inlines += 1; trans_item(ccx, *item); local_def(item.id) } @@ -64,6 +65,7 @@ fn maybe_instantiate_inline(ccx: @crate_ctxt, fn_id: ast::def_id) with a non-item parent"); } csearch::found(ast::ii_method(impl_did, mth)) => { + ccx.stats.n_inlines += 1; ccx.external.insert(fn_id, Some(mth.id)); let {bounds: impl_bnds, region_param: _, ty: impl_ty} = ty::lookup_item_type(ccx.tcx, impl_did); diff --git a/src/rustc/middle/trans/monomorphize.rs b/src/rustc/middle/trans/monomorphize.rs index 385f4116190..243b0b96fa3 100644 --- a/src/rustc/middle/trans/monomorphize.rs +++ b/src/rustc/middle/trans/monomorphize.rs @@ -97,6 +97,8 @@ fn monomorphic_fn(ccx: @crate_ctxt, let mono_ty = ty::subst_tps(ccx.tcx, substs, llitem_ty); let llfty = type_of_fn_from_ty(ccx, mono_ty); + ccx.stats.n_monos += 1; + let depth = option::get_default(ccx.monomorphizing.find(fn_id), 0u); // Random cut-off -- code that needs to instantiate the same function // recursively more than ten times can probably safely be assumed to be diff --git a/src/rustc/middle/ty.rs b/src/rustc/middle/ty.rs index a1307d70972..f66e609cd70 100644 --- a/src/rustc/middle/ty.rs +++ b/src/rustc/middle/ty.rs @@ -1546,6 +1546,7 @@ fn type_is_immediate(ty: t) -> bool { type_is_unique(ty) || type_is_region_ptr(ty); } + fn type_needs_drop(cx: ctxt, ty: t) -> bool { match cx.needs_drop_cache.find(ty) { Some(result) => return result, @@ -1557,8 +1558,22 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool { // scalar types ty_nil | ty_bot | ty_bool | ty_int(_) | ty_float(_) | ty_uint(_) | ty_type | ty_ptr(_) | ty_rptr(_, _) | - ty_estr(vstore_fixed(_)) | ty_estr(vstore_slice(_)) | - ty_evec(_, vstore_slice(_)) => false, + ty_estr(vstore_fixed(_)) | + ty_estr(vstore_slice(_)) | + ty_evec(_, vstore_slice(_)) | + ty_self => false, + + ty_box(_) | ty_uniq(_) | + ty_opaque_box | ty_opaque_closure_ptr(*) | + ty_estr(vstore_uniq) | + ty_estr(vstore_box) | + ty_evec(_, vstore_uniq) | + ty_evec(_, vstore_box) => true, + + ty_trait(*) => true, + + ty_param(*) | ty_infer(*) => true, + ty_evec(mt, vstore_fixed(_)) => type_needs_drop(cx, mt.ty), ty_unboxed_vec(mt) => type_needs_drop(cx, mt.ty), ty_rec(flds) => { @@ -1598,7 +1613,6 @@ fn type_needs_drop(cx: ctxt, ty: t) -> bool { _ => true } } - _ => true }; cx.needs_drop_cache.insert(ty, result); |
