parent
146b61189a
commit
76d07f4056
2
mk/rt.mk
2
mk/rt.mk
@ -56,7 +56,6 @@ RUNTIME_CS_$(1) := \
|
||||
rt/rust_srv.cpp \
|
||||
rt/rust_kernel.cpp \
|
||||
rt/rust_shape.cpp \
|
||||
rt/rust_obstack.cpp \
|
||||
rt/rust_abi.cpp \
|
||||
rt/rust_cc.cpp \
|
||||
rt/rust_debug.cpp \
|
||||
@ -76,7 +75,6 @@ RUNTIME_HDR_$(1) := rt/globals.h \
|
||||
rt/rust_internal.h \
|
||||
rt/rust_util.h \
|
||||
rt/rust_env.h \
|
||||
rt/rust_obstack.h \
|
||||
rt/rust_unwind.h \
|
||||
rt/rust_upcall.h \
|
||||
rt/rust_port.h \
|
||||
|
@ -1,195 +0,0 @@
|
||||
// Object stacks, used in lieu of dynamically-sized frames.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include <cstdlib>
|
||||
#include <iostream>
|
||||
#include <new>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "rust_internal.h"
|
||||
#include "rust_obstack.h"
|
||||
#include "rust_shape.h"
|
||||
#include "rust_task.h"
|
||||
|
||||
// ISAAC, let go of max()!
|
||||
#ifdef max
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
#undef DPRINT
|
||||
#define DPRINT(fmt, ...)
|
||||
|
||||
const size_t DEFAULT_CHUNK_SIZE = 128;
|
||||
const size_t MAX_CHUNK_SIZE = (1024*64);
|
||||
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;
|
||||
uint32_t pad0; // FIXME: x86-specific
|
||||
uint32_t pad1;
|
||||
uint8_t data[];
|
||||
|
||||
rust_obstack_alloc(size_t in_len, const type_desc *in_tydesc)
|
||||
: len(in_len), tydesc(in_tydesc) {}
|
||||
};
|
||||
|
||||
void *
|
||||
rust_obstack_chunk::alloc(size_t len, type_desc *tydesc) {
|
||||
DPRINT("alloc(%lu) alen=%lu size=%lu\n", len, alen, size);
|
||||
|
||||
size_t aligned_alen = align_to(alen, DEFAULT_ALIGNMENT);
|
||||
size_t end_alen = aligned_alen + sizeof(rust_obstack_alloc) + len;
|
||||
if (end_alen > size) {
|
||||
DPRINT("Not enough space, len=%lu alen=%lu aligned=%lu end=%lu!\n",
|
||||
len, alen, aligned_alen, end_alen);
|
||||
return NULL; // Not enough space.
|
||||
}
|
||||
|
||||
rust_obstack_alloc *a =
|
||||
new(data + aligned_alen) rust_obstack_alloc(len, tydesc);
|
||||
memset(a->data, '\0', len); // FIXME: For GC.
|
||||
alen = end_alen;
|
||||
return &a->data;
|
||||
}
|
||||
|
||||
bool
|
||||
rust_obstack_chunk::free(void *ptr) {
|
||||
uint8_t *p = (uint8_t *)ptr;
|
||||
if (p < data || p > data + size)
|
||||
return false;
|
||||
assert(p <= data + alen);
|
||||
alen = (size_t)(p - data);
|
||||
return true;
|
||||
}
|
||||
|
||||
void *
|
||||
rust_obstack_chunk::mark() {
|
||||
uint8_t *m = data + alen;
|
||||
assert (m >= data && m <= data+size);
|
||||
return m;
|
||||
}
|
||||
|
||||
// Allocates the given number of bytes in a new chunk.
|
||||
void *
|
||||
rust_obstack::alloc_new(size_t len, type_desc *tydesc) {
|
||||
size_t default_chunk_size = DEFAULT_CHUNK_SIZE;
|
||||
if (chunk) {
|
||||
default_chunk_size = std::min(chunk->size * 2, MAX_CHUNK_SIZE);
|
||||
}
|
||||
|
||||
size_t chunk_size = std::max(sizeof(rust_obstack_alloc) + len,
|
||||
default_chunk_size);
|
||||
void *ptr = task->malloc(sizeof(rust_obstack_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, tydesc);
|
||||
}
|
||||
|
||||
rust_obstack::~rust_obstack() {
|
||||
while (chunk) {
|
||||
rust_obstack_chunk *prev = chunk->prev;
|
||||
task->free(chunk);
|
||||
chunk = prev;
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
rust_obstack::alloc(size_t len, type_desc *tydesc) {
|
||||
if (!chunk)
|
||||
return alloc_new(len, tydesc);
|
||||
|
||||
void *ptr = chunk->alloc(len, tydesc);
|
||||
ptr = ptr ? ptr : alloc_new(len, tydesc);
|
||||
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void
|
||||
rust_obstack::free(void *ptr) {
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
assert(chunk);
|
||||
while (!chunk->free(ptr)) {
|
||||
DPRINT("deleting chunk at %p (ptr=%p, data=%p-%p)\n",
|
||||
chunk, ptr,
|
||||
chunk->data, chunk->data + chunk->size);
|
||||
rust_obstack_chunk *prev = chunk->prev;
|
||||
task->free(chunk);
|
||||
chunk = prev;
|
||||
assert(chunk);
|
||||
}
|
||||
}
|
||||
|
||||
void *
|
||||
rust_obstack::mark() {
|
||||
void *m = chunk ? chunk->mark() : NULL;
|
||||
DPRINT("mark == %p, chunk == %p, data == %p-%p\n", m, chunk,
|
||||
(chunk ? chunk->data : NULL),
|
||||
(chunk ? chunk->data + chunk->size : NULL));
|
||||
return m;
|
||||
}
|
||||
|
||||
|
||||
// Iteration over self-describing obstacks
|
||||
|
||||
std::pair<const type_desc *,void *>
|
||||
rust_obstack::iterator::operator*() const {
|
||||
return std::make_pair(alloc->tydesc, alloc->data);
|
||||
}
|
||||
|
||||
rust_obstack::iterator &
|
||||
rust_obstack::iterator::operator++() {
|
||||
uint8_t *adata = align_to(alloc->data + alloc->len, DEFAULT_ALIGNMENT);
|
||||
alloc = reinterpret_cast<rust_obstack_alloc *>(adata);
|
||||
if (reinterpret_cast<uint8_t *>(alloc) >= chunk->data + chunk->alen) {
|
||||
// We reached the end of this chunk; go on to the next one.
|
||||
chunk = chunk->prev;
|
||||
if (chunk)
|
||||
alloc = reinterpret_cast<rust_obstack_alloc *>(chunk->data);
|
||||
else
|
||||
alloc = NULL;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
rust_obstack::iterator::operator==(const rust_obstack::iterator &other)
|
||||
const {
|
||||
return chunk == other.chunk && alloc == other.alloc;
|
||||
}
|
||||
|
||||
bool
|
||||
rust_obstack::iterator::operator!=(const rust_obstack::iterator &other)
|
||||
const {
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
|
||||
// Debugging
|
||||
|
||||
void
|
||||
rust_obstack::dump() const {
|
||||
iterator b = begin(), e = end();
|
||||
while (b != e) {
|
||||
std::pair<const type_desc *,void *> data = *b;
|
||||
uint8_t *dp = reinterpret_cast<uint8_t *>(data.second);
|
||||
|
||||
shape::arena arena;
|
||||
shape::type_param *params =
|
||||
shape::type_param::from_tydesc_and_data(data.first, dp, arena);
|
||||
shape::log log(task, true, data.first->shape, params,
|
||||
data.first->shape_tables, dp, std::cerr);
|
||||
log.walk();
|
||||
std::cerr << "\n";
|
||||
|
||||
++b;
|
||||
}
|
||||
|
||||
std::cerr << "end of dynastack dump\n";
|
||||
}
|
||||
|
@ -1,75 +0,0 @@
|
||||
// Object stacks, used in lieu of dynamically-sized frames.
|
||||
|
||||
#ifndef RUST_OBSTACK_H
|
||||
#define RUST_OBSTACK_H
|
||||
|
||||
#include <utility>
|
||||
|
||||
struct rust_obstack_alloc;
|
||||
struct rust_task;
|
||||
struct type_desc;
|
||||
|
||||
// A contiguous set of allocations.
|
||||
struct rust_obstack_chunk {
|
||||
rust_obstack_chunk *prev;
|
||||
size_t size;
|
||||
size_t alen;
|
||||
size_t pad;
|
||||
uint8_t data[];
|
||||
|
||||
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, type_desc *tydesc);
|
||||
bool free(void *ptr);
|
||||
void *mark();
|
||||
};
|
||||
|
||||
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, type_desc *tydesc);
|
||||
|
||||
public:
|
||||
class iterator {
|
||||
rust_obstack_chunk *chunk;
|
||||
rust_obstack_alloc *alloc;
|
||||
|
||||
public:
|
||||
iterator(rust_obstack_chunk *in_chunk)
|
||||
: chunk(in_chunk),
|
||||
alloc(in_chunk
|
||||
? reinterpret_cast<rust_obstack_alloc *>(in_chunk->data)
|
||||
: NULL) {}
|
||||
|
||||
std::pair<const type_desc *,void *> operator*() const;
|
||||
iterator &operator++();
|
||||
bool operator==(const iterator &other) const;
|
||||
bool operator!=(const iterator &other) const;
|
||||
};
|
||||
|
||||
rust_obstack(rust_task *in_task) : chunk(NULL), task(in_task) {}
|
||||
~rust_obstack();
|
||||
|
||||
inline iterator begin() const {
|
||||
iterator it(chunk);
|
||||
return it;
|
||||
}
|
||||
|
||||
inline iterator end() const {
|
||||
iterator it(NULL);
|
||||
return it;
|
||||
}
|
||||
|
||||
void *alloc(size_t len, type_desc *tydesc);
|
||||
void free(void *ptr);
|
||||
void *mark();
|
||||
|
||||
/** Debugging tool: dumps the contents of this obstack to stderr. */
|
||||
void dump() const;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -79,7 +79,6 @@ rust_task::rust_task(rust_task_thread *thread, rust_task_list *state,
|
||||
boxed(&local_region),
|
||||
unwinding(false),
|
||||
propagate_failure(true),
|
||||
dynastack(this),
|
||||
cc_counter(0),
|
||||
total_stack_sz(0),
|
||||
state(state),
|
||||
|
@ -13,7 +13,6 @@
|
||||
#include "rust_debug.h"
|
||||
#include "rust_internal.h"
|
||||
#include "rust_kernel.h"
|
||||
#include "rust_obstack.h"
|
||||
#include "boxed_region.h"
|
||||
#include "rust_stack.h"
|
||||
#include "rust_port_selector.h"
|
||||
@ -80,8 +79,6 @@ rust_task : public kernel_owned<rust_task>, rust_cond
|
||||
|
||||
bool propagate_failure;
|
||||
|
||||
rust_obstack dynastack;
|
||||
|
||||
uint32_t cc_counter;
|
||||
|
||||
debug::task_debug_info debug;
|
||||
|
@ -382,95 +382,6 @@ upcall_vec_grow(rust_vec** vp, size_t new_sz) {
|
||||
UPCALL_SWITCH_STACK(&args, upcall_s_vec_grow);
|
||||
}
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Returns a token that can be used to deallocate all of the allocated space
|
||||
* space in the dynamic stack.
|
||||
*/
|
||||
|
||||
struct s_dynastack_mark_args {
|
||||
void *retval;
|
||||
};
|
||||
|
||||
extern "C" CDECL void
|
||||
upcall_s_dynastack_mark(s_dynastack_mark_args *args) {
|
||||
args->retval = rust_task_thread::get_task()->dynastack.mark();
|
||||
}
|
||||
|
||||
extern "C" CDECL void *
|
||||
upcall_dynastack_mark() {
|
||||
s_dynastack_mark_args args = {0};
|
||||
UPCALL_SWITCH_STACK(&args, upcall_s_dynastack_mark);
|
||||
return args.retval;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Allocates space in the dynamic stack and returns it.
|
||||
*
|
||||
* FIXME: Deprecated since dynamic stacks need to be self-describing for GC.
|
||||
*/
|
||||
|
||||
struct s_dynastack_alloc_args {
|
||||
void *retval;
|
||||
size_t sz;
|
||||
};
|
||||
|
||||
extern "C" CDECL void
|
||||
upcall_s_dynastack_alloc(s_dynastack_alloc_args *args) {
|
||||
size_t sz = args->sz;
|
||||
args->retval = sz ?
|
||||
rust_task_thread::get_task()->dynastack.alloc(sz, NULL) : NULL;
|
||||
}
|
||||
|
||||
extern "C" CDECL void *
|
||||
upcall_dynastack_alloc(size_t sz) {
|
||||
s_dynastack_alloc_args args = {0, sz};
|
||||
UPCALL_SWITCH_STACK(&args, upcall_s_dynastack_alloc);
|
||||
return args.retval;
|
||||
}
|
||||
|
||||
/**********************************************************************
|
||||
* Allocates space associated with a type descriptor in the dynamic stack and
|
||||
* returns it.
|
||||
*/
|
||||
|
||||
struct s_dynastack_alloc_2_args {
|
||||
void *retval;
|
||||
size_t sz;
|
||||
type_desc *ty;
|
||||
};
|
||||
|
||||
extern "C" CDECL void
|
||||
upcall_s_dynastack_alloc_2(s_dynastack_alloc_2_args *args) {
|
||||
size_t sz = args->sz;
|
||||
type_desc *ty = args->ty;
|
||||
args->retval = sz ?
|
||||
rust_task_thread::get_task()->dynastack.alloc(sz, ty) : NULL;
|
||||
}
|
||||
|
||||
extern "C" CDECL void *
|
||||
upcall_dynastack_alloc_2(size_t sz, type_desc *ty) {
|
||||
s_dynastack_alloc_2_args args = {0, sz, ty};
|
||||
UPCALL_SWITCH_STACK(&args, upcall_s_dynastack_alloc_2);
|
||||
return args.retval;
|
||||
}
|
||||
|
||||
struct s_dynastack_free_args {
|
||||
void *ptr;
|
||||
};
|
||||
|
||||
extern "C" CDECL void
|
||||
upcall_s_dynastack_free(s_dynastack_free_args *args) {
|
||||
return rust_task_thread::get_task()->dynastack.free(args->ptr);
|
||||
}
|
||||
|
||||
/** Frees space in the dynamic stack. */
|
||||
extern "C" CDECL void
|
||||
upcall_dynastack_free(void *ptr) {
|
||||
s_dynastack_free_args args = {ptr};
|
||||
UPCALL_SWITCH_STACK(&args, upcall_s_dynastack_free);
|
||||
}
|
||||
|
||||
extern "C" _Unwind_Reason_Code
|
||||
__gxx_personality_v0(int version,
|
||||
_Unwind_Action actions,
|
||||
|
@ -56,10 +56,6 @@ str_reserve_shared
|
||||
vec_from_buf_shared
|
||||
unsupervise
|
||||
upcall_cmp_type
|
||||
upcall_dynastack_alloc
|
||||
upcall_dynastack_alloc_2
|
||||
upcall_dynastack_free
|
||||
upcall_dynastack_mark
|
||||
upcall_fail
|
||||
upcall_free
|
||||
upcall_validate_box
|
||||
|
Loading…
Reference in New Issue
Block a user