diff options
| author | Marijn Haverbeke <marijnh@gmail.com> | 2011-08-25 10:18:02 +0200 |
|---|---|---|
| committer | Marijn Haverbeke <marijnh@gmail.com> | 2011-08-29 09:07:53 +0200 |
| commit | c9c5ee252a8523778377f2832765442e611e85a4 (patch) | |
| tree | 85c0837af34b2431fc17da0a166254144aaa99c7 /src/rt | |
| parent | 855e0a471365c7c61a139e2437215028bd231af5 (diff) | |
| download | rust-c9c5ee252a8523778377f2832765442e611e85a4.tar.gz rust-c9c5ee252a8523778377f2832765442e611e85a4.zip | |
Implement non-internal ivecs
Vectors are now similar to our old, pre-internal vectors, except that they are uniquely owned, not refcounted. Their name should probably change too, then. I've renamed them to vec in the runtime, will do so throughout the compiler later.
Diffstat (limited to 'src/rt')
| -rw-r--r-- | src/rt/intrinsics/intrinsics.cpp | 13 | ||||
| -rw-r--r-- | src/rt/intrinsics/intrinsics.ll.in | 27 | ||||
| -rw-r--r-- | src/rt/main.ll.in | 10 | ||||
| -rw-r--r-- | src/rt/rust.cpp | 20 | ||||
| -rw-r--r-- | src/rt/rust_builtin.cpp | 222 | ||||
| -rw-r--r-- | src/rt/rust_shape.cpp | 15 | ||||
| -rw-r--r-- | src/rt/rust_shape.h | 85 | ||||
| -rw-r--r-- | src/rt/rust_upcall.cpp | 84 | ||||
| -rw-r--r-- | src/rt/rust_util.h | 24 | ||||
| -rw-r--r-- | src/rt/rust_uv.cpp | 21 | ||||
| -rw-r--r-- | src/rt/rustrt.def.in | 17 |
11 files changed, 132 insertions, 406 deletions
diff --git a/src/rt/intrinsics/intrinsics.cpp b/src/rt/intrinsics/intrinsics.cpp index a9f90326007..bbe0fc811dd 100644 --- a/src/rt/intrinsics/intrinsics.cpp +++ b/src/rt/intrinsics/intrinsics.cpp @@ -9,17 +9,10 @@ extern "C" CDECL void upcall_fail(rust_task *task, char const *expr, char const *file, size_t line); extern "C" void -rust_intrinsic_ivec_len(rust_task *task, size_t *retptr, type_desc *ty, - rust_ivec *v) +rust_intrinsic_vec_len(rust_task *task, size_t *retptr, type_desc *ty, + rust_vec **vp) { - size_t fill; - if (v->fill) - fill = v->fill; - else if (v->payload.ptr) - fill = v->payload.ptr->fill; - else - fill = 0; - *retptr = fill / ty->size; + *retptr = (*vp)->fill / ty->size; } extern "C" void diff --git a/src/rt/intrinsics/intrinsics.ll.in b/src/rt/intrinsics/intrinsics.ll.in index 17937329df5..872cec7fa21 100644 --- a/src/rt/intrinsics/intrinsics.ll.in +++ b/src/rt/intrinsics/intrinsics.ll.in @@ -40,9 +40,7 @@ target triple = "@CFG_LLVM_TRIPLE@" %struct.registers_t = type { i32, i32, i32, i32, i32, i32, i32, i32, i16, i16, i16, i16, i16, i16, i32, i32 } %"class.rust_task::wakeup_callback" = type { i32 (...)** } %struct.rc_base.5 = type { i32 } -%struct.rust_ivec = type { i32, i32, %union.rust_ivec_payload } -%union.rust_ivec_payload = type { %struct.rust_ivec_heap* } -%struct.rust_ivec_heap = type { i32, [0 x i8] } +%struct.rust_vec = type { i32, i32, [ 0 x i8 ] } %class.rust_port = type { i32, %class.rust_kernel*, %struct.rust_task*, i32, %class.ptr_vec, %class.ptr_vec.7, %class.rust_chan*, %class.lock_and_signal } %class.ptr_vec = type { %struct.rust_task*, i32, i32, %struct.rust_token** } %struct.rust_token = type opaque @@ -53,29 +51,14 @@ target triple = "@CFG_LLVM_TRIPLE@" @.str = private unnamed_addr constant [42 x i8] c"attempt to cast values of differing sizes\00", align 1 @.str1 = private unnamed_addr constant [15 x i8] c"intrinsics.cpp\00", align 1 -define linkonce_odr void @rust_intrinsic_ivec_len(%struct.rust_task* nocapture %task, i32* nocapture %retptr, %struct.type_desc* nocapture %ty, %struct.rust_ivec* nocapture %v) nounwind { +define linkonce_odr void @rust_intrinsic_vec_len(%struct.rust_task* nocapture %task, i32* nocapture %retptr, %struct.type_desc* nocapture %ty, %struct.rust_vec** nocapture %v) nounwind { entry: - %fill1 = getelementptr inbounds %struct.rust_ivec* %v, i32 0, i32 0 + %ptr1 = load %struct.rust_vec** %v, align 4, !tbaa !0 + %fill1 = getelementptr inbounds %struct.rust_vec* %ptr1, i32 0, i32 0 %tmp2 = load i32* %fill1, align 4, !tbaa !0 - %tobool = icmp eq i32 %tmp2, 0 - br i1 %tobool, label %if.else, label %if.end17 - -if.else: ; preds = %entry - %ptr = getelementptr inbounds %struct.rust_ivec* %v, i32 0, i32 2, i32 0 - %tmp7 = load %struct.rust_ivec_heap** %ptr, align 4, !tbaa !3 - %tobool8 = icmp eq %struct.rust_ivec_heap* %tmp7, null - br i1 %tobool8, label %if.end17, label %if.then9 - -if.then9: ; preds = %if.else - %fill14 = getelementptr inbounds %struct.rust_ivec_heap* %tmp7, i32 0, i32 0 - %tmp15 = load i32* %fill14, align 4, !tbaa !0 - br label %if.end17 - -if.end17: ; preds = %if.else, %entry, %if.then9 - %fill.0 = phi i32 [ %tmp15, %if.then9 ], [ %tmp2, %entry ], [ 0, %if.else ] %size = getelementptr inbounds %struct.type_desc* %ty, i32 0, i32 1 %tmp20 = load i32* %size, align 4, !tbaa !0 - %div = udiv i32 %fill.0, %tmp20 + %div = udiv i32 %tmp2, %tmp20 store i32 %div, i32* %retptr, align 4, !tbaa !0 ret void } diff --git a/src/rt/main.ll.in b/src/rt/main.ll.in index 391f4d8daaf..6df51e67503 100644 --- a/src/rt/main.ll.in +++ b/src/rt/main.ll.in @@ -10,21 +10,21 @@ %task = type { i32, i32, i32, i32, i32, i32, i32, i32 } -%ivec = type { i32, i32, [4 x { i32, i32, i32, i32, [0 x i8] }*] } +%vec = type { i32, i32, [0 x i8] } @_rust_crate_map_toplevel = external global %0 declare i32 @rust_start(i32, i32, i32, i32) -declare external fastcc void @_rust_main(i1* nocapture, %task*, %2* nocapture, %ivec*) +declare external fastcc void @_rust_main(i1* nocapture, %task*, %2* nocapture, %vec*) -define void @_rust_main_wrap(i1* nocapture, %task *, %2* nocapture, %ivec *) +define void @_rust_main_wrap(i1* nocapture, %task *, %2* nocapture, %vec *) { - tail call fastcc void @_rust_main(i1* %0, %task *%1, %2* nocapture %2, %ivec* %3) + tail call fastcc void @_rust_main(i1* %0, %task *%1, %2* nocapture %2, %vec* %3) ret void } define i32 @"MAIN"(i32, i32) { - %3 = tail call i32 @rust_start(i32 ptrtoint (void (i1*, %task*, %2*, %ivec*)* @_rust_main_wrap to i32), i32 %0, i32 %1, i32 ptrtoint (%0* @_rust_crate_map_toplevel to i32)) + %3 = tail call i32 @rust_start(i32 ptrtoint (void (i1*, %task*, %2*, %vec*)* @_rust_main_wrap to i32), i32 %0, i32 %1, i32 ptrtoint (%0* @_rust_crate_map_toplevel to i32)) ret i32 %3 } diff --git a/src/rt/rust.cpp b/src/rt/rust.cpp index a158be04e57..b5a462154ed 100644 --- a/src/rt/rust.cpp +++ b/src/rt/rust.cpp @@ -10,7 +10,7 @@ command_line_args : public kernel_owned<command_line_args> rust_str **strs; // [str] passed to rust_task::start. - rust_ivec *args; + rust_vec *args; command_line_args(rust_task *task, int sys_argc, @@ -51,21 +51,13 @@ command_line_args : public kernel_owned<command_line_args> strs[i]->ref_count++; } - size_t ivec_interior_sz = - sizeof(size_t) * 2 + sizeof(rust_str *) * 4; - args = (rust_ivec *) - kernel->malloc(ivec_interior_sz, + args = (rust_vec *) + kernel->malloc(vec_size<rust_str*>(argc), "command line arg interior"); - args->fill = 0; - size_t ivec_exterior_sz = sizeof(rust_str *) * argc; - args->alloc = ivec_exterior_sz; - // NB: _rust_main owns the ivec payload and will be responsible for + args->fill = args->alloc = sizeof(rust_str *) * argc; + // NB: _rust_main owns the vec and will be responsible for // freeing it - args->payload.ptr = (rust_ivec_heap *) - kernel->malloc(ivec_exterior_sz + sizeof(size_t), - "command line arg exterior"); - args->payload.ptr->fill = ivec_exterior_sz; - memcpy(&args->payload.ptr->data, strs, ivec_exterior_sz); + memcpy(&args->data[0], strs, args->fill); } ~command_line_args() { diff --git a/src/rt/rust_builtin.cpp b/src/rt/rust_builtin.cpp index 044239065e9..a8929677aff 100644 --- a/src/rt/rust_builtin.cpp +++ b/src/rt/rust_builtin.cpp @@ -206,18 +206,14 @@ str_byte_len(rust_task *task, rust_str *s) } extern "C" CDECL rust_str * -str_from_ivec(rust_task *task, rust_ivec *v) +str_from_vec(rust_task *task, rust_vec **vp) { - bool is_interior = v->fill || !v->payload.ptr; - uintptr_t fill = is_interior ? v->fill : v->payload.ptr->fill; - void *data = is_interior ? v->payload.data : v->payload.ptr->data; - - rust_str *st = - vec_alloc_with_data(task, - fill + 1, // +1 to fit at least '\0' - fill, - 1, - fill ? data : NULL); + 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; @@ -226,6 +222,33 @@ str_from_ivec(rust_task *task, rust_ivec *v) return st; } +extern "C" CDECL void +vec_reserve_shared(rust_task* task, type_desc* ty, rust_vec** vp, + size_t n_elts) { + size_t new_sz = n_elts * ty->size; + if (new_sz > (*vp)->alloc) { + size_t new_alloc = next_power_of_two(new_sz); + *vp = (rust_vec*)task->kernel->realloc(*vp, new_alloc + + sizeof(rust_vec)); + (*vp)->alloc = new_alloc; + } +} + +/** + * Copies elements in an unsafe buffer to the given interior vector. The + * vector must have size zero. + */ +extern "C" CDECL rust_vec* +vec_from_buf_shared(rust_task *task, type_desc *ty, + void *ptr, size_t count) { + 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); + return v; +} + extern "C" CDECL rust_str * str_from_cstr(rust_task *task, char *sbuf) { @@ -471,23 +494,19 @@ rust_list_files(rust_task *task, rust_str *path) { closedir(dirp); } #endif - size_t str_ivec_sz = - sizeof(size_t) // fill - + sizeof(size_t) // alloc - + sizeof(rust_str *) * 4; // payload - rust_box *box = (rust_box *)task->malloc(sizeof(rust_box) + str_ivec_sz, - "rust_box(list_files_ivec)"); + rust_box *box = + (rust_box *)task->malloc(sizeof(rust_box) + sizeof(rust_vec*), + "rust_box(list_files_vec)"); + rust_vec* vec = + (rust_vec*)task->kernel->malloc(vec_size<rust_str*>(strings.size()), + "list_files_vec"); box->ref_count = 1; - rust_ivec *iv = (rust_ivec *)&box->data; - iv->fill = 0; - - size_t alloc_sz = sizeof(rust_str *) * strings.size(); - iv->alloc = alloc_sz; - iv->payload.ptr = (rust_ivec_heap *) - task->kernel->malloc(alloc_sz + sizeof(size_t), "files ivec"); - iv->payload.ptr->fill = alloc_sz; - memcpy(&iv->payload.ptr->data, strings.data(), alloc_sz); + rust_vec** box_content = (rust_vec**)&box->data[0]; + *box_content = vec; + size_t alloc_sz = sizeof(rust_str*) * strings.size(); + vec->fill = vec->alloc = alloc_sz; + memcpy(&vec->data[0], strings.data(), alloc_sz); return box; } @@ -549,157 +568,6 @@ nano_time(rust_task *task, uint64_t *ns) { *ns = t.time_ns(); } -/** - * Preallocates the exact number of bytes in the given interior vector. - */ -extern "C" CDECL void -ivec_reserve(rust_task *task, type_desc *ty, rust_ivec *v, size_t n_elems) -{ - size_t new_alloc = n_elems * ty->size; - if (new_alloc <= v->alloc) - return; // Already big enough. - - rust_ivec_heap *heap_part; - if (v->fill || !v->payload.ptr) { - // On stack; spill to heap. - heap_part = (rust_ivec_heap *)task->malloc(new_alloc + - sizeof(size_t), - "ivec reserve heap part"); - heap_part->fill = v->fill; - memcpy(&heap_part->data, v->payload.data, v->fill); - - v->fill = 0; - v->payload.ptr = heap_part; - } else { - // On heap; resize. - heap_part = (rust_ivec_heap *) - task->realloc(v->payload.ptr, - new_alloc + sizeof(size_t)); - v->payload.ptr = heap_part; - } - - v->alloc = new_alloc; -} - -/** - * Preallocates the exact number of bytes in the given interior vector. - */ -extern "C" CDECL void -ivec_reserve_shared(rust_task *task, type_desc *ty, rust_ivec *v, - size_t n_elems) -{ - size_t new_alloc = n_elems * ty->size; - if (new_alloc <= v->alloc) - return; // Already big enough. - - rust_ivec_heap *heap_part; - if (v->fill || !v->payload.ptr) { - // On stack; spill to heap. - heap_part = (rust_ivec_heap *) - task->kernel->malloc(new_alloc + sizeof(size_t), - "ivec reserve shared"); - heap_part->fill = v->fill; - memcpy(&heap_part->data, v->payload.data, v->fill); - - v->fill = 0; - v->payload.ptr = heap_part; - } else { - // On heap; resize. - heap_part = (rust_ivec_heap *)task->kernel->realloc(v->payload.ptr, - new_alloc + sizeof(size_t)); - v->payload.ptr = heap_part; - } - - v->alloc = new_alloc; -} - -/** - * Returns true if the given vector is on the heap and false if it's on the - * stack. - */ -extern "C" CDECL bool -ivec_on_heap(rust_task *task, type_desc *ty, rust_ivec *v) -{ - return !v->fill && v->payload.ptr; -} - -/** - * Returns an unsafe pointer to the data part of an interior vector. - */ -extern "C" CDECL void * -ivec_to_ptr(rust_task *task, type_desc *ty, rust_ivec *v) -{ - return v->fill ? v->payload.data : v->payload.ptr->data; -} - -static size_t -get_ivec_size(rust_ivec *v) -{ - if (v->fill) - return v->fill; - if (v->payload.ptr) - return v->payload.ptr->fill; - return 0; -} - -/** - * Copies elements in an unsafe buffer to the given interior vector. The - * vector must have size zero. - */ -extern "C" CDECL void -ivec_copy_from_buf(rust_task *task, type_desc *ty, rust_ivec *v, void *ptr, - size_t count) -{ - size_t old_size = get_ivec_size(v); - if (old_size) { - task->fail(); - return; - } - - ivec_reserve(task, ty, v, count); - - size_t new_size = count * ty->size; - if (v->fill || !v->payload.ptr) { - // On stack. - memmove(v->payload.data, ptr, new_size); - v->fill = new_size; - return; - } - - // On heap. - memmove(v->payload.ptr->data, ptr, new_size); - v->payload.ptr->fill = new_size; -} - -/** - * Copies elements in an unsafe buffer to the given interior vector. The - * vector must have size zero. - */ -extern "C" CDECL void -ivec_copy_from_buf_shared(rust_task *task, type_desc *ty, rust_ivec *v, - void *ptr, size_t count) -{ - size_t old_size = get_ivec_size(v); - if (old_size) { - task->fail(); - return; - } - - ivec_reserve_shared(task, ty, v, count); - - size_t new_size = count * ty->size; - if (v->fill || !v->payload.ptr) { - // On stack. - memmove(v->payload.data, ptr, new_size); - v->fill = new_size; - return; - } - - // On heap. - memmove(v->payload.ptr->data, ptr, new_size); - v->payload.ptr->fill = new_size; -} - extern "C" CDECL void pin_task(rust_task *task) { task->pin(); diff --git a/src/rt/rust_shape.cpp b/src/rt/rust_shape.cpp index f56aa0251ce..c08663bface 100644 --- a/src/rt/rust_shape.cpp +++ b/src/rt/rust_shape.cpp @@ -226,17 +226,6 @@ size_of::walk_struct(bool align, const uint8_t *end_sp) { sa = struct_sa; } -void -size_of::walk_ivec(bool align, bool is_pod, size_align &elem_sa) { - if (!elem_sa.is_set()) - walk(align); // Determine the size the slow way. - else - sa = elem_sa; // Use the size hint. - - sa.set(sizeof(rust_ivec) - sizeof(uintptr_t) + sa.size * 4, - max(sa.alignment, sizeof(uintptr_t))); -} - // Copy constructors @@ -321,8 +310,8 @@ public: walk_vec(align, is_pod, get_evec_data_range(dp)); } - void walk_ivec(bool align, bool is_pod, size_align &elem_sa) { - walk_vec(align, is_pod, get_ivec_data_range(dp)); + void walk_vec(bool align, bool is_pod, uint16_t sp_size) { + walk_vec(align, is_pod, get_vec_data_range(dp)); } void walk_box(bool align) { diff --git a/src/rt/rust_shape.h b/src/rt/rust_shape.h index eb683110180..2ce4fcb5645 100644 --- a/src/rt/rust_shape.h +++ b/src/rt/rust_shape.h @@ -37,7 +37,7 @@ const uint8_t SHAPE_I64 = 7u; const uint8_t SHAPE_F32 = 8u; const uint8_t SHAPE_F64 = 9u; const uint8_t SHAPE_EVEC = 10u; -const uint8_t SHAPE_IVEC = 11u; +const uint8_t SHAPE_VEC = 11u; const uint8_t SHAPE_TAG = 12u; const uint8_t SHAPE_BOX = 13u; const uint8_t SHAPE_STRUCT = 17u; @@ -192,7 +192,7 @@ protected: private: void walk_evec(bool align); - void walk_ivec(bool align); + void walk_vec(bool align); void walk_tag(bool align); void walk_box(bool align); void walk_struct(bool align); @@ -278,6 +278,7 @@ public: template<typename T> void ctxt<T>::walk(bool align) { + switch (*sp++) { case SHAPE_U8: WALK_NUMBER(uint8_t); break; case SHAPE_U16: WALK_NUMBER(uint16_t); break; @@ -290,7 +291,7 @@ ctxt<T>::walk(bool align) { case SHAPE_F32: WALK_NUMBER(float); break; case SHAPE_F64: WALK_NUMBER(double); break; case SHAPE_EVEC: walk_evec(align); break; - case SHAPE_IVEC: walk_ivec(align); break; + case SHAPE_VEC: walk_vec(align); break; case SHAPE_TAG: walk_tag(align); break; case SHAPE_BOX: walk_box(align); break; case SHAPE_STRUCT: walk_struct(align); break; @@ -347,18 +348,13 @@ ctxt<T>::walk_evec(bool align) { template<typename T> void -ctxt<T>::walk_ivec(bool align) { +ctxt<T>::walk_vec(bool align) { bool is_pod = *sp++; - size_align elem_sa = get_size_align(sp); uint16_t sp_size = get_u16_bump(sp); const uint8_t *end_sp = sp + sp_size; - // FIXME: Hack to work around our incorrect alignment in some cases. - if (elem_sa.alignment == 8) - elem_sa.alignment = 4; - - static_cast<T *>(this)->walk_ivec(align, is_pod, elem_sa); + static_cast<T *>(this)->walk_vec(align, is_pod, sp_size); sp = end_sp; } @@ -471,8 +467,8 @@ public: void walk_evec(bool align, bool is_pod, uint16_t sp_size) { DPRINT("evec<"); walk(align); DPRINT(">"); } - void walk_ivec(bool align, bool is_pod, size_align &elem_sa) { - DPRINT("ivec<"); walk(align); DPRINT(">"); + void walk_vec(bool align, bool is_pod, uint16_t sp_size) { + DPRINT("vec<"); walk(align); DPRINT(">"); } void walk_box(bool align) { DPRINT("box<"); walk(align); DPRINT(">"); @@ -522,7 +518,6 @@ public: void walk_tag(bool align, tag_info &tinfo); void walk_struct(bool align, const uint8_t *end_sp); - void walk_ivec(bool align, bool is_pod, size_align &elem_sa); void walk_box(bool align) { sa.set(sizeof(void *), sizeof(void *)); } void walk_port(bool align) { sa.set(sizeof(void *), sizeof(void *)); } @@ -534,6 +529,9 @@ public: void walk_evec(bool align, bool is_pod, uint16_t sp_size) { sa.set(sizeof(void *), sizeof(void *)); } + void walk_vec(bool align, bool is_pod, uint16_t sp_size) { + sa.set(sizeof(void*), sizeof(void*)); + } void walk_var(bool align, uint8_t param_index) { const type_param *param = ¶ms[param_index]; @@ -725,9 +723,9 @@ protected: void walk_variant(bool align, tag_info &tinfo, uint32_t variant); static std::pair<uint8_t *,uint8_t *> get_evec_data_range(ptr dp); - static std::pair<uint8_t *,uint8_t *> get_ivec_data_range(ptr dp); + static std::pair<uint8_t *,uint8_t *> get_vec_data_range(ptr dp); static std::pair<ptr_pair,ptr_pair> get_evec_data_range(ptr_pair &dp); - static std::pair<ptr_pair,ptr_pair> get_ivec_data_range(ptr_pair &dp); + static std::pair<ptr_pair,ptr_pair> get_vec_data_range(ptr_pair &dp); public: U dp; @@ -740,7 +738,6 @@ public: : ctxt< data<T,U> >(in_task, in_sp, in_params, in_tables), dp(in_dp) {} void walk_tag(bool align, tag_info &tinfo); - void walk_ivec(bool align, bool is_pod, size_align &elem_sa); void walk_struct(bool align, const uint8_t *end_sp) { static_cast<T *>(this)->walk_struct(align, end_sp); @@ -749,6 +746,9 @@ public: void walk_evec(bool align, bool is_pod, uint16_t sp_size) { DATA_SIMPLE(void *, walk_evec(align, is_pod, sp_size)); } + void walk_vec(bool align, bool is_pod, uint16_t sp_size) { + DATA_SIMPLE(void *, walk_vec(align, is_pod, sp_size)); + } void walk_box(bool align) { DATA_SIMPLE(void *, walk_box(align)); } void walk_port(bool align) { DATA_SIMPLE(void *, walk_port(align)); } @@ -815,27 +815,10 @@ data<T,U>::get_evec_data_range(ptr dp) { template<typename T,typename U> std::pair<uint8_t *,uint8_t *> -data<T,U>::get_ivec_data_range(ptr dp) { - size_t fill = bump_dp<size_t>(dp); - bump_dp<size_t>(dp); // Skip over alloc. - uint8_t *payload_dp = dp; - rust_ivec_payload payload = bump_dp<rust_ivec_payload>(dp); - - uint8_t *start, *end; - if (!fill) { - if (!payload.ptr) { // Zero length. - start = end = NULL; - } else { // On heap. - fill = payload.ptr->fill; - start = payload.ptr->data; - end = start + fill; - } - } else { // On stack. - start = payload_dp; - end = start + fill; - } - - return std::make_pair(start, end); +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); } template<typename T,typename U> @@ -850,9 +833,9 @@ data<T,U>::get_evec_data_range(ptr_pair &dp) { template<typename T,typename U> std::pair<ptr_pair,ptr_pair> -data<T,U>::get_ivec_data_range(ptr_pair &dp) { - std::pair<uint8_t *,uint8_t *> fst = get_ivec_data_range(dp.fst); - std::pair<uint8_t *,uint8_t *> snd = get_ivec_data_range(dp.snd); +data<T,U>::get_vec_data_range(ptr_pair &dp) { + std::pair<uint8_t *,uint8_t *> fst = get_vec_data_range(dp.fst); + std::pair<uint8_t *,uint8_t *> snd = get_vec_data_range(dp.snd); ptr_pair start(fst.first, snd.first); ptr_pair end(fst.second, snd.second); return std::make_pair(start, end); @@ -860,24 +843,6 @@ data<T,U>::get_ivec_data_range(ptr_pair &dp) { template<typename T,typename U> void -data<T,U>::walk_ivec(bool align, bool is_pod, size_align &elem_sa) { - if (!elem_sa.is_set()) - elem_sa = size_of::get(*this); - else if (elem_sa.alignment == 8) - elem_sa.alignment = 4; // FIXME: This is an awful hack. - - // Get a pointer to the interior vector, and determine its size. - if (align) dp = align_to(dp, ALIGNOF(rust_ivec *)); - U end_dp = dp + sizeof(rust_ivec) - sizeof(uintptr_t) + elem_sa.size * 4; - - // Call to the implementation. - static_cast<T *>(this)->walk_ivec(align, is_pod, elem_sa); - - dp = end_dp; -} - -template<typename T,typename U> -void data<T,U>::walk_tag(bool align, tag_info &tinfo) { size_of::compute_tag_size(*this, tinfo); @@ -978,8 +943,8 @@ private: walk_vec(align, is_pod, get_evec_data_range(dp)); } - void walk_ivec(bool align, bool is_pod, size_align &elem_sa) { - walk_vec(align, is_pod, get_ivec_data_range(dp)); + void walk_vec(bool align, bool is_pod, uint16_t sp_size) { + walk_vec(align, is_pod, get_vec_data_range(dp)); } void walk_tag(bool align, tag_info &tinfo, uint32_t tag_variant) { diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 9857f06231e..c94e993e7e6 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -62,16 +62,6 @@ upcall_log_str(rust_task *task, uint32_t level, rust_str *str) { } extern "C" CDECL void -upcall_log_istr(rust_task *task, uint32_t level, rust_ivec *str) { - LOG_UPCALL_ENTRY(task); - if (task->sched->log_lvl < level) - return; - const char *buf = (const char *) - (str->fill ? str->payload.data : str->payload.ptr->data); - task->sched->log(task, level, "rust: %s", buf); -} - -extern "C" CDECL void upcall_yield(rust_task *task) { LOG_UPCALL_ENTRY(task); LOG(task, comm, "upcall yield()"); @@ -354,69 +344,33 @@ upcall_get_type_desc(rust_task *task, return td; } -/** - * Resizes an interior vector that has been spilled to the heap. - */ extern "C" CDECL void -upcall_ivec_resize_shared(rust_task *task, - rust_ivec *v, - size_t newsz) { +upcall_vec_grow(rust_task* task, rust_vec** vp, size_t new_sz) { LOG_UPCALL_ENTRY(task); - scoped_lock with(task->sched->lock); - I(task->sched, !v->fill); - - size_t new_alloc = next_power_of_two(newsz); - rust_ivec_heap *new_heap_part = (rust_ivec_heap *) - task->kernel->realloc(v->payload.ptr, new_alloc + sizeof(size_t)); - - new_heap_part->fill = newsz; - v->alloc = new_alloc; - v->payload.ptr = new_heap_part; -} - -/** - * Spills an interior vector to the heap. - */ -extern "C" CDECL void -upcall_ivec_spill_shared(rust_task *task, - rust_ivec *v, - size_t newsz) { - LOG_UPCALL_ENTRY(task); - scoped_lock with(task->sched->lock); - size_t new_alloc = next_power_of_two(newsz); - - rust_ivec_heap *heap_part = (rust_ivec_heap *) - task->kernel->malloc(new_alloc + sizeof(size_t), - "ivec spill shared"); - heap_part->fill = newsz; - memcpy(&heap_part->data, v->payload.data, v->fill); - - v->fill = 0; - v->alloc = new_alloc; - v->payload.ptr = heap_part; + // FIXME factor this into a utility function + if (new_sz > (*vp)->alloc) { + size_t new_alloc = next_power_of_two(new_sz); + *vp = (rust_vec*)task->kernel->realloc(*vp, new_alloc + + sizeof(rust_vec)); + (*vp)->alloc = new_alloc; + } + (*vp)->fill = new_sz; } extern "C" CDECL void -upcall_ivec_push(rust_task* task, rust_ivec* v, type_desc* elt_ty, void* x) { +upcall_vec_push(rust_task* task, rust_vec** vp, type_desc* elt_ty, + void* elt) { LOG_UPCALL_ENTRY(task); - bool is_interior = v->fill || !v->payload.ptr; - size_t sz = elt_ty->size; - size_t old_fill = is_interior ? v->fill : v->payload.ptr->fill; - size_t new_sz = sz + old_fill; + rust_vec* v = *vp; + size_t new_sz = v->fill + elt_ty->size; if (new_sz > v->alloc) { - if (is_interior) { - upcall_ivec_spill_shared(task, v, new_sz); - is_interior = false; - } else { - upcall_ivec_resize_shared(task, v, new_sz); - } - } else { - if (is_interior) v->fill = new_sz; - else v->payload.ptr->fill = new_sz; + size_t new_alloc = next_power_of_two(new_sz); + *vp = v = (rust_vec*)task->kernel->realloc(v, new_alloc + + sizeof(rust_vec)); + v->alloc = new_alloc; } - uint8_t* dataptr = is_interior ? &v->payload.data[0] - : &v->payload.ptr->data[0]; - copy_elements(task, elt_ty, dataptr + old_fill, x, sz); + copy_elements(task, elt_ty, &v->data[0] + v->fill, elt, elt_ty->size); + v->fill += elt_ty->size; } diff --git a/src/rt/rust_util.h b/src/rt/rust_util.h index 6ab7d305a82..10cdbce6109 100644 --- a/src/rt/rust_util.h +++ b/src/rt/rust_util.h @@ -197,28 +197,18 @@ typedef rust_evec rust_str; // Interior vectors (rust-user-code level). struct -rust_ivec_heap -{ - size_t fill; - uint8_t data[]; -}; - -// Note that the payload is actually size 4*sizeof(elem), even when heapified -union -rust_ivec_payload -{ - rust_ivec_heap *ptr; // if on heap - uint8_t data[]; // if on stack -}; - -struct -rust_ivec +rust_vec { size_t fill; // in bytes; if zero, heapified size_t alloc; // in bytes - rust_ivec_payload payload; + uint8_t data[0]; }; +template <typename T> +inline size_t vec_size(size_t elems) { + return sizeof(rust_vec) + sizeof(T) * elems; +} + // // Local Variables: // mode: C++ diff --git a/src/rt/rust_uv.cpp b/src/rt/rust_uv.cpp index b792121de35..add0e8da455 100644 --- a/src/rt/rust_uv.cpp +++ b/src/rt/rust_uv.cpp @@ -113,12 +113,12 @@ static socket_data *make_socket(rust_task *task, rust_chan *chan) { static uv_buf_t alloc_buffer(uv_stream_t *socket, size_t suggested_size) { LOG_CALLBACK_ENTRY(socket); uv_buf_t buf; - size_t actual_size = suggested_size + sizeof (rust_ivec_heap); + size_t actual_size = suggested_size + sizeof (rust_vec); socket_data *data = (socket_data*)socket->data; char *base = reinterpret_cast<char*>(data->task->kernel->malloc(actual_size, "read buffer")); - buf.base = base + sizeof (rust_ivec_heap); + buf.base = base + sizeof (rust_vec); buf.len = suggested_size; return buf; } @@ -129,26 +129,23 @@ static void read_progress(uv_stream_t *socket, ssize_t nread, uv_buf_t buf) { I(data->task->sched, data->reader != NULL); I(data->task->sched, nread <= ssize_t(buf.len)); - rust_ivec_heap *base = reinterpret_cast<rust_ivec_heap*>( - reinterpret_cast<char*>(buf.base) - sizeof (rust_ivec_heap)); - rust_ivec v; - v.fill = 0; - v.alloc = buf.len; - v.payload.ptr = base; + rust_vec *v = reinterpret_cast<rust_vec*>( + reinterpret_cast<char*>(buf.base) - sizeof (rust_vec)); + v->alloc = buf.len; switch (nread) { case -1: // End of stream - base->fill = 0; + v->fill = 0; uv_read_stop(socket); break; case 0: // Nothing read - data->task->kernel->free(base); + data->task->kernel->free(v); return; default: // Got nread bytes - base->fill = nread; + v->fill = nread; break; } - data->reader->send(&v); + data->reader->send(v); } static void new_connection(uv_handle_t *socket, int status) { diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 64617d3dfa5..3157b474b60 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -30,12 +30,6 @@ get_task_pointer get_task_trampoline get_time hack_allow_leaks -ivec_copy_from_buf -ivec_copy_from_buf_shared -ivec_on_heap -ivec_reserve -ivec_reserve_shared -ivec_to_ptr last_os_error leak migrate_alloc @@ -70,7 +64,9 @@ str_buf str_byte_len str_from_buf str_from_cstr -str_from_ivec +str_from_vec +vec_reserve_shared +vec_from_buf_shared str_push_byte str_slice task_sleep @@ -86,14 +82,13 @@ upcall_fail upcall_free upcall_get_type_desc upcall_grow_task -upcall_ivec_resize_shared -upcall_ivec_spill_shared -upcall_ivec_push +upcall_vec_grow +upcall_vec_push upcall_kill upcall_log_double upcall_log_float upcall_log_int -upcall_log_istr +upcall_log_str upcall_log_str upcall_log_type upcall_malloc |
