www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - What does nothrow buy me?

reply Q. Schroll <qs.il.paperinik gmail.com> writes:
Obviously, nothrow documents the behavior of a function and is 
checked when the code is available to the compiler.

At first glance, one could assume a nothrow function can save the 
compiler from the need to generate exception handling stuff for a 
function. But since nothrow doesn't mean the function won't 
throw, but merely that it won't throw an Exception, what 
optimizations does nothrow enable?
Oct 26 2020
next sibling parent reply Tobias Pankrath <tobias+dlang pankrath.net> writes:
On Monday, 26 October 2020 at 18:47:41 UTC, Q. Schroll wrote:
 Obviously, nothrow documents the behavior of a function and is 
 checked when the code is available to the compiler.

 At first glance, one could assume a nothrow function can save 
 the compiler from the need to generate exception handling stuff 
 for a function. But since nothrow doesn't mean the function 
 won't throw, but merely that it won't throw an Exception, what 
 optimizations does nothrow enable?
Isn't proper unwinding of the stack only required for Exceptions?
Oct 26 2020
parent "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Mon, Oct 26, 2020 at 06:52:40PM +0000, Tobias Pankrath via Digitalmars-d
wrote:
 On Monday, 26 October 2020 at 18:47:41 UTC, Q. Schroll wrote:
 Obviously, nothrow documents the behavior of a function and is
 checked when the code is available to the compiler.
 
 At first glance, one could assume a nothrow function can save the
 compiler from the need to generate exception handling stuff for a
 function. But since nothrow doesn't mean the function won't throw,
 but merely that it won't throw an Exception, what optimizations does
 nothrow enable?
Isn't proper unwinding of the stack only required for Exceptions?
Yes. The compiler is permitted to skip stack unwinding code when throwing Errors. So yes, nothrow does win you some optimizations in some cases. That's one of the reasons user code generally shouldn't catch Errors -- because some unwinding code may have been skipped and your state may be inconsistent. Continuing normal execution after catching an Error is definitely a no-no. T -- Life is too short to run proprietary software. -- Bdale Garbee
Oct 26 2020
prev sibling next sibling parent Joseph Rushton Wakeling <joseph.wakeling webdrake.net> writes:
On Monday, 26 October 2020 at 18:47:41 UTC, Q. Schroll wrote:
 Obviously, nothrow documents the behavior of a function and is 
 checked when the code is available to the compiler.

 At first glance, one could assume a nothrow function can save 
 the compiler from the need to generate exception handling stuff 
 for a function. But since nothrow doesn't mean the function 
 won't throw, but merely that it won't throw an Exception, what 
 optimizations does nothrow enable?
Another use-case is when you have functions or methods that are designed to be run as the entry point of a separate thread or fiber task. An uncaught exception can cause the thread (or whole program) to hang, so having these functions guaranteed `nothrow` can be valuable. Of course, this is a bit of a workaround for the lack of decent exception handling for these cross-thread/fiber cases, but that's a bigger technical discussion...
Oct 27 2020
prev sibling next sibling parent reply Atila Neves <atila.neves gmail.com> writes:
On Monday, 26 October 2020 at 18:47:41 UTC, Q. Schroll wrote:
 Obviously, nothrow documents the behavior of a function and is 
 checked when the code is available to the compiler.

 At first glance, one could assume a nothrow function can save 
 the compiler from the need to generate exception handling stuff 
 for a function. But since nothrow doesn't mean the function 
 won't throw, but merely that it won't throw an Exception, what 
 optimizations does nothrow enable?
It's also extremely useful for when D code is being called from other languages. Throwing an exception from a function registered with Python is not a thing one wants to do, for instance.
Oct 27 2020
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Tue, Oct 27, 2020 at 06:10:45PM +0000, Atila Neves via Digitalmars-d wrote:
 On Monday, 26 October 2020 at 18:47:41 UTC, Q. Schroll wrote:
[...]
 At first glance, one could assume a nothrow function can save the
 compiler from the need to generate exception handling stuff for a
 function. But since nothrow doesn't mean the function won't throw,
 but merely that it won't throw an Exception, what optimizations does
 nothrow enable?
It's also extremely useful for when D code is being called from other languages. Throwing an exception from a function registered with Python is not a thing one wants to do, for instance.
But how does it help in the case of throwing an Error from a function registered with Python? Arguably, that's something you even *more* wouldn't want to do. T -- Why waste time reinventing the wheel, when you could be reinventing the engine? -- Damian Conway
Oct 27 2020
parent reply Atila Neves <atila.neves gmail.com> writes:
On Tuesday, 27 October 2020 at 18:21:23 UTC, H. S. Teoh wrote:
 On Tue, Oct 27, 2020 at 06:10:45PM +0000, Atila Neves via 
 Digitalmars-d wrote:
 On Monday, 26 October 2020 at 18:47:41 UTC, Q. Schroll wrote:
[...]
 At first glance, one could assume a nothrow function can 
 save the compiler from the need to generate exception 
 handling stuff for a function. But since nothrow doesn't 
 mean the function won't throw, but merely that it won't 
 throw an Exception, what optimizations does nothrow enable?
It's also extremely useful for when D code is being called from other languages. Throwing an exception from a function registered with Python is not a thing one wants to do, for instance.
But how does it help in the case of throwing an Error from a function registered with Python? Arguably, that's something you even *more* wouldn't want to do. T
Unfortunately, it doesn't. But errors are supposed to mean a non-recoverable problem anyway. I know it's not always like that in practice and that you don't want to crash someone's Excel sheet, but... making them nothrow makes me write a catch block, which makes me also catch errors.
Oct 28 2020
parent reply Steven Schveighoffer <schveiguy gmail.com> writes:
On 10/28/20 8:52 AM, Atila Neves wrote:
 On Tuesday, 27 October 2020 at 18:21:23 UTC, H. S. Teoh wrote:
 On Tue, Oct 27, 2020 at 06:10:45PM +0000, Atila Neves via 
 Digitalmars-d wrote:
 On Monday, 26 October 2020 at 18:47:41 UTC, Q. Schroll wrote:
[...]
 At first glance, one could assume a nothrow function can > save the 
compiler from the need to generate exception > handling stuff for a function. But since nothrow doesn't > mean the function won't throw, but merely that it won't > throw an Exception, what optimizations does nothrow enable? It's also extremely useful for when D code is being called from other languages. Throwing an exception from a function registered with Python is not a thing one wants to do, for instance.
But how does it help in the case of throwing an Error from a function registered with Python?  Arguably, that's something you even *more* wouldn't want to do. T
Unfortunately, it doesn't. But errors are supposed to mean a non-recoverable problem anyway. I know it's not always like that in practice and that you don't want to crash someone's Excel sheet, but... making them nothrow makes me write a catch block, which makes me also catch errors.
How does it make you write a catch block? If you only call nothrow functions, then your function is nothrow. If you assert in your nothrow function, it won't complain about catching. How does it make you write a catch block that catches Errors? Catching Exception is sufficient to shut up the compiler. -Steve
Oct 28 2020
parent Atila Neves <atila.neves gmail.com> writes:
On Wednesday, 28 October 2020 at 14:46:40 UTC, Steven 
Schveighoffer wrote:
 On 10/28/20 8:52 AM, Atila Neves wrote:
 On Tuesday, 27 October 2020 at 18:21:23 UTC, H. S. Teoh wrote:
 On Tue, Oct 27, 2020 at 06:10:45PM +0000, Atila Neves via 
 Digitalmars-d wrote:
 [...]
[...]
 [...]
But how does it help in the case of throwing an Error from a function registered with Python?  Arguably, that's something you even *more* wouldn't want to do. T
Unfortunately, it doesn't. But errors are supposed to mean a non-recoverable problem anyway. I know it's not always like that in practice and that you don't want to crash someone's Excel sheet, but... making them nothrow makes me write a catch block, which makes me also catch errors.
How does it make you write a catch block? If you only call nothrow functions, then your function is nothrow. If you assert in your nothrow function, it won't complain about catching. How does it make you write a catch block that catches Errors? Catching Exception is sufficient to shut up the compiler.
Because the code I call from the nothrow function isn't nothrow itself. It's true that it won't force me to catch errors, but I tend to in wrapper code nearly automatically. I realise now I didn't explain it well before.
Nov 07 2020
prev sibling next sibling parent Max Haughton <maxhaton gmail.com> writes:
On Monday, 26 October 2020 at 18:47:41 UTC, Q. Schroll wrote:
 Obviously, nothrow documents the behavior of a function and is 
 checked when the code is available to the compiler.

 At first glance, one could assume a nothrow function can save 
 the compiler from the need to generate exception handling stuff 
 for a function. But since nothrow doesn't mean the function 
 won't throw, but merely that it won't throw an Exception, what 
 optimizations does nothrow enable?
If the compiler doesn't have to think about recovery (i.e. errors should result in the program's termination) then the control flow analysis and register allocation can be improved. It's hard to measure because of the implementation of the function, but you can see it in the assembly sometimes.
Oct 27 2020
prev sibling parent reply random <frederick.mueller existiert.net> writes:
On Monday, 26 October 2020 at 18:47:41 UTC, Q. Schroll wrote:
 Obviously, nothrow documents the behavior of a function and is 
 checked when the code is available to the compiler.

 At first glance, one could assume a nothrow function can save 
 the compiler from the need to generate exception handling stuff 
 for a function. But since nothrow doesn't mean the function 
 won't throw, but merely that it won't throw an Exception, what 
 optimizations does nothrow enable?
This is a bit old but anyway. When you call functions which potentially throw, the compiler has to generate landing pads to handle exceptions if: 1. You have a catch block. 2. You have to call destructors. This does not directly impact runtime performance but it bloats the executable code (and it will probably impact runtime performance because of caching). I'm not a compiler expert, so take this with a grain of salt. I found this very helpful to understand how exceptions work: https://monoinfinito.wordpress.com/2013/04/23/c-exceptions-under-the-hood-14-multiple-landing-pads-the-teachings-of-the-guru/ I linked article 14 with landing pads but you should probably start at the beginning ;)
Nov 08 2020
parent reply "H. S. Teoh" <hsteoh quickfur.ath.cx> writes:
On Sun, Nov 08, 2020 at 10:00:28PM +0000, random via Digitalmars-d wrote:
 On Monday, 26 October 2020 at 18:47:41 UTC, Q. Schroll wrote:
[...]
 At first glance, one could assume a nothrow function can save the
 compiler from the need to generate exception handling stuff for a
 function. But since nothrow doesn't mean the function won't throw,
 but merely that it won't throw an Exception, what optimizations does
 nothrow enable?
The reason it's a bad idea to catch Throwable is because the compiler is *not* obligated to generate exception handling stuff in nothrow functions, even if a Throwable ends up going through that function.. [...]
 When you call functions which potentially throw, the compiler has to
 generate landing pads to handle exceptions if:
 
 1. You have a catch block.
 2. You have to call destructors.
 
 This does not directly impact runtime performance but it bloats the
 executable code (and it will probably impact runtime performance
 because of caching).
[...] Nothrow functions can have exception handling code elided. So in that case it will not incur the runtime cost. T -- Computers aren't intelligent; they only think they are.
Nov 08 2020
parent Steven Schveighoffer <schveiguy gmail.com> writes:
On 11/8/20 6:53 PM, H. S. Teoh wrote:
 On Sun, Nov 08, 2020 at 10:00:28PM +0000, random via Digitalmars-d wrote: >
[...]
 When you call functions which potentially throw, the compiler has to
 generate landing pads to handle exceptions if:

 1. You have a catch block.
 2. You have to call destructors.

 This does not directly impact runtime performance but it bloats the
 executable code (and it will probably impact runtime performance
 because of caching).
[...] Nothrow functions can have exception handling code elided. So in that case it will not incur the runtime cost.
I think this is slightly incorrect. If you throw an Error inside a nothrow function, it will properly run destructors, and you can catch the Error inside the function. I would say as well, if you catch an Error or Throwable resulting from a call to a nothrow function, it should always generate that handling code. But I think the spec is written such that it might elide the exception handling code (I don't see this ever happening). The main case is when you *don't* catch Error or Exception when calling a nothrow function, and your code does cleanup via RAII, the cleanup will not happen. -Steve
Nov 09 2020