diff --git a/src/rustc/driver/session.rs b/src/rustc/driver/session.rs index 1a70edc18437..e8014b7b661e 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 eb78e46f273b..f08c9e9d4c2e 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 443f135f46d9..b1f31c4fd145 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 54dc6bb7c6dd..045f175bea1a 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, 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));