rt: Make the dynamic stack self-describing
This commit is contained in:
parent
729437d2c0
commit
614a930c51
@ -109,7 +109,8 @@ fn declare_upcalls(_tn: type_names, tydesc_type: TypeRef,
|
||||
[taskptr_type, T_ptr(tydesc_type), T_ptr(T_i8()), T_i32()],
|
||||
T_void()),
|
||||
dynastack_mark: d(~"dynastack_mark", [], T_ptr(T_i8())),
|
||||
dynastack_alloc: d(~"dynastack_alloc", [T_size_t()], T_ptr(T_i8())),
|
||||
dynastack_alloc: d(~"dynastack_alloc_2",
|
||||
[T_size_t(), T_ptr(tydesc_type)], T_ptr(T_i8())),
|
||||
dynastack_free: d(~"dynastack_free", [T_ptr(T_i8())], T_void())};
|
||||
}
|
||||
//
|
||||
|
@ -471,7 +471,8 @@ fn alloca(cx: &@block_ctxt, t: TypeRef) -> ValueRef {
|
||||
ret Alloca(new_raw_block_ctxt(cx.fcx, cx.fcx.llstaticallocas), t);
|
||||
}
|
||||
|
||||
fn array_alloca(cx: &@block_ctxt, t: TypeRef, n: ValueRef) -> ValueRef {
|
||||
fn dynastack_alloca(cx: &@block_ctxt, t: TypeRef, n: ValueRef, ty: ty::t)
|
||||
-> ValueRef {
|
||||
let bcx = cx;
|
||||
let dy_cx = new_raw_block_ctxt(cx.fcx, cx.fcx.lldynamicallocas);
|
||||
let lltaskptr = bcx_fcx(bcx).lltaskptr;
|
||||
@ -485,7 +486,11 @@ fn array_alloca(cx: &@block_ctxt, t: TypeRef, n: ValueRef) -> ValueRef {
|
||||
|
||||
let dynastack_alloc = bcx_ccx(bcx).upcalls.dynastack_alloc;
|
||||
let llsz = Mul(dy_cx, C_uint(llsize_of_real(bcx_ccx(bcx), t)), n);
|
||||
let llresult = Call(dy_cx, dynastack_alloc, [lltaskptr, llsz]);
|
||||
|
||||
let ti = none;
|
||||
let lltydesc = get_tydesc(cx, ty, false, tps_normal, ti).result.val;
|
||||
|
||||
let llresult = Call(dy_cx, dynastack_alloc, [lltaskptr, llsz, lltydesc]);
|
||||
ret PointerCast(dy_cx, llresult, T_ptr(t));
|
||||
}
|
||||
|
||||
@ -4868,8 +4873,10 @@ fn alloc_ty(cx: &@block_ctxt, t: ty::t) -> result {
|
||||
|
||||
let n = size_of(llderivedtydescs_block_ctxt(bcx.fcx), t);
|
||||
bcx.fcx.llderivedtydescs = n.bcx.llbb;
|
||||
val = array_alloca(bcx, T_i8(), n.val);
|
||||
} else { val = alloca(bcx, type_of(bcx_ccx(cx), cx.sp, t)); }
|
||||
val = dynastack_alloca(bcx, T_i8(), n.val, t);
|
||||
} else {
|
||||
val = alloca(bcx, type_of(bcx_ccx(cx), cx.sp, t));
|
||||
}
|
||||
// NB: since we've pushed all size calculations in this
|
||||
// function up to the alloca block, we actually return the
|
||||
// block passed into us unmodified; it doesn't really
|
||||
|
@ -5,7 +5,7 @@ import lib::llvm::llvm::{ValueRef, TypeRef};
|
||||
import back::abi;
|
||||
import trans::{call_memmove, trans_shared_malloc, llsize_of,
|
||||
type_of_or_i8, incr_ptr, INIT, copy_val, load_if_immediate,
|
||||
alloca, array_alloca, size_of, llderivedtydescs_block_ctxt,
|
||||
alloca, size_of, llderivedtydescs_block_ctxt,
|
||||
lazily_emit_tydesc_glue, get_tydesc, load_inbounds,
|
||||
move_val_if_temp, trans_lval, node_id_type,
|
||||
new_sub_block_ctxt, tps_normal, do_spill};
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <new>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "rust_internal.h"
|
||||
@ -18,9 +19,20 @@
|
||||
#define DPRINT(fmt,...)
|
||||
|
||||
//const size_t DEFAULT_CHUNK_SIZE = 4096;
|
||||
const size_t DEFAULT_CHUNK_SIZE = 300000;
|
||||
const size_t DEFAULT_CHUNK_SIZE = 500000;
|
||||
const size_t DEFAULT_ALIGNMENT = 16;
|
||||
|
||||
// A single type-tagged allocation in a chunk.
|
||||
struct rust_obstack_alloc {
|
||||
size_t len;
|
||||
const type_desc *tydesc;
|
||||
uint8_t data[];
|
||||
|
||||
rust_obstack_alloc(size_t in_len, const type_desc *in_tydesc)
|
||||
: len(in_len), tydesc(in_tydesc) {}
|
||||
};
|
||||
|
||||
// A contiguous set of allocations.
|
||||
struct rust_obstack_chunk {
|
||||
rust_obstack_chunk *prev;
|
||||
size_t size;
|
||||
@ -31,22 +43,24 @@ struct rust_obstack_chunk {
|
||||
rust_obstack_chunk(rust_obstack_chunk *in_prev, size_t in_size)
|
||||
: prev(in_prev), size(in_size), alen(0) {}
|
||||
|
||||
void *alloc(size_t len);
|
||||
void *alloc(size_t len, type_desc *tydesc);
|
||||
bool free(void *ptr);
|
||||
void *mark();
|
||||
};
|
||||
|
||||
void *
|
||||
rust_obstack_chunk::alloc(size_t len) {
|
||||
rust_obstack_chunk::alloc(size_t len, type_desc *tydesc) {
|
||||
alen = align_to(alen, DEFAULT_ALIGNMENT);
|
||||
|
||||
if (len > size - alen) {
|
||||
if (sizeof(rust_obstack_alloc) + 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;
|
||||
|
||||
rust_obstack_alloc *a = new(data + alen) rust_obstack_alloc(len, tydesc);
|
||||
alen += sizeof(*a) + len;
|
||||
return &a->data;
|
||||
}
|
||||
|
||||
bool
|
||||
@ -59,14 +73,20 @@ rust_obstack_chunk::free(void *ptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
void *
|
||||
rust_obstack_chunk::mark() {
|
||||
return data + alen;
|
||||
}
|
||||
|
||||
// Allocates the given number of bytes in a new chunk.
|
||||
void *
|
||||
rust_obstack::alloc_new(size_t len) {
|
||||
size_t chunk_size = std::max(len, DEFAULT_CHUNK_SIZE);
|
||||
rust_obstack::alloc_new(size_t len, type_desc *tydesc) {
|
||||
size_t chunk_size = std::max(sizeof(rust_obstack_alloc) + 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);
|
||||
return chunk->alloc(len, tydesc);
|
||||
}
|
||||
|
||||
rust_obstack::~rust_obstack() {
|
||||
@ -78,14 +98,14 @@ rust_obstack::~rust_obstack() {
|
||||
}
|
||||
|
||||
void *
|
||||
rust_obstack::alloc(size_t len) {
|
||||
rust_obstack::alloc(size_t len, type_desc *tydesc) {
|
||||
if (!chunk)
|
||||
return alloc_new(len);
|
||||
return alloc_new(len, tydesc);
|
||||
|
||||
DPRINT("alloc sz %u", (uint32_t)len);
|
||||
|
||||
void *ptr = chunk->alloc(len);
|
||||
ptr = ptr ? ptr : alloc_new(len);
|
||||
void *ptr = chunk->alloc(len, tydesc);
|
||||
ptr = ptr ? ptr : alloc_new(len, tydesc);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
@ -107,3 +127,8 @@ rust_obstack::free(void *ptr) {
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
rust_obstack::mark() {
|
||||
return chunk ? chunk->mark() : NULL;
|
||||
}
|
||||
|
||||
|
@ -5,20 +5,22 @@
|
||||
|
||||
struct rust_obstack_chunk;
|
||||
struct rust_task;
|
||||
struct type_desc;
|
||||
|
||||
class rust_obstack {
|
||||
rust_obstack_chunk *chunk;
|
||||
rust_task *task;
|
||||
|
||||
// Allocates the given number of bytes in a new chunk.
|
||||
void *alloc_new(size_t len);
|
||||
void *alloc_new(size_t len, type_desc *tydesc);
|
||||
|
||||
public:
|
||||
rust_obstack(rust_task *in_task) : chunk(NULL), task(in_task) {}
|
||||
~rust_obstack();
|
||||
|
||||
void *alloc(size_t len);
|
||||
void *alloc(size_t len, type_desc *tydesc);
|
||||
void free(void *ptr);
|
||||
void *mark();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -368,13 +368,26 @@ upcall_vec_push(rust_task* task, rust_vec** vp, type_desc* elt_ty,
|
||||
*/
|
||||
extern "C" CDECL void *
|
||||
upcall_dynastack_mark(rust_task *task) {
|
||||
return task->dynastack.alloc(0);
|
||||
return task->dynastack.mark();
|
||||
}
|
||||
|
||||
/** Allocates space in the dynamic stack and returns it. */
|
||||
/**
|
||||
* Allocates space in the dynamic stack and returns it.
|
||||
*
|
||||
* FIXME: Deprecated since dynamic stacks need to be self-describing for GC.
|
||||
*/
|
||||
extern "C" CDECL void *
|
||||
upcall_dynastack_alloc(rust_task *task, size_t sz) {
|
||||
return sz ? task->dynastack.alloc(sz) : NULL;
|
||||
return sz ? task->dynastack.alloc(sz, NULL) : NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates space associated with a type descriptor in the dynamic stack and
|
||||
* returns it.
|
||||
*/
|
||||
extern "C" CDECL void *
|
||||
upcall_dynastack_alloc_2(rust_task *task, size_t sz, type_desc *ty) {
|
||||
return sz ? task->dynastack.alloc(sz, ty) : NULL;
|
||||
}
|
||||
|
||||
/** Frees space in the dynamic stack. */
|
||||
|
@ -77,6 +77,7 @@ task_join
|
||||
unsupervise
|
||||
upcall_cmp_type
|
||||
upcall_dynastack_alloc
|
||||
upcall_dynastack_alloc_2
|
||||
upcall_dynastack_free
|
||||
upcall_dynastack_mark
|
||||
upcall_exit
|
||||
|
Loading…
Reference in New Issue
Block a user