Issue 3490 - DMD Never Inlines Functions that Could Throw
Summary: DMD Never Inlines Functions that Could Throw
Status: RESOLVED FIXED
Alias: None
Product: D
Classification: Unclassified
Component: dmd (show other issues)
Version: D2
Hardware: All All
: P2 normal
Assignee: No Owner
URL:
Keywords: bounty, performance
Depends on:
Blocks:
 
Reported: 2009-11-09 06:26 UTC by David Simcha
Modified: 2014-03-18 13:21 UTC (History)
7 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description David Simcha 2009-11-09 06:26:18 UTC
Here's an absurdly simple test program.  enforceStuff() does not get inlined, as the disassembly below shows.  I couldn't find anything about exceptions in inline.c, but if this doesn't get inlined, I assume nothing that could throw ever does.  

This severely affects the performance of std.range, since Andrei uses enforce() all over the place, causing lots of stuff not to be inlined.  For example, I read disassemblies involving std.range.Take and it seems like Take.popFront() and Take.front() are never inlined.

void main() {
    enforceStuff(1);
}

void enforceStuff(uint num) {  // Not inlined.
   if(num == 0) {
       throw new Exception("");
   }
}

Disassembly of main():

__Dmain PROC NEAR
;  COMDEF __Dmain
        push    eax                                     ; 0000 _ 50
        mov     eax, 1                                  ; 0001 _ B8, 00000001
        call    _D5test812enforceStuffFkZv              ; 0006 _ E8, 00000000(rel)
        xor     eax, eax                                ; 000B _ 31. C0
        pop     ecx                                     ; 000D _ 59
        ret                                             ; 000E _ C3
__Dmain ENDP
Comment 1 Ary Borenszweig 2009-11-09 06:32:37 UTC
Here's why:

int Statement::inlineCost(InlineCostState *ics)
{
    return COST_MAX;		// default is we can't inline it
}

and ThrowStatement never overrides it.
Comment 2 Leandro Lucarella 2010-07-08 06:54:15 UTC
I'm marking this a a blocker of bug 859 so there is a single bug to track all
the inlining issues. Please do the same if you open more bugs associated to
inlining, or post them directly in bug 859.
Comment 3 Brad Roberts 2010-07-08 22:47:07 UTC
undoing false dependency
Comment 4 Leandro Lucarella 2010-07-09 06:14:20 UTC
(In reply to comment #3)
> undoing false dependency

Can you elaborate a little on why having bug 859 as a tracker of all missing inline oportunities is a bad thing?

Thanks
Comment 5 Nick Sabalausky 2014-03-12 07:54:51 UTC
While DMD still doesn't inline functions that (directly) contain a "throw" statement, the original poster's issues with std.range and emplace have largely been addressed several versions ago (at least as far back as 2.060, maybe more):

- Many uses of enforce in std.range, such as the ones in Take, have been replaced by asserts.

- Functions like Take.popFront() and Take.front() are inlined (likely due to the switch to assert).

- Some of the enforce functions (except for errnoEnforce and the enforce that takes a lazy Throwable as a param) are inlineable because they don't use "throw" directly. Instead, they call the private helper "bailOut" which does the actual throwing. The "bailOut" function isn't inlineable, but that shouldn't be a problem since it only gets called when the condition fails.
Comment 6 Nick Sabalausky 2014-03-12 08:30:21 UTC
https://github.com/D-Programming-Language/dmd/pull/3378
Comment 7 github-bugzilla 2014-03-13 06:37:13 UTC
Commits pushed to master at https://github.com/D-Programming-Language/dmd

https://github.com/D-Programming-Language/dmd/commit/8f3557c77e524a2b00e4d5c26265041e09318a04
fix issue 3490 - DMD Never Inlines Functions that Could Throw

https://github.com/D-Programming-Language/dmd/commit/99b9b04733ba2aa557e09fecdb82650cc56864bd
Merge pull request #3378 from Abscissa/fix3490

fix issue 3490 - DMD Never Inlines Functions that Could Throw
Comment 8 Andrei Alexandrescu 2014-03-18 12:50:45 UTC
I assume this is enough to pay the bounty. @WalterBright?
Comment 9 Walter Bright 2014-03-18 13:18:41 UTC
(In reply to comment #8)
> I assume this is enough to pay the bounty. @WalterBright?

yes