about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/cleanup.rs116
-rw-r--r--src/libstd/rt/comm.rs12
-rw-r--r--src/libstd/rt/local_heap.rs50
-rw-r--r--src/libstd/rt/mod.rs2
-rw-r--r--src/libstd/rt/task.rs21
-rw-r--r--src/libstd/sys.rs5
-rw-r--r--src/libstd/unstable/lang.rs19
7 files changed, 94 insertions, 131 deletions
diff --git a/src/libstd/cleanup.rs b/src/libstd/cleanup.rs
index dd7e85ce7e1..36c1fdf781b 100644
--- a/src/libstd/cleanup.rs
+++ b/src/libstd/cleanup.rs
@@ -13,107 +13,14 @@
 use libc::{c_char, c_void, intptr_t, uintptr_t};
 use ptr::mut_null;
 use repr::BoxRepr;
+use rt;
+use rt::OldTaskContext;
 use sys::TypeDesc;
 use cast::transmute;
-#[cfg(not(test))] use rt::borrowck::clear_task_borrow_list;
 
 #[cfg(not(test))] use ptr::to_unsafe_ptr;
 
-/**
- * Runtime structures
- *
- * NB: These must match the representation in the C++ runtime.
- */
-
 type DropGlue<'self> = &'self fn(**TypeDesc, *c_void);
-type FreeGlue<'self> = &'self fn(**TypeDesc, *c_void);
-
-type TaskID = uintptr_t;
-
-struct StackSegment { priv opaque: () }
-struct Scheduler { priv opaque: () }
-struct SchedulerLoop { priv opaque: () }
-struct Kernel { priv opaque: () }
-struct Env { priv opaque: () }
-struct AllocHeader { priv opaque: () }
-struct MemoryRegion { priv opaque: () }
-
-#[cfg(target_arch="x86")]
-struct Registers {
-    data: [u32, ..16]
-}
-
-#[cfg(target_arch="arm")]
-#[cfg(target_arch="mips")]
-struct Registers {
-    data: [u32, ..32]
-}
-
-#[cfg(target_arch="x86")]
-#[cfg(target_arch="arm")]
-#[cfg(target_arch="mips")]
-struct Context {
-    regs: Registers,
-    next: *Context,
-    pad: [u32, ..3]
-}
-
-#[cfg(target_arch="x86_64")]
-struct Registers {
-    data: [u64, ..22]
-}
-
-#[cfg(target_arch="x86_64")]
-struct Context {
-    regs: Registers,
-    next: *Context,
-    pad: uintptr_t
-}
-
-struct BoxedRegion {
-    env: *Env,
-    backing_region: *MemoryRegion,
-    live_allocs: *BoxRepr
-}
-
-#[cfg(target_arch="x86")]
-#[cfg(target_arch="arm")]
-#[cfg(target_arch="mips")]
-struct Task {
-    // Public fields
-    refcount: intptr_t,                 // 0
-    id: TaskID,                         // 4
-    pad: [u32, ..2],                    // 8
-    ctx: Context,                       // 16
-    stack_segment: *StackSegment,       // 96
-    runtime_sp: uintptr_t,              // 100
-    scheduler: *Scheduler,              // 104
-    scheduler_loop: *SchedulerLoop,     // 108
-
-    // Fields known only to the runtime
-    kernel: *Kernel,                    // 112
-    name: *c_char,                      // 116
-    list_index: i32,                    // 120
-    boxed_region: BoxedRegion           // 128
-}
-
-#[cfg(target_arch="x86_64")]
-struct Task {
-    // Public fields
-    refcount: intptr_t,
-    id: TaskID,
-    ctx: Context,
-    stack_segment: *StackSegment,
-    runtime_sp: uintptr_t,
-    scheduler: *Scheduler,
-    scheduler_loop: *SchedulerLoop,
-
-    // Fields known only to the runtime
-    kernel: *Kernel,
-    name: *c_char,
-    list_index: i32,
-    boxed_region: BoxedRegion
-}
 
 /*
  * Box annihilation
@@ -132,9 +39,9 @@ unsafe fn each_live_alloc(read_next_before: bool,
     //! Walks the internal list of allocations
 
     use managed;
+    use rt::local_heap;
 
-    let task: *Task = transmute(rustrt::rust_get_task());
-    let box = (*task).boxed_region.live_allocs;
+    let box = local_heap::live_allocs();
     let mut box: *mut BoxRepr = transmute(copy box);
     while box != mut_null() {
         let next_before = transmute(copy (*box).header.next);
@@ -156,7 +63,11 @@ unsafe fn each_live_alloc(read_next_before: bool,
 
 #[cfg(unix)]
 fn debug_mem() -> bool {
-    ::rt::env::get().debug_mem
+    // XXX: Need to port the environment struct to newsched
+    match rt::context() {
+        OldTaskContext => ::rt::env::get().debug_mem,
+        _ => false
+    }
 }
 
 #[cfg(windows)]
@@ -165,13 +76,12 @@ fn debug_mem() -> bool {
 }
 
 /// Destroys all managed memory (i.e. @ boxes) held by the current task.
-#[cfg(not(test))]
-#[lang="annihilate"]
 pub unsafe fn annihilate() {
-    use unstable::lang::local_free;
+    use rt::local_heap::local_free;
     use io::WriterUtil;
     use io;
     use libc;
+    use rt::borrowck;
     use sys;
     use managed;
 
@@ -183,7 +93,7 @@ pub unsafe fn annihilate() {
 
     // Quick hack: we need to free this list upon task exit, and this
     // is a convenient place to do it.
-    clear_task_borrow_list();
+    borrowck::clear_task_borrow_list();
 
     // Pass 1: Make all boxes immortal.
     //
@@ -207,7 +117,7 @@ pub unsafe fn annihilate() {
         if !uniq {
             let tydesc: *TypeDesc = transmute(copy (*box).header.type_desc);
             let drop_glue: DropGlue = transmute(((*tydesc).drop_glue, 0));
-            drop_glue(to_unsafe_ptr(&tydesc), transmute(&(*box).data));
+            drop_glue(&tydesc, transmute(&(*box).data));
         }
     }
 
diff --git a/src/libstd/rt/comm.rs b/src/libstd/rt/comm.rs
index 82e6d44fe62..dd27c03ff51 100644
--- a/src/libstd/rt/comm.rs
+++ b/src/libstd/rt/comm.rs
@@ -399,12 +399,6 @@ impl<T: Owned> GenericChan<T> for SharedChan<T> {
 }
 
 impl<T: Owned> GenericSmartChan<T> for SharedChan<T> {
-    #[cfg(stage0)] // odd type checking errors
-    fn try_send(&self, _val: T) -> bool {
-        fail!()
-    }
-
-    #[cfg(not(stage0))]
     fn try_send(&self, val: T) -> bool {
         unsafe {
             let (next_pone, next_cone) = oneshot();
@@ -448,12 +442,6 @@ impl<T: Owned> GenericPort<T> for SharedPort<T> {
         }
     }
 
-    #[cfg(stage0)] // odd type checking errors
-    fn try_recv(&self) -> Option<T> {
-        fail!()
-    }
-
-    #[cfg(not(stage0))]
     fn try_recv(&self) -> Option<T> {
         unsafe {
             let (next_link_port, next_link_chan) = oneshot();
diff --git a/src/libstd/rt/local_heap.rs b/src/libstd/rt/local_heap.rs
index 38cd25f9da5..f62c9fb2c66 100644
--- a/src/libstd/rt/local_heap.rs
+++ b/src/libstd/rt/local_heap.rs
@@ -10,11 +10,24 @@
 
 //! The local, garbage collected heap
 
+use libc;
 use libc::{c_void, uintptr_t, size_t};
 use ops::Drop;
+use repr::BoxRepr;
+use rt;
+use rt::OldTaskContext;
+use rt::local::Local;
+use rt::task::Task;
 
 type MemoryRegion = c_void;
-type BoxedRegion = c_void;
+
+struct Env { priv opaque: () }
+
+struct BoxedRegion {
+    env: *Env,
+    backing_region: *MemoryRegion,
+    live_allocs: *BoxRepr
+}
 
 pub type OpaqueBox = c_void;
 pub type TypeDesc = c_void;
@@ -71,6 +84,40 @@ impl Drop for LocalHeap {
     }
 }
 
+// A little compatibility function
+pub unsafe fn local_free(ptr: *libc::c_char) {
+    match rt::context() {
+        OldTaskContext => {
+            rust_upcall_free_noswitch(ptr);
+
+            extern {
+                #[fast_ffi]
+                unsafe fn rust_upcall_free_noswitch(ptr: *libc::c_char);
+            }
+        }
+        _ => {
+            do Local::borrow::<Task,()> |task| {
+                task.heap.free(ptr as *libc::c_void);
+            }
+        }
+    }
+}
+
+pub fn live_allocs() -> *BoxRepr {
+    let region = match rt::context() {
+        OldTaskContext => {
+            unsafe { rust_current_boxed_region() }
+        }
+        _ => {
+            do Local::borrow::<Task, *BoxedRegion> |task| {
+                task.heap.boxed_region
+            }
+        }
+    };
+
+    return unsafe { (*region).live_allocs };
+}
+
 extern {
     fn rust_new_memory_region(synchronized: uintptr_t,
                                detailed_leaks: uintptr_t,
@@ -86,4 +133,5 @@ extern {
                                  ptr: *OpaqueBox,
                                  size: size_t) -> *OpaqueBox;
     fn rust_boxed_region_free(region: *BoxedRegion, box: *OpaqueBox);
+    fn rust_current_boxed_region() -> *BoxedRegion;
 }
diff --git a/src/libstd/rt/mod.rs b/src/libstd/rt/mod.rs
index 6c4e5742eb3..fec555e8afd 100644
--- a/src/libstd/rt/mod.rs
+++ b/src/libstd/rt/mod.rs
@@ -124,7 +124,7 @@ mod thread;
 pub mod env;
 
 /// The local, managed heap
-mod local_heap;
+pub mod local_heap;
 
 /// The Logger trait and implementations
 pub mod logging;
diff --git a/src/libstd/rt/task.rs b/src/libstd/rt/task.rs
index 833f25b253c..68f7eb659b0 100644
--- a/src/libstd/rt/task.rs
+++ b/src/libstd/rt/task.rs
@@ -15,6 +15,7 @@
 
 use borrow;
 use cast::transmute;
+use cleanup;
 use libc::{c_void, uintptr_t};
 use ptr;
 use prelude::*;
@@ -118,6 +119,10 @@ impl Task {
             }
             _ => ()
         }
+
+        // Destroy remaining boxes
+        unsafe { cleanup::annihilate(); }
+
         self.destroyed = true;
     }
 }
@@ -269,4 +274,20 @@ mod test {
             assert!(res.is_err());
         }
     }
+
+    #[test]
+    fn heap_cycles() {
+        use option::{Option, Some, None};
+
+        do run_in_newsched_task {
+            struct List {
+                next: Option<@mut List>,
+            }
+
+            let a = @mut List { next: None };
+            let b = @mut List { next: Some(a) };
+
+            a.next = Some(b);
+        }
+    }
 }
diff --git a/src/libstd/sys.rs b/src/libstd/sys.rs
index 8ac60ffb979..523c5d633cf 100644
--- a/src/libstd/sys.rs
+++ b/src/libstd/sys.rs
@@ -216,12 +216,15 @@ pub fn begin_unwind_(msg: *c_char, file: *c_char, line: size_t) -> ! {
                         task.logger.log(Left(outmsg.take()));
                     }
                 } else {
-                    rtdebug!("%s", outmsg);
+                    rterrln!("%s", outmsg);
                 }
 
                 gc::cleanup_stack_for_failure();
 
                 let task = Local::unsafe_borrow::<Task>();
+                if (*task).unwinder.unwinding {
+                    rtabort!("unwinding again");
+                }
                 (*task).unwinder.begin_unwind();
             }
         }
diff --git a/src/libstd/unstable/lang.rs b/src/libstd/unstable/lang.rs
index d71a672eb35..f750b31a466 100644
--- a/src/libstd/unstable/lang.rs
+++ b/src/libstd/unstable/lang.rs
@@ -43,9 +43,6 @@ pub mod rustrt {
                                               size: uintptr_t)
                                            -> *c_char;
 
-        #[fast_ffi]
-        unsafe fn rust_upcall_free_noswitch(ptr: *c_char);
-
         #[rust_stack]
         fn rust_try_get_task() -> *rust_task;
 
@@ -105,16 +102,7 @@ pub unsafe fn local_malloc(td: *c_char, size: uintptr_t) -> *c_char {
 // problem occurs, call exit instead.
 #[lang="free"]
 pub unsafe fn local_free(ptr: *c_char) {
-    match context() {
-        OldTaskContext => {
-            rustrt::rust_upcall_free_noswitch(ptr);
-        }
-        _ => {
-            do Local::borrow::<Task,()> |task| {
-                task.heap.free(ptr as *c_void);
-            }
-        }
-    }
+    ::rt::local_heap::local_free(ptr);
 }
 
 #[lang="borrow_as_imm"]
@@ -162,6 +150,11 @@ pub unsafe fn strdup_uniq(ptr: *c_uchar, len: uint) -> ~str {
     str::raw::from_buf_len(ptr, len)
 }
 
+#[lang="annihilate"]
+pub unsafe fn annihilate() {
+    ::cleanup::annihilate()
+}
+
 #[lang="start"]
 pub fn start(main: *u8, argc: int, argv: **c_char,
              crate_map: *u8) -> int {