tech-kern archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: Nested functions [was Re: valgrind]



> [...] said, moving to fat function pointers on machines that don't
> already use them is a real ABI change and therefore a big deal; but
> it could be done if there were a compelling argument to justify going
> through all the associated dark rituals.

Or as a private experiment, in which compatibility with other ABIs is
irrelevant.  That's what I would, putatively, be doing.

> The conclusion over the past ~25 years has been that there isn't;
> qsort and things like it work "well enough" and real uses for
> closures that really motivate the feature come up rarely enough that
> it doesn't happen.

Nested functions are not closures, or at least not what I know as
closures.  A nested function pointer (conceptually) goes invalid as
soon as anything it refers to goes out of scope, or at the latest as
soon as its smallest enclosing block exits (or possibly when its
smallest enclosing function returns).  The thing I know as a closure
would preserve the referred-to objects as long as the closure is
potentially callable.  This requires more reference tracking than C
typically makes possible.

> There is no solution based on trampolines that'll pass security (or
> at least security-theatre) muster.  Unless maybe by doing something
> that's horrifying in other ways.

The safest alternative that comes to my mind is to have two stacks, one
for trampolines and one for everything else.  But that requires
something much like two stack pointers, including assist from the
setjmp/longjmp implementation and, if applicable, threads.

> (For example: you could declare a static limit on how many instances
> of the closure you'll ever produce, make a global array to stuff the
> data pointer in, and statically generate N trampoline entry points
> that read from that array and call the primary function.  But there
> are many other ways in which this is horrible.)

But there are use cases for which it is not a stupid implementation;
for example, if no containing function is ever called recursively or
reentrantly, and of course if the limit is high enough, it is obviously
safe and quite possibly one of the fastest techniques available (since
"creating" a trampoline can be made very fast, not needing even D$
pushes and I$ flushes).  But, under those conditions, the autos in the
enclosing function can be promoted to static storage duration and the
nested function turned, essentially, into an ordinary function.

Are the cases where the compiler can prove that's true a big enough
fraction of the use cases to be useful?  I don't know, not even for my
own code.  I _think_ one of the heavier uses of the technique - my ssh
implementation - could work just fine with this approach, but I haven't
looked at every nested function closely enough to be sure.  (It needs
more than nested functions, though; one of its uses of nested functions
is to combine them with what gcc calls nonlocal gotos as a throw-out
mechanism better in many respects than setjmp/longjmp.)

/~\ The ASCII				  Mouse
\ / Ribbon Campaign
 X  Against HTML		mouse%rodents-montreal.org@localhost
/ \ Email!	     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B


Home | Main Index | Thread Index | Old Index