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 time_passes: uint = 2u;
const count_llvm_insns: uint = 4u; const count_llvm_insns: uint = 4u;
const time_llvm_passes: uint = 8u; const time_llvm_passes: uint = 8u;
const stats: uint = 16u; const trans_stats: uint = 16u;
const no_asm_comments: uint = 32u; const no_asm_comments: uint = 32u;
const no_verify: uint = 64u; const no_verify: uint = 64u;
const trace: uint = 128u; const trace: uint = 128u;
@ -36,6 +36,7 @@ const trace: uint = 128u;
// It should be removed // It should be removed
const no_rt: uint = 256u; const no_rt: uint = 256u;
const coherence: uint = 512u; const coherence: uint = 512u;
const borrowck_stats: uint = 1024u;
fn debugging_opts_map() -> ~[(str, str, uint)] { fn debugging_opts_map() -> ~[(str, str, uint)] {
~[("ppregions", "prettyprint regions with \ ~[("ppregions", "prettyprint regions with \
@ -49,7 +50,8 @@ fn debugging_opts_map() -> ~[(str, str, uint)] {
("no-verify", "skip LLVM verification", no_verify), ("no-verify", "skip LLVM verification", no_verify),
("trace", "emit trace logs", trace), ("trace", "emit trace logs", trace),
("no-rt", "do not link to the runtime", no_rt), ("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 time_passes() -> bool { self.debugging_opt(time_passes) }
fn count_llvm_insns() -> bool { self.debugging_opt(count_llvm_insns) } fn count_llvm_insns() -> bool { self.debugging_opt(count_llvm_insns) }
fn time_llvm_passes() -> bool { self.debugging_opt(time_llvm_passes) } 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_asm_comments() -> bool { self.debugging_opt(no_asm_comments) }
fn no_verify() -> bool { self.debugging_opt(no_verify) } fn no_verify() -> bool { self.debugging_opt(no_verify) }
fn trace() -> bool { self.debugging_opt(trace) } fn trace() -> bool { self.debugging_opt(trace) }
fn coherence() -> bool { self.debugging_opt(coherence) } fn coherence() -> bool { self.debugging_opt(coherence) }
fn borrowck_stats() -> bool { self.debugging_opt(borrowck_stats) }
} }
/// Some reasonable defaults /// Some reasonable defaults

View file

@ -175,11 +175,37 @@ fn check_crate(tcx: ty::ctxt,
last_use_map: last_use_map, last_use_map: last_use_map,
binding_map: int_hash(), binding_map: int_hash(),
root_map: root_map(), 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); let req_maps = gather_loans::gather_loans(bccx, crate);
check_loans::check_loans(bccx, req_maps, 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); 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, last_use_map: liveness::last_use_map,
binding_map: binding_map, binding_map: binding_map,
root_map: root_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 // 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 // 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, req_mutbl: ast::mutability,
scope_r: ty::region) { scope_r: ty::region) {
self.bccx.guaranteed_paths += 1;
#debug["guarantee_valid(cmt=%s, req_mutbl=%s, scope_r=%s)", #debug["guarantee_valid(cmt=%s, req_mutbl=%s, scope_r=%s)",
self.bccx.cmt_to_repr(cmt), self.bccx.cmt_to_repr(cmt),
self.bccx.mut_to_str(req_mutbl), self.bccx.mut_to_str(req_mutbl),
@ -179,20 +181,27 @@ impl methods for gather_loan_ctxt {
let _i = indenter(); let _i = indenter();
alt cmt.lp { alt cmt.lp {
// If this expression is a loanable path, we MUST take out a loan. // If this expression is a loanable path, we MUST take out a
// This is somewhat non-obvious. You might think, for example, that // loan. This is somewhat non-obvious. You might think,
// if we have an immutable local variable `x` whose value is being // for example, that if we have an immutable local variable
// borrowed, we could rely on `x` not to change. This is not so, // `x` whose value is being borrowed, we could rely on `x`
// however, because even immutable locals can be moved. So we take // not to change. This is not so, however, because even
// out a loan on `x`, guaranteeing that it remains immutable for the // immutable locals can be moved. So we take out a loan on
// duration of the reference: if there is an attempt to move it // `x`, guaranteeing that it remains immutable for the
// within that scope, the loan will be detected and an error will be // duration of the reference: if there is an attempt to move
// reported. // it within that scope, the loan will be detected and an
// error will be reported.
some(_) { some(_) {
alt scope_r { alt scope_r {
ty::re_scope(scope_id) { ty::re_scope(scope_id) {
let loans = self.bccx.loan(cmt, req_mutbl); let loans = self.bccx.loan(cmt, req_mutbl);
self.add_loans(scope_id, loans); 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( self.bccx.span_err(
@ -225,6 +234,7 @@ impl methods for gather_loan_ctxt {
// we were able guarantee the validity of the ptr, // we were able guarantee the validity of the ptr,
// perhaps by rooting or because it is immutably // perhaps by rooting or because it is immutably
// rooted. good. // rooted. good.
self.bccx.stable_paths += 1;
} }
err(e) { err(e) {
// not able to guarantee the validity of the ptr. // not able to guarantee the validity of the ptr.
@ -235,6 +245,7 @@ impl methods for gather_loan_ctxt {
alt opt_scope_id { alt opt_scope_id {
some(scope_id) { some(scope_id) {
self.req_maps.pure_map.insert(scope_id, e); self.req_maps.pure_map.insert(scope_id, e);
self.bccx.req_pure_paths += 1;
} }
none { none {
// otherwise, fine, I give up. // 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) helper: glue_helper, name: str)
-> ValueRef { -> ValueRef {
let _icx = ccx.insn_ctxt("make_generic_glue"); 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); ret make_generic_glue_inner(ccx, t, llfn, helper);
} }
@ -4550,7 +4550,7 @@ fn trans_fn(ccx: @crate_ctxt,
ty_self: self_arg, ty_self: self_arg,
param_substs: option<param_substs>, param_substs: option<param_substs>,
id: ast::node_id) { 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() } let start = if do_time { time::get_time() }
else { {sec: 0i64, nsec: 0i32} }; else { {sec: 0i64, nsec: 0i32} };
let _icx = ccx.insn_ctxt("trans_fn"); 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. // Translate the metadata.
write_metadata(ccx, crate); write_metadata(ccx, crate);
if ccx.sess.stats() { if ccx.sess.trans_stats() {
io::println("--- trans stats ---"); io::println("--- trans stats ---");
io::println(#fmt("n_static_tydescs: %u", io::println(#fmt("n_static_tydescs: %u",
ccx.stats.n_static_tydescs)); ccx.stats.n_static_tydescs));