rt: Create different stack-switching paths for upcalls and shims
Shims need to play with the stack limit, upcalls don't. Only one upcall, upcall_fail is allowed to catch, and we need a find a way to get rid of that catch as well because it results in _Unwind_Resume running off the end of the Rust stack.
This commit is contained in:
parent
f57fd8de1f
commit
c73eb8ff51
1 changed files with 34 additions and 22 deletions
|
|
@ -27,7 +27,15 @@ check_stack_alignment() __attribute__ ((aligned (16)));
|
||||||
static void check_stack_alignment() { }
|
static void check_stack_alignment() { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define SWITCH_STACK(A, F) upcall_call_shim_on_c_stack((void*)A, (void*)F)
|
#define UPCALL_SWITCH_STACK(A, F) call_upcall_on_c_stack((void*)A, (void*)F)
|
||||||
|
|
||||||
|
inline void
|
||||||
|
call_upcall_on_c_stack(void *args, void *fn_ptr) {
|
||||||
|
check_stack_alignment();
|
||||||
|
rust_task *task = rust_scheduler::get_task();
|
||||||
|
rust_scheduler *sched = task->sched;
|
||||||
|
sched->c_context.call_shim_on_c_stack(args, fn_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
extern "C" void record_sp(void *limit);
|
extern "C" void record_sp(void *limit);
|
||||||
|
|
||||||
|
|
@ -35,7 +43,8 @@ extern "C" void record_sp(void *limit);
|
||||||
* Switches to the C-stack and invokes |fn_ptr|, passing |args| as argument.
|
* Switches to the C-stack and invokes |fn_ptr|, passing |args| as argument.
|
||||||
* This is used by the C compiler to call native functions and by other
|
* This is used by the C compiler to call native functions and by other
|
||||||
* upcalls to switch to the C stack. The return value is passed through a
|
* upcalls to switch to the C stack. The return value is passed through a
|
||||||
* field in the args parameter.
|
* field in the args parameter. This upcall is specifically for switching
|
||||||
|
* to the shim functions generated by rustc.
|
||||||
*/
|
*/
|
||||||
extern "C" CDECL void
|
extern "C" CDECL void
|
||||||
upcall_call_shim_on_c_stack(void *args, void *fn_ptr) {
|
upcall_call_shim_on_c_stack(void *args, void *fn_ptr) {
|
||||||
|
|
@ -51,10 +60,9 @@ upcall_call_shim_on_c_stack(void *args, void *fn_ptr) {
|
||||||
try {
|
try {
|
||||||
sched->c_context.call_shim_on_c_stack(args, fn_ptr);
|
sched->c_context.call_shim_on_c_stack(args, fn_ptr);
|
||||||
} catch (...) {
|
} catch (...) {
|
||||||
task = rust_scheduler::get_task();
|
A(sched, false, "Native code threw an exception");
|
||||||
task->record_stack_limit();
|
|
||||||
throw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
task = rust_scheduler::get_task();
|
task = rust_scheduler::get_task();
|
||||||
task->record_stack_limit();
|
task->record_stack_limit();
|
||||||
}
|
}
|
||||||
|
|
@ -80,8 +88,12 @@ extern "C" CDECL void
|
||||||
upcall_fail(char const *expr,
|
upcall_fail(char const *expr,
|
||||||
char const *file,
|
char const *file,
|
||||||
size_t line) {
|
size_t line) {
|
||||||
s_fail_args args = {expr,file,line};
|
try {
|
||||||
SWITCH_STACK(&args, upcall_s_fail);
|
s_fail_args args = {expr,file,line};
|
||||||
|
UPCALL_SWITCH_STACK(&args, upcall_s_fail);
|
||||||
|
} catch (rust_task*) {
|
||||||
|
throw;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
|
|
@ -124,7 +136,7 @@ upcall_s_malloc(s_malloc_args *args) {
|
||||||
extern "C" CDECL uintptr_t
|
extern "C" CDECL uintptr_t
|
||||||
upcall_malloc(size_t nbytes, type_desc *td) {
|
upcall_malloc(size_t nbytes, type_desc *td) {
|
||||||
s_malloc_args args = {0, nbytes, td};
|
s_malloc_args args = {0, nbytes, td};
|
||||||
SWITCH_STACK(&args, upcall_s_malloc);
|
UPCALL_SWITCH_STACK(&args, upcall_s_malloc);
|
||||||
return args.retval;
|
return args.retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -156,7 +168,7 @@ upcall_s_free(s_free_args *args) {
|
||||||
extern "C" CDECL void
|
extern "C" CDECL void
|
||||||
upcall_free(void* ptr, uintptr_t is_gc) {
|
upcall_free(void* ptr, uintptr_t is_gc) {
|
||||||
s_free_args args = {ptr, is_gc};
|
s_free_args args = {ptr, is_gc};
|
||||||
SWITCH_STACK(&args, upcall_s_free);
|
UPCALL_SWITCH_STACK(&args, upcall_s_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
|
|
@ -189,7 +201,7 @@ upcall_s_shared_malloc(s_shared_malloc_args *args) {
|
||||||
extern "C" CDECL uintptr_t
|
extern "C" CDECL uintptr_t
|
||||||
upcall_shared_malloc(size_t nbytes, type_desc *td) {
|
upcall_shared_malloc(size_t nbytes, type_desc *td) {
|
||||||
s_shared_malloc_args args = {0, nbytes, td};
|
s_shared_malloc_args args = {0, nbytes, td};
|
||||||
SWITCH_STACK(&args, upcall_s_shared_malloc);
|
UPCALL_SWITCH_STACK(&args, upcall_s_shared_malloc);
|
||||||
return args.retval;
|
return args.retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -216,7 +228,7 @@ upcall_s_shared_free(s_shared_free_args *args) {
|
||||||
extern "C" CDECL void
|
extern "C" CDECL void
|
||||||
upcall_shared_free(void* ptr) {
|
upcall_shared_free(void* ptr) {
|
||||||
s_shared_free_args args = {ptr};
|
s_shared_free_args args = {ptr};
|
||||||
SWITCH_STACK(&args, upcall_s_shared_free);
|
UPCALL_SWITCH_STACK(&args, upcall_s_shared_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
|
|
@ -262,7 +274,7 @@ void upcall_s_create_shared_type_desc(s_create_shared_type_desc_args *args)
|
||||||
extern "C" CDECL type_desc *
|
extern "C" CDECL type_desc *
|
||||||
upcall_create_shared_type_desc(type_desc *td) {
|
upcall_create_shared_type_desc(type_desc *td) {
|
||||||
s_create_shared_type_desc_args args = { td, 0 };
|
s_create_shared_type_desc_args args = { td, 0 };
|
||||||
SWITCH_STACK(&args, upcall_s_create_shared_type_desc);
|
UPCALL_SWITCH_STACK(&args, upcall_s_create_shared_type_desc);
|
||||||
return args.res;
|
return args.res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -285,7 +297,7 @@ void upcall_s_free_shared_type_desc(type_desc *td)
|
||||||
|
|
||||||
extern "C" CDECL void
|
extern "C" CDECL void
|
||||||
upcall_free_shared_type_desc(type_desc *td) {
|
upcall_free_shared_type_desc(type_desc *td) {
|
||||||
SWITCH_STACK(td, upcall_s_free_shared_type_desc);
|
UPCALL_SWITCH_STACK(td, upcall_s_free_shared_type_desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**********************************************************************
|
/**********************************************************************
|
||||||
|
|
@ -325,7 +337,7 @@ upcall_get_type_desc(void *curr_crate, // ignored, legacy compat.
|
||||||
type_desc const **descs,
|
type_desc const **descs,
|
||||||
uintptr_t n_obj_params) {
|
uintptr_t n_obj_params) {
|
||||||
s_get_type_desc_args args = {0,size,align,n_descs,descs,n_obj_params};
|
s_get_type_desc_args args = {0,size,align,n_descs,descs,n_obj_params};
|
||||||
SWITCH_STACK(&args, upcall_s_get_type_desc);
|
UPCALL_SWITCH_STACK(&args, upcall_s_get_type_desc);
|
||||||
return args.retval;
|
return args.retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -347,7 +359,7 @@ upcall_s_vec_grow(s_vec_grow_args *args) {
|
||||||
extern "C" CDECL void
|
extern "C" CDECL void
|
||||||
upcall_vec_grow(rust_vec** vp, size_t new_sz) {
|
upcall_vec_grow(rust_vec** vp, size_t new_sz) {
|
||||||
s_vec_grow_args args = {vp, new_sz};
|
s_vec_grow_args args = {vp, new_sz};
|
||||||
SWITCH_STACK(&args, upcall_s_vec_grow);
|
UPCALL_SWITCH_STACK(&args, upcall_s_vec_grow);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy elements from one vector to another,
|
// Copy elements from one vector to another,
|
||||||
|
|
@ -414,7 +426,7 @@ upcall_s_dynastack_mark(s_dynastack_mark_args *args) {
|
||||||
extern "C" CDECL void *
|
extern "C" CDECL void *
|
||||||
upcall_dynastack_mark() {
|
upcall_dynastack_mark() {
|
||||||
s_dynastack_mark_args args = {0};
|
s_dynastack_mark_args args = {0};
|
||||||
SWITCH_STACK(&args, upcall_s_dynastack_mark);
|
UPCALL_SWITCH_STACK(&args, upcall_s_dynastack_mark);
|
||||||
return args.retval;
|
return args.retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -439,7 +451,7 @@ upcall_s_dynastack_alloc(s_dynastack_alloc_args *args) {
|
||||||
extern "C" CDECL void *
|
extern "C" CDECL void *
|
||||||
upcall_dynastack_alloc(size_t sz) {
|
upcall_dynastack_alloc(size_t sz) {
|
||||||
s_dynastack_alloc_args args = {0, sz};
|
s_dynastack_alloc_args args = {0, sz};
|
||||||
SWITCH_STACK(&args, upcall_s_dynastack_alloc);
|
UPCALL_SWITCH_STACK(&args, upcall_s_dynastack_alloc);
|
||||||
return args.retval;
|
return args.retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -465,7 +477,7 @@ upcall_s_dynastack_alloc_2(s_dynastack_alloc_2_args *args) {
|
||||||
extern "C" CDECL void *
|
extern "C" CDECL void *
|
||||||
upcall_dynastack_alloc_2(size_t sz, type_desc *ty) {
|
upcall_dynastack_alloc_2(size_t sz, type_desc *ty) {
|
||||||
s_dynastack_alloc_2_args args = {0, sz, ty};
|
s_dynastack_alloc_2_args args = {0, sz, ty};
|
||||||
SWITCH_STACK(&args, upcall_s_dynastack_alloc_2);
|
UPCALL_SWITCH_STACK(&args, upcall_s_dynastack_alloc_2);
|
||||||
return args.retval;
|
return args.retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -482,7 +494,7 @@ upcall_s_dynastack_free(s_dynastack_free_args *args) {
|
||||||
extern "C" CDECL void
|
extern "C" CDECL void
|
||||||
upcall_dynastack_free(void *ptr) {
|
upcall_dynastack_free(void *ptr) {
|
||||||
s_dynastack_free_args args = {ptr};
|
s_dynastack_free_args args = {ptr};
|
||||||
SWITCH_STACK(&args, upcall_s_dynastack_free);
|
UPCALL_SWITCH_STACK(&args, upcall_s_dynastack_free);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" _Unwind_Reason_Code
|
extern "C" _Unwind_Reason_Code
|
||||||
|
|
@ -524,7 +536,7 @@ upcall_rust_personality(int version,
|
||||||
s_rust_personality_args args = {(_Unwind_Reason_Code)0,
|
s_rust_personality_args args = {(_Unwind_Reason_Code)0,
|
||||||
version, actions, exception_class,
|
version, actions, exception_class,
|
||||||
ue_header, context};
|
ue_header, context};
|
||||||
SWITCH_STACK(&args, upcall_s_rust_personality);
|
UPCALL_SWITCH_STACK(&args, upcall_s_rust_personality);
|
||||||
return args.retval;
|
return args.retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -553,7 +565,7 @@ upcall_cmp_type(int8_t *result, const type_desc *tydesc,
|
||||||
const type_desc **subtydescs, uint8_t *data_0,
|
const type_desc **subtydescs, uint8_t *data_0,
|
||||||
uint8_t *data_1, uint8_t cmp_type) {
|
uint8_t *data_1, uint8_t cmp_type) {
|
||||||
s_cmp_type_args args = {result, tydesc, subtydescs, data_0, data_1, cmp_type};
|
s_cmp_type_args args = {result, tydesc, subtydescs, data_0, data_1, cmp_type};
|
||||||
SWITCH_STACK(&args, upcall_s_cmp_type);
|
UPCALL_SWITCH_STACK(&args, upcall_s_cmp_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
extern "C" void
|
extern "C" void
|
||||||
|
|
@ -573,7 +585,7 @@ upcall_s_log_type(s_log_type_args *args) {
|
||||||
extern "C" void
|
extern "C" void
|
||||||
upcall_log_type(const type_desc *tydesc, uint8_t *data, uint32_t level) {
|
upcall_log_type(const type_desc *tydesc, uint8_t *data, uint32_t level) {
|
||||||
s_log_type_args args = {tydesc, data, level};
|
s_log_type_args args = {tydesc, data, level};
|
||||||
SWITCH_STACK(&args, upcall_s_log_type);
|
UPCALL_SWITCH_STACK(&args, upcall_s_log_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct rust_new_stack2_args {
|
struct rust_new_stack2_args {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue