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.
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.
Adding a new kind of zval? Perhaps that's Herculean. I don't know.
I hope I've gotten my zval terminology right.
Best Regards,
Jeff
--
PHP Internals - PHP Runtime Development Mailing List
To unsubscribe, visit: http://www.php.net/unsub.php