diff options
| author | Brian Anderson <banderson@mozilla.com> | 2012-05-31 01:26:05 -0700 |
|---|---|---|
| committer | Brian Anderson <banderson@mozilla.com> | 2012-05-31 01:26:05 -0700 |
| commit | 41b02b7c57092f1da63beec60358061a9579d8c6 (patch) | |
| tree | ddf24839509ffcf50f6fc57c570b13a5b223ec87 | |
| parent | 615f5324754bdbb97998181cf1ada4c53337c7f3 (diff) | |
| parent | 3a2c92b46334d422c438061335f6f76669c8743f (diff) | |
| download | rust-41b02b7c57092f1da63beec60358061a9579d8c6.tar.gz rust-41b02b7c57092f1da63beec60358061a9579d8c6.zip | |
Merge remote-tracking branch 'brson/self-describing-uniques'
Conflicts: src/snapshots.txt
| -rw-r--r-- | mk/host.mk | 2 | ||||
| -rw-r--r-- | mk/target.mk | 48 | ||||
| -rw-r--r-- | src/libcore/vec.rs | 7 | ||||
| -rw-r--r-- | src/rt/rust.cpp | 4 | ||||
| -rw-r--r-- | src/rt/rust_builtin.cpp | 63 | ||||
| -rw-r--r-- | src/rt/rust_cc.cpp | 8 | ||||
| -rw-r--r-- | src/rt/rust_shape.h | 30 | ||||
| -rw-r--r-- | src/rt/rust_task.cpp | 5 | ||||
| -rw-r--r-- | src/rt/rust_upcall.cpp | 200 | ||||
| -rw-r--r-- | src/rt/rust_upcall.h | 5 | ||||
| -rw-r--r-- | src/rt/rust_util.h | 42 | ||||
| -rw-r--r-- | src/rt/rustrt.def.in | 9 | ||||
| -rw-r--r-- | src/rustc/back/upcall.rs | 37 | ||||
| -rw-r--r-- | src/rustc/middle/trans/alt.rs | 9 | ||||
| -rw-r--r-- | src/rustc/middle/trans/base.rs | 91 | ||||
| -rw-r--r-- | src/rustc/middle/trans/closure.rs | 16 | ||||
| -rw-r--r-- | src/rustc/middle/trans/common.rs | 20 | ||||
| -rw-r--r-- | src/rustc/middle/trans/tvec.rs | 128 | ||||
| -rw-r--r-- | src/rustc/middle/trans/type_of.rs | 10 | ||||
| -rw-r--r-- | src/rustc/middle/trans/uniq.rs | 51 | ||||
| -rw-r--r-- | src/snapshots.txt | 8 |
21 files changed, 495 insertions, 298 deletions
diff --git a/mk/host.mk b/mk/host.mk index 48d92011998..1065ac3f396 100644 --- a/mk/host.mk +++ b/mk/host.mk @@ -74,7 +74,7 @@ $$(HLIB$(2)_H_$(4))/$$(CFG_STDLIB): \ @$$(call E, cp: $$@) $$(Q)cp $$< $$@ $$(Q)cp -R $$(TLIB$(1)_T_$(4)_H_$(3))/$(STDLIB_GLOB) \ - $$(TLIB$(1)_T_$(4)_H_$(3))/$(STDLIB_DSYM_GLOB) \ + $$(wildcard $$(TLIB$(1)_T_$(4)_H_$(3))/$(STDLIB_DSYM_GLOB)) \ $$(HLIB$(2)_H_$(4)) $$(HLIB$(2)_H_$(4))/libcore.rlib: \ diff --git a/mk/target.mk b/mk/target.mk index c049ce5c296..b6e00b978aa 100644 --- a/mk/target.mk +++ b/mk/target.mk @@ -8,8 +8,9 @@ # (resp. corelib), set this flag to 1. It will cause stage1 to use # the snapshot runtime (resp. corelib) rather than the runtime # (resp. corelib) from the working directory. -USE_SNAPSHOT_RUNTIME=0 -USE_SNAPSHOT_CORELIB=0 +USE_SNAPSHOT_RUNTIME=1 +USE_SNAPSHOT_CORELIB=1 +USE_SNAPSHOT_STDLIB=1 define TARGET_STAGE_N @@ -18,13 +19,6 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/libmorestack.a: \ @$$(call E, cp: $$@) $$(Q)cp $$< $$@ -$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB): \ - $$(STDLIB_CRATE) $$(STDLIB_INPUTS) \ - $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_CORELIB) \ - $$(TSREQ$(1)_T_$(2)_H_$(3)) - @$$(call E, compile_and_link: $$@) - $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< && touch $$@ - $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_RUSTLLVM): \ rustllvm/$(2)/$$(CFG_RUSTLLVM) @$$(call E, cp: $$@) @@ -116,6 +110,30 @@ $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_CORELIB): \ endef +define TARGET_STDLIB_FROM_SNAPSHOT + +$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB): \ + $$(HLIB$(1)_H_$(3))/$$(CFG_STDLIB) \ + $$(STDLIB_INPUTS) \ + $$(TSREQ$(1)_T_$(2)_H_$(3)) + @$$(call E, cp: $$@) + $$(Q)cp $$< $$@ + $$(Q)cp $$(HLIB$(1)_H_$(3))/$$(STDLIB_GLOB) \ + $$(TLIB$(1)_T_$(2)_H_$(3)) + +endef + +define TARGET_STDLIB_FROM_WD + +$$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_STDLIB): \ + $$(STDLIB_CRATE) $$(STDLIB_INPUTS) \ + $$(TLIB$(1)_T_$(2)_H_$(3))/$$(CFG_CORELIB) \ + $$(TSREQ$(1)_T_$(2)_H_$(3)) + @$$(call E, compile_and_link: $$@) + $$(STAGE$(1)_T_$(2)_H_$(3)) -o $$@ $$< && touch $$@ + +endef + # In principle, each host can build each target: $(foreach source,$(CFG_TARGET_TRIPLES), \ $(foreach target,$(CFG_TARGET_TRIPLES), \ @@ -142,11 +160,20 @@ else $(eval $(call TARGET_CORELIB_FROM_WD,0,$(src),$(src)))) endif +ifeq ($(USE_SNAPSHOT_STDLIB),1) + $(foreach src,$(CFG_HOST_TRIPLE),\ + $(eval $(call TARGET_STDLIB_FROM_SNAPSHOT,0,$(src),$(src)))) +else + $(foreach src,$(CFG_HOST_TRIPLE),\ + $(eval $(call TARGET_STDLIB_FROM_WD,0,$(src),$(src)))) +endif + # Non-host triples build the stage0 runtime from the working directory $(foreach source,$(CFG_TARGET_TRIPLES), \ $(foreach target,$(NON_HOST_TRIPLES), \ $(eval $(call TARGET_RT_FROM_WD,0,$(target),$(source))) \ $(eval $(call TARGET_CORELIB_FROM_WD,0,$(target),$(source))) \ + $(eval $(call TARGET_STDLIB_FROM_WD,0,$(target),$(source))) \ )) # After stage0, always build the stage0 runtime from the working directory @@ -158,5 +185,8 @@ $(foreach source,$(CFG_TARGET_TRIPLES), \ $(eval $(call TARGET_CORELIB_FROM_WD,1,$(target),$(source))) \ $(eval $(call TARGET_CORELIB_FROM_WD,2,$(target),$(source))) \ $(eval $(call TARGET_CORELIB_FROM_WD,3,$(target),$(source))) \ + $(eval $(call TARGET_STDLIB_FROM_WD,1,$(target),$(source))) \ + $(eval $(call TARGET_STDLIB_FROM_WD,2,$(target),$(source))) \ + $(eval $(call TARGET_STDLIB_FROM_WD,3,$(target),$(source))) \ )) diff --git a/src/libcore/vec.rs b/src/libcore/vec.rs index fdc8b1ed248..a743cbc5576 100644 --- a/src/libcore/vec.rs +++ b/src/libcore/vec.rs @@ -1162,7 +1162,12 @@ impl extensions<T> for [T] { mod unsafe { // FIXME: This should have crate visibility (#1893 blocks that) #[doc = "The internal representation of a vector"] - type vec_repr = {mut fill: uint, mut alloc: uint, data: u8}; + type vec_repr = { + box_header: (uint, uint, uint, uint), + mut fill: uint, + mut alloc: uint, + data: u8 + }; #[doc = " Constructs a vector from an unsafe pointer to a buffer diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp index 2fed06854cb..4019c8701ac 100644 --- a/src/rt/rust.cpp +++ b/src/rt/rust.cpp @@ -13,7 +13,7 @@ command_line_args : public kernel_owned<command_line_args> char **argv; // [str] passed to rust_task::start. - rust_vec *args; + rust_vec_box *args; command_line_args(rust_task *task, int sys_argc, @@ -47,7 +47,7 @@ command_line_args : public kernel_owned<command_line_args> ~command_line_args() { for (int i = 0; i < argc; ++i) { - rust_vec *s = ((rust_vec**)&args->data)[i]; + rust_vec *s = ((rust_vec**)&args->body.data)[i]; kernel->free(s); } kernel->free(args); diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 97fbcf4953d..eebb114f5fc 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -85,7 +85,7 @@ rust_getcwd() { } #if defined(__WIN32__) -extern "C" CDECL rust_vec * +extern "C" CDECL rust_vec_box * rust_env_pairs() { rust_task *task = rust_get_current_task(); size_t envc = 0; @@ -95,14 +95,14 @@ rust_env_pairs() { ++envc; } c = ch; - rust_vec *v = (rust_vec *) - task->kernel->malloc(vec_size<rust_vec*>(envc), + rust_vec_box *v = (rust_vec_box *) + task->kernel->malloc(vec_size<rust_vec_box*>(envc), "str vec interior"); - v->fill = v->alloc = sizeof(rust_vec*) * envc; + v->body.fill = v->body.alloc = sizeof(rust_vec*) * envc; for (size_t i = 0; i < envc; ++i) { size_t n = strlen(c); rust_str *str = make_str(task->kernel, c, n, "str"); - ((rust_str**)&v->data)[i] = str; + ((rust_str**)&v->body.data)[i] = str; c += n + 1; } if (ch) { @@ -111,7 +111,7 @@ rust_env_pairs() { return v; } #else -extern "C" CDECL rust_vec * +extern "C" CDECL rust_vec_box * rust_env_pairs() { rust_task *task = rust_get_current_task(); #ifdef __APPLE__ @@ -140,14 +140,14 @@ unsupervise() { } extern "C" CDECL void -vec_reserve_shared(type_desc* ty, rust_vec** vp, +vec_reserve_shared(type_desc* ty, rust_vec_box** vp, size_t n_elts) { rust_task *task = rust_get_current_task(); reserve_vec_exact(task, vp, n_elts * ty->size); } extern "C" CDECL void -str_reserve_shared(rust_vec** sp, +str_reserve_shared(rust_vec_box** sp, size_t n_elts) { rust_task *task = rust_get_current_task(); reserve_vec_exact(task, sp, n_elts + 1); @@ -157,25 +157,26 @@ str_reserve_shared(rust_vec** sp, * Copies elements in an unsafe buffer to the given interior vector. The * vector must have size zero. */ -extern "C" CDECL rust_vec* +extern "C" CDECL rust_vec_box* vec_from_buf_shared(type_desc *ty, void *ptr, size_t count) { rust_task *task = rust_get_current_task(); size_t fill = ty->size * count; - rust_vec* v = (rust_vec*)task->kernel->malloc(fill + sizeof(rust_vec), - "vec_from_buf"); - v->fill = v->alloc = fill; - memmove(&v->data[0], ptr, fill); + rust_vec_box* v = (rust_vec_box*) + task->kernel->malloc(fill + sizeof(rust_vec_box), + "vec_from_buf"); + v->body.fill = v->body.alloc = fill; + memmove(&v->body.data[0], ptr, fill); return v; } extern "C" CDECL void -rust_str_push(rust_vec** sp, uint8_t byte) { +rust_str_push(rust_vec_box** sp, uint8_t byte) { rust_task *task = rust_get_current_task(); - size_t fill = (*sp)->fill; + size_t fill = (*sp)->body.fill; reserve_vec(task, sp, fill + 1); - (*sp)->data[fill-1] = byte; - (*sp)->data[fill] = 0; - (*sp)->fill = fill + 1; + (*sp)->body.data[fill-1] = byte; + (*sp)->body.data[fill] = 0; + (*sp)->body.fill = fill + 1; } extern "C" CDECL rust_vec* @@ -367,13 +368,13 @@ debug_get_stk_seg() { return task->stk; } -extern "C" CDECL rust_vec* +extern "C" CDECL rust_vec_box* rust_list_files(rust_str *path) { rust_task *task = rust_get_current_task(); array_list<rust_str*> strings; #if defined(__WIN32__) WIN32_FIND_DATA FindFileData; - HANDLE hFind = FindFirstFile((char*)path->data, &FindFileData); + HANDLE hFind = FindFirstFile((char*)path->body.data, &FindFileData); if (hFind != INVALID_HANDLE_VALUE) { do { rust_str *str = make_str(task->kernel, FindFileData.cFileName, @@ -384,25 +385,25 @@ rust_list_files(rust_str *path) { FindClose(hFind); } #else - DIR *dirp = opendir((char*)path->data); + DIR *dirp = opendir((char*)path->body.data); if (dirp) { struct dirent *dp; while ((dp = readdir(dirp))) { - rust_vec *str = make_str(task->kernel, dp->d_name, - strlen(dp->d_name), - "list_files_str"); + rust_vec_box *str = make_str(task->kernel, dp->d_name, + strlen(dp->d_name), + "list_files_str"); strings.push(str); } closedir(dirp); } #endif - rust_vec *vec = (rust_vec *) - task->kernel->malloc(vec_size<rust_vec*>(strings.size()), + rust_vec_box *vec = (rust_vec_box *) + task->kernel->malloc(vec_size<rust_vec_box*>(strings.size()), "list_files_vec"); size_t alloc_sz = sizeof(rust_vec*) * strings.size(); - vec->fill = vec->alloc = alloc_sz; - memcpy(&vec->data[0], strings.data(), alloc_sz); + vec->body.fill = vec->body.alloc = alloc_sz; + memcpy(&vec->body.data[0], strings.data(), alloc_sz); return vec; } @@ -520,9 +521,9 @@ void tm_to_rust_tm(tm* in_tm, rust_tm* out_tm, int32_t gmtoff, if (zone != NULL) { size_t size = strlen(zone); str_reserve_shared(&out_tm->tm_zone, size); - memcpy(out_tm->tm_zone->data, zone, size); - out_tm->tm_zone->fill = size + 1; - out_tm->tm_zone->data[size] = '\0'; + memcpy(out_tm->tm_zone->body.data, zone, size); + out_tm->tm_zone->body.fill = size + 1; + out_tm->tm_zone->body.data[size] = '\0'; } } diff --git a/src/rt/rust_cc.cpp b/src/rt/rust_cc.cpp index 66f044b8ce9..4d6aaf02070 100644 --- a/src/rt/rust_cc.cpp +++ b/src/rt/rust_cc.cpp @@ -117,7 +117,9 @@ class irc : public shape::data<irc,shape::ptr> { } void walk_uniq2() { - shape::data<irc,shape::ptr>::walk_uniq_contents1(); + rust_opaque_box *box = *(rust_opaque_box**)dp; + if (box) + shape::data<irc,shape::ptr>::walk_uniq_contents1(); } void walk_rptr2() { @@ -373,7 +375,9 @@ class mark : public shape::data<mark,shape::ptr> { } void walk_uniq2() { - shape::data<mark,shape::ptr>::walk_uniq_contents1(); + rust_opaque_box *box = *(rust_opaque_box**)dp; + if (box) + shape::data<mark,shape::ptr>::walk_uniq_contents1(); } void walk_rptr2() { diff --git a/src/rt/rust_shape.h b/src/rt/rust_shape.h index c6817b23a6e..77a253d2bb7 100644 --- a/src/rt/rust_shape.h +++ b/src/rt/rust_shape.h @@ -783,6 +783,11 @@ public: return box->td; } + inline const type_desc *uniq_body_td() const { + rust_opaque_box *box = *reinterpret_cast<rust_opaque_box**>(p); + return box->td; + } + inline ptr box_body() const { rust_opaque_box *box = *reinterpret_cast<rust_opaque_box**>(p); return make((uint8_t*)::box_body(box)); @@ -881,6 +886,11 @@ public: return box_fst->td; } + inline const type_desc *uniq_body_td() const { + rust_opaque_box *box_fst = *reinterpret_cast<rust_opaque_box**>(fst); + return box_fst->td; + } + inline ptr_pair box_body() const { rust_opaque_box *box_fst = *reinterpret_cast<rust_opaque_box**>(fst); rust_opaque_box *box_snd = *reinterpret_cast<rust_opaque_box**>(snd); @@ -1067,10 +1077,16 @@ data<T,U>::walk_box_contents1() { template<typename T,typename U> void data<T,U>::walk_uniq_contents1() { - typename U::template data<uint8_t *>::t box_ptr = bump_dp<uint8_t *>(dp); - U data_ptr(box_ptr); - T sub(*static_cast<T *>(this), data_ptr); - static_cast<T *>(this)->walk_uniq_contents2(sub); + const type_desc *body_td = dp.uniq_body_td(); + if (body_td) { + U body_dp(dp.box_body()); + arena arena; + type_param *params = type_param::from_tydesc(body_td, arena); + T sub(*static_cast<T *>(this), body_td->shape, params, + body_td->shape_tables, body_dp); + sub.align = true; + static_cast<T *>(this)->walk_uniq_contents2(sub); + } } template<typename T,typename U> @@ -1094,9 +1110,9 @@ data<T,U>::walk_variant1(tag_info &tinfo, tag_variant_t variant_id) { template<typename T,typename U> std::pair<uint8_t *,uint8_t *> data<T,U>::get_vec_data_range(ptr dp) { - rust_vec* ptr = bump_dp<rust_vec*>(dp); - uint8_t* data = &ptr->data[0]; - return std::make_pair(data, data + ptr->fill); + rust_vec_box* ptr = bump_dp<rust_vec_box*>(dp); + uint8_t* data = &ptr->body.data[0]; + return std::make_pair(data, data + ptr->body.fill); } template<typename T,typename U> diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 2331cccd590..5299de0ed34 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -7,7 +7,6 @@ #include "rust_task.h" #include "rust_cc.h" -#include "rust_upcall.h" #include "rust_env.h" #include "rust_port.h" @@ -130,6 +129,8 @@ cleanup_task(cleanup_args *args) { } } +extern "C" CDECL void upcall_exchange_free(void *ptr); + // This runs on the Rust stack void task_start_wrapper(spawn_args *a) { @@ -161,7 +162,7 @@ void task_start_wrapper(spawn_args *a) // free the environment (which should be a unique closure). const type_desc *td = env->td; td->drop_glue(NULL, NULL, td->first_param, box_body(env)); - upcall_shared_free(env); + upcall_exchange_free(env); } // The cleanup work needs lots of stack diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 9ad1f3a5e4d..ac11ee7a26b 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -152,6 +152,92 @@ upcall_trace(char const *msg, } /********************************************************************** + * Allocate an object in the exchange heap + */ + +extern "C" CDECL uintptr_t +exchange_malloc(rust_task *task, type_desc *td, uintptr_t size) { + + LOG(task, mem, "upcall exchange malloc(0x%" PRIxPTR ")", td); + + // Copied from boxed_region + size_t header_size = sizeof(rust_opaque_box); + size_t body_size = size; + size_t body_align = td->align; + // FIXME: This alignment calculation is suspicious. Is it right? + size_t total_size = align_to(header_size, body_align) + body_size; + + void *p = task->kernel->malloc(total_size, "exchange malloc"); + + rust_opaque_box *header = static_cast<rust_opaque_box*>(p); + header->td = td; + + memset(&header[1], '\0', body_size); + + return (uintptr_t)header; +} + +struct s_exchange_malloc_args { + uintptr_t retval; + type_desc *td; +}; + +extern "C" CDECL void +upcall_s_exchange_malloc(s_exchange_malloc_args *args) { + rust_task *task = rust_get_current_task(); + LOG_UPCALL_ENTRY(task); + + uintptr_t retval = exchange_malloc(task, args->td, args->td->size); + args->retval = retval; +} + +extern "C" CDECL uintptr_t +upcall_exchange_malloc(type_desc *td) { + s_exchange_malloc_args args = {0, td}; + UPCALL_SWITCH_STACK(&args, upcall_s_exchange_malloc); + return args.retval; +} + +struct s_exchange_malloc_dyn_args { + uintptr_t retval; + type_desc *td; + uintptr_t size; +}; + +extern "C" CDECL void +upcall_s_exchange_malloc_dyn(s_exchange_malloc_dyn_args *args) { + rust_task *task = rust_get_current_task(); + LOG_UPCALL_ENTRY(task); + + uintptr_t retval = exchange_malloc(task, args->td, args->size); + args->retval = retval; +} + +extern "C" CDECL uintptr_t +upcall_exchange_malloc_dyn(type_desc *td, uintptr_t size) { + s_exchange_malloc_dyn_args args = {0, td, size}; + UPCALL_SWITCH_STACK(&args, upcall_s_exchange_malloc_dyn); + return args.retval; +} + +struct s_exchange_free_args { + void *ptr; +}; + +extern "C" CDECL void +upcall_s_exchange_free(s_exchange_free_args *args) { + rust_task *task = rust_get_current_task(); + LOG_UPCALL_ENTRY(task); + task->kernel->free(args->ptr); +} + +extern "C" CDECL void +upcall_exchange_free(void *ptr) { + s_exchange_free_args args = {ptr}; + UPCALL_SWITCH_STACK(&args, upcall_s_exchange_free); +} + +/********************************************************************** * Allocate an object in the task-local heap. */ @@ -234,81 +320,6 @@ upcall_validate_box(rust_opaque_box* ptr) { } } -/********************************************************************** - * Allocate an object in the exchange heap. - */ - -struct s_shared_malloc_args { - uintptr_t retval; - size_t nbytes; -}; - -extern "C" CDECL void -upcall_s_shared_malloc(s_shared_malloc_args *args) { - rust_task *task = rust_get_current_task(); - LOG_UPCALL_ENTRY(task); - - LOG(task, mem, "upcall shared_malloc(%" PRIdPTR ")", args->nbytes); - void *p = task->kernel->malloc(args->nbytes, "shared malloc"); - memset(p, '\0', args->nbytes); - LOG(task, mem, "upcall shared_malloc(%" PRIdPTR ") = 0x%" PRIxPTR, - args->nbytes, (uintptr_t)p); - args->retval = (uintptr_t) p; -} - -extern "C" CDECL uintptr_t -upcall_shared_malloc(size_t nbytes) { - s_shared_malloc_args args = {0, nbytes}; - UPCALL_SWITCH_STACK(&args, upcall_s_shared_malloc); - return args.retval; -} - -/********************************************************************** - * Called whenever an object in the exchange heap is freed. - */ - -struct s_shared_free_args { - void *ptr; -}; - -extern "C" CDECL void -upcall_s_shared_free(s_shared_free_args *args) { - rust_task *task = rust_get_current_task(); - LOG_UPCALL_ENTRY(task); - - rust_sched_loop *sched_loop = task->sched_loop; - DLOG(sched_loop, mem, - "upcall shared_free(0x%" PRIxPTR")", - (uintptr_t)args->ptr); - task->kernel->free(args->ptr); -} - -extern "C" CDECL void -upcall_shared_free(void* ptr) { - s_shared_free_args args = {ptr}; - UPCALL_SWITCH_STACK(&args, upcall_s_shared_free); -} - -struct s_shared_realloc_args { - void *retval; - void *ptr; - size_t size; -}; - -extern "C" CDECL void -upcall_s_shared_realloc(s_shared_realloc_args *args) { - rust_task *task = rust_get_current_task(); - LOG_UPCALL_ENTRY(task); - args->retval = task->kernel->realloc(args->ptr, args->size); -} - -extern "C" CDECL void * -upcall_shared_realloc(void *ptr, size_t size) { - s_shared_realloc_args args = {NULL, ptr, size}; - UPCALL_SWITCH_STACK(&args, upcall_s_shared_realloc); - return args.retval; -} - /**********************************************************************/ struct s_str_new_uniq_args { @@ -361,10 +372,10 @@ upcall_s_str_new_shared(s_str_new_shared_args *args) { vec_size<char>(str_fill), "str_new_shared"); rust_str *str = (rust_str *)box_body(args->retval); - str->fill = str_fill; - str->alloc = str_alloc; - memcpy(&str->data, args->cstr, args->len); - str->data[args->len] = '\0'; + str->body.fill = str_fill; + str->body.alloc = str_alloc; + memcpy(&str->body.data, args->cstr, args->len); + str->body.data[args->len] = '\0'; } extern "C" CDECL rust_opaque_box* @@ -376,7 +387,7 @@ upcall_str_new_shared(const char *cstr, size_t len) { struct s_vec_grow_args { - rust_vec** vp; + rust_vec_box** vp; size_t new_sz; }; @@ -385,37 +396,38 @@ upcall_s_vec_grow(s_vec_grow_args *args) { rust_task *task = rust_get_current_task(); LOG_UPCALL_ENTRY(task); reserve_vec(task, args->vp, args->new_sz); - (*args->vp)->fill = args->new_sz; + (*args->vp)->body.fill = args->new_sz; } extern "C" CDECL void -upcall_vec_grow(rust_vec** vp, size_t new_sz) { +upcall_vec_grow(rust_vec_box** vp, size_t new_sz) { s_vec_grow_args args = {vp, new_sz}; UPCALL_SWITCH_STACK(&args, upcall_s_vec_grow); } struct s_str_concat_args { - rust_vec* lhs; - rust_vec* rhs; - rust_vec* retval; + rust_vec_box* lhs; + rust_vec_box* rhs; + rust_vec_box* retval; }; extern "C" CDECL void upcall_s_str_concat(s_str_concat_args *args) { - rust_vec *lhs = args->lhs; - rust_vec *rhs = args->rhs; + rust_vec *lhs = &args->lhs->body; + rust_vec *rhs = &args->rhs->body; rust_task *task = rust_get_current_task(); size_t fill = lhs->fill + rhs->fill - 1; - rust_vec* v = (rust_vec*)task->kernel->malloc(fill + sizeof(rust_vec), - "str_concat"); - v->fill = v->alloc = fill; - memmove(&v->data[0], &lhs->data[0], lhs->fill - 1); - memmove(&v->data[lhs->fill - 1], &rhs->data[0], rhs->fill); + rust_vec_box* v = (rust_vec_box*) + task->kernel->malloc(fill + sizeof(rust_vec_box), + "str_concat"); + v->body.fill = v->body.alloc = fill; + memmove(&v->body.data[0], &lhs->data[0], lhs->fill - 1); + memmove(&v->body.data[lhs->fill - 1], &rhs->data[0], rhs->fill); args->retval = v; } -extern "C" CDECL rust_vec* -upcall_str_concat(rust_vec* lhs, rust_vec* rhs) { +extern "C" CDECL rust_vec_box* +upcall_str_concat(rust_vec_box* lhs, rust_vec_box* rhs) { s_str_concat_args args = {lhs, rhs, 0}; UPCALL_SWITCH_STACK(&args, upcall_s_str_concat); return args.retval; diff --git a/src/rt/rust_upcall.h b/src/rt/rust_upcall.h index 0030ef19b36..b2b2db20674 100644 --- a/src/rt/rust_upcall.h +++ b/src/rt/rust_upcall.h @@ -1,9 +1,4 @@ - #ifndef RUST_UPCALL_H #define RUST_UPCALL_H -// Upcalls used from C code on occasion: - -extern "C" CDECL void upcall_shared_free(void* ptr); - #endif diff --git a/src/rt/rust_util.h b/src/rt/rust_util.h index b517362df1f..3a7bd0b7d71 100644 --- a/src/rt/rust_util.h +++ b/src/rt/rust_util.h @@ -42,9 +42,16 @@ rust_vec uint8_t data[0]; }; +struct +rust_vec_box +{ + rust_opaque_box header; + rust_vec body; +}; + template <typename T> inline size_t vec_size(size_t elems) { - return sizeof(rust_vec) + sizeof(T) * elems; + return sizeof(rust_vec_box) + sizeof(T) * elems; } template <typename T> @@ -53,19 +60,20 @@ vec_data(rust_vec *v) { return reinterpret_cast<T*>(v->data); } -inline void reserve_vec_exact(rust_task* task, rust_vec** vpp, size_t size) { - if (size > (*vpp)->alloc) { - *vpp = (rust_vec*)task->kernel - ->realloc(*vpp, size + sizeof(rust_vec)); - (*vpp)->alloc = size; +inline void reserve_vec_exact(rust_task* task, rust_vec_box** vpp, + size_t size) { + if (size > (*vpp)->body.alloc) { + *vpp = (rust_vec_box*)task->kernel + ->realloc(*vpp, size + sizeof(rust_vec_box)); + (*vpp)->body.alloc = size; } } -inline void reserve_vec(rust_task* task, rust_vec** vpp, size_t size) { +inline void reserve_vec(rust_task* task, rust_vec_box** vpp, size_t size) { reserve_vec_exact(task, vpp, next_power_of_two(size)); } -typedef rust_vec rust_str; +typedef rust_vec_box rust_str; inline rust_str * make_str(rust_kernel* kernel, const char* c, size_t strlen, @@ -74,24 +82,24 @@ make_str(rust_kernel* kernel, const char* c, size_t strlen, size_t str_alloc = str_fill; rust_str *str = (rust_str *) kernel->malloc(vec_size<char>(str_fill), name); - str->fill = str_fill; - str->alloc = str_alloc; - memcpy(&str->data, c, strlen); - str->data[strlen] = '\0'; + str->body.fill = str_fill; + str->body.alloc = str_alloc; + memcpy(&str->body.data, c, strlen); + str->body.data[strlen] = '\0'; return str; } -inline rust_vec * +inline rust_vec_box * make_str_vec(rust_kernel* kernel, size_t nstrs, char **strs) { - rust_vec *v = (rust_vec *) - kernel->malloc(vec_size<rust_vec*>(nstrs), + rust_vec_box *v = (rust_vec_box *) + kernel->malloc(vec_size<rust_vec_box*>(nstrs), "str vec interior"); - v->fill = v->alloc = sizeof(rust_vec*) * nstrs; + v->body.fill = v->body.alloc = sizeof(rust_vec_box*) * nstrs; for (size_t i = 0; i < nstrs; ++i) { rust_str *str = make_str(kernel, strs[i], strlen(strs[i]), "str"); - ((rust_str**)&v->data)[i] = str; + ((rust_str**)&v->body.data)[i] = str; } return v; } diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index d982110bb99..8a627795850 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -74,10 +74,6 @@ upcall_validate_box upcall_log_type upcall_malloc upcall_rust_personality -upcall_s_shared_malloc -upcall_shared_malloc -upcall_shared_free -upcall_shared_realloc upcall_vec_grow upcall_str_new upcall_str_new_uniq @@ -88,6 +84,9 @@ upcall_call_shim_on_rust_stack upcall_new_stack upcall_del_stack upcall_reset_stack_limit +upcall_exchange_malloc +upcall_exchange_malloc_dyn +upcall_exchange_free rust_uv_loop_new rust_uv_loop_delete rust_uv_loop_refcount @@ -161,4 +160,4 @@ rust_port_take rust_port_drop rust_port_task rust_task_inhibit_kill -rust_task_allow_kill \ No newline at end of file +rust_task_allow_kill diff --git a/src/rustc/back/upcall.rs b/src/rustc/back/upcall.rs index 7cc71fca0b2..33fec5fab03 100644 --- a/src/rustc/back/upcall.rs +++ b/src/rustc/back/upcall.rs @@ -3,8 +3,8 @@ import driver::session; import middle::trans::base; import middle::trans::common::{T_fn, T_i1, T_i8, T_i32, T_int, T_nil, - T_opaque_vec, T_ptr, - T_size_t, T_void}; + T_opaque_vec, T_ptr, T_unique_ptr, + T_size_t, T_void, T_vec2}; import lib::llvm::{type_names, ModuleRef, ValueRef, TypeRef}; type upcalls = @@ -12,10 +12,10 @@ type upcalls = trace: ValueRef, malloc: ValueRef, free: ValueRef, + exchange_malloc: ValueRef, + exchange_malloc_dyn: ValueRef, + exchange_free: ValueRef, validate_box: ValueRef, - shared_malloc: ValueRef, - shared_free: ValueRef, - shared_realloc: ValueRef, mark: ValueRef, vec_grow: ValueRef, str_new_uniq: ValueRef, @@ -49,7 +49,6 @@ fn declare_upcalls(targ_cfg: @session::config, let int_t = T_int(targ_cfg); let size_t = T_size_t(targ_cfg); - let opaque_vec_t = T_opaque_vec(targ_cfg); ret @{_fail: dv("fail", [T_ptr(T_i8()), T_ptr(T_i8()), @@ -62,29 +61,31 @@ fn declare_upcalls(targ_cfg: @session::config, T_ptr(T_i8()))), free: nothrow(dv("free", [T_ptr(T_i8())])), + exchange_malloc: + nothrow(d("exchange_malloc", [T_ptr(tydesc_type)], + T_ptr(T_i8()))), + exchange_malloc_dyn: + nothrow(d("exchange_malloc_dyn", + [T_ptr(tydesc_type), int_t], + T_ptr(T_i8()))), + exchange_free: + nothrow(dv("exchange_free", [T_ptr(T_i8())])), validate_box: nothrow(dv("validate_box", [T_ptr(T_i8())])), - shared_malloc: - nothrow(d("shared_malloc", [size_t], T_ptr(T_i8()))), - shared_free: - nothrow(dv("shared_free", [T_ptr(T_i8())])), - shared_realloc: - nothrow(d("shared_realloc", [T_ptr(T_i8()), size_t], - T_ptr(T_i8()))), mark: d("mark", [T_ptr(T_i8())], int_t), vec_grow: - nothrow(dv("vec_grow", [T_ptr(T_ptr(opaque_vec_t)), int_t])), + nothrow(dv("vec_grow", [T_ptr(T_ptr(T_i8())), int_t])), str_new_uniq: nothrow(d("str_new_uniq", [T_ptr(T_i8()), int_t], - T_ptr(opaque_vec_t))), + T_ptr(T_i8()))), str_new_shared: nothrow(d("str_new_shared", [T_ptr(T_i8()), int_t], T_ptr(T_i8()))), str_concat: - nothrow(d("str_concat", [T_ptr(opaque_vec_t), - T_ptr(opaque_vec_t)], - T_ptr(opaque_vec_t))), + nothrow(d("str_concat", [T_ptr(T_i8()), + T_ptr(T_i8())], + T_ptr(T_i8()))), cmp_type: dv("cmp_type", [T_ptr(T_i1()), T_ptr(tydesc_type), diff --git a/src/rustc/middle/trans/alt.rs b/src/rustc/middle/trans/alt.rs index 3cac9f3685e..5c079f30106 100644 --- a/src/rustc/middle/trans/alt.rs +++ b/src/rustc/middle/trans/alt.rs @@ -471,7 +471,8 @@ fn compile_submatch(bcx: block, m: match, vals: [ValueRef], } if any_uniq_pat(m, col) { - let unboxed = Load(bcx, val); + let box = Load(bcx, val); + let unboxed = GEPi(bcx, box, [0u, abi::box_field_body]); compile_submatch(bcx, enter_uniq(dm, m, col, val), [unboxed] + vals_left, chk, exits); ret; @@ -762,8 +763,10 @@ fn bind_irrefutable_pat(bcx: block, pat: @ast::pat, val: ValueRef, bcx = bind_irrefutable_pat(bcx, inner, unboxed, true); } ast::pat_uniq(inner) { - let val = Load(bcx, val); - bcx = bind_irrefutable_pat(bcx, inner, val, true); + let box = Load(bcx, val); + let unboxed = + GEPi(bcx, box, [0u, abi::box_field_body]); + bcx = bind_irrefutable_pat(bcx, inner, unboxed, true); } ast::pat_wild | ast::pat_lit(_) | ast::pat_range(_, _) { } } diff --git a/src/rustc/middle/trans/base.rs b/src/rustc/middle/trans/base.rs index 1dee76c61ed..a95797fd7e3 100644 --- a/src/rustc/middle/trans/base.rs +++ b/src/rustc/middle/trans/base.rs @@ -236,9 +236,9 @@ fn trans_free(cx: block, v: ValueRef) -> block { cx } -fn trans_shared_free(cx: block, v: ValueRef) -> block { +fn trans_unique_free(cx: block, v: ValueRef) -> block { let _icx = cx.insn_ctxt("trans_shared_free"); - Call(cx, cx.ccx().upcalls.shared_free, + Call(cx, cx.ccx().upcalls.exchange_free, [PointerCast(cx, v, T_ptr(T_i8()))]); ret cx; } @@ -326,15 +326,6 @@ fn GEP_enum(bcx: block, llblobptr: ValueRef, enum_id: ast::def_id, GEPi(bcx, typed_blobptr, [0u, ix]) } -// trans_shared_malloc: expects a type indicating which pointer type we want -// and a size indicating how much space we want malloc'd. -fn shared_malloc(cx: block, llptr_ty: TypeRef, llsize: ValueRef) - -> ValueRef { - let _icx = cx.insn_ctxt("opaque_shared_malloc"); - let rval = Call(cx, cx.ccx().upcalls.shared_malloc, [llsize]); - PointerCast(cx, rval, llptr_ty) -} - // Returns a pointer to the body for the box. The box may be an opaque // box. The result will be casted to the type of body_t, if it is statically // known. @@ -384,6 +375,59 @@ fn malloc_boxed(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} { ret {box: box, body: body}; } +fn malloc_unique_raw(bcx: block, t: ty::t) -> ValueRef { + let _icx = bcx.insn_ctxt("malloc_unique_box_raw"); + let ccx = bcx.ccx(); + + // Grab the TypeRef type of box_ptr, because that's what trans_raw_malloc + // wants. + let box_ptr = ty::mk_imm_uniq(ccx.tcx, t); + let llty = type_of(ccx, box_ptr); + + // Get the tydesc for the body: + let mut static_ti = none; + let lltydesc = get_tydesc(ccx, t, static_ti); + lazily_emit_all_tydesc_glue(ccx, static_ti); + + // Allocate space: + let rval = Call(bcx, ccx.upcalls.exchange_malloc, [lltydesc]); + ret PointerCast(bcx, rval, llty); +} + +fn malloc_unique(bcx: block, t: ty::t) -> {box: ValueRef, body: ValueRef} { + let _icx = bcx.insn_ctxt("malloc_unique_box"); + let box = malloc_unique_raw(bcx, t); + let body = GEPi(bcx, box, [0u, abi::box_field_body]); + ret {box: box, body: body}; +} + +fn malloc_unique_dyn_raw(bcx: block, t: ty::t, size: ValueRef) -> ValueRef { + let _icx = bcx.insn_ctxt("malloc_unique_box_raw"); + let ccx = bcx.ccx(); + + // Grab the TypeRef type of box_ptr, because that's what trans_raw_malloc + // wants. + let box_ptr = ty::mk_imm_uniq(ccx.tcx, t); + let llty = type_of(ccx, box_ptr); + + // Get the tydesc for the body: + let mut static_ti = none; + let lltydesc = get_tydesc(ccx, t, static_ti); + lazily_emit_all_tydesc_glue(ccx, static_ti); + + // Allocate space: + let rval = Call(bcx, ccx.upcalls.exchange_malloc_dyn, [lltydesc, size]); + ret PointerCast(bcx, rval, llty); +} + +fn malloc_unique_dyn(bcx: block, t: ty::t, size: ValueRef + ) -> {box: ValueRef, body: ValueRef} { + let _icx = bcx.insn_ctxt("malloc_unique_box"); + let box = malloc_unique_dyn_raw(bcx, t, size); + let body = GEPi(bcx, box, [0u, abi::box_field_body]); + ret {box: box, body: body}; +} + // Type descriptor and type glue stuff fn get_tydesc_simple(ccx: @crate_ctxt, t: ty::t) -> ValueRef { @@ -1754,7 +1798,7 @@ fn autoderef(cx: block, e_id: ast::node_id, v1 = PointerCast(cx, body, T_ptr(llty)); } ty::ty_uniq(_) { - let derefed = uniq::autoderef(v1, t1); + let derefed = uniq::autoderef(cx, v1, t1); t1 = derefed.t; v1 = derefed.v; } @@ -2636,6 +2680,9 @@ fn trans_lval(cx: block, e: @ast::expr) -> lval_result { let non_gc_val = non_gc_box_cast(sub.bcx, sub.val, t); GEPi(sub.bcx, non_gc_val, [0u, abi::box_field_body]) } + ty::ty_uniq(_) { + GEPi(sub.bcx, sub.val, [0u, abi::box_field_body]) + } ty::ty_res(_, _, _) { GEPi(sub.bcx, sub.val, [0u, 1u]) } @@ -2644,7 +2691,7 @@ fn trans_lval(cx: block, e: @ast::expr) -> lval_result { let ellty = T_ptr(type_of(ccx, ety)); PointerCast(sub.bcx, sub.val, ellty) } - ty::ty_ptr(_) | ty::ty_uniq(_) | ty::ty_rptr(_,_) { sub.val } + ty::ty_ptr(_) | ty::ty_rptr(_,_) { sub.val } }; ret lval_owned(sub.bcx, val); } @@ -2920,7 +2967,15 @@ fn adapt_borrowed_value(lv: lval_result, _arg: ty::arg, } ty::ty_uniq(_) { - ret lv; // no change needed at runtime (I think) + let box_ptr = { + alt lv.kind { + temporary { lv.val } + owned { Load(bcx, lv.val) } + owned_imm { lv.val } + } + }; + let body_ptr = GEPi(bcx, box_ptr, [0u, abi::box_field_body]); + ret lval_temp(bcx, body_ptr); } ty::ty_str | ty::ty_vec(_) | @@ -3817,9 +3872,11 @@ fn trans_fail_expr(bcx: block, sp_opt: option<span>, bcx = expr_res.bcx; if ty::type_is_str(e_ty) { - let data = tvec::get_dataptr( - bcx, expr_res.val, type_of( - ccx, ty::mk_mach_uint(tcx, ast::ty_u8))); + let unit_ty = ty::mk_mach_uint(tcx, ast::ty_u8); + let vec_ty = ty::mk_vec(tcx, {ty: unit_ty, mutbl: ast::m_imm}); + let unit_llty = type_of(ccx, unit_ty); + let body = tvec::get_bodyptr(bcx, expr_res.val, vec_ty); + let data = tvec::get_dataptr(bcx, body, unit_llty); ret trans_fail_value(bcx, sp_opt, data); } else if bcx.unreachable || ty::type_is_bot(e_ty) { ret bcx; diff --git a/src/rustc/middle/trans/closure.rs b/src/rustc/middle/trans/closure.rs index 7f58053165d..a3b2ab85d58 100644 --- a/src/rustc/middle/trans/closure.rs +++ b/src/rustc/middle/trans/closure.rs @@ -116,7 +116,7 @@ fn ev_to_str(ccx: @crate_ctxt, ev: environment_value) -> str { } fn mk_tuplified_uniq_cbox_ty(tcx: ty::ctxt, cdata_ty: ty::t) -> ty::t { - let cbox_ty = tuplify_cbox_ty(tcx, cdata_ty, ty::mk_type(tcx)); + let cbox_ty = tuplify_box_ty(tcx, cdata_ty); ret ty::mk_imm_uniq(tcx, cbox_ty); } @@ -179,10 +179,7 @@ fn allocate_cbox(bcx: block, (bcx, box) } ty::ck_uniq { - let uniq_cbox_ty = mk_tuplified_uniq_cbox_ty(tcx, cdata_ty); - let box = uniq::alloc_uniq(bcx, uniq_cbox_ty); - nuke_ref_count(bcx, box); - let bcx = store_tydesc(bcx, cdata_ty, box, ti); + let box = malloc_unique_raw(bcx, cdata_ty); (bcx, box) } ty::ck_block { @@ -557,8 +554,8 @@ fn make_opaque_cbox_take_glue( let sz = Add(bcx, sz, shape::llsize_of(ccx, T_box_header(ccx))); // Allocate memory, update original ptr, and copy existing data - let malloc = ccx.upcalls.shared_malloc; - let cbox_out = Call(bcx, malloc, [sz]); + let malloc = ccx.upcalls.exchange_malloc; + let cbox_out = Call(bcx, malloc, [tydesc]); let cbox_out = PointerCast(bcx, cbox_out, llopaquecboxty); call_memmove(bcx, cbox_out, cbox_in, sz); Store(bcx, cbox_out, cboxptr); @@ -606,7 +603,7 @@ fn make_opaque_cbox_free_glue( ty::ck_box | ty::ck_uniq { /* hard cases: */ } } - let ccx = bcx.ccx(), tcx = ccx.tcx; + let ccx = bcx.ccx(); with_cond(bcx, IsNotNull(bcx, cbox)) {|bcx| // Load the type descr found in the cbox let lltydescty = T_ptr(ccx.tydesc_type); @@ -628,8 +625,7 @@ fn make_opaque_cbox_free_glue( trans_free(bcx, cbox) } ty::ck_uniq { - let bcx = free_ty(bcx, tydesc, ty::mk_type(tcx)); - trans_shared_free(bcx, cbox) + trans_unique_free(bcx, cbox) } } } diff --git a/src/rustc/middle/trans/common.rs b/src/rustc/middle/trans/common.rs index c0994192a4e..194a1993ce3 100644 --- a/src/rustc/middle/trans/common.rs +++ b/src/rustc/middle/trans/common.rs @@ -271,7 +271,7 @@ fn add_clean_temp_mem(cx: block, val: ValueRef, ty: ty::t) { } } fn add_clean_free(cx: block, ptr: ValueRef, shared: bool) { - let free_fn = if shared { bind base::trans_shared_free(_, ptr) } + let free_fn = if shared { bind base::trans_unique_free(_, ptr) } else { bind base::trans_free(_, ptr) }; in_scope_cx(cx) {|info| info.cleanups += [clean_temp(ptr, free_fn, @@ -654,15 +654,8 @@ fn T_opaque_vec(targ_cfg: @session::config) -> TypeRef { // representation of @T as a tuple (i.e., the ty::t version of what T_box() // returns). fn tuplify_box_ty(tcx: ty::ctxt, t: ty::t) -> ty::t { - ret tuplify_cbox_ty(tcx, t, ty::mk_type(tcx)); -} - -// As tuplify_box_ty(), but allows the caller to specify what type of type -// descr is embedded in the box (ty::type vs ty::send_type). This is useful -// for unique closure boxes, hence the name "cbox_ty" (closure box type). -fn tuplify_cbox_ty(tcx: ty::ctxt, t: ty::t, tydesc_t: ty::t) -> ty::t { let ptr = ty::mk_ptr(tcx, {ty: ty::mk_nil(tcx), mutbl: ast::m_imm}); - ret ty::mk_tup(tcx, [ty::mk_uint(tcx), tydesc_t, + ret ty::mk_tup(tcx, [ty::mk_uint(tcx), ty::mk_type(tcx), ptr, ptr, t]); } @@ -693,6 +686,15 @@ fn T_opaque_box_ptr(cx: @crate_ctxt) -> TypeRef { ret T_box_ptr(T_opaque_box(cx)); } +fn T_unique(cx: @crate_ctxt, t: TypeRef) -> TypeRef { + ret T_struct(T_box_header_fields(cx) + [t]); +} + +fn T_unique_ptr(t: TypeRef) -> TypeRef { + const unique_addrspace: uint = 0u; + ret llvm::LLVMPointerType(t, unique_addrspace as c_uint); +} + fn T_port(cx: @crate_ctxt, _t: TypeRef) -> TypeRef { ret T_struct([cx.int_type]); // Refcount diff --git a/src/rustc/middle/trans/tvec.rs b/src/rustc/middle/trans/tvec.rs index bcc5bbc3fa0..e37806dccf8 100644 --- a/src/rustc/middle/trans/tvec.rs +++ b/src/rustc/middle/trans/tvec.rs @@ -2,7 +2,7 @@ import syntax::ast; import driver::session::session; import lib::llvm::{ValueRef, TypeRef}; import back::abi; -import base::{call_memmove, shared_malloc, +import base::{call_memmove, INIT, copy_val, load_if_immediate, get_tydesc, sub_block, do_spill_noroot, dest, bcx_icx}; @@ -21,6 +21,24 @@ fn set_fill(bcx: block, vptr: ValueRef, fill: ValueRef) { fn get_alloc(bcx: block, vptr: ValueRef) -> ValueRef { Load(bcx, GEPi(bcx, vptr, [0u, abi::vec_elt_alloc])) } + +fn get_bodyptr(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> ValueRef { + let ccx = bcx.ccx(); + alt ty::get(vec_ty).struct { + ty::ty_evec(_, ty::vstore_uniq) | ty::ty_estr(ty::vstore_uniq) + | ty::ty_vec(_) | ty::ty_str { + let boxptr = PointerCast(bcx, vptr, T_ptr(T_box_header(ccx))); + let bodyptr = GEPi(bcx, boxptr, [1u]); + let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty); + let llunit_ty = type_of::type_of(ccx, unit_ty); + PointerCast(bcx, bodyptr, T_ptr(T_vec(ccx, llunit_ty))) + } + _ { + vptr + } + } +} + fn get_dataptr(bcx: block, vptr: ValueRef, unit_ty: TypeRef) -> ValueRef { let _icx = bcx.insn_ctxt("tvec::get_dataptr"); @@ -35,41 +53,55 @@ fn pointer_add(bcx: block, ptr: ValueRef, bytes: ValueRef) -> ValueRef { ret PointerCast(bcx, InBoundsGEP(bcx, bptr, [bytes]), old_ty); } -fn alloc_uniq_raw(bcx: block, fill: ValueRef, alloc: ValueRef) -> result { +fn alloc_uniq_raw(bcx: block, unit_ty: ty::t, + fill: ValueRef, alloc: ValueRef) -> result { let _icx = bcx.insn_ctxt("tvec::alloc_uniq_raw"); let ccx = bcx.ccx(); - let llvecty = ccx.opaque_vec_type; + let llunitty = type_of::type_of(ccx, unit_ty); + let llvecty = T_vec(ccx, llunitty); let vecsize = Add(bcx, alloc, llsize_of(ccx, llvecty)); - let vecptr = shared_malloc(bcx, T_ptr(llvecty), vecsize); - Store(bcx, fill, GEPi(bcx, vecptr, [0u, abi::vec_elt_fill])); - Store(bcx, alloc, GEPi(bcx, vecptr, [0u, abi::vec_elt_alloc])); - ret {bcx: bcx, val: vecptr}; + let vecbodyty = unit_ty; // FIXME: This is not the correct type + let {box, body} = base::malloc_unique_dyn(bcx, vecbodyty, vecsize); + let boxptr = PointerCast(bcx, box, + T_unique_ptr(T_unique(bcx.ccx(), llvecty))); + let bodyptr = PointerCast(bcx, body, T_ptr(llvecty)); + Store(bcx, fill, GEPi(bcx, bodyptr, [0u, abi::vec_elt_fill])); + Store(bcx, alloc, GEPi(bcx, bodyptr, [0u, abi::vec_elt_alloc])); + ret {bcx: bcx, val: boxptr}; } -fn alloc_uniq(bcx: block, llunitty: TypeRef, elts: uint) -> result { +fn alloc_uniq(bcx: block, unit_ty: ty::t, elts: uint) -> result { let _icx = bcx.insn_ctxt("tvec::alloc_uniq"); let ccx = bcx.ccx(); - let llvecty = T_vec(ccx, llunitty); + let llunitty = type_of::type_of(ccx, unit_ty); let unit_sz = llsize_of(ccx, llunitty); let fill = Mul(bcx, C_uint(ccx, elts), unit_sz); let alloc = if elts < 4u { Mul(bcx, C_int(ccx, 4), unit_sz) } else { fill }; - let {bcx: bcx, val: vptr} = alloc_uniq_raw(bcx, fill, alloc); - let vptr = PointerCast(bcx, vptr, T_ptr(llvecty)); - + let {bcx: bcx, val: vptr} = alloc_uniq_raw(bcx, unit_ty, fill, alloc); ret {bcx: bcx, val: vptr}; } fn duplicate_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> result { let _icx = bcx.insn_ctxt("tvec::duplicate_uniq"); let ccx = bcx.ccx(); - let fill = get_fill(bcx, vptr); + let body_ptr = get_bodyptr(bcx, vptr, vec_ty); + let fill = get_fill(bcx, body_ptr); let size = Add(bcx, fill, llsize_of(ccx, ccx.opaque_vec_type)); - let newptr = shared_malloc(bcx, val_ty(vptr), size); - call_memmove(bcx, newptr, vptr, size); + let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty); - Store(bcx, fill, GEPi(bcx, newptr, [0u, abi::vec_elt_alloc])); + let llunitty = type_of::type_of(ccx, unit_ty); + let llvecty = T_vec(ccx, llunitty); + let vecbodyty = unit_ty; // FIXME: This is not the correct type + let {box: newptr, body: new_body_ptr} = + base::malloc_unique_dyn(bcx, vecbodyty, size); + let newptr = PointerCast(bcx, newptr, + T_unique_ptr(T_unique(bcx.ccx(), llvecty))); + let new_body_ptr = PointerCast(bcx, new_body_ptr, T_ptr(llvecty)); + call_memmove(bcx, new_body_ptr, body_ptr, size); + + Store(bcx, fill, GEPi(bcx, new_body_ptr, [0u, abi::vec_elt_alloc])); let bcx = if ty::type_needs_drop(bcx.tcx(), unit_ty) { iter_vec(bcx, newptr, vec_ty, base::take_ty) } else { bcx }; @@ -83,7 +115,7 @@ fn make_free_glue(bcx: block, vptr: ValueRef, vec_ty: ty::t) -> let bcx = if ty::type_needs_drop(tcx, unit_ty) { iter_vec(bcx, vptr, vec_ty, base::drop_ty) } else { bcx }; - base::trans_shared_free(bcx, vptr) + base::trans_unique_free(bcx, vptr) } } @@ -133,9 +165,10 @@ fn trans_evec(bcx: block, args: [@ast::expr], {bcx: bcx, val: p, dataptr: vp} } ast::vstore_uniq { - let {bcx, val} = alloc_uniq(bcx, llunitty, args.len()); + let {bcx, val} = alloc_uniq(bcx, unit_ty, args.len()); add_clean_free(bcx, val, true); - let dataptr = get_dataptr(bcx, val, llunitty); + let body = get_bodyptr(bcx, val, vec_ty); + let dataptr = get_dataptr(bcx, body, llunitty); {bcx: bcx, val: val, dataptr: dataptr} } ast::vstore_box { @@ -216,8 +249,9 @@ fn get_base_and_len(cx: block, v: ValueRef, e_ty: ty::t) (base, len) } ty::vstore_uniq { - let base = tvec::get_dataptr(cx, v, llunitty); - let len = tvec::get_fill(cx, v); + let body = tvec::get_bodyptr(cx, v, vec_ty); + let base = tvec::get_dataptr(cx, body, llunitty); + let len = tvec::get_fill(cx, body); (base, len) } ty::vstore_box { @@ -249,7 +283,9 @@ fn trans_estr(bcx: block, s: str, vstore: ast::vstore, ast::vstore_uniq { let cs = PointerCast(bcx, C_cstr(ccx, s), T_ptr(T_i8())); let len = C_uint(ccx, str::len(s)); - Call(bcx, ccx.upcalls.str_new_uniq, [cs, len]) + let c = Call(bcx, ccx.upcalls.str_new_uniq, [cs, len]); + PointerCast(bcx, c, + T_unique_ptr(T_unique(ccx, T_vec(ccx, T_i8())))) } ast::vstore_box { @@ -274,19 +310,23 @@ fn trans_append(bcx: block, vec_ty: ty::t, lhsptr: ValueRef, let lhs = Load(bcx, lhsptr); let self_append = ICmp(bcx, lib::llvm::IntEQ, lhs, rhs); - let lfill = get_fill(bcx, lhs); - let rfill = get_fill(bcx, rhs); + let lbody = get_bodyptr(bcx, lhs, vec_ty); + let rbody = get_bodyptr(bcx, rhs, vec_ty); + let lfill = get_fill(bcx, lbody); + let rfill = get_fill(bcx, rbody); let mut new_fill = Add(bcx, lfill, rfill); if strings { new_fill = Sub(bcx, new_fill, C_int(ccx, 1)); } let opaque_lhs = PointerCast(bcx, lhsptr, - T_ptr(T_ptr(ccx.opaque_vec_type))); + T_ptr(T_ptr(T_i8()))); Call(bcx, ccx.upcalls.vec_grow, [opaque_lhs, new_fill]); // Was overwritten if we resized let lhs = Load(bcx, lhsptr); let rhs = Select(bcx, self_append, lhs, rhs); - let lhs_data = get_dataptr(bcx, lhs, llunitty); + let lbody = get_bodyptr(bcx, lhs, vec_ty); + + let lhs_data = get_dataptr(bcx, lbody, llunitty); let mut lhs_off = lfill; if strings { lhs_off = Sub(bcx, lhs_off, C_int(ccx, 1)); } let write_ptr = pointer_add(bcx, lhs_data, lhs_off); @@ -311,18 +351,18 @@ fn trans_append_literal(bcx: block, vptrptr: ValueRef, vec_ty: ty::t, let scratch = base::alloca(bcx, elt_llty); for vec::each(vals) {|val| bcx = base::trans_expr_save_in(bcx, val, scratch); - let vptr = Load(bcx, vptrptr); + let vptr = get_bodyptr(bcx, Load(bcx, vptrptr), vec_ty); let old_fill = get_fill(bcx, vptr); let new_fill = Add(bcx, old_fill, elt_sz); let do_grow = ICmp(bcx, lib::llvm::IntUGT, new_fill, get_alloc(bcx, vptr)); bcx = base::with_cond(bcx, do_grow) {|bcx| let pt = PointerCast(bcx, vptrptr, - T_ptr(T_ptr(ccx.opaque_vec_type))); + T_ptr(T_ptr(T_i8()))); Call(bcx, ccx.upcalls.vec_grow, [pt, new_fill]); bcx }; - let vptr = Load(bcx, vptrptr); + let vptr = get_bodyptr(bcx, Load(bcx, vptrptr), vec_ty); set_fill(bcx, vptr, new_fill); let targetptr = pointer_add(bcx, get_dataptr(bcx, vptr, elt_llty), old_fill); @@ -336,23 +376,30 @@ fn trans_add(bcx: block, vec_ty: ty::t, lhs: ValueRef, let _icx = bcx.insn_ctxt("tvec::trans_add"); let ccx = bcx.ccx(); + let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty); + let llunitty = type_of::type_of(ccx, unit_ty); + if ty::get(vec_ty).struct == ty::ty_str { + let lhs = PointerCast(bcx, lhs, T_ptr(T_i8())); + let rhs = PointerCast(bcx, rhs, T_ptr(T_i8())); let n = Call(bcx, ccx.upcalls.str_concat, [lhs, rhs]); + let n = PointerCast( + bcx, n, T_unique_ptr(T_unique(ccx, T_vec(ccx, llunitty)))); ret base::store_in_dest(bcx, n, dest); } - let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty); - let llunitty = type_of::type_of(ccx, unit_ty); + let lhs_body = get_bodyptr(bcx, lhs, vec_ty); + let rhs_body = get_bodyptr(bcx, rhs, vec_ty); - let lhs_fill = get_fill(bcx, lhs); - let rhs_fill = get_fill(bcx, rhs); + let lhs_fill = get_fill(bcx, lhs_body); + let rhs_fill = get_fill(bcx, rhs_body); let new_fill = Add(bcx, lhs_fill, rhs_fill); let mut {bcx: bcx, val: new_vec_ptr} = - alloc_uniq_raw(bcx, new_fill, new_fill); - new_vec_ptr = PointerCast(bcx, new_vec_ptr, T_ptr(T_vec(ccx, llunitty))); + alloc_uniq_raw(bcx, unit_ty, new_fill, new_fill); + let new_vec_body_ptr = get_bodyptr(bcx, new_vec_ptr, vec_ty); let write_ptr_ptr = do_spill_noroot - (bcx, get_dataptr(bcx, new_vec_ptr, llunitty)); + (bcx, get_dataptr(bcx, new_vec_body_ptr, llunitty)); let copy_fn = fn@(bcx: block, addr: ValueRef, _ty: ty::t) -> block { let ccx = bcx.ccx(); @@ -408,16 +455,17 @@ fn iter_vec_uniq(bcx: block, vptr: ValueRef, vec_ty: ty::t, let ccx = bcx.ccx(); let unit_ty = ty::sequence_element_type(bcx.tcx(), vec_ty); let llunitty = type_of::type_of(ccx, unit_ty); - let vptr = PointerCast(bcx, vptr, T_ptr(T_vec(ccx, llunitty))); - let data_ptr = get_dataptr(bcx, vptr, llunitty); + let body_ptr = get_bodyptr(bcx, vptr, vec_ty); + let data_ptr = get_dataptr(bcx, body_ptr, llunitty); iter_vec_raw(bcx, data_ptr, vec_ty, fill, f) } fn iter_vec(bcx: block, vptr: ValueRef, vec_ty: ty::t, f: iter_vec_block) -> block { let _icx = bcx.insn_ctxt("tvec::iter_vec"); - let vptr = PointerCast(bcx, vptr, T_ptr(bcx.ccx().opaque_vec_type)); - ret iter_vec_uniq(bcx, vptr, vec_ty, get_fill(bcx, vptr), f); + let body_ptr = get_bodyptr(bcx, vptr, vec_ty); + let fill = get_fill(bcx, body_ptr); + ret iter_vec_uniq(bcx, vptr, vec_ty, fill, f); } // diff --git a/src/rustc/middle/trans/type_of.rs b/src/rustc/middle/trans/type_of.rs index b094a576cb1..fedd7c713cf 100644 --- a/src/rustc/middle/trans/type_of.rs +++ b/src/rustc/middle/trans/type_of.rs @@ -85,15 +85,19 @@ fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef { ty::ty_uint(t) { T_uint_ty(cx, t) } ty::ty_float(t) { T_float_ty(cx, t) } ty::ty_estr(ty::vstore_uniq) | - ty::ty_str { T_ptr(T_vec(cx, T_i8())) } + ty::ty_str { + T_unique_ptr(T_unique(cx, T_vec(cx, T_i8()))) + } ty::ty_enum(did, _) { type_of_enum(cx, did, t) } ty::ty_estr(ty::vstore_box) { T_box_ptr(T_box(cx, T_i8())) } ty::ty_evec(mt, ty::vstore_box) | ty::ty_box(mt) { T_box_ptr(T_box(cx, type_of(cx, mt.ty))) } ty::ty_opaque_box { T_box_ptr(T_box(cx, T_i8())) } - ty::ty_uniq(mt) { T_ptr(type_of(cx, mt.ty)) } + ty::ty_uniq(mt) { T_unique_ptr(T_unique(cx, type_of(cx, mt.ty))) } ty::ty_evec(mt, ty::vstore_uniq) | - ty::ty_vec(mt) { T_ptr(T_vec(cx, type_of(cx, mt.ty))) } + ty::ty_vec(mt) { + T_unique_ptr(T_unique(cx, T_vec(cx, type_of(cx, mt.ty)))) + } ty::ty_ptr(mt) { T_ptr(type_of(cx, mt.ty)) } ty::ty_rptr(_, mt) { T_ptr(type_of(cx, mt.ty)) } diff --git a/src/rustc/middle/trans/uniq.rs b/src/rustc/middle/trans/uniq.rs index bac8033e6ea..a3325fc4904 100644 --- a/src/rustc/middle/trans/uniq.rs +++ b/src/rustc/middle/trans/uniq.rs @@ -5,34 +5,28 @@ import build::*; import base::*; import shape::llsize_of; -export trans_uniq, make_free_glue, autoderef, duplicate, alloc_uniq; +export trans_uniq, make_free_glue, autoderef, duplicate; fn trans_uniq(bcx: block, contents: @ast::expr, node_id: ast::node_id, dest: dest) -> block { let _icx = bcx.insn_ctxt("uniq::trans_uniq"); let uniq_ty = node_id_type(bcx, node_id); - let llptr = alloc_uniq(bcx, uniq_ty); - add_clean_free(bcx, llptr, true); - let bcx = trans_expr_save_in(bcx, contents, llptr); - revoke_clean(bcx, llptr); - ret store_in_dest(bcx, llptr, dest); -} - -fn alloc_uniq(bcx: block, uniq_ty: ty::t) -> ValueRef { - let _icx = bcx.insn_ctxt("uniq::alloc_uniq"); let contents_ty = content_ty(uniq_ty); - let llty = type_of::type_of(bcx.ccx(), contents_ty); - let llsz = llsize_of(bcx.ccx(), llty); - let llptrty = T_ptr(llty); - shared_malloc(bcx, llptrty, llsz) + let {box, body} = malloc_unique(bcx, contents_ty); + add_clean_free(bcx, box, true); + let bcx = trans_expr_save_in(bcx, contents, body); + revoke_clean(bcx, box); + ret store_in_dest(bcx, box, dest); } fn make_free_glue(bcx: block, vptr: ValueRef, t: ty::t) -> block { let _icx = bcx.insn_ctxt("uniq::make_free_glue"); with_cond(bcx, IsNotNull(bcx, vptr)) {|bcx| - let bcx = drop_ty(bcx, vptr, content_ty(t)); - trans_shared_free(bcx, vptr) + let content_ty = content_ty(t); + let body_ptr = opaque_box_body(bcx, content_ty, vptr); + let bcx = drop_ty(bcx, body_ptr, content_ty); + trans_unique_free(bcx, vptr) } } @@ -43,18 +37,31 @@ fn content_ty(t: ty::t) -> ty::t { } } -fn autoderef(v: ValueRef, t: ty::t) -> {v: ValueRef, t: ty::t} { +fn autoderef(bcx: block, v: ValueRef, t: ty::t) -> {v: ValueRef, t: ty::t} { let content_ty = content_ty(t); + let v = opaque_box_body(bcx, content_ty, v); ret {v: v, t: content_ty}; } fn duplicate(bcx: block, v: ValueRef, t: ty::t) -> result { let _icx = bcx.insn_ctxt("uniq::duplicate"); let content_ty = content_ty(t); - let llptr = alloc_uniq(bcx, t); + let {box: dst_box, body: dst_body} = malloc_unique(bcx, content_ty); + + let src_box = v; + let src_body = opaque_box_body(bcx, content_ty, src_box); + let src_body = load_if_immediate(bcx, src_body, content_ty); + #debug("ST: %?", val_str(bcx.ccx().tn, src_body)); + #debug("DT: %?", val_str(bcx.ccx().tn, dst_body)); + let bcx = copy_val(bcx, INIT, dst_body, src_body, content_ty); + + let src_tydesc_ptr = GEPi(bcx, src_box, + [0u, back::abi::box_field_tydesc]); + let dst_tydesc_ptr = GEPi(bcx, dst_box, + [0u, back::abi::box_field_tydesc]); + + let td = Load(bcx, src_tydesc_ptr); + Store(bcx, td, dst_tydesc_ptr); - let src = load_if_immediate(bcx, v, content_ty); - let dst = llptr; - let bcx = copy_val(bcx, INIT, dst, src, content_ty); - ret rslt(bcx, dst); + ret rslt(bcx, dst_box); } \ No newline at end of file diff --git a/src/snapshots.txt b/src/snapshots.txt index 5ca29713c44..c8546daf238 100644 --- a/src/snapshots.txt +++ b/src/snapshots.txt @@ -1,3 +1,11 @@ +S 2012-05-30 0c0818b + winnt-i386 910bc6b562e8e310e99f8174292f2b0a0d93ef6c + linux-x86_64 482bfe7c000bc798945524dd750d3e06be2c0283 + linux-i386 f794e99472bc59773fa5281a4f9e2875e59f812f + freebsd-x86_64 29ec0b56d05c59e3a6eec2a97f17e2429c1a6331 + macos-x86_64 d562f05c8911e7405b0a9ff5815f49fca69045d3 + macos-i386 4d09cc2a4882d92f125718161e3d7086531748e6 + S 2012-05-30 02dde78 winnt-i386 b394e3db0639942a9844ce6f78d34239a90127af linux-x86_64 bd3128bce34f2f131f37bc1c7077a4d2e367ff50 |
