Merge branch 'master' of github.com:graydon/rust
This commit is contained in:
commit
84bbc12444
10 changed files with 65 additions and 6 deletions
|
|
@ -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", [])
|
||||
};
|
||||
}
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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__)
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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++
|
||||
|
|
|
|||
|
|
@ -200,6 +200,7 @@ rust_task : public kernel_owned<rust_task>, 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();
|
||||
};
|
||||
|
||||
//
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue