Remove estrs and evecs from runtime. Issue #855

This commit is contained in:
Brian Anderson 2011-09-02 11:28:19 -07:00
parent e68f687179
commit 99ee0fca67
9 changed files with 38 additions and 310 deletions

View File

@ -19,7 +19,6 @@ native "rust" mod rustrt {
fn debug_obj<T>(x: &T, nmethods: uint, nbytes: uint);
fn debug_fn<T>(x: &T);
fn debug_ptrcast<T, U>(x: @T) -> @U;
fn debug_trap(msg: str);
}
fn debug_tydesc<T>() { rustrt::debug_tydesc::<T>(); }
@ -48,8 +47,6 @@ fn debug_fn<T>(x: &T) { rustrt::debug_fn::<T>(x); }
fn ptr_cast<T, U>(x: @T) -> @U { ret rustrt::debug_ptrcast::<T, U>(x); }
fn trap(s: str) { rustrt::debug_trap(s); }
fn refcount<T>(a: &@T) -> uint {
let p: *uint = unsafe::reinterpret_cast(a);
ret *p;

View File

@ -1,7 +1,6 @@
native "rust" mod rustrt {
fn rust_list_files(path: &istr) -> [istr];
fn rust_dirent_filename(ent: os::libc::dirent) -> str;
}
fn list_dir(path: &istr) -> [istr] {

View File

@ -7,11 +7,9 @@ command_line_args : public kernel_owned<command_line_args>
rust_task *task;
int argc;
char **argv;
rust_str **strs;
// [str] passed to rust_task::start.
rust_vec *args;
rust_vec *args_istr;
command_line_args(rust_task *task,
int sys_argc,
@ -40,52 +38,24 @@ command_line_args : public kernel_owned<command_line_args>
LocalFree(wargv);
#endif
// Allocate a vector of estrs
size_t vec_fill = sizeof(rust_str *) * argc;
size_t vec_alloc = next_power_of_two(vec_fill);
void *mem = kernel->malloc(vec_alloc, "command line");
strs = (rust_str**) mem;
for (int i = 0; i < argc; ++i) {
size_t str_fill = strlen(argv[i]) + 1;
size_t str_alloc = next_power_of_two(sizeof(rust_str) + str_fill);
mem = kernel->malloc(str_alloc, "command line arg");
strs[i] = new (mem) rust_str(str_alloc, str_fill,
(uint8_t const *)argv[i]);
strs[i]->ref_count++;
}
args = (rust_vec *)
kernel->malloc(vec_size<rust_str*>(argc),
"command line arg interior");
args->fill = args->alloc = sizeof(rust_str *) * argc;
memcpy(&args->data[0], strs, args->fill);
// Allocate a vector of istrs
args_istr = (rust_vec *)
kernel->malloc(vec_size<rust_vec*>(argc),
"command line arg interior");
args_istr->fill = args_istr->alloc = sizeof(rust_vec*) * argc;
args->fill = args->alloc = sizeof(rust_vec*) * argc;
for (int i = 0; i < argc; ++i) {
rust_vec *str = make_istr(kernel, argv[i],
strlen(argv[i]),
"command line arg");
((rust_vec**)&args_istr->data)[i] = str;
((rust_vec**)&args->data)[i] = str;
}
}
~command_line_args() {
// Free the estr args
kernel->free(args);
for (int i = 0; i < argc; ++i)
kernel->free(strs[i]);
kernel->free(strs);
// Free the istr args
for (int i = 0; i < argc; ++i) {
rust_vec *s = ((rust_vec**)&args_istr->data)[i];
rust_vec *s = ((rust_vec**)&args->data)[i];
kernel->free(s);
}
kernel->free(args_istr);
kernel->free(args);
#ifdef __WIN32__
for (int i = 0; i < argc; ++i) {
@ -97,11 +67,9 @@ command_line_args : public kernel_owned<command_line_args>
};
bool main_takes_istr = true;
// FIXME: Transitional. Please remove.
extern "C" CDECL void
set_main_takes_istr(uintptr_t flag) {
main_takes_istr = flag != 0;
}
/**
@ -136,11 +104,7 @@ rust_start(uintptr_t main_fn, int argc, char **argv,
DLOG(sched, dom, "startup: arg[%d] = '%s'", i, args->argv[i]);
}
if (main_takes_istr) {
root_task->start(main_fn, (uintptr_t)args->args_istr);
} else {
root_task->start(main_fn, (uintptr_t)args->args);
}
root_task->start(main_fn, (uintptr_t)args->args);
root_task->deref();
root_task = NULL;

View File

@ -7,7 +7,7 @@
/* Native builtins. */
extern "C" CDECL rust_str*
extern "C" CDECL rust_vec*
last_os_error(rust_task *task) {
LOG(task, task, "last_os_error()");
@ -39,16 +39,9 @@ last_os_error(rust_task *task) {
return NULL;
}
#endif
size_t fill = strlen(buf) + 1;
size_t alloc = next_power_of_two(sizeof(rust_str) + fill);
void *mem = task->malloc(alloc, "rust_str(last_os_error)");
if (!mem) {
task->fail();
return NULL;
}
rust_str *st = new (mem) rust_str(alloc, fill,
(const uint8_t *)buf);
rust_vec * st = make_istr(task->kernel, buf, strlen(buf),
"last_os_error");
#ifdef __WIN32__
LocalFree((HLOCAL)buf);
#endif
@ -115,43 +108,6 @@ unsupervise(rust_task *task) {
task->unsupervise();
}
/* Helper for str_alloc and str_from_vec. Returns NULL as failure. */
static rust_evec*
vec_alloc_with_data(rust_task *task,
size_t n_elts,
size_t fill,
size_t elt_size,
void *d)
{
size_t alloc = next_power_of_two(sizeof(rust_evec) + (n_elts * elt_size));
void *mem = task->malloc(alloc, "rust_evec (with data)");
if (!mem) return NULL;
return new (mem) rust_evec(alloc, fill * elt_size, (uint8_t*)d);
}
extern "C" CDECL char const *
str_buf(rust_task *task, rust_str *s)
{
return (char const *)&s->data[0];
}
extern "C" CDECL rust_str *
str_from_vec(rust_task *task, rust_vec **vp)
{
rust_vec* v = *vp;
rust_str *st = vec_alloc_with_data(task,
v->fill + 1, // +1 for \0
v->fill,
1,
&v->data[0]);
if (!st) {
task->fail();
return NULL;
}
st->data[st->fill++] = '\0';
return st;
}
extern "C" CDECL void
vec_reserve_shared(rust_task* task, type_desc* ty, rust_vec** vp,
size_t n_elts) {
@ -370,19 +326,6 @@ debug_ptrcast(rust_task *task,
return ptr;
}
extern "C" CDECL void
debug_trap(rust_task *task, rust_str *s)
{
LOG(task, stdlib, "trapping: %s", s->data);
// FIXME: x86-ism.
__asm__("int3");
}
rust_str* c_str_to_rust(rust_task *task, char const *str) {
size_t len = strlen(str) + 1;
return vec_alloc_with_data(task, len, len, 1, (void*)str);
}
extern "C" CDECL rust_vec*
rust_list_files(rust_task *task, rust_vec **path) {
array_list<rust_vec*> strings;
@ -421,18 +364,6 @@ rust_list_files(rust_task *task, rust_vec **path) {
return vec;
}
#if defined(__WIN32__)
extern "C" CDECL rust_str *
rust_dirent_filename(rust_task *task, void* ent) {
return NULL;
}
#else
extern "C" CDECL rust_str *
rust_dirent_filename(rust_task *task, dirent* ent) {
return c_str_to_rust(task, ent->d_name);
}
#endif
extern "C" CDECL int
rust_file_is_dir(rust_task *task, char *path) {
struct stat buf;

View File

@ -4,8 +4,9 @@
// Upcalls.
// FIXME: Transitional. Please remove
extern "C" CDECL char const *
str_buf(rust_task *task, rust_str *s);
str_buf(rust_task *task, void *s) { return NULL; }
#ifdef __i386__
void
@ -52,15 +53,6 @@ void upcall_log_double(rust_task *task, uint32_t level, double *f) {
task->sched->log(task, level, "rust: %12.12f", *f);
}
extern "C" CDECL void
upcall_log_str(rust_task *task, uint32_t level, rust_str *str) {
LOG_UPCALL_ENTRY(task);
if (task->sched->log_lvl >= level) {
const char *c = str_buf(task, str);
task->sched->log(task, level, "rust: %s", c);
}
}
extern "C" CDECL void
upcall_yield(rust_task *task) {
LOG_UPCALL_ENTRY(task);
@ -68,6 +60,26 @@ upcall_yield(rust_task *task) {
task->yield(1);
}
// Copy elements from one vector to another,
// dealing with reference counts
static inline void
copy_elements(rust_task *task, type_desc *elem_t,
void *pdst, void *psrc, size_t n)
{
char *dst = (char *)pdst, *src = (char *)psrc;
memmove(dst, src, n);
// increment the refcount of each element of the vector
if (elem_t->take_glue) {
glue_fn *take_glue = elem_t->take_glue;
size_t elem_size = elem_t->size;
const type_desc **tydescs = elem_t->first_param;
for (char *p = dst; p < dst+n; p += elem_size) {
take_glue(NULL, task, NULL, tydescs, p);
}
}
}
extern "C" CDECL void
upcall_sleep(rust_task *task, size_t time_in_us) {
LOG_UPCALL_ENTRY(task);
@ -179,150 +191,6 @@ upcall_shared_free(rust_task *task, void* ptr) {
task->kernel->free(ptr);
}
rust_str *make_str(rust_task *task, char const *s, size_t fill) {
size_t alloc = next_power_of_two(sizeof(rust_str) + fill);
void *mem = task->malloc(alloc, "rust_str (make_str)");
if (!mem) {
task->fail();
return NULL;
}
rust_str *st = new (mem) rust_str(alloc, fill,
(uint8_t const *) s);
LOG(task, mem,
"upcall new_str('%s', %" PRIdPTR ") = 0x%" PRIxPTR,
s, fill, st);
return st;
}
extern "C" CDECL rust_str *
upcall_new_str(rust_task *task, char const *s, size_t fill) {
LOG_UPCALL_ENTRY(task);
return make_str(task, s, fill);
}
static rust_evec *
vec_grow(rust_task *task,
rust_evec *v,
size_t n_bytes,
uintptr_t *need_copy,
type_desc *td)
{
rust_scheduler *sched = task->sched;
LOG(task, mem,
"vec_grow(0x%" PRIxPTR ", %" PRIdPTR
"), rc=%" PRIdPTR " alloc=%" PRIdPTR ", fill=%" PRIdPTR
", need_copy=0x%" PRIxPTR,
v, n_bytes, v->ref_count, v->alloc, v->fill, need_copy);
*need_copy = 0;
size_t alloc = next_power_of_two(sizeof(rust_evec) + v->fill + n_bytes);
if (v->ref_count == 1) {
// Fastest path: already large enough.
if (v->alloc >= alloc) {
LOG(task, mem, "no-growth path");
return v;
}
// Second-fastest path: can at least realloc.
LOG(task, mem, "realloc path");
v = (rust_evec*) task->realloc(v, alloc, td->is_stateful);
if (!v) {
task->fail();
return NULL;
}
v->alloc = alloc;
} else {
/**
* Slowest path: make a new vec.
*
* 1. Allocate a new rust_evec with desired additional space.
* 2. Down-ref the shared rust_evec, point to the new one instead.
* 3. Copy existing elements into the new rust_evec.
*
* Step 3 is a bit tricky. We don't know how to properly copy the
* elements in the runtime (all we have are bits in a buffer; no
* type information and no copy glue). What we do instead is set the
* need_copy outparam flag to indicate to our caller (vec-copy glue)
* that we need the copies performed for us.
*/
LOG(task, mem, "new vec path");
void *mem = task->malloc(alloc, "rust_evec (vec_grow)", td);
if (!mem) {
task->fail();
return NULL;
}
if (v->ref_count != CONST_REFCOUNT)
v->deref();
v = new (mem) rust_evec(alloc, 0, NULL);
*need_copy = 1;
}
I(sched, sizeof(rust_evec) + v->fill <= v->alloc);
return v;
}
// Copy elements from one vector to another,
// dealing with reference counts
static inline void
copy_elements(rust_task *task, type_desc *elem_t,
void *pdst, void *psrc, size_t n)
{
char *dst = (char *)pdst, *src = (char *)psrc;
memmove(dst, src, n);
// increment the refcount of each element of the vector
if (elem_t->take_glue) {
glue_fn *take_glue = elem_t->take_glue;
size_t elem_size = elem_t->size;
const type_desc **tydescs = elem_t->first_param;
for (char *p = dst; p < dst+n; p += elem_size) {
take_glue(NULL, task, NULL, tydescs, p);
}
}
}
extern "C" CDECL void
upcall_evec_append(rust_task *task, type_desc *t, type_desc *elem_t,
rust_evec **dst_ptr, rust_evec *src, bool skip_null)
{
LOG_UPCALL_ENTRY(task);
rust_evec *dst = *dst_ptr;
uintptr_t need_copy;
size_t n_src_bytes = skip_null ? src->fill - 1 : src->fill;
size_t n_dst_bytes = skip_null ? dst->fill - 1 : dst->fill;
rust_evec *new_vec = vec_grow(task, dst, n_src_bytes, &need_copy, t);
// If src and dst are the same (due to "v += v"), then dst getting
// resized causes src to move as well.
if (dst == src && !need_copy) {
src = new_vec;
}
if (need_copy) {
// Copy any dst elements in, omitting null if doing str.
copy_elements(task, elem_t, &new_vec->data, &dst->data, n_dst_bytes);
}
// Copy any src elements in, carrying along null if doing str.
void *new_end = (void *)((char *)new_vec->data + n_dst_bytes);
copy_elements(task, elem_t, new_end, &src->data, src->fill);
new_vec->fill = n_dst_bytes + src->fill;
// Write new_vec back through the alias we were given.
*dst_ptr = new_vec;
}
// FIXME: Transitional. Please remove.
extern "C" CDECL void
upcall_vec_append(rust_task *task, type_desc *t, type_desc *elem_t,
rust_evec **dst_ptr, rust_evec *src, bool skip_null) {
upcall_evec_append(task, t, elem_t, dst_ptr, src, skip_null);
}
extern "C" CDECL type_desc *
upcall_get_type_desc(rust_task *task,
void *curr_crate, // ignored, legacy compat.

View File

@ -164,36 +164,6 @@ isaac_init(sched_or_kernel *sched, randctx *rctx)
randinit(rctx, 1);
}
// Vectors (rust-user-code level).
struct
rust_evec
{
RUST_REFCOUNTED(rust_evec)
size_t alloc;
size_t fill;
size_t pad; // Pad to align data[0] to 16 bytes.
uint8_t data[];
rust_evec(size_t alloc, size_t fill,
uint8_t const *d)
: ref_count(1),
alloc(alloc),
fill(fill)
{
if (d)
memcpy(&data[0], d, fill);
}
~rust_evec() {}
inline void *operator new(size_t size, void *mem) {
return mem;
}
};
// Strings are just exterior vecs
typedef rust_evec rust_str;
// Interior vectors (rust-user-code level).
struct

View File

@ -19,7 +19,6 @@ debug_opaque
del_port
debug_ptrcast
debug_tag
debug_trap
debug_tydesc
do_gc
drop_port
@ -44,7 +43,6 @@ rand_free
rand_new
rand_next
refcount
rust_dirent_filename
rust_file_is_dir
rust_get_stdin
rust_get_stdout
@ -63,7 +61,6 @@ size_of
squareroot
start_task
str_buf
str_from_vec
vec_reserve_shared
vec_from_buf_shared
task_sleep
@ -86,14 +83,9 @@ upcall_kill
upcall_log_double
upcall_log_float
upcall_log_int
upcall_log_str
upcall_log_str
upcall_log_type
upcall_malloc
upcall_new_str
upcall_shared_malloc
upcall_shared_free
upcall_sleep
upcall_evec_append
upcall_vec_append
upcall_yield

View File

@ -25,6 +25,7 @@ mod run;
mod sha1;
mod sort;
mod str;
mod sys;
mod task;
mod test;
mod uint;

6
src/test/stdtest/sys.rs Normal file
View File

@ -0,0 +1,6 @@
import std::sys;
#[test]
fn last_os_error() {
log sys::rustrt::last_os_error();
}