Re: Comments on non-unique naming convention for closures

From: Date: Sat, 30 Nov 2013 09:34:28 +0000
Subject: Re: Comments on non-unique naming convention for closures
References: 1 2 3 4 5  Groups: php.internals 
Request: Send a blank email to internals+get-70453@lists.php.net to get a copy of this message
On 30/11/13 03:46, Stas Malyshev wrote:
Having discussed the options with Dmitry and another contributor off PHP Internals list, we have decided to base the generated <internal> function name on a hash of the source content between the text pointers
Wouldn't that imply that two closures with the same code would be identified as the same closure? If so, I'm not sure this is a correct approach - one can definitely have two different closures (with different states, different bindings, etc.) having same source text. Or am I missing something here? Stas, nope, not quite. The compiler generates a zend_function oparray for each closure that it compiles at *compile time*, and stores this in the execution function table under a mangled name. It also generates a ZEND_DECLARE_LAMBDA_FUNCTION <mangled name> instruction at the appropriate place in the oparray referencing the closure. When *executed*, this acts as the CTOR for the closure object and this deep copies the dummy mangled zend_function entry into the closure object. It is this entry within the closure object that is in fact executed when the closure is invoked. The use bindings take place as part of the CTOR. This copy is then GCed at the closure DTOR.
So the CTOR will occur each time the ZEND_DECLARE_LAMBDA_FUNCTION is executed, and the DTORs occur in line with normal PHP scoping / GC rules. This bug is that the current mangling rules mean that under some perverse (but possible in real life) conditions, two different source codes could generate the same mangled name so the second entry would incorrectly override the first, resulting in the closure CTORs binding the wrong function, so we need a unique mangling algo. The mangled zend_function entry is never executed; only used as a copy template. A simple sequence count of the number of closures compiled this request would be fine to separate closure declarations and guarantee uniqueness -- except when OPcaching is involved, so some context dependent hash i needed. This is really a separate thread, but in order to allow opcode caching, the PHP compiler *must* generate the same oparray for a given source sequence, so in fact even if the same function (...) {...} text sequence occured multiple times in the same source file, then the oparrays would be identical anyway, and using the same mangled zend_function entry is fine. However, if the 1/2^64 (or thereabouts) chance of a false collision is unacceptable, we could always embed the closure compile count in the name as well, or the microsecond compile time. Hope this explanation helps :-) Terry

« previous php.internals (#70453) next »