about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@mimiga.net>2011-08-17 18:14:47 -0700
committerPatrick Walton <pcwalton@mimiga.net>2011-08-17 18:14:57 -0700
commitf17edf9829e88090445a7f8b3e74979ca08ecfa0 (patch)
treefd90dd7fc3cbba3c4aa6efd9cb64525bb359807c
parent0b7af403843d54c3200f8f9accbd2b279d6a7a0c (diff)
downloadrust-f17edf9829e88090445a7f8b3e74979ca08ecfa0.tar.gz
rust-f17edf9829e88090445a7f8b3e74979ca08ecfa0.zip
rustc: Use obstacks in lieu of dynamically-allocated frames only when the frame is actually dynamically-sized
-rw-r--r--src/comp/middle/trans.rs19
-rw-r--r--src/comp/middle/trans_common.rs1
-rw-r--r--src/rt/rust_obstack.cpp24
-rw-r--r--src/rt/rust_shape.cpp25
-rw-r--r--src/rt/rust_upcall.cpp2
-rw-r--r--src/rt/rust_util.h10
6 files changed, 57 insertions, 24 deletions
diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs
index 8ecac617e19..9d797db2ee9 100644
--- a/src/comp/middle/trans.rs
+++ b/src/comp/middle/trans.rs
@@ -466,17 +466,28 @@ fn alloca(cx: &@block_ctxt, t: TypeRef) -> ValueRef {
 }
 
 fn array_alloca(cx: &@block_ctxt, t: TypeRef, n: ValueRef) -> ValueRef {
+    let bcx = cx;
     let builder = new_builder(cx.fcx.lldynamicallocas);
+    let lltaskptr = bcx_fcx(bcx).lltaskptr;
     alt bcx_fcx(cx).llobstacktoken {
         none. {
-            let dynastack_mark = bcx_ccx(cx).upcalls.dynastack_mark;
-            let lltaskptr = bcx_fcx(cx).lltaskptr;
             bcx_fcx(cx).llobstacktoken =
-                some(builder.Call(dynastack_mark, ~[lltaskptr]));
+                some(mk_obstack_token(bcx_ccx(cx), cx.fcx.lldynamicallocas,
+                                      lltaskptr));
         }
         some(_) { /* no-op */ }
     }
-    ret builder.ArrayAlloca(t, n);
+
+    let dynastack_alloc = bcx_ccx(bcx).upcalls.dynastack_alloc;
+    let llsz = builder.Mul(C_uint(llsize_of_real(bcx_ccx(bcx), t)), n);
+    let llresult = builder.Call(dynastack_alloc, ~[lltaskptr, llsz]);
+    ret builder.PointerCast(llresult, T_ptr(t));
+}
+
+fn mk_obstack_token(ccx: &@crate_ctxt, lldynamicallocas: BasicBlockRef,
+                    lltaskptr: ValueRef) -> ValueRef {
+    let builder = new_builder(lldynamicallocas);
+    ret builder.Call(ccx.upcalls.dynastack_mark, ~[lltaskptr]);
 }
 
 
diff --git a/src/comp/middle/trans_common.rs b/src/comp/middle/trans_common.rs
index 2285aeefc8f..d37e01f573c 100644
--- a/src/comp/middle/trans_common.rs
+++ b/src/comp/middle/trans_common.rs
@@ -217,7 +217,6 @@ type fn_ctxt = {
     mutable llreturn: BasicBlockRef,
 
     // The token used to clear the dynamic allocas at the end of this frame.
-    // Will be |none| if there are no dynamic allocas.
     mutable llobstacktoken: option::t<ValueRef>,
 
     // The 'self' object currently in use in this function, if there
diff --git a/src/rt/rust_obstack.cpp b/src/rt/rust_obstack.cpp
index 5ec996f4e32..f76a80aada9 100644
--- a/src/rt/rust_obstack.cpp
+++ b/src/rt/rust_obstack.cpp
@@ -14,7 +14,12 @@
 #undef max
 #endif
 
-const size_t DEFAULT_CHUNK_SIZE = 4096;
+//#define DPRINT(fmt,...)     fprintf(stderr, fmt, ##__VA_ARGS__)
+#define DPRINT(fmt,...)
+
+//const size_t DEFAULT_CHUNK_SIZE = 4096;
+const size_t DEFAULT_CHUNK_SIZE = 300000;
+const size_t DEFAULT_ALIGNMENT = 16;
 
 struct rust_obstack_chunk {
     rust_obstack_chunk *prev;
@@ -32,8 +37,13 @@ struct rust_obstack_chunk {
 
 void *
 rust_obstack_chunk::alloc(size_t len) {
-    if (len > size - alen)
+    alen = align_to(alen, DEFAULT_ALIGNMENT);
+
+    if (len > size - alen) {
+        DPRINT("Not enough space, len=%lu!\n", len);
+        assert(0);
         return NULL;    // Not enough space.
+    }
     void *result = data + alen;
     alen += len;
     return result;
@@ -42,7 +52,7 @@ rust_obstack_chunk::alloc(size_t len) {
 bool
 rust_obstack_chunk::free(void *ptr) {
     uint8_t *p = (uint8_t *)ptr;
-    if (p < data || p >= data + size)
+    if (p < data || p > data + size)
         return false;
     assert(p <= data + alen);
     alen = (size_t)(p - data);
@@ -54,6 +64,7 @@ void *
 rust_obstack::alloc_new(size_t len) {
     size_t chunk_size = std::max(len, DEFAULT_CHUNK_SIZE);
     void *ptr = task->malloc(sizeof(chunk) + chunk_size, "obstack");
+    DPRINT("making new chunk at %p, len %lu\n", ptr, chunk_size);
     chunk = new(ptr) rust_obstack_chunk(chunk, chunk_size);
     return chunk->alloc(len);
 }
@@ -70,8 +81,12 @@ void *
 rust_obstack::alloc(size_t len) {
     if (!chunk)
         return alloc_new(len);
+
+    DPRINT("alloc sz %u", (uint32_t)len);
+
     void *ptr = chunk->alloc(len);
     ptr = ptr ? ptr : alloc_new(len);
+
     return ptr;
 }
 
@@ -80,8 +95,11 @@ rust_obstack::free(void *ptr) {
     if (!ptr)
         return;
 
+    DPRINT("free ptr %p\n", ptr);
+
     assert(chunk);
     while (!chunk->free(ptr)) {
+        DPRINT("deleting chunk at %p\n", chunk);
         rust_obstack_chunk *prev = chunk->prev;
         task->free(chunk);
         chunk = prev;
diff --git a/src/rt/rust_shape.cpp b/src/rt/rust_shape.cpp
index c23d3aaa858..e5b96e7e91f 100644
--- a/src/rt/rust_shape.cpp
+++ b/src/rt/rust_shape.cpp
@@ -64,18 +64,6 @@ const uint8_t CMP_LT = 1u;
 const uint8_t CMP_LE = 2u;
 
 
-// Utility functions
-
-// Rounds |size| to the nearest |alignment|. Invariant: |alignment| is a power
-// of two.
-template<typename T>
-static inline T
-align_to(T size, size_t alignment) {
-    assert(alignment);
-    T x = (T)(((uintptr_t)size + alignment - 1) & ~(alignment - 1));
-    return x;
-}
-
 // Utility classes
 
 struct size_align {
@@ -185,11 +173,18 @@ public:
     }
 };
 
-inline ptr_pair
-align_to(const ptr_pair &pair, size_t n) {
-    return ptr_pair::make(align_to(pair.fst, n), align_to(pair.snd, n));
+}   // end namespace shape
+
+
+inline shape::ptr_pair
+align_to(const shape::ptr_pair &pair, size_t n) {
+    return shape::ptr_pair::make(align_to(pair.fst, n),
+                                 align_to(pair.snd, n));
 }
 
+
+namespace shape {
+
 // NB: This function does not align.
 template<typename T>
 inline data_pair<T>
diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp
index d04de59a4df..ac99f501f25 100644
--- a/src/rt/rust_upcall.cpp
+++ b/src/rt/rust_upcall.cpp
@@ -430,7 +430,7 @@ upcall_dynastack_mark(rust_task *task) {
 /** Allocates space in the dynamic stack and returns it. */
 extern "C" CDECL void *
 upcall_dynastack_alloc(rust_task *task, size_t sz) {
-    return task->dynastack.alloc(sz);
+    return sz ? task->dynastack.alloc(sz) : NULL;
 }
 
 /** Frees space in the dynamic stack. */
diff --git a/src/rt/rust_util.h b/src/rt/rust_util.h
index 6e6f364e3a6..401c39413b6 100644
--- a/src/rt/rust_util.h
+++ b/src/rt/rust_util.h
@@ -125,6 +125,16 @@ next_power_of_two(size_t s)
     return tmp + 1;
 }
 
+// Rounds |size| to the nearest |alignment|. Invariant: |alignment| is a power
+// of two.
+template<typename T>
+static inline T
+align_to(T size, size_t alignment) {
+    assert(alignment);
+    T x = (T)(((uintptr_t)size + alignment - 1) & ~(alignment - 1));
+    return x;
+}
+
 // Initialization helper for ISAAC RNG
 
 template <typename sched_or_kernel>