diff --git a/libphobos/libdruntime/gcc/deh.d b/libphobos/libdruntime/gcc/deh.d index a7eb37cfd9e..ba57fed38dc 100644 --- a/libphobos/libdruntime/gcc/deh.d +++ b/libphobos/libdruntime/gcc/deh.d @@ -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.