about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorNiko Matsakis <niko@alum.mit.edu>2013-03-15 15:24:24 -0400
committerNiko Matsakis <niko@alum.mit.edu>2013-04-30 06:59:32 -0400
commita896440ca1b93cc5dc6edd827ea2ae89602bfa9e (patch)
treec6945d51bf84faeb9be6ac32247c8ffa2cd39226 /src/libcore
parentb5a7e8b35322869b1cf51bd1b35a86e9e721da54 (diff)
downloadrust-a896440ca1b93cc5dc6edd827ea2ae89602bfa9e.tar.gz
rust-a896440ca1b93cc5dc6edd827ea2ae89602bfa9e.zip
new borrow checker (mass squash)
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/cleanup.rs40
-rw-r--r--src/libcore/io.rs14
-rw-r--r--src/libcore/rt/sched/mod.rs2
-rw-r--r--src/libcore/str.rs12
-rw-r--r--src/libcore/to_bytes.rs2
-rw-r--r--src/libcore/unstable/lang.rs47
-rw-r--r--src/libcore/vec.rs11
7 files changed, 87 insertions, 41 deletions
diff --git a/src/libcore/cleanup.rs b/src/libcore/cleanup.rs
index a07c6b4811b..1dfe1b22dc4 100644
--- a/src/libcore/cleanup.rs
+++ b/src/libcore/cleanup.rs
@@ -126,14 +126,17 @@ struct AnnihilateStats {
     n_bytes_freed: uint
 }
 
-unsafe fn each_live_alloc(f: &fn(box: *mut BoxRepr, uniq: bool) -> bool) {
+unsafe fn each_live_alloc(read_next_before: bool,
+                          f: &fn(box: *mut BoxRepr, uniq: bool) -> bool) {
+    //! Walks the internal list of allocations
+
     use managed;
 
     let task: *Task = transmute(rustrt::rust_get_task());
     let box = (*task).boxed_region.live_allocs;
     let mut box: *mut BoxRepr = transmute(copy box);
     while box != mut_null() {
-        let next = transmute(copy (*box).header.next);
+        let next_before = transmute(copy (*box).header.next);
         let uniq =
             (*box).header.ref_count == managed::raw::RC_MANAGED_UNIQUE;
 
@@ -141,7 +144,11 @@ unsafe fn each_live_alloc(f: &fn(box: *mut BoxRepr, uniq: bool) -> bool) {
             break
         }
 
-        box = next
+        if read_next_before {
+            box = next_before;
+        } else {
+            box = transmute(copy (*box).header.next);
+        }
     }
 }
 
@@ -159,7 +166,7 @@ fn debug_mem() -> bool {
 #[cfg(notest)]
 #[lang="annihilate"]
 pub unsafe fn annihilate() {
-    use unstable::lang::local_free;
+    use unstable::lang::{local_free, debug_ptr};
     use io::WriterUtil;
     use io;
     use libc;
@@ -173,27 +180,46 @@ pub unsafe fn annihilate() {
     };
 
     // Pass 1: Make all boxes immortal.
-    for each_live_alloc |box, uniq| {
+    //
+    // In this pass, nothing gets freed, so it does not matter whether
+    // we read the next field before or after the callback.
+    for each_live_alloc(true) |box, uniq| {
         stats.n_total_boxes += 1;
         if uniq {
+            debug_ptr("Managed-uniq: ", &*box);
             stats.n_unique_boxes += 1;
         } else {
+            debug_ptr("Immortalizing: ", &*box);
             (*box).header.ref_count = managed::raw::RC_IMMORTAL;
         }
     }
 
     // Pass 2: Drop all boxes.
-    for each_live_alloc |box, uniq| {
+    //
+    // In this pass, unique-managed boxes may get freed, but not
+    // managed boxes, so we must read the `next` field *after* the
+    // 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);
             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);
             drop_glue(to_unsafe_ptr(&tydesc), transmute(&(*box).data));
+            debug_ptr("Dropped ", &*box);
         }
     }
 
     // Pass 3: Free all boxes.
-    for each_live_alloc |box, uniq| {
+    //
+    // In this pass, managed boxes may get freed (but not
+    // unique-managed boxes, though I think that none of those are
+    // left), so we must read the `next` field before, since it will
+    // not be valid after.
+    for each_live_alloc(true) |box, uniq| {
         if !uniq {
+            debug_ptr("About to free: ", &*box);
             stats.n_bytes_freed +=
                 (*((*box).header.type_desc)).size
                 + sys::size_of::<BoxRepr>();
diff --git a/src/libcore/io.rs b/src/libcore/io.rs
index 35ffd88c8f4..217ea1a9982 100644
--- a/src/libcore/io.rs
+++ b/src/libcore/io.rs
@@ -1022,7 +1022,7 @@ pub enum WriterType { Screen, File }
 pub trait Writer {
 
     /// Write all of the given bytes.
-    fn write(&self, v: &const [u8]);
+    fn write(&self, v: &[u8]);
 
     /// Move the current position within the stream. The second parameter
     /// determines the position that the first parameter is relative to.
@@ -1039,7 +1039,7 @@ pub trait Writer {
 }
 
 impl Writer for @Writer {
-    fn write(&self, v: &const [u8]) { self.write(v) }
+    fn write(&self, v: &[u8]) { self.write(v) }
     fn seek(&self, a: int, b: SeekStyle) { self.seek(a, b) }
     fn tell(&self) -> uint { self.tell() }
     fn flush(&self) -> int { self.flush() }
@@ -1047,7 +1047,7 @@ impl Writer for @Writer {
 }
 
 impl<W:Writer,C> Writer for Wrapper<W, C> {
-    fn write(&self, bs: &const [u8]) { self.base.write(bs); }
+    fn write(&self, bs: &[u8]) { self.base.write(bs); }
     fn seek(&self, off: int, style: SeekStyle) { self.base.seek(off, style); }
     fn tell(&self) -> uint { self.base.tell() }
     fn flush(&self) -> int { self.base.flush() }
@@ -1055,7 +1055,7 @@ impl<W:Writer,C> Writer for Wrapper<W, C> {
 }
 
 impl Writer for *libc::FILE {
-    fn write(&self, v: &const [u8]) {
+    fn write(&self, v: &[u8]) {
         unsafe {
             do vec::as_const_buf(v) |vbuf, len| {
                 let nout = libc::fwrite(vbuf as *c_void,
@@ -1105,7 +1105,7 @@ pub fn FILE_writer(f: *libc::FILE, cleanup: bool) -> @Writer {
 }
 
 impl Writer for fd_t {
-    fn write(&self, v: &const [u8]) {
+    fn write(&self, v: &[u8]) {
         unsafe {
             let mut count = 0u;
             do vec::as_const_buf(v) |vbuf, len| {
@@ -1262,7 +1262,7 @@ pub fn u64_to_be_bytes<T>(n: u64, size: uint,
     }
 }
 
-pub fn u64_from_be_bytes(data: &const [u8],
+pub fn u64_from_be_bytes(data: &[u8],
                          start: uint,
                          size: uint)
                       -> u64 {
@@ -1497,7 +1497,7 @@ pub struct BytesWriter {
 }
 
 impl Writer for BytesWriter {
-    fn write(&self, v: &const [u8]) {
+    fn write(&self, v: &[u8]) {
         let v_len = v.len();
         let bytes_len = vec::uniq_len(&const self.bytes);
 
diff --git a/src/libcore/rt/sched/mod.rs b/src/libcore/rt/sched/mod.rs
index 28946281628..a2132676c1a 100644
--- a/src/libcore/rt/sched/mod.rs
+++ b/src/libcore/rt/sched/mod.rs
@@ -304,7 +304,7 @@ pub impl Scheduler {
         unsafe {
             let last_task = transmute::<Option<&Task>, Option<&mut Task>>(last_task);
             let last_task_context = match last_task {
-                Some(ref t) => Some(&mut t.saved_context), None => None
+                Some(t) => Some(&mut t.saved_context), None => None
             };
             let next_task_context = match self.current_task {
                 Some(ref mut t) => Some(&mut t.saved_context), None => None
diff --git a/src/libcore/str.rs b/src/libcore/str.rs
index 064bffa0056..f4430ca669f 100644
--- a/src/libcore/str.rs
+++ b/src/libcore/str.rs
@@ -2356,9 +2356,6 @@ pub trait StrSlice<'self> {
     fn any(&self, it: &fn(char) -> bool) -> bool;
     fn contains<'a>(&self, needle: &'a str) -> bool;
     fn contains_char(&self, needle: char) -> bool;
-    #[cfg(stage1)]
-    #[cfg(stage2)]
-    #[cfg(stage3)]
     fn char_iter(&self) -> StrCharIterator<'self>;
     fn each(&self, it: &fn(u8) -> bool);
     fn eachi(&self, it: &fn(uint, u8) -> bool);
@@ -2420,9 +2417,6 @@ impl<'self> StrSlice<'self> for &'self str {
         contains_char(*self, needle)
     }
 
-    #[cfg(stage1)]
-    #[cfg(stage2)]
-    #[cfg(stage3)]
     #[inline]
     fn char_iter(&self) -> StrCharIterator<'self> {
         StrCharIterator {
@@ -2615,17 +2609,11 @@ impl Clone for ~str {
     }
 }
 
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
 pub struct StrCharIterator<'self> {
     priv index: uint,
     priv string: &'self str,
 }
 
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
 impl<'self> Iterator<char> for StrCharIterator<'self> {
     #[inline]
     fn next(&mut self) -> Option<char> {
diff --git a/src/libcore/to_bytes.rs b/src/libcore/to_bytes.rs
index 7b4b6994e50..63dcf0f44dc 100644
--- a/src/libcore/to_bytes.rs
+++ b/src/libcore/to_bytes.rs
@@ -19,7 +19,7 @@ use io::Writer;
 use option::{None, Option, Some};
 use str;
 
-pub type Cb<'self> = &'self fn(buf: &const [u8]) -> bool;
+pub type Cb<'self> = &'self fn(buf: &[u8]) -> bool;
 
 /**
  * A trait to implement in order to make a type hashable;
diff --git a/src/libcore/unstable/lang.rs b/src/libcore/unstable/lang.rs
index de0542afc39..cf71b01aeae 100644
--- a/src/libcore/unstable/lang.rs
+++ b/src/libcore/unstable/lang.rs
@@ -11,7 +11,7 @@
 //! Runtime calls emitted by the compiler.
 
 use cast::transmute;
-use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int};
+use libc::{c_char, c_uchar, c_void, size_t, uintptr_t, c_int, STDERR_FILENO};
 use managed::raw::BoxRepr;
 use str;
 use sys;
@@ -74,7 +74,44 @@ pub fn fail_borrowed() {
 #[lang="exchange_malloc"]
 #[inline(always)]
 pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
-    transmute(exchange_alloc::malloc(transmute(td), transmute(size)))
+    let result = transmute(exchange_alloc::malloc(transmute(td), transmute(size)));
+    debug_ptr("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 = false;
+
+#[inline]
+pub fn debug_ptr<T>(tag: &'static str, p: *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);
+    }
+
+    fn debug_ptr_slow<T>(tag: &'static str, p: *T) {
+        use io;
+        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);
+
+        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));
+
+        dbg.write_str("\n");
+    }
 }
 
 // NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
@@ -83,13 +120,16 @@ pub unsafe fn exchange_malloc(td: *c_char, size: uintptr_t) -> *c_char {
 #[lang="exchange_free"]
 #[inline(always)]
 pub unsafe fn exchange_free(ptr: *c_char) {
+    debug_ptr("exchange_free: ", ptr);
     exchange_alloc::free(transmute(ptr))
 }
 
 #[lang="malloc"]
 #[inline(always)]
 pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
-    return rustrt::rust_upcall_malloc_noswitch(td, size);
+    let result = rustrt::rust_upcall_malloc_noswitch(td, size);
+    debug_ptr("local_malloc: ", result);
+    return result;
 }
 
 // NB: Calls to free CANNOT be allowed to fail, as throwing an exception from
@@ -98,6 +138,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);
     rustrt::rust_upcall_free_noswitch(ptr);
 }
 
diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs
index 94f86664353..2f9488d1bc7 100644
--- a/src/libcore/vec.rs
+++ b/src/libcore/vec.rs
@@ -19,9 +19,6 @@ use cmp::{Eq, Ord, TotalEq, TotalOrd, Ordering, Less, Equal, Greater};
 use clone::Clone;
 use old_iter::BaseIter;
 use old_iter;
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
 use iterator::Iterator;
 use kinds::Copy;
 use libc;
@@ -1824,7 +1821,7 @@ pub trait CopyableVector<T> {
 }
 
 /// Extension methods for vectors
-impl<'self,T:Copy> CopyableVector<T> for &'self const [T] {
+impl<'self,T:Copy> CopyableVector<T> for &'self [T] {
     /// Returns a copy of `v`.
     #[inline]
     fn to_owned(&self) -> ~[T] {
@@ -2710,18 +2707,12 @@ impl<A:Clone> Clone for ~[A] {
 }
 
 // could be implemented with &[T] with .slice(), but this avoids bounds checks
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
 pub struct VecIterator<'self, T> {
     priv ptr: *T,
     priv end: *T,
     priv lifetime: &'self T // FIXME: #5922
 }
 
-#[cfg(stage1)]
-#[cfg(stage2)]
-#[cfg(stage3)]
 impl<'self, T> Iterator<&'self T> for VecIterator<'self, T> {
     #[inline]
     fn next(&mut self) -> Option<&'self T> {