about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorGraydon Hoare <graydon@mozilla.com>2012-09-12 14:48:13 -0700
committerGraydon Hoare <graydon@mozilla.com>2012-09-12 14:48:18 -0700
commit719a4750ba7d4c6e35f6a2d0579ab9fb79dbf1f3 (patch)
tree92bfb74d14d82481b421c0e8b384dd0efeeda61e /src
parent4ce2ee12beea76727fe2ced87748c31725ce4e98 (diff)
Add some monomorphizing instrumentation, simplify types before emitting glue.
Diffstat (limited to 'src')
-rw-r--r--src/rustc/middle/trans/base.rs13
-rw-r--r--src/rustc/middle/trans/common.rs4
-rw-r--r--src/rustc/middle/trans/glue.rs98
-rw-r--r--src/rustc/middle/trans/inline.rs2
-rw-r--r--src/rustc/middle/trans/monomorphize.rs2
-rw-r--r--src/rustc/middle/ty.rs20
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);