about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorTim Chevalier <chevalier@alum.wellesley.edu>2012-10-05 14:58:42 -0700
committerTim Chevalier <chevalier@alum.wellesley.edu>2012-10-05 15:37:01 -0700
commite16dbb7888504ef5d0de0c14493fc8ecc492ee30 (patch)
tree80c1bde3c3f3b0cf47993dfe769418cc2ac55323 /src/libstd
parente3cb70fa8a6f9163352f26ae2614ab4c9a261838 (diff)
downloadrust-e16dbb7888504ef5d0de0c14493fc8ecc492ee30.tar.gz
rust-e16dbb7888504ef5d0de0c14493fc8ecc492ee30.zip
Demode some code using by-mutbl-ref; warn about by-mutbl-ref
The parser now warns about use of mutbl-ref mode, though it's kind
of a lie since this commit doesn't remove support for the mode.

Changed move_val_init to have stage0 and stage1/2 versions, the latter of
which is demoded.

Changed the type that the typechecker expects the move_val_init
intrinsic to have. After this is pushed, I can make a new snapshot,
which will remove the need for the stage0 versions.
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/arena.rs115
1 files changed, 115 insertions, 0 deletions
diff --git a/src/libstd/arena.rs b/src/libstd/arena.rs
index 4d2b910fa85..69478b3e731 100644
--- a/src/libstd/arena.rs
+++ b/src/libstd/arena.rs
@@ -31,9 +31,14 @@ use libc::size_t;
 
 #[abi = "rust-intrinsic"]
 extern mod rusti {
+    #[cfg(stage0)]
     fn move_val_init<T>(&dst: T, -src: T);
+    #[cfg(stage1)]
+    #[cfg(stage2)]
+    fn move_val_init<T>(dst: &mut T, -src: T);
     fn needs_drop<T>() -> bool;
 }
+
 extern mod rustrt {
     #[rust_stack]
     fn rust_call_tydesc_glue(root: *u8, tydesc: *TypeDesc, field: size_t);
@@ -127,6 +132,8 @@ unsafe fn un_bitpack_tydesc_ptr(p: uint) -> (*TypeDesc, bool) {
     (reinterpret_cast(&(p & !1)), p & 1 == 1)
 }
 
+// tjc: Can get rid of the duplication post-snapshot
+#[cfg(stage0)]
 // The duplication between the POD and non-POD functions is annoying.
 impl &Arena {
     // Functions for the POD part of the arena
@@ -234,6 +241,114 @@ impl &Arena {
         } else { self.alloc_nonpod(op) }
     }
 }
+#[cfg(stage1)]
+#[cfg(stage2)]
+impl &Arena {
+    // Functions for the POD part of the arena
+    fn alloc_pod_grow(n_bytes: uint, align: uint) -> *u8 {
+        // Allocate a new chunk.
+        let chunk_size = at_vec::capacity(self.pod_head.data);
+        let new_min_chunk_size = uint::max(n_bytes, chunk_size);
+        self.chunks = @Cons(copy self.pod_head, self.chunks);
+        self.pod_head =
+            chunk(uint::next_power_of_two(new_min_chunk_size + 1u), true);
+
+        return self.alloc_pod_inner(n_bytes, align);
+    }
+
+    #[inline(always)]
+    fn alloc_pod_inner(n_bytes: uint, align: uint) -> *u8 {
+        let head = &mut self.pod_head;
+
+        let start = round_up_to(head.fill, align);
+        let end = start + n_bytes;
+        if end > at_vec::capacity(head.data) {
+            return self.alloc_pod_grow(n_bytes, align);
+        }
+        head.fill = end;
+
+        //debug!("idx = %u, size = %u, align = %u, fill = %u",
+        //       start, n_bytes, align, head.fill);
+
+        unsafe {
+            ptr::offset(vec::raw::to_ptr(head.data), start)
+        }
+    }
+
+    #[inline(always)]
+    fn alloc_pod<T>(op: fn() -> T) -> &self/T {
+        unsafe {
+            let tydesc = sys::get_type_desc::<T>();
+            let ptr = self.alloc_pod_inner((*tydesc).size, (*tydesc).align);
+            let ptr: *mut T = reinterpret_cast(&ptr);
+            rusti::move_val_init(&mut (*ptr), op());
+            return reinterpret_cast(&ptr);
+        }
+    }
+
+    // Functions for the non-POD part of the arena
+    fn alloc_nonpod_grow(n_bytes: uint, align: uint) -> (*u8, *u8) {
+        // Allocate a new chunk.
+        let chunk_size = at_vec::capacity(self.head.data);
+        let new_min_chunk_size = uint::max(n_bytes, chunk_size);
+        self.chunks = @Cons(copy self.head, self.chunks);
+        self.head =
+            chunk(uint::next_power_of_two(new_min_chunk_size + 1u), false);
+
+        return self.alloc_nonpod_inner(n_bytes, align);
+    }
+
+    #[inline(always)]
+    fn alloc_nonpod_inner(n_bytes: uint, align: uint) -> (*u8, *u8) {
+        let head = &mut self.head;
+
+        let tydesc_start = head.fill;
+        let after_tydesc = head.fill + sys::size_of::<*TypeDesc>();
+        let start = round_up_to(after_tydesc, align);
+        let end = start + n_bytes;
+        if end > at_vec::capacity(head.data) {
+            return self.alloc_nonpod_grow(n_bytes, align);
+        }
+        head.fill = round_up_to(end, sys::pref_align_of::<*TypeDesc>());
+
+        //debug!("idx = %u, size = %u, align = %u, fill = %u",
+        //       start, n_bytes, align, head.fill);
+
+        unsafe {
+            let buf = vec::raw::to_ptr(head.data);
+            return (ptr::offset(buf, tydesc_start), ptr::offset(buf, start));
+        }
+    }
+
+    #[inline(always)]
+    fn alloc_nonpod<T>(op: fn() -> T) -> &self/T {
+        unsafe {
+            let tydesc = sys::get_type_desc::<T>();
+            let (ty_ptr, ptr) =
+                self.alloc_nonpod_inner((*tydesc).size, (*tydesc).align);
+            let ty_ptr: *mut uint = reinterpret_cast(&ty_ptr);
+            let ptr: *mut T = reinterpret_cast(&ptr);
+            // Write in our tydesc along with a bit indicating that it
+            // has *not* been initialized yet.
+            *ty_ptr = reinterpret_cast(&tydesc);
+            // Actually initialize it
+            rusti::move_val_init(&mut(*ptr), op());
+            // Now that we are done, update the tydesc to indicate that
+            // the object is there.
+            *ty_ptr = bitpack_tydesc_ptr(tydesc, true);
+
+            return reinterpret_cast(&ptr);
+        }
+    }
+
+    // The external interface
+    #[inline(always)]
+    fn alloc<T>(op: fn() -> T) -> &self/T {
+        if !rusti::needs_drop::<T>() {
+            self.alloc_pod(op)
+        } else { self.alloc_nonpod(op) }
+    }
+}
 
 #[test]
 fn test_arena_destructors() {