Overloading Lazy Vs. Non-Lazy
Lars T. Kyllingstad
public at kyllingen.NOSPAMnet
Fri Aug 13 06:51:05 PDT 2010
On Fri, 13 Aug 2010 09:21:00 -0400, Steven Schveighoffer wrote:
> On Thu, 12 Aug 2010 16:47:40 -0400, dsimcha <dsimcha at yahoo.com> wrote:
>
>> == Quote from Don (nospam at nospam.com)'s article
>>> Steven Schveighoffer wrote:
>>> > On Thu, 12 Aug 2010 02:00:00 -0400, Brad Roberts
>>> <braddr at puremagic.com>
>>> > wrote:
>>> >
>>> >> On 8/11/2010 6:19 AM, dsimcha wrote:
>>> >>> An issue that's come up here several times before is that
>>> >>> enforce() effectively disables inlining of the function it's used
>>> >>> in. From reading some
>>> >>> disassemblies, the reason seems to be because of all the ASM code
>>> that's
>>> >>> required for lazy parameters. I wonder if either of the following
>>> is
>>> >>> feasible:
>>> >>>
>>> >>> 1. When a function takes a lazy parameter, the compiler
>>> automatically
>>> >>> generates two versions under the hood: One that actually takes a
>>> >>> non-lazy
>>> >>> parameter and is used when the value is known at compile time and
>>> >>> another that
>>> >>> works like current lazy functions. The only problem here is that
>>> >>> this might
>>> >>> create issues when using function pointers/delegates.
>>> >>>
>>> >>> 2. Allow overloading of lazy and non-lazy functions, with the
>>> >>> rule that the
>>> >>> lazy version gets called whenever the value must be computed at
>>> >>> runtime and
>>> >>> the non-lazy version gets called if the value is statically known
>>> and
>>> >>> thus
>>> >>> there's no evaluation to speak of.
>>> >>
>>> >> It's the throw that blocks inlining right now. Lazy might also
>>> >> disable inlining
>>> >> too, I haven't looked for that case. Either way, that's purely a
>>> >> quality of
>>> >> implementation issue. I don't think it'd be a good idea to bend
>>> >> the library all
>>> >> that much to work around that kind of limitation. It's something
>>> that
>>> >> will get
>>> >> better as time permits.
>>> >
>>> > Well, there's something to be said about preventing the bloated
>>> > generation of code that accompanies lazy.
>>> Inlining a lazy function that only returns a compile-time constant
>>> could inline very nicely. The delegate would disappear completely.
>>
>> Just to clarify: enforce() calls a function called bailOut() if
>> necessary that
>> actually does the throwing. This of course is not inlined w.r.t.
>> enforce().
>> However, the lazy parameter also prevents inlining of enforce() itself
>> and
>> generates a ton of code at the ASM level.
>>
>> Don is right, though. In principle, when a statically known delegate D
>> (lazy is
>> just syntactic sugar for delegates) that returns a statically known
>> constant is
>> passed to a statically known function F, D can be inlined w.r.t. F and
>> F can be
>> inlined w.r.t. its caller.
>>
>> The problem, though, is that F needs to be inlined first so that the
>> compiler can
>> optimize F w.r.t. the parameters passed to it from a specific caller.
>> However, F
>> won't look worth inlining until the compiler realizes that it can
>> inline D w.r.t.
>> F. Therefore, the compiler would need an inliner that uses something
>> more
>> sophisticated than a simple greedy algorithm to discover this
>> optimization
>> opportunity.
>
> In principle, we should be able to inline enforce. Great. When is this
> going to happen? Well, we can inline all calls to enforce *today* if we
> simply remove the lazy attribute, and apply a lazy version in a small
> number of places. I think it's worth doing it, because the inlining
> fixes are not going to happen for a while. It's easy to switch it back
> once we can inline trivial lazy parameters.
>
> -Steve
I agree. A quick grep of the phobos sources shows that in the vast
majority of cases, enforce() gets called either without a message or just
with a string literal.
-Lars
More information about the Digitalmars-d
mailing list