libphobos: Select the appropriate exception handler in getClassInfo
This is analogous to __gdc_personality, which ignores in-flight exceptions that we haven't collided with yet. libphobos/ChangeLog: * libdruntime/gcc/deh.d (ExceptionHeader.getClassInfo): Move to... (getClassInfo): ...here as free function. Add lsda parameter. (scanLSDA): Pass lsda to actionTableLookup. (actionTableLookup): Add lsda parameter, pass to getClassInfo. (__gdc_personality): Remove currentCfa variable.
This commit is contained in:
parent
ed3ec7343b
commit
8088a33df5
|
@ -279,26 +279,6 @@ struct ExceptionHeader
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Look at the chain of inflight exceptions and pick the class type that'll
|
||||
* be looked for in catch clauses.
|
||||
*/
|
||||
static ClassInfo getClassInfo(_Unwind_Exception* unwindHeader) @nogc
|
||||
{
|
||||
ExceptionHeader* eh = toExceptionHeader(unwindHeader);
|
||||
// The first thrown Exception at the top of the stack takes precedence
|
||||
// over others that are inflight, unless an Error was thrown, in which
|
||||
// case, we search for error handlers instead.
|
||||
Throwable ehobject = eh.object;
|
||||
for (ExceptionHeader* ehn = eh.next; ehn; ehn = ehn.next)
|
||||
{
|
||||
Error e = cast(Error)ehobject;
|
||||
if (e is null || (cast(Error)ehn.object) !is null)
|
||||
ehobject = ehn.object;
|
||||
}
|
||||
return ehobject.classinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert from pointer to unwindHeader to pointer to ExceptionHeader
|
||||
* that it is embedded inside of.
|
||||
|
@ -666,7 +646,7 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti
|
|||
{
|
||||
// Otherwise we have a catch handler or exception specification.
|
||||
handler = actionTableLookup(actions, unwindHeader, actionRecord,
|
||||
exceptionClass, TTypeBase,
|
||||
lsda, exceptionClass, TTypeBase,
|
||||
TType, TTypeEncoding,
|
||||
saw_handler, saw_cleanup);
|
||||
}
|
||||
|
@ -694,7 +674,8 @@ _Unwind_Reason_Code scanLSDA(const(ubyte)* lsda, _Unwind_Exception_Class excepti
|
|||
* Look up and return the handler index of the classType in Action Table.
|
||||
*/
|
||||
int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader,
|
||||
const(ubyte)* actionRecord, _Unwind_Exception_Class exceptionClass,
|
||||
const(ubyte)* actionRecord, const(ubyte)* lsda,
|
||||
_Unwind_Exception_Class exceptionClass,
|
||||
_Unwind_Ptr TTypeBase, const(ubyte)* TType,
|
||||
ubyte TTypeEncoding,
|
||||
out bool saw_handler, out bool saw_cleanup)
|
||||
|
@ -702,7 +683,7 @@ int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader,
|
|||
ClassInfo thrownType;
|
||||
if (isGdcExceptionClass(exceptionClass))
|
||||
{
|
||||
thrownType = ExceptionHeader.getClassInfo(unwindHeader);
|
||||
thrownType = getClassInfo(unwindHeader, lsda);
|
||||
}
|
||||
|
||||
while (1)
|
||||
|
@ -778,6 +759,41 @@ int actionTableLookup(_Unwind_Action actions, _Unwind_Exception* unwindHeader,
|
|||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Look at the chain of inflight exceptions and pick the class type that'll
|
||||
* be looked for in catch clauses.
|
||||
*/
|
||||
ClassInfo getClassInfo(_Unwind_Exception* unwindHeader,
|
||||
const(ubyte)* currentLsd) @nogc
|
||||
{
|
||||
ExceptionHeader* eh = ExceptionHeader.toExceptionHeader(unwindHeader);
|
||||
// The first thrown Exception at the top of the stack takes precedence
|
||||
// over others that are inflight, unless an Error was thrown, in which
|
||||
// case, we search for error handlers instead.
|
||||
Throwable ehobject = eh.object;
|
||||
for (ExceptionHeader* ehn = eh.next; ehn; ehn = ehn.next)
|
||||
{
|
||||
const(ubyte)* nextLsd = void;
|
||||
_Unwind_Ptr nextLandingPad = void;
|
||||
_Unwind_Word nextCfa = void;
|
||||
int nextHandler = void;
|
||||
|
||||
ExceptionHeader.restore(&ehn.unwindHeader, nextHandler, nextLsd, nextLandingPad, nextCfa);
|
||||
|
||||
// Don't combine when the exceptions are from different functions.
|
||||
if (currentLsd != nextLsd)
|
||||
break;
|
||||
|
||||
Error e = cast(Error)ehobject;
|
||||
if (e is null || (cast(Error)ehn.object) !is null)
|
||||
{
|
||||
currentLsd = nextLsd;
|
||||
ehobject = ehn.object;
|
||||
}
|
||||
}
|
||||
return ehobject.classinfo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the personality function has found neither a cleanup or handler.
|
||||
* To support ARM EABI personality routines, that must also unwind the stack.
|
||||
|
@ -934,16 +950,15 @@ private _Unwind_Reason_Code __gdc_personality(_Unwind_Action actions,
|
|||
// current object onto the end of the prevous object.
|
||||
ExceptionHeader* eh = ExceptionHeader.toExceptionHeader(unwindHeader);
|
||||
auto currentLsd = lsda;
|
||||
auto currentCfa = cfa;
|
||||
bool bypassed = false;
|
||||
|
||||
while (eh.next)
|
||||
{
|
||||
ExceptionHeader* ehn = eh.next;
|
||||
const(ubyte)* nextLsd;
|
||||
_Unwind_Ptr nextLandingPad;
|
||||
_Unwind_Word nextCfa;
|
||||
int nextHandler;
|
||||
const(ubyte)* nextLsd = void;
|
||||
_Unwind_Ptr nextLandingPad = void;
|
||||
_Unwind_Word nextCfa = void;
|
||||
int nextHandler = void;
|
||||
|
||||
ExceptionHeader.restore(&ehn.unwindHeader, nextHandler, nextLsd, nextLandingPad, nextCfa);
|
||||
|
||||
|
@ -952,14 +967,13 @@ private _Unwind_Reason_Code __gdc_personality(_Unwind_Action actions,
|
|||
{
|
||||
// We found an Error, bypass the exception chain.
|
||||
currentLsd = nextLsd;
|
||||
currentCfa = nextCfa;
|
||||
eh = ehn;
|
||||
bypassed = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Don't combine when the exceptions are from different functions.
|
||||
if (currentLsd != nextLsd && currentCfa != nextCfa)
|
||||
if (currentLsd != nextLsd)
|
||||
break;
|
||||
|
||||
// Add our object onto the end of the existing chain.
|
||||
|
|
Loading…
Reference in New Issue