digitalmars.D - Idea: norecover blocks
- dsimcha (27/27) Jan 17 2009 I've been thinking about exception handling in D as it relates to nothro...
- Walter Bright (2/2) Jan 17 2009 Throwing unrecoverable exceptions still allows a function to be marked
- dsimcha (23/25) Jan 17 2009 This misses the point. The idea is, you have a function A that calls a ...
- Walter Bright (12/39) Jan 17 2009 void A() nothrow {
- dsimcha (6/17) Jan 17 2009 The problem is that, at least according to my testing, this has signific...
- Walter Bright (2/7) Jan 17 2009 Try casting B to be a nothrow function.
I've been thinking about exception handling in D as it relates to nothrow. The obvious benefit of nothrow is compiler-enforced documentation, but a second benefit is performance with scope statements and RAII. If the compiler knows some function call can't throw, it can generate better code. In some cases, it's possible to call a function that throws an exception, but because of the nature of the client code, this exception would be deemed unrecoverable anyhow, and the program should simply die. However, the fact that these lower-level functions still throw prevents the higher level functions from being marked nothrow, hurting performance. Catching the exception is no help, because the try-catch block has its own performance cost. It would be nice if these function calls could be marked as norecover, thus preventing the compiler from generating any finally blocks for scope statements and RAII, and allowing the higher level functions to be marked as nothrow. For example: void foo() nothrow { auto scratch = new uint[1_000]; // May throw outOfMemoryError. // Use scratch. } The above wouldn't work because new throws an outOfMemoryError, but: void foo() nothrow { norecover auto scratch = new uint[1_000]; // Use scratch. } would work. I honestly don't know much about how exception handling is implemented at the ASM level, but I do know that scope statements and RAII are in practice performance killers in the presence of throwing code. Does this sound like a reasonable strategy for mitigating this performance drain?
Jan 17 2009
Throwing unrecoverable exceptions still allows a function to be marked as nothrow.
Jan 17 2009
== Quote from Walter Bright (newshound1 digitalmars.com)'s articleThrowing unrecoverable exceptions still allows a function to be marked as nothrow.This misses the point. The idea is, you have a function A that calls a library function B. B throws an exception that is considered recoverable by whoever wrote B. However, within A, you want to treat the exception thrown by B as unrecoverable. void A() nothrow { B(); } void B() { if(someCondition) { throw new bException("Some Error"); } // Do stuff. } You could catch the bException in A, but that would require enough of a performance hit that any gain from having A be nothrow would likely be lost (at least in the cases I've tested). The idea is that you would declare something like: void A() nothrow { norecover { B(); } } and all exceptions thrown by code inside the norecover block would be treated as unrecoverable, even if they would normally be considered recoverable.
Jan 17 2009
dsimcha wrote:This misses the point. The idea is, you have a function A that calls a library function B. B throws an exception that is considered recoverable by whoever wrote B. However, within A, you want to treat the exception thrown by B as unrecoverable. void A() nothrow { B(); } void B() { if(someCondition) { throw new bException("Some Error"); } // Do stuff. } You could catch the bException in A, but that would require enough of a performance hit that any gain from having A be nothrow would likely be lost (at least in the cases I've tested). The idea is that you would declare something like: void A() nothrow { norecover { B(); } } and all exceptions thrown by code inside the norecover block would be treated as unrecoverable, even if they would normally be considered recoverable.void A() nothrow { try { B(); } catch (Object o) { abort(); } } will do it.
Jan 17 2009
== Quote from Walter Bright (newshound1 digitalmars.com)'s articlevoid A() nothrow { try { B(); } catch (Object o) { abort(); } } will do it.The problem is that, at least according to my testing, this has significant overhead, to the point where you may as well just not make A nothrow, from a performance perspective. Basically, what I'm asking is, if the compiler knew that you weren't going to try to recover from a bException, could it do better than catch { abort(); }?
Jan 17 2009
dsimcha wrote:The problem is that, at least according to my testing, this has significant overhead, to the point where you may as well just not make A nothrow, from a performance perspective. Basically, what I'm asking is, if the compiler knew that you weren't going to try to recover from a bException, could it do better than catch { abort(); }?Try casting B to be a nothrow function.
Jan 17 2009