forked from OSchip/llvm-project
[libunwind] Improve unwinder stack usage - III
Implement the same optimization committed under r271004 on non-EHABI, non-SJLJ unwinder as well. Change-Id: I7f80ed91a75d1e778b50ba87cf8fb68658a083c7 llvm-svn: 272680
This commit is contained in:
parent
9df8f6c472
commit
af914fa2db
|
@ -33,16 +33,15 @@
|
||||||
#if !_LIBUNWIND_ARM_EHABI
|
#if !_LIBUNWIND_ARM_EHABI
|
||||||
|
|
||||||
static _Unwind_Reason_Code
|
static _Unwind_Reason_Code
|
||||||
unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
|
unwind_phase1(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
|
||||||
unw_cursor_t cursor1;
|
unw_init_local(cursor, uc);
|
||||||
unw_init_local(&cursor1, uc);
|
|
||||||
|
|
||||||
// Walk each frame looking for a place to stop.
|
// Walk each frame looking for a place to stop.
|
||||||
bool handlerNotFound = true;
|
bool handlerNotFound = true;
|
||||||
while (handlerNotFound) {
|
while (handlerNotFound) {
|
||||||
// Ask libuwind to get next frame (skip over first which is
|
// Ask libuwind to get next frame (skip over first which is
|
||||||
// _Unwind_RaiseException).
|
// _Unwind_RaiseException).
|
||||||
int stepResult = unw_step(&cursor1);
|
int stepResult = unw_step(cursor);
|
||||||
if (stepResult == 0) {
|
if (stepResult == 0) {
|
||||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached "
|
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_step() reached "
|
||||||
"bottom => _URC_END_OF_STACK\n",
|
"bottom => _URC_END_OF_STACK\n",
|
||||||
|
@ -58,7 +57,7 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
|
||||||
// See if frame has code to run (has personality routine).
|
// See if frame has code to run (has personality routine).
|
||||||
unw_proc_info_t frameInfo;
|
unw_proc_info_t frameInfo;
|
||||||
unw_word_t sp;
|
unw_word_t sp;
|
||||||
if (unw_get_proc_info(&cursor1, &frameInfo) != UNW_ESUCCESS) {
|
if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
|
||||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info "
|
_LIBUNWIND_TRACE_UNWINDING("unwind_phase1(ex_ojb=%p): unw_get_proc_info "
|
||||||
"failed => _URC_FATAL_PHASE1_ERROR\n",
|
"failed => _URC_FATAL_PHASE1_ERROR\n",
|
||||||
(void *)exception_object);
|
(void *)exception_object);
|
||||||
|
@ -70,12 +69,12 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
|
||||||
char functionBuf[512];
|
char functionBuf[512];
|
||||||
const char *functionName = functionBuf;
|
const char *functionName = functionBuf;
|
||||||
unw_word_t offset;
|
unw_word_t offset;
|
||||||
if ((unw_get_proc_name(&cursor1, functionBuf, sizeof(functionBuf),
|
if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
|
||||||
&offset) != UNW_ESUCCESS) ||
|
&offset) != UNW_ESUCCESS) ||
|
||||||
(frameInfo.start_ip + offset > frameInfo.end_ip))
|
(frameInfo.start_ip + offset > frameInfo.end_ip))
|
||||||
functionName = ".anonymous.";
|
functionName = ".anonymous.";
|
||||||
unw_word_t pc;
|
unw_word_t pc;
|
||||||
unw_get_reg(&cursor1, UNW_REG_IP, &pc);
|
unw_get_reg(cursor, UNW_REG_IP, &pc);
|
||||||
_LIBUNWIND_TRACE_UNWINDING(
|
_LIBUNWIND_TRACE_UNWINDING(
|
||||||
"unwind_phase1(ex_ojb=%p): pc=0x%" PRIx64 ", start_ip=0x%" PRIx64
|
"unwind_phase1(ex_ojb=%p): pc=0x%" PRIx64 ", start_ip=0x%" PRIx64
|
||||||
", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n",
|
", func=%s, lsda=0x%" PRIx64 ", personality=0x%" PRIx64 "\n",
|
||||||
|
@ -93,13 +92,13 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
|
||||||
(void *)exception_object, (void *)(uintptr_t)p);
|
(void *)exception_object, (void *)(uintptr_t)p);
|
||||||
_Unwind_Reason_Code personalityResult =
|
_Unwind_Reason_Code personalityResult =
|
||||||
(*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,
|
(*p)(1, _UA_SEARCH_PHASE, exception_object->exception_class,
|
||||||
exception_object, (struct _Unwind_Context *)(&cursor1));
|
exception_object, (struct _Unwind_Context *)(cursor));
|
||||||
switch (personalityResult) {
|
switch (personalityResult) {
|
||||||
case _URC_HANDLER_FOUND:
|
case _URC_HANDLER_FOUND:
|
||||||
// found a catch clause or locals that need destructing in this frame
|
// found a catch clause or locals that need destructing in this frame
|
||||||
// stop search and remember stack pointer at the frame
|
// stop search and remember stack pointer at the frame
|
||||||
handlerNotFound = false;
|
handlerNotFound = false;
|
||||||
unw_get_reg(&cursor1, UNW_REG_SP, &sp);
|
unw_get_reg(cursor, UNW_REG_SP, &sp);
|
||||||
exception_object->private_2 = (uintptr_t)sp;
|
exception_object->private_2 = (uintptr_t)sp;
|
||||||
_LIBUNWIND_TRACE_UNWINDING(
|
_LIBUNWIND_TRACE_UNWINDING(
|
||||||
"unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND \n",
|
"unwind_phase1(ex_ojb=%p): _URC_HANDLER_FOUND \n",
|
||||||
|
@ -127,9 +126,8 @@ unwind_phase1(unw_context_t *uc, _Unwind_Exception *exception_object) {
|
||||||
|
|
||||||
|
|
||||||
static _Unwind_Reason_Code
|
static _Unwind_Reason_Code
|
||||||
unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
|
unwind_phase2(unw_context_t *uc, unw_cursor_t *cursor, _Unwind_Exception *exception_object) {
|
||||||
unw_cursor_t cursor2;
|
unw_init_local(cursor, uc);
|
||||||
unw_init_local(&cursor2, uc);
|
|
||||||
|
|
||||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n",
|
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p)\n",
|
||||||
(void *)exception_object);
|
(void *)exception_object);
|
||||||
|
@ -139,7 +137,7 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
|
||||||
|
|
||||||
// Ask libuwind to get next frame (skip over first which is
|
// Ask libuwind to get next frame (skip over first which is
|
||||||
// _Unwind_RaiseException).
|
// _Unwind_RaiseException).
|
||||||
int stepResult = unw_step(&cursor2);
|
int stepResult = unw_step(cursor);
|
||||||
if (stepResult == 0) {
|
if (stepResult == 0) {
|
||||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
|
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_step() reached "
|
||||||
"bottom => _URC_END_OF_STACK\n",
|
"bottom => _URC_END_OF_STACK\n",
|
||||||
|
@ -155,8 +153,8 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
|
||||||
// Get info about this frame.
|
// Get info about this frame.
|
||||||
unw_word_t sp;
|
unw_word_t sp;
|
||||||
unw_proc_info_t frameInfo;
|
unw_proc_info_t frameInfo;
|
||||||
unw_get_reg(&cursor2, UNW_REG_SP, &sp);
|
unw_get_reg(cursor, UNW_REG_SP, &sp);
|
||||||
if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
|
if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
|
||||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
|
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): unw_get_proc_info "
|
||||||
"failed => _URC_FATAL_PHASE1_ERROR\n",
|
"failed => _URC_FATAL_PHASE1_ERROR\n",
|
||||||
(void *)exception_object);
|
(void *)exception_object);
|
||||||
|
@ -168,7 +166,7 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
|
||||||
char functionBuf[512];
|
char functionBuf[512];
|
||||||
const char *functionName = functionBuf;
|
const char *functionName = functionBuf;
|
||||||
unw_word_t offset;
|
unw_word_t offset;
|
||||||
if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
|
if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
|
||||||
&offset) != UNW_ESUCCESS) ||
|
&offset) != UNW_ESUCCESS) ||
|
||||||
(frameInfo.start_ip + offset > frameInfo.end_ip))
|
(frameInfo.start_ip + offset > frameInfo.end_ip))
|
||||||
functionName = ".anonymous.";
|
functionName = ".anonymous.";
|
||||||
|
@ -191,7 +189,7 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
|
||||||
}
|
}
|
||||||
_Unwind_Reason_Code personalityResult =
|
_Unwind_Reason_Code personalityResult =
|
||||||
(*p)(1, action, exception_object->exception_class, exception_object,
|
(*p)(1, action, exception_object->exception_class, exception_object,
|
||||||
(struct _Unwind_Context *)(&cursor2));
|
(struct _Unwind_Context *)(cursor));
|
||||||
switch (personalityResult) {
|
switch (personalityResult) {
|
||||||
case _URC_CONTINUE_UNWIND:
|
case _URC_CONTINUE_UNWIND:
|
||||||
// Continue unwinding
|
// Continue unwinding
|
||||||
|
@ -212,14 +210,14 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
|
||||||
// We may get control back if landing pad calls _Unwind_Resume().
|
// We may get control back if landing pad calls _Unwind_Resume().
|
||||||
if (_LIBUNWIND_TRACING_UNWINDING) {
|
if (_LIBUNWIND_TRACING_UNWINDING) {
|
||||||
unw_word_t pc;
|
unw_word_t pc;
|
||||||
unw_get_reg(&cursor2, UNW_REG_IP, &pc);
|
unw_get_reg(cursor, UNW_REG_IP, &pc);
|
||||||
unw_get_reg(&cursor2, UNW_REG_SP, &sp);
|
unw_get_reg(cursor, UNW_REG_SP, &sp);
|
||||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "
|
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2(ex_ojb=%p): re-entering "
|
||||||
"user code with ip=0x%" PRIx64
|
"user code with ip=0x%" PRIx64
|
||||||
", sp=0x%" PRIx64 "\n",
|
", sp=0x%" PRIx64 "\n",
|
||||||
(void *)exception_object, pc, sp);
|
(void *)exception_object, pc, sp);
|
||||||
}
|
}
|
||||||
unw_resume(&cursor2);
|
unw_resume(cursor);
|
||||||
// unw_resume() only returns if there was an error.
|
// unw_resume() only returns if there was an error.
|
||||||
return _URC_FATAL_PHASE2_ERROR;
|
return _URC_FATAL_PHASE2_ERROR;
|
||||||
default:
|
default:
|
||||||
|
@ -237,18 +235,17 @@ unwind_phase2(unw_context_t *uc, _Unwind_Exception *exception_object) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static _Unwind_Reason_Code
|
static _Unwind_Reason_Code
|
||||||
unwind_phase2_forced(unw_context_t *uc,
|
unwind_phase2_forced(unw_context_t *uc, unw_cursor_t *cursor,
|
||||||
_Unwind_Exception *exception_object,
|
_Unwind_Exception *exception_object,
|
||||||
_Unwind_Stop_Fn stop, void *stop_parameter) {
|
_Unwind_Stop_Fn stop, void *stop_parameter) {
|
||||||
unw_cursor_t cursor2;
|
unw_init_local(cursor, uc);
|
||||||
unw_init_local(&cursor2, uc);
|
|
||||||
|
|
||||||
// Walk each frame until we reach where search phase said to stop
|
// Walk each frame until we reach where search phase said to stop
|
||||||
while (unw_step(&cursor2) > 0) {
|
while (unw_step(cursor) > 0) {
|
||||||
|
|
||||||
// Update info about this frame.
|
// Update info about this frame.
|
||||||
unw_proc_info_t frameInfo;
|
unw_proc_info_t frameInfo;
|
||||||
if (unw_get_proc_info(&cursor2, &frameInfo) != UNW_ESUCCESS) {
|
if (unw_get_proc_info(cursor, &frameInfo) != UNW_ESUCCESS) {
|
||||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step "
|
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): unw_step "
|
||||||
"failed => _URC_END_OF_STACK\n",
|
"failed => _URC_END_OF_STACK\n",
|
||||||
(void *)exception_object);
|
(void *)exception_object);
|
||||||
|
@ -260,7 +257,7 @@ unwind_phase2_forced(unw_context_t *uc,
|
||||||
char functionBuf[512];
|
char functionBuf[512];
|
||||||
const char *functionName = functionBuf;
|
const char *functionName = functionBuf;
|
||||||
unw_word_t offset;
|
unw_word_t offset;
|
||||||
if ((unw_get_proc_name(&cursor2, functionBuf, sizeof(functionBuf),
|
if ((unw_get_proc_name(cursor, functionBuf, sizeof(functionBuf),
|
||||||
&offset) != UNW_ESUCCESS) ||
|
&offset) != UNW_ESUCCESS) ||
|
||||||
(frameInfo.start_ip + offset > frameInfo.end_ip))
|
(frameInfo.start_ip + offset > frameInfo.end_ip))
|
||||||
functionName = ".anonymous.";
|
functionName = ".anonymous.";
|
||||||
|
@ -276,7 +273,7 @@ unwind_phase2_forced(unw_context_t *uc,
|
||||||
(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
|
(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE);
|
||||||
_Unwind_Reason_Code stopResult =
|
_Unwind_Reason_Code stopResult =
|
||||||
(*stop)(1, action, exception_object->exception_class, exception_object,
|
(*stop)(1, action, exception_object->exception_class, exception_object,
|
||||||
(struct _Unwind_Context *)(&cursor2), stop_parameter);
|
(struct _Unwind_Context *)(cursor), stop_parameter);
|
||||||
_LIBUNWIND_TRACE_UNWINDING(
|
_LIBUNWIND_TRACE_UNWINDING(
|
||||||
"unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n",
|
"unwind_phase2_forced(ex_ojb=%p): stop function returned %d\n",
|
||||||
(void *)exception_object, stopResult);
|
(void *)exception_object, stopResult);
|
||||||
|
@ -296,7 +293,7 @@ unwind_phase2_forced(unw_context_t *uc,
|
||||||
(void *)exception_object, (void *)(uintptr_t)p);
|
(void *)exception_object, (void *)(uintptr_t)p);
|
||||||
_Unwind_Reason_Code personalityResult =
|
_Unwind_Reason_Code personalityResult =
|
||||||
(*p)(1, action, exception_object->exception_class, exception_object,
|
(*p)(1, action, exception_object->exception_class, exception_object,
|
||||||
(struct _Unwind_Context *)(&cursor2));
|
(struct _Unwind_Context *)(cursor));
|
||||||
switch (personalityResult) {
|
switch (personalityResult) {
|
||||||
case _URC_CONTINUE_UNWIND:
|
case _URC_CONTINUE_UNWIND:
|
||||||
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
|
_LIBUNWIND_TRACE_UNWINDING("unwind_phase2_forced(ex_ojb=%p): "
|
||||||
|
@ -311,7 +308,7 @@ unwind_phase2_forced(unw_context_t *uc,
|
||||||
"_URC_INSTALL_CONTEXT\n",
|
"_URC_INSTALL_CONTEXT\n",
|
||||||
(void *)exception_object);
|
(void *)exception_object);
|
||||||
// We may get control back if landing pad calls _Unwind_Resume().
|
// We may get control back if landing pad calls _Unwind_Resume().
|
||||||
unw_resume(&cursor2);
|
unw_resume(cursor);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
// Personality routine returned an unknown result code.
|
// Personality routine returned an unknown result code.
|
||||||
|
@ -332,7 +329,7 @@ unwind_phase2_forced(unw_context_t *uc,
|
||||||
_Unwind_Action lastAction =
|
_Unwind_Action lastAction =
|
||||||
(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
|
(_Unwind_Action)(_UA_FORCE_UNWIND | _UA_CLEANUP_PHASE | _UA_END_OF_STACK);
|
||||||
(*stop)(1, lastAction, exception_object->exception_class, exception_object,
|
(*stop)(1, lastAction, exception_object->exception_class, exception_object,
|
||||||
(struct _Unwind_Context *)(&cursor2), stop_parameter);
|
(struct _Unwind_Context *)(cursor), stop_parameter);
|
||||||
|
|
||||||
// Clean up phase did not resume at the frame that the search phase said it
|
// Clean up phase did not resume at the frame that the search phase said it
|
||||||
// would.
|
// would.
|
||||||
|
@ -346,6 +343,7 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) {
|
||||||
_LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)\n",
|
_LIBUNWIND_TRACE_API("_Unwind_RaiseException(ex_obj=%p)\n",
|
||||||
(void *)exception_object);
|
(void *)exception_object);
|
||||||
unw_context_t uc;
|
unw_context_t uc;
|
||||||
|
unw_cursor_t cursor;
|
||||||
unw_getcontext(&uc);
|
unw_getcontext(&uc);
|
||||||
|
|
||||||
// Mark that this is a non-forced unwind, so _Unwind_Resume()
|
// Mark that this is a non-forced unwind, so _Unwind_Resume()
|
||||||
|
@ -354,12 +352,12 @@ _Unwind_RaiseException(_Unwind_Exception *exception_object) {
|
||||||
exception_object->private_2 = 0;
|
exception_object->private_2 = 0;
|
||||||
|
|
||||||
// phase 1: the search phase
|
// phase 1: the search phase
|
||||||
_Unwind_Reason_Code phase1 = unwind_phase1(&uc, exception_object);
|
_Unwind_Reason_Code phase1 = unwind_phase1(&uc, &cursor, exception_object);
|
||||||
if (phase1 != _URC_NO_REASON)
|
if (phase1 != _URC_NO_REASON)
|
||||||
return phase1;
|
return phase1;
|
||||||
|
|
||||||
// phase 2: the clean up phase
|
// phase 2: the clean up phase
|
||||||
return unwind_phase2(&uc, exception_object);
|
return unwind_phase2(&uc, &cursor, exception_object);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -379,14 +377,15 @@ _LIBUNWIND_EXPORT void
|
||||||
_Unwind_Resume(_Unwind_Exception *exception_object) {
|
_Unwind_Resume(_Unwind_Exception *exception_object) {
|
||||||
_LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", (void *)exception_object);
|
_LIBUNWIND_TRACE_API("_Unwind_Resume(ex_obj=%p)\n", (void *)exception_object);
|
||||||
unw_context_t uc;
|
unw_context_t uc;
|
||||||
|
unw_cursor_t cursor;
|
||||||
unw_getcontext(&uc);
|
unw_getcontext(&uc);
|
||||||
|
|
||||||
if (exception_object->private_1 != 0)
|
if (exception_object->private_1 != 0)
|
||||||
unwind_phase2_forced(&uc, exception_object,
|
unwind_phase2_forced(&uc, &cursor, exception_object,
|
||||||
(_Unwind_Stop_Fn) exception_object->private_1,
|
(_Unwind_Stop_Fn) exception_object->private_1,
|
||||||
(void *)exception_object->private_2);
|
(void *)exception_object->private_2);
|
||||||
else
|
else
|
||||||
unwind_phase2(&uc, exception_object);
|
unwind_phase2(&uc, &cursor, exception_object);
|
||||||
|
|
||||||
// Clients assume _Unwind_Resume() does not return, so all we can do is abort.
|
// Clients assume _Unwind_Resume() does not return, so all we can do is abort.
|
||||||
_LIBUNWIND_ABORT("_Unwind_Resume() can't return");
|
_LIBUNWIND_ABORT("_Unwind_Resume() can't return");
|
||||||
|
@ -403,6 +402,7 @@ _Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
|
||||||
_LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)\n",
|
_LIBUNWIND_TRACE_API("_Unwind_ForcedUnwind(ex_obj=%p, stop=%p)\n",
|
||||||
(void *)exception_object, (void *)(uintptr_t)stop);
|
(void *)exception_object, (void *)(uintptr_t)stop);
|
||||||
unw_context_t uc;
|
unw_context_t uc;
|
||||||
|
unw_cursor_t cursor;
|
||||||
unw_getcontext(&uc);
|
unw_getcontext(&uc);
|
||||||
|
|
||||||
// Mark that this is a forced unwind, so _Unwind_Resume() can do
|
// Mark that this is a forced unwind, so _Unwind_Resume() can do
|
||||||
|
@ -411,7 +411,7 @@ _Unwind_ForcedUnwind(_Unwind_Exception *exception_object,
|
||||||
exception_object->private_2 = (uintptr_t) stop_parameter;
|
exception_object->private_2 = (uintptr_t) stop_parameter;
|
||||||
|
|
||||||
// do it
|
// do it
|
||||||
return unwind_phase2_forced(&uc, exception_object, stop, stop_parameter);
|
return unwind_phase2_forced(&uc, &cursor, exception_object, stop, stop_parameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue