about summary refs log tree commit diff
path: root/src/libcore
diff options
context:
space:
mode:
authorEric Holk <eric.holk@gmail.com>2012-06-14 11:38:45 -0700
committerEric Holk <eric.holk@gmail.com>2012-06-21 16:11:11 -0700
commit9bdb2c9e48cefc684b6163249ca816cd96350bde (patch)
treea1f34c68a5490f86915133815c1bbf8d20de88c6 /src/libcore
parent0e5cfd9f339c78384ef3fbcb4d230fa0bb363d54 (diff)
downloadrust-9bdb2c9e48cefc684b6163249ca816cd96350bde.tar.gz
rust-9bdb2c9e48cefc684b6163249ca816cd96350bde.zip
Library vecs are fast now.
Diffstat (limited to 'src/libcore')
-rw-r--r--src/libcore/dvec.rs8
-rw-r--r--src/libcore/sys.rs1
-rw-r--r--src/libcore/uint-template/uint.rs1
-rw-r--r--src/libcore/vec.rs40
4 files changed, 36 insertions, 14 deletions
diff --git a/src/libcore/dvec.rs b/src/libcore/dvec.rs
index ef368fe7a8b..d30179fd881 100644
--- a/src/libcore/dvec.rs
+++ b/src/libcore/dvec.rs
@@ -113,6 +113,7 @@ impl extensions<A> for dvec<A> {
     and return a new vector to replace it with.
 
     "]
+    #[inline(always)]
     fn swap(f: fn(-[mut A]) -> [mut A]) {
         self.borrow { |v| self.return(f(v)) }
     }
@@ -136,11 +137,8 @@ impl extensions<A> for dvec<A> {
 impl extensions<A:copy> for dvec<A> {
     #[doc = "Append a single item to the end of the list"]
     fn push(t: A) {
-        self.swap { |v|
-            let mut v <- v;
-            vec::push(v, t);
-            v
-        }
+        self.check_not_borrowed();
+        vec::push(self.data, t);
     }
 
     #[doc = "Remove and return the last element"]
diff --git a/src/libcore/sys.rs b/src/libcore/sys.rs
index 1e4e5b17bb9..77207d8aebf 100644
--- a/src/libcore/sys.rs
+++ b/src/libcore/sys.rs
@@ -51,6 +51,7 @@ pure fn get_type_desc<T>() -> *type_desc {
 }
 
 #[doc = "Returns the size of a type"]
+#[inline(always)]
 pure fn size_of<T>() -> uint unsafe {
     unchecked { rusti::size_of::<T>() }
 }
diff --git a/src/libcore/uint-template/uint.rs b/src/libcore/uint-template/uint.rs
index e1bb89c27c4..843215bd4b9 100644
--- a/src/libcore/uint-template/uint.rs
+++ b/src/libcore/uint-template/uint.rs
@@ -81,6 +81,7 @@ fn iterate(lo: uint, hi: uint, it: fn(uint) -> bool) -> bool {
 }
 
 #[doc = "Returns the smallest power of 2 greater than or equal to `n`"]
+#[inline(always)]
 fn next_power_of_two(n: uint) -> uint {
     let halfbits: uint = sys::size_of::<uint>() * 4u;
     let mut tmp: uint = n - 1u;
diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs
index a1b2ee23f0f..c029e9f2448 100644
--- a/src/libcore/vec.rs
+++ b/src/libcore/vec.rs
@@ -92,6 +92,11 @@ native mod rustrt {
                            ++count: libc::size_t) -> *unsafe::vec_repr;
 }
 
+#[abi = "rust-intrinsic"]
+native mod rusti {
+    fn move_val_init<T>(&dst: T, -src: T);
+}
+
 #[doc = "A function used to initialize the elements of a vector"]
 type init_op<T> = fn(uint) -> T;
 
@@ -392,17 +397,33 @@ fn pop<T>(&v: [const T]) -> T unsafe {
 #[doc = "Append an element to a vector"]
 #[inline(always)]
 fn push<T>(&v: [const T], +initval: T) {
-    let ln = v.len();
     unsafe {
-        reserve_at_least(v, ln + 1u);
-        unsafe::set_len(v, ln + 1u);
-        let p = ptr::mut_addr_of(v[ln]);
+        let repr: **unsafe::vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
+        let fill = (**repr).fill;
+        if (**repr).alloc > fill {
+            let sz = sys::size_of::<T>();
+            (**repr).fill += sz;
+            let p = ptr::addr_of((**repr).data);
+            let p = ptr::offset(p, fill) as *mut T;
+            rusti::move_val_init(*p, initval);
+        }
+        else {
+            push_slow(v, initval);
+        }
+    }
+}
 
-        // FIXME: for performance, try replacing the memmove and <- with a
-        // memset and unsafe::forget.
-        ptr::memset(p, 0, 1u); // needed to stop drop glue from running on
-                               // garbage data.
-        *p = initval;
+fn push_slow<T>(&v: [const T], +initval: T) {
+    unsafe {
+        let ln = v.len();
+        reserve_at_least(v, ln + 1u);
+        let repr: **unsafe::vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
+        let fill = (**repr).fill;
+        let sz = sys::size_of::<T>();
+        (**repr).fill += sz;
+        let p = ptr::addr_of((**repr).data);
+        let p = ptr::offset(p, fill) as *mut T;
+        rusti::move_val_init(*p, initval);
     }
 }
 
@@ -497,6 +518,7 @@ Sets the element at position `index` to `val`. If `index` is past the end
 of the vector, expands the vector by replicating `initval` to fill the
 intervening space.
 "]
+#[inline(always)]
 fn grow_set<T: copy>(&v: [mut T], index: uint, initval: T, val: T) {
     if index >= len(v) { grow(v, index - len(v) + 1u, initval); }
     v[index] = val;