add ability to report statistics about how borrowck is being used
This commit is contained in:
parent
9b7d9a9a1b
commit
668285b9c8
4 changed files with 64 additions and 17 deletions
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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));
|
||||||
|
|
Loading…
Reference in a new issue