Change borrow debugging so it is disabled by -O

This commit is contained in:
Niko Matsakis
2013-05-03 05:42:00 -04:00
parent 9bded76260
commit 34024353e8
7 changed files with 129 additions and 73 deletions

View File

@@ -33,8 +33,6 @@ pub struct Environment {
argv: **c_char, argv: **c_char,
/// Print GC debugging info (true if env var RUST_DEBUG_MEM is set) /// Print GC debugging info (true if env var RUST_DEBUG_MEM is set)
debug_mem: bool, debug_mem: bool,
/// Track origin of `@mut` borrows (true if env var RUST_DEBUG_BORROWS is set)
debug_borrows: bool
} }
/// Get the global environment settings /// Get the global environment settings

View File

@@ -19,7 +19,7 @@ use sys;
use unstable::exchange_alloc; use unstable::exchange_alloc;
use cast::transmute; use cast::transmute;
use task::rt::rust_get_task; use task::rt::rust_get_task;
use option::{Some, None}; use option::{Option, Some, None};
#[allow(non_camel_case_types)] #[allow(non_camel_case_types)]
pub type rust_task = c_void; pub type rust_task = c_void;
@@ -79,6 +79,19 @@ struct BorrowRecord {
line: size_t line: size_t
} }
fn try_take_task_borrow_list() -> Option<~[BorrowRecord]> {
unsafe {
let cur_task = rust_get_task();
let ptr = rustrt::rust_take_task_borrow_list(cur_task);
if ptr.is_null() {
None
} else {
let v: ~[BorrowRecord] = transmute(ptr);
Some(v)
}
}
}
fn swap_task_borrow_list(f: &fn(~[BorrowRecord]) -> ~[BorrowRecord]) { fn swap_task_borrow_list(f: &fn(~[BorrowRecord]) -> ~[BorrowRecord]) {
unsafe { unsafe {
let cur_task = rust_get_task(); let cur_task = rust_get_task();
@@ -93,23 +106,20 @@ fn swap_task_borrow_list(f: &fn(~[BorrowRecord]) -> ~[BorrowRecord]) {
pub unsafe fn clear_task_borrow_list() { pub unsafe fn clear_task_borrow_list() {
// pub because it is used by the box annihilator. // pub because it is used by the box annihilator.
let cur_task = rust_get_task(); let _ = try_take_task_borrow_list();
let ptr = rustrt::rust_take_task_borrow_list(cur_task);
if !ptr.is_null() {
let _: ~[BorrowRecord] = transmute(ptr);
}
} }
fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) { fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) {
debug_ptr("fail_borrowed: ", box); debug_ptr("fail_borrowed: ", box);
if !::rt::env::get().debug_borrows { match try_take_task_borrow_list() {
let msg = "borrowed"; None => { // not recording borrows
do str::as_buf(msg) |msg_p, _| { let msg = "borrowed";
fail_(msg_p as *c_char, file, line); do str::as_buf(msg) |msg_p, _| {
fail_(msg_p as *c_char, file, line);
}
} }
} else { Some(borrow_list) => { // recording borrows
do swap_task_borrow_list |borrow_list| {
let mut msg = ~"borrowed"; let mut msg = ~"borrowed";
let mut sep = " at "; let mut sep = " at ";
for borrow_list.each_reverse |entry| { for borrow_list.each_reverse |entry| {
@@ -126,7 +136,6 @@ fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) {
do str::as_buf(msg) |msg_p, _| { do str::as_buf(msg) |msg_p, _| {
fail_(msg_p as *c_char, file, line) fail_(msg_p as *c_char, file, line)
} }
borrow_list
} }
} }
} }
@@ -211,34 +220,6 @@ pub unsafe fn borrow_as_imm(a: *u8) {
(*a).header.ref_count |= FROZEN_BIT; (*a).header.ref_count |= FROZEN_BIT;
} }
fn add_borrow_to_task_list(a: *mut BoxRepr, file: *c_char, line: size_t) {
do swap_task_borrow_list |borrow_list| {
let mut borrow_list = borrow_list;
borrow_list.push(BorrowRecord {box: a, file: file, line: line});
borrow_list
}
}
fn remove_borrow_from_task_list(a: *mut BoxRepr, file: *c_char, line: size_t) {
do swap_task_borrow_list |borrow_list| {
let mut borrow_list = borrow_list;
let br = BorrowRecord {box: a, file: file, line: line};
match borrow_list.rposition_elem(&br) {
Some(idx) => {
borrow_list.remove(idx);
borrow_list
}
None => {
let err = fmt!("no borrow found, br=%?, borrow_list=%?",
br, borrow_list);
do str::as_buf(err) |msg_p, _| {
fail_(msg_p as *c_char, file, line)
}
}
}
}
}
#[cfg(not(stage0))] #[cfg(not(stage0))]
#[lang="borrow_as_imm"] #[lang="borrow_as_imm"]
#[inline(always)] #[inline(always)]
@@ -252,12 +233,8 @@ pub unsafe fn borrow_as_imm(a: *u8, file: *c_char, line: size_t) -> uint {
if (ref_count & MUT_BIT) != 0 { if (ref_count & MUT_BIT) != 0 {
fail_borrowed(a, file, line); fail_borrowed(a, file, line);
} else {
(*a).header.ref_count |= FROZEN_BIT;
if ::rt::env::get().debug_borrows {
add_borrow_to_task_list(a, file, line);
}
} }
ref_count ref_count
} }
@@ -273,15 +250,53 @@ pub unsafe fn borrow_as_mut(a: *u8, file: *c_char, line: size_t) -> uint {
let ref_count = (*a).header.ref_count; let ref_count = (*a).header.ref_count;
if (ref_count & (MUT_BIT|FROZEN_BIT)) != 0 { if (ref_count & (MUT_BIT|FROZEN_BIT)) != 0 {
fail_borrowed(a, file, line); fail_borrowed(a, file, line);
} else {
(*a).header.ref_count |= (MUT_BIT|FROZEN_BIT);
if ::rt::env::get().debug_borrows {
add_borrow_to_task_list(a, file, line);
}
} }
ref_count ref_count
} }
#[cfg(not(stage0))]
#[lang="record_borrow"]
pub unsafe fn record_borrow(a: *u8, old_ref_count: uint,
file: *c_char, line: size_t) {
if (old_ref_count & ALL_BITS) == 0 {
// was not borrowed before
let a: *mut BoxRepr = transmute(a);
do swap_task_borrow_list |borrow_list| {
let mut borrow_list = borrow_list;
borrow_list.push(BorrowRecord {box: a, file: file, line: line});
borrow_list
}
}
}
#[cfg(not(stage0))]
#[lang="unrecord_borrow"]
pub unsafe fn unrecord_borrow(a: *u8, old_ref_count: uint,
file: *c_char, line: size_t) {
if (old_ref_count & ALL_BITS) == 0 {
// was not borrowed before
let a: *mut BoxRepr = transmute(a);
do swap_task_borrow_list |borrow_list| {
let mut borrow_list = borrow_list;
let br = BorrowRecord {box: a, file: file, line: line};
match borrow_list.rposition_elem(&br) {
Some(idx) => {
borrow_list.remove(idx);
borrow_list
}
None => {
let err = fmt!("no borrow found, br=%?, borrow_list=%?",
br, borrow_list);
do str::as_buf(err) |msg_p, _| {
fail_(msg_p as *c_char, file, line)
}
}
}
}
}
}
#[cfg(stage0)] #[cfg(stage0)]
#[lang="return_to_mut"] #[lang="return_to_mut"]
#[inline(always)] #[inline(always)]
@@ -312,10 +327,6 @@ pub unsafe fn return_to_mut(a: *u8, old_ref_count: uint,
debug_ptr(" (old) : ", old_ref_count as *()); debug_ptr(" (old) : ", old_ref_count as *());
debug_ptr(" (new) : ", ref_count as *()); debug_ptr(" (new) : ", ref_count as *());
debug_ptr(" (comb): ", combined as *()); debug_ptr(" (comb): ", combined as *());
if ::rt::env::get().debug_borrows {
remove_borrow_from_task_list(a, file, line);
}
} }
} }

View File

@@ -70,18 +70,20 @@ pub enum LangItem {
ReturnToMutFnLangItem, // 32 ReturnToMutFnLangItem, // 32
CheckNotBorrowedFnLangItem, // 33 CheckNotBorrowedFnLangItem, // 33
StrDupUniqFnLangItem, // 34 StrDupUniqFnLangItem, // 34
RecordBorrowFnLangItem, // 35
UnrecordBorrowFnLangItem, // 36
StartFnLangItem, // 35 StartFnLangItem, // 37
} }
pub struct LanguageItems { pub struct LanguageItems {
items: [Option<def_id>, ..36] items: [Option<def_id>, ..38]
} }
pub impl LanguageItems { pub impl LanguageItems {
pub fn new() -> LanguageItems { pub fn new() -> LanguageItems {
LanguageItems { LanguageItems {
items: [ None, ..36 ] items: [ None, ..38 ]
} }
} }
@@ -133,8 +135,10 @@ pub impl LanguageItems {
32 => "return_to_mut", 32 => "return_to_mut",
33 => "check_not_borrowed", 33 => "check_not_borrowed",
34 => "strdup_uniq", 34 => "strdup_uniq",
35 => "record_borrow",
36 => "unrecord_borrow",
35 => "start", 37 => "start",
_ => "???" _ => "???"
} }
@@ -251,6 +255,12 @@ pub impl LanguageItems {
pub fn strdup_uniq_fn(&const self) -> def_id { pub fn strdup_uniq_fn(&const self) -> def_id {
self.items[StrDupUniqFnLangItem as uint].get() self.items[StrDupUniqFnLangItem as uint].get()
} }
pub fn record_borrow_fn(&const self) -> def_id {
self.items[RecordBorrowFnLangItem as uint].get()
}
pub fn unrecord_borrow_fn(&const self) -> def_id {
self.items[UnrecordBorrowFnLangItem as uint].get()
}
pub fn start_fn(&const self) -> def_id { pub fn start_fn(&const self) -> def_id {
self.items[StartFnLangItem as uint].get() self.items[StartFnLangItem as uint].get()
} }
@@ -302,6 +312,8 @@ fn LanguageItemCollector(crate: @crate,
item_refs.insert(@~"check_not_borrowed", item_refs.insert(@~"check_not_borrowed",
CheckNotBorrowedFnLangItem as uint); CheckNotBorrowedFnLangItem as uint);
item_refs.insert(@~"strdup_uniq", StrDupUniqFnLangItem as uint); item_refs.insert(@~"strdup_uniq", StrDupUniqFnLangItem as uint);
item_refs.insert(@~"record_borrow", RecordBorrowFnLangItem as uint);
item_refs.insert(@~"unrecord_borrow", UnrecordBorrowFnLangItem as uint);
item_refs.insert(@~"start", StartFnLangItem as uint); item_refs.insert(@~"start", StartFnLangItem as uint);
LanguageItemCollector { LanguageItemCollector {

View File

@@ -489,15 +489,37 @@ pub fn add_clean_return_to_mut(bcx: block,
clean_temp( clean_temp(
frozen_val_ref, frozen_val_ref,
|bcx| { |bcx| {
let mut bcx = bcx;
let box_ptr =
build::Load(bcx,
build::PointerCast(bcx,
frozen_val_ref,
T_ptr(T_ptr(T_i8()))));
let bits_val =
build::Load(bcx,
bits_val_ref);
if bcx.tcx().sess.opts.optimize == session::No {
bcx = callee::trans_lang_call(
bcx,
bcx.tcx().lang_items.unrecord_borrow_fn(),
~[
box_ptr,
bits_val,
filename_val,
line_val
],
expr::Ignore);
}
callee::trans_lang_call( callee::trans_lang_call(
bcx, bcx,
bcx.tcx().lang_items.return_to_mut_fn(), bcx.tcx().lang_items.return_to_mut_fn(),
~[ ~[
build::Load(bcx, box_ptr,
build::PointerCast(bcx, bits_val,
frozen_val_ref,
T_ptr(T_ptr(T_i8())))),
build::Load(bcx, bits_val_ref),
filename_val, filename_val,
line_val line_val
], ],

View File

@@ -101,6 +101,7 @@ use middle::trans::type_of;
use middle::ty; use middle::ty;
use util::common::indenter; use util::common::indenter;
use util::ppaux::ty_to_str; use util::ppaux::ty_to_str;
use driver::session;
use core::container::Set; // XXX: this should not be necessary use core::container::Set; // XXX: this should not be necessary
use core::to_bytes; use core::to_bytes;
@@ -564,19 +565,34 @@ pub impl Datum {
DynaMut => bcx.tcx().lang_items.borrow_as_mut_fn(), DynaMut => bcx.tcx().lang_items.borrow_as_mut_fn(),
}; };
let box_ptr = Load(bcx,
PointerCast(bcx,
scratch.val,
T_ptr(T_ptr(T_i8()))));
bcx = callee::trans_lang_call( bcx = callee::trans_lang_call(
bcx, bcx,
freeze_did, freeze_did,
~[ ~[
Load(bcx, box_ptr,
PointerCast(bcx,
scratch.val,
T_ptr(T_ptr(T_i8())))),
filename, filename,
line line
], ],
expr::SaveIn(scratch_bits.val)); expr::SaveIn(scratch_bits.val));
if bcx.tcx().sess.opts.optimize == session::No {
bcx = callee::trans_lang_call(
bcx,
bcx.tcx().lang_items.record_borrow_fn(),
~[
box_ptr,
Load(bcx, scratch_bits.val),
filename,
line
],
expr::Ignore);
}
add_clean_return_to_mut( add_clean_return_to_mut(
cleanup_bcx, scratch.val, scratch_bits.val, cleanup_bcx, scratch.val, scratch_bits.val,
filename, line); filename, line);

View File

@@ -24,7 +24,6 @@
#define RUST_SEED "RUST_SEED" #define RUST_SEED "RUST_SEED"
#define RUST_POISON_ON_FREE "RUST_POISON_ON_FREE" #define RUST_POISON_ON_FREE "RUST_POISON_ON_FREE"
#define RUST_DEBUG_MEM "RUST_DEBUG_MEM" #define RUST_DEBUG_MEM "RUST_DEBUG_MEM"
#define RUST_DEBUG_BORROWS "RUST_DEBUG_BORROWS"
#if defined(__WIN32__) #if defined(__WIN32__)
static int static int
@@ -131,7 +130,6 @@ load_env(int argc, char **argv) {
env->argc = argc; env->argc = argc;
env->argv = argv; env->argv = argv;
env->debug_mem = getenv(RUST_DEBUG_MEM) != NULL; env->debug_mem = getenv(RUST_DEBUG_MEM) != NULL;
env->debug_borrows = getenv(RUST_DEBUG_BORROWS) != NULL;
return env; return env;
} }

View File

@@ -28,7 +28,6 @@ struct rust_env {
int argc; int argc;
char **argv; char **argv;
rust_bool debug_mem; rust_bool debug_mem;
rust_bool debug_borrows;
}; };
rust_env* load_env(int argc, char **argv); rust_env* load_env(int argc, char **argv);