Skip to content

Commit 84bbc12

Browse files
committed
Merge branch 'master' of github.com:graydon/rust
2 parents 28f9af6 + 9a738fd commit 84bbc12

File tree

10 files changed

+65
-6
lines changed

10 files changed

+65
-6
lines changed

src/comp/back/upcall.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ type upcalls =
2727
dynastack_free: ValueRef,
2828
alloc_c_stack: ValueRef,
2929
call_shim_on_c_stack: ValueRef,
30-
rust_personality: ValueRef};
30+
rust_personality: ValueRef,
31+
reset_stack_limit: ValueRef};
3132

3233
fn declare_upcalls(targ_cfg: @session::config,
3334
_tn: type_names,
@@ -89,7 +90,8 @@ fn declare_upcalls(targ_cfg: @session::config,
8990
// arguments: void *args, void *fn_ptr
9091
[T_ptr(T_i8()), T_ptr(T_i8())],
9192
int_t),
92-
rust_personality: d("rust_personality", [], T_i32())
93+
rust_personality: d("rust_personality", [], T_i32()),
94+
reset_stack_limit: dv("reset_stack_limit", [])
9395
};
9496
}
9597
//

src/comp/middle/trans.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3904,6 +3904,11 @@ fn trans_landing_pad(bcx: @block_ctxt,
39043904
// The landing pad block is a cleanup
39053905
SetCleanup(bcx, llpad);
39063906

3907+
// Because we may have unwound across a stack boundary, we must call into
3908+
// the runtime to figure out which stack segment we are on and place the
3909+
// stack limit back into the TLS.
3910+
Call(bcx, bcx_ccx(bcx).upcalls.reset_stack_limit, []);
3911+
39073912
// FIXME: This seems like a very naive and redundant way to generate the
39083913
// landing pads, as we're re-generating all in-scope cleanups for each
39093914
// function call. Probably good optimization opportunities here.

src/rt/arch/i386/record_sp.S

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
#if defined(__APPLE__) || defined(_WIN32)
44
#define RECORD_SP _record_sp
5+
#define GET_SP _get_sp
56
#else
67
#define RECORD_SP record_sp
8+
#define GET_SP get_sp
79
#endif
810

911
.globl RECORD_SP
12+
.globl GET_SP
1013

1114
#if defined(__linux__)
1215
RECORD_SP:
@@ -25,3 +28,7 @@ RECORD_SP:
2528
ret
2629
#endif
2730
#endif
31+
32+
GET_SP:
33+
movl %esp, %eax
34+
ret

src/rt/arch/x86_64/morestack.S

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,10 @@ MORESTACK:
132132

133133
addq $8, %rsp
134134
popq %rbp
135+
#ifdef __linux__
136+
.cfi_restore %rbp
137+
.cfi_def_cfa %rsp, 8
138+
#endif
135139
ret
136140

137141
#if defined(__ELF__)

src/rt/arch/x86_64/record_sp.S

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,14 @@
22

33
#if defined(__APPLE__) || defined(_WIN32)
44
#define RECORD_SP _record_sp
5+
#define GET_SP _get_sp
56
#else
67
#define RECORD_SP record_sp
8+
#define GET_SP get_sp
79
#endif
810

911
.globl RECORD_SP
12+
.globl GET_SP
1013

1114
#if defined(__linux__)
1215
RECORD_SP:
@@ -23,3 +26,7 @@ RECORD_SP:
2326
ret
2427
#endif
2528
#endif
29+
30+
GET_SP:
31+
movq %rsp, %rax
32+
ret

src/rt/rust_task.cpp

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@
1818
// to the rt, compiler and dynamic linker for running small functions
1919
// FIXME: We want this to be 128 but need to slim the red zone calls down
2020
#ifdef __i386__
21-
#define RED_ZONE_SIZE 2048
21+
#define RED_ZONE_SIZE 65536
2222
#endif
2323

2424
#ifdef __x86_64__
25-
#define RED_ZONE_SIZE 2048
25+
#define RED_ZONE_SIZE 65536
2626
#endif
2727

2828
// Stack size
@@ -613,6 +613,29 @@ rust_task::record_stack_limit() {
613613
"Stack size must be greater than LIMIT_OFFSET");
614614
record_sp(stk->data + LIMIT_OFFSET + RED_ZONE_SIZE);
615615
}
616+
617+
extern "C" uintptr_t get_sp();
618+
619+
/*
620+
Called by landing pads during unwinding to figure out which
621+
stack segment we are currently running on, delete the others,
622+
and record the stack limit (which was not restored when unwinding
623+
through __morestack).
624+
*/
625+
void
626+
rust_task::reset_stack_limit() {
627+
uintptr_t sp = get_sp();
628+
// Not positive these bounds for sp are correct.
629+
// I think that the first possible value for esp on a new
630+
// stack is stk->limit, which points one word in front of
631+
// the first work to be pushed onto a new stack.
632+
while (sp <= (uintptr_t)stk->data || stk->limit < sp) {
633+
del_stk(this, stk);
634+
A(sched, stk != NULL, "Failed to find the current stack");
635+
}
636+
record_stack_limit();
637+
}
638+
616639
//
617640
// Local Variables:
618641
// mode: C++

src/rt/rust_task.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ rust_task : public kernel_owned<rust_task>, rust_cond
200200
void *new_stack(size_t stk_sz, void *args_addr, size_t args_sz);
201201
void del_stack();
202202
void record_stack_limit();
203+
void reset_stack_limit();
203204
};
204205

205206
//

src/rt/rust_upcall.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -259,6 +259,15 @@ upcall_del_stack() {
259259
task->del_stack();
260260
}
261261

262+
// Landing pads need to call this to insert the
263+
// correct limit into TLS.
264+
// NB: This must be called on the Rust stack
265+
extern "C" CDECL void
266+
upcall_reset_stack_limit() {
267+
rust_task *task = rust_scheduler::get_task();
268+
task->reset_stack_limit();
269+
}
270+
262271
extern "C" _Unwind_Reason_Code
263272
__gxx_personality_v0(int version,
264273
_Unwind_Action actions,

src/rt/rustrt.def.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ upcall_vec_push
6969
upcall_call_shim_on_c_stack
7070
upcall_new_stack
7171
upcall_del_stack
72+
upcall_reset_stack_limit
7273
asm_call_on_stack
7374
rust_uv_default_loop
7475
rust_uv_loop_new

src/test/run-fail/morestack3.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ resource and_then_get_big_again(_i: @int) {
2525
getbig(i - 1);
2626
}
2727
}
28-
getbig(1000);
28+
getbig(100);
2929
}
3030

3131
fn main() {
3232
rustrt::set_min_stack(256u);
33-
std::task::spawn(1000, getbig_and_fail);
33+
std::task::spawn(100, getbig_and_fail);
3434
}

0 commit comments

Comments
 (0)