Remove estrs and evecs from runtime. Issue #855
This commit is contained in:
parent
e68f687179
commit
99ee0fca67
@ -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;
|
||||
|
@ -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] {
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
6
src/test/stdtest/sys.rs
Normal file
@ -0,0 +1,6 @@
|
||||
import std::sys;
|
||||
|
||||
#[test]
|
||||
fn last_os_error() {
|
||||
log sys::rustrt::last_os_error();
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user