[libc++abi] Simplify __gxx_personality_v0

In three cases we call `scan_eh_tab` to parse LSDA:

* `actions & _UA_SEARCH_PHASE`
* `actions & _UA_CLEANUP_PHASE && actions & _UA_HANDLER_FRAME && !native_exception`
* `actions & _UA_CLEANUP_PHASE && !(actions & _UA_HANDLER_FRAME)`

Check
`actions & _UA_CLEANUP_PHASE && actions & _UA_HANDLER_FRAME && native_exception` first,
then we can move three `scan_eh_tab` into one place.

Another simplification is that we can check whether the result of `scan_eh_tab`
is `_UA_CONTINUE_UNWIND` or `_UA_FATAL_PHASE1_ERROR` first. Then many of the
original checks will be dead and can thus be deleted.

Reviewed By: #libc_abi, ldionne

Differential Revision: https://reviews.llvm.org/D93186
This commit is contained in:
Fangrui Song 2021-01-07 14:05:46 -08:00
parent 63b42a0514
commit 85f86e8a3c
1 changed files with 39 additions and 66 deletions

View File

@ -962,78 +962,51 @@ __gxx_personality_v0
bool native_exception = (exceptionClass & get_vendor_and_language) ==
(kOurExceptionClass & get_vendor_and_language);
scan_results results;
// Process a catch handler for a native exception first.
if (actions == (_UA_CLEANUP_PHASE | _UA_HANDLER_FRAME) &&
native_exception) {
// Reload the results from the phase 1 cache.
__cxa_exception* exception_header =
(__cxa_exception*)(unwind_exception + 1) - 1;
results.ttypeIndex = exception_header->handlerSwitchValue;
results.actionRecord = exception_header->actionRecord;
results.languageSpecificData = exception_header->languageSpecificData;
results.landingPad =
reinterpret_cast<uintptr_t>(exception_header->catchTemp);
results.adjustedPtr = exception_header->adjustedPtr;
// Jump to the handler.
set_registers(unwind_exception, context, results);
return _URC_INSTALL_CONTEXT;
}
// In other cases we need to scan LSDA.
scan_eh_tab(results, actions, native_exception, unwind_exception, context);
if (results.reason == _URC_CONTINUE_UNWIND ||
results.reason == _URC_FATAL_PHASE1_ERROR)
return results.reason;
if (actions & _UA_SEARCH_PHASE)
{
// Phase 1 search: All we're looking for in phase 1 is a handler that
// halts unwinding
scan_eh_tab(results, actions, native_exception, unwind_exception, context);
if (results.reason == _URC_HANDLER_FOUND)
{
// Found one. Can we cache the results somewhere to optimize phase 2?
if (native_exception)
{
__cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
exception_header->handlerSwitchValue = static_cast<int>(results.ttypeIndex);
exception_header->actionRecord = results.actionRecord;
exception_header->languageSpecificData = results.languageSpecificData;
exception_header->catchTemp = reinterpret_cast<void*>(results.landingPad);
exception_header->adjustedPtr = results.adjustedPtr;
}
return _URC_HANDLER_FOUND;
assert(results.reason == _URC_HANDLER_FOUND);
if (native_exception) {
// For a native exception, cache the LSDA result.
__cxa_exception* exc = (__cxa_exception*)(unwind_exception + 1) - 1;
exc->handlerSwitchValue = static_cast<int>(results.ttypeIndex);
exc->actionRecord = results.actionRecord;
exc->languageSpecificData = results.languageSpecificData;
exc->catchTemp = reinterpret_cast<void*>(results.landingPad);
exc->adjustedPtr = results.adjustedPtr;
}
// Did not find a catching-handler. Return the results of the scan
// (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE1_ERROR
// if we were called improperly).
return results.reason;
return _URC_HANDLER_FOUND;
}
if (actions & _UA_CLEANUP_PHASE)
{
// Phase 2 search:
// Did we find a catching handler in phase 1?
if (actions & _UA_HANDLER_FRAME)
{
// Yes, phase 1 said we have a catching handler here.
// Did we cache the results of the scan?
if (native_exception)
{
// Yes, reload the results from the cache.
__cxa_exception* exception_header = (__cxa_exception*)(unwind_exception+1) - 1;
results.ttypeIndex = exception_header->handlerSwitchValue;
results.actionRecord = exception_header->actionRecord;
results.languageSpecificData = exception_header->languageSpecificData;
results.landingPad = reinterpret_cast<uintptr_t>(exception_header->catchTemp);
results.adjustedPtr = exception_header->adjustedPtr;
}
else
{
// No, do the scan again to reload the results.
scan_eh_tab(results, actions, native_exception, unwind_exception, context);
// Phase 1 told us we would find a handler. Now in Phase 2 we
// didn't find a handler. The eh table should not be changing!
if (results.reason != _URC_HANDLER_FOUND)
call_terminate(native_exception, unwind_exception);
}
// Jump to the handler
set_registers(unwind_exception, context, results);
return _URC_INSTALL_CONTEXT;
}
// Either we didn't do a phase 1 search (due to forced unwinding), or
// phase 1 reported no catching-handlers.
// Search for a (non-catching) cleanup
scan_eh_tab(results, actions, native_exception, unwind_exception, context);
if (results.reason == _URC_HANDLER_FOUND)
{
// Found a non-catching handler. Jump to it:
set_registers(unwind_exception, context, results);
return _URC_INSTALL_CONTEXT;
}
// Did not find a cleanup. Return the results of the scan
// (normally _URC_CONTINUE_UNWIND, but could have been _URC_FATAL_PHASE2_ERROR
// if we were called improperly).
return results.reason;
}
// We were called improperly: neither a phase 1 or phase 2 search
return _URC_FATAL_PHASE1_ERROR;
assert(actions & _UA_CLEANUP_PHASE);
assert(results.reason == _URC_HANDLER_FOUND);
set_registers(unwind_exception, context, results);
return _URC_INSTALL_CONTEXT;
}
#if defined(__SEH__) && !defined(__USING_SJLJ_EXCEPTIONS__)