{"push_id":1098386067,"size":1,"distinct_size":1,"ref":"refs/heads/bind_static","head":"8f54c688c2cff654cf54bd79da764f448297d190","before":"dd512e4f902a425200209cd82bafe8c6d0de2d77","commits":[{"sha":"8f54c688c2cff654cf54bd79da764f448297d190","author":{"email":"4b2e18320c056ace942ee736b14cf905fac6af77@hotmail.com","name":"Bob Weinand"},"message":"Make static binding consistent and faster\n\nProviously cases like\nclass A { function foo() { static $a = 0; print $a++; } } (new A)->foo(); class B extends A {} (new B)->foo(); (new A)->foo(); (new B)->foo();\nexposed different behavior depending on whether class B is early bound (add a surrounding if (1) { } statement) or the first call to the foo method happens after binding.\nThe reference was only installed at the first BIND_STATIC opcode, causing different behavior depending on whether statics were duplicated before or after BIND_STATIC.\n\nThis patch fixes that by always creating a reference, right at compile time.\nThe semantics are now that each function (with the exception of trait functions, which are expected to be literally copy-pasted) shares its statics with all instances of it.\n\nThe case above will now print 0123 in every case instead of 0011 or 0123 depending on binding times.\n\nAlso with Closures:\nfunction getClosure() { return function () { static $a = 0; print $a++; }; } $f = getClosure(); $f(); $g = getClosure(); $f(); $g(); $f();\nwill now print 0123 instead of 0102.\n\nThis makes behavior much more consistent.\n\nTo achieve this, it was needed to move to a zval+name array (instead of HashTable) for statics (as we cannot have mutable references in an immutable array in opcache).\nHence statics need to be copied directly into process memory upon each request instead of residing in shared memory. (That also removes the need for some run-time duplications.)\nTo support that, the patch adds a way to relocate pointers inside copied memory and arena allocates the copied parts.\n\nAdditionally, the better locality (statics now are typically closer to the op_array - side effect of arena allocation), one less fetch inside ZEND_BIND_STATIC (hello stalling cycles waiting for memory...) and much faster Closure binding account for (up to) 1.5% run-time improvement on real world applications (typical modern applications are relatively heavy on Closures nowadays).","distinct":true,"url":"https://api.github.com/repos/bwoebi/php-src/commits/8f54c688c2cff654cf54bd79da764f448297d190"}]}