diff --git a/src/libcore/rt/env.rs b/src/libcore/rt/env.rs index 1f52cf77868a..e479375401a3 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 a3e44b5feea4..27fc3287bdb3 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 314b58d13e14..448f33796bcf 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 705a89381dfa..2a13cf73f8bb 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 d6df6c87dec4..af7165c53a7c 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 e6fe35609ec9..041b4efac52a 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 322198bb031f..df27f7674f26 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);