On Monday 17 December 2007, Jeff Moore wrote:
> On Dec 17, 2007, at 10:30 PM, Larry Garfield wrote:
> > I'm assuming that making the function above GC-able would be a
> > herculean task
> > at this point, based on previous comments, but I do not actually
> > know myself.
>
> Hi Larry,
>
> Let me use a different example than yours.
>
> function getAdder($x) {
>    return function ($y) {
>      lexical $x;
>      return $x + $y;
>    }
> }
>
> $plusFive = getAdder(5);
> $plusTen = getAdder(10);
>
> echo $plusFive(4); // 9
> echo $plusTen(7); // 17
>
> If the closure definition (and thus getAddr) returns a string
> representing an anonymous function name, then there is no where to
> hold the enclosing variable $x and no way to know when to free it.
> Notice that in this example, we have two different enclosing contexts,
> one where $x is 5 and one where $x is 10.
>
> If we introduce a new variable type, a new kind of zval, then
> internally, that variable can hold:
> 1) A reference to the local variables of getAddr.  (here $x)
> 2) A reference to $this if the closure is declared in a method
> 3) A reference to the opcodes of the compiled anonymous function.
>
> The opcodes for the closure would be compiled and squirreled away when
> the script is compiled.
>
> When getAddr is executed, a zval would be created that holds the
> reference to the enclosing locals and a reference to the proper
> opcodes.  Note that $plusFive and $plusTen would hold two different
> zvals, one for each invocation of getAddr, but that both would refer
> to the same opcodes structure.

So the compiled code is then single-sourced, much the same way that a class is 
single sourced and objects simply contain references to it.  The Objects can 
be GCed whenever, but the class opcodes remain for the life of the script.  

> When a codeblock zval is executed, such as at $plusFive(4), the
> enclosing context can be passed to the anonymous function function to
> make the lexical $x statement bind to the proper variable.
>
> When the zval in $plusFive reaches zero references, it can
> subsequently free its references to the local variables of getAddr.
>
> As far as I can see, no herculean garbage collection or reference
> counting is required.

By separating the opcodes from the zval, you've side-stepped the need to do 
so.  That means declaring a dynamic function (or lambda, or whatever we end 
up calling this thing) inside a loop is no more expensive than instantiating 
a class inside of a loop.  I'm glad you know more about engine internals than 
I do. :-)

> Adding a new kind of zval?  Perhaps that's Herculean.  I don't know.

It sounds (to the layman) like it could/should be modeled on the way 
objects/classes are implemented in PHP 5, as "fancy references".  (I believe 
Sara Golemon had an article a while back that explained them that way.  Sara, 
my apologies if I am misquoting you.)  Whether that's a "new type of zval" or 
not I do not know.

> I hope I've gotten my zval terminology right.

Better than mine would be. :-)  And it seems to solve most of the 
implementation concerns that were raised earlier, at least at an abstract 
level.  The catch would be that I don't know the performance impact of making 
the compiler find and define these sorts of functions.  Can someone with more 
engine experience weigh in if the above is workable?

-- 
Larry Garfield                  AIM: LOLG42
[EMAIL PROTECTED]               ICQ: 6817012

"If nature has made any one thing less susceptible than all others of 
exclusive property, it is the action of the thinking power called an idea, 
which an individual may exclusively possess as long as he keeps it to 
himself; but the moment it is divulged, it forces itself into the possession 
of every one, and the receiver cannot dispossess himself of it."  -- Thomas 
Jefferson

-- 
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to