make a nothrow call a throwing function

monarch_dodra monarchdodra at gmail.com
Fri Feb 8 03:54:45 PST 2013


On Friday, 8 February 2013 at 09:33:19 UTC, Jonathan M Davis 
wrote:
> On Friday, February 08, 2013 09:30:41 Artur Skawina wrote:
>> On 02/08/13 01:33, Jonathan M Davis wrote:
>> > Hmmm. I wouldn't have thought that you could get the 
>> > function pointer at
>> > compiler time. Regardless, you lose any possibility of 
>> > inlining the
>> > function call, which is the main problem AFAIK, though I 
>> > don't know if
>> > they would have been an option in the case of dup anyway.
>> 
>> It doesn't affect inlining. (Obviously, that's compiler 
>> dependent, but
>> there's no reason why it should and indeed does not w/ gdc)
>
> How could it not affect inlining? You're using a pointer to a 
> function instead
> of the function itself, so it can't be inlined. Do you mean 
> that dup in
> particular doens't get inlined even when called directly? 
> That's quite
> possible, but in the general case, using a function pointer 
> rather than
> calling a function directly risks taking a small efficiency hit 
> due to the fact
> that the function can no longer be inlined.
>
> - Jonathan M Davis

Well, aren't you saying that because usually, function pointers 
aren't obtained at compile time?

In any case, I also tested it, and the disassemble seems to give 
the exact same code (inlined, as far as I can tell) for calling 
via function or function pointer:
http://d.godbolt.org/#{%22version%22%3A3%2C%22filterAsm%22%3A{%22labels%22%3Atrue%2C%22directives%22%3Atrue%2C%22commentOnly%22%3Atrue}%2C%22compilers%22%3A[{%22source%22%3A%22%2F%2F%20Type%20your%20code%20here%2C%20or%20load%20an%20example.\n\nint%20i%3B\n\nvoid%20foo%28%29\n{\n%20%20%2B%2Bi%3B\n}\n\nvoid%20bar%28%29\n{\n%20%20enum%20fun%20%3D%20cast%28void%20function%28%29%20nothrow%29%20%26foo%3B\n%20%20fun%28%29%3B\n%20%20%2F%2Ffoo%28%29%3B\n}\n\nvoid%20main%28%29\n{\n%20%20bar%28%29%3B\n%20%20assert%28i%20%3D%3D%201%29%3B\n}%22%2C%22compiler%22%3A%22%2Fusr%2Fbin%2Fgdc%22%2C%22options%22%3A%22-O2%20-march%3Dnative%20-inline%22}]}

http://d.godbolt.org/#{%22version%22%3A3%2C%22filterAsm%22%3A{%22labels%22%3Atrue%2C%22directives%22%3Atrue%2C%22commentOnly%22%3Atrue}%2C%22compilers%22%3A[{%22source%22%3A%22%2F%2F%20Type%20your%20code%20here%2C%20or%20load%20an%20example.\n\nint%20i%3B\n\nvoid%20foo%28%29\n{\n%20%20%2B%2Bi%3B\n}\n\nvoid%20bar%28%29\n{\n%20%20%2F%2Fenum%20fun%20%3D%20cast%28void%20function%28%29%20nothrow%29%20%26foo%3B\n%20%20%2F%2Ffun%28%29%3B\n%20%20foo%28%29%3B\n}\n\nvoid%20main%28%29\n{\n%20%20bar%28%29%3B\n%20%20assert%28i%20%3D%3D%201%29%3B\n}%22%2C%22compiler%22%3A%22%2Fusr%2Fbin%2Fgdc%22%2C%22options%22%3A%22-O2%20-march%3Dnative%20-inline%22}]}

And a third version, after adding the "nothrow" keyword. Slight 
changes, but I can't tell if they are "true" changes:
http://d.godbolt.org/#{%22version%22%3A3%2C%22filterAsm%22%3A{%22labels%22%3Atrue%2C%22directives%22%3Atrue%2C%22commentOnly%22%3Atrue}%2C%22compilers%22%3A[{%22source%22%3A%22%2F%2F%20Type%20your%20code%20here%2C%20or%20load%20an%20example.\n\nint%20i%3B\n\nvoid%20foo%28%29\n{\n%20%20%2B%2Bi%3B\n}\n\nvoid%20bar%28%29%20nothrow\n{\n%20%20enum%20fun%20%3D%20cast%28void%20function%28%29%20nothrow%29%20%26foo%3B\n%20%20fun%28%29%3B\n%20%20%2F%2Ffoo%28%29%3B\n}\n\nvoid%20main%28%29\n{\n%20%20bar%28%29%3B\n%20%20assert%28i%20%3D%3D%201%29%3B\n}%22%2C%22compiler%22%3A%22%2Fusr%2Fbin%2Fgdc%22%2C%22options%22%3A%22-O2%20-march%3Dnative%20-inline%22}]}

That said, when everything is said and done, the try catch 
version also generates the same inline code
http://d.godbolt.org/#{%22version%22%3A3%2C%22filterAsm%22%3A{%22labels%22%3Atrue%2C%22directives%22%3Atrue%2C%22commentOnly%22%3Atrue}%2C%22compilers%22%3A[{%22source%22%3A%22%2F%2F%20Type%20your%20code%20here%2C%20or%20load%20an%20example.\n\nint%20i%3B\n\nvoid%20foo%28%29\n{\n%20%20%2B%2Bi%3B\n}\n\nvoid%20bar%28%29%20nothrow\n{\n%20%20enum%20fun%20%3D%20cast%28void%20function%28%29%20nothrow%29%20%26foo%3B\n%20%20fun%28%29%3B\n%20%20%2F%2Ffoo%28%29%3B\n}\n\nvoid%20main%28%29\n{\n%20%20bar%28%29%3B\n%20%20assert%28i%20%3D%3D%201%29%3B\n}%22%2C%22compiler%22%3A%22%2Fusr%2Fbin%2Fgdc%22%2C%22options%22%3A%22-O2%20-march%3Dnative%20-inline%22}]}

But in this case, the compiler has access to the call, so it can 
*tell* exceptions won't get thrown.

Finally, in this last version, which calls dup, we can see the 
"cast" version takes less intructions that the try/catch version.

http://d.godbolt.org/#{%22version%22%3A3%2C%22filterAsm%22%3A{%22labels%22%3Atrue%2C%22directives%22%3Atrue%2C%22commentOnly%22%3Atrue}%2C%22compilers%22%3A[{%22source%22%3A%22%2F%2F%20Type%20your%20code%20here%2C%20or%20load%20an%20example.\n\nchar[]%20s%3B\n\nvoid%20foo%28%29\n{\n%20%20s%20%3D%20\%22hello\%22.dup%3B\n}\n\nversion%28all%29\n{\n%20%20void%20bar%28%29%20nothrow\n%20%20{\n%20%20%20%20enum%20fun%20%3D%20cast%28void%20function%28%29%20nothrow%29%20%26foo%3B\n%20%20%20%20fun%28%29%3B\n%20%20}\n}\nelse\n{\n%20%20void%20bar%28%29%20nothrow\n%20%20{\n%20%20%20%20try{\n%20%20%20%20%20%20foo%28%29%3B\n%20%20%20%20}catch{}\n%20%20}\n}\n\nvoid%20main%28%29\n{\n%20%20bar%28%29%3B\n%20%20assert%28s%20%3D%3D%20\%22hello\%22%29%3B\n}%22%2C%22compiler%22%3A%22%2Fusr%2Fbin%2Fgdc%22%2C%22options%22%3A%22-O2%20-march%3Dnative%20-inline%22}]}

But at the end of the day, it is a dangerous semantic for not 
that much gain.


More information about the Digitalmars-d-learn mailing list