From 491d1106454c9ffa3950afe27ea3488ef5c19e32 Mon Sep 17 00:00:00 2001 From: Michael Sullivan Date: Fri, 10 Jun 2011 14:11:22 -0700 Subject: [PATCH 1/4] Make type_desc fields have useful types and better names. Add in cmp_glue. --- src/rt/rust_internal.h | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h index 5545d613a32..9426fec904a 100644 --- a/src/rt/rust_internal.h +++ b/src/rt/rust_internal.h @@ -206,19 +206,27 @@ struct rust_timer { #include "rust_util.h" +typedef void FASTCALL (glue_fn)(void *, rust_task *, void *, + const type_desc **, void *); +typedef void FASTCALL (cmp_glue_fn)(void *, rust_task *, void *, + const type_desc **, + void *, void *, int8_t); + + struct type_desc { // First part of type_desc is known to compiler. // first_param = &descs[1] if dynamic, null if static. const type_desc **first_param; size_t size; size_t align; - uintptr_t copy_glue_off; - uintptr_t drop_glue_off; - uintptr_t free_glue_off; - uintptr_t sever_glue_off; // For GC. - uintptr_t mark_glue_off; // For GC. - uintptr_t obj_drop_glue_off; // For custom destructors. + glue_fn *take_glue; + glue_fn *drop_glue; + glue_fn *free_glue; + glue_fn *sever_glue; // For GC. + glue_fn *mark_glue; // For GC. + glue_fn *obj_drop_glue; // For custom destructors. uintptr_t is_stateful; + cmp_glue_fn *cmp_glue; // Residual fields past here are known only to runtime. UT_hash_handle hh; From 95def699f10b9ec92721d6057a86c454c3c64122 Mon Sep 17 00:00:00 2001 From: Michael Sullivan Date: Fri, 10 Jun 2011 14:14:00 -0700 Subject: [PATCH 2/4] Implement upcall_vec_append and use it for vector append. --- src/comp/back/upcall.rs | 5 ++++ src/comp/middle/trans.rs | 2 +- src/rt/rust_upcall.cpp | 49 +++++++++++++++++++++++++++++++++++++++- src/rt/rustrt.def.in | 1 + 4 files changed, 55 insertions(+), 2 deletions(-) diff --git a/src/comp/back/upcall.rs b/src/comp/back/upcall.rs index 272c4d71d3f..c2c90f641f1 100644 --- a/src/comp/back/upcall.rs +++ b/src/comp/back/upcall.rs @@ -5,6 +5,7 @@ import trans::decl_cdecl_fn; import trans::T_f32; import trans::T_f64; import trans::T_fn; +import trans::T_bool; import trans::T_i8; import trans::T_i32; import trans::T_int; @@ -53,6 +54,7 @@ type upcalls = rec( ValueRef new_str, ValueRef new_vec, ValueRef vec_grow, + ValueRef vec_append, ValueRef get_type_desc, ValueRef new_task, ValueRef start_task, @@ -111,6 +113,9 @@ fn declare_upcalls(type_names tn, ModuleRef llmod) -> @upcalls { vec_grow=d("vec_grow", [T_opaque_vec_ptr(), T_size_t(), T_ptr(T_int()), T_ptr(T_tydesc(tn))], T_opaque_vec_ptr()), + vec_append=d("vec_append", [T_ptr(T_tydesc(tn)), T_ptr(T_tydesc(tn)), + T_ptr(T_opaque_vec_ptr()), + T_opaque_vec_ptr(), T_bool()], T_void()), get_type_desc=d("get_type_desc", [T_ptr(T_nil()), T_size_t(), T_size_t(), T_size_t(), T_ptr(T_ptr(T_tydesc(tn)))], diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 744ff4d7ce6..da4fe79b8fb 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3681,7 +3681,7 @@ fn trans_vec_append(&@block_ctxt cx, &ty::t t, auto dst = bcx.build.PointerCast(lhs, T_ptr(T_opaque_vec_ptr())); auto src = bcx.build.PointerCast(rhs, T_opaque_vec_ptr()); - ret res(bcx, bcx.build.FastCall(cx.fcx.lcx.ccx.glues.vec_append_glue, + ret res(bcx, bcx.build.Call(cx.fcx.lcx.ccx.upcalls.vec_append, [cx.fcx.lltaskptr, llvec_tydesc.val, llelt_tydesc.val, diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 411d72cc110..3e03cdc7ebb 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -415,7 +415,7 @@ upcall_vec_grow(rust_task *task, * * 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 infromation and no copy glue). What we do instead is set the + * 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. */ @@ -436,6 +436,53 @@ upcall_vec_grow(rust_task *task, 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; + + // 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 = src; p < src+n; p += elem_size) { + take_glue(NULL, task, NULL, tydescs, p); + } + } + memmove(dst, src, n); +} + +extern "C" CDECL void +upcall_vec_append(rust_task *task, type_desc *t, type_desc *elem_t, + rust_vec **dst_ptr, rust_vec *src, bool skip_null) +{ + LOG_UPCALL_ENTRY(task); + rust_vec *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_vec *new_vec = upcall_vec_grow(task, dst, n_src_bytes, + &need_copy, t); + + 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; +} + + extern "C" CDECL type_desc * upcall_get_type_desc(rust_task *task, void *curr_crate, // ignored, legacy compat. diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index 4bbacc53b50..9be5141f04d 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -73,6 +73,7 @@ upcall_start_thread upcall_trace_str upcall_trace_word upcall_vec_grow +upcall_vec_append upcall_yield vec_alloc vec_alloc_mut From 5378f48a03296372cc29cc9e74bdad9491432600 Mon Sep 17 00:00:00 2001 From: Michael Sullivan Date: Fri, 10 Jun 2011 14:57:39 -0700 Subject: [PATCH 3/4] Remove vec_append_glue from the compiler. --- src/comp/back/abi.rs | 4 ++-- src/comp/middle/trans.rs | 39 ++------------------------------------- 2 files changed, 4 insertions(+), 39 deletions(-) diff --git a/src/comp/back/abi.rs b/src/comp/back/abi.rs index e1fb2f00d91..107905f5085 100644 --- a/src/comp/back/abi.rs +++ b/src/comp/back/abi.rs @@ -88,8 +88,8 @@ fn bzero_glue_name() -> str { ret "rust_bzero_glue"; } -fn vec_append_glue_name() -> str { - ret "rust_vec_append_glue"; +fn yield_glue_name() -> str { + ret "rust_yield_glue"; } fn no_op_type_glue_name() -> str { diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index da4fe79b8fb..02e981d4527 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -85,8 +85,7 @@ state obj namegen(mutable int i) { type derived_tydesc_info = rec(ValueRef lltydesc, bool escapes); -type glue_fns = rec(ValueRef no_op_type_glue, - ValueRef vec_append_glue); +type glue_fns = rec(ValueRef no_op_type_glue); type tydesc_info = rec(ty::t ty, ValueRef tydesc, @@ -8724,39 +8723,6 @@ fn make_no_op_type_glue(ValueRef fun) { new_builder(llbb).RetVoid(); } -fn make_vec_append_glue(ModuleRef llmod, type_names tn) -> ValueRef { - /* - * Args to vec_append_glue: - * - * 0. (Implicit) task ptr - * - * 1. Pointer to the tydesc of the vec, so that we can tell if it's gc - * mem, and have a tydesc to pass to malloc if we're allocating anew. - * - * 2. Pointer to the tydesc of the vec's stored element type, so that - * elements can be copied to a newly alloc'ed vec if one must be - * created. - * - * 3. Dst vec ptr (i.e. ptr to ptr to rust_vec). - * - * 4. Src vec (i.e. ptr to rust_vec). - * - * 5. Flag indicating whether to skip trailing null on dst. - * - */ - - auto ty = T_fn([T_taskptr(tn), - T_ptr(T_tydesc(tn)), - T_ptr(T_tydesc(tn)), - T_ptr(T_opaque_vec_ptr()), - T_opaque_vec_ptr(), T_bool()], - T_void()); - - auto llfn = decl_fastcall_fn(llmod, abi::vec_append_glue_name(), ty); - ret llfn; -} - - fn vec_fill(&@block_ctxt bcx, ValueRef v) -> ValueRef { ret bcx.build.Load(bcx.build.GEP(v, [C_int(0), C_int(abi::vec_elt_fill)])); @@ -8769,8 +8735,7 @@ fn vec_p0(&@block_ctxt bcx, ValueRef v) -> ValueRef { } fn make_glues(ModuleRef llmod, &type_names tn) -> @glue_fns { - ret @rec(no_op_type_glue = decl_no_op_type_glue(llmod, tn), - vec_append_glue = make_vec_append_glue(llmod, tn)); + ret @rec(no_op_type_glue = decl_no_op_type_glue(llmod, tn)); } fn make_common_glue(&session::session sess, &str output) { From ccd1bcf7a754a5437cd108bb6bb8a32848334fe6 Mon Sep 17 00:00:00 2001 From: Michael Sullivan Date: Tue, 14 Jun 2011 15:54:58 -0700 Subject: [PATCH 4/4] Make tydesc glue functions use cdecl. --- src/comp/middle/trans.rs | 14 +++++++------- src/rt/rust_internal.h | 10 +++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 02e981d4527..4d5be62b048 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -1971,7 +1971,7 @@ fn declare_generic_glue(&@local_ctxt cx, fn_nm = mangle_internal_name_by_seq(cx.ccx, "glue_" + name); } - auto llfn = decl_fastcall_fn(cx.ccx.llmod, fn_nm, llfnty); + auto llfn = decl_cdecl_fn(cx.ccx.llmod, fn_nm, llfnty); set_glue_inlining(cx, llfn, t); ret llfn; } @@ -3232,11 +3232,11 @@ fn call_tydesc_glue_full(&@block_ctxt cx, ValueRef v, auto llfnptr = cx.build.GEP(tydesc, [C_int(0), C_int(field)]); auto llfn = cx.build.Load(llfnptr); - cx.build.FastCall(llfn, [C_null(T_ptr(T_nil())), - cx.fcx.lltaskptr, - C_null(T_ptr(T_nil())), - lltydescs, - llrawptr]); + cx.build.Call(llfn, [C_null(T_ptr(T_nil())), + cx.fcx.lltaskptr, + C_null(T_ptr(T_nil())), + lltydescs, + llrawptr]); } fn call_tydesc_glue(&@block_ctxt cx, ValueRef v, @@ -3311,7 +3311,7 @@ fn call_cmp_glue(&@block_ctxt cx, llrawrhsptr, llop]; - r.bcx.build.FastCall(llfn, llargs); + r.bcx.build.Call(llfn, llargs); ret res(r.bcx, r.bcx.build.Load(llcmpresultptr)); } diff --git a/src/rt/rust_internal.h b/src/rt/rust_internal.h index 9426fec904a..5db1216c102 100644 --- a/src/rt/rust_internal.h +++ b/src/rt/rust_internal.h @@ -206,11 +206,11 @@ struct rust_timer { #include "rust_util.h" -typedef void FASTCALL (glue_fn)(void *, rust_task *, void *, - const type_desc **, void *); -typedef void FASTCALL (cmp_glue_fn)(void *, rust_task *, void *, - const type_desc **, - void *, void *, int8_t); +typedef void CDECL (glue_fn)(void *, rust_task *, void *, + const type_desc **, void *); +typedef void CDECL (cmp_glue_fn)(void *, rust_task *, void *, + const type_desc **, + void *, void *, int8_t); struct type_desc {