about summary refs log tree commit diff
path: root/src/rt/rust_builtin.cpp
diff options
context:
space:
mode:
authorRob Arnold <robarnold@cs.cmu.edu>2011-07-05 22:55:41 -0700
committerRob Arnold <robarnold@cs.cmu.edu>2011-07-06 20:41:24 -0700
commitf6117173c9f26efdcf50cb664d006ea2bdf0d0cb (patch)
tree04f20cc1e1a057d520b9329e343ef6b63ddb52e9 /src/rt/rust_builtin.cpp
parent2e2e1f7cb36aeac0abb730a752fcd78cf91a380f (diff)
downloadrust-f6117173c9f26efdcf50cb664d006ea2bdf0d0cb.tar.gz
rust-f6117173c9f26efdcf50cb664d006ea2bdf0d0cb.zip
Allocate rust_ivec buffers out of the kernel pool
The duplication of upcalls is due to the fact that the runtime is
shared between stage0/rustc and stage1/rustc. Once snapshots are
updated, they should be de-duplicated.
Diffstat (limited to 'src/rt/rust_builtin.cpp')
-rw-r--r--src/rt/rust_builtin.cpp60
1 files changed, 60 insertions, 0 deletions
diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp
index 6438c549c55..872a317ca38 100644
--- a/src/rt/rust_builtin.cpp
+++ b/src/rt/rust_builtin.cpp
@@ -649,6 +649,37 @@ ivec_reserve(rust_task *task, type_desc *ty, rust_ivec *v, size_t n_elems)
 }
 
 /**
+ * Preallocates the exact number of bytes in the given interior vector.
+ */
+extern "C" CDECL void
+ivec_reserve_shared(rust_task *task, type_desc *ty, rust_ivec *v,
+                    size_t n_elems)
+{
+    size_t new_alloc = n_elems * ty->size;
+    if (new_alloc <= v->alloc)
+        return;     // Already big enough.
+
+    rust_ivec_heap *heap_part;
+    if (v->fill || !v->payload.ptr) {
+        // On stack; spill to heap.
+        heap_part = (rust_ivec_heap *)task->kernel->malloc(new_alloc +
+                                                           sizeof(size_t));
+        heap_part->fill = v->fill;
+        memcpy(&heap_part->data, v->payload.data, v->fill);
+
+        v->fill = 0;
+        v->payload.ptr = heap_part;
+    } else {
+        // On heap; resize.
+        heap_part = (rust_ivec_heap *)task->kernel->realloc(v->payload.ptr,
+                                                new_alloc + sizeof(size_t));
+        v->payload.ptr = heap_part;
+    }
+
+    v->alloc = new_alloc;
+}
+
+/**
  * Returns true if the given vector is on the heap and false if it's on the
  * stack.
  */
@@ -706,6 +737,35 @@ ivec_copy_from_buf(rust_task *task, type_desc *ty, rust_ivec *v, void *ptr,
     v->payload.ptr->fill = new_size;
 }
 
+/**
+ * Copies elements in an unsafe buffer to the given interior vector. The
+ * vector must have size zero.
+ */
+extern "C" CDECL void
+ivec_copy_from_buf_shared(rust_task *task, type_desc *ty, rust_ivec *v,
+                   void *ptr, size_t count)
+{
+    size_t old_size = get_ivec_size(v);
+    if (old_size) {
+        task->fail(1);
+        return;
+    }
+
+    ivec_reserve_shared(task, ty, v, count);
+
+    size_t new_size = count * ty->size;
+    if (v->fill || !v->payload.ptr) {
+        // On stack.
+        memmove(v->payload.data, ptr, new_size);
+        v->fill = new_size;
+        return;
+    }
+
+    // On heap.
+    memmove(v->payload.ptr->data, ptr, new_size);
+    v->payload.ptr->fill = new_size;
+}
+
 extern "C" CDECL void
 pin_task(rust_task *task) {
     task->pin();