diff options
| author | Niko Matsakis <niko@alum.mit.edu> | 2013-03-15 15:24:24 -0400 |
|---|---|---|
| committer | Niko Matsakis <niko@alum.mit.edu> | 2013-04-30 06:59:32 -0400 |
| commit | a896440ca1b93cc5dc6edd827ea2ae89602bfa9e (patch) | |
| tree | c6945d51bf84faeb9be6ac32247c8ffa2cd39226 /src/libcore | |
| parent | b5a7e8b35322869b1cf51bd1b35a86e9e721da54 (diff) | |
| download | rust-a896440ca1b93cc5dc6edd827ea2ae89602bfa9e.tar.gz rust-a896440ca1b93cc5dc6edd827ea2ae89602bfa9e.zip | |
new borrow checker (mass squash)
Diffstat (limited to 'src/libcore')
| -rw-r--r-- | src/libcore/cleanup.rs | 40 | ||||
| -rw-r--r-- | src/libcore/io.rs | 14 | ||||
| -rw-r--r-- | src/libcore/rt/sched/mod.rs | 2 | ||||
| -rw-r--r-- | src/libcore/str.rs | 12 | ||||
| -rw-r--r-- | src/libcore/to_bytes.rs | 2 | ||||
| -rw-r--r-- | src/libcore/unstable/lang.rs | 47 | ||||
| -rw-r--r-- | src/libcore/vec.rs | 11 |
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> { |
