new borrow checker (mass squash)
This commit is contained in:
parent
b5a7e8b353
commit
a896440ca1
172 changed files with 6475 additions and 4303 deletions
|
|
@ -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>();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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> {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue