about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2012-07-05 12:59:03 -0700
committerNiko Matsakis <niko@alum.mit.edu>2012-07-11 14:41:41 -0700
commit668285b9c85bebc5d1a4e8d346e99b580420be8e (patch)
treecceb6f110cec6712c67df074761e85193b3cb028
parent9b7d9a9a1bcfba81979f6f1165b5274c93b03039 (diff)
downloadrust-668285b9c85bebc5d1a4e8d346e99b580420be8e.tar.gz
rust-668285b9c85bebc5d1a4e8d346e99b580420be8e.zip
add ability to report statistics about how borrowck is being used
-rw-r--r--src/rustc/driver/session.rs9
-rw-r--r--src/rustc/middle/borrowck.rs37
-rw-r--r--src/rustc/middle/borrowck/gather_loans.rs29
-rw-r--r--src/rustc/middle/trans/base.rs6
4 files changed, 64 insertions, 17 deletions
diff --git a/src/rustc/driver/session.rs b/src/rustc/driver/session.rs
index 1a70edc1843..e8014b7b661 100644
--- a/src/rustc/driver/session.rs
+++ b/src/rustc/driver/session.rs
@@ -28,7 +28,7 @@ const ppregions: uint = 1u;
 const time_passes: uint = 2u;
 const count_llvm_insns: uint = 4u;
 const time_llvm_passes: uint = 8u;
-const stats: uint = 16u;
+const trans_stats: uint = 16u;
 const no_asm_comments: uint = 32u;
 const no_verify: uint = 64u;
 const trace: uint = 128u;
@@ -36,6 +36,7 @@ const trace: uint = 128u;
 // It should be removed
 const no_rt: uint = 256u;
 const coherence: uint = 512u;
+const borrowck_stats: uint = 1024u;
 
 fn debugging_opts_map() -> ~[(str, str, uint)] {
     ~[("ppregions", "prettyprint regions with \
@@ -49,7 +50,8 @@ fn debugging_opts_map() -> ~[(str, str, uint)] {
      ("no-verify", "skip LLVM verification", no_verify),
      ("trace", "emit trace logs", trace),
      ("no-rt", "do not link to the runtime", no_rt),
-     ("coherence", "perform coherence checking", coherence)
+     ("coherence", "perform coherence checking", coherence),
+     ("borrowck-stats", "gather borrowck statistics",  borrowck_stats)
     ]
 }
 
@@ -160,11 +162,12 @@ impl session for session {
     fn time_passes() -> bool { self.debugging_opt(time_passes) }
     fn count_llvm_insns() -> bool { self.debugging_opt(count_llvm_insns) }
     fn time_llvm_passes() -> bool { self.debugging_opt(time_llvm_passes) }
-    fn stats() -> bool { self.debugging_opt(stats) }
+    fn trans_stats() -> bool { self.debugging_opt(trans_stats) }
     fn no_asm_comments() -> bool { self.debugging_opt(no_asm_comments) }
     fn no_verify() -> bool { self.debugging_opt(no_verify) }
     fn trace() -> bool { self.debugging_opt(trace) }
     fn coherence() -> bool { self.debugging_opt(coherence) }
+    fn borrowck_stats() -> bool { self.debugging_opt(borrowck_stats) }
 }
 
 /// Some reasonable defaults
diff --git a/src/rustc/middle/borrowck.rs b/src/rustc/middle/borrowck.rs
index eb78e46f273..f08c9e9d4c2 100644
--- a/src/rustc/middle/borrowck.rs
+++ b/src/rustc/middle/borrowck.rs
@@ -175,11 +175,37 @@ fn check_crate(tcx: ty::ctxt,
                  last_use_map: last_use_map,
                  binding_map: int_hash(),
                  root_map: root_map(),
-                 mutbl_map: int_hash()};
+                 mutbl_map: int_hash(),
+                 mut loaned_paths_same: 0,
+                 mut loaned_paths_imm: 0,
+                 mut stable_paths: 0,
+                 mut req_pure_paths: 0,
+                 mut guaranteed_paths: 0};
 
     let req_maps = gather_loans::gather_loans(bccx, crate);
     check_loans::check_loans(bccx, req_maps, crate);
+
+    if tcx.sess.borrowck_stats() {
+        io::println("--- borrowck stats ---");
+        io::println(#fmt["paths requiring guarantees: %u",
+                        bccx.guaranteed_paths]);
+        io::println(#fmt["paths requiring loans     : %s",
+                         make_stat(bccx, bccx.loaned_paths_same)]);
+        io::println(#fmt["paths requiring imm loans : %s",
+                         make_stat(bccx, bccx.loaned_paths_imm)]);
+        io::println(#fmt["stable paths              : %s",
+                         make_stat(bccx, bccx.stable_paths)]);
+        io::println(#fmt["paths requiring purity    : %s",
+                         make_stat(bccx, bccx.req_pure_paths)]);
+    }
+
     ret (bccx.root_map, bccx.mutbl_map);
+
+    fn make_stat(bccx: borrowck_ctxt, stat: uint) -> str {
+        let stat_f = stat as float;
+        let total = bccx.guaranteed_paths as float;
+        #fmt["%u (%.0f%%)", stat  , stat_f * 100f / total]
+    }
 }
 
 // ----------------------------------------------------------------------
@@ -190,7 +216,14 @@ type borrowck_ctxt = @{tcx: ty::ctxt,
                        last_use_map: liveness::last_use_map,
                        binding_map: binding_map,
                        root_map: root_map,
-                       mutbl_map: mutbl_map};
+                       mutbl_map: mutbl_map,
+
+                       // Statistics:
+                       mut loaned_paths_same: uint,
+                       mut loaned_paths_imm: uint,
+                       mut stable_paths: uint,
+                       mut req_pure_paths: uint,
+                       mut guaranteed_paths: uint};
 
 // a map mapping id's of expressions of gc'd type (@T, @[], etc) where
 // the box needs to be kept live to the id of the scope for which they
diff --git a/src/rustc/middle/borrowck/gather_loans.rs b/src/rustc/middle/borrowck/gather_loans.rs
index 443f135f46d..b1f31c4fd14 100644
--- a/src/rustc/middle/borrowck/gather_loans.rs
+++ b/src/rustc/middle/borrowck/gather_loans.rs
@@ -172,6 +172,8 @@ impl methods for gather_loan_ctxt {
                        req_mutbl: ast::mutability,
                        scope_r: ty::region) {
 
+        self.bccx.guaranteed_paths += 1;
+
         #debug["guarantee_valid(cmt=%s, req_mutbl=%s, scope_r=%s)",
                self.bccx.cmt_to_repr(cmt),
                self.bccx.mut_to_str(req_mutbl),
@@ -179,20 +181,27 @@ impl methods for gather_loan_ctxt {
         let _i = indenter();
 
         alt cmt.lp {
-          // If this expression is a loanable path, we MUST take out a loan.
-          // This is somewhat non-obvious.  You might think, for example, that
-          // if we have an immutable local variable `x` whose value is being
-          // borrowed, we could rely on `x` not to change.  This is not so,
-          // however, because even immutable locals can be moved.  So we take
-          // out a loan on `x`, guaranteeing that it remains immutable for the
-          // duration of the reference: if there is an attempt to move it
-          // within that scope, the loan will be detected and an error will be
-          // reported.
+          // If this expression is a loanable path, we MUST take out a
+          // loan.  This is somewhat non-obvious.  You might think,
+          // for example, that if we have an immutable local variable
+          // `x` whose value is being borrowed, we could rely on `x`
+          // not to change.  This is not so, however, because even
+          // immutable locals can be moved.  So we take out a loan on
+          // `x`, guaranteeing that it remains immutable for the
+          // duration of the reference: if there is an attempt to move
+          // it within that scope, the loan will be detected and an
+          // error will be reported.
           some(_) {
             alt scope_r {
               ty::re_scope(scope_id) {
                 let loans = self.bccx.loan(cmt, req_mutbl);
                 self.add_loans(scope_id, loans);
+
+                if req_mutbl == m_imm && cmt.mutbl != m_imm {
+                    self.bccx.loaned_paths_imm += 1;
+                } else {
+                    self.bccx.loaned_paths_same += 1;
+                }
               }
               _ {
                 self.bccx.span_err(
@@ -225,6 +234,7 @@ impl methods for gather_loan_ctxt {
                 // we were able guarantee the validity of the ptr,
                 // perhaps by rooting or because it is immutably
                 // rooted.  good.
+                self.bccx.stable_paths += 1;
               }
               err(e) {
                 // not able to guarantee the validity of the ptr.
@@ -235,6 +245,7 @@ impl methods for gather_loan_ctxt {
                 alt opt_scope_id {
                   some(scope_id) {
                     self.req_maps.pure_map.insert(scope_id, e);
+                    self.bccx.req_pure_paths += 1;
                   }
                   none {
                     // otherwise, fine, I give up.
diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs
index 54dc6bb7c6d..045f175bea1 100644
--- a/src/rustc/middle/trans/base.rs
+++ b/src/rustc/middle/trans/base.rs
@@ -551,7 +551,7 @@ fn make_generic_glue(ccx: @crate_ctxt, t: ty::t, llfn: ValueRef,
                      helper: glue_helper, name: str)
     -> ValueRef {
     let _icx = ccx.insn_ctxt("make_generic_glue");
-    if !ccx.sess.stats() {
+    if !ccx.sess.trans_stats() {
         ret make_generic_glue_inner(ccx, t, llfn, helper);
     }
 
@@ -4550,7 +4550,7 @@ fn trans_fn(ccx: @crate_ctxt,
             ty_self: self_arg,
             param_substs: option<param_substs>,
             id: ast::node_id) {
-    let do_time = ccx.sess.stats();
+    let do_time = ccx.sess.trans_stats();
     let start = if do_time { time::get_time() }
                 else { {sec: 0i64, nsec: 0i32} };
     let _icx = ccx.insn_ctxt("trans_fn");
@@ -5591,7 +5591,7 @@ fn trans_crate(sess: session::session, crate: @ast::crate, tcx: ty::ctxt,
 
     // Translate the metadata.
     write_metadata(ccx, crate);
-    if ccx.sess.stats() {
+    if ccx.sess.trans_stats() {
         io::println("--- trans stats ---");
         io::println(#fmt("n_static_tydescs: %u",
                          ccx.stats.n_static_tydescs));