add ability to report statistics about how borrowck is being used

This commit is contained in:
Niko Matsakis 2012-07-05 12:59:03 -07:00
parent 9b7d9a9a1b
commit 668285b9c8
4 changed files with 64 additions and 17 deletions

View file

@ -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

View file

@ -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

View file

@ -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.

View file

@ -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));