From 4af2d90af59bb5e28e5d114d8a6004d68fad3bd5 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 1 May 2013 10:29:47 -0400 Subject: add an option to debug borrows (RUST_DEBUG_BORROW) so you can find out where the offending borrow occurred. This ... still needs some work. --- src/rt/rust_env.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/rt/rust_env.cpp') diff --git a/src/rt/rust_env.cpp b/src/rt/rust_env.cpp index 041b4efac52..e6fe35609ec 100644 --- a/src/rt/rust_env.cpp +++ b/src/rt/rust_env.cpp @@ -24,6 +24,7 @@ #define RUST_SEED "RUST_SEED" #define RUST_POISON_ON_FREE "RUST_POISON_ON_FREE" #define RUST_DEBUG_MEM "RUST_DEBUG_MEM" +#define RUST_DEBUG_BORROWS "RUST_DEBUG_BORROWS" #if defined(__WIN32__) static int @@ -130,6 +131,7 @@ load_env(int argc, char **argv) { env->argc = argc; env->argv = argv; env->debug_mem = getenv(RUST_DEBUG_MEM) != NULL; + env->debug_borrows = getenv(RUST_DEBUG_BORROWS) != NULL; return env; } -- cgit 1.4.1-3-g733a5 From 34024353e86e22e459a1981f563e3d4f43906432 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 3 May 2013 05:42:00 -0400 Subject: Change borrow debugging so it is disabled by -O --- src/libcore/rt/env.rs | 2 - src/libcore/unstable/lang.rs | 121 ++++++++++++++++++++---------------- src/librustc/middle/lang_items.rs | 20 ++++-- src/librustc/middle/trans/common.rs | 32 ++++++++-- src/librustc/middle/trans/datum.rs | 24 +++++-- src/rt/rust_env.cpp | 2 - src/rt/rust_env.h | 1 - 7 files changed, 129 insertions(+), 73 deletions(-) (limited to 'src/rt/rust_env.cpp') diff --git a/src/libcore/rt/env.rs b/src/libcore/rt/env.rs index 1f52cf77868..e479375401a 100644 --- a/src/libcore/rt/env.rs +++ b/src/libcore/rt/env.rs @@ -33,8 +33,6 @@ pub struct Environment { argv: **c_char, /// Print GC debugging info (true if env var RUST_DEBUG_MEM is set) 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 diff --git a/src/libcore/unstable/lang.rs b/src/libcore/unstable/lang.rs index a3e44b5feea..27fc3287bdb 100644 --- a/src/libcore/unstable/lang.rs +++ b/src/libcore/unstable/lang.rs @@ -19,7 +19,7 @@ use sys; use unstable::exchange_alloc; use cast::transmute; use task::rt::rust_get_task; -use option::{Some, None}; +use option::{Option, Some, None}; #[allow(non_camel_case_types)] pub type rust_task = c_void; @@ -79,6 +79,19 @@ struct BorrowRecord { 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]) { unsafe { 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 because it is used by the box annihilator. - let cur_task = rust_get_task(); - let ptr = rustrt::rust_take_task_borrow_list(cur_task); - if !ptr.is_null() { - let _: ~[BorrowRecord] = transmute(ptr); - } + let _ = try_take_task_borrow_list(); } fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) { debug_ptr("fail_borrowed: ", box); - if !::rt::env::get().debug_borrows { - let msg = "borrowed"; - do str::as_buf(msg) |msg_p, _| { - fail_(msg_p as *c_char, file, line); + match try_take_task_borrow_list() { + None => { // not recording borrows + let msg = "borrowed"; + do str::as_buf(msg) |msg_p, _| { + fail_(msg_p as *c_char, file, line); + } } - } else { - do swap_task_borrow_list |borrow_list| { + Some(borrow_list) => { // recording borrows let mut msg = ~"borrowed"; let mut sep = " at "; 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, _| { 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; } -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))] #[lang="borrow_as_imm"] #[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 { 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 } @@ -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; if (ref_count & (MUT_BIT|FROZEN_BIT)) != 0 { 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 } + +#[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)] #[lang="return_to_mut"] #[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(" (new) : ", ref_count as *()); debug_ptr(" (comb): ", combined as *()); - - if ::rt::env::get().debug_borrows { - remove_borrow_from_task_list(a, file, line); - } } } diff --git a/src/librustc/middle/lang_items.rs b/src/librustc/middle/lang_items.rs index 314b58d13e1..448f33796bc 100644 --- a/src/librustc/middle/lang_items.rs +++ b/src/librustc/middle/lang_items.rs @@ -70,18 +70,20 @@ pub enum LangItem { ReturnToMutFnLangItem, // 32 CheckNotBorrowedFnLangItem, // 33 StrDupUniqFnLangItem, // 34 + RecordBorrowFnLangItem, // 35 + UnrecordBorrowFnLangItem, // 36 - StartFnLangItem, // 35 + StartFnLangItem, // 37 } pub struct LanguageItems { - items: [Option, ..36] + items: [Option, ..38] } pub impl LanguageItems { pub fn new() -> LanguageItems { LanguageItems { - items: [ None, ..36 ] + items: [ None, ..38 ] } } @@ -133,8 +135,10 @@ pub impl LanguageItems { 32 => "return_to_mut", 33 => "check_not_borrowed", 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 { 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 { self.items[StartFnLangItem as uint].get() } @@ -302,6 +312,8 @@ fn LanguageItemCollector(crate: @crate, item_refs.insert(@~"check_not_borrowed", CheckNotBorrowedFnLangItem 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); LanguageItemCollector { diff --git a/src/librustc/middle/trans/common.rs b/src/librustc/middle/trans/common.rs index 705a89381df..2a13cf73f8b 100644 --- a/src/librustc/middle/trans/common.rs +++ b/src/librustc/middle/trans/common.rs @@ -489,15 +489,37 @@ pub fn add_clean_return_to_mut(bcx: block, clean_temp( frozen_val_ref, |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( bcx, bcx.tcx().lang_items.return_to_mut_fn(), ~[ - build::Load(bcx, - build::PointerCast(bcx, - frozen_val_ref, - T_ptr(T_ptr(T_i8())))), - build::Load(bcx, bits_val_ref), + box_ptr, + bits_val, filename_val, line_val ], diff --git a/src/librustc/middle/trans/datum.rs b/src/librustc/middle/trans/datum.rs index d6df6c87dec..af7165c53a7 100644 --- a/src/librustc/middle/trans/datum.rs +++ b/src/librustc/middle/trans/datum.rs @@ -101,6 +101,7 @@ use middle::trans::type_of; use middle::ty; use util::common::indenter; use util::ppaux::ty_to_str; +use driver::session; use core::container::Set; // XXX: this should not be necessary use core::to_bytes; @@ -564,19 +565,34 @@ pub impl Datum { 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, freeze_did, ~[ - Load(bcx, - PointerCast(bcx, - scratch.val, - T_ptr(T_ptr(T_i8())))), + box_ptr, filename, line ], 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( cleanup_bcx, scratch.val, scratch_bits.val, filename, line); diff --git a/src/rt/rust_env.cpp b/src/rt/rust_env.cpp index e6fe35609ec..041b4efac52 100644 --- a/src/rt/rust_env.cpp +++ b/src/rt/rust_env.cpp @@ -24,7 +24,6 @@ #define RUST_SEED "RUST_SEED" #define RUST_POISON_ON_FREE "RUST_POISON_ON_FREE" #define RUST_DEBUG_MEM "RUST_DEBUG_MEM" -#define RUST_DEBUG_BORROWS "RUST_DEBUG_BORROWS" #if defined(__WIN32__) static int @@ -131,7 +130,6 @@ load_env(int argc, char **argv) { env->argc = argc; env->argv = argv; env->debug_mem = getenv(RUST_DEBUG_MEM) != NULL; - env->debug_borrows = getenv(RUST_DEBUG_BORROWS) != NULL; return env; } diff --git a/src/rt/rust_env.h b/src/rt/rust_env.h index 322198bb031..df27f7674f2 100644 --- a/src/rt/rust_env.h +++ b/src/rt/rust_env.h @@ -28,7 +28,6 @@ struct rust_env { int argc; char **argv; rust_bool debug_mem; - rust_bool debug_borrows; }; rust_env* load_env(int argc, char **argv); -- cgit 1.4.1-3-g733a5 From bf2d3c71e37d3b7aabe57a3d9ea3fada449715c1 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Sat, 4 May 2013 14:25:15 -0400 Subject: improve DEBUG_BORROW printouts --- src/libcore/cleanup.rs | 17 +++--- src/libcore/rt/env.rs | 2 + src/libcore/unstable/lang.rs | 139 +++++++++++++++++++++++++++++-------------- src/rt/rust_env.cpp | 2 + src/rt/rust_env.h | 1 + 5 files changed, 109 insertions(+), 52 deletions(-) (limited to 'src/rt/rust_env.cpp') diff --git a/src/libcore/cleanup.rs b/src/libcore/cleanup.rs index 5e2f4af184d..3f7366c6c45 100644 --- a/src/libcore/cleanup.rs +++ b/src/libcore/cleanup.rs @@ -167,7 +167,8 @@ fn debug_mem() -> bool { #[cfg(notest)] #[lang="annihilate"] pub unsafe fn annihilate() { - use unstable::lang::{local_free, debug_ptr}; + use unstable::lang::{local_free}; + use unstable::lang; use io::WriterUtil; use io; use libc; @@ -191,10 +192,10 @@ pub unsafe fn annihilate() { for each_live_alloc(true) |box, uniq| { stats.n_total_boxes += 1; if uniq { - debug_ptr("Managed-uniq: ", &*box); + lang::debug_mem("Managed-uniq: ", &*box); stats.n_unique_boxes += 1; } else { - debug_ptr("Immortalizing: ", &*box); + lang::debug_mem("Immortalizing: ", &*box); (*box).header.ref_count = managed::raw::RC_IMMORTAL; } } @@ -206,13 +207,13 @@ pub unsafe fn annihilate() { // callback, as the original value may have been freed. for each_live_alloc(false) |box, uniq| { if !uniq { - debug_ptr("Invoking tydesc/glue on: ", &*box); + lang::debug_mem("Invoking tydesc/glue on: ", &*box); let tydesc: *TypeDesc = transmute(copy (*box).header.type_desc); let drop_glue: DropGlue = transmute(((*tydesc).drop_glue, 0)); - debug_ptr("Box data: ", &(*box).data); - debug_ptr("Type descriptor: ", tydesc); + lang::debug_mem("Box data: ", &(*box).data); + lang::debug_mem("Type descriptor: ", tydesc); drop_glue(to_unsafe_ptr(&tydesc), transmute(&(*box).data)); - debug_ptr("Dropped ", &*box); + lang::debug_mem("Dropped ", &*box); } } @@ -224,7 +225,7 @@ pub unsafe fn annihilate() { // not be valid after. for each_live_alloc(true) |box, uniq| { if !uniq { - debug_ptr("About to free: ", &*box); + lang::debug_mem("About to free: ", &*box); stats.n_bytes_freed += (*((*box).header.type_desc)).size + sys::size_of::(); diff --git a/src/libcore/rt/env.rs b/src/libcore/rt/env.rs index e479375401a..1d7ff173149 100644 --- a/src/libcore/rt/env.rs +++ b/src/libcore/rt/env.rs @@ -33,6 +33,8 @@ pub struct Environment { argv: **c_char, /// Print GC debugging info (true if env var RUST_DEBUG_MEM is set) debug_mem: bool, + /// Print GC debugging info (true if env var RUST_DEBUG_BORROW is set) + debug_borrow: bool, } /// Get the global environment settings diff --git a/src/libcore/unstable/lang.rs b/src/libcore/unstable/lang.rs index 01ab2345918..5a65a5c24bb 100644 --- a/src/libcore/unstable/lang.rs +++ b/src/libcore/unstable/lang.rs @@ -20,6 +20,7 @@ use unstable::exchange_alloc; use cast::transmute; use task::rt::rust_get_task; use option::{Option, Some, None}; +use io; #[allow(non_camel_case_types)] pub type rust_task = c_void; @@ -109,8 +110,8 @@ pub unsafe fn clear_task_borrow_list() { let _ = try_take_task_borrow_list(); } -fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) { - debug_ptr("fail_borrowed: ", box); +unsafe fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) { + debug_borrow("fail_borrowed: ", box, 0, 0, file, line); match try_take_task_borrow_list() { None => { // not recording borrows @@ -145,42 +146,95 @@ fn fail_borrowed(box: *mut BoxRepr, file: *c_char, line: size_t) { #[inline(always)] pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char { let result = transmute(exchange_alloc::malloc(transmute(td), transmute(size))); - debug_ptr("exchange_malloc: ", result); + debug_mem("exchange_malloc: ", result); return result; } /// Because this code is so perf. sensitive, use a static constant so that /// debug printouts are compiled out most of the time. -static ENABLE_DEBUG_PTR: bool = true; +static ENABLE_DEBUG: bool = true; #[inline] -pub fn debug_ptr(tag: &'static str, p: *const T) { +pub fn debug_mem(tag: &'static str, p: *const T) { //! A useful debugging function that prints a pointer + tag + newline //! without allocating memory. - if ENABLE_DEBUG_PTR && ::rt::env::get().debug_mem { - debug_ptr_slow(tag, p); + if ENABLE_DEBUG && ::rt::env::get().debug_mem { + debug_mem_slow(tag, p); } - fn debug_ptr_slow(tag: &'static str, p: *const T) { - use io; + fn debug_mem_slow(tag: &'static str, p: *const T) { let dbg = STDERR_FILENO as io::fd_t; - let letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', - '9', 'a', 'b', 'c', 'd', 'e', 'f']; dbg.write_str(tag); + dbg.write_hex(p as uint); + dbg.write_str("\n"); + } +} + +#[inline] +unsafe fn debug_borrow(tag: &'static str, + p: *const T, + old_bits: uint, + new_bits: uint, + filename: *c_char, + line: size_t) { + //! A useful debugging function that prints a pointer + tag + newline + //! without allocating memory. + + if ENABLE_DEBUG && ::rt::env::get().debug_borrow { + debug_borrow_slow(tag, p, old_bits, new_bits, filename, line); + } + + unsafe fn debug_borrow_slow(tag: &'static str, + p: *const T, + old_bits: uint, + new_bits: uint, + filename: *c_char, + line: size_t) { + let dbg = STDERR_FILENO as io::fd_t; + dbg.write_str(tag); + dbg.write_hex(p as uint); + dbg.write_str(" "); + dbg.write_hex(old_bits); + dbg.write_str(" "); + dbg.write_hex(new_bits); + dbg.write_str(" "); + dbg.write_cstr(filename); + dbg.write_str(":"); + dbg.write_hex(line as uint); + dbg.write_str("\n"); + } +} + +trait DebugPrints { + fn write_hex(&self, val: uint); + unsafe fn write_cstr(&self, str: *c_char); +} +impl DebugPrints for io::fd_t { + fn write_hex(&self, mut i: uint) { + let letters = ['0', '1', '2', '3', '4', '5', '6', '7', '8', + '9', 'a', 'b', 'c', 'd', 'e', 'f']; static uint_nibbles: uint = ::uint::bytes << 1; let mut buffer = [0_u8, ..uint_nibbles+1]; - let mut i = p as uint; let mut c = uint_nibbles; while c > 0 { c -= 1; buffer[c] = letters[i & 0xF] as u8; i >>= 4; } - dbg.write(buffer.slice(0, uint_nibbles)); + self.write(buffer.slice(0, uint_nibbles)); + } - dbg.write_str("\n"); + unsafe fn write_cstr(&self, p: *c_char) { + use libc::strlen; + use vec; + + let len = strlen(p); + let p: *u8 = transmute(p); + do vec::raw::buf_as_slice(p, len as uint) |s| { + self.write(s); + } } } @@ -190,7 +244,7 @@ pub fn debug_ptr(tag: &'static str, p: *const T) { #[lang="exchange_free"] #[inline(always)] pub unsafe fn exchange_free(ptr: *c_char) { - debug_ptr("exchange_free: ", ptr); + debug_mem("exchange_free: ", ptr); exchange_alloc::free(transmute(ptr)) } @@ -198,7 +252,7 @@ pub unsafe fn exchange_free(ptr: *c_char) { #[inline(always)] pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { let result = rustrt::rust_upcall_malloc_noswitch(td, size); - debug_ptr("local_malloc: ", result); + debug_mem("local_malloc: ", result); return result; } @@ -208,7 +262,7 @@ pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char { #[lang="free"] #[inline(always)] pub unsafe fn local_free(ptr: *c_char) { - debug_ptr("local_free: ", ptr); + debug_mem("local_free: ", ptr); rustrt::rust_upcall_free_noswitch(ptr); } @@ -225,19 +279,18 @@ pub unsafe fn borrow_as_imm(a: *u8) { #[inline(always)] pub unsafe fn borrow_as_imm(a: *u8, file: *c_char, line: size_t) -> uint { let a: *mut BoxRepr = transmute(a); - let ref_count = (*a).header.ref_count; + let old_ref_count = (*a).header.ref_count; + let new_ref_count = old_ref_count | FROZEN_BIT; - debug_ptr("borrow_as_imm (ptr) :", a); - debug_ptr(" (ref) :", ref_count as *()); - debug_ptr(" (line): ", line as *()); + debug_borrow("borrow_as_imm:", a, old_ref_count, new_ref_count, file, line); - if (ref_count & MUT_BIT) != 0 { + if (old_ref_count & MUT_BIT) != 0 { fail_borrowed(a, file, line); } - (*a).header.ref_count = ref_count | FROZEN_BIT; + (*a).header.ref_count = new_ref_count; - ref_count + old_ref_count } #[cfg(not(stage0))] @@ -245,18 +298,18 @@ pub unsafe fn borrow_as_imm(a: *u8, file: *c_char, line: size_t) -> uint { #[inline(always)] pub unsafe fn borrow_as_mut(a: *u8, file: *c_char, line: size_t) -> uint { let a: *mut BoxRepr = transmute(a); + let old_ref_count = (*a).header.ref_count; + let new_ref_count = old_ref_count | MUT_BIT | FROZEN_BIT; - debug_ptr("borrow_as_mut (ptr): ", a); - debug_ptr(" (line): ", line as *()); + debug_borrow("borrow_as_mut:", a, old_ref_count, new_ref_count, file, line); - let ref_count = (*a).header.ref_count; - if (ref_count & (MUT_BIT|FROZEN_BIT)) != 0 { + if (old_ref_count & (MUT_BIT|FROZEN_BIT)) != 0 { fail_borrowed(a, file, line); } - (*a).header.ref_count = ref_count | MUT_BIT | FROZEN_BIT; + (*a).header.ref_count = new_ref_count; - ref_count + old_ref_count } @@ -267,6 +320,7 @@ pub unsafe fn record_borrow(a: *u8, old_ref_count: uint, if (old_ref_count & ALL_BITS) == 0 { // was not borrowed before let a: *mut BoxRepr = transmute(a); + debug_borrow("record_borrow:", a, old_ref_count, 0, file, line); do swap_task_borrow_list |borrow_list| { let mut borrow_list = borrow_list; borrow_list.push(BorrowRecord {box: a, file: file, line: line}); @@ -282,6 +336,7 @@ pub unsafe fn unrecord_borrow(a: *u8, old_ref_count: uint, if (old_ref_count & ALL_BITS) == 0 { // was not borrowed before let a: *mut BoxRepr = transmute(a); + debug_borrow("unrecord_borrow:", a, old_ref_count, 0, file, line); do swap_task_borrow_list |borrow_list| { let mut borrow_list = borrow_list; let br = BorrowRecord {box: a, file: file, line: line}; @@ -317,21 +372,20 @@ pub unsafe fn return_to_mut(a: *u8) { #[cfg(not(stage0))] #[lang="return_to_mut"] #[inline(always)] -pub unsafe fn return_to_mut(a: *u8, old_ref_count: uint, +pub unsafe fn return_to_mut(a: *u8, orig_ref_count: uint, file: *c_char, line: size_t) { // Sometimes the box is null, if it is conditionally frozen. // See e.g. #4904. if !a.is_null() { let a: *mut BoxRepr = transmute(a); - let ref_count = (*a).header.ref_count; - let combined = (ref_count & !ALL_BITS) | (old_ref_count & ALL_BITS); - (*a).header.ref_count = combined; - - debug_ptr("return_to_mut (ptr) : ", a); - debug_ptr(" (line): ", line as *()); - debug_ptr(" (old) : ", old_ref_count as *()); - debug_ptr(" (new) : ", ref_count as *()); - debug_ptr(" (comb): ", combined as *()); + let old_ref_count = (*a).header.ref_count; + let new_ref_count = + (old_ref_count & !ALL_BITS) | (orig_ref_count & ALL_BITS); + + debug_borrow("return_to_mut:", + a, old_ref_count, new_ref_count, file, line); + + (*a).header.ref_count = new_ref_count; } } @@ -355,10 +409,7 @@ pub unsafe fn check_not_borrowed(a: *u8, line: size_t) { let a: *mut BoxRepr = transmute(a); let ref_count = (*a).header.ref_count; - debug_ptr("check_not_borrowed (ptr) : ", a); - debug_ptr(" (line): ", line as *()); - debug_ptr(" (rc) : ", ref_count as *()); - + debug_borrow("check_not_borrowed:", a, ref_count, 0, file, line); if (ref_count & FROZEN_BIT) != 0 { fail_borrowed(a, file, line); } diff --git a/src/rt/rust_env.cpp b/src/rt/rust_env.cpp index 041b4efac52..360d6114928 100644 --- a/src/rt/rust_env.cpp +++ b/src/rt/rust_env.cpp @@ -24,6 +24,7 @@ #define RUST_SEED "RUST_SEED" #define RUST_POISON_ON_FREE "RUST_POISON_ON_FREE" #define RUST_DEBUG_MEM "RUST_DEBUG_MEM" +#define RUST_DEBUG_BORROW "RUST_DEBUG_BORROW" #if defined(__WIN32__) static int @@ -130,6 +131,7 @@ load_env(int argc, char **argv) { env->argc = argc; env->argv = argv; env->debug_mem = getenv(RUST_DEBUG_MEM) != NULL; + env->debug_borrow = getenv(RUST_DEBUG_BORROW) != NULL; return env; } diff --git a/src/rt/rust_env.h b/src/rt/rust_env.h index df27f7674f2..b897f0c09a9 100644 --- a/src/rt/rust_env.h +++ b/src/rt/rust_env.h @@ -28,6 +28,7 @@ struct rust_env { int argc; char **argv; rust_bool debug_mem; + rust_bool debug_borrow; }; rust_env* load_env(int argc, char **argv); -- cgit 1.4.1-3-g733a5