about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorErick Tryzelaar <erick.tryzelaar@gmail.com>2013-08-06 16:18:58 -0700
committerErick Tryzelaar <erick.tryzelaar@gmail.com>2013-08-06 16:18:58 -0700
commit8567611adfa69c4488133e18d3ec4fc195afadd1 (patch)
tree80e325db23f407d643e2ada480de23b1fb8b4fc6 /src/libstd
parentfb9b27910b41e714dfd6b3ccc48161260943c9cf (diff)
parentd89ff7eef969aee6b493bc846b64d68358fafbcd (diff)
downloadrust-8567611adfa69c4488133e18d3ec4fc195afadd1.tar.gz
rust-8567611adfa69c4488133e18d3ec4fc195afadd1.zip
Merge commit 'd89ff7eef969aee6b493bc846b64d68358fafbcd' into remove-str-trailing-nulls
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/comm.rs110
-rw-r--r--src/libstd/gc.rs358
-rw-r--r--src/libstd/logging.rs10
-rw-r--r--src/libstd/pipes.rs44
-rw-r--r--src/libstd/rt/local.rs81
-rw-r--r--src/libstd/rt/local_ptr.rs26
-rw-r--r--src/libstd/rt/logging.rs21
-rw-r--r--src/libstd/rt/mod.rs10
-rw-r--r--src/libstd/rt/sched.rs12
-rw-r--r--src/libstd/rt/task.rs17
-rw-r--r--src/libstd/stackwalk.rs80
-rw-r--r--src/libstd/std.rs2
-rw-r--r--src/libstd/str.rs9
-rw-r--r--src/libstd/sys.rs4
14 files changed, 114 insertions, 670 deletions
diff --git a/src/libstd/comm.rs b/src/libstd/comm.rs
index a0731dc3494..4356f1143da 100644
--- a/src/libstd/comm.rs
+++ b/src/libstd/comm.rs
@@ -14,7 +14,6 @@ Message passing
 
 #[allow(missing_doc)];
 
-use cast::transmute;
 use either::{Either, Left, Right};
 use kinds::Send;
 use option::{Option, Some};
@@ -23,12 +22,6 @@ pub use rt::comm::SendDeferred;
 use rtcomm = rt::comm;
 use rt;
 
-use pipes::{wait_many, PacketHeader};
-
-// FIXME #5160: Making this public exposes some plumbing from
-// pipes. Needs some refactoring
-pub use pipes::Selectable;
-
 /// A trait for things that can send multiple messages.
 pub trait GenericChan<T> {
     /// Sends a message.
@@ -146,15 +139,6 @@ impl<T: Send> Peekable<T> for Port<T> {
     }
 }
 
-impl<T: Send> Selectable for Port<T> {
-    fn header(&mut self) -> *mut PacketHeader {
-        match self.inner {
-            Left(ref mut port) => port.header(),
-            Right(_) => fail!("can't select on newsched ports")
-        }
-    }
-}
-
 /// A channel that can be shared between many senders.
 pub struct SharedChan<T> {
     inner: Either<Exclusive<pipesy::Chan<T>>, rtcomm::SharedChan<T>>
@@ -318,8 +302,8 @@ mod pipesy {
 
     use kinds::Send;
     use option::{Option, Some, None};
-    use pipes::{recv, try_recv, peek, PacketHeader};
-    use super::{GenericChan, GenericSmartChan, GenericPort, Peekable, Selectable};
+    use pipes::{recv, try_recv, peek};
+    use super::{GenericChan, GenericSmartChan, GenericPort, Peekable};
     use cast::transmute_mut;
 
     /*proto! oneshot (
@@ -651,80 +635,6 @@ mod pipesy {
         }
     }
 
-    impl<T: Send> Selectable for Port<T> {
-        fn header(&mut self) -> *mut PacketHeader {
-            match self.endp {
-                Some(ref mut endp) => endp.header(),
-                None => fail!("peeking empty stream")
-            }
-    }
-}
-
-}
-
-/// Returns the index of an endpoint that is ready to receive.
-pub fn selecti<T: Selectable>(endpoints: &mut [T]) -> uint {
-    wait_many(endpoints)
-}
-
-/// Returns 0 or 1 depending on which endpoint is ready to receive
-pub fn select2i<A:Selectable, B:Selectable>(a: &mut A, b: &mut B)
-                                            -> Either<(), ()> {
-    let mut endpoints = [ a.header(), b.header() ];
-    match wait_many(endpoints) {
-        0 => Left(()),
-        1 => Right(()),
-        _ => fail!("wait returned unexpected index"),
-    }
-}
-
-/// Receive a message from one of two endpoints.
-pub trait Select2<T: Send, U: Send> {
-    /// Receive a message or return `None` if a connection closes.
-    fn try_select(&mut self) -> Either<Option<T>, Option<U>>;
-    /// Receive a message or fail if a connection closes.
-    fn select(&mut self) -> Either<T, U>;
-}
-
-impl<T:Send,
-     U:Send,
-     Left:Selectable + GenericPort<T>,
-     Right:Selectable + GenericPort<U>>
-     Select2<T, U>
-     for (Left, Right) {
-    fn select(&mut self) -> Either<T, U> {
-        // XXX: Bad borrow check workaround.
-        unsafe {
-            let this: &(Left, Right) = transmute(self);
-            match *this {
-                (ref lp, ref rp) => {
-                    let lp: &mut Left = transmute(lp);
-                    let rp: &mut Right = transmute(rp);
-                    match select2i(lp, rp) {
-                        Left(()) => Left(lp.recv()),
-                        Right(()) => Right(rp.recv()),
-                    }
-                }
-            }
-        }
-    }
-
-    fn try_select(&mut self) -> Either<Option<T>, Option<U>> {
-        // XXX: Bad borrow check workaround.
-        unsafe {
-            let this: &(Left, Right) = transmute(self);
-            match *this {
-                (ref lp, ref rp) => {
-                    let lp: &mut Left = transmute(lp);
-                    let rp: &mut Right = transmute(rp);
-                    match select2i(lp, rp) {
-                        Left(()) => Left (lp.try_recv()),
-                        Right(()) => Right(rp.try_recv()),
-                    }
-                }
-            }
-        }
-    }
 }
 
 #[cfg(test)]
@@ -733,22 +643,6 @@ mod test {
     use super::{Chan, Port, oneshot, stream};
 
     #[test]
-    fn test_select2() {
-        let (p1, c1) = stream();
-        let (p2, c2) = stream();
-
-        c1.send(~"abc");
-
-        let mut tuple = (p1, p2);
-        match tuple.select() {
-            Right(_) => fail!(),
-            _ => (),
-        }
-
-        c2.send(123);
-    }
-
-    #[test]
     fn test_oneshot() {
         let (p, c) = oneshot();
 
diff --git a/src/libstd/gc.rs b/src/libstd/gc.rs
deleted file mode 100644
index 2e27f82f6f6..00000000000
--- a/src/libstd/gc.rs
+++ /dev/null
@@ -1,358 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[doc(hidden)];
-#[allow(non_uppercase_statics)];
-
-/*! Precise garbage collector
-
-The precise GC exposes two functions, gc and
-cleanup_stack_for_failure. The gc function is the entry point to the
-garbage collector itself. The cleanup_stack_for_failure is the entry
-point for GC-based cleanup.
-
-Precise GC depends on changes to LLVM's GC which add support for
-automatic rooting and addrspace-based metadata marking. Rather than
-explicitly rooting pointers with LLVM's gcroot intrinsic, the GC
-merely creates allocas for pointers, and allows an LLVM pass to
-automatically infer roots based on the allocas present in a function
-(and live at a given location). The compiler communicates the type of
-the pointer to LLVM by setting the addrspace of the pointer type. The
-compiler then emits a map from addrspace to tydesc, which LLVM then
-uses to match pointers with their tydesc. The GC reads the metadata
-table produced by LLVM, and uses it to determine which glue functions
-to call to free objects on their respective heaps.
-
-GC-based cleanup is a replacement for landing pads which relies on the
-GC infrastructure to find pointers on the stack to cleanup. Whereas
-the normal GC needs to walk task-local heap allocations, the cleanup
-code needs to walk exchange heap allocations and stack-allocations
-with destructors.
-
-*/
-
-use cast;
-use container::{Set, MutableSet};
-use io;
-use libc::{uintptr_t};
-use option::{None, Option, Some};
-use ptr;
-use hashmap::HashSet;
-use stackwalk::walk_stack;
-use sys;
-use unstable::intrinsics::{TyDesc};
-
-pub use stackwalk::Word;
-
-// Mirrors rust_stack.h stk_seg
-pub struct StackSegment {
-    prev: *StackSegment,
-    next: *StackSegment,
-    end: uintptr_t,
-    // And other fields which we don't care about...
-}
-
-pub mod rustrt {
-    use stackwalk::Word;
-    use super::StackSegment;
-
-    #[link_name = "rustrt"]
-    extern {
-        #[rust_stack]
-        pub fn rust_gc_metadata() -> *Word;
-
-        pub fn rust_get_stack_segment() -> *StackSegment;
-        pub fn rust_get_c_stack() -> *StackSegment;
-    }
-}
-
-unsafe fn bump<T, U>(ptr: *T, count: uint) -> *U {
-    return ptr::offset(ptr, count as int) as *U;
-}
-
-unsafe fn align_to_pointer<T>(ptr: *T) -> *T {
-    let align = sys::min_align_of::<*T>();
-    let ptr = ptr as uint;
-    let ptr = (ptr + (align - 1)) & -align;
-    return ptr as *T;
-}
-
-unsafe fn get_safe_point_count() -> uint {
-    let module_meta = rustrt::rust_gc_metadata();
-    return *module_meta;
-}
-
-struct SafePoint {
-    sp_meta: *Word,
-    fn_meta: *Word,
-}
-
-// Returns the safe point metadata for the given program counter, if
-// any.
-unsafe fn is_safe_point(pc: *Word) -> Option<SafePoint> {
-    let module_meta = rustrt::rust_gc_metadata();
-    let num_safe_points = *module_meta;
-    let safe_points: *Word = bump(module_meta, 1);
-
-    if ptr::is_null(pc) {
-        return None;
-    }
-
-    // FIXME (#2997): Use binary rather than linear search.
-    let mut spi = 0;
-    while spi < num_safe_points {
-        let sp: **Word = bump(safe_points, spi*3);
-        let sp_loc = *sp;
-        if sp_loc == pc {
-            return Some(SafePoint {
-                sp_meta: *bump(sp, 1),
-                fn_meta: *bump(sp, 2),
-            });
-        }
-        spi += 1;
-    }
-    return None;
-}
-
-type Visitor<'self> = &'self fn(root: **Word, tydesc: *TyDesc);
-
-// Walks the list of roots for the given safe point, and calls visitor
-// on each root.
-unsafe fn _walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) {
-    let fp_bytes = fp as *u8;
-    let sp_meta = sp.sp_meta as *u32;
-
-    let num_stack_roots = *sp_meta as uint;
-    let num_reg_roots = *ptr::offset(sp_meta, 1) as uint;
-
-    let stack_roots: *u32 = bump(sp_meta, 2);
-    let reg_roots: *u8 = bump(stack_roots, num_stack_roots);
-    let addrspaces: *Word = align_to_pointer(bump(reg_roots, num_reg_roots));
-    let tydescs: ***TyDesc = bump(addrspaces, num_stack_roots);
-
-    // Stack roots
-    let mut sri = 0;
-    while sri < num_stack_roots {
-        if *ptr::offset(addrspaces, sri as int) >= 1 {
-            let root =
-                ptr::offset(fp_bytes, *ptr::offset(stack_roots, sri as int) as int)
-                as **Word;
-            let tydescpp = ptr::offset(tydescs, sri as int);
-            let tydesc = if ptr::is_not_null(tydescpp) &&
-                ptr::is_not_null(*tydescpp) {
-                **tydescpp
-            } else {
-                ptr::null()
-            };
-            visitor(root, tydesc);
-        }
-        sri += 1;
-    }
-
-    // Register roots
-    let mut rri = 0;
-    while rri < num_reg_roots {
-        if *ptr::offset(addrspaces, (num_stack_roots + rri) as int) == 1 {
-            // FIXME(#2997): Need to find callee saved registers on the stack.
-        }
-        rri += 1;
-    }
-}
-
-unsafe fn walk_safe_point(fp: *Word, sp: SafePoint, visitor: Visitor) {
-    _walk_safe_point(fp, sp, visitor)
-}
-
-// Is fp contained in segment?
-unsafe fn is_frame_in_segment(fp: *Word, segment: *StackSegment) -> bool {
-    let begin = segment as Word;
-    let end = (*segment).end as Word;
-    let frame = fp as Word;
-
-    return begin <= frame && frame <= end;
-}
-
-struct Segment { segment: *StackSegment, boundary: bool }
-
-// Find and return the segment containing the given frame pointer. At
-// stack segment boundaries, returns true for boundary, so that the
-// caller can do any special handling to identify where the correct
-// return address is in the stack frame.
-unsafe fn find_segment_for_frame(fp: *Word, segment: *StackSegment)
-    -> Segment {
-    // Check if frame is in either current frame or previous frame.
-    let in_segment = is_frame_in_segment(fp, segment);
-    let in_prev_segment = ptr::is_not_null((*segment).prev) &&
-        is_frame_in_segment(fp, (*segment).prev);
-
-    // If frame is not in either segment, walk down segment list until
-    // we find the segment containing this frame.
-    if !in_segment && !in_prev_segment {
-        let mut segment = segment;
-        while ptr::is_not_null((*segment).next) &&
-            is_frame_in_segment(fp, (*segment).next) {
-            segment = (*segment).next;
-        }
-        return Segment {segment: segment, boundary: false};
-    }
-
-    // If frame is in previous frame, then we're at a boundary.
-    if !in_segment && in_prev_segment {
-        return Segment {segment: (*segment).prev, boundary: true};
-    }
-
-    // Otherwise, we're somewhere on the inside of the frame.
-    return Segment {segment: segment, boundary: false};
-}
-
-type Memory = uint;
-
-static task_local_heap: Memory = 1;
-static exchange_heap:   Memory = 2;
-static stack:           Memory = 4;
-
-static need_cleanup:    Memory = exchange_heap | stack;
-
-// Walks stack, searching for roots of the requested type, and passes
-// each root to the visitor.
-unsafe fn _walk_gc_roots(mem: Memory, sentinel: **Word, visitor: Visitor) {
-    let mut segment = rustrt::rust_get_stack_segment();
-    let mut last_ret: *Word = ptr::null();
-    // To avoid collecting memory used by the GC itself, skip stack
-    // frames until past the root GC stack frame. The root GC stack
-    // frame is marked by a sentinel, which is a box pointer stored on
-    // the stack.
-    let mut reached_sentinel = ptr::is_null(sentinel);
-    do walk_stack |frame| {
-        let pc = last_ret;
-        let Segment {segment: next_segment, boundary: boundary} =
-            find_segment_for_frame(frame.fp, segment);
-        segment = next_segment;
-        // Each stack segment is bounded by a morestack frame. The
-        // morestack frame includes two return addresses, one for
-        // morestack itself, at the normal offset from the frame
-        // pointer, and then a second return address for the
-        // function prologue (which called morestack after
-        // determining that it had hit the end of the stack).
-        // Since morestack itself takes two parameters, the offset
-        // for this second return address is 3 greater than the
-        // return address for morestack.
-        let ret_offset = if boundary { 4 } else { 1 };
-        last_ret = *ptr::offset(frame.fp, ret_offset as int) as *Word;
-
-        if !ptr::is_null(pc) {
-
-            let mut delay_reached_sentinel = reached_sentinel;
-            let sp = is_safe_point(pc);
-            match sp {
-                Some(sp_info) => {
-                    do walk_safe_point(frame.fp, sp_info) |root, tydesc| {
-                        // Skip roots until we see the sentinel.
-                        if !reached_sentinel && root == sentinel {
-                            delay_reached_sentinel = true;
-                        }
-
-                        // Skip null pointers, which can occur when a
-                        // unique pointer has already been freed.
-                        if reached_sentinel && !ptr::is_null(*root) {
-                            if ptr::is_null(tydesc) {
-                                // Root is a generic box.
-                                let refcount = **root;
-                                if mem | task_local_heap != 0 && refcount != -1 {
-                                    visitor(root, tydesc);
-                                } else if mem | exchange_heap != 0 && refcount == -1 {
-                                    visitor(root, tydesc);
-                                }
-                            } else {
-                                // Root is a non-immediate.
-                                if mem | stack != 0 {
-                                    visitor(root, tydesc);
-                                }
-                            }
-                        }
-                    }
-                }
-                None => ()
-            }
-            reached_sentinel = delay_reached_sentinel;
-        }
-    }
-}
-
-unsafe fn walk_gc_roots(mem: Memory, sentinel: **Word, visitor: Visitor) {
-    _walk_gc_roots(mem, sentinel, visitor)
-}
-pub fn gc() {
-    unsafe {
-        // Abort when GC is disabled.
-        if get_safe_point_count() == 0 {
-            return;
-        }
-
-        do walk_gc_roots(task_local_heap, ptr::null()) |_root, _tydesc| {
-            // FIXME(#2997): Walk roots and mark them.
-            io::stdout().write([46]); // .
-        }
-    }
-}
-
-#[cfg(gc)]
-fn expect_sentinel() -> bool { true }
-
-#[cfg(nogc)]
-fn expect_sentinel() -> bool { false }
-
-// Entry point for GC-based cleanup. Walks stack looking for exchange
-// heap and stack allocations requiring drop, and runs all
-// destructors.
-//
-// This should only be called from fail!, as it will drop the roots
-// which are *live* on the stack, rather than dropping those that are
-// dead.
-pub fn cleanup_stack_for_failure() {
-    unsafe {
-        // Abort when GC is disabled.
-        if get_safe_point_count() == 0 {
-            return;
-        }
-
-        // Leave a sentinel on the stack to mark the current frame. The
-        // stack walker will ignore any frames above the sentinel, thus
-        // avoiding collecting any memory being used by the stack walker
-        // itself.
-        //
-        // However, when core itself is not compiled with GC, then none of
-        // the functions in core will have GC metadata, which means we
-        // won't be able to find the sentinel root on the stack. In this
-        // case, we can safely skip the sentinel since we won't find our
-        // own stack roots on the stack anyway.
-        let sentinel_box = ~0;
-        let sentinel: **Word = if expect_sentinel() {
-            cast::transmute(&sentinel_box)
-        } else {
-            ptr::null()
-        };
-
-        let mut roots = HashSet::new();
-        do walk_gc_roots(need_cleanup, sentinel) |root, tydesc| {
-            // Track roots to avoid double frees.
-            if !roots.contains(&*root) {
-                roots.insert(*root);
-
-                if ptr::is_null(tydesc) {
-                    // FIXME #4420: Destroy this box
-                    // FIXME #4330: Destroy this box
-                } else {
-                    ((*tydesc).drop_glue)(*root as *i8);
-                }
-            }
-        }
-    }
-}
diff --git a/src/libstd/logging.rs b/src/libstd/logging.rs
index c662e5997af..6e11d14aea9 100644
--- a/src/libstd/logging.rs
+++ b/src/libstd/logging.rs
@@ -85,16 +85,6 @@ pub fn log_type<T>(level: u32, object: &T) {
 fn newsched_log_str(msg: ~str) {
     use rt::task::Task;
     use rt::local::Local;
-    use str::StrSlice;
-    use container::Container;
-
-    // Truncate the string
-    let buf_bytes = 256;
-    let msg = if msg.len() > buf_bytes {
-        msg.slice(0, buf_bytes) + "[...]"
-    } else {
-        msg
-    };
 
     unsafe {
         match Local::try_unsafe_borrow::<Task>() {
diff --git a/src/libstd/pipes.rs b/src/libstd/pipes.rs
index 1fd534825a5..78f937e058a 100644
--- a/src/libstd/pipes.rs
+++ b/src/libstd/pipes.rs
@@ -868,47 +868,3 @@ pub mod rt {
     pub fn make_some<T>(val: T) -> Option<T> { Some(val) }
     pub fn make_none<T>() -> Option<T> { None }
 }
-
-#[cfg(test)]
-mod test {
-    use either::Right;
-    use comm::{Chan, Port, oneshot, recv_one, stream, Select2,
-               GenericChan, Peekable};
-
-    #[test]
-    fn test_select2() {
-        let (p1, c1) = stream();
-        let (p2, c2) = stream();
-
-        c1.send(~"abc");
-
-        let mut tuple = (p1, p2);
-        match tuple.select() {
-            Right(_) => fail!(),
-            _ => (),
-        }
-
-        c2.send(123);
-    }
-
-    #[test]
-    fn test_oneshot() {
-        let (p, c) = oneshot();
-
-        c.send(());
-
-        recv_one(p)
-    }
-
-    #[test]
-    fn test_peek_terminated() {
-        let (port, chan): (Port<int>, Chan<int>) = stream();
-
-        {
-            // Destroy the channel
-            let _chan = chan;
-        }
-
-        assert!(!port.peek());
-    }
-}
diff --git a/src/libstd/rt/local.rs b/src/libstd/rt/local.rs
index 7ab63233cff..131507196b1 100644
--- a/src/libstd/rt/local.rs
+++ b/src/libstd/rt/local.rs
@@ -126,6 +126,7 @@ impl Local for IoFactoryObject {
 
 #[cfg(test)]
 mod test {
+    use unstable::run_in_bare_thread;
     use rt::test::*;
     use super::*;
     use rt::task::Task;
@@ -133,56 +134,64 @@ mod test {
 
     #[test]
     fn thread_local_task_smoke_test() {
-        local_ptr::init_tls_key();
-        let mut sched = ~new_test_uv_sched();
-        let task = ~Task::new_root(&mut sched.stack_pool, || {});
-        Local::put(task);
-        let task: ~Task = Local::take();
-        cleanup_task(task);
+        do run_in_bare_thread {
+            local_ptr::init_tls_key();
+            let mut sched = ~new_test_uv_sched();
+            let task = ~Task::new_root(&mut sched.stack_pool, || {});
+            Local::put(task);
+            let task: ~Task = Local::take();
+            cleanup_task(task);
+        }
     }
 
     #[test]
     fn thread_local_task_two_instances() {
-        local_ptr::init_tls_key();
-        let mut sched = ~new_test_uv_sched();
-        let task = ~Task::new_root(&mut sched.stack_pool, || {});
-        Local::put(task);
-        let task: ~Task = Local::take();
-        cleanup_task(task);
-        let task = ~Task::new_root(&mut sched.stack_pool, || {});
-        Local::put(task);
-        let task: ~Task = Local::take();
-        cleanup_task(task);
+        do run_in_bare_thread {
+            local_ptr::init_tls_key();
+            let mut sched = ~new_test_uv_sched();
+            let task = ~Task::new_root(&mut sched.stack_pool, || {});
+            Local::put(task);
+            let task: ~Task = Local::take();
+            cleanup_task(task);
+            let task = ~Task::new_root(&mut sched.stack_pool, || {});
+            Local::put(task);
+            let task: ~Task = Local::take();
+            cleanup_task(task);
+        }
 
     }
 
     #[test]
     fn borrow_smoke_test() {
-        local_ptr::init_tls_key();
-        let mut sched = ~new_test_uv_sched();
-        let task = ~Task::new_root(&mut sched.stack_pool, || {});
-        Local::put(task);
-
-        unsafe {
-            let _task: *mut Task = Local::unsafe_borrow();
+        do run_in_bare_thread {
+            local_ptr::init_tls_key();
+            let mut sched = ~new_test_uv_sched();
+            let task = ~Task::new_root(&mut sched.stack_pool, || {});
+            Local::put(task);
+
+            unsafe {
+                let _task: *mut Task = Local::unsafe_borrow();
+            }
+            let task: ~Task = Local::take();
+            cleanup_task(task);
         }
-        let task: ~Task = Local::take();
-        cleanup_task(task);
     }
 
     #[test]
     fn borrow_with_return() {
-        local_ptr::init_tls_key();
-        let mut sched = ~new_test_uv_sched();
-        let task = ~Task::new_root(&mut sched.stack_pool, || {});
-        Local::put(task);
-
-        let res = do Local::borrow::<Task,bool> |_task| {
-            true
-        };
-        assert!(res)
-        let task: ~Task = Local::take();
-        cleanup_task(task);
+        do run_in_bare_thread {
+            local_ptr::init_tls_key();
+            let mut sched = ~new_test_uv_sched();
+            let task = ~Task::new_root(&mut sched.stack_pool, || {});
+            Local::put(task);
+
+            let res = do Local::borrow::<Task,bool> |_task| {
+                true
+            };
+            assert!(res)
+                let task: ~Task = Local::take();
+            cleanup_task(task);
+        }
     }
 
 }
diff --git a/src/libstd/rt/local_ptr.rs b/src/libstd/rt/local_ptr.rs
index cd7c5daa444..652e39b05c7 100644
--- a/src/libstd/rt/local_ptr.rs
+++ b/src/libstd/rt/local_ptr.rs
@@ -52,7 +52,9 @@ pub unsafe fn put<T>(sched: ~T) {
 pub unsafe fn take<T>() -> ~T {
     let key = tls_key();
     let void_ptr: *mut c_void = tls::get(key);
-    rtassert!(void_ptr.is_not_null());
+    if void_ptr.is_null() {
+        rtabort!("thread-local pointer is null. bogus!");
+    }
     let ptr: ~T = cast::transmute(void_ptr);
     tls::set(key, ptr::mut_null());
     return ptr;
@@ -68,8 +70,8 @@ pub fn exists() -> bool {
     }
 }
 
-/// Borrow the thread-local scheduler from thread-local storage.
-/// While the scheduler is borrowed it is not available in TLS.
+/// Borrow the thread-local value from thread-local storage.
+/// While the value is borrowed it is not available in TLS.
 ///
 /// # Safety note
 ///
@@ -88,21 +90,23 @@ pub unsafe fn borrow<T>(f: &fn(&mut T)) {
     }
 }
 
-/// Borrow a mutable reference to the thread-local Scheduler
+/// Borrow a mutable reference to the thread-local value
 ///
 /// # Safety Note
 ///
-/// Because this leaves the Scheduler in thread-local storage it is possible
+/// Because this leaves the value in thread-local storage it is possible
 /// For the Scheduler pointer to be aliased
 pub unsafe fn unsafe_borrow<T>() -> *mut T {
     let key = tls_key();
-    let mut void_sched: *mut c_void = tls::get(key);
-    rtassert!(void_sched.is_not_null());
+    let mut void_ptr: *mut c_void = tls::get(key);
+    if void_ptr.is_null() {
+        rtabort!("thread-local pointer is null. bogus!");
+    }
     {
-        let sched: *mut *mut c_void = &mut void_sched;
-        let sched: *mut ~T = sched as *mut ~T;
-        let sched: *mut T = &mut **sched;
-        return sched;
+        let ptr: *mut *mut c_void = &mut void_ptr;
+        let ptr: *mut ~T = ptr as *mut ~T;
+        let ptr: *mut T = &mut **ptr;
+        return ptr;
     }
 }
 
diff --git a/src/libstd/rt/logging.rs b/src/libstd/rt/logging.rs
index 76619704bee..117795f6c90 100644
--- a/src/libstd/rt/logging.rs
+++ b/src/libstd/rt/logging.rs
@@ -10,6 +10,7 @@
 
 use either::*;
 use libc;
+use str::StrSlice;
 
 pub trait Logger {
     fn log(&mut self, msg: Either<~str, &'static str>);
@@ -35,10 +36,22 @@ impl Logger for StdErrLogger {
                 s
             }
         };
-        let dbg = ::libc::STDERR_FILENO as ::io::fd_t;
-        dbg.write_str(s);
-        dbg.write_str("\n");
-        dbg.flush();
+
+        // Truncate the string
+        let buf_bytes = 256;
+        if s.len() > buf_bytes {
+            let s = s.slice(0, buf_bytes) + "[...]";
+            print(s);
+        } else {
+            print(s)
+        };
+
+        fn print(s: &str) {
+            let dbg = ::libc::STDERR_FILENO as ::io::fd_t;
+            dbg.write_str(s);
+            dbg.write_str("\n");
+            dbg.flush();
+        }
     }
 }
 
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index 4cfe0efacfe..33e83fd9040 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -432,13 +432,3 @@ pub fn context() -> RuntimeContext {
         pub fn rust_try_get_task() -> *rust_task;
     }
 }
-
-#[test]
-fn test_context() {
-    use unstable::run_in_bare_thread;
-
-    assert_eq!(context(), OldTaskContext);
-    do run_in_bare_thread {
-        assert_eq!(context(), GlobalContext);
-    }
-}
diff --git a/src/libstd/rt/sched.rs b/src/libstd/rt/sched.rs
index 18cfeade157..1a75f2569b5 100644
--- a/src/libstd/rt/sched.rs
+++ b/src/libstd/rt/sched.rs
@@ -172,6 +172,10 @@ impl Scheduler {
 
         rtdebug!("stopping scheduler %u", stask.sched.get_ref().sched_id());
 
+        // Should not have any messages
+        let message = stask.sched.get_mut_ref().message_queue.pop();
+        assert!(message.is_none());
+
         stask.destroyed = true;
     }
 
@@ -335,19 +339,24 @@ impl Scheduler {
         let mut this = self;
         match this.message_queue.pop() {
             Some(PinnedTask(task)) => {
+                this.event_loop.callback(Scheduler::run_sched_once);
                 let mut task = task;
                 task.give_home(Sched(this.make_handle()));
                 this.resume_task_immediately(task);
                 return None;
             }
             Some(TaskFromFriend(task)) => {
+                this.event_loop.callback(Scheduler::run_sched_once);
+                rtdebug!("got a task from a friend. lovely!");
                 return this.sched_schedule_task(task);
             }
             Some(Wake) => {
+                this.event_loop.callback(Scheduler::run_sched_once);
                 this.sleepy = false;
                 return Some(this);
             }
             Some(Shutdown) => {
+                this.event_loop.callback(Scheduler::run_sched_once);
                 if this.sleepy {
                     // There may be an outstanding handle on the
                     // sleeper list.  Pop them all to make sure that's
@@ -395,6 +404,7 @@ impl Scheduler {
     /// Take a non-homed task we aren't allowed to run here and send
     /// it to the designated friend scheduler to execute.
     fn send_to_friend(&mut self, task: ~Task) {
+        rtdebug!("sending a task to friend");
         match self.friend_handle {
             Some(ref mut handle) => {
                 handle.send(TaskFromFriend(task));
@@ -426,12 +436,14 @@ impl Scheduler {
                             Scheduler::send_task_home(task);
                             return Some(this);
                         } else {
+                            this.event_loop.callback(Scheduler::run_sched_once);
                             task.give_home(Sched(home_handle));
                             this.resume_task_immediately(task);
                             return None;
                         }
                     }
                     AnySched if this.run_anything => {
+                        this.event_loop.callback(Scheduler::run_sched_once);
                         task.give_home(AnySched);
                         this.resume_task_immediately(task);
                         return None;
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs
index abafe1cf209..cb949edd7bb 100644
--- a/src/libstd/rt/task.rs
+++ b/src/libstd/rt/task.rs
@@ -228,6 +228,19 @@ impl Task {
                     _ => ()
                 }
 
+                // FIXME #8302: Dear diary. I'm so tired and confused.
+                // There's some interaction in rustc between the box
+                // annihilator and the TLS dtor by which TLS is
+                // accessed from annihilated box dtors *after* TLS is
+                // destroyed. Somehow setting TLS back to null, as the
+                // old runtime did, makes this work, but I don't currently
+                // understand how. I would expect that, if the annihilator
+                // reinvokes TLS while TLS is uninitialized, that
+                // TLS would be reinitialized but never destroyed,
+                // but somehow this works. I have no idea what's going
+                // on but this seems to make things magically work. FML.
+                self.storage = LocalStorage(ptr::null(), None);
+
                 // Destroy remaining boxes. Also may run user dtors.
                 unsafe { cleanup::annihilate(); }
             }
@@ -303,7 +316,7 @@ impl Task {
 impl Drop for Task {
     fn drop(&self) {
         rtdebug!("called drop for a task: %u", borrow::to_uint(self));
-        assert!(self.destroyed)
+        rtassert!(self.destroyed)
     }
 }
 
@@ -313,7 +326,7 @@ impl Drop for Task {
 impl Coroutine {
 
     pub fn new(stack_pool: &mut StackPool, start: ~fn()) -> Coroutine {
-        static MIN_STACK_SIZE: uint = 2000000; // XXX: Too much stack
+        static MIN_STACK_SIZE: uint = 3000000; // XXX: Too much stack
 
         let start = Coroutine::build_start_wrapper(start);
         let mut stack = stack_pool.take_segment(MIN_STACK_SIZE);
diff --git a/src/libstd/stackwalk.rs b/src/libstd/stackwalk.rs
deleted file mode 100644
index cc516fb559e..00000000000
--- a/src/libstd/stackwalk.rs
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-#[allow(missing_doc)];
-
-use cast::transmute;
-use unstable::intrinsics;
-
-pub type Word = uint;
-
-pub struct Frame {
-    fp: *Word
-}
-
-pub fn Frame(fp: *Word) -> Frame {
-    Frame {
-        fp: fp
-    }
-}
-
-pub fn walk_stack(visit: &fn(Frame)) {
-
-    debug!("beginning stack walk");
-
-    do frame_address |frame_pointer| {
-        let mut frame_address: *Word = unsafe {
-            transmute(frame_pointer)
-        };
-        loop {
-            let fr = Frame(frame_address);
-
-            debug!("frame: %x", unsafe { transmute(fr.fp) });
-            visit(fr);
-
-            unsafe {
-                let next_fp: **Word = transmute(frame_address);
-                frame_address = *next_fp;
-                if *frame_address == 0u {
-                    debug!("encountered task_start_wrapper. ending walk");
-                    // This is the task_start_wrapper_frame. There is
-                    // no stack beneath it and it is a foreign frame.
-                    break;
-                }
-            }
-        }
-    }
-}
-
-#[test]
-fn test_simple() {
-    do walk_stack |_frame| {
-    }
-}
-
-#[test]
-fn test_simple_deep() {
-    fn run(i: int) {
-        if i == 0 { return }
-
-        do walk_stack |_frame| {
-            // Would be nice to test something here...
-        }
-        run(i - 1);
-    }
-
-    run(10);
-}
-
-fn frame_address(f: &fn(x: *u8)) {
-    unsafe {
-        intrinsics::frame_address(f)
-    }
-}
diff --git a/src/libstd/std.rs b/src/libstd/std.rs
index d51f0de1d27..236103ec886 100644
--- a/src/libstd/std.rs
+++ b/src/libstd/std.rs
@@ -170,7 +170,6 @@ pub mod local_data;
 
 /* Runtime and platform support */
 
-pub mod gc;
 pub mod libc;
 pub mod c_str;
 pub mod os;
@@ -197,7 +196,6 @@ pub mod unstable;
 mod unicode;
 #[path = "num/cmath.rs"]
 mod cmath;
-mod stackwalk;
 
 // XXX: This shouldn't be pub, and it should be reexported under 'unstable'
 // but name resolution doesn't work without it being pub.
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index 4a5fa82a226..a77371bbfc9 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -1068,7 +1068,7 @@ pub mod raw {
         let new_len = s.len() + 1;
         s.reserve_at_least(new_len);
         do s.as_mut_buf |buf, len| {
-            *ptr::mut_offset(buf, len as int) = b;
+            *ptr::mut_offset(buf, (len-1) as int) = b;
         }
         set_len(&mut *s, new_len);
     }
@@ -3081,6 +3081,13 @@ mod tests {
     }
 
     #[test]
+    fn test_push_byte() {
+        let mut s = ~"ABC";
+        unsafe{raw::push_byte(&mut s, 'D' as u8)};
+        assert_eq!(s, ~"ABCD");
+    }
+
+    #[test]
     fn test_shift_byte() {
         let mut s = ~"ABC";
         let b = unsafe{raw::shift_byte(&mut s)};
diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs
index b40f87617a9..83ee4cf07c6 100644
--- a/src/libstd/sys.rs
+++ b/src/libstd/sys.rs
@@ -14,7 +14,6 @@
 
 use c_str::ToCStr;
 use cast;
-use gc;
 use io;
 use libc;
 use libc::{c_char, size_t};
@@ -147,7 +146,6 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
     match context {
         OldTaskContext => {
             unsafe {
-                gc::cleanup_stack_for_failure();
                 rustrt::rust_upcall_fail(msg, file, line);
                 cast::transmute(())
             }
@@ -180,8 +178,6 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
                              msg, file, line as int);
                 }
 
-                gc::cleanup_stack_for_failure();
-
                 let task = Local::unsafe_borrow::<Task>();
                 if (*task).unwinder.unwinding {
                     rtabort!("unwinding again");