From 7bf41392b62f8e118ac21842804808c516b953b0 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Mon, 5 Dec 2011 15:12:36 -0800 Subject: correct the use of 'sed -i' --- src/etc/gen-intrinsics | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/etc/gen-intrinsics b/src/etc/gen-intrinsics index 757df61596c..660c367991b 100755 --- a/src/etc/gen-intrinsics +++ b/src/etc/gen-intrinsics @@ -17,10 +17,11 @@ do -Isrc/rt/arch/$ARCH -fno-stack-protector \ -o src/rt/intrinsics/intrinsics.$ARCH.ll.in \ src/rt/intrinsics/intrinsics.cpp - sed -i \ + sed -i .orig \ -e 's/^target datalayout =/; target datalayout =/' \ src/rt/intrinsics/intrinsics.$ARCH.ll.in - sed -i \ + sed -i .orig \ -e 's/^target triple = "[^"]*"/target triple = "@CFG_TARGET_TRIPLE@"/' \ src/rt/intrinsics/intrinsics.$ARCH.ll.in -done \ No newline at end of file + rm src/rt/intrinsics/intrinsics.$ARCH.ll.in.orig +done -- cgit 1.4.1-3-g733a5 From 9a738fd61d3006796d518ba751f5bb632f65edb6 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 6 Dec 2011 16:26:47 -0800 Subject: rt: Various tweaks to make __morestack unwinding work on linux When unwinding through __morestack the stack limit in the TLS is invalidated and must be reset. Instead of actually landing at __morestack we're just going to make all our Rust landing pads call upcall_reset_stack_limit, which will find the stack segment that corresponds to the current stack pointer and put the limit in the TLS. Also massively expand the stack segment red zone to make more room for the dynamic linker. Will fix in the future. --- src/comp/back/upcall.rs | 6 ++++-- src/comp/middle/trans.rs | 5 +++++ src/rt/arch/i386/record_sp.S | 7 +++++++ src/rt/arch/x86_64/morestack.S | 4 ++++ src/rt/arch/x86_64/record_sp.S | 7 +++++++ src/rt/rust_task.cpp | 27 +++++++++++++++++++++++++-- src/rt/rust_task.h | 1 + src/rt/rust_upcall.cpp | 9 +++++++++ src/rt/rustrt.def.in | 1 + src/test/run-fail/morestack3.rs | 4 ++-- 10 files changed, 65 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/comp/back/upcall.rs b/src/comp/back/upcall.rs index 419a7fdc34c..71f33ccb372 100644 --- a/src/comp/back/upcall.rs +++ b/src/comp/back/upcall.rs @@ -27,7 +27,8 @@ type upcalls = dynastack_free: ValueRef, alloc_c_stack: ValueRef, call_shim_on_c_stack: ValueRef, - rust_personality: ValueRef}; + rust_personality: ValueRef, + reset_stack_limit: ValueRef}; fn declare_upcalls(targ_cfg: @session::config, _tn: type_names, @@ -89,7 +90,8 @@ fn declare_upcalls(targ_cfg: @session::config, // arguments: void *args, void *fn_ptr [T_ptr(T_i8()), T_ptr(T_i8())], int_t), - rust_personality: d("rust_personality", [], T_i32()) + rust_personality: d("rust_personality", [], T_i32()), + reset_stack_limit: dv("reset_stack_limit", []) }; } // diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 6804434bb4c..41df1b28edd 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3904,6 +3904,11 @@ fn trans_landing_pad(bcx: @block_ctxt, // The landing pad block is a cleanup SetCleanup(bcx, llpad); + // Because we may have unwound across a stack boundary, we must call into + // the runtime to figure out which stack segment we are on and place the + // stack limit back into the TLS. + Call(bcx, bcx_ccx(bcx).upcalls.reset_stack_limit, []); + // FIXME: This seems like a very naive and redundant way to generate the // landing pads, as we're re-generating all in-scope cleanups for each // function call. Probably good optimization opportunities here. diff --git a/src/rt/arch/i386/record_sp.S b/src/rt/arch/i386/record_sp.S index 153225e8187..3f299de5d15 100644 --- a/src/rt/arch/i386/record_sp.S +++ b/src/rt/arch/i386/record_sp.S @@ -2,11 +2,14 @@ #if defined(__APPLE__) || defined(_WIN32) #define RECORD_SP _record_sp +#define GET_SP _get_sp #else #define RECORD_SP record_sp +#define GET_SP get_sp #endif .globl RECORD_SP +.globl GET_SP #if defined(__linux__) RECORD_SP: @@ -25,3 +28,7 @@ RECORD_SP: ret #endif #endif + +GET_SP: + movl %esp, %eax + ret \ No newline at end of file diff --git a/src/rt/arch/x86_64/morestack.S b/src/rt/arch/x86_64/morestack.S index ef0edcee720..535b6190f1c 100644 --- a/src/rt/arch/x86_64/morestack.S +++ b/src/rt/arch/x86_64/morestack.S @@ -132,6 +132,10 @@ MORESTACK: addq $8, %rsp popq %rbp +#ifdef __linux__ + .cfi_restore %rbp + .cfi_def_cfa %rsp, 8 +#endif ret #if defined(__ELF__) diff --git a/src/rt/arch/x86_64/record_sp.S b/src/rt/arch/x86_64/record_sp.S index e8284c5fac9..415f6685655 100644 --- a/src/rt/arch/x86_64/record_sp.S +++ b/src/rt/arch/x86_64/record_sp.S @@ -2,11 +2,14 @@ #if defined(__APPLE__) || defined(_WIN32) #define RECORD_SP _record_sp +#define GET_SP _get_sp #else #define RECORD_SP record_sp +#define GET_SP get_sp #endif .globl RECORD_SP +.globl GET_SP #if defined(__linux__) RECORD_SP: @@ -23,3 +26,7 @@ RECORD_SP: ret #endif #endif + +GET_SP: + movq %rsp, %rax + ret diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index b540225243f..888c9ac701a 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -18,11 +18,11 @@ // to the rt, compiler and dynamic linker for running small functions // FIXME: We want this to be 128 but need to slim the red zone calls down #ifdef __i386__ -#define RED_ZONE_SIZE 2048 +#define RED_ZONE_SIZE 65536 #endif #ifdef __x86_64__ -#define RED_ZONE_SIZE 2048 +#define RED_ZONE_SIZE 65536 #endif // Stack size @@ -613,6 +613,29 @@ rust_task::record_stack_limit() { "Stack size must be greater than LIMIT_OFFSET"); record_sp(stk->data + LIMIT_OFFSET + RED_ZONE_SIZE); } + +extern "C" uintptr_t get_sp(); + +/* +Called by landing pads during unwinding to figure out which +stack segment we are currently running on, delete the others, +and record the stack limit (which was not restored when unwinding +through __morestack). + */ +void +rust_task::reset_stack_limit() { + uintptr_t sp = get_sp(); + // Not positive these bounds for sp are correct. + // I think that the first possible value for esp on a new + // stack is stk->limit, which points one word in front of + // the first work to be pushed onto a new stack. + while (sp <= (uintptr_t)stk->data || stk->limit < sp) { + del_stk(this, stk); + A(sched, stk != NULL, "Failed to find the current stack"); + } + record_stack_limit(); +} + // // Local Variables: // mode: C++ diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 00a9fc277dc..47472801510 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -200,6 +200,7 @@ rust_task : public kernel_owned, rust_cond void *new_stack(size_t stk_sz, void *args_addr, size_t args_sz); void del_stack(); void record_stack_limit(); + void reset_stack_limit(); }; // diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 653db471fc0..5a4c37c500c 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -259,6 +259,15 @@ upcall_del_stack() { task->del_stack(); } +// Landing pads need to call this to insert the +// correct limit into TLS. +// NB: This must be called on the Rust stack +extern "C" CDECL void +upcall_reset_stack_limit() { + rust_task *task = rust_scheduler::get_task(); + task->reset_stack_limit(); +} + extern "C" _Unwind_Reason_Code __gxx_personality_v0(int version, _Unwind_Action actions, diff --git a/src/rt/rustrt.def.in b/src/rt/rustrt.def.in index ba1a9c1403d..306c750c8fb 100644 --- a/src/rt/rustrt.def.in +++ b/src/rt/rustrt.def.in @@ -69,6 +69,7 @@ upcall_vec_push upcall_call_shim_on_c_stack upcall_new_stack upcall_del_stack +upcall_reset_stack_limit asm_call_on_stack rust_uv_default_loop rust_uv_loop_new diff --git a/src/test/run-fail/morestack3.rs b/src/test/run-fail/morestack3.rs index 9fdd0326b66..9796017a8eb 100644 --- a/src/test/run-fail/morestack3.rs +++ b/src/test/run-fail/morestack3.rs @@ -25,10 +25,10 @@ resource and_then_get_big_again(_i: @int) { getbig(i - 1); } } - getbig(1000); + getbig(100); } fn main() { rustrt::set_min_stack(256u); - std::task::spawn(1000, getbig_and_fail); + std::task::spawn(100, getbig_and_fail); } \ No newline at end of file -- cgit 1.4.1-3-g733a5 From aa99bfa170971b14bb72a10ef153480ec4caaa46 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 6 Dec 2011 14:02:06 -0800 Subject: do not stringify AST nodes unless emitting comments --- src/comp/middle/trans.rs | 4 +++- src/comp/middle/trans_build.rs | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 41df1b28edd..693c8ae79e8 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -4536,7 +4536,9 @@ fn zero_alloca(cx: @block_ctxt, llptr: ValueRef, t: ty::t) fn trans_stmt(cx: @block_ctxt, s: ast::stmt) -> @block_ctxt { // FIXME Fill in cx.sp - add_span_comment(cx, s.span, stmt_to_str(s)); + if (!bcx_ccx(cx).sess.get_opts().no_asm_comments) { + add_span_comment(cx, s.span, stmt_to_str(s)); + } let bcx = cx; alt s.node { diff --git a/src/comp/middle/trans_build.rs b/src/comp/middle/trans_build.rs index 02894769ae6..b7756b0902d 100644 --- a/src/comp/middle/trans_build.rs +++ b/src/comp/middle/trans_build.rs @@ -515,7 +515,9 @@ fn add_span_comment(bcx: @block_ctxt, sp: span, text: str) { fn add_comment(bcx: @block_ctxt, text: str) { let ccx = bcx_ccx(bcx); if (!ccx.sess.get_opts().no_asm_comments) { - let comment_text = "; " + text; + check str::is_not_empty("$"); + let sanitized = str::replace(text, "$", ""); + let comment_text = "; " + sanitized; let asm = str::as_buf(comment_text, { |c| str::as_buf("", { |e| llvm::LLVMConstInlineAsm(T_fn([], T_void()), c, e, 0, 0)})}); -- cgit 1.4.1-3-g733a5 From 66355607da4a2491e4a75dc6e0d2036120f0ede2 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 6 Dec 2011 15:55:11 -0800 Subject: hack for now: map uint hashes into a u32, which helps x86_64 perf. --- src/libstd/map.rs | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/libstd/map.rs b/src/libstd/map.rs index c802b5b889f..a4ef4674017 100644 --- a/src/libstd/map.rs +++ b/src/libstd/map.rs @@ -137,21 +137,25 @@ fn mk_hashmap(hasher: hashfn, eqer: eqfn) // is always a power of 2), so that all buckets are probed for a // fixed key. - fn hashl(n: uint, _nbkts: uint) -> uint { ret (n >>> 16u) * 2u + 1u; } - fn hashr(n: uint, _nbkts: uint) -> uint { ret 0x0000_ffff_u & n; } - fn hash(h: uint, nbkts: uint, i: uint) -> uint { - ret (hashl(h, nbkts) * i + hashr(h, nbkts)) % nbkts; + fn hashl(n: u32) -> u32 { ret (n >>> 16u32) * 2u32 + 1u32; } + fn hashr(n: u32) -> u32 { ret 0x0000_ffff_u32 & n; } + fn hash(h: u32, nbkts: uint, i: uint) -> uint { + ret ((hashl(h) as uint) * i + (hashr(h) as uint)) % nbkts; } + + fn to_u64(h: uint) -> u32 { + ret (h as u32) ^ ((h >>> 16u) as u32); + } + /** * We attempt to never call this with a full table. If we do, it * will fail. */ - fn insert_common(hasher: hashfn, eqer: eqfn, bkts: [mutable bucket], nbkts: uint, key: K, val: V) -> bool { let i: uint = 0u; - let h: uint = hasher(key); + let h = to_u64(hasher(key)); while i < nbkts { let j: uint = hash(h, nbkts, i); alt bkts[j] { @@ -171,7 +175,7 @@ fn mk_hashmap(hasher: hashfn, eqer: eqfn) bkts: [mutable bucket], nbkts: uint, key: K) -> option::t { let i: uint = 0u; - let h: uint = hasher(key); + let h = to_u64(hasher(key)); while i < nbkts { let j: uint = hash(h, nbkts, i); alt bkts[j] { @@ -244,7 +248,7 @@ fn mk_hashmap(hasher: hashfn, eqer: eqfn) } fn remove(key: K) -> option::t { let i: uint = 0u; - let h: uint = hasher(key); + let h = to_u64(hasher(key)); while i < nbkts { let j: uint = hash(h, nbkts, i); alt bkts[j] { -- cgit 1.4.1-3-g733a5 From 8b608125ac2d59cace17fc3f177d13e2a0021716 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Tue, 6 Dec 2011 21:34:50 -0800 Subject: fix hash function: + binds tighter than << --- src/comp/syntax/ast_util.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/comp/syntax/ast_util.rs b/src/comp/syntax/ast_util.rs index e9b89b59cd5..f39b5865c25 100644 --- a/src/comp/syntax/ast_util.rs +++ b/src/comp/syntax/ast_util.rs @@ -193,7 +193,10 @@ fn is_constraint_arg(e: @expr) -> bool { fn eq_ty(&&a: @ty, &&b: @ty) -> bool { ret std::box::ptr_eq(a, b); } -fn hash_ty(&&t: @ty) -> uint { ret t.span.lo << 16u + t.span.hi; } +fn hash_ty(&&t: @ty) -> uint { + let res = (t.span.lo << 16u) + t.span.hi; + ret res; +} fn hash_def_id(&&id: def_id) -> uint { id.crate as uint << 16u + (id.node as uint) -- cgit 1.4.1-3-g733a5 From 9b7347dd9648fd4cdf134700ec35bc370022da2b Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Fri, 2 Dec 2011 19:04:35 -0800 Subject: modify upcalls to take structs as args --- src/rt/rust_upcall.cpp | 336 ++++++++++++++++++++++++++++++++++++------------- 1 file changed, 252 insertions(+), 84 deletions(-) (limited to 'src') diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 5a4c37c500c..40cb35f0149 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -6,7 +6,31 @@ #include "rust_upcall.h" #include -// Upcalls. +extern "C" void record_sp(void *limit); + +/** + * Switches to the C-stack and invokes |fn_ptr|, passing |args| as argument. + */ +extern "C" CDECL void +upcall_call_shim_on_c_stack(void *args, void *fn_ptr) { + rust_task *task = rust_scheduler::get_task(); + + // FIXME (1226) - The shim functions generated by rustc contain the + // morestack prologue, so we need to let them know they have enough + // stack. + record_sp(0); + + rust_scheduler *sched = task->sched; + try { + sched->c_context.call_shim_on_c_stack(args, fn_ptr); + } catch (...) { + task = rust_scheduler::get_task(); + task->record_stack_limit(); + throw; + } + task = rust_scheduler::get_task(); + task->record_stack_limit(); +} #if defined(__i386__) || defined(__x86_64__) || defined(_M_X64) void @@ -47,24 +71,34 @@ copy_elements(rust_task *task, type_desc *elem_t, } } +struct s_fail_args { + char const *expr; + char const *file; + size_t line; +}; + extern "C" CDECL void -upcall_fail(char const *expr, - char const *file, - size_t line) { +upcall_s_fail(s_fail_args *args) { rust_task *task = rust_scheduler::get_task(); LOG_UPCALL_ENTRY(task); - LOG_ERR(task, upcall, "upcall fail '%s', %s:%" PRIdPTR, expr, file, line); + LOG_ERR(task, upcall, "upcall fail '%s', %s:%" PRIdPTR, + args->expr, args->file, args->line); task->fail(); } +struct s_malloc_args { + size_t nbytes; + type_desc *td; +}; + extern "C" CDECL uintptr_t -upcall_malloc(size_t nbytes, type_desc *td) { +upcall_s_malloc(s_malloc_args *args) { rust_task *task = rust_scheduler::get_task(); LOG_UPCALL_ENTRY(task); LOG(task, mem, "upcall malloc(%" PRIdPTR ", 0x%" PRIxPTR ")", - nbytes, td); + args->nbytes, args->td); gc::maybe_gc(task); cc::maybe_cc(task); @@ -72,107 +106,136 @@ upcall_malloc(size_t nbytes, type_desc *td) { // TODO: Maybe use dladdr here to find a more useful name for the // type_desc. - void *p = task->malloc(nbytes, "tdesc", td); - memset(p, '\0', nbytes); + void *p = task->malloc(args->nbytes, "tdesc", args->td); + memset(p, '\0', args->nbytes); - task->local_allocs[p] = td; + task->local_allocs[p] = args->td; debug::maybe_track_origin(task, p); LOG(task, mem, "upcall malloc(%" PRIdPTR ", 0x%" PRIxPTR ") = 0x%" PRIxPTR, - nbytes, td, (uintptr_t)p); + args->nbytes, args->td, (uintptr_t)p); return (uintptr_t) p; } +struct s_free_args { + void *ptr; + uintptr_t is_gc; +}; + /** * Called whenever an object's ref count drops to zero. */ extern "C" CDECL void -upcall_free(void* ptr, uintptr_t is_gc) { +upcall_s_free(s_free_args *args) { rust_task *task = rust_scheduler::get_task(); LOG_UPCALL_ENTRY(task); rust_scheduler *sched = task->sched; DLOG(sched, mem, "upcall free(0x%" PRIxPTR ", is_gc=%" PRIdPTR ")", - (uintptr_t)ptr, is_gc); + (uintptr_t)args->ptr, args->is_gc); - task->local_allocs.erase(ptr); - debug::maybe_untrack_origin(task, ptr); + task->local_allocs.erase(args->ptr); + debug::maybe_untrack_origin(task, args->ptr); - task->free(ptr, (bool) is_gc); + task->free(args->ptr, (bool) args->is_gc); } +struct s_shared_malloc_args { + size_t nbytes; + type_desc *td; +}; + extern "C" CDECL uintptr_t -upcall_shared_malloc(size_t nbytes, type_desc *td) { +upcall_s_shared_malloc(s_shared_malloc_args *args) { rust_task *task = rust_scheduler::get_task(); LOG_UPCALL_ENTRY(task); LOG(task, mem, - "upcall shared_malloc(%" PRIdPTR ", 0x%" PRIxPTR ")", - nbytes, td); - void *p = task->kernel->malloc(nbytes, "shared malloc"); - memset(p, '\0', nbytes); + "upcall shared_malloc(%" PRIdPTR ", 0x%" PRIxPTR ")", + args->nbytes, args->td); + void *p = task->kernel->malloc(args->nbytes, "shared malloc"); + memset(p, '\0', args->nbytes); LOG(task, mem, - "upcall shared_malloc(%" PRIdPTR ", 0x%" PRIxPTR - ") = 0x%" PRIxPTR, - nbytes, td, (uintptr_t)p); + "upcall shared_malloc(%" PRIdPTR ", 0x%" PRIxPTR + ") = 0x%" PRIxPTR, + args->nbytes, args->td, (uintptr_t)p); return (uintptr_t) p; } +struct s_shared_free_args { + void *ptr; +}; + /** * Called whenever an object's ref count drops to zero. */ extern "C" CDECL void -upcall_shared_free(void* ptr) { +upcall_s_shared_free(s_shared_free_args *args) { rust_task *task = rust_scheduler::get_task(); LOG_UPCALL_ENTRY(task); rust_scheduler *sched = task->sched; DLOG(sched, mem, "upcall shared_free(0x%" PRIxPTR")", - (uintptr_t)ptr); - task->kernel->free(ptr); + (uintptr_t)args->ptr); + task->kernel->free(args->ptr); } +struct s_get_type_desc_args { + size_t size; + size_t align; + size_t n_descs; + type_desc const **descs; + uintptr_t n_obj_params; +}; + extern "C" CDECL type_desc * -upcall_get_type_desc(void *curr_crate, // ignored, legacy compat. - size_t size, - size_t align, - size_t n_descs, - type_desc const **descs, - uintptr_t n_obj_params) { +upcall_s_get_type_desc(s_get_type_desc_args *args) { rust_task *task = rust_scheduler::get_task(); check_stack(task); LOG_UPCALL_ENTRY(task); LOG(task, cache, "upcall get_type_desc with size=%" PRIdPTR - ", align=%" PRIdPTR ", %" PRIdPTR " descs", size, align, - n_descs); + ", align=%" PRIdPTR ", %" PRIdPTR " descs", args->size, args->align, + args->n_descs); rust_crate_cache *cache = task->get_crate_cache(); - type_desc *td = cache->get_type_desc(size, align, n_descs, descs, - n_obj_params); + type_desc *td = cache->get_type_desc(args->size, args->align, args->n_descs, + args->descs, args->n_obj_params); LOG(task, cache, "returning tydesc 0x%" PRIxPTR, td); return td; } +struct s_vec_grow_args { + rust_vec** vp; + size_t new_sz; +}; + extern "C" CDECL void -upcall_vec_grow(rust_vec** vp, size_t new_sz) { +upcall_s_vec_grow(s_vec_grow_args *args) { rust_task *task = rust_scheduler::get_task(); LOG_UPCALL_ENTRY(task); - reserve_vec(task, vp, new_sz); - (*vp)->fill = new_sz; + reserve_vec(task, args->vp, args->new_sz); + (*args->vp)->fill = args->new_sz; } +struct s_vec_push_args { + rust_vec** vp; + type_desc* elt_ty; + void* elt; +}; + extern "C" CDECL void -upcall_vec_push(rust_vec** vp, type_desc* elt_ty, void* elt) { +upcall_s_vec_push(s_vec_push_args *args) { rust_task *task = rust_scheduler::get_task(); LOG_UPCALL_ENTRY(task); - size_t new_sz = (*vp)->fill + elt_ty->size; - reserve_vec(task, vp, new_sz); - rust_vec* v = *vp; - copy_elements(task, elt_ty, &v->data[0] + v->fill, elt, elt_ty->size); - v->fill += elt_ty->size; + size_t new_sz = (*args->vp)->fill + args->elt_ty->size; + reserve_vec(task, args->vp, new_sz); + rust_vec* v = *args->vp; + copy_elements(task, args->elt_ty, &v->data[0] + v->fill, + args->elt, args->elt_ty->size); + v->fill += args->elt_ty->size; } /** @@ -180,60 +243,49 @@ upcall_vec_push(rust_vec** vp, type_desc* elt_ty, void* elt) { * space in the dynamic stack. */ extern "C" CDECL void * -upcall_dynastack_mark() { +upcall_s_dynastack_mark() { return rust_scheduler::get_task()->dynastack.mark(); } +struct s_dynastack_alloc_args { + size_t sz; +}; + /** * Allocates space in the dynamic stack and returns it. * * FIXME: Deprecated since dynamic stacks need to be self-describing for GC. */ extern "C" CDECL void * -upcall_dynastack_alloc(size_t sz) { +upcall_s_dynastack_alloc(s_dynastack_alloc_args *args) { + size_t sz = args->sz; return sz ? rust_scheduler::get_task()->dynastack.alloc(sz, NULL) : NULL; } +struct s_dynastack_alloc_2_args { + size_t sz; + type_desc *ty; +}; + /** * Allocates space associated with a type descriptor in the dynamic stack and * returns it. */ extern "C" CDECL void * -upcall_dynastack_alloc_2(size_t sz, type_desc *ty) { +upcall_s_dynastack_alloc_2(s_dynastack_alloc_2_args *args) { + size_t sz = args->sz; + type_desc *ty = args->ty; return sz ? rust_scheduler::get_task()->dynastack.alloc(sz, ty) : NULL; } +struct s_dynastack_free_args { + void *ptr; +}; + /** Frees space in the dynamic stack. */ extern "C" CDECL void -upcall_dynastack_free(void *ptr) { - return rust_scheduler::get_task()->dynastack.free(ptr); -} - -extern "C" void record_sp(void *limit); - -/** - * Switch to the C stack and call the given function, passing a single pointer - * argument. - */ -extern "C" CDECL void -upcall_call_shim_on_c_stack(void *args, void *fn_ptr) { - rust_task *task = rust_scheduler::get_task(); - - // FIXME (1226) - The shim functions generated by rustc contain the - // morestack prologue, so we need to let them know they have enough - // stack. - record_sp(0); - - rust_scheduler *sched = task->sched; - try { - sched->c_context.call_shim_on_c_stack(args, fn_ptr); - } catch (...) { - task = rust_scheduler::get_task(); - task->record_stack_limit(); - throw; - } - task = rust_scheduler::get_task(); - task->record_stack_limit(); +upcall_s_dynastack_free(s_dynastack_free_args *args) { + return rust_scheduler::get_task()->dynastack.free(args->ptr); } struct rust_new_stack2_args { @@ -275,17 +327,134 @@ __gxx_personality_v0(int version, _Unwind_Exception *ue_header, _Unwind_Context *context); +struct s_rust_personality_args { + int version; + _Unwind_Action actions; + uint64_t exception_class; + _Unwind_Exception *ue_header; + _Unwind_Context *context; +}; + +extern "C" _Unwind_Reason_Code +upcall_s_rust_personality(s_rust_personality_args *args) { + return __gxx_personality_v0(args->version, + args->actions, + args->exception_class, + args->ue_header, + args->context); +} + +// ______________________________________________________________________________ +// Upcalls in original format: deprecated and should be removed once snapshot +// transitions them away. + +extern "C" CDECL void +upcall_fail(char const *expr, + char const *file, + size_t line) { + s_fail_args args = {expr,file,line}; + upcall_s_fail(&args); +} + +extern "C" CDECL uintptr_t +upcall_malloc(size_t nbytes, type_desc *td) { + s_malloc_args args = {nbytes, td}; + return upcall_s_malloc(&args); +} + +/** + * Called whenever an object's ref count drops to zero. + */ +extern "C" CDECL void +upcall_free(void* ptr, uintptr_t is_gc) { + s_free_args args = {ptr, is_gc}; + upcall_s_free(&args); +} + +extern "C" CDECL uintptr_t +upcall_shared_malloc(size_t nbytes, type_desc *td) { + s_shared_malloc_args args = {nbytes, td}; + return upcall_s_shared_malloc(&args); +} + +/** + * Called whenever an object's ref count drops to zero. + */ +extern "C" CDECL void +upcall_shared_free(void* ptr) { + s_shared_free_args args = {ptr}; + upcall_s_shared_free(&args); +} + +extern "C" CDECL type_desc * +upcall_get_type_desc(void *curr_crate, // ignored, legacy compat. + size_t size, + size_t align, + size_t n_descs, + type_desc const **descs, + uintptr_t n_obj_params) { + s_get_type_desc_args args = {size,align,n_descs,descs,n_obj_params}; + return upcall_s_get_type_desc(&args); +} + +extern "C" CDECL void +upcall_vec_grow(rust_vec** vp, size_t new_sz) { + s_vec_grow_args args = {vp, new_sz}; + upcall_s_vec_grow(&args); +} + +extern "C" CDECL void +upcall_vec_push(rust_vec** vp, type_desc* elt_ty, void* elt) { + s_vec_push_args args = {vp, elt_ty, elt}; + upcall_s_vec_push(&args); +} + +/** + * Returns a token that can be used to deallocate all of the allocated space + * space in the dynamic stack. + */ +extern "C" CDECL void * +upcall_dynastack_mark() { + return upcall_s_dynastack_mark(); +} + +/** + * Allocates space in the dynamic stack and returns it. + * + * FIXME: Deprecated since dynamic stacks need to be self-describing for GC. + */ +extern "C" CDECL void * +upcall_dynastack_alloc(size_t sz) { + s_dynastack_alloc_args args = {sz}; + return upcall_s_dynastack_alloc(&args); +} + +/** + * Allocates space associated with a type descriptor in the dynamic stack and + * returns it. + */ +extern "C" CDECL void * +upcall_dynastack_alloc_2(size_t sz, type_desc *ty) { + s_dynastack_alloc_2_args args = {sz, ty}; + return upcall_s_dynastack_alloc_2(&args); +} + +/** Frees space in the dynamic stack. */ +extern "C" CDECL void +upcall_dynastack_free(void *ptr) { + s_dynastack_free_args args = {ptr}; + return upcall_s_dynastack_free(&args); +} + extern "C" _Unwind_Reason_Code upcall_rust_personality(int version, _Unwind_Action actions, uint64_t exception_class, _Unwind_Exception *ue_header, _Unwind_Context *context) { - return __gxx_personality_v0(version, - actions, - exception_class, - ue_header, - context); + s_rust_personality_args args = {version, actions, exception_class, ue_header, + context}; + return upcall_s_rust_personality(&args); } // @@ -295,6 +464,5 @@ upcall_rust_personality(int version, // indent-tabs-mode: nil // c-basic-offset: 4 // buffer-file-coding-system: utf-8-unix -// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'"; // End: // -- cgit 1.4.1-3-g733a5 From c11d0b0aa0343fbc6ddf8114ce96904c9870de8a Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 6 Dec 2011 20:55:03 -0800 Subject: rt: Move upcall_cmp_type/upcall_log_type to rust_upcall.cpp --- src/rt/rust_shape.cpp | 8 ++++---- src/rt/rust_upcall.cpp | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/rt/rust_shape.cpp b/src/rt/rust_shape.cpp index 326e4e2a514..3593d0ff335 100644 --- a/src/rt/rust_shape.cpp +++ b/src/rt/rust_shape.cpp @@ -530,9 +530,9 @@ log::walk_res(const rust_fn *dtor, unsigned n_params, } // end namespace shape extern "C" void -upcall_cmp_type(int8_t *result, const type_desc *tydesc, - const type_desc **subtydescs, uint8_t *data_0, - uint8_t *data_1, uint8_t cmp_type) { +shape_cmp_type(int8_t *result, const type_desc *tydesc, + const type_desc **subtydescs, uint8_t *data_0, + uint8_t *data_1, uint8_t cmp_type) { rust_task *task = rust_scheduler::get_task(); shape::arena arena; @@ -553,7 +553,7 @@ upcall_cmp_type(int8_t *result, const type_desc *tydesc, } extern "C" void -upcall_log_type(const type_desc *tydesc, uint8_t *data, uint32_t level) { +shape_log_type(const type_desc *tydesc, uint8_t *data, uint32_t level) { rust_task *task = rust_scheduler::get_task(); if (task->sched->log_lvl < level) return; // TODO: Don't evaluate at all? diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 40cb35f0149..c971119342c 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -457,6 +457,26 @@ upcall_rust_personality(int version, return upcall_s_rust_personality(&args); } +extern "C" void +shape_cmp_type(int8_t *result, const type_desc *tydesc, + const type_desc **subtydescs, uint8_t *data_0, + uint8_t *data_1, uint8_t cmp_type); + +extern "C" void +upcall_cmp_type(int8_t *result, const type_desc *tydesc, + const type_desc **subtydescs, uint8_t *data_0, + uint8_t *data_1, uint8_t cmp_type) { + shape_cmp_type(result, tydesc, subtydescs, data_0, data_1, cmp_type); +} + +extern "C" void +shape_log_type(const type_desc *tydesc, uint8_t *data, uint32_t level); + +extern "C" void +upcall_log_type(const type_desc *tydesc, uint8_t *data, uint32_t level) { + shape_log_type(tydesc, data, level); +} + // // Local Variables: // mode: C++ -- cgit 1.4.1-3-g733a5 From 00636e3155647f843fb1f8e8c981429feb8dd7f2 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 6 Dec 2011 21:14:00 -0800 Subject: rt: Convert log_type and cmp_type upcalls to shim form --- src/rt/rust_upcall.cpp | 49 +++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 39 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index c971119342c..22dc18982d5 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -344,6 +344,41 @@ upcall_s_rust_personality(s_rust_personality_args *args) { args->context); } +extern "C" void +shape_cmp_type(int8_t *result, const type_desc *tydesc, + const type_desc **subtydescs, uint8_t *data_0, + uint8_t *data_1, uint8_t cmp_type); + +struct s_cmp_type_args { + int8_t *result; + const type_desc *tydesc; + const type_desc **subtydescs; + uint8_t *data_0; + uint8_t *data_1; + uint8_t cmp_type; +}; + +extern "C" void +upcall_s_cmp_type(s_cmp_type_args *args) { + shape_cmp_type(args->result, args->tydesc, args->subtydescs, + args->data_0, args->data_1, args->cmp_type); +} + +extern "C" void +shape_log_type(const type_desc *tydesc, uint8_t *data, uint32_t level); + +struct s_log_type_args { + const type_desc *tydesc; + uint8_t *data; + uint32_t level; +}; + +extern "C" void +upcall_s_log_type(s_log_type_args *args) { + shape_log_type(args->tydesc, args->data, args->level); +} + + // ______________________________________________________________________________ // Upcalls in original format: deprecated and should be removed once snapshot // transitions them away. @@ -457,24 +492,18 @@ upcall_rust_personality(int version, return upcall_s_rust_personality(&args); } -extern "C" void -shape_cmp_type(int8_t *result, const type_desc *tydesc, - const type_desc **subtydescs, uint8_t *data_0, - uint8_t *data_1, uint8_t cmp_type); - extern "C" void upcall_cmp_type(int8_t *result, const type_desc *tydesc, const type_desc **subtydescs, uint8_t *data_0, uint8_t *data_1, uint8_t cmp_type) { - shape_cmp_type(result, tydesc, subtydescs, data_0, data_1, cmp_type); + s_cmp_type_args args = {result, tydesc, subtydescs, data_0, data_1, cmp_type}; + upcall_s_cmp_type(&args); } -extern "C" void -shape_log_type(const type_desc *tydesc, uint8_t *data, uint32_t level); - extern "C" void upcall_log_type(const type_desc *tydesc, uint8_t *data, uint32_t level) { - shape_log_type(tydesc, data, level); + s_log_type_args args = {tydesc, data, level}; + upcall_s_log_type(&args); } // -- cgit 1.4.1-3-g733a5 From 3d7b89bc4dc63632ee0003869811933ddc1962e9 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 6 Dec 2011 21:19:59 -0800 Subject: rt: Reorganize rust_upcall.cpp a bit --- src/rt/rust_upcall.cpp | 68 ++++++++++++++++++++++++++------------------------ 1 file changed, 36 insertions(+), 32 deletions(-) (limited to 'src') diff --git a/src/rt/rust_upcall.cpp b/src/rt/rust_upcall.cpp index 22dc18982d5..e4b646e39ff 100644 --- a/src/rt/rust_upcall.cpp +++ b/src/rt/rust_upcall.cpp @@ -288,38 +288,6 @@ upcall_s_dynastack_free(s_dynastack_free_args *args) { return rust_scheduler::get_task()->dynastack.free(args->ptr); } -struct rust_new_stack2_args { - void *new_stack; - size_t stk_sz; - void *args_addr; - size_t args_sz; -}; - -// A new stack function suitable for calling through -// upcall_call_shim_on_c_stack -extern "C" CDECL void -upcall_new_stack(struct rust_new_stack2_args *args) { - rust_task *task = rust_scheduler::get_task(); - args->new_stack = task->new_stack(args->stk_sz, - args->args_addr, - args->args_sz); -} - -extern "C" CDECL void -upcall_del_stack() { - rust_task *task = rust_scheduler::get_task(); - task->del_stack(); -} - -// Landing pads need to call this to insert the -// correct limit into TLS. -// NB: This must be called on the Rust stack -extern "C" CDECL void -upcall_reset_stack_limit() { - rust_task *task = rust_scheduler::get_task(); - task->reset_stack_limit(); -} - extern "C" _Unwind_Reason_Code __gxx_personality_v0(int version, _Unwind_Action actions, @@ -506,6 +474,42 @@ upcall_log_type(const type_desc *tydesc, uint8_t *data, uint32_t level) { upcall_s_log_type(&args); } +struct rust_new_stack2_args { + void *new_stack; + size_t stk_sz; + void *args_addr; + size_t args_sz; +}; + +// A new stack function suitable for calling through +// upcall_call_shim_on_c_stack +// FIXME: Convert this to the same arrangement as +// the other upcalls, simplify __morestack +extern "C" CDECL void +upcall_new_stack(struct rust_new_stack2_args *args) { + rust_task *task = rust_scheduler::get_task(); + args->new_stack = task->new_stack(args->stk_sz, + args->args_addr, + args->args_sz); +} + +// FIXME: As above +extern "C" CDECL void +upcall_del_stack() { + rust_task *task = rust_scheduler::get_task(); + task->del_stack(); +} + +// Landing pads need to call this to insert the +// correct limit into TLS. +// NB: This must run on the Rust stack because it +// needs to acquire the value of the stack pointer +extern "C" CDECL void +upcall_reset_stack_limit() { + rust_task *task = rust_scheduler::get_task(); + task->reset_stack_limit(); +} + // // Local Variables: // mode: C++ -- cgit 1.4.1-3-g733a5 From 5d1a1dc4203f8ae77e2e9c5cba393887f0b7d762 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 6 Dec 2011 17:03:54 -0800 Subject: rt: Rename stk_seg.limit to stk_seg.end rust_task is using the word limit it two ways, so one has to change. --- src/rt/rust_scheduler.cpp | 1 - src/rt/rust_task.cpp | 14 +++++++------- src/rt/rust_task.h | 2 +- 3 files changed, 8 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/rt/rust_scheduler.cpp b/src/rt/rust_scheduler.cpp index 42b2e490404..601a7c3f0ef 100644 --- a/src/rt/rust_scheduler.cpp +++ b/src/rt/rust_scheduler.cpp @@ -286,7 +286,6 @@ rust_scheduler::start_main_loop() { scheduled_task->state->name); place_task_in_tls(scheduled_task); - //pthread_setspecific(89, (void *)scheduled_task->stk->limit); interrupt_flag = 0; diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 888c9ac701a..0f97a0a6853 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -51,8 +51,8 @@ new_stk(rust_scheduler *sched, rust_task *task, size_t minsz) LOGPTR(task->sched, "new stk", (uintptr_t)stk); memset(stk, 0, sizeof(stk_seg)); stk->next = task->stk; - stk->limit = (uintptr_t) &stk->data[minsz + RED_ZONE_SIZE]; - LOGPTR(task->sched, "stk limit", stk->limit); + stk->end = (uintptr_t) &stk->data[minsz + RED_ZONE_SIZE]; + LOGPTR(task->sched, "stk end", stk->end); stk->valgrind_id = VALGRIND_STACK_REGISTER(&stk->data[0], &stk->data[minsz + RED_ZONE_SIZE]); @@ -106,7 +106,7 @@ rust_task::rust_task(rust_scheduler *sched, rust_task_list *state, user.notify_enabled = 0; stk = new_stk(sched, this, 0); - user.rust_sp = stk->limit; + user.rust_sp = stk->end; if (supervisor) { supervisor->ref(); } @@ -582,7 +582,7 @@ rust_task::new_stack(size_t stk_sz, void *args_addr, size_t args_sz) { stk_seg *stk_seg = new_stk(sched, this, stk_sz + args_sz); - uint8_t *new_sp = (uint8_t*)stk_seg->limit; + uint8_t *new_sp = (uint8_t*)stk_seg->end; size_t sizeof_retaddr = sizeof(void*); // Make enough room on the new stack to hold the old stack pointer // in addition to the function arguments @@ -608,7 +608,7 @@ rust_task::record_stack_limit() { // account for those 256 bytes. const unsigned LIMIT_OFFSET = 256; A(sched, - (uintptr_t)stk->limit - RED_ZONE_SIZE + (uintptr_t)stk->end - RED_ZONE_SIZE - (uintptr_t)stk->data >= LIMIT_OFFSET, "Stack size must be greater than LIMIT_OFFSET"); record_sp(stk->data + LIMIT_OFFSET + RED_ZONE_SIZE); @@ -627,9 +627,9 @@ rust_task::reset_stack_limit() { uintptr_t sp = get_sp(); // Not positive these bounds for sp are correct. // I think that the first possible value for esp on a new - // stack is stk->limit, which points one word in front of + // stack is stk->end, which points one word in front of // the first work to be pushed onto a new stack. - while (sp <= (uintptr_t)stk->data || stk->limit < sp) { + while (sp <= (uintptr_t)stk->data || stk->end < sp) { del_stk(this, stk); A(sched, stk != NULL, "Failed to find the current stack"); } diff --git a/src/rt/rust_task.h b/src/rt/rust_task.h index 47472801510..3d5cbff9910 100644 --- a/src/rt/rust_task.h +++ b/src/rt/rust_task.h @@ -25,7 +25,7 @@ struct rust_box; struct stk_seg { stk_seg *next; - uintptr_t limit; + uintptr_t end; unsigned int valgrind_id; #ifndef _LP64 uint32_t pad; -- cgit 1.4.1-3-g733a5 From 9656ceac60258c4189c31b402def67039ae17822 Mon Sep 17 00:00:00 2001 From: Brian Anderson Date: Tue, 6 Dec 2011 17:19:24 -0800 Subject: rt: Put 16 guard bytes at the end of the stack --- src/rt/rust_task.cpp | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/rt/rust_task.cpp b/src/rt/rust_task.cpp index 0f97a0a6853..bdc2f7ff7ce 100644 --- a/src/rt/rust_task.cpp +++ b/src/rt/rust_task.cpp @@ -14,15 +14,22 @@ #include "globals.h" +// Each stack gets some guard bytes that valgrind will verify we don't touch +#ifndef NVALGRIND +#define STACK_NOACCESS_SIZE 16 +#else +#define STACK_NOACCESS_SIZE 0 +#endif + // The amount of extra space at the end of each stack segment, available // to the rt, compiler and dynamic linker for running small functions // FIXME: We want this to be 128 but need to slim the red zone calls down #ifdef __i386__ -#define RED_ZONE_SIZE 65536 +#define RED_ZONE_SIZE (65536 + STACK_NOACCESS_SIZE) #endif #ifdef __x86_64__ -#define RED_ZONE_SIZE 65536 +#define RED_ZONE_SIZE (65536 + STACK_NOACCESS_SIZE) #endif // Stack size @@ -56,6 +63,9 @@ new_stk(rust_scheduler *sched, rust_task *task, size_t minsz) stk->valgrind_id = VALGRIND_STACK_REGISTER(&stk->data[0], &stk->data[minsz + RED_ZONE_SIZE]); +#ifndef NVALGRIND + VALGRIND_MAKE_MEM_NOACCESS(stk->data, STACK_NOACCESS_SIZE); +#endif task->stk = stk; return stk; } @@ -67,6 +77,9 @@ del_stk(rust_task *task, stk_seg *stk) task->stk = stk->next; +#ifndef NVALGRIND + VALGRIND_MAKE_MEM_DEFINED(stk->data, STACK_NOACCESS_SIZE); +#endif VALGRIND_STACK_DEREGISTER(stk->valgrind_id); LOGPTR(task->sched, "freeing stk segment", (uintptr_t)stk); task->free(stk); -- cgit 1.4.1-3-g733a5 From d28e0c0c0ae329705a063a025b853b292ff033a7 Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 7 Dec 2011 14:09:45 +0100 Subject: Make typestate properly descend pattern guards Closes #1265 --- src/comp/middle/tstate/pre_post_conditions.rs | 4 ++++ src/comp/middle/tstate/states.rs | 6 ++++++ 2 files changed, 10 insertions(+) (limited to 'src') diff --git a/src/comp/middle/tstate/pre_post_conditions.rs b/src/comp/middle/tstate/pre_post_conditions.rs index d0ac63704d7..d8e57c90986 100644 --- a/src/comp/middle/tstate/pre_post_conditions.rs +++ b/src/comp/middle/tstate/pre_post_conditions.rs @@ -452,6 +452,10 @@ fn find_pre_post_expr(fcx: fn_ctxt, e: @expr) { expr_alt(ex, alts) { find_pre_post_expr(fcx, ex); fn do_an_alt(fcx: fn_ctxt, an_alt: arm) -> pre_and_post { + alt an_alt.guard { + some(e) { find_pre_post_expr(fcx, e); } + _ {} + } find_pre_post_block(fcx, an_alt.body); ret block_pp(fcx.ccx, an_alt.body); } diff --git a/src/comp/middle/tstate/states.rs b/src/comp/middle/tstate/states.rs index ed84520a6b9..aa7977d142d 100644 --- a/src/comp/middle/tstate/states.rs +++ b/src/comp/middle/tstate/states.rs @@ -530,6 +530,12 @@ fn find_pre_post_state_expr(fcx: fn_ctxt, pres: prestate, e: @expr) -> bool { if vec::len(alts) > 0u { a_post = false_postcond(num_constrs); for an_alt: arm in alts { + alt an_alt.guard { + some(e) { + changed |= find_pre_post_state_expr(fcx, e_post, e); + } + _ {} + } changed |= find_pre_post_state_block(fcx, e_post, an_alt.body); intersect(a_post, block_poststate(fcx.ccx, an_alt.body)); -- cgit 1.4.1-3-g733a5 From 03a6e542126b755a9cd2f4f56144107ba0f4d1cd Mon Sep 17 00:00:00 2001 From: Marijn Haverbeke Date: Wed, 7 Dec 2011 15:28:57 +0100 Subject: Disallow binding by-mut-ref and by-move arguments Fix bug in bound by-copy arguments. Closes #1261 --- src/comp/middle/mut.rs | 25 +++++++++++++++++++++++++ src/comp/middle/trans.rs | 6 ++++++ src/libstd/task.rs | 2 +- src/test/bench/task-perf-word-count.rs | 18 +++++++++--------- src/test/stdtest/treemap.rs | 4 ++-- 5 files changed, 43 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/comp/middle/mut.rs b/src/comp/middle/mut.rs index 12598f3729b..63dadd347e1 100644 --- a/src/comp/middle/mut.rs +++ b/src/comp/middle/mut.rs @@ -150,6 +150,7 @@ fn visit_decl(cx: @ctx, d: @decl, &&e: (), v: visit::vt<()>) { fn visit_expr(cx: @ctx, ex: @expr, &&e: (), v: visit::vt<()>) { alt ex.node { expr_call(f, args, _) { check_call(cx, f, args); } + expr_bind(f, args) { check_bind(cx, f, args); } expr_swap(lhs, rhs) { check_lval(cx, lhs, msg_assign); check_lval(cx, rhs, msg_assign); @@ -230,6 +231,30 @@ fn check_call(cx: @ctx, f: @expr, args: [@expr]) { } } +fn check_bind(cx: @ctx, f: @expr, args: [option::t<@expr>]) { + let arg_ts = ty::ty_fn_args(cx.tcx, ty::expr_ty(cx.tcx, f)); + let i = 0u; + for arg in args { + alt arg { + some(expr) { + alt (alt arg_ts[i].mode { + by_mut_ref. { some("by mutable reference") } + by_move. { some("by move") } + _ { none } + }) { + some(name) { + cx.tcx.sess.span_err( + expr.span, "can not bind an argument passed " + name); + } + none. {} + } + } + _ {} + } + i += 1u; + } +} + fn is_immutable_def(def: def) -> option::t { alt def { def_fn(_, _) | def_mod(_) | def_native_mod(_) | def_const(_) | diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 693c8ae79e8..107c53cfac3 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -3462,6 +3462,12 @@ fn trans_bind_thunk(cx: @local_ctxt, sp: span, incoming_fty: ty::t, bcx = bound_arg.bcx; let val = bound_arg.val; if out_arg.mode == ast::by_val { val = Load(bcx, val); } + if out_arg.mode == ast::by_copy { + let {bcx: cx, val: alloc} = alloc_ty(bcx, out_arg.ty); + bcx = memmove_ty(cx, alloc, val, out_arg.ty); + bcx = take_ty(bcx, alloc, out_arg.ty); + val = alloc; + } // If the type is parameterized, then we need to cast the // type we actually have to the parameterized out type. if ty::type_contains_params(cx.ccx.tcx, out_arg.ty) { diff --git a/src/libstd/task.rs b/src/libstd/task.rs index a8765407f3a..3e396d3ac63 100644 --- a/src/libstd/task.rs +++ b/src/libstd/task.rs @@ -288,7 +288,7 @@ fn spawn_inner(-data: T, f: fn(T), notify: option>) -> task unsafe { - fn wrapper(-data: *u8, f: fn(T)) unsafe { + fn wrapper(data: *u8, f: fn(T)) unsafe { let data: ~T = unsafe::reinterpret_cast(data); f(*data); } diff --git a/src/test/bench/task-perf-word-count.rs b/src/test/bench/task-perf-word-count.rs index 2d4e14af058..d0309713633 100644 --- a/src/test/bench/task-perf-word-count.rs +++ b/src/test/bench/task-perf-word-count.rs @@ -112,12 +112,12 @@ mod map_reduce { send(out, chan(p)); - let ref_count = 0; - let is_done = false; + let state = @{mutable ref_count: 0, mutable is_done: false}; - fn get(p: port, &ref_count: int, &is_done: bool) -> - option { - while !is_done || ref_count > 0 { + fn get(p: port, state: @{mutable ref_count: int, + mutable is_done: bool}) + -> option { + while !state.is_done || state.ref_count > 0 { alt recv(p) { emit_val(v) { // log_err #fmt("received %d", v); @@ -125,16 +125,16 @@ mod map_reduce { } done. { // log_err "all done"; - is_done = true; + state.is_done = true; } - ref. { ref_count += 1; } - release. { ref_count -= 1; } + ref. { state.ref_count += 1; } + release. { state.ref_count -= 1; } } } ret none; } - reduce(key, bind get(p, ref_count, is_done)); + reduce(key, bind get(p, state)); } fn map_reduce(-inputs: [str]) { diff --git a/src/test/stdtest/treemap.rs b/src/test/stdtest/treemap.rs index 1701be37901..2fba1ebb196 100644 --- a/src/test/stdtest/treemap.rs +++ b/src/test/stdtest/treemap.rs @@ -39,8 +39,8 @@ fn traverse_in_order() { insert(m, 2, ()); insert(m, 1, ()); - let n = 0; - fn t(&n: int, &&k: int, &&_v: ()) { assert (n == k); n += 1; } + let n = @mutable 0; + fn t(n: @mutable int, &&k: int, &&_v: ()) { assert (*n == k); *n += 1; } traverse(m, bind t(n, _, _)); } -- cgit 1.4.1-3-g733a5 From 6c95e400d82699887b66f5de0fef2bb5e1f8cc32 Mon Sep 17 00:00:00 2001 From: Niko Matsakis Date: Wed, 7 Dec 2011 07:21:07 -0800 Subject: repair more hash functions --- src/comp/middle/ty.rs | 30 +++++++++++++++--------------- src/comp/syntax/ast_util.rs | 2 +- src/libstd/str.rs | 2 +- 3 files changed, 17 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/comp/middle/ty.rs b/src/comp/middle/ty.rs index b5b5559f4aa..022b249674b 100644 --- a/src/comp/middle/ty.rs +++ b/src/comp/middle/ty.rs @@ -1299,23 +1299,23 @@ fn type_autoderef(cx: ctxt, t: ty::t) -> ty::t { fn hash_type_structure(st: sty) -> uint { fn hash_uint(id: uint, n: uint) -> uint { let h = id; - h += h << 5u + n; + h += (h << 5u) + n; ret h; } fn hash_def(id: uint, did: ast::def_id) -> uint { let h = id; - h += h << 5u + (did.crate as uint); - h += h << 5u + (did.node as uint); + h += (h << 5u) + (did.crate as uint); + h += (h << 5u) + (did.node as uint); ret h; } fn hash_subty(id: uint, subty: t) -> uint { let h = id; - h += h << 5u + hash_ty(subty); + h += (h << 5u) + hash_ty(subty); ret h; } fn hash_type_constr(id: uint, c: @type_constr) -> uint { let h = id; - h += h << 5u + hash_def(h, c.node.id); + h += (h << 5u) + hash_def(h, c.node.id); ret hash_type_constr_args(h, c.node.args); } fn hash_type_constr_args(id: uint, args: [@ty_constr_arg]) -> uint { @@ -1338,8 +1338,8 @@ fn hash_type_structure(st: sty) -> uint { fn hash_fn(id: uint, args: [arg], rty: t) -> uint { let h = id; - for a: arg in args { h += h << 5u + hash_ty(a.ty); } - h += h << 5u + hash_ty(rty); + for a: arg in args { h += (h << 5u) + hash_ty(a.ty); } + h += (h << 5u) + hash_ty(rty); ret h; } alt st { @@ -1366,19 +1366,19 @@ fn hash_type_structure(st: sty) -> uint { ty_str. { ret 17u; } ty_tag(did, tys) { let h = hash_def(18u, did); - for typ: t in tys { h += h << 5u + hash_ty(typ); } + for typ: t in tys { h += (h << 5u) + hash_ty(typ); } ret h; } ty_box(mt) { ret hash_subty(19u, mt.ty); } ty_vec(mt) { ret hash_subty(21u, mt.ty); } ty_rec(fields) { let h = 26u; - for f: field in fields { h += h << 5u + hash_ty(f.mt.ty); } + for f: field in fields { h += (h << 5u) + hash_ty(f.mt.ty); } ret h; } ty_tup(ts) { let h = 25u; - for tt in ts { h += h << 5u + hash_ty(tt); } + for tt in ts { h += (h << 5u) + hash_ty(tt); } ret h; } @@ -1389,7 +1389,7 @@ fn hash_type_structure(st: sty) -> uint { ty_native_fn(args, rty) { ret hash_fn(28u, args, rty); } ty_obj(methods) { let h = 29u; - for m: method in methods { h += h << 5u + str::hash(m.ident); } + for m: method in methods { h += (h << 5u) + str::hash(m.ident); } ret h; } ty_var(v) { ret hash_uint(30u, v as uint); } @@ -1400,15 +1400,15 @@ fn hash_type_structure(st: sty) -> uint { ty_ptr(mt) { ret hash_subty(35u, mt.ty); } ty_res(did, sub, tps) { let h = hash_subty(hash_def(18u, did), sub); - for tp: t in tps { h += h << 5u + hash_ty(tp); } + for tp: t in tps { h += (h << 5u) + hash_ty(tp); } ret h; } ty_constr(t, cs) { let h = 36u; - for c: @type_constr in cs { h += h << 5u + hash_type_constr(h, c); } + for c: @type_constr in cs { h += (h << 5u) + hash_type_constr(h, c); } ret h; } - ty_uniq(mt) { let h = 37u; h += h << 5u + hash_ty(mt.ty); ret h; } + ty_uniq(mt) { let h = 37u; h += (h << 5u) + hash_ty(mt.ty); ret h; } } } @@ -1416,7 +1416,7 @@ fn hash_type_info(st: sty, cname_opt: option::t) -> uint { let h = hash_type_structure(st); alt cname_opt { none. {/* no-op */ } - some(s) { h += h << 5u + str::hash(s); } + some(s) { h += (h << 5u) + str::hash(s); } } ret h; } diff --git a/src/comp/syntax/ast_util.rs b/src/comp/syntax/ast_util.rs index f39b5865c25..60b3f2b6fa4 100644 --- a/src/comp/syntax/ast_util.rs +++ b/src/comp/syntax/ast_util.rs @@ -199,7 +199,7 @@ fn hash_ty(&&t: @ty) -> uint { } fn hash_def_id(&&id: def_id) -> uint { - id.crate as uint << 16u + (id.node as uint) + (id.crate as uint << 16u) + (id.node as uint) } fn eq_def_id(&&a: def_id, &&b: def_id) -> bool { diff --git a/src/libstd/str.rs b/src/libstd/str.rs index 2bae8d699a5..521dc33758e 100644 --- a/src/libstd/str.rs +++ b/src/libstd/str.rs @@ -324,7 +324,7 @@ fn char_range_at(s: str, i: uint) -> {ch: char, next: uint} { // Clunky way to get the right bits from the first byte. Uses two shifts, // the first to clip off the marker bits at the left of the byte, and then // a second (as uint) to get it to the right position. - val += (b0 << (w + 1u as u8) as uint) << (w - 1u) * 6u - w - 1u; + val += (b0 << (w + 1u as u8) as uint) << ((w - 1u) * 6u - w - 1u); ret {ch: val as char, next: i}; } -- cgit 1.4.1-3-g733a5