about summary refs log tree commit diff
path: root/src/rt
diff options
context:
space:
mode:
authorMarijn Haverbeke <marijnh@gmail.com>2011-08-24 13:53:34 +0200
committerMarijn Haverbeke <marijnh@gmail.com>2011-08-24 13:57:27 +0200
commite58c48bddae60e21dc8958407dadf6d187b78ea9 (patch)
tree9e56cc68bbabf7e8904f321112341e5a389fc143 /src/rt
parentbead045f2724e3a256a2123a844b079f82047dd4 (diff)
downloadrust-e58c48bddae60e21dc8958407dadf6d187b78ea9.tar.gz
rust-e58c48bddae60e21dc8958407dadf6d187b78ea9.zip
Optimize += [x] into a simple push operation
This is a preparation for making vectors always-on-the-heap again,
which would cause way too much malloc traffic for this idiom. I will
add an efficient std::vec::push in the future, and migrate += [x] to
that instead.

Reduces compiler code size by 3%
Diffstat (limited to 'src/rt')
-rw-r--r--src/rt/rust_upcall.cpp24
-rw-r--r--src/rt/rustrt.def.in1
2 files changed, 25 insertions, 0 deletions
diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp
index 622baad32c9..174855cac23 100644
--- a/src/rt/rust_upcall.cpp
+++ b/src/rt/rust_upcall.cpp
@@ -394,6 +394,30 @@ upcall_ivec_spill_shared(rust_task *task,
     v->payload.ptr = heap_part;
 }
 
+extern "C" CDECL void
+upcall_ivec_push(rust_task* task, rust_ivec* v, type_desc* elt_ty, void* x) {
+    LOG_UPCALL_ENTRY(task);
+    bool is_interior = v->fill || !v->payload.ptr;
+    size_t sz = elt_ty->size;
+    size_t old_fill = is_interior ? v->fill : v->payload.ptr->fill;
+    size_t new_sz = sz + old_fill;
+    if (new_sz > v->alloc) {
+        if (is_interior) {
+            upcall_ivec_spill_shared(task, v, new_sz);
+            is_interior = false;
+        } else {
+            upcall_ivec_resize_shared(task, v, new_sz);
+        }
+    } else {
+        if (is_interior) v->fill = new_sz;
+        else v->payload.ptr->fill = new_sz;
+    }
+    uint8_t* dataptr = is_interior ? &v->payload.data[0]
+                                   : &v->payload.ptr->data[0];
+    copy_elements(task, elt_ty, dataptr + old_fill, x, sz);
+}
+
+
 /**
  * Returns a token that can be used to deallocate all of the allocated space
  * space in the dynamic stack.
diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in
index 58aa681f633..a3ecebf22a9 100644
--- a/src/rt/rustrt.def.in
+++ b/src/rt/rustrt.def.in
@@ -89,6 +89,7 @@ upcall_get_type_desc
 upcall_grow_task
 upcall_ivec_resize_shared
 upcall_ivec_spill_shared
+upcall_ivec_push
 upcall_kill
 upcall_log_double
 upcall_log_float