[PHP-CVS] com php-src: Fixed bug #62987 (Assigning to ArrayObject[null][something] overrides all undefined variables): NEWS ext/spl/spl_array.c ext/spl/tests/bug62978.phpt
Commit:67d7d03f00cb3185a4d5958ab7a4b063fc33405c Author:Xinchen Hui larue...@php.net Sat, 1 Sep 2012 14:17:39 +0800 Parents: 5dc2cef370885c552c20f3ff44bccd402850de9e Branches: PHP-5.3 Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=67d7d03f00cb3185a4d5958ab7a4b063fc33405c Log: Fixed bug #62987 (Assigning to ArrayObject[null][something] overrides all undefined variables) The get_zval_ptr_ptr of spl_array handler should act as same as the vm's Bugs: https://bugs.php.net/62987 Changed paths: M NEWS M ext/spl/spl_array.c A ext/spl/tests/bug62978.phpt Diff: diff --git a/NEWS b/NEWS index a6e05be..ae82821 100644 --- a/NEWS +++ b/NEWS @@ -45,6 +45,8 @@ PHP NEWS . Fixed bug (segfault due to retval is not initialized). (Laruence) - SPL: + . Bug #62987 (Assigning to ArrayObject[null][something] overrides all +undefined variables). (Laruence) . Fixed bug #62904 (Crash when cloning an object which inherits SplFixedArray) (Laruence) . Fixed bug #62616 (ArrayIterator::count() from IteratorIterator instance diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 80ca5be..11540de 100755 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -312,38 +312,41 @@ static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object, long index; HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); -/* We cannot get the pointer pointer so we don't allow it here for now - if (check_inherited intern-fptr_offset_get) { - return zend_call_method_with_1_params(object, Z_OBJCE_P(object), intern-fptr_offset_get, offsetGet, NULL, offset); - }*/ - if (!offset) { return EG(uninitialized_zval_ptr); } if ((type == BP_VAR_W || type == BP_VAR_RW) (ht-nApplyCount 0)) { zend_error(E_WARNING, Modification of ArrayObject during sorting is prohibited); - return EG(uninitialized_zval_ptr);; + return EG(error_zval_ptr);; } switch(Z_TYPE_P(offset)) { + case IS_NULL: + Z_STRVAL_P(offset) = ; + Z_STRLEN_P(offset) = 0; case IS_STRING: if (zend_symtable_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) retval) == FAILURE) { - if (type == BP_VAR_W || type == BP_VAR_RW) { - zval *value; - ALLOC_INIT_ZVAL(value); - zend_symtable_update(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void**)value, sizeof(void*), NULL); - zend_symtable_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) retval); - return retval; - } else { - zend_error(E_NOTICE, Undefined index: %s, Z_STRVAL_P(offset)); - return EG(uninitialized_zval_ptr); + switch (type) { + case BP_VAR_R: + zend_error(E_NOTICE, Undefined index: %s, Z_STRVAL_P(offset)); + case BP_VAR_UNSET: + case BP_VAR_IS: + retval = EG(uninitialized_zval_ptr); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,Undefined index: %s, Z_STRVAL_P(offset)); + case BP_VAR_W: { + zval *value; + ALLOC_INIT_ZVAL(value); + zend_symtable_update(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void**)value, sizeof(void*), (void **)retval); + } } - } else { - return retval; } - case IS_DOUBLE: + return retval; case IS_RESOURCE: + zend_error(E_STRICT, Resource ID#%ld used as offset, casting to integer (%ld), Z_LVAL_P(offset), Z_LVAL_P(offset)); + case IS_DOUBLE: case IS_BOOL: case IS_LONG: if (offset-type == IS_DOUBLE) { @@ -352,23 +355,27 @@ static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object, index = Z_LVAL_P(offset); } if (zend_hash_index_find(ht, index, (void **) retval) == FAILURE) { - if (type == BP_VAR_W || type == BP_VAR_RW) { - zval *value; - ALLOC_INIT_ZVAL(value); - zend_hash_index_update(ht, index, (void**)value, sizeof(void*), NULL); -
[PHP-CVS] com php-src: Merge branch 'PHP-5.3' into PHP-5.4: NEWS ext/spl/spl_array.c
Commit:863e7e0acbe284d5c7738fa9c601023ad5773d3f Author:Xinchen Hui larue...@php.net Sat, 1 Sep 2012 14:27:09 +0800 Parents: e658a91b3d826ea4104b17f3a6123c1e9f3aee86 67d7d03f00cb3185a4d5958ab7a4b063fc33405c Branches: PHP-5.4 Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=863e7e0acbe284d5c7738fa9c601023ad5773d3f Log: Merge branch 'PHP-5.3' into PHP-5.4 Conflicts: ext/spl/spl_array.c Changed paths: MM NEWS MM ext/spl/spl_array.c Diff: diff --cc NEWS index d88aa18,ae82821..62e2038 --- a/NEWS +++ b/NEWS @@@ -60,121 -43,53 +60,123 @@@ PH - Session: . Fixed bug (segfault due to retval is not initialized). (Laruence) + . Fixed bug (segfault due to PS(mod_user_implemented) not be reseted +when close handler call exit). (Laruence) - SPL: + . Bug #62987 (Assigning to ArrayObject[null][something] overrides all + undefined variables). (Laruence) . Fixed bug #62904 (Crash when cloning an object which inherits SplFixedArray) (Laruence) + . Implemented FR #62840 (Add sort flag to ArrayObject::ksort). (Laruence) + +- Standard: + . Fixed bug #62836 (Seg fault or broken object references on unserialize()). +(Laruence) + +- FPM: + . Merged PR 121 by minitux to add support for slow request counting on PHP +FPM status page. (Lars) + +16 Aug 2012, PHP 5.4.6 + +- CLI Server: + . Implemented FR #62700 (have the console output 'Listening on +http://localhost:8000'). (pascal.chev...@free.fr) + +- Core: + . Fixed bug #62661 (Interactive php-cli crashes if include() is used in +auto_prepend_file). (Laruence) + . Fixed bug #62653: (unset($array[$float]) causes a crash). (Nikita Popov, +Laruence) + . Fixed bug #62565 (Crashes due non-initialized internal properties_table). +(Felipe) + . Fixed bug #60194 (--with-zend-multibyte and --enable-debug reports LEAK +with run-test.php). (Laruence) + +- CURL: + . Fixed bug #62499 (curl_setopt($ch, CURLOPT_COOKIEFILE, ) returns false). +(r.hampartsum...@gmail.com, Laruence) + +- DateTime: + . Fixed Bug #62500 (Segfault in DateInterval class when extended). (Laruence) + +- Fileinfo: + . Fixed bug #61964 (finfo_open with directory causes invalid free). +(reeze@gmail.com) + +- Intl: + . Fixed bug #62564 (Extending MessageFormatter and adding property causes +crash). (Felipe) + +- MySQLnd: + . Fixed bug #62594 (segfault in mysqlnd_res_meta::set_mode). (Laruence) + +- readline: + . Fixed bug #62612 (readline extension compilation fails with +sapi/cli/cli.h: No such file). (Johannes) + +- Reflection: + . Implemented FR #61602 (Allow access to name of constant used as default +value). (reeze@gmail.com) + +- SimpleXML: + . Implemented FR #55218 Get namespaces from current node. (Lonny) + +- SPL: . Fixed bug #62616 (ArrayIterator::count() from IteratorIterator instance gives Segmentation fault). (Laruence, Gustavo) + . Fixed bug #61527 (ArrayIterator gives misleading notice on next() when +moved to the end). (reeze@gmail.com) -- Enchant: - . Fixed bug #62838 (enchant_dict_quick_check() destroys zval, but fails to - initialize it). (Tony, Mateusz Goik). +- Streams: + . Fixed bug #62597 (segfault in php_stream_wrapper_log_error with ZTS build). +(Laruence) -19 Jul 2012, PHP 5.3.15 +- Zlib: + . Fixed bug #55544 (ob_gzhandler always conflicts with +zlib.output_compression). (Laruence) -- Zend Engine: - . Fixed bug #51094 (parse_ini_file() with INI_SCANNER_RAW cuts a value that -includes a semi-colon). (Pierrick) - -- COM: - . Fixed bug #62146 com_dotnet cannot be built shared. (Johannes) +19 Jul 2012, PHP 5.4.5 - Core: - . Fixed potential overflow in _php_stream_scandir, CVE-2012-2688. (Jason -Powell, Stas) - . Fixed bug #62432 (ReflectionMethod random corrupt memory on high -concurrent). (Johannes) . Fixed bug #62443 (Crypt SHA256/512 Segfaults With Malformed Salt). (Anthony Ferrara) + . Fixed bug #62432 (ReflectionMethod random corrupt memory on high +concurrent). (Johannes) + . Fixed bug #62373 (serialize() generates wrong reference to the object). +(Moriyoshi) + . Fixed bug #62357 (compile failure: (S) Arguments missing for built-in +function __memcmp). (Laruence) + . Fixed bug #61998 (Using traits with method aliases appears to result in +crash during execution). (Dmitry) + . Fixed bug #51094 (parse_ini_file() with INI_SCANNER_RAW cuts a value that +includes a semi-colon). (Pierrick) + . Fixed potential overflow in _php_stream_scandir (CVE-2012-2688). +(Jason Powell, Stas) -- Fileinfo: - . Fixed magic file regex support. (Felipe) +- EXIF: + . Fixed information leak in ext exif (discovered by Martin Noga, +Matthew j00ru Jurczyk, Gynvael Coldwind) - FPM: - . Fixed bug #61045 (fpm don't send error log to fastcgi
[PHP-CVS] com php-src: Remove extra blank in notice message, should act as same as vm: ext/spl/spl_array.c ext/spl/spl_iterators.c ext/spl/tests/arrayObject___construct_basic2.phpt ext/spl/tests/array
Commit:f3108b5f818b2757d2e518f37d3927e83858ae4f Author:Xinchen Hui larue...@php.net Sat, 1 Sep 2012 14:37:45 +0800 Parents: 863e7e0acbe284d5c7738fa9c601023ad5773d3f Branches: PHP-5.4 Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=f3108b5f818b2757d2e518f37d3927e83858ae4f Log: Remove extra blank in notice message, should act as same as vm Changed paths: M ext/spl/spl_array.c M ext/spl/spl_iterators.c M ext/spl/tests/arrayObject___construct_basic2.phpt M ext/spl/tests/arrayObject___construct_basic3.phpt M ext/spl/tests/arrayObject___construct_basic4.phpt M ext/spl/tests/arrayObject___construct_basic5.phpt M ext/spl/tests/arrayObject_magicMethods1.phpt M ext/spl/tests/arrayObject_magicMethods3.phpt M ext/spl/tests/arrayObject_magicMethods4.phpt M ext/spl/tests/arrayObject_magicMethods6.phpt M ext/spl/tests/arrayObject_setFlags_basic1.phpt M ext/spl/tests/array_001.phpt M ext/spl/tests/array_010.phpt M ext/spl/tests/bug45622.phpt M ext/spl/tests/bug45622b.phpt M ext/spl/tests/bug54323.phpt M ext/spl/tests/bug62978.phpt M ext/spl/tests/iterator_044.phpt diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 0b3b5a3..3c6b41e 100755 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -323,13 +323,13 @@ static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object, if (zend_symtable_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) retval) == FAILURE) { switch (type) { case BP_VAR_R: - zend_error(E_NOTICE, Undefined index: %s, Z_STRVAL_P(offset)); + zend_error(E_NOTICE, Undefined index: %s, Z_STRVAL_P(offset)); case BP_VAR_UNSET: case BP_VAR_IS: retval = EG(uninitialized_zval_ptr); break; case BP_VAR_RW: - zend_error(E_NOTICE,Undefined index: %s, Z_STRVAL_P(offset)); + zend_error(E_NOTICE,Undefined index: %s, Z_STRVAL_P(offset)); case BP_VAR_W: { zval *value; ALLOC_INIT_ZVAL(value); @@ -351,13 +351,13 @@ static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object, if (zend_hash_index_find(ht, index, (void **) retval) == FAILURE) { switch (type) { case BP_VAR_R: - zend_error(E_NOTICE, Undefined offset: %ld, index); + zend_error(E_NOTICE, Undefined offset: %ld, index); case BP_VAR_UNSET: case BP_VAR_IS: retval = EG(uninitialized_zval_ptr); break; case BP_VAR_RW: - zend_error(E_NOTICE, Undefined offset: %ld, index); + zend_error(E_NOTICE, Undefined offset: %ld, index); case BP_VAR_W: { zval *value; ALLOC_INIT_ZVAL(value); @@ -520,11 +520,11 @@ static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval } if (ht == EG(symbol_table)) { if (zend_delete_global_variable(Z_STRVAL_P(offset), Z_STRLEN_P(offset) TSRMLS_CC)) { - zend_error(E_NOTICE,Undefined index: %s, Z_STRVAL_P(offset)); + zend_error(E_NOTICE,Undefined index: %s, Z_STRVAL_P(offset)); } } else { if (zend_symtable_del(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1) == FAILURE) { - zend_error(E_NOTICE,Undefined index: %s, Z_STRVAL_P(offset)); + zend_error(E_NOTICE,Undefined index: %s, Z_STRVAL_P(offset)); } else { spl_array_object *obj = intern; @@ -570,7 +570,7 @@ static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval return; } if (zend_hash_index_del(ht, index) == FAILURE) { - zend_error(E_NOTICE,Undefined offset: %ld, Z_LVAL_P(offset)); + zend_error(E_NOTICE,Undefined offset: %ld, Z_LVAL_P(offset)); } break; default: diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index e5dc030..098d7dc 100755 ---
[PHP-CVS] com php-src: Merge branch 'PHP-5.4': ext/spl/spl_iterators.c
Commit:7b5960b08577700275468b396e6f962e0b70 Author:Xinchen Hui larue...@php.net Sat, 1 Sep 2012 14:38:33 +0800 Parents: 59e34bad32cecd823577f43756776d6d6936e93e f3108b5f818b2757d2e518f37d3927e83858ae4f Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=7b5960b08577700275468b396e6f962e0b70 Log: Merge branch 'PHP-5.4' Changed paths: MM ext/spl/spl_iterators.c Diff: -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
Re: [PHP-CVS] com php-src: Fixed bug #62987 (Assigning to ArrayObject[null][something] overrides all undefined variables): NEWS ext/spl/spl_array.c ext/spl/tests/bug62978.phpt
Hi Rms: this bug is a critical one. please notice this fix. :) thanks On Sat, Sep 1, 2012 at 2:21 PM, Xinchen Hui larue...@php.net wrote: Commit:67d7d03f00cb3185a4d5958ab7a4b063fc33405c Author:Xinchen Hui larue...@php.net Sat, 1 Sep 2012 14:17:39 +0800 Parents: 5dc2cef370885c552c20f3ff44bccd402850de9e Branches: PHP-5.3 Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=67d7d03f00cb3185a4d5958ab7a4b063fc33405c Log: Fixed bug #62987 (Assigning to ArrayObject[null][something] overrides all undefined variables) The get_zval_ptr_ptr of spl_array handler should act as same as the vm's Bugs: https://bugs.php.net/62987 Changed paths: M NEWS M ext/spl/spl_array.c A ext/spl/tests/bug62978.phpt Diff: diff --git a/NEWS b/NEWS index a6e05be..ae82821 100644 --- a/NEWS +++ b/NEWS @@ -45,6 +45,8 @@ PHP NEWS . Fixed bug (segfault due to retval is not initialized). (Laruence) - SPL: + . Bug #62987 (Assigning to ArrayObject[null][something] overrides all +undefined variables). (Laruence) . Fixed bug #62904 (Crash when cloning an object which inherits SplFixedArray) (Laruence) . Fixed bug #62616 (ArrayIterator::count() from IteratorIterator instance diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 80ca5be..11540de 100755 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -312,38 +312,41 @@ static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object, long index; HashTable *ht = spl_array_get_hash_table(intern, 0 TSRMLS_CC); -/* We cannot get the pointer pointer so we don't allow it here for now - if (check_inherited intern-fptr_offset_get) { - return zend_call_method_with_1_params(object, Z_OBJCE_P(object), intern-fptr_offset_get, offsetGet, NULL, offset); - }*/ - if (!offset) { return EG(uninitialized_zval_ptr); } if ((type == BP_VAR_W || type == BP_VAR_RW) (ht-nApplyCount 0)) { zend_error(E_WARNING, Modification of ArrayObject during sorting is prohibited); - return EG(uninitialized_zval_ptr);; + return EG(error_zval_ptr);; } switch(Z_TYPE_P(offset)) { + case IS_NULL: + Z_STRVAL_P(offset) = ; + Z_STRLEN_P(offset) = 0; case IS_STRING: if (zend_symtable_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) retval) == FAILURE) { - if (type == BP_VAR_W || type == BP_VAR_RW) { - zval *value; - ALLOC_INIT_ZVAL(value); - zend_symtable_update(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void**)value, sizeof(void*), NULL); - zend_symtable_find(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void **) retval); - return retval; - } else { - zend_error(E_NOTICE, Undefined index: %s, Z_STRVAL_P(offset)); - return EG(uninitialized_zval_ptr); + switch (type) { + case BP_VAR_R: + zend_error(E_NOTICE, Undefined index: %s, Z_STRVAL_P(offset)); + case BP_VAR_UNSET: + case BP_VAR_IS: + retval = EG(uninitialized_zval_ptr); + break; + case BP_VAR_RW: + zend_error(E_NOTICE,Undefined index: %s, Z_STRVAL_P(offset)); + case BP_VAR_W: { + zval *value; + ALLOC_INIT_ZVAL(value); + zend_symtable_update(ht, Z_STRVAL_P(offset), Z_STRLEN_P(offset)+1, (void**)value, sizeof(void*), (void **)retval); + } } - } else { - return retval; } - case IS_DOUBLE: + return retval; case IS_RESOURCE: + zend_error(E_STRICT, Resource ID#%ld used as offset, casting to integer (%ld), Z_LVAL_P(offset), Z_LVAL_P(offset)); + case IS_DOUBLE: case IS_BOOL: case IS_LONG: if (offset-type == IS_DOUBLE) { @@ -352,23 +355,27 @@ static zval **spl_array_get_dimension_ptr_ptr(int check_inherited, zval *object, index = Z_LVAL_P(offset); } if (zend_hash_index_find(ht, index, (void **) retval) == FAILURE) { - if (type == BP_VAR_W || type ==
[PHP-CVS] com php-src: Make sure that exception is thrown on rewind() after closing too: Zend/tests/generators/generator_rewind.phpt Zend/zend_generators.c
Commit:cc07038fa9b2a59893c52fb0c515a1fb03e56d5c Author:Nikita Popov ni...@php.net Wed, 29 Aug 2012 20:31:34 +0200 Parents: d60e3c6ef53986e82178bb657ad907edc16d2c34 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=cc07038fa9b2a59893c52fb0c515a1fb03e56d5c Log: Make sure that exception is thrown on rewind() after closing too Changed paths: M Zend/tests/generators/generator_rewind.phpt M Zend/zend_generators.c Diff: diff --git a/Zend/tests/generators/generator_rewind.phpt b/Zend/tests/generators/generator_rewind.phpt index 3224f6a..af885ef 100644 --- a/Zend/tests/generators/generator_rewind.phpt +++ b/Zend/tests/generators/generator_rewind.phpt @@ -21,6 +21,14 @@ try { echo \n, $e, \n\n; } +$gen = gen(); +foreach ($gen as $v) { } +try { +foreach ($gen as $v) { } +} catch (Exception $e) { +echo \n, $e, \n\n; +} + function gen2() { echo in generator\n; @@ -40,4 +48,12 @@ Stack trace: #0 %s(%d): Generator-rewind() #1 {main} +before yield +after yield + +exception 'Exception' with message 'Cannot rewind a generator that was already run' in %s:%d +Stack trace: +#0 %s(%d): unknown() +#1 {main} + in generator diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 03294f7..0eb17d0 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -500,7 +500,7 @@ void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */ static void zend_generator_ensure_initialized(zend_generator *generator TSRMLS_DC) /* {{{ */ { - if (!generator-value) { + if (generator-execute_data !generator-value) { zend_generator_resume(generator TSRMLS_CC); generator-flags |= ZEND_GENERATOR_AT_FIRST_YIELD; } -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Fix segfault when traversing a by-ref generator twice: Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt Zend/tests/generators/generator_rewind.phpt Zend
Commit:bef79588d543db996d092191ac498751a1cc161f Author:Nikita Popov ni...@php.net Wed, 29 Aug 2012 20:46:56 +0200 Parents: cc07038fa9b2a59893c52fb0c515a1fb03e56d5c Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=bef79588d543db996d092191ac498751a1cc161f Log: Fix segfault when traversing a by-ref generator twice If you try to traverse an already closed generator an exception will now be thrown. Furthermore this changes the error for traversing a by-val generator by-ref from an E_ERROR to an Exception. Changed paths: M Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt M Zend/tests/generators/generator_rewind.phpt M Zend/zend_generators.c Diff: diff --git a/Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt b/Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt index 9c618d2..de5b22f 100644 --- a/Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt +++ b/Zend/tests/generators/errors/non_ref_generator_iterated_by_ref_error.phpt @@ -10,4 +10,9 @@ foreach ($gen as $value) { } ? --EXPECTF-- -Fatal error: You can only iterate a generator by-reference if it declared that it yields by-reference in %s on line %d +Fatal error: Uncaught exception 'Exception' with message 'You can only iterate a generator by-reference if it declared that it yields by-reference' in %s:%d +Stack trace: +#0 %s(%d): unknown() +#1 {main} + thrown in %s on line %d + diff --git a/Zend/tests/generators/generator_rewind.phpt b/Zend/tests/generators/generator_rewind.phpt index af885ef..c4b5bbb 100644 --- a/Zend/tests/generators/generator_rewind.phpt +++ b/Zend/tests/generators/generator_rewind.phpt @@ -21,21 +21,27 @@ try { echo \n, $e, \n\n; } -$gen = gen(); +function gen2() { +$foo = 'bar'; +yield $foo; +yield $foo; +} + +$gen = gen2(); foreach ($gen as $v) { } try { foreach ($gen as $v) { } } catch (Exception $e) { -echo \n, $e, \n\n; +echo $e, \n\n; } -function gen2() { +function gen3() { echo in generator\n; if (false) yield; } -$gen = gen2(); +$gen = gen3(); $gen-rewind(); ? @@ -48,10 +54,7 @@ Stack trace: #0 %s(%d): Generator-rewind() #1 {main} -before yield -after yield - -exception 'Exception' with message 'Cannot rewind a generator that was already run' in %s:%d +exception 'Exception' with message 'Cannot traverse an already closed generator' in %s:%d Stack trace: #0 %s(%d): unknown() #1 {main} diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 0eb17d0..60fa8b6 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -766,8 +766,14 @@ zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *ob generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC); + if (!generator-execute_data) { + zend_throw_exception(NULL, Cannot traverse an already closed generator, 0 TSRMLS_CC); + return NULL; + } + if (by_ref !(generator-execute_data-op_array-fn_flags ZEND_ACC_RETURN_REFERENCE)) { - zend_error(E_ERROR, You can only iterate a generator by-reference if it declared that it yields by-reference); + zend_throw_exception(NULL, You can only iterate a generator by-reference if it declared that it yields by-reference, 0 TSRMLS_CC); + return NULL; } iterator = emalloc(sizeof(zend_generator_iterator)); -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Merge remote-tracking branch 'php-src/master' into addGeneratorsSupport: Zend/zend_compile.c Zend/zend_compile.h Zend/zend_language_parser.y Zend/zend_vm_def.h Zend/zend_vm_exec
Commit:d60e3c6ef53986e82178bb657ad907edc16d2c34 Author:Nikita Popov ni...@php.net Sat, 25 Aug 2012 20:07:01 +0200 Parents: bd70d155885fdc087afba912c1b290615b864e2f 35951d4be0bd27c85519995a95429bd0d0a76a00 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=d60e3c6ef53986e82178bb657ad907edc16d2c34 Log: Merge remote-tracking branch 'php-src/master' into addGeneratorsSupport Conflicts: Zend/zend_language_parser.y Zend/zend_vm_execute.skl Changed paths: MM Zend/zend_compile.c MM Zend/zend_compile.h MM Zend/zend_language_parser.y MM Zend/zend_vm_def.h MM Zend/zend_vm_execute.h MM Zend/zend_vm_execute.skl Diff: diff --cc Zend/zend_vm_def.h index 1016679,92c5fcf..ffd81b0 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@@ -3049,20 -3053,12 +3051,20 @@@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF FREE_OP1_IF_VAR(); - if (EX(op_array)-has_finally_block) { - ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_RETURN_BY_REF); + if (EXPECTED(!EX(op_array)-has_finally_block)) { + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); } - ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_RETURN_BY_REF); } +ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, ANY, ANY) +{ + if (EX(op_array)-has_finally_block) { + ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_RETURN); + } + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); +} + ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY) { USE_OPLINE diff --cc Zend/zend_vm_execute.h index a643967,1e0b2b5..b0e05b1 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@@ -409,26 -400,6 +409,26 @@@ zend_execute_data *zend_create_execute_ EX(function_state).function = (zend_function *) op_array; EX(function_state).arguments = NULL; + return execute_data; +} + +ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC) +{ + DCL_OPLINE - - zend_bool original_in_execution = EG(in_execution); ++ zend_bool original_in_execution; + + + + if (EG(exception)) { + return; + } + ++ original_in_execution = EG(in_execution); + EG(in_execution) = 1; + + LOAD_REGS(); + LOAD_OPLINE(); + while (1) { int ret; #ifdef ZEND_WIN32 diff --cc Zend/zend_vm_execute.skl index 25b3d71,0c5e8a3..58e5631 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@@ -70,28 -63,6 +70,28 @@@ zend_execute_data *zend_create_execute_ EX(function_state).function = (zend_function *) op_array; EX(function_state).arguments = NULL; + return execute_data; +} + +ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *execute_data TSRMLS_DC) +{ + DCL_OPLINE - - zend_bool original_in_execution = EG(in_execution); ++ zend_bool original_in_execution; + + {%HELPER_VARS%} + + {%INTERNAL_LABELS%} + + if (EG(exception)) { + return; + } + ++ original_in_execution = EG(in_execution); + EG(in_execution) = 1; + + LOAD_REGS(); + LOAD_OPLINE(); + while (1) { {%ZEND_VM_CONTINUE_LABEL%} #ifdef ZEND_WIN32 -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Add dedicated opcode for returns from a generator: Zend/zend_opcode.c Zend/zend_vm_def.h Zend/zend_vm_execute.h Zend/zend_vm_opcodes.h
Commit:68c1e1cfe95b026086cacf40a005ea8f399e9595 Author:Nikita Popov ni...@php.net Fri, 24 Aug 2012 13:51:39 +0200 Parents: 6517ed021520a608a18da4653cb9c6b414121f6f Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=68c1e1cfe95b026086cacf40a005ea8f399e9595 Log: Add dedicated opcode for returns from a generator Generators don't have a return value, so it doesn't make sense to have a shared implementation here. Changed paths: M Zend/zend_opcode.c M Zend/zend_vm_def.h M Zend/zend_vm_execute.h M Zend/zend_vm_opcodes.h Diff: diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 0f39b8a..5c4b20f 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -586,9 +586,8 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) CG(zend_lineno) = opline-lineno; zend_error(E_COMPILE_ERROR, Generators cannot return values using \return\); } - if (opline-opcode == ZEND_RETURN_BY_REF) { - opline-opcode = ZEND_RETURN; - } + + opline-opcode = ZEND_GENERATOR_RETURN; } break; } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 975a2a7..216cd59 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2931,17 +2931,6 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY) zval *retval_ptr; zend_free_op free_op1; - if (EX(op_array)-fn_flags ZEND_ACC_GENERATOR) { - /* The generator object is stored in return_value_ptr_ptr */ - zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); - - /* Close the generator to free up resources */ - zend_generator_close(generator, 1 TSRMLS_CC); - - /* Pass execution back to handling code */ - ZEND_VM_RETURN(); - } - SAVE_OPLINE(); retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R); @@ -3066,6 +3055,14 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY) ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); } +ZEND_VM_HANDLER(162, ZEND_GENERATOR_RETURN, ANY, ANY) +{ + if (EX(op_array)-has_finally_block) { + ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_RETURN); + } + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); +} + ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY) { USE_OPLINE diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 402442f..ebc0fb9 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -885,6 +885,14 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(ZEND_OPCODE_HANDLER return zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } +static int ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + if (EX(op_array)-has_finally_block) { + return zend_finally_handler_leaving_SPEC(ZEND_RETURN, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); +} + static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -2443,17 +2451,6 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG zval *retval_ptr; - if (EX(op_array)-fn_flags ZEND_ACC_GENERATOR) { - /* The generator object is stored in return_value_ptr_ptr */ - zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); - - /* Close the generator to free up resources */ - zend_generator_close(generator, 1 TSRMLS_CC); - - /* Pass execution back to handling code */ - ZEND_VM_RETURN(); - } - SAVE_OPLINE(); retval_ptr = opline-op1.zv; @@ -7760,17 +7757,6 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zval *retval_ptr; zend_free_op free_op1; - if (EX(op_array)-fn_flags ZEND_ACC_GENERATOR) { - /* The generator object is stored in return_value_ptr_ptr */ - zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); - - /* Close the generator to free up resources */ - zend_generator_close(generator, 1 TSRMLS_CC); - - /* Pass execution back to handling code */ - ZEND_VM_RETURN(); - } - SAVE_OPLINE(); retval_ptr = _get_zval_ptr_tmp(opline-op1.var, EX_Ts(), free_op1 TSRMLS_CC); @@ -12982,17 +12968,6 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
[PHP-CVS] com php-src: Finally with return now works in generators too: Zend/tests/generators/finally_with_return.phpt
Commit:7cdf6367a51a54fce8676aeb6fd32bf91b00f84b Author:Nikita Popov ni...@php.net Fri, 24 Aug 2012 13:52:16 +0200 Parents: 68c1e1cfe95b026086cacf40a005ea8f399e9595 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=7cdf6367a51a54fce8676aeb6fd32bf91b00f84b Log: Finally with return now works in generators too Changed paths: A Zend/tests/generators/finally_with_return.phpt Diff: diff --git a/Zend/tests/generators/finally_with_return.phpt b/Zend/tests/generators/finally_with_return.phpt new file mode 100644 index 000..b26a49f --- /dev/null +++ b/Zend/tests/generators/finally_with_return.phpt @@ -0,0 +1,33 @@ +--TEST-- +Use of finally in generator with return +--FILE-- +?php + +function gen() { +try { +try { +echo before return\n; +return; +echo after return\n; +} finally { +echo before return in inner finally\n; +return; +echo after return in inner finally\n; +} +} finally { +echo outer finally run\n; +} + +echo code after finally\n; + +yield; // force generator +} + +$gen = gen(); +$gen-rewind(); // force run + +? +--EXPECTF-- +before return +before return in inner finally +outer finally run -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Merge remote-tracking branch 'php-src/master' into addGeneratorsSupport: Zend/zend_compile.c Zend/zend_compile.h Zend/zend_opcode.c Zend/zend_vm_def.h Zend/zend_vm_execute.h
Commit:6517ed021520a608a18da4653cb9c6b414121f6f Author:Nikita Popov ni...@php.net Fri, 24 Aug 2012 13:29:40 +0200 Parents: f45a0f31c8354947c0e2b9ea44a63fc0a2c23a01 071580ea1f450513dba2dbf585a9498614f855e7 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=6517ed021520a608a18da4653cb9c6b414121f6f Log: Merge remote-tracking branch 'php-src/master' into addGeneratorsSupport Conflicts: Zend/zend_vm_def.h Zend/zend_vm_execute.h Changed paths: MM Zend/zend_compile.c MM Zend/zend_compile.h MM Zend/zend_opcode.c MM Zend/zend_vm_def.h MM Zend/zend_vm_execute.h diff --cc Zend/zend_vm_def.h index f8955c5,ce1674e..975a2a7 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@@ -1840,291 -1840,296 +1840,294 @@@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VA ZEND_VM_NEXT_OPCODE(); } - ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY) + ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) { - USE_OPLINE - - #if DEBUG_ZEND=2 - printf(Jumping to %d\n, opline-op1.opline_num); - #endif - ZEND_VM_SET_OPCODE(opline-op1.jmp_addr); - ZEND_VM_CONTINUE(); /* CHECK_ME */ - } + zend_bool nested; + zend_op_array *op_array = EX(op_array); - ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMP|VAR|CV, ANY) - { - USE_OPLINE - zend_free_op free_op1; - zval *val; - int ret; ++ /* Generators go throw a different cleanup process */ ++ if (EX(op_array)-fn_flags ZEND_ACC_GENERATOR) { ++ /* The generator object is stored in return_value_ptr_ptr */ ++ zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + - SAVE_OPLINE(); - val = GET_OP1_ZVAL_PTR(BP_VAR_R); ++ /* Close the generator to free up resources */ ++ zend_generator_close(generator, 1 TSRMLS_CC); + - if (OP1_TYPE == IS_TMP_VAR EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { - ret = Z_LVAL_P(val); - } else { - ret = i_zend_is_true(val); - FREE_OP1(); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } - } - if (!ret) { - #if DEBUG_ZEND=2 - printf(Conditional jmp to %d\n, opline-op2.opline_num); - #endif - ZEND_VM_SET_OPCODE(opline-op2.jmp_addr); - ZEND_VM_CONTINUE(); ++ /* Pass execution back to handling code */ ++ ZEND_VM_RETURN(); + } + - ZEND_VM_NEXT_OPCODE(); - } + EG(current_execute_data) = EX(prev_execute_data); + EG(opline_ptr) = NULL; + if (!EG(active_symbol_table)) { - zval ***cv = EX_CVs(); - zval ***end = cv + op_array-last_var; - while (cv != end) { - if (*cv) { - zval_ptr_dtor(*cv); - } - cv++; - } ++ zend_free_compiled_variables(EX_CVs(), op_array-last_var); + } - ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMP|VAR|CV, ANY) - { - USE_OPLINE - zend_free_op free_op1; - zval *val; - int ret; + if ((op_array-fn_flags ZEND_ACC_CLOSURE) op_array-prototype) { + zval_ptr_dtor((zval**)op_array-prototype); + } - SAVE_OPLINE(); - val = GET_OP1_ZVAL_PTR(BP_VAR_R); + nested = EX(nested); - if (OP1_TYPE == IS_TMP_VAR EXPECTED(Z_TYPE_P(val) == IS_BOOL)) { - ret = Z_LVAL_P(val); - zend_vm_stack_free(execute_data TSRMLS_CC); ++ /* For generators the execute_data is stored on the heap, for everything ++ * else it is stored on the VM stack. */ ++ if (op_array-fn_flags ZEND_ACC_GENERATOR) { ++ efree(execute_data); + } else { - ret = i_zend_is_true(val); - FREE_OP1(); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); - } ++ zend_vm_stack_free(execute_data TSRMLS_CC); + } - if (ret) { - #if DEBUG_ZEND=2 - printf(Conditional jmp to %d\n, opline-op2.opline_num); - #endif - ZEND_VM_SET_OPCODE(opline-op2.jmp_addr); - ZEND_VM_CONTINUE(); + + if (nested) { + execute_data = EG(current_execute_data); } + if (nested) { + USE_OPLINE - ZEND_VM_NEXT_OPCODE(); - } + LOAD_REGS(); + LOAD_OPLINE(); + if (UNEXPECTED(opline-opcode == ZEND_INCLUDE_OR_EVAL)) { - ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMP|VAR|CV, ANY) - { - USE_OPLINE - zend_free_op free_op1; - zval *val; - int retval; + EX(function_state).function = (zend_function *) EX(op_array); + EX(function_state).arguments = NULL; + EX(object) = EX(current_object); -
[PHP-CVS] com php-src: Disallow serialization and unserialization: Zend/tests/generators/errors/serialize_unserialize_error.phpt Zend/zend_generators.c
Commit:f45a0f31c8354947c0e2b9ea44a63fc0a2c23a01 Author:Nikita Popov ni...@php.net Mon, 20 Aug 2012 16:01:16 +0200 Parents: 1823b16fa15894f72fc01724766289dbecf5a62a Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=f45a0f31c8354947c0e2b9ea44a63fc0a2c23a01 Log: Disallow serialization and unserialization Changed paths: A Zend/tests/generators/errors/serialize_unserialize_error.phpt M Zend/zend_generators.c Diff: diff --git a/Zend/tests/generators/errors/serialize_unserialize_error.phpt b/Zend/tests/generators/errors/serialize_unserialize_error.phpt new file mode 100644 index 000..a8470b0 --- /dev/null +++ b/Zend/tests/generators/errors/serialize_unserialize_error.phpt @@ -0,0 +1,46 @@ +--TEST-- +Generators can't be serialized or unserialized +--FILE-- +?php + +function gen() { yield; } + +$gen = gen(); + +try { +serialize($gen); +} catch (Exception $e) { +echo $e, \n\n; +} + +try { +var_dump(unserialize('O:9:Generator:0:{}')); +} catch (Exception $e) { +echo $e, \n\n; +} + +try { +var_dump(unserialize('C:9:Generator:0:{}')); +} catch (Exception $e) { +echo $e; +} + +? +--EXPECTF-- +exception 'Exception' with message 'Serialization of 'Generator' is not allowed' in %s:%d +Stack trace: +#0 %s(%d): serialize(Object(Generator)) +#1 {main} + +exception 'Exception' with message 'Unserialization of 'Generator' is not allowed' in %s:%d +Stack trace: +#0 [internal function]: Generator-__wakeup() +#1 %s(%d): unserialize('O:9:Generator...') +#2 {main} + + +Notice: unserialize(): Error at offset 19 of 20 bytes in %s on line %d +exception 'Exception' with message 'Unserialization of 'Generator' is not allowed' in %s:%d +Stack trace: +#0 %s(%d): unserialize('C:9:Generator...') +#1 {main} diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 41c6dfc..b4d8932 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -590,6 +590,23 @@ ZEND_METHOD(Generator, send) } } + +/* {{{ proto void Generator::__wakeup + * Throws an Exception as generators can't be serialized */ +ZEND_METHOD(Generator, __wakeup) +{ + /* Just specifying the zend_class_unserialize_deny handler is not enough, +* because it is only invoked for C unserialization. For O the error has +* to be thrown in __wakeup. */ + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + zend_throw_exception(NULL, Unserialization of 'Generator' is not allowed, 0 TSRMLS_CC); +} +/* }}} */ + /* get_iterator implementation */ typedef struct _zend_generator_iterator { @@ -712,12 +729,13 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_generator_send, 0, 0, 1) ZEND_END_ARG_INFO() static const zend_function_entry generator_functions[] = { - ZEND_ME(Generator, rewind, arginfo_generator_void, ZEND_ACC_PUBLIC) - ZEND_ME(Generator, valid, arginfo_generator_void, ZEND_ACC_PUBLIC) - ZEND_ME(Generator, current, arginfo_generator_void, ZEND_ACC_PUBLIC) - ZEND_ME(Generator, key, arginfo_generator_void, ZEND_ACC_PUBLIC) - ZEND_ME(Generator, next,arginfo_generator_void, ZEND_ACC_PUBLIC) - ZEND_ME(Generator, send,arginfo_generator_send, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, rewind, arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, valid,arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, current, arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, key, arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, next, arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, send, arginfo_generator_send, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, __wakeup, arginfo_generator_void, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -729,6 +747,8 @@ void zend_register_generator_ce(TSRMLS_D) /* {{{ */ zend_ce_generator = zend_register_internal_class(ce TSRMLS_CC); zend_ce_generator-ce_flags |= ZEND_ACC_FINAL_CLASS; zend_ce_generator-create_object = zend_generator_create; + zend_ce_generator-serialize = zend_class_serialize_deny; + zend_ce_generator-unserialize = zend_class_unserialize_deny; /* get_iterator has to be assigned *after* implementing the inferface */ zend_class_implements(zend_ce_generator TSRMLS_CC, 1, zend_ce_iterator); -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Drop Generator::close() method: Zend/tests/generators/clone_with_foreach.phpt Zend/tests/generators/clone_with_stack.phpt Zend/tests/generators/clone_with_symbol_table.phpt Zend
Commit:05f10480c556ebe52bbef52cb2da5a0aca8ee070 Author:Nikita Popov ni...@php.net Mon, 20 Aug 2012 12:53:18 +0200 Parents: 7195a5b3768e519b8f50d131a8c7041a0b57959e Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=05f10480c556ebe52bbef52cb2da5a0aca8ee070 Log: Drop Generator::close() method Changed paths: M Zend/tests/generators/clone_with_foreach.phpt M Zend/tests/generators/clone_with_stack.phpt M Zend/tests/generators/clone_with_symbol_table.phpt M Zend/tests/generators/clone_with_this.phpt D Zend/tests/generators/close_inside_generator.phpt D Zend/tests/generators/generator_close.phpt M Zend/tests/generators/yield_during_method_call.phpt M Zend/zend_generators.c M Zend/zend_generators.h Diff: diff --git a/Zend/tests/generators/clone_with_foreach.phpt b/Zend/tests/generators/clone_with_foreach.phpt index b887338..b05ed07 100644 --- a/Zend/tests/generators/clone_with_foreach.phpt +++ b/Zend/tests/generators/clone_with_foreach.phpt @@ -20,7 +20,7 @@ $g2-next(); var_dump($g1-current()); var_dump($g2-current()); -$g1-close(); +unset($g1); $g2-next(); var_dump($g2-current()); diff --git a/Zend/tests/generators/clone_with_stack.phpt b/Zend/tests/generators/clone_with_stack.phpt index 673c0e5..5a8e6d8 100644 --- a/Zend/tests/generators/clone_with_stack.phpt +++ b/Zend/tests/generators/clone_with_stack.phpt @@ -10,7 +10,7 @@ function gen() { $g1 = gen(); $g1-rewind(); $g2 = clone $g1; -$g1-close(); +unset($g1); $g2-send(10); ? diff --git a/Zend/tests/generators/clone_with_symbol_table.phpt b/Zend/tests/generators/clone_with_symbol_table.phpt index 0d1bd4e..e1fefeb 100644 --- a/Zend/tests/generators/clone_with_symbol_table.phpt +++ b/Zend/tests/generators/clone_with_symbol_table.phpt @@ -19,7 +19,7 @@ function gen() { $g1 = gen(); $g1-rewind(); $g2 = clone $g1; -$g1-close(); +unset($g1); $g2-next(); ? diff --git a/Zend/tests/generators/clone_with_this.phpt b/Zend/tests/generators/clone_with_this.phpt index 66efd02..b242d85 100644 --- a/Zend/tests/generators/clone_with_this.phpt +++ b/Zend/tests/generators/clone_with_this.phpt @@ -16,7 +16,7 @@ class Test { $g1 = (new Test)-gen(); $g1-rewind(); // goto yield $g2 = clone $g1; -$g1-close(); +unset($g1); $g2-next(); ? diff --git a/Zend/tests/generators/close_inside_generator.phpt b/Zend/tests/generators/close_inside_generator.phpt deleted file mode 100644 index 1df64bf..000 --- a/Zend/tests/generators/close_inside_generator.phpt +++ /dev/null @@ -1,22 +0,0 @@ ---TEST-- -Calling close() during the exectution of the generator ---FILE-- -?php - -function gen() { -/* Pass the generator object itself in */ -$gen = yield; - -/* Close generator while it is currently running */ -$gen-close(); - - echo Still running; -} - -$gen = gen(); -$gen-send($gen); - -? ---EXPECTF-- -Warning: A generator cannot be closed while it is running in %s on line %d -Still running diff --git a/Zend/tests/generators/generator_close.phpt b/Zend/tests/generators/generator_close.phpt deleted file mode 100644 index 3dec285..000 --- a/Zend/tests/generators/generator_close.phpt +++ /dev/null @@ -1,32 +0,0 @@ ---TEST-- -Generator can be closed by calling -close() ---FILE-- -?php - -function allNumbers() { -for ($i = 0; true; ++$i) { -yield $i; -} -} - -$numbers = allNumbers(); - -foreach ($numbers as $n) { -var_dump($n); -if ($n == 9) { -$numbers-close(); -} -} - -? ---EXPECT-- -int(0) -int(1) -int(2) -int(3) -int(4) -int(5) -int(6) -int(7) -int(8) -int(9) diff --git a/Zend/tests/generators/yield_during_method_call.phpt b/Zend/tests/generators/yield_during_method_call.phpt index e8859ac..5fbe84f 100644 --- a/Zend/tests/generators/yield_during_method_call.phpt +++ b/Zend/tests/generators/yield_during_method_call.phpt @@ -20,13 +20,13 @@ $gen-send('foo'); // test resource cleanup $gen = gen(); $gen-rewind(); -$gen-close(); +unset($gen); // test cloning $g1 = gen(); $g1-rewind(); $g2 = clone $g1; -$g1-close(); +unset($g1); $g2-send('bar'); ? diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 716b0a7..41c6dfc 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -301,8 +301,6 @@ static zend_object_value zend_generator_create(zend_class_entry *class_type TSRM /* The key will be incremented on first use, so it'll start at 0 */ generator-largest_used_integer_key = -1; - generator-is_currently_running = 0; - zend_object_std_init(generator-std, class_type TSRMLS_CC); object.handle = zend_objects_store_put(generator, NULL, @@ -391,8 +389,6 @@ static void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */ zend_class_entry *original_scope = EG(scope); zend_class_entry *original_called_scope = EG(called_scope); - zend_bool original_is_currently_running = generator-is_currently_running;
[PHP-CVS] com php-src: Support trivial finally in generators (no yield, no return): Zend/zend_vm_def.h Zend/zend_vm_execute.h
Commit:ae716939eb500f962336d37b96069cb7452c25df Author:Nikita Popov ni...@php.net Mon, 13 Aug 2012 17:17:18 +0200 Parents: f4ce3646285fbdd3354ca86ae67857b6ee8f7e3a Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=ae716939eb500f962336d37b96069cb7452c25df Log: Support trivial finally in generators (no yield, no return) The finally clause is now properly run when an exception is thrown in the try-block. It is not yet run on `return` and also not run when the generator is claused within a try block. I'll add those two things as soon as laruence refactored the finally code. Changed paths: M Zend/zend_vm_def.h M Zend/zend_vm_execute.h Diff: diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 83ae5c5..49ee314 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2513,6 +2513,18 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) zend_bool nested; zend_op_array *op_array = EX(op_array); + /* Generators go throw a different cleanup process */ + if (EX(op_array)-fn_flags ZEND_ACC_GENERATOR) { + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + /* Close the generator to free up resources */ + zend_generator_close(generator, 1 TSRMLS_CC); + + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); + } + EG(current_execute_data) = EX(prev_execute_data); EG(opline_ptr) = NULL; if (!EG(active_symbol_table)) { @@ -5213,18 +5225,6 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) ZEND_VM_SET_OPCODE(EX(op_array)-opcodes[finally_op_num]); ZEND_VM_CONTINUE(); } else { - /* For generators skip the leave handler and return directly */ - if (EX(op_array)-fn_flags ZEND_ACC_GENERATOR) { - /* The generator object is stored in return_value_ptr_ptr */ - zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); - - /* Close the generator to free up resources */ - zend_generator_close(generator, 1 TSRMLS_CC); - - /* Pass execution back to handling code */ - ZEND_VM_RETURN(); - } - ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); } } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 495b520..94c2a7c 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -496,6 +496,18 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) zend_bool nested; zend_op_array *op_array = EX(op_array); + /* Generators go throw a different cleanup process */ + if (EX(op_array)-fn_flags ZEND_ACC_GENERATOR) { + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + /* Close the generator to free up resources */ + zend_generator_close(generator, 1 TSRMLS_CC); + + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); + } + EG(current_execute_data) = EX(prev_execute_data); EG(opline_ptr) = NULL; if (!EG(active_symbol_table)) { @@ -1177,18 +1189,6 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER ZEND_VM_SET_OPCODE(EX(op_array)-opcodes[finally_op_num]); ZEND_VM_CONTINUE(); } else { - /* For generators skip the leave handler and return directly */ - if (EX(op_array)-fn_flags ZEND_ACC_GENERATOR) { - /* The generator object is stored in return_value_ptr_ptr */ - zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); - - /* Close the generator to free up resources */ - zend_generator_close(generator, 1 TSRMLS_CC); - - /* Pass execution back to handling code */ - ZEND_VM_RETURN(); - } - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } } -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Fix implementation of Iterator interface: Zend/tests/generators/generator_in_multipleiterator.phpt Zend/zend_generators.c
Commit:268740d9848d435054ce73a8cfe36b2b732cd1f7 Author:Nikita Popov ni...@php.net Thu, 26 Jul 2012 17:07:24 +0200 Parents: 99f93dd9a846e3d615ec61c734aca2e7ee256600 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=268740d9848d435054ce73a8cfe36b2b732cd1f7 Log: Fix implementation of Iterator interface It looks like you have to implement the Iterator interface *before* assigning get_iterator. Otherwise the structure for user iterators isn't correctly zeroed out. Additionaly I'm setting class_entry-iterator_funcs.funcs now. Not sure if this is strictly necessary, but better safe than sorry ;) Changed paths: A Zend/tests/generators/generator_in_multipleiterator.phpt M Zend/zend_generators.c Diff: diff --git a/Zend/tests/generators/generator_in_multipleiterator.phpt b/Zend/tests/generators/generator_in_multipleiterator.phpt new file mode 100644 index 000..611dbc9 --- /dev/null +++ b/Zend/tests/generators/generator_in_multipleiterator.phpt @@ -0,0 +1,37 @@ +--TEST-- +Generators work properly in MultipleIterator +--FILE-- +?php + +function gen1() { +yield 'a'; +yield 'aa'; +} + +function gen2() { +yield 'b'; +yield 'bb'; +} + +$it = new MultipleIterator; +$it-attachIterator(gen1()); +$it-attachIterator(gen2()); + +foreach ($it as $values) { +var_dump($values); +} + +? +--EXPECT-- +array(2) { + [0]= + string(1) a + [1]= + string(1) b +} +array(2) { + [0]= + string(2) aa + [1]= + string(2) bb +} diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index d7ffb30..716b0a7 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -759,9 +759,11 @@ void zend_register_generator_ce(TSRMLS_D) /* {{{ */ zend_ce_generator = zend_register_internal_class(ce TSRMLS_CC); zend_ce_generator-ce_flags |= ZEND_ACC_FINAL_CLASS; zend_ce_generator-create_object = zend_generator_create; - zend_ce_generator-get_iterator = zend_generator_get_iterator; + /* get_iterator has to be assigned *after* implementing the inferface */ zend_class_implements(zend_ce_generator TSRMLS_CC, 1, zend_ce_iterator); + zend_ce_generator-get_iterator = zend_generator_get_iterator; + zend_ce_generator-iterator_funcs.funcs = zend_generator_iterator_functions; memcpy(zend_generator_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); zend_generator_handlers.get_constructor = zend_generator_get_constructor; -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Throw error also for return occuring before yield: Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt Zend/tests/generators/errors/generator_cannot_ret
Commit:134089372b94de2e3e8c2a1aba4cbc415c803d67 Author:Nikita Popov ni...@php.net Sun, 22 Jul 2012 20:11:09 +0200 Parents: 94b2ccae9ce95c4c71bb8db8ce75dcdf26df7d7a Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=134089372b94de2e3e8c2a1aba4cbc415c803d67 Log: Throw error also for return occuring before yield Previously only an error was thrown when return occured after yield. Also returns before the first yield would fail for by-ref generators. Now the error message is handled in pass_two, so all returns are checked. Changed paths: A Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt M Zend/tests/generators/errors/generator_cannot_return_error.phpt M Zend/zend_compile.c M Zend/zend_opcode.c Diff: diff --git a/Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt b/Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt new file mode 100644 index 000..ad618d2 --- /dev/null +++ b/Zend/tests/generators/errors/generator_cannot_return_before_yield_error.phpt @@ -0,0 +1,13 @@ +--TEST-- +Generators cannot return values (even before yield) +--FILE-- +?php + +function gen() { +return $foo; +yield; +} + +? +--EXPECTF-- +Fatal error: Generators cannot return values using return in %s on line 4 diff --git a/Zend/tests/generators/errors/generator_cannot_return_error.phpt b/Zend/tests/generators/errors/generator_cannot_return_error.phpt index 9a46bff..5114906 100644 --- a/Zend/tests/generators/errors/generator_cannot_return_error.phpt +++ b/Zend/tests/generators/errors/generator_cannot_return_error.phpt @@ -10,4 +10,4 @@ function gen() { ? --EXPECTF-- -Fatal error: Generators cannot return values using return in %s on line %d +Fatal error: Generators cannot return values using return in %s on line 5 diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index f0648a2..483ff30 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2611,14 +2611,9 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */ { zend_op *opline; int start_op_number, end_op_number; + zend_bool returns_reference = (CG(active_op_array)-fn_flags ZEND_ACC_RETURN_REFERENCE) != 0; - /* For generators the modifier applies to the yielded values, not the -* return value. */ - zend_bool returns_reference = (CG(active_op_array)-fn_flags ZEND_ACC_RETURN_REFERENCE) !(CG(active_op_array)-fn_flags ZEND_ACC_GENERATOR); - - if ((CG(active_op_array)-fn_flags ZEND_ACC_GENERATOR) expr != NULL) { - zend_error(E_COMPILE_ERROR, Generators cannot return values using \return\); - } + /* The error for use of return inside a generator is thrown in pass_two. */ if (do_end_vparse) { if (returns_reference !zend_is_function_or_method_call(expr)) { diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 65fa851..0042c37 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -532,6 +532,18 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC) case ZEND_JMP_SET_VAR: opline-op2.jmp_addr = op_array-opcodes[opline-op2.opline_num]; break; + case ZEND_RETURN: + case ZEND_RETURN_BY_REF: + if (op_array-fn_flags ZEND_ACC_GENERATOR) { + if (opline-op1_type != IS_CONST || Z_TYPE_P(opline-op1.zv) != IS_NULL) { + CG(zend_lineno) = opline-lineno; + zend_error(E_COMPILE_ERROR, Generators cannot return values using \return\); + } + if (opline-opcode == ZEND_RETURN_BY_REF) { + opline-opcode = ZEND_RETURN; + } + } + break; } ZEND_VM_SET_OPCODE_HANDLER(opline); opline++; -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Add T_YIELD in tokenizer_data.c: ext/tokenizer/tests/token_get_all_variation11.phpt ext/tokenizer/tests/token_get_all_variation13.phpt ext/tokenizer/tests/token_get_all_variatio
Commit:99f93dd9a846e3d615ec61c734aca2e7ee256600 Author:Nikita Popov ni...@php.net Sun, 22 Jul 2012 20:19:07 +0200 Parents: 134089372b94de2e3e8c2a1aba4cbc415c803d67 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=99f93dd9a846e3d615ec61c734aca2e7ee256600 Log: Add T_YIELD in tokenizer_data.c Also had to fix up some tokenizer tests that were affected by the token number changes. Changed paths: M ext/tokenizer/tests/token_get_all_variation11.phpt M ext/tokenizer/tests/token_get_all_variation13.phpt M ext/tokenizer/tests/token_get_all_variation17.phpt M ext/tokenizer/tests/token_get_all_variation4.phpt M ext/tokenizer/tests/token_get_all_variation5.phpt M ext/tokenizer/tests/token_get_all_variation6.phpt M ext/tokenizer/tests/token_get_all_variation8.phpt M ext/tokenizer/tokenizer_data.c Diff: diff --git a/ext/tokenizer/tests/token_get_all_variation11.phpt b/ext/tokenizer/tests/token_get_all_variation11.phpt index ecc8617..98d8996 100644 --- a/ext/tokenizer/tests/token_get_all_variation11.phpt +++ b/ext/tokenizer/tests/token_get_all_variation11.phpt @@ -130,7 +130,7 @@ array(49) { [6]= array(3) { [0]= -int(283) +int(%d) [1]= string(2) == [2]= @@ -273,7 +273,7 @@ array(49) { [27]= array(3) { [0]= -int(283) +int(%d) [1]= string(2) == [2]= diff --git a/ext/tokenizer/tests/token_get_all_variation13.phpt b/ext/tokenizer/tests/token_get_all_variation13.phpt index 9b2f3bc..6f85492 100644 --- a/ext/tokenizer/tests/token_get_all_variation13.phpt +++ b/ext/tokenizer/tests/token_get_all_variation13.phpt @@ -1005,7 +1005,7 @@ array(145) { [122]= array(3) { [0]= -int(288) +int(%d) [1]= string(10) instanceof [2]= diff --git a/ext/tokenizer/tests/token_get_all_variation17.phpt b/ext/tokenizer/tests/token_get_all_variation17.phpt index dccc4c9..f71444b 100644 --- a/ext/tokenizer/tests/token_get_all_variation17.phpt +++ b/ext/tokenizer/tests/token_get_all_variation17.phpt @@ -145,7 +145,7 @@ array(81) { [14]= array(3) { [0]= -int(283) +int(%d) [1]= string(2) == [2]= diff --git a/ext/tokenizer/tests/token_get_all_variation4.phpt b/ext/tokenizer/tests/token_get_all_variation4.phpt index 45e6f8a..6bc111e 100644 --- a/ext/tokenizer/tests/token_get_all_variation4.phpt +++ b/ext/tokenizer/tests/token_get_all_variation4.phpt @@ -339,7 +339,7 @@ array(89) { [38]= array(3) { [0]= -int(279) +int(%d) [1]= string(2) [2]= @@ -518,7 +518,7 @@ array(89) { [60]= array(3) { [0]= -int(278) +int(%d) [1]= string(2) || [2]= diff --git a/ext/tokenizer/tests/token_get_all_variation5.phpt b/ext/tokenizer/tests/token_get_all_variation5.phpt index 0068f28..681fb48 100644 --- a/ext/tokenizer/tests/token_get_all_variation5.phpt +++ b/ext/tokenizer/tests/token_get_all_variation5.phpt @@ -181,7 +181,7 @@ array(94) { [18]= array(3) { [0]= -int(277) +int(%d) [1]= string(2) += [2]= @@ -238,7 +238,7 @@ array(94) { [25]= array(3) { [0]= -int(276) +int(%d) [1]= string(2) -= [2]= @@ -295,7 +295,7 @@ array(94) { [32]= array(3) { [0]= -int(275) +int(%d) [1]= string(2) *= [2]= @@ -352,7 +352,7 @@ array(94) { [39]= array(3) { [0]= -int(274) +int(%d) [1]= string(2) /= [2]= @@ -409,7 +409,7 @@ array(94) { [46]= array(3) { [0]= -int(272) +int(%d) [1]= string(2) %= [2]= @@ -466,7 +466,7 @@ array(94) { [53]= array(3) { [0]= -int(271) +int(%d) [1]= string(2) = [2]= @@ -523,7 +523,7 @@ array(94) { [60]= array(3) { [0]= -int(270) +int(%d) [1]= string(2) |= [2]= @@ -580,7 +580,7 @@ array(94) { [67]= array(3) { [0]= -int(269) +int(%d) [1]= string(2) ^= [2]= @@ -637,7 +637,7 @@ array(94) { [74]= array(3) { [0]= -int(267) +int(%d) [1]= string(3) = [2]= @@ -694,7 +694,7 @@ array(94) { [81]= array(3) { [0]= -int(268) +int(%d) [1]= string(3) = [2]= @@ -751,7 +751,7 @@ array(94) { [88]= array(3) { [0]= -int(273) +int(%d) [1]= string(2) .= [2]= diff --git a/ext/tokenizer/tests/token_get_all_variation6.phpt b/ext/tokenizer/tests/token_get_all_variation6.phpt index 54936d0..6213dab 100644 --- a/ext/tokenizer/tests/token_get_all_variation6.phpt +++ b/ext/tokenizer/tests/token_get_all_variation6.phpt @@ -191,7 +191,7 @@ array(50) { [21]= array(3) { [0]= -int(287) +int(%d) [1]= string(2) [2]= @@ -277,7 +277,7 @@ array(50) { [32]= array(3) { [0]= -int(286) +int(%d) [1]= string(2) [2]= diff --git a/ext/tokenizer/tests/token_get_all_variation8.phpt
[PHP-CVS] com php-src: Remove reference restrictions from foreach: Zend/tests/errmsg_043.phpt Zend/tests/foreach_temp_array_expr_with_refs.phpt Zend/tests/generators/yield_by_reference.phpt Zend/zend_
Commit:de80e3ce4b5b7a9ec0cfdd0778e77027a7ebfcc2 Author:Nikita Popov ni...@php.net Sun, 22 Jul 2012 14:33:25 +0200 Parents: 80748631aa1c4193cbc68f8854d82e7a57817fe2 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=de80e3ce4b5b7a9ec0cfdd0778e77027a7ebfcc2 Log: Remove reference restrictions from foreach foreach only allowed variables to be traversed by reference. This never really made sense because a) Expressions like array($a, $b) can be meaningfully iterated by-ref b) Function calls can return by-ref (so they can also be meaningfully iterated) c) Iterators could at least in theory also be iterated by-ref (not sure if any iterator makes use of this) With by-ref generators the restriction makes even less sense, so I removed it altogether. Changed paths: D Zend/tests/errmsg_043.phpt A Zend/tests/foreach_temp_array_expr_with_refs.phpt M Zend/tests/generators/yield_by_reference.phpt M Zend/zend_compile.c M Zend/zend_language_parser.y D tests/lang/foreachLoop.008.phpt Diff: diff --git a/Zend/tests/errmsg_043.phpt b/Zend/tests/errmsg_043.phpt deleted file mode 100644 index 3de8bc2..000 --- a/Zend/tests/errmsg_043.phpt +++ /dev/null @@ -1,12 +0,0 @@ ---TEST-- -errmsg: cannot create references to temp array ---FILE-- -?php - -foreach (array(1,2,3) as $k=$v) { -} - -echo Done\n; -? ---EXPECTF-- -Fatal error: Cannot create references to elements of a temporary array expression in %s on line %d diff --git a/Zend/tests/foreach_temp_array_expr_with_refs.phpt b/Zend/tests/foreach_temp_array_expr_with_refs.phpt new file mode 100644 index 000..8978b7b --- /dev/null +++ b/Zend/tests/foreach_temp_array_expr_with_refs.phpt @@ -0,0 +1,18 @@ +--TEST-- +Temporary array expressions can be iterated by reference +--FILE-- +?php + +$a = 'a'; +$b = 'b'; + +foreach ([$a, $b] as $value) { +$value .= '-foo'; +} + +var_dump($a, $b); + +? +--EXPECT-- +string(5) a-foo +string(5) b-foo diff --git a/Zend/tests/generators/yield_by_reference.phpt b/Zend/tests/generators/yield_by_reference.phpt index 5a6c169..dba0791 100644 --- a/Zend/tests/generators/yield_by_reference.phpt +++ b/Zend/tests/generators/yield_by_reference.phpt @@ -9,24 +9,34 @@ function iter(array $array) { } } -$array = [1, 2, 3, 4, 5]; +$array = [1, 2, 3]; $iter = iter($array); foreach ($iter as $value) { $value *= -1; } var_dump($array); +$array = [1, 2, 3]; +foreach (iter($array) as $value) { +$value *= -1; +} +var_dump($array); + ? --EXPECT-- -array(5) { +array(3) { + [0]= + int(-1) + [1]= + int(-2) + [2]= + int(-3) +} +array(3) { [0]= int(-1) [1]= int(-2) [2]= - int(-3) - [3]= - int(-4) - [4]= - int(-5) + int(-3) } diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 51fc8c3..f0648a2 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -6317,9 +6317,7 @@ void zend_do_foreach_cont(znode *foreach_token, const znode *open_brackets_token if (value-EA ZEND_PARSED_REFERENCE_VARIABLE) { assign_by_ref = 1; - if (!(opline-1)-extended_value) { - zend_error(E_COMPILE_ERROR, Cannot create references to elements of a temporary array expression); - } + /* Mark extended_value for assign-by-reference */ opline-extended_value |= ZEND_FE_FETCH_BYREF; CG(active_op_array)-opcodes[foreach_token-u.op.opline_num].extended_value |= ZEND_FE_RESET_REFERENCE; diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index e5f31b5..4221752 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -312,7 +312,7 @@ unticked_statement: foreach_statement { zend_do_foreach_end($1, $4 TSRMLS_CC); } | T_FOREACH '(' expr_without_variable T_AS { zend_do_foreach_begin($1, $2, $3, $4, 0 TSRMLS_CC); } - variable foreach_optional_arg ')' { zend_check_writable_variable($6); zend_do_foreach_cont($1, $2, $4, $6, $7 TSRMLS_CC); } + foreach_variable foreach_optional_arg ')' { zend_do_foreach_cont($1, $2, $4, $6, $7 TSRMLS_CC); } foreach_statement { zend_do_foreach_end($1, $4 TSRMLS_CC); } | T_DECLARE { $1.u.op.opline_num = get_next_op_number(CG(active_op_array)); zend_do_declare_begin(TSRMLS_C); } '(' declare_list ')' declare_statement { zend_do_declare_end($1 TSRMLS_CC); } | ';' /* empty statement */ diff --git a/tests/lang/foreachLoop.008.phpt b/tests/lang/foreachLoop.008.phpt deleted file mode 100644 index 787f43b..000 --- a/tests/lang/foreachLoop.008.phpt +++ /dev/null @@ -1,10 +0,0 @@ ---TEST-- -Foreach loop tests - error case: reference to constant array, with key. ---FILE-- -?php -foreach (array(1,2) as $k=$v) { - var_dump($v); -} -? ---EXPECTF-- -Fatal error: Cannot create references to elements of a temporary array
[PHP-CVS] com php-src: Add some more tests: Zend/tests/generators/fibonacci.phpt Zend/tests/generators/generator_closure.phpt Zend/tests/generators/generator_closure_with_this.phpt Zend/tests/generato
Commit:1f70a4c5fea97aa577aa5d9ee5f33d91d70e690d Author:Nikita Popov ni...@php.net Fri, 20 Jul 2012 17:40:04 +0200 Parents: 612c2490b7973d71d472860ade48d7ab342b5911 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=1f70a4c5fea97aa577aa5d9ee5f33d91d70e690d Log: Add some more tests Changed paths: A Zend/tests/generators/fibonacci.phpt A Zend/tests/generators/generator_closure.phpt A Zend/tests/generators/generator_closure_with_this.phpt A Zend/tests/generators/generator_static_method.phpt Diff: diff --git a/Zend/tests/generators/fibonacci.phpt b/Zend/tests/generators/fibonacci.phpt new file mode 100644 index 000..35b3135 --- /dev/null +++ b/Zend/tests/generators/fibonacci.phpt @@ -0,0 +1,36 @@ +--TEST-- +Creating an infinite fibonacci list using a generator +--FILE-- +?php + +function fib() { +list($a, $b) = [1, 1]; +while (true) { +yield $b; +list($a, $b) = [$b, $a + $b]; +} +} + +foreach (fib() as $n) { +if ($n 1000) break; + +var_dump($n); +} + +? +--EXPECT-- +int(1) +int(2) +int(3) +int(5) +int(8) +int(13) +int(21) +int(34) +int(55) +int(89) +int(144) +int(233) +int(377) +int(610) +int(987) diff --git a/Zend/tests/generators/generator_closure.phpt b/Zend/tests/generators/generator_closure.phpt new file mode 100644 index 000..bf80066 --- /dev/null +++ b/Zend/tests/generators/generator_closure.phpt @@ -0,0 +1,20 @@ +--TEST-- +Closures can be generators +--FILE-- +?php + +$genFactory = function() { +yield 1; +yield 2; +yield 3; +}; + +foreach ($genFactory() as $value) { +var_dump($value); +} + +? +--EXPECT-- +int(1) +int(2) +int(3) diff --git a/Zend/tests/generators/generator_closure_with_this.phpt b/Zend/tests/generators/generator_closure_with_this.phpt new file mode 100644 index 000..d5a4861 --- /dev/null +++ b/Zend/tests/generators/generator_closure_with_this.phpt @@ -0,0 +1,20 @@ +--TEST-- +Non-static closures can be generators +--FILE-- +?php + +class Test { +public function getGenFactory() { +return function() { +yield $this; +}; +} +} + +$genFactory = (new Test)-getGenFactory(); +var_dump($genFactory()-current()); + +? +--EXPECT-- +object(Test)#1 (0) { +} diff --git a/Zend/tests/generators/generator_static_method.phpt b/Zend/tests/generators/generator_static_method.phpt new file mode 100644 index 000..cd9b450 --- /dev/null +++ b/Zend/tests/generators/generator_static_method.phpt @@ -0,0 +1,29 @@ +--TEST-- +A static method can be a generator +--FILE-- +?php + +class Test { +public static function gen() { +var_dump(get_class()); +var_dump(get_called_class()); +yield 1; +yield 2; +yield 3; +} +} + +class ExtendedTest extends Test { +} + +foreach (ExtendedTest::gen() as $i) { +var_dump($i); +} + +? +--EXPECT-- +string(4) Test +string(12) ExtendedTest +int(1) +int(2) +int(3) -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] svn: /SVNROOT/ global_avail
felipe Sat, 01 Sep 2012 17:27:21 + Revision: http://svn.php.net/viewvc?view=revisionrevision=327420 Log: - Granted Zend karma to Nikita Popov (nikic) Changed paths: U SVNROOT/global_avail Modified: SVNROOT/global_avail === --- SVNROOT/global_avail2012-09-01 14:51:06 UTC (rev 327419) +++ SVNROOT/global_avail2012-09-01 17:27:21 UTC (rev 327420) @@ -48,7 +48,7 @@ avail|loudi,mrkschan,pmjones,irker|phd.git,web/doc.git,web/doc-editor.git # People who work on the Engine - not people with just tests access -avail|andi,zeev,andrei,stas,sterling,sas,derick,sebastian,phanto,jani,hirokawa,fujimoto,rvenkat,sesser,kalowsky,iliaa,hyanantha,georg,wez,edink,helly,hholzgra,imajes,gschlossnagle,moriyoshi,dmitry,jon,pollita,tony2001,johannes,bjori,davidw,nicholsr,wharmby,felipe,robinf,scottmac,nlopess,mattwil,colder,lbarnaud,pajoye,cseiler,dsp,shire,gron,gopalv,gwynne,pierrick,laruence,cataphract,ab,lstrojny|php-src.git/Zend,php-src.git/TSRM +avail|andi,zeev,andrei,stas,sterling,sas,derick,sebastian,phanto,jani,hirokawa,fujimoto,rvenkat,sesser,kalowsky,iliaa,hyanantha,georg,wez,edink,helly,hholzgra,imajes,gschlossnagle,moriyoshi,dmitry,jon,pollita,tony2001,johannes,bjori,davidw,nicholsr,wharmby,felipe,robinf,scottmac,nlopess,mattwil,colder,lbarnaud,pajoye,cseiler,dsp,shire,gron,gopalv,gwynne,pierrick,laruence,cataphract,ab,lstrojny,nikic|php-src.git/Zend,php-src.git/TSRM # The PHP Documentation Group maintains the documentation and its # translations. -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Forgot to git add two tests: Zend/tests/generators/close_inside_generator.phpt Zend/tests/generators/func_get_args.phpt
Commit:5a9bddba6699d056383107728392048cd7ccb598 Author:Nikita Popov ni...@php.net Mon, 25 Jun 2012 21:41:50 +0200 Parents: ab75ed6ba9b5eace710976bf76d631728d4bb403 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=5a9bddba6699d056383107728392048cd7ccb598 Log: Forgot to git add two tests Changed paths: A Zend/tests/generators/close_inside_generator.phpt A Zend/tests/generators/func_get_args.phpt Diff: diff --git a/Zend/tests/generators/close_inside_generator.phpt b/Zend/tests/generators/close_inside_generator.phpt new file mode 100644 index 000..41a91c9 --- /dev/null +++ b/Zend/tests/generators/close_inside_generator.phpt @@ -0,0 +1,22 @@ +--TEST-- +Calling close() during the exectution of the generator +--FILE-- +?php + +function *gen() { +/* Pass the generator object itself in */ +$gen = yield; + +/* Close generator while it is currently running */ +$gen-close(); + + echo Still running; +} + +$gen = gen(); +$gen-send($gen); + +? +--EXPECTF-- +Warning: A generator cannot be closed while it is running in %s on line %d +Still running diff --git a/Zend/tests/generators/func_get_args.phpt b/Zend/tests/generators/func_get_args.phpt new file mode 100644 index 000..7ce7fb0 --- /dev/null +++ b/Zend/tests/generators/func_get_args.phpt @@ -0,0 +1,20 @@ +--TEST-- +func_get_args() can be used inside generator functions +--FILE-- +?php + +function *gen() { +var_dump(func_get_args()); +} + +$gen = gen(foo, bar); +$gen-rewind(); + +? +--EXPECT-- +array(2) { + [0]= + string(3) foo + [1]= + string(3) bar +} -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Implement get_iterator: Zend/zend_generators.c
Commit:04e781f0e4a4ea879c5e85b8d209b9b44cc32f8d Author:Nikita Popov ni...@php.net Sat, 23 Jun 2012 01:28:16 +0200 Parents: 1d3f37ddedc931d700a4e1135f63e094df88dbc4 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=04e781f0e4a4ea879c5e85b8d209b9b44cc32f8d Log: Implement get_iterator This implements the get_iterator handler for Generator objects, thus making direct foreach() iteration significantly faster. Changed paths: M Zend/zend_generators.c Diff: diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index b7538e7..10d91f5 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -564,6 +564,114 @@ ZEND_METHOD(Generator, close) } /* }}} */ +/* get_iterator implementation */ + +typedef struct _zend_generator_iterator { + zend_object_iterator intern; + zend_generator *generator; +} zend_generator_iterator; + +static void zend_generator_iterator_dtor(zend_object_iterator *iterator TSRMLS_DC) /* {{{ */ +{ + zval_ptr_dtor((zval **) iterator-data); + efree(iterator); +} +/* }}} */ + +static int zend_generator_iterator_valid(zend_object_iterator *iterator TSRMLS_DC) /* {{{ */ +{ + zval *object = (zval *) iterator-data; + zend_generator *generator = ((zend_generator_iterator *) iterator)-generator; + + zend_generator_ensure_initialized(object, generator TSRMLS_CC); + + return generator-value != NULL ? SUCCESS : FAILURE; +} +/* }}} */ + +static void zend_generator_iterator_get_data(zend_object_iterator *iterator, zval ***data TSRMLS_DC) /* {{{ */ +{ + zval *object = (zval *) iterator-data; + zend_generator *generator = ((zend_generator_iterator *) iterator)-generator; + + zend_generator_ensure_initialized(object, generator TSRMLS_CC); + + if (generator-value) { + *data = generator-value; + } else { + *data = NULL; + } +} +/* }}} */ + +static int zend_generator_iterator_get_key(zend_object_iterator *iterator, char **str_key, uint *str_key_len, ulong *int_key TSRMLS_DC) /* {{{ */ +{ + zval *object = (zval *) iterator-data; + zend_generator *generator = ((zend_generator_iterator *) iterator)-generator; + + zend_generator_ensure_initialized(object, generator TSRMLS_CC); + + if (!generator-key) { + return HASH_KEY_NON_EXISTANT; + } + + if (Z_TYPE_P(generator-key) == IS_LONG) { + *int_key = Z_LVAL_P(generator-key); + return HASH_KEY_IS_LONG; + } + + if (Z_TYPE_P(generator-key) == IS_STRING) { + *str_key = estrndup(Z_STRVAL_P(generator-key), Z_STRLEN_P(generator-key)); + *str_key_len = Z_STRLEN_P(generator-key) + 1; + return HASH_KEY_IS_STRING; + } + + /* Waiting for Etienne's patch to allow arbitrary zval keys. Until then +* error out on non-int and non-string keys. */ + zend_error(E_ERROR, Currently only int and string keys can be yielded); +} +/* }}} */ + +static void zend_generator_iterator_move_forward(zend_object_iterator *iterator TSRMLS_DC) /* {{{ */ +{ + zval *object = (zval *) iterator-data; + zend_generator *generator = ((zend_generator_iterator *) iterator)-generator; + + zend_generator_ensure_initialized(object, generator TSRMLS_CC); + + zend_generator_resume(object, generator TSRMLS_CC); +} +/* }}} */ + +static zend_object_iterator_funcs zend_generator_iterator_functions = { + zend_generator_iterator_dtor, + zend_generator_iterator_valid, + zend_generator_iterator_get_data, + zend_generator_iterator_get_key, + zend_generator_iterator_move_forward, + NULL +}; + +zend_object_iterator *zend_generator_get_iterator(zend_class_entry *ce, zval *object, int by_ref TSRMLS_DC) /* {{{ */ +{ + zend_generator_iterator *iterator; + + if (by_ref) { + zend_error(E_ERROR, By reference iteration of generators is currently not supported); + } + + iterator = emalloc(sizeof(zend_generator_iterator)); + iterator-intern.funcs = zend_generator_iterator_functions; + + Z_ADDREF_P(object); + iterator-intern.data = (void *) object; + + iterator-generator = zend_object_store_get_object(object TSRMLS_CC); + + return (zend_object_iterator *) iterator; +} +/* }}} */ + ZEND_BEGIN_ARG_INFO(arginfo_generator_void, 0) ZEND_END_ARG_INFO() @@ -590,6 +698,7 @@ void zend_register_generator_ce(TSRMLS_D) /* {{{ */ zend_ce_generator = zend_register_internal_class(ce TSRMLS_CC); zend_ce_generator-ce_flags |= ZEND_ACC_FINAL_CLASS; zend_ce_generator-create_object = zend_generator_create; + zend_ce_generator-get_iterator = zend_generator_get_iterator; zend_class_implements(zend_ce_generator TSRMLS_CC, 1, zend_ce_iterator); -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Disallow closing a generator during its execution: Zend/zend_generators.c Zend/zend_generators.h
Commit:ab75ed6ba9b5eace710976bf76d631728d4bb403 Author:Nikita Popov ni...@php.net Sat, 23 Jun 2012 16:08:15 +0200 Parents: 14766e1417c721d9643f6a2a785db3e88b565814 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=ab75ed6ba9b5eace710976bf76d631728d4bb403 Log: Disallow closing a generator during its execution If a generator is closed while it is running an E_WARNING is thrown and the call is ignored. Maybe a fatal error should be thrown instead? Changed paths: M Zend/zend_generators.c M Zend/zend_generators.h Diff: diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 487975e..bccbb48 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -300,6 +300,8 @@ static zend_object_value zend_generator_create(zend_class_entry *class_type TSRM /* The key will be incremented on first use, so it'll start at 0 */ generator-largest_used_integer_key = -1; + generator-is_currently_running = 0; + zend_object_std_init(generator-std, class_type TSRMLS_CC); object.handle = zend_objects_store_put(generator, NULL, @@ -339,6 +341,8 @@ static void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */ zend_class_entry *original_scope = EG(scope); zend_class_entry *original_called_scope = EG(called_scope); + zend_bool original_is_currently_running = generator-is_currently_running; + /* Remember the current stack position so we can back up pushed args */ generator-original_stack_top = zend_vm_stack_top(TSRMLS_C); @@ -363,6 +367,8 @@ static void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */ EG(scope) = generator-execute_data-current_scope; EG(called_scope) = generator-execute_data-current_called_scope; + generator-is_currently_running = 1; + /* We want the backtrace to look as if the generator function was * called from whatever method we are current running (e.g. next()). * The first prev_execute_data contains an additional stack frame, @@ -387,6 +393,8 @@ static void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */ EG(scope) = original_scope; EG(called_scope) = original_called_scope; + generator-is_currently_running = original_is_currently_running; + /* The stack top before and after the execution differ, i.e. there are * arguments pushed to the stack. */ if (generator-original_stack_top != zend_vm_stack_top(TSRMLS_C)) { @@ -549,6 +557,11 @@ ZEND_METHOD(Generator, close) generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + if (generator-is_currently_running) { + zend_error(E_WARNING, A generator cannot be closed while it is running); + return; + } + zend_generator_close(generator, 0 TSRMLS_CC); } /* }}} */ diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h index 89193bb..73d85287 100644 --- a/Zend/zend_generators.h +++ b/Zend/zend_generators.h @@ -46,6 +46,10 @@ typedef struct _zend_generator { temp_variable *send_target; /* Largest used integer key for auto-incrementing keys */ long largest_used_integer_key; + + /* We need to know whether the generator is currently executed to avoid it +* being closed while still running */ + zend_bool is_currently_running; } zend_generator; extern ZEND_API zend_class_entry *zend_ce_generator; -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Pass zend_generator directly to Zend VM: Zend/zend_generators.c Zend/zend_vm_def.h Zend/zend_vm_execute.h
Commit:14766e1417c721d9643f6a2a785db3e88b565814 Author:Nikita Popov ni...@php.net Sat, 23 Jun 2012 14:43:52 +0200 Parents: 04e781f0e4a4ea879c5e85b8d209b9b44cc32f8d Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=14766e1417c721d9643f6a2a785db3e88b565814 Log: Pass zend_generator directly to Zend VM Previously the zval* of the generator was passed into the VM by misusing EG(return_value_ptr_ptr). Now the zend_generator* itself is directly passed in. This saves us from always having to pass the zval* around everywhere. Changed paths: M Zend/zend_generators.c M Zend/zend_vm_def.h M Zend/zend_vm_execute.h diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 10d91f5..487975e 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -321,7 +321,7 @@ static zend_function *zend_generator_get_constructor(zval *object TSRMLS_DC) /* } /* }}} */ -static void zend_generator_resume(zval *object, zend_generator *generator TSRMLS_DC) /* {{{ */ +static void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */ { /* The generator is already closed, thus can't resume */ if (!generator-execute_data) { @@ -352,7 +352,7 @@ static void zend_generator_resume(zval *object, zend_generator *generator TSRMLS /* We (mis)use the return_value_ptr_ptr to provide the generator object * to the executor, so YIELD will be able to set the yielded value */ - EG(return_value_ptr_ptr) = object; + EG(return_value_ptr_ptr) = (zval **) generator; /* Set executor globals */ EG(current_execute_data) = generator-execute_data; @@ -399,10 +399,10 @@ static void zend_generator_resume(zval *object, zend_generator *generator TSRMLS } /* }}} */ -static void zend_generator_ensure_initialized(zval *object, zend_generator *generator TSRMLS_DC) /* {{{ */ +static void zend_generator_ensure_initialized(zend_generator *generator TSRMLS_DC) /* {{{ */ { if (!generator-value) { - zend_generator_resume(object, generator TSRMLS_CC); + zend_generator_resume(generator TSRMLS_CC); } } /* }}} */ @@ -411,17 +411,15 @@ static void zend_generator_ensure_initialized(zval *object, zend_generator *gene * Rewind the generator */ ZEND_METHOD(Generator, rewind) { - zval *object; zend_generator *generator; if (zend_parse_parameters_none() == FAILURE) { return; } - object = getThis(); - generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC); + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); - zend_generator_ensure_initialized(object, generator TSRMLS_CC); + zend_generator_ensure_initialized(generator TSRMLS_CC); /* Generators aren't rewindable, so rewind() only has to make sure that * the generator is initialized, nothing more */ @@ -432,17 +430,15 @@ ZEND_METHOD(Generator, rewind) * Check whether the generator is valid */ ZEND_METHOD(Generator, valid) { - zval *object; zend_generator *generator; if (zend_parse_parameters_none() == FAILURE) { return; } - object = getThis(); - generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC); + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); - zend_generator_ensure_initialized(object, generator TSRMLS_CC); + zend_generator_ensure_initialized(generator TSRMLS_CC); RETURN_BOOL(generator-value != NULL); } @@ -452,17 +448,15 @@ ZEND_METHOD(Generator, valid) * Get the current value */ ZEND_METHOD(Generator, current) { - zval *object; zend_generator *generator; if (zend_parse_parameters_none() == FAILURE) { return; } - object = getThis(); - generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC); + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); - zend_generator_ensure_initialized(object, generator TSRMLS_CC); + zend_generator_ensure_initialized(generator TSRMLS_CC); if (generator-value) { RETURN_ZVAL(generator-value, 1, 0); @@ -474,17 +468,15 @@ ZEND_METHOD(Generator, current) * Get the current key */ ZEND_METHOD(Generator, key) { - zval *object; zend_generator *generator; if (zend_parse_parameters_none() == FAILURE) { return; } - object = getThis(); - generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC); + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); - zend_generator_ensure_initialized(object, generator TSRMLS_CC); +
[PHP-CVS] com php-src: Add sceleton for yield* expression: Zend/tests/generators/errors/yield_in_normal_function_error.phpt Zend/tests/generators/errors/yield_outside_function_error.phpt Zend/zend_com
Commit:d939d2dee58bf894ae9af631bdee173243157068 Author:Nikita Popov ni...@php.net Mon, 11 Jun 2012 23:59:46 +0200 Parents: f169b26dd7a4047996ab1284e649fda0cfb1a10b Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=d939d2dee58bf894ae9af631bdee173243157068 Log: Add sceleton for yield* expression This does not yet actually implement any delegation. Changed paths: M Zend/tests/generators/errors/yield_in_normal_function_error.phpt M Zend/tests/generators/errors/yield_outside_function_error.phpt M Zend/zend_compile.c M Zend/zend_compile.h M Zend/zend_generators.c M Zend/zend_language_parser.y M Zend/zend_language_scanner.c M Zend/zend_language_scanner_defs.h M Zend/zend_vm_def.h M Zend/zend_vm_execute.h M Zend/zend_vm_opcodes.h diff --git a/Zend/tests/generators/errors/yield_in_normal_function_error.phpt b/Zend/tests/generators/errors/yield_in_normal_function_error.phpt index 802510d..4670a41 100644 --- a/Zend/tests/generators/errors/yield_in_normal_function_error.phpt +++ b/Zend/tests/generators/errors/yield_in_normal_function_error.phpt @@ -9,4 +9,4 @@ function foo() { ? --EXPECTF-- -Fatal error: The yield statement can only be used inside a generator function in %s on line %d +Fatal error: The yield expression can only be used inside a generator function in %s on line %d diff --git a/Zend/tests/generators/errors/yield_outside_function_error.phpt b/Zend/tests/generators/errors/yield_outside_function_error.phpt index fd7169d..5f47e75 100644 --- a/Zend/tests/generators/errors/yield_outside_function_error.phpt +++ b/Zend/tests/generators/errors/yield_outside_function_error.phpt @@ -7,4 +7,4 @@ yield Test; ? --EXPECTF-- -Fatal error: The yield statement can only be used inside a generator function in %s on line %d +Fatal error: The yield expression can only be used inside a generator function in %s on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index da61b76..35ff2bb 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2667,7 +2667,7 @@ void zend_do_yield(znode *result, const znode *value, const znode *key TSRMLS_DC zend_op *opline; if ((CG(active_op_array)-fn_flags ZEND_ACC_GENERATOR) == 0) { - zend_error(E_COMPILE_ERROR, The \yield\ statement can only be used inside a generator function); + zend_error(E_COMPILE_ERROR, The \yield\ expression can only be used inside a generator function); } opline = get_next_op(CG(active_op_array) TSRMLS_CC); @@ -2692,6 +2692,27 @@ void zend_do_yield(znode *result, const znode *value, const znode *key TSRMLS_DC } /* }}} */ +void zend_do_delegate_yield(znode *result, const znode *value TSRMLS_DC) /* {{{ */ +{ + zend_op *opline; + + if ((CG(active_op_array)-fn_flags ZEND_ACC_GENERATOR) == 0) { + zend_error(E_COMPILE_ERROR, The \yield*\ expression can only be used inside a generator function); + } + + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + + opline-opcode = ZEND_DELEGATE_YIELD; + + SET_NODE(opline-op1, value); + SET_UNUSED(opline-op2); + + opline-result_type = IS_VAR; + opline-result.var = get_temporary_variable(CG(active_op_array)); + GET_NODE(result, opline-result); +} +/* }}} */ + void zend_do_suspend_if_generator(TSRMLS_D) /* {{{ */ { zend_op *opline; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index ec86ed8..d0587d1 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -491,6 +491,7 @@ int zend_do_begin_class_member_function_call(znode *class_name, znode *method_na void zend_do_end_function_call(znode *function_name, znode *result, const znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC); void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC); void zend_do_yield(znode *result, const znode *value, const znode *key TSRMLS_DC); +void zend_do_delegate_yield(znode *result, const znode *value TSRMLS_DC); void zend_do_suspend_if_generator(TSRMLS_D); void zend_do_handle_exception(TSRMLS_D); diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 6efa710..f8374b8 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -245,7 +245,7 @@ static void zend_generator_clone_storage(zend_generator *orig, zend_generator ** } /* Update the send_target to use the temporary variable with the same -* offset as the original generator, but in out temporary variable +* offset as the original generator, but in our temporary variable * memory segment. */ if (orig-send_target) { size_t offset = (char *) orig-send_target - (char *) execute_data-Ts; @@ -536,7 +536,6 @@ ZEND_METHOD(Generator, send) /* The sent value was initialized to NULL, so dtor that */
[PHP-CVS] com php-src: Fix thread safe build: Zend/zend_execute.c Zend/zend_execute.h Zend/zend_generators.c Zend/zend_vm_def.h Zend/zend_vm_execute.h
Commit:6233408a2a51389a2bbd250c5900d395648e897f Author:Nikita Popov ni...@php.net Wed, 20 Jun 2012 21:31:23 +0200 Parents: d939d2dee58bf894ae9af631bdee173243157068 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=6233408a2a51389a2bbd250c5900d395648e897f Log: Fix thread safe build Changed paths: M Zend/zend_execute.c M Zend/zend_execute.h M Zend/zend_generators.c M Zend/zend_vm_def.h M Zend/zend_vm_execute.h Diff: diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index c7ef212..0e40650 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1538,7 +1538,7 @@ ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const t return get_zval_ptr_ptr(op_type, node, Ts, should_free, type); } -void zend_clean_and_cache_symbol_table(HashTable *symbol_table) /* {{{ */ +void zend_clean_and_cache_symbol_table(HashTable *symbol_table TSRMLS_DC) /* {{{ */ { if (EG(symtable_cache_ptr) = EG(symtable_cache_limit)) { zend_hash_destroy(symbol_table); diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 48f46bb..92160b5 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -432,7 +432,7 @@ ZEND_API zval **zend_get_zval_ptr_ptr(int op_type, const znode_op *node, const t ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS); -void zend_clean_and_cache_symbol_table(HashTable *symbol_table); +void zend_clean_and_cache_symbol_table(HashTable *symbol_table TSRMLS_DC); void zend_free_compiled_variables(zval ***CVs, int num); void **zend_copy_arguments(void **arguments_end); diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index f8374b8..b7538e7 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -34,7 +34,7 @@ void zend_generator_close(zend_generator *generator, zend_bool finished_executio if (!execute_data-symbol_table) { zend_free_compiled_variables(execute_data-CVs, execute_data-op_array-last_var); } else { - zend_clean_and_cache_symbol_table(execute_data-symbol_table); + zend_clean_and_cache_symbol_table(execute_data-symbol_table TSRMLS_CC); } if (execute_data-current_this) { @@ -560,7 +560,7 @@ ZEND_METHOD(Generator, close) generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); - zend_generator_close(generator, 0); + zend_generator_close(generator, 0 TSRMLS_CC); } /* }}} */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index e5d8a76..fea1f40 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2572,7 +2572,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) EG(active_op_array) = EX(op_array); EG(return_value_ptr_ptr) = EX(original_return_value); if (EG(active_symbol_table)) { - zend_clean_and_cache_symbol_table(EG(active_symbol_table)); + zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); } EG(active_symbol_table) = EX(symbol_table); @@ -2717,7 +2717,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY) EG(active_op_array) = EX(op_array); EG(return_value_ptr_ptr) = EX(original_return_value); if (EG(active_symbol_table)) { - zend_clean_and_cache_symbol_table(EG(active_symbol_table)); + zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); } EG(active_symbol_table) = EX(symbol_table); } else { /* ZEND_OVERLOADED_FUNCTION */ @@ -5265,7 +5265,7 @@ ZEND_VM_HANDLER(159, ZEND_SUSPEND_AND_RETURN_GENERATOR, ANY, ANY) if (!EG(active_symbol_table)) { zend_free_compiled_variables(EX_CVs(), execute_data-op_array-last_var); } else { - zend_clean_and_cache_symbol_table(EG(active_symbol_table)); + zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); } efree(execute_data); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 6f1a885..0f965c5 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -556,7 +556,7 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) EG(active_op_array) = EX(op_array); EG(return_value_ptr_ptr) = EX(original_return_value); if (EG(active_symbol_table)) { - zend_clean_and_cache_symbol_table(EG(active_symbol_table)); + zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC); }
[PHP-CVS] com php-src: Fix backtraces and func_get_args(): Zend/tests/generators/backtrace.phpt Zend/zend_execute.c Zend/zend_execute.h Zend/zend_generators.c Zend/zend_vm_def.h Zend/zend_vm_execute.h
Commit:f169b26dd7a4047996ab1284e649fda0cfb1a10b Author:Nikita Popov ni...@php.net Sat, 9 Jun 2012 00:40:47 +0200 Parents: 40760ecb90d1b024c76862e33d13d40137650af7 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=f169b26dd7a4047996ab1284e649fda0cfb1a10b Log: Fix backtraces and func_get_args() To make the generator function show up in backtraces one has to insert an additional execute_data into the chain, as prev_execute_data-function_state is used to determine the called function. Adding the additional stack frame is also required for func_get_args(), as the arguments are fetched from there too. The arguments have to be copied in order to keep them around. Due to the way they are saved doing so is quite ugly, so I added another function zend_copy_arguments to zend_execute.c which handles this. Changed paths: M Zend/tests/generators/backtrace.phpt M Zend/zend_execute.c M Zend/zend_execute.h M Zend/zend_generators.c M Zend/zend_vm_def.h M Zend/zend_vm_execute.h diff --git a/Zend/tests/generators/backtrace.phpt b/Zend/tests/generators/backtrace.phpt index cbf8de1..77976f9 100644 --- a/Zend/tests/generators/backtrace.phpt +++ b/Zend/tests/generators/backtrace.phpt @@ -7,7 +7,7 @@ function f1() { debug_print_backtrace(); } -function *f2() { +function *f2($arg1, $arg2) { f1(); } @@ -15,11 +15,12 @@ function f3($gen) { $gen-rewind(); // trigger run } -$gen = f2(); +$gen = f2('foo', 'bar'); f3($gen); ? --EXPECTF-- #0 f1() called at [%s:%d] -#1 Generator-rewind() called at [%s:%d] -#2 f3(Generator Object ()) called at [%s:%d] +#1 f2(foo, bar) called at [%s:%d] +#2 Generator-rewind() called at [%s:%d] +#3 f3(Generator Object ()) called at [%s:%d] diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 9031fb5..c7ef212 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -1563,6 +1563,25 @@ void zend_free_compiled_variables(zval ***CVs, int num) /* {{{ */ } /* }}} */ +void** zend_copy_arguments(void **arguments_end) /* {{{ */ +{ + int arguments_count = (int) (zend_uintptr_t) *arguments_end; + size_t arguments_size = (arguments_count + 1) * sizeof(void **); + void **arguments_start = arguments_end - arguments_count; + void **copied_arguments_start = emalloc(arguments_size); + void **copied_arguments_end = copied_arguments_start + arguments_count; + int i; + + memcpy(copied_arguments_start, arguments_start, arguments_size); + + for (i = 0; i arguments_count; i++) { + Z_ADDREF_P((zval *) arguments_start[i]); + } + + return copied_arguments_end; +} +/* }}} */ + /* * Local variables: * tab-width: 4 diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 6dfd607..48f46bb 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -434,6 +434,7 @@ ZEND_API int zend_do_fcall(ZEND_OPCODE_HANDLER_ARGS); void zend_clean_and_cache_symbol_table(HashTable *symbol_table); void zend_free_compiled_variables(zval ***CVs, int num); +void **zend_copy_arguments(void **arguments_end); #define CACHED_PTR(num) \ EG(active_op_array)-run_time_cache[(num)] diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index b5642dd..6efa710 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -94,6 +94,28 @@ void zend_generator_close(zend_generator *generator, zend_bool finished_executio efree(generator-backed_up_stack); } + /* We have added an additional stack frame in prev_execute_data, so we +* have to free it. It also contains the arguments passed to the +* generator (for func_get_args) so those have to be freed too. */ + { + zend_execute_data *prev_execute_data = execute_data-prev_execute_data; + void **arguments = prev_execute_data-function_state.arguments; + + if (arguments) { + int arguments_count = (int) (zend_uintptr_t) *arguments; + zval **arguments_start = (zval **) (arguments - arguments_count); + int i; + + for (i = 0; i arguments_count; ++i) { + zval_ptr_dtor(arguments_start + i); + } + + efree(arguments_start); + } + + efree(prev_execute_data); + } + efree(execute_data); generator-execute_data = NULL; } @@ -240,6 +262,18 @@ static void zend_generator_clone_storage(zend_generator *orig, zend_generator ** if (execute_data-object) { Z_ADDREF_P(execute_data-object); } + + /* Prev execute data contains an additional stack frame (for proper)
[PHP-CVS] com php-src: Fix cloning of generator methods: Zend/tests/generators/clone_with_this.phpt Zend/zend_generators.c
Commit:40760ecb90d1b024c76862e33d13d40137650af7 Author:Nikita Popov ni...@php.net Sun, 3 Jun 2012 02:40:03 +0200 Parents: bf82f46ea9028faa3830525d2462effe7d08600d Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=40760ecb90d1b024c76862e33d13d40137650af7 Log: Fix cloning of generator methods Forgot to add a reference to the this variable Changed paths: A Zend/tests/generators/clone_with_this.phpt M Zend/zend_generators.c Diff: diff --git a/Zend/tests/generators/clone_with_this.phpt b/Zend/tests/generators/clone_with_this.phpt new file mode 100644 index 000..b0f28be --- /dev/null +++ b/Zend/tests/generators/clone_with_this.phpt @@ -0,0 +1,24 @@ +--TEST-- +Cloning a generator method (with this) +--FILE-- +?php + +class Test { +protected $foo; + +public function *gen() { +$this-foo = 'bar'; +yield; // interrupt +var_dump($this-foo); +} +} + +$g1 = (new Test)-gen(); +$g1-rewind(); // goto yield +$g2 = clone $g1; +$g1-close(); +$g2-next(); + +? +--EXPECT-- +string(3) bar diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index a3277e6..b5642dd 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -233,6 +233,10 @@ static void zend_generator_clone_storage(zend_generator *orig, zend_generator ** Z_ADDREF_P(clone-send_target-var.ptr); } + if (execute_data-current_this) { + Z_ADDREF_P(execute_data-current_this); + } + if (execute_data-object) { Z_ADDREF_P(execute_data-object); } -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Properly handle yield during method calls: Zend/tests/generators/yield_during_method_call.phpt Zend/zend_generators.c
Commit:bf82f46ea9028faa3830525d2462effe7d08600d Author:Nikita Popov ni...@php.net Sun, 3 Jun 2012 02:16:29 +0200 Parents: 7b3bfa5784cf36647f21a72ceb9741e40927a5b6 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=bf82f46ea9028faa3830525d2462effe7d08600d Log: Properly handle yield during method calls Changed paths: A Zend/tests/generators/yield_during_method_call.phpt M Zend/zend_generators.c Diff: diff --git a/Zend/tests/generators/yield_during_method_call.phpt b/Zend/tests/generators/yield_during_method_call.phpt new file mode 100644 index 000..da987ab --- /dev/null +++ b/Zend/tests/generators/yield_during_method_call.phpt @@ -0,0 +1,35 @@ +--TEST-- +Yield can be used during a method call +--FILE-- +?php + +class A { +public function b($c) { +echo $c, \n; +} +} + +function *gen() { +$a = new A; +$a-b(yield); +} + +$gen = gen(); +$gen-send('foo'); + +// test resource cleanup +$gen = gen(); +$gen-rewind(); +$gen-close(); + +// test cloning +$g1 = gen(); +$g1-rewind(); +$g2 = clone $g1; +$g1-close(); +$g2-send('bar'); + +? +--EXPECT-- +foo +bar diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index df204fa..a3277e6 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -41,6 +41,10 @@ void zend_generator_close(zend_generator *generator, zend_bool finished_executio zval_ptr_dtor(execute_data-current_this); } + if (execute_data-object) { + zval_ptr_dtor(execute_data-object); + } + /* If the generator is closed before it can finish execution (reach * a return statement) we have to free loop variables manually, as * we don't know whether the SWITCH_FREE / FREE opcodes have run */ @@ -228,6 +232,10 @@ static void zend_generator_clone_storage(zend_generator *orig, zend_generator ** ); Z_ADDREF_P(clone-send_target-var.ptr); } + + if (execute_data-object) { + Z_ADDREF_P(execute_data-object); + } } /* The value and key are known not to be references, so simply add refs */ -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Add cloning support for generators: Zend/tests/generators/clone.phpt Zend/tests/generators/clone_with_foreach.phpt Zend/tests/generators/clone_with_stack.phpt Zend/tests/generat
Commit:6117f4c7c0abe3721c2371600a97641003de21a7 Author:Nikita Popov ni...@php.net Sat, 2 Jun 2012 20:40:58 +0200 Parents: 1477be9aa88689f7e547a24258dc4d63637fd5b0 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=6117f4c7c0abe3721c2371600a97641003de21a7 Log: Add cloning support for generators Generators can now be cloned. I'm pretty sure that my current code does not yet cover all the edge cases of cloning the execution context, so there are probably a few bugs in there :) Changed paths: A Zend/tests/generators/clone.phpt A Zend/tests/generators/clone_with_foreach.phpt A Zend/tests/generators/clone_with_stack.phpt A Zend/tests/generators/clone_with_symbol_table.phpt M Zend/zend_generators.c diff --git a/Zend/tests/generators/clone.phpt b/Zend/tests/generators/clone.phpt new file mode 100644 index 000..94c4c63 --- /dev/null +++ b/Zend/tests/generators/clone.phpt @@ -0,0 +1,32 @@ +--TEST-- +Generators can be cloned +--FILE-- +?php + +function *firstN($end) { +for ($i = 0; $i $end; ++$i) { +yield $i; +} +} + +$g1 = firstN(5); +var_dump($g1-current()); +$g1-next(); + +$g2 = clone $g1; +var_dump($g2-current()); +$g2-next(); + +var_dump($g2-current()); +var_dump($g1-current()); + +$g1-next(); +var_dump($g1-current()); + +? +--EXPECT-- +int(0) +int(1) +int(2) +int(1) +int(2) diff --git a/Zend/tests/generators/clone_with_foreach.phpt b/Zend/tests/generators/clone_with_foreach.phpt new file mode 100644 index 000..42cf334 --- /dev/null +++ b/Zend/tests/generators/clone_with_foreach.phpt @@ -0,0 +1,33 @@ +--TEST-- +Cloning a generator with a foreach loop properly adds a ref for the loop var +--FILE-- +?php + +function *gen() { +foreach ([1, 2, 3] as $i) { +yield $i; +} +} + +$g1 = gen(); +var_dump($g1-current()); + +$g2 = clone $g1; +var_dump($g2-current()); + +$g1-next(); +$g2-next(); +var_dump($g1-current()); +var_dump($g2-current()); + +$g1-close(); +$g2-next(); +var_dump($g2-current()); + +? +--EXPECT-- +int(1) +int(1) +int(2) +int(2) +int(3) diff --git a/Zend/tests/generators/clone_with_stack.phpt b/Zend/tests/generators/clone_with_stack.phpt new file mode 100644 index 000..79bca31 --- /dev/null +++ b/Zend/tests/generators/clone_with_stack.phpt @@ -0,0 +1,18 @@ +--TEST-- +A generator with an active stack can be cloned +--FILE-- +?php + +function *gen() { +var_dump(str_repeat(x, yield)); +} + +$g1 = gen(); +$g1-rewind(); +$g2 = clone $g1; +$g1-close(); +$g2-send(10); + +? +--EXPECT-- +string(10) xx diff --git a/Zend/tests/generators/clone_with_symbol_table.phpt b/Zend/tests/generators/clone_with_symbol_table.phpt new file mode 100644 index 000..2a4cf10 --- /dev/null +++ b/Zend/tests/generators/clone_with_symbol_table.phpt @@ -0,0 +1,27 @@ +--TEST-- +A generator using a symbol table can be cloned +--FILE-- +?php + +function *gen() { +// force compiled variable for $foo +$foo = 'foo'; + +// force symbol table +extract(['foo' = 'bar']); + +// interrupt +yield; + +var_dump($foo); +} + +$g1 = gen(); +$g1-rewind(); +$g2 = clone $g1; +$g1-close(); +$g2-next(); + +? +--EXPECT-- +string(3) bar diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 5b58e21..01b93ef 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -34,13 +34,7 @@ void zend_generator_close(zend_generator *generator, zend_bool finished_executio if (!execute_data-symbol_table) { zend_free_compiled_variables(execute_data-CVs, execute_data-op_array-last_var); } else { - if (EG(symtable_cache_ptr) = EG(symtable_cache_limit)) { - zend_hash_destroy(execute_data-symbol_table); - FREE_HASHTABLE(execute_data-symbol_table); - } else { - zend_hash_clean(execute_data-symbol_table); - *(++EG(symtable_cache_ptr)) = execute_data-symbol_table; - } + zend_clean_and_cache_symbol_table(execute_data-symbol_table); } if (execute_data-current_this) { @@ -121,6 +115,134 @@ static void zend_generator_free_storage(zend_generator *generator TSRMLS_DC) /* } /* }}} */ +static void zend_generator_clone_storage(zend_generator *orig, zend_generator **clone_ptr) /* {{{ */ +{ + zend_generator *clone = emalloc(sizeof(zend_generator)); + memcpy(clone, orig, sizeof(zend_generator)); + + if (orig-execute_data) { + /* Create a few shorter aliases to the old execution data */ + zend_execute_data *execute_data = orig-execute_data; + zend_op_array *op_array = execute_data-op_array; + HashTable *symbol_table = execute_data-symbol_table; + + /* Alloc separate execution context, as well as separate sections for +
[PHP-CVS] com php-src: Improve backtraces from generators: Zend/tests/generators/backtrace.phpt Zend/zend_generators.c
Commit:7b3bfa5784cf36647f21a72ceb9741e40927a5b6 Author:Nikita Popov ni...@php.net Sun, 3 Jun 2012 02:00:11 +0200 Parents: 6117f4c7c0abe3721c2371600a97641003de21a7 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=7b3bfa5784cf36647f21a72ceb9741e40927a5b6 Log: Improve backtraces from generators The current situation is still not perfect, as the generator function itself does not appear in the stack trace. This makes sense in some way, but it would probably be more helpful if it would show up (with the bound arguments) after the $generator-xyz() call. This could be misleading too though as the function is not *really* called there. Changed paths: A Zend/tests/generators/backtrace.phpt M Zend/zend_generators.c Diff: diff --git a/Zend/tests/generators/backtrace.phpt b/Zend/tests/generators/backtrace.phpt new file mode 100644 index 000..cbf8de1 --- /dev/null +++ b/Zend/tests/generators/backtrace.phpt @@ -0,0 +1,25 @@ +--TEST-- +Printing the stack trace in a generator +--FILE-- +?php + +function f1() { +debug_print_backtrace(); +} + +function *f2() { +f1(); +} + +function f3($gen) { +$gen-rewind(); // trigger run +} + +$gen = f2(); +f3($gen); + +? +--EXPECTF-- +#0 f1() called at [%s:%d] +#1 Generator-rewind() called at [%s:%d] +#2 f3(Generator Object ()) called at [%s:%d] diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 01b93ef..df204fa 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -317,6 +317,10 @@ static void zend_generator_resume(zval *object, zend_generator *generator TSRMLS EG(scope) = generator-execute_data-current_scope; EG(called_scope) = generator-execute_data-current_called_scope; + /* Set prev_execute_data to the current execute_data to get halfways +* reasonable backtraces */ + generator-execute_data-prev_execute_data = original_execute_data; + /* Go to next opcode (we don't want to run the last one again) */ generator-execute_data-opline++; -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Make $generator-send() return the current value: Zend/tests/generators/send_returns_current.phpt Zend/zend_generators.c
Commit:1477be9aa88689f7e547a24258dc4d63637fd5b0 Author:Nikita Popov ni...@php.net Thu, 31 May 2012 20:03:18 +0200 Parents: ee89e228f6f684555dd219d8a46d173cfed3230a Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=1477be9aa88689f7e547a24258dc4d63637fd5b0 Log: Make $generator-send() return the current value This makes the API easier to use (and is consistent with Python and JS). Changed paths: A Zend/tests/generators/send_returns_current.phpt M Zend/zend_generators.c Diff: diff --git a/Zend/tests/generators/send_returns_current.phpt b/Zend/tests/generators/send_returns_current.phpt new file mode 100644 index 000..d3a4afd --- /dev/null +++ b/Zend/tests/generators/send_returns_current.phpt @@ -0,0 +1,20 @@ +--TEST-- +$generator-send() returns the yielded value +--FILE-- +?php + +function *reverseEchoGenerator() { +$data = yield; +while (true) { +$data = yield strrev($data); +} +} + +$gen = reverseEchoGenerator(); +var_dump($gen-send('foo')); +var_dump($gen-send('bar')); + +? +--EXPECT-- +string(3) oof +string(3) rab diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 4754d75..5b58e21 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -336,7 +336,7 @@ ZEND_METHOD(Generator, next) } /* }}} */ -/* {{{ proto void Generator::send() +/* {{{ proto mixed Generator::send() * Sends a value to the generator */ ZEND_METHOD(Generator, send) { @@ -366,6 +366,10 @@ ZEND_METHOD(Generator, send) generator-send_target-var.ptr_ptr = value; zend_generator_resume(object, generator TSRMLS_CC); + + if (generator-value) { + RETURN_ZVAL(generator-value, 1, 0); + } } /* {{{ proto void Generator::close() -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Allow throwing exceptions from generators: Zend/tests/generators/generator_throwing_exception.phpt Zend/zend_vm_def.h Zend/zend_vm_execute.h
Commit:0033a525213e68e6ae74b3c3d75fd6ea4beea5d6 Author:Nikita Popov ni...@php.net Wed, 30 May 2012 16:28:33 +0200 Parents: 879016023566ce162be1d81e973bde9db76dd519 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=0033a525213e68e6ae74b3c3d75fd6ea4beea5d6 Log: Allow throwing exceptions from generators The missing piece is how one can find the next stack frame, which is required for dtor'ing arguments pushed to the stack. As the generator execute_data does not live on the stack one can't use it to figure out the start of the next stack frame. So there must be some other method. Changed paths: A Zend/tests/generators/generator_throwing_exception.phpt M Zend/zend_vm_def.h M Zend/zend_vm_execute.h diff --git a/Zend/tests/generators/generator_throwing_exception.phpt b/Zend/tests/generators/generator_throwing_exception.phpt new file mode 100644 index 000..5df4a81 --- /dev/null +++ b/Zend/tests/generators/generator_throwing_exception.phpt @@ -0,0 +1,28 @@ +--TEST-- +Generators can throw exceptions +--FILE-- +?php + +function *gen() { +yield 'foo'; +throw new Exception('test'); +yield 'bar'; +} + +$gen = gen(); + +var_dump($gen-current()); + +try { +$gen-next(); +} catch (Exception $e) { +echo 'Caught exception with message ', $e-getMessage(), '', \n; +} + +var_dump($gen-current()); + +? +--EXPECT-- +string(3) foo +Caught exception with message test +NULL diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index f1fd64c..cbdf701 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2821,10 +2821,10 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY) /* The generator object is stored in return_value_ptr_ptr */ zend_generator *generator = (zend_generator *) zend_object_store_get_object(*EG(return_value_ptr_ptr) TSRMLS_CC); - /* Close the generator to free up resources. */ + /* Close the generator to free up resources */ zend_generator_close(generator, 1 TSRMLS_CC); - /* Pass execution back to generator handling code */ + /* Pass execution back to handling code */ ZEND_VM_RETURN(); } @@ -4992,11 +4992,25 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) int i; zend_uint catch_op_num = 0; int catched = 0; - zval restored_error_reporting; + void **stack_frame; - void **stack_frame = (void**)(((char*)EX_Ts()) + - (ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * EX(op_array)-T)); + /* Figure out where the next stack frame (which maybe contains pushed +* arguments that have to be dtor'ed) starts */ + if (EX(op_array)-fn_flags ZEND_ACC_GENERATOR) { + /* For generators the execution context is not stored on the stack so +* I don't know yet how to figure out where the next stack frame +* starts. For now I'll just use the stack top to ignore argument +* dtor'ing altogether. */ + stack_frame = zend_vm_stack_top(TSRMLS_C); + } else { + /* In all other cases the next stack frame starts after the temporary +* variables section of the current execution context */ + stack_frame = (void **) ((char *) EX_Ts() + + ZEND_MM_ALIGNED_SIZE(sizeof(temp_variable)) * EX(op_array)-T); + } + /* If the exception was thrown during a function call there might be +* arguments pushed to the stack that have to be dtor'ed. */ while (zend_vm_stack_top(TSRMLS_C) != stack_frame) { zval *stack_zval_p = zend_vm_stack_pop(TSRMLS_C); zval_ptr_dtor(stack_zval_p); @@ -5058,6 +5072,8 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) /* restore previous error_reporting value */ if (!EG(error_reporting) EX(old_error_reporting) != NULL Z_LVAL_P(EX(old_error_reporting)) != 0) { + zval restored_error_reporting; + Z_TYPE(restored_error_reporting) = IS_LONG; Z_LVAL(restored_error_reporting) = Z_LVAL_P(EX(old_error_reporting)); convert_to_string(restored_error_reporting); @@ -5067,6 +5083,18 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) EX(old_error_reporting) = NULL; if (!catched) { + /* For generators skip the leave handler return directly */ + if (EX(op_array)-fn_flags ZEND_ACC_GENERATOR) { + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) zend_object_store_get_object(*EG(return_value_ptr_ptr) TSRMLS_CC); + + /* Close the generator to free up resources */ + zend_generator_close(generator, 1 TSRMLS_CC); + + /* Pass execution
[PHP-CVS] com php-src: Add auto-increment keys: Zend/tests/generators/auto_incrementing_keys.phpt Zend/zend_generators.c Zend/zend_generators.h Zend/zend_vm_def.h Zend/zend_vm_execute.h
Commit:879016023566ce162be1d81e973bde9db76dd519 Author:Nikita Popov ni...@php.net Wed, 30 May 2012 05:05:49 +0200 Parents: bc08c2cf9485e20fea0eef7ab149cefdf9a3662e Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=879016023566ce162be1d81e973bde9db76dd519 Log: Add auto-increment keys When no key is explicitely yielded PHP will used auto-incrementing keys as a fallback. They behave the same as with arrays, i.e. the key is the successor of the largest previously used integer key. Changed paths: A Zend/tests/generators/auto_incrementing_keys.phpt M Zend/zend_generators.c M Zend/zend_generators.h M Zend/zend_vm_def.h M Zend/zend_vm_execute.h diff --git a/Zend/tests/generators/auto_incrementing_keys.phpt b/Zend/tests/generators/auto_incrementing_keys.phpt new file mode 100644 index 000..623f2d8 --- /dev/null +++ b/Zend/tests/generators/auto_incrementing_keys.phpt @@ -0,0 +1,22 @@ +--TEST-- +Generator keys are auto-incrementing by default +--FILE-- +?php + +function *gen() { +yield 'foo'; +yield 'bar'; +yield 5 = 'rab'; +yield 'oof'; +} + +foreach (gen() as $k = $v) { +echo $k, ' = ', $v, \n; +} + +? +--EXPECT-- +0 = foo +1 = bar +5 = rab +6 = oof diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index d3d4b3f..5c211b0 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -116,6 +116,9 @@ static zend_object_value zend_generator_create(zend_class_entry *class_type TSRM generator = emalloc(sizeof(zend_generator)); memset(generator, 0, sizeof(zend_generator)); + /* The key will be incremented on first use, so it'll start at 0 */ + generator-largest_used_integer_key = -1; + zend_object_std_init(generator-std, class_type TSRMLS_CC); object.handle = zend_objects_store_put(generator, NULL, diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h index 2fd2c93..b73557c 100644 --- a/Zend/zend_generators.h +++ b/Zend/zend_generators.h @@ -34,6 +34,8 @@ typedef struct _zend_generator { zval *key; /* Variable to put sent value into */ temp_variable *send_target; + /* Largest used integer key for auto-incrementing keys */ + long largest_used_integer_key; } zend_generator; extern ZEND_API zend_class_entry *zend_ce_generator; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 36b9c93..f1fd64c 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5332,11 +5332,19 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE generator-key = key; } + if (Z_TYPE_P(generator-key) == IS_LONG +Z_LVAL_P(generator-key) generator-largest_used_integer_key + ) { + generator-largest_used_integer_key = Z_LVAL_P(generator-key); + } + FREE_OP2_IF_VAR(); } else { - /* Setting the key to NULL signals that the auto-increment key -* generation should be used */ - generator-key = NULL; + /* If no key was specified we use auto-increment keys */ + generator-largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator-key); + ZVAL_LONG(generator-key, generator-largest_used_integer_key); } /* If a value is sent it should go into the result var */ diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index ac7ff7f..09c3461 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -4127,10 +4127,18 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLE generator-key = key; } + if (Z_TYPE_P(generator-key) == IS_LONG +Z_LVAL_P(generator-key) generator-largest_used_integer_key + ) { + generator-largest_used_integer_key = Z_LVAL_P(generator-key); + } + } else { - /* Setting the key to NULL signals that the auto-increment key -* generation should be used */ - generator-key = NULL; + /* If no key was specified we use auto-increment keys */ + generator-largest_used_integer_key++; + + ALLOC_INIT_ZVAL(generator-key); + ZVAL_LONG(generator-key, generator-largest_used_integer_key); } /* If a value is sent it should go into the result var */ @@ -4760,10 +4768,18 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ generator-key = key; } + if (Z_TYPE_P(generator-key) == IS_LONG +Z_LVAL_P(generator-key) generator-largest_used_integer_key + ) { + generator-largest_used_integer_key = Z_LVAL_P(generator-key); +
[PHP-CVS] com php-src: Add $generator-close() method: Zend/tests/generators/generator_close.phpt Zend/zend_generators.c
Commit:72a91d08e7d70d5524feb6cc7c8e32b3bd68f1df Author:Nikita Popov ni...@php.net Tue, 29 May 2012 18:11:18 +0200 Parents: 12e928314fb270db31adc361ac4993b4f0fe000a Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=72a91d08e7d70d5524feb6cc7c8e32b3bd68f1df Log: Add $generator-close() method Calling $generator-close() is equivalent to executing a return statement at the current position in the generator. Changed paths: A Zend/tests/generators/generator_close.phpt M Zend/zend_generators.c Diff: diff --git a/Zend/tests/generators/generator_close.phpt b/Zend/tests/generators/generator_close.phpt new file mode 100644 index 000..003eef0 --- /dev/null +++ b/Zend/tests/generators/generator_close.phpt @@ -0,0 +1,32 @@ +--TEST-- +Generator can be closed by calling -close() +--FILE-- +?php + +function *allNumbers() { +for ($i = 0; true; ++$i) { +yield $i; +} +} + +$numbers = allNumbers(); + +foreach ($numbers as $n) { +var_dump($n); +if ($n == 9) { +$numbers-close(); +} +} + +? +--EXPECT-- +int(0) +int(1) +int(2) +int(3) +int(4) +int(5) +int(6) +int(7) +int(8) +int(9) diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 0cf600a..b2fe8af 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -324,6 +324,22 @@ ZEND_METHOD(Generator, send) zend_generator_resume(object, generator TSRMLS_CC); } +/* {{{ proto void Generator::close() + * Closes the generator */ +ZEND_METHOD(Generator, close) +{ + zend_generator *generator; + + if (zend_parse_parameters_none() == FAILURE) { + return; + } + + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_generator_close(generator, 0); +} +/* }}} */ + ZEND_BEGIN_ARG_INFO(arginfo_generator_void, 0) ZEND_END_ARG_INFO() @@ -338,6 +354,7 @@ static const zend_function_entry generator_functions[] = { ZEND_ME(Generator, key, arginfo_generator_void, ZEND_ACC_PUBLIC) ZEND_ME(Generator, next,arginfo_generator_void, ZEND_ACC_PUBLIC) ZEND_ME(Generator, send,arginfo_generator_send, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, close, arginfo_generator_void, ZEND_ACC_PUBLIC) ZEND_FE_END }; -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Allow to use yield without value: Zend/tests/generators/yield_without_value.phpt Zend/zend_compile.c Zend/zend_language_parser.y Zend/zend_vm_def.h Zend/zend_vm_execute.h
Commit:ad525c288ad83df497ed1a0668915cad61d72e26 Author:Nikita Popov ni...@php.net Tue, 29 May 2012 17:53:11 +0200 Parents: 3600914ced52eb4f6db10410ba887c8e2a2acfe1 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=ad525c288ad83df497ed1a0668915cad61d72e26 Log: Allow to use yield without value If the generator is used as a coroutine it often doesn't make sense to yield anything. In this case one can simply receive values using $value = yield; The yield here will simply yield NULL. Changed paths: A Zend/tests/generators/yield_without_value.phpt M Zend/zend_compile.c M Zend/zend_language_parser.y M Zend/zend_vm_def.h M Zend/zend_vm_execute.h diff --git a/Zend/tests/generators/yield_without_value.phpt b/Zend/tests/generators/yield_without_value.phpt new file mode 100644 index 000..dc467a8 --- /dev/null +++ b/Zend/tests/generators/yield_without_value.phpt @@ -0,0 +1,27 @@ +--TEST-- +yield can be used without a value +--FILE-- +?php + +function *recv() { +while (true) { +var_dump(yield); +} +} + +$reciever = recv(); +var_dump($reciever-current()); +$reciever-send(1); +var_dump($reciever-current()); +$reciever-send(2); +var_dump($reciever-current()); +$reciever-send(3); + +? +--EXPECT-- +NULL +int(1) +NULL +int(2) +NULL +int(3) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 37e4901..89549bb 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2673,8 +2673,12 @@ void zend_do_yield(znode *result, const znode *expr TSRMLS_DC) /* {{{ */ opline = get_next_op(CG(active_op_array) TSRMLS_CC); opline-opcode = ZEND_YIELD; - SET_NODE(opline-op1, expr); - SET_UNUSED(opline-op2); + + if (expr) { + SET_NODE(opline-op1, expr); + } else { + SET_UNUSED(opline-op2); + } opline-result_type = IS_VAR; opline-result.var = get_temporary_variable(CG(active_op_array)); diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y index ea8ac41..ac22e7f 100644 --- a/Zend/zend_language_parser.y +++ b/Zend/zend_language_parser.y @@ -801,6 +801,7 @@ expr_without_variable: | combined_scalar { $$ = $1; } | '`' backticks_expr '`' { zend_do_shell_exec($$, $2 TSRMLS_CC); } | T_PRINT expr { zend_do_print($$, $2 TSRMLS_CC); } + | T_YIELD { zend_do_yield($$, NULL TSRMLS_CC); } | T_YIELD expr { zend_do_yield($$, $2 TSRMLS_CC); } | function is_generator is_reference { zend_do_begin_lambda_function_declaration($$, $1, $2.op_type, $3.op_type, 0 TSRMLS_CC); } '(' parameter_list ')' lexical_vars { zend_do_suspend_if_generator(TSRMLS_C); } diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 8c810cd..6761030 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5258,7 +5258,7 @@ ZEND_VM_HANDLER(159, ZEND_SUSPEND_AND_RETURN_GENERATOR, ANY, ANY) ZEND_VM_RETURN(); } -ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV, ANY) +ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, ANY) { USE_OPLINE @@ -5271,7 +5271,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV, ANY) } /* Set the new yielded value */ - { + if (OP1_TYPE != IS_UNUSED) { zend_free_op free_op1; zval *value = GET_OP1_ZVAL_PTR(BP_VAR_R); @@ -5291,11 +5291,15 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV, ANY) generator-value = copy; } else { - generator-value = value; Z_ADDREF_P(value); + generator-value = value; } FREE_OP1_IF_VAR(); + } else { + /* If no value way specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator-value = EG(uninitialized_zval); } /* If a value is sent it should go into the result var */ diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index fa07733..efe0812 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -3047,7 +3047,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS } /* Set the new yielded value */ - { + if (IS_CONST != IS_UNUSED) { zval *value = opline-op1.zv; @@ -3067,10 +3067,14 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS generator-value = copy; } else { - generator-value = value; Z_ADDREF_P(value); + generator-value = value; } + } else { + /* If no value way specified yield null */ + Z_ADDREF(EG(uninitialized_zval)); + generator-value = EG(uninitialized_zval); } /* If
[PHP-CVS] com php-src: Fix segfault when send()ing to a closed generator: Zend/tests/generators/send_after_close.phpt Zend/zend_generators.c
Commit:12e928314fb270db31adc361ac4993b4f0fe000a Author:Nikita Popov ni...@php.net Tue, 29 May 2012 18:01:08 +0200 Parents: ad525c288ad83df497ed1a0668915cad61d72e26 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=12e928314fb270db31adc361ac4993b4f0fe000a Log: Fix segfault when send()ing to a closed generator Changed paths: A Zend/tests/generators/send_after_close.phpt M Zend/zend_generators.c Diff: diff --git a/Zend/tests/generators/send_after_close.phpt b/Zend/tests/generators/send_after_close.phpt new file mode 100644 index 000..6a251b2 --- /dev/null +++ b/Zend/tests/generators/send_after_close.phpt @@ -0,0 +1,14 @@ +--TEST-- +Calls to send() after close should do nothing +--FILE-- +?php + +function *gen() { } + +$gen = gen(); +$gen-send(Test); + +? +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 01c9aa3..0cf600a 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -308,6 +308,11 @@ ZEND_METHOD(Generator, send) zend_generator_ensure_initialized(object, generator TSRMLS_CC); + /* The generator is already closed, thus can't send anything */ + if (!generator-execute_data) { + return; + } + /* The sent value was initialized to NULL, so dtor that */ zval_ptr_dtor(generator-send_target-var.ptr_ptr); -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Add support for $generator-send(): Zend/tests/generators/generator_send.phpt Zend/zend_compile.c Zend/zend_compile.h Zend/zend_generators.c Zend/zend_generators.h Zend/zend_lan
Commit:3600914ced52eb4f6db10410ba887c8e2a2acfe1 Author:Nikita Popov ni...@php.net Tue, 29 May 2012 17:34:33 +0200 Parents: b770b221e0b3036708deb9e22dacf296402787f0 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=3600914ced52eb4f6db10410ba887c8e2a2acfe1 Log: Add support for $generator-send() Yield now is an expression and the return value is the value passed to $generator-send(). By default (i.e. if -next() is called) the value is NULL. Unlike in Python -send() can be run without priming the generator with a -next() call first. Changed paths: A Zend/tests/generators/generator_send.phpt M Zend/zend_compile.c M Zend/zend_compile.h M Zend/zend_generators.c M Zend/zend_generators.h M Zend/zend_language_parser.y M Zend/zend_vm_def.h M Zend/zend_vm_execute.h diff --git a/Zend/tests/generators/generator_send.phpt b/Zend/tests/generators/generator_send.phpt new file mode 100644 index 000..11ac37f --- /dev/null +++ b/Zend/tests/generators/generator_send.phpt @@ -0,0 +1,22 @@ +--TEST-- +Values can be sent back to the generator +--FILE-- +?php + +function *gen() { +var_dump(yield yield foo); +var_dump(yield yield bar); +} + +$gen = gen(); +var_dump($gen-current()); +$gen-send(send bar); +var_dump($gen-current()); +$gen-send(send foo); + +? +--EXPECT-- +string(9) yield foo +string(8) send bar +string(9) yield bar +string(8) send foo diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 30fecf1..37e4901 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2662,7 +2662,7 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */ } /* }}} */ -void zend_do_yield(znode *expr TSRMLS_DC) /* {{{ */ +void zend_do_yield(znode *result, const znode *expr TSRMLS_DC) /* {{{ */ { zend_op *opline; @@ -2675,6 +2675,10 @@ void zend_do_yield(znode *expr TSRMLS_DC) /* {{{ */ opline-opcode = ZEND_YIELD; SET_NODE(opline-op1, expr); SET_UNUSED(opline-op2); + + opline-result_type = IS_VAR; + opline-result.var = get_temporary_variable(CG(active_op_array)); + GET_NODE(result, opline-result); } /* }}} */ diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 5365f96..953a9f1 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -490,7 +490,7 @@ void zend_do_build_full_name(znode *result, znode *prefix, znode *name, int is_c int zend_do_begin_class_member_function_call(znode *class_name, znode *method_name TSRMLS_DC); void zend_do_end_function_call(znode *function_name, znode *result, const znode *argument_list, int is_method, int is_dynamic_fcall TSRMLS_DC); void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC); -void zend_do_yield(znode *expr TSRMLS_DC); +void zend_do_yield(znode *result, const znode *expr TSRMLS_DC); void zend_do_suspend_if_generator(TSRMLS_D); void zend_do_handle_exception(TSRMLS_D); diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index e4b0704..01c9aa3 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -292,15 +292,47 @@ ZEND_METHOD(Generator, next) } /* }}} */ +/* {{{ proto void Generator::send() + * Sends a value to the generator */ +ZEND_METHOD(Generator, send) +{ + zval *object, *value; + zend_generator *generator; + + if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, z, value) == FAILURE) { + return; + } + + object = getThis(); + generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC); + + zend_generator_ensure_initialized(object, generator TSRMLS_CC); + + /* The sent value was initialized to NULL, so dtor that */ + zval_ptr_dtor(generator-send_target-var.ptr_ptr); + + /* Set new sent value */ + Z_ADDREF_P(value); + generator-send_target-var.ptr = value; + generator-send_target-var.ptr_ptr = value; + + zend_generator_resume(object, generator TSRMLS_CC); +} + ZEND_BEGIN_ARG_INFO(arginfo_generator_void, 0) ZEND_END_ARG_INFO() +ZEND_BEGIN_ARG_INFO_EX(arginfo_generator_send, 0, 0, 1) + ZEND_ARG_INFO(0, value) +ZEND_END_ARG_INFO() + static const zend_function_entry generator_functions[] = { ZEND_ME(Generator, rewind, arginfo_generator_void, ZEND_ACC_PUBLIC) ZEND_ME(Generator, valid, arginfo_generator_void, ZEND_ACC_PUBLIC) ZEND_ME(Generator, current, arginfo_generator_void, ZEND_ACC_PUBLIC) ZEND_ME(Generator, key, arginfo_generator_void, ZEND_ACC_PUBLIC) ZEND_ME(Generator, next,arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, send,arginfo_generator_send, ZEND_ACC_PUBLIC) ZEND_FE_END }; diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h index 192e9e7..c9b43b3 100644 --- a/Zend/zend_generators.h +++ b/Zend/zend_generators.h @@ -30,6 +30,8 @@ typedef struct _zend_generator { zend_execute_data *execute_data; /* Current value */
[PHP-CVS] com php-src: Set EG(current_execute_data): Zend/tests/generators/generator_method.phpt Zend/zend_generators.c
Commit:bcc7d976f31a572160a52c15f415deea3497ab68 Author:Nikita Popov ni...@php.net Mon, 28 May 2012 00:24:58 +0200 Parents: 9f52c5c22647f0648dbb350c551417b1ad070359 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=bcc7d976f31a572160a52c15f415deea3497ab68 Log: Set EG(current_execute_data) This fixes several issues. In particular it makes method generators work properly and also allows generators using a symbol table. Changed paths: A Zend/tests/generators/generator_method.phpt M Zend/zend_generators.c Diff: diff --git a/Zend/tests/generators/generator_method.phpt b/Zend/tests/generators/generator_method.phpt new file mode 100644 index 000..b64476d --- /dev/null +++ b/Zend/tests/generators/generator_method.phpt @@ -0,0 +1,29 @@ +--TEST-- +Methods can be generators +--FILE-- +?php + +class Test implements IteratorAggregate { +protected $data; + +public function __construct(array $data) { +$this-data = $data; +} + +public function *getIterator() { +foreach ($this-data as $value) { +yield $value; +} +} +} + +$test = new Test(['foo', 'bar', 'baz']); +foreach ($test as $value) { +var_dump($value); +} + +? +--EXPECT-- +string(3) foo +string(3) bar +string(3) baz diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 12116a0..00d637c 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -148,6 +148,7 @@ static void zend_generator_resume(zval *object, zend_generator *generator TSRMLS { /* Backup executor globals */ zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr); + zend_execute_data *original_execute_data = EG(current_execute_data); zend_op **original_opline_ptr = EG(opline_ptr); zend_op_array *original_active_op_array = EG(active_op_array); HashTable *original_active_symbol_table = EG(active_symbol_table); @@ -160,6 +161,7 @@ static void zend_generator_resume(zval *object, zend_generator *generator TSRMLS EG(return_value_ptr_ptr) = object; /* Set executor globals */ + EG(current_execute_data) = generator-execute_data; EG(opline_ptr) = generator-execute_data-opline; EG(active_op_array) = generator-execute_data-op_array; EG(active_symbol_table) = generator-execute_data-symbol_table; @@ -175,6 +177,7 @@ static void zend_generator_resume(zval *object, zend_generator *generator TSRMLS /* Restore executor globals */ EG(return_value_ptr_ptr) = original_return_value_ptr_ptr; + EG(current_execute_data) = original_execute_data; EG(opline_ptr) = original_opline_ptr; EG(active_op_array) = original_active_op_array; EG(active_symbol_table) = original_active_symbol_table; -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Add support for generator methods: Zend/zend_generators.c Zend/zend_vm_def.h Zend/zend_vm_execute.h
Commit:247bb737d552508829c5de7770ed0b15c3d8f7fd Author:Nikita Popov ni...@php.net Sun, 27 May 2012 03:50:31 +0200 Parents: 39d3d5ec138119acf614fb285e92c3bcda7a2555 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=247bb737d552508829c5de7770ed0b15c3d8f7fd Log: Add support for generator methods Changed paths: M Zend/zend_generators.c M Zend/zend_vm_def.h M Zend/zend_vm_execute.h Diff: diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 36a9727..ae706f1 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -48,6 +48,10 @@ void zend_generator_close(zend_generator *generator TSRMLS_DC) /* {{{ */ } } + if (execute_data-current_this) { + zval_ptr_dtor(execute_data-current_this); + } + efree(execute_data); generator-execute_data = NULL; } @@ -105,28 +109,43 @@ static void zend_generator_resume(zval *object, zend_generator *generator TSRMLS return; } - /* Backup executor globals */ - zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr); - zend_op **original_opline_ptr = EG(opline_ptr); - zend_op_array *original_active_op_array = EG(active_op_array); - - /* We (mis) use the return_value_ptr_ptr to provide the generator object -* to the executor. This way YIELD will be able to set the yielded value */ - EG(return_value_ptr_ptr) = object; - - EG(opline_ptr) = generator-execute_data-opline; - EG(active_op_array) = generator-execute_data-op_array; - - /* Go to next opcode (we don't want to run the last one again) */ - generator-execute_data-opline++; - - /* Resume execution */ - execute_ex(generator-execute_data TSRMLS_CC); - - /* Restore executor globals */ - EG(return_value_ptr_ptr) = original_return_value_ptr_ptr; - EG(opline_ptr) = original_opline_ptr; - EG(active_op_array) = original_active_op_array; + { + /* Backup executor globals */ + zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr); + zend_op **original_opline_ptr = EG(opline_ptr); + zend_op_array *original_active_op_array = EG(active_op_array); + HashTable *original_active_symbol_table = EG(active_symbol_table); + zval *original_This = EG(This); + zend_class_entry *original_scope = EG(scope); + zend_class_entry *original_called_scope = EG(called_scope); + + /* We (mis)use the return_value_ptr_ptr to provide the generator object +* to the executor, so YIELD will be able to set the yielded value */ + EG(return_value_ptr_ptr) = object; + + /* Set executor globals */ + EG(opline_ptr) = generator-execute_data-opline; + EG(active_op_array) = generator-execute_data-op_array; + EG(active_symbol_table) = generator-execute_data-symbol_table; + EG(This) = generator-execute_data-current_this; + EG(scope) = generator-execute_data-current_scope; + EG(called_scope) = generator-execute_data-current_called_scope; + + /* Go to next opcode (we don't want to run the last one again) */ + generator-execute_data-opline++; + + /* Resume execution */ + execute_ex(generator-execute_data TSRMLS_CC); + + /* Restore executor globals */ + EG(return_value_ptr_ptr) = original_return_value_ptr_ptr; + EG(opline_ptr) = original_opline_ptr; + EG(active_op_array) = original_active_op_array; + EG(active_symbol_table) = original_active_symbol_table; + EG(This) = original_This; + EG(scope) = original_scope; + EG(called_scope) = original_called_scope; + } } /* }}} */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 781bd9f..42397ed 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5225,6 +5225,11 @@ ZEND_VM_HANDLER(159, ZEND_SUSPEND_AND_RETURN_GENERATOR, ANY, ANY) *EG(return_value_ptr_ptr) = return_value; + /* back up some executor globals */ + EX(current_this) = EG(This); + EX(current_scope) = EG(scope); + EX(current_called_scope) = EG(called_scope); + /* back up the execution context */ generator = (zend_generator *) zend_object_store_get_object(return_value TSRMLS_CC); generator-execute_data = execute_data; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 1eac105..fa802c6 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1207,6 +1207,11 @@ static int ZEND_FASTCALL
[PHP-CVS] com php-src: Fix generator creation when execute_data is not nested: Zend/tests/generators/dynamic_call.phpt Zend/zend_vm_def.h Zend/zend_vm_execute.h
Commit:9f52c5c22647f0648dbb350c551417b1ad070359 Author:Nikita Popov ni...@php.net Sun, 27 May 2012 22:48:21 +0200 Parents: 64a643a4e3c1b45d3a9b2ad24537f7aab6296f7d Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=9f52c5c22647f0648dbb350c551417b1ad070359 Log: Fix generator creation when execute_data is not nested This happens primarily when the generator is invoked from some internal place like a dynamic function call. Changed paths: A Zend/tests/generators/dynamic_call.phpt M Zend/zend_vm_def.h M Zend/zend_vm_execute.h Diff: diff --git a/Zend/tests/generators/dynamic_call.phpt b/Zend/tests/generators/dynamic_call.phpt new file mode 100644 index 000..7b4b0c3 --- /dev/null +++ b/Zend/tests/generators/dynamic_call.phpt @@ -0,0 +1,19 @@ +--TEST-- +It's possible to invoke a generator dynamically +--FILE-- +?php + +function *gen($foo, $bar) { +yield $foo; +yield $bar; +} + +$gen = call_user_func('gen', 'bar', 'foo'); +foreach ($gen as $value) { +var_dump($value); +} + +? +--EXPECT-- +string(3) bar +string(3) foo diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 440b36d..0b06c92 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5265,10 +5265,12 @@ ZEND_VM_HANDLER(159, ZEND_SUSPEND_AND_RETURN_GENERATOR, ANY, ANY) EX(called_scope) = DECODE_CTOR(EX(called_scope)); zend_vm_stack_clear_multiple(TSRMLS_C); + + ZEND_VM_INC_OPCODE(); + ZEND_VM_LEAVE(); } - ZEND_VM_INC_OPCODE(); - ZEND_VM_LEAVE(); + ZEND_VM_RETURN(); } ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV, ANY) diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 8f06afa..6879d9d 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1247,10 +1247,12 @@ static int ZEND_FASTCALL ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER(ZEND_OP EX(called_scope) = DECODE_CTOR(EX(called_scope)); zend_vm_stack_clear_multiple(TSRMLS_C); + + ZEND_VM_INC_OPCODE(); + ZEND_VM_LEAVE(); } - ZEND_VM_INC_OPCODE(); - ZEND_VM_LEAVE(); + ZEND_VM_RETURN(); } static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Add first real generator test: Zend/tests/generators/xrange.phpt
Commit:39d3d5ec138119acf614fb285e92c3bcda7a2555 Author:Nikita Popov ni...@php.net Sun, 27 May 2012 00:50:27 +0200 Parents: cbfa96cad59d679502eca002a1e920065f11f871 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=39d3d5ec138119acf614fb285e92c3bcda7a2555 Log: Add first real generator test The test implements an xrange() function (the generator version of range()). Changed paths: A Zend/tests/generators/xrange.phpt Diff: diff --git a/Zend/tests/generators/xrange.phpt b/Zend/tests/generators/xrange.phpt new file mode 100644 index 000..685c6b3 --- /dev/null +++ b/Zend/tests/generators/xrange.phpt @@ -0,0 +1,23 @@ +--TEST-- +Simple generator xrange() test +--FILE-- +?php + +function *xrange($start, $end, $step = 1) { + for ($i = $start; $i = $end; $i += $step) { + yield $i; + } +} + +foreach (xrange(10, 20, 2) as $i) { + var_dump($i); +} + +? +--EXPECT-- +int(10) +int(12) +int(14) +int(16) +int(18) +int(20) -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Make the GOTO and SWITCH VMs work again: Zend/zend_vm_def.h Zend/zend_vm_execute.h Zend/zend_vm_execute.skl Zend/zend_vm_gen.php
Commit:b770b221e0b3036708deb9e22dacf296402787f0 Author:Nikita Popov ni...@php.net Tue, 29 May 2012 02:31:56 +0200 Parents: 4aab08b64c2318775be6d8e629747ac66a108485 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=b770b221e0b3036708deb9e22dacf296402787f0 Log: Make the GOTO and SWITCH VMs work again Changed paths: M Zend/zend_vm_def.h M Zend/zend_vm_execute.h M Zend/zend_vm_execute.skl M Zend/zend_vm_gen.php diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 04b6595..47d5ec4 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5203,6 +5203,7 @@ ZEND_VM_HANDLER(159, ZEND_SUSPEND_AND_RETURN_GENERATOR, ANY, ANY) *EG(return_value_ptr_ptr) = return_value; /* back up some executor globals */ + SAVE_OPLINE(); EX(current_this) = EG(This); EX(current_scope) = EG(scope); EX(current_called_scope) = EG(called_scope); @@ -5248,6 +5249,8 @@ ZEND_VM_HANDLER(159, ZEND_SUSPEND_AND_RETURN_GENERATOR, ANY, ANY) zend_vm_stack_clear_multiple(TSRMLS_C); + LOAD_REGS(); + LOAD_OPLINE(); ZEND_VM_INC_OPCODE(); ZEND_VM_LEAVE(); } @@ -5293,6 +5296,10 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV, ANY) FREE_OP1_IF_VAR(); } + /* The GOTO VM uses a local opline variable. We need to set the opline +* variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + ZEND_VM_RETURN(); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index c195148..bd22768 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -393,10 +393,10 @@ static zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array * if (op_array-this_var != -1 EG(This)) { Z_ADDREF_P(EG(This)); /* For $this pointer */ if (!EG(active_symbol_table)) { - EX_CV(op_array-this_var) = (zval**)EX_CVs() + (op_array-last_var + op_array-this_var); - *EX_CV(op_array-this_var) = EG(This); + EX(CVs)[op_array-this_var] = (zval **) EX(CVs) + op_array-last_var + op_array-this_var; + *EX(CVs)[op_array-this_var] = EG(This); } else { - if (zend_hash_add(EG(active_symbol_table), this, sizeof(this), EG(This), sizeof(zval *), (void**)EX_CV(op_array-this_var))==FAILURE) { + if (zend_hash_add(EG(active_symbol_table), this, sizeof(this), EG(This), sizeof(zval *), (void **) EX(CVs)[op_array-this_var])==FAILURE) { Z_DELREF_P(EG(This)); } } @@ -425,7 +425,6 @@ ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC) EG(in_execution) = 1; -zend_vm_enter: LOAD_REGS(); LOAD_OPLINE(); @@ -444,8 +443,10 @@ zend_vm_enter: return; case 2: execute_data = zend_create_execute_data_from_op_array(EG(active_op_array), 1 TSRMLS_CC); + break; case 3: execute_data = EG(current_execute_data); + break; default: break; } @@ -1185,6 +1186,7 @@ static int ZEND_FASTCALL ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER(ZEND_OP *EG(return_value_ptr_ptr) = return_value; /* back up some executor globals */ + SAVE_OPLINE(); EX(current_this) = EG(This); EX(current_scope) = EG(scope); EX(current_called_scope) = EG(called_scope); @@ -1230,6 +1232,8 @@ static int ZEND_FASTCALL ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER(ZEND_OP zend_vm_stack_clear_multiple(TSRMLS_C); + LOAD_REGS(); + LOAD_OPLINE(); ZEND_VM_INC_OPCODE(); ZEND_VM_LEAVE(); } @@ -3067,6 +3071,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS } + /* The GOTO VM uses a local opline variable. We need to set the opline +* variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + ZEND_VM_RETURN(); } @@ -7704,6 +7712,10 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } + /* The GOTO VM uses a local opline variable. We need to set the opline +* variable in execute_data so we don't resume at an old position. */ + SAVE_OPLINE(); + ZEND_VM_RETURN(); } @@ -12419,6 +12431,10 @@
[PHP-CVS] com php-src: Add way to pass generator object to opcode handlers: Zend/zend_generators.c
Commit:1a99d1c8874936f7e232840a580d7bc588d63a6c Author:Nikita Popov ni...@php.net Sat, 26 May 2012 19:40:29 +0200 Parents: f627be52540738e124da7cb1566d7f60a2b6a48b Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=1a99d1c8874936f7e232840a580d7bc588d63a6c Log: Add way to pass generator object to opcode handlers The generator zval is put into the return_value_ptr_ptr. Changed paths: M Zend/zend_generators.c Diff: diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index de1271f..1ea910b 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -86,17 +86,23 @@ static zend_function *zend_generator_get_constructor(zval *object TSRMLS_DC) /* } /* }}} */ -static void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */ +static void zend_generator_resume(zval *object, zend_generator *generator TSRMLS_DC) /* {{{ */ { + /* Go to next opcode (we don't want to run the last one again) */ generator-execute_data-opline++; + + /* We (mis) use the return_value_ptr_ptr to provide the generator object +* to the executor. This way YIELD will be able to set the yielded value */ + EG(return_value_ptr_ptr) = object; + execute_ex(generator-execute_data TSRMLS_CC); } /* }}} */ -static void zend_generator_ensure_initialized(zend_generator *generator TSRMLS_DC) /* {{{ */ +static void zend_generator_ensure_initialized(zval *object, zend_generator *generator TSRMLS_DC) /* {{{ */ { if (!generator-value) { - zend_generator_resume(generator TSRMLS_CC); + zend_generator_resume(object, generator TSRMLS_CC); } } /* }}} */ @@ -105,15 +111,17 @@ static void zend_generator_ensure_initialized(zend_generator *generator TSRMLS_D * Rewind the generator */ ZEND_METHOD(Generator, rewind) { + zval *object; zend_generator *generator; if (zend_parse_parameters_none() == FAILURE) { return; } - generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + object = getThis(); + generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC); - zend_generator_ensure_initialized(generator TSRMLS_CC); + zend_generator_ensure_initialized(object, generator TSRMLS_CC); } /* }}} */ @@ -121,15 +129,17 @@ ZEND_METHOD(Generator, rewind) * Check whether the generator is valid */ ZEND_METHOD(Generator, valid) { + zval *object; zend_generator *generator; if (zend_parse_parameters_none() == FAILURE) { return; } - generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + object = getThis(); + generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC); - zend_generator_ensure_initialized(generator TSRMLS_CC); + zend_generator_ensure_initialized(object, generator TSRMLS_CC); } /* }}} */ @@ -137,15 +147,17 @@ ZEND_METHOD(Generator, valid) * Get the current value */ ZEND_METHOD(Generator, current) { + zval *object; zend_generator *generator; if (zend_parse_parameters_none() == FAILURE) { return; } - generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + object = getThis(); + generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC); - zend_generator_ensure_initialized(generator TSRMLS_CC); + zend_generator_ensure_initialized(object, generator TSRMLS_CC); } /* }}} */ @@ -153,15 +165,17 @@ ZEND_METHOD(Generator, current) * Get the current key */ ZEND_METHOD(Generator, key) { + zval *object; zend_generator *generator; if (zend_parse_parameters_none() == FAILURE) { return; } - generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + object = getThis(); + generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC); - zend_generator_ensure_initialized(generator TSRMLS_CC); + zend_generator_ensure_initialized(object, generator TSRMLS_CC); } /* }}} */ @@ -169,15 +183,16 @@ ZEND_METHOD(Generator, key) * Advances the generator */ ZEND_METHOD(Generator, next) { + zval *object; zend_generator *generator; if (zend_parse_parameters_none() == FAILURE) { return; } - generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC); - zend_generator_ensure_initialized(generator TSRMLS_CC); + zend_generator_ensure_initialized(object, generator TSRMLS_CC); } /* }}} */ -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Add YIELD opcode implementation: Zend/zend_compile.c Zend/zend_generators.c Zend/zend_vm_def.h Zend/zend_vm_execute.h Zend/zend_vm_opcodes.h
Commit:fafce58683e74a397023cc1077aae210109b40b6 Author:Nikita Popov ni...@php.net Sat, 26 May 2012 22:44:53 +0200 Parents: 1a99d1c8874936f7e232840a580d7bc588d63a6c Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=fafce58683e74a397023cc1077aae210109b40b6 Log: Add YIELD opcode implementation Changed paths: M Zend/zend_compile.c M Zend/zend_generators.c M Zend/zend_vm_def.h M Zend/zend_vm_execute.h M Zend/zend_vm_opcodes.h diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index f0802ef..b0e6ee2 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2660,11 +2660,17 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */ void zend_do_yield(znode *expr TSRMLS_DC) /* {{{ */ { + zend_op *opline; + if ((CG(active_op_array)-fn_flags ZEND_ACC_GENERATOR) == 0) { zend_error(E_COMPILE_ERROR, The \yield\ statement can only be used inside a generator function); } - /* do nothing for now */ + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + + opline-opcode = ZEND_YIELD; + SET_NODE(opline-op1, expr); + SET_UNUSED(opline-op2); } /* }}} */ diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 1ea910b..8161fc7 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -53,6 +53,10 @@ static void zend_generator_free_storage(zend_generator *generator TSRMLS_DC) /* efree(execute_data); } + if (generator-value) { + zval_ptr_dtor(generator-value); + } + efree(generator); } /* }}} */ @@ -88,14 +92,28 @@ static zend_function *zend_generator_get_constructor(zval *object TSRMLS_DC) /* static void zend_generator_resume(zval *object, zend_generator *generator TSRMLS_DC) /* {{{ */ { - /* Go to next opcode (we don't want to run the last one again) */ - generator-execute_data-opline++; + /* Backup executor globals */ + zval **original_return_value_ptr_ptr = EG(return_value_ptr_ptr); + zend_op **original_opline_ptr = EG(opline_ptr); + zend_op_array *original_active_op_array = EG(active_op_array); /* We (mis) use the return_value_ptr_ptr to provide the generator object * to the executor. This way YIELD will be able to set the yielded value */ EG(return_value_ptr_ptr) = object; + EG(opline_ptr) = generator-execute_data-opline; + EG(active_op_array) = generator-execute_data-op_array; + + /* Go to next opcode (we don't want to run the last one again) */ + generator-execute_data-opline++; + + /* Resume execution */ execute_ex(generator-execute_data TSRMLS_CC); + + /* Restore executor globals */ + EG(return_value_ptr_ptr) = original_return_value_ptr_ptr; + EG(opline_ptr) = original_opline_ptr; + EG(active_op_array) = original_active_op_array; } /* }}} */ @@ -190,6 +208,7 @@ ZEND_METHOD(Generator, next) return; } + object = getThis(); generator = (zend_generator *) zend_object_store_get_object(object TSRMLS_CC); zend_generator_ensure_initialized(object, generator TSRMLS_CC); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index f4d16be..b2fc051 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5255,4 +5255,45 @@ ZEND_VM_HANDLER(159, ZEND_SUSPEND_AND_RETURN_GENERATOR, ANY, ANY) ZEND_VM_LEAVE(); } +ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV, ANY) +{ + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) zend_object_store_get_object(*EG(return_value_ptr_ptr) TSRMLS_CC); + + /* Destroy the previously yielded value */ + if (generator-value) { + zval_ptr_dtor(generator-value); + } + + { + USE_OPLINE + zend_free_op free_op1; + zval *value = GET_OP1_ZVAL_PTR(BP_VAR_R); + + /* Consts, temporary variables and references need copying */ + if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR + || (PZVAL_IS_REF(value) Z_REFCOUNT_P(value) 0) + ) { + zval *copy; + + ALLOC_ZVAL(copy); + INIT_PZVAL_COPY(copy, value); + + /* Temporary variables don't need ctor copying */ + if (!IS_OP1_TMP_FREE()) { + zval_copy_ctor(copy); + } + + generator-value = copy; + } else { + generator-value = value; + Z_ADDREF_P(value); + } + + FREE_OP1_IF_VAR(); + } + + ZEND_VM_RETURN(); +} + ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper) diff --git a/Zend/zend_vm_execute.h
[PHP-CVS] com php-src: Add support for executing a zend_execute_data: Zend/zend_execute.h Zend/zend_generators.c Zend/zend_generators.h Zend/zend_vm_execute.h Zend/zend_vm_execute.skl Zend/zend_vm_gen
Commit:f627be52540738e124da7cb1566d7f60a2b6a48b Author:Nikita Popov ni...@php.net Sat, 26 May 2012 17:53:13 +0200 Parents: ececcbce0e37a306afc1a039f52188b6c243fecc Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=f627be52540738e124da7cb1566d7f60a2b6a48b Log: Add support for executing a zend_execute_data This adds another function execute_ex(), which accepts a zend_execute_data struct to run (contrary to execute(), which accepts a zend_op_array from which it initialized the execute_data). This needs a bit more cleanup. Changed paths: M Zend/zend_execute.h M Zend/zend_generators.c M Zend/zend_generators.h M Zend/zend_vm_execute.h M Zend/zend_vm_execute.skl M Zend/zend_vm_gen.php diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 7d42738..75a7eaa 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -56,6 +56,7 @@ void init_executor(TSRMLS_D); void shutdown_executor(TSRMLS_D); void shutdown_destructors(TSRMLS_D); ZEND_API void execute(zend_op_array *op_array TSRMLS_DC); +ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC); ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, int return_value_used TSRMLS_DC); ZEND_API int zend_is_true(zval *op); #define safe_free_zval_ptr(p) safe_free_zval_ptr_rel(p ZEND_FILE_LINE_CC ZEND_FILE_LINE_EMPTY_CC) diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 00af655..de1271f 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -86,13 +86,34 @@ static zend_function *zend_generator_get_constructor(zval *object TSRMLS_DC) /* } /* }}} */ +static void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */ +{ + generator-execute_data-opline++; + execute_ex(generator-execute_data TSRMLS_CC); +} +/* }}} */ + +static void zend_generator_ensure_initialized(zend_generator *generator TSRMLS_DC) /* {{{ */ +{ + if (!generator-value) { + zend_generator_resume(generator TSRMLS_CC); + } +} +/* }}} */ + /* {{{ proto void Generator::rewind() * Rewind the generator */ ZEND_METHOD(Generator, rewind) { + zend_generator *generator; + if (zend_parse_parameters_none() == FAILURE) { return; } + + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_generator_ensure_initialized(generator TSRMLS_CC); } /* }}} */ @@ -100,9 +121,15 @@ ZEND_METHOD(Generator, rewind) * Check whether the generator is valid */ ZEND_METHOD(Generator, valid) { + zend_generator *generator; + if (zend_parse_parameters_none() == FAILURE) { return; } + + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_generator_ensure_initialized(generator TSRMLS_CC); } /* }}} */ @@ -110,9 +137,15 @@ ZEND_METHOD(Generator, valid) * Get the current value */ ZEND_METHOD(Generator, current) { + zend_generator *generator; + if (zend_parse_parameters_none() == FAILURE) { return; } + + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_generator_ensure_initialized(generator TSRMLS_CC); } /* }}} */ @@ -120,9 +153,15 @@ ZEND_METHOD(Generator, current) * Get the current key */ ZEND_METHOD(Generator, key) { + zend_generator *generator; + if (zend_parse_parameters_none() == FAILURE) { return; } + + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_generator_ensure_initialized(generator TSRMLS_CC); } /* }}} */ @@ -130,9 +169,15 @@ ZEND_METHOD(Generator, key) * Advances the generator */ ZEND_METHOD(Generator, next) { + zend_generator *generator; + if (zend_parse_parameters_none() == FAILURE) { return; } + + generator = (zend_generator *) zend_object_store_get_object(getThis() TSRMLS_CC); + + zend_generator_ensure_initialized(generator TSRMLS_CC); } /* }}} */ diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h index c3b8f45..1422b71 100644 --- a/Zend/zend_generators.h +++ b/Zend/zend_generators.h @@ -32,6 +32,8 @@ typedef struct _zend_generator { /* The suspended execution context. */ zend_execute_data *execute_data; + /* Current value */ + zval *value; } zend_generator; END_EXTERN_C() diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 8316a0a..c83a4db 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -339,25 +339,9 @@ static opcode_handler_t zend_vm_get_opcode_handler(zend_uchar opcode, zend_op* o #define EX_Ts() EX(Ts) -ZEND_API void execute(zend_op_array *op_array TSRMLS_DC) -{ - DCL_OPLINE - +static zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zend_bool nested
[PHP-CVS] com php-src: Add dummy Iterator implementation: Zend/zend_generators.c
Commit:2c5ecb4fea3580dfe7e89be7b236b1cacbaf80de Author:Nikita Popov ni...@php.net Wed, 23 May 2012 16:07:15 +0200 Parents: 9ce9a7e639bbb6c1c4bb34d542d2ac4e42e9457e Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=2c5ecb4fea3580dfe7e89be7b236b1cacbaf80de Log: Add dummy Iterator implementation This simply adds dummy rewind/valid/current/key/next methods to Generator. Changed paths: M Zend/zend_generators.c Diff: diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index d9ddd75..00af655 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -20,6 +20,7 @@ #include zend.h #include zend_API.h +#include zend_interfaces.h #include zend_generators.h ZEND_API zend_class_entry *zend_ce_generator; @@ -85,7 +86,65 @@ static zend_function *zend_generator_get_constructor(zval *object TSRMLS_DC) /* } /* }}} */ +/* {{{ proto void Generator::rewind() + * Rewind the generator */ +ZEND_METHOD(Generator, rewind) +{ + if (zend_parse_parameters_none() == FAILURE) { + return; + } +} +/* }}} */ + +/* {{{ proto bool Generator::valid() + * Check whether the generator is valid */ +ZEND_METHOD(Generator, valid) +{ + if (zend_parse_parameters_none() == FAILURE) { + return; + } +} +/* }}} */ + +/* {{{ proto mixed Generator::current() + * Get the current value */ +ZEND_METHOD(Generator, current) +{ + if (zend_parse_parameters_none() == FAILURE) { + return; + } +} +/* }}} */ + +/* {{{ proto mixed Generator::key() + * Get the current key */ +ZEND_METHOD(Generator, key) +{ + if (zend_parse_parameters_none() == FAILURE) { + return; + } +} +/* }}} */ + +/* {{{ proto void Generator::next() + * Advances the generator */ +ZEND_METHOD(Generator, next) +{ + if (zend_parse_parameters_none() == FAILURE) { + return; + } +} +/* }}} */ + +ZEND_BEGIN_ARG_INFO(arginfo_generator_void, 0) +ZEND_END_ARG_INFO() + static const zend_function_entry generator_functions[] = { + ZEND_ME(Generator, rewind, arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, valid, arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, current, arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, key, arginfo_generator_void, ZEND_ACC_PUBLIC) + ZEND_ME(Generator, next,arginfo_generator_void, ZEND_ACC_PUBLIC) ZEND_FE_END }; @@ -98,6 +157,8 @@ void zend_register_generator_ce(TSRMLS_D) /* {{{ */ zend_ce_generator-ce_flags |= ZEND_ACC_FINAL_CLASS; zend_ce_generator-create_object = zend_generator_create; + zend_class_implements(zend_ce_generator TSRMLS_CC, 1, zend_ce_iterator); + memcpy(zend_generator_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); zend_generator_handlers.get_constructor = zend_generator_get_constructor; } -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Allow calling zend_vm_gen from everywhere: Zend/zend_vm_gen.php
Commit:ececcbce0e37a306afc1a039f52188b6c243fecc Author:Nikita Popov ni...@php.net Wed, 23 May 2012 20:34:17 +0200 Parents: 2c5ecb4fea3580dfe7e89be7b236b1cacbaf80de Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=ececcbce0e37a306afc1a039f52188b6c243fecc Log: Allow calling zend_vm_gen from everywhere Before one could only call it with cwd=Zend. Changed paths: M Zend/zend_vm_gen.php Diff: diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 3163000..a6314ed 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -1182,7 +1182,7 @@ function gen_vm($def, $skel) { // Generate opcode #defines (zend_vm_opcodes.h) $code_len = strlen((string)$max_opcode); - $f = fopen(zend_vm_opcodes.h, w+) or die(ERROR: Cannot create zend_vm_opcodes.h\n); + $f = fopen(__DIR__ . /zend_vm_opcodes.h, w+) or die(ERROR: Cannot create zend_vm_opcodes.h\n); // Insert header out($f, $GLOBALS['header_text']); @@ -1196,8 +1196,8 @@ function gen_vm($def, $skel) { echo zend_vm_opcodes.h generated successfully.\n; // Generate zend_vm_execute.h - $f = fopen(zend_vm_execute.h, w+) or die(ERROR: Cannot create zend_vm_execute.h\n); - $executor_file = realpath(zend_vm_execute.h); + $f = fopen(__DIR__ . /zend_vm_execute.h, w+) or die(ERROR: Cannot create zend_vm_execute.h\n); + $executor_file = realpath(__DIR__ . /zend_vm_execute.h); // Insert header out($f, $GLOBALS['header_text']); @@ -1440,6 +1440,6 @@ if (!defined(ZEND_VM_LINES)) { define(ZEND_VM_LINES, 0); } -gen_vm(zend_vm_def.h, zend_vm_execute.skl); +gen_vm(__DIR__ . /zend_vm_def.h, __DIR__ . /zend_vm_execute.skl); ? -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Add ZEND_SUSPEND_AND_RETURN_GENERATOR opcode: Zend/zend_compile.c Zend/zend_vm_def.h Zend/zend_vm_execute.h Zend/zend_vm_opcodes.h
Commit:1cec3f12cc719ccde286a3a55f6da1a5bf9ea2e4 Author:Nikita Popov ni...@php.net Sat, 19 May 2012 23:11:18 +0200 Parents: e14cfafcbfbe58e0fc3f7b814698a908b0dffca5 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=1cec3f12cc719ccde286a3a55f6da1a5bf9ea2e4 Log: Add ZEND_SUSPEND_AND_RETURN_GENERATOR opcode If the function is a generator this opcode will be invoked right after receiving the function arguments. The current implementation is just a dummy. Changed paths: M Zend/zend_compile.c M Zend/zend_vm_def.h M Zend/zend_vm_execute.h M Zend/zend_vm_opcodes.h Diff: diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 831f9f9..f0802ef 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2670,12 +2670,18 @@ void zend_do_yield(znode *expr TSRMLS_DC) /* {{{ */ void zend_do_suspend_if_generator(TSRMLS_D) /* {{{ */ { + zend_op *opline; + // we only suspend execution if the current function is a generator if ((CG(active_op_array)-fn_flags ZEND_ACC_GENERATOR) == 0) { return; } - /* do nothing for now */ + opline = get_next_op(CG(active_op_array) TSRMLS_CC); + + opline-opcode = ZEND_SUSPEND_AND_RETURN_GENERATOR; + SET_UNUSED(opline-op1); + SET_UNUSED(opline-op2); } /* }}} */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 7b13b44..9dc7e08 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5195,4 +5195,11 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED) ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HANDLER(159, ZEND_SUSPEND_AND_RETURN_GENERATOR, ANY, ANY) +{ + /* do nothing for now */ + + ZEND_VM_NEXT_OPCODE(); +} + ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper) diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 2096c44..c6c3af6 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1152,6 +1152,13 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS } } +static int ZEND_FASTCALL ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + /* do nothing for now */ + + ZEND_VM_NEXT_OPCODE(); +} + static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -40782,6 +40789,31 @@ void zend_init_opcodes_handlers(void) ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, ZEND_JMP_SET_VAR_SPEC_CV_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, + ZEND_SUSPEND_AND_RETURN_GENERATOR_SPEC_HANDLER, ZEND_NULL_HANDLER }; zend_opcode_handlers = (opcode_handler_t*)labels; diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index 680778c..9e24dee 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -159,3 +159,4 @@ #define ZEND_SEPARATE156 #define ZEND_QM_ASSIGN_VAR 157 #define ZEND_JMP_SET_VAR 158 +#define ZEND_SUSPEND_AND_RETURN_GENERATOR159 -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Add some boilerplate code for Generator class: Zend/tests/generators/errors/generator_extend_error.phpt Zend/tests/generators/errors/generator_instantiate_error.phpt Zend/tests/
Commit:40b7533576b4f2ec4ba872d027179d92db71d844 Author:Nikita Popov ni...@php.net Sun, 20 May 2012 14:19:16 +0200 Parents: ca59e5464de78dae1f7c874a6bcc4f7ea2948b1d Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=40b7533576b4f2ec4ba872d027179d92db71d844 Log: Add some boilerplate code for Generator class The Generator class now uses a zend_generator struct, so it'll be able to store additional info. This commit also ensures that Generator cannot be directly instantiated and extended. The error tests are now in a separate folder from the (yet-to-come) functional tests. Changed paths: A Zend/tests/generators/errors/generator_extend_error.phpt A Zend/tests/generators/errors/generator_instantiate_error.phpt A Zend/tests/generators/errors/yield_in_normal_function_error.phpt A Zend/tests/generators/errors/yield_outside_function_error.phpt D Zend/tests/generators/yield_in_normal_function_error.phpt D Zend/tests/generators/yield_outside_function_error.phpt M Zend/zend_generators.c Diff: diff --git a/Zend/tests/generators/errors/generator_extend_error.phpt b/Zend/tests/generators/errors/generator_extend_error.phpt new file mode 100644 index 000..550f16a --- /dev/null +++ b/Zend/tests/generators/errors/generator_extend_error.phpt @@ -0,0 +1,10 @@ +--TEST-- +The Generator class cannot be extended +--FILE-- +?php + +class ExtendedGenerator extends Generator { } + +? +--EXPECTF-- +Fatal error: Class ExtendedGenerator may not inherit from final class (Generator) in %s on line %d diff --git a/Zend/tests/generators/errors/generator_instantiate_error.phpt b/Zend/tests/generators/errors/generator_instantiate_error.phpt new file mode 100644 index 000..f8941c0 --- /dev/null +++ b/Zend/tests/generators/errors/generator_instantiate_error.phpt @@ -0,0 +1,10 @@ +--TEST-- +It's not possible to directly instantiate the Generator class +--FILE-- +?php + +new Generator; + +? +--EXPECTF-- +Catchable fatal error: The Generator class is reserved for internal use and cannot be manually instantiated in %s on line %d diff --git a/Zend/tests/generators/errors/yield_in_normal_function_error.phpt b/Zend/tests/generators/errors/yield_in_normal_function_error.phpt new file mode 100644 index 000..802510d --- /dev/null +++ b/Zend/tests/generators/errors/yield_in_normal_function_error.phpt @@ -0,0 +1,12 @@ +--TEST-- +Yield cannot be used in normal (non-generator) functions +--FILE-- +?php + +function foo() { +yield Test; +} + +? +--EXPECTF-- +Fatal error: The yield statement can only be used inside a generator function in %s on line %d diff --git a/Zend/tests/generators/errors/yield_outside_function_error.phpt b/Zend/tests/generators/errors/yield_outside_function_error.phpt new file mode 100644 index 000..fd7169d --- /dev/null +++ b/Zend/tests/generators/errors/yield_outside_function_error.phpt @@ -0,0 +1,10 @@ +--TEST-- +Yield cannot be used outside of functions +--FILE-- +?php + +yield Test; + +? +--EXPECTF-- +Fatal error: The yield statement can only be used inside a generator function in %s on line %d diff --git a/Zend/tests/generators/yield_in_normal_function_error.phpt b/Zend/tests/generators/yield_in_normal_function_error.phpt deleted file mode 100644 index 802510d..000 --- a/Zend/tests/generators/yield_in_normal_function_error.phpt +++ /dev/null @@ -1,12 +0,0 @@ ---TEST-- -Yield cannot be used in normal (non-generator) functions ---FILE-- -?php - -function foo() { -yield Test; -} - -? ---EXPECTF-- -Fatal error: The yield statement can only be used inside a generator function in %s on line %d diff --git a/Zend/tests/generators/yield_outside_function_error.phpt b/Zend/tests/generators/yield_outside_function_error.phpt deleted file mode 100644 index fd7169d..000 --- a/Zend/tests/generators/yield_outside_function_error.phpt +++ /dev/null @@ -1,10 +0,0 @@ ---TEST-- -Yield cannot be used outside of functions ---FILE-- -?php - -yield Test; - -? ---EXPECTF-- -Fatal error: The yield statement can only be used inside a generator function in %s on line %d diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 6f98dcb..21581db 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -23,6 +23,49 @@ #include zend_generators.h ZEND_API zend_class_entry *zend_ce_generator; +static zend_object_handlers zend_generator_handlers; + +typedef struct _zend_generator { + zend_object std; + /* nothing more for now */ +} zend_generator; + +static void zend_generator_free_storage(zend_generator *generator TSRMLS_DC) /* {{{ */ +{ + zend_object_std_dtor(generator-std TSRMLS_CC); + + efree(generator); +} +/* }}} */ + +static zend_object_value zend_generator_create(zend_class_entry *class_type TSRMLS_DC) /* {{{ */ +{ + zend_generator *generator; + zend_object_value object; + + generator = emalloc(sizeof(zend_generator)); + memset(generator, 0, sizeof(zend_generator)); + +
[PHP-CVS] com php-src: Add empty Generator class: Zend/Makefile.am Zend/Zend.dsp Zend/ZendTS.dsp Zend/zend_default_classes.c Zend/zend_generators.c Zend/zend_generators.h configure.in win32/build/conf
Commit:ca59e5464de78dae1f7c874a6bcc4f7ea2948b1d Author:Nikita Popov ni...@php.net Sun, 20 May 2012 00:03:27 +0200 Parents: 1cec3f12cc719ccde286a3a55f6da1a5bf9ea2e4 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=ca59e5464de78dae1f7c874a6bcc4f7ea2948b1d Log: Add empty Generator class Changed paths: M Zend/Makefile.am M Zend/Zend.dsp M Zend/ZendTS.dsp M Zend/zend_default_classes.c A Zend/zend_generators.c A Zend/zend_generators.h M configure.in M win32/build/config.w32 Diff: diff --git a/Zend/Makefile.am b/Zend/Makefile.am index 5ec4590..e5757fa 100644 --- a/Zend/Makefile.am +++ b/Zend/Makefile.am @@ -17,7 +17,8 @@ libZend_la_SOURCES=\ zend_objects_API.c zend_ts_hash.c zend_stream.c \ zend_default_classes.c \ zend_iterators.c zend_interfaces.c zend_exceptions.c \ - zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c + zend_strtod.c zend_closures.c zend_float.c zend_string.c zend_signal.c \ + zend_generators.c libZend_la_LDFLAGS = libZend_la_LIBADD = @ZEND_EXTRA_LIBS@ diff --git a/Zend/Zend.dsp b/Zend/Zend.dsp index ebe0197..23ebd45 100644 --- a/Zend/Zend.dsp +++ b/Zend/Zend.dsp @@ -159,6 +159,10 @@ SOURCE=.\zend_float.c # End Source File # Begin Source File +SOURCE=.\zend_generators.c +# End Source File +# Begin Source File + SOURCE=.\zend_hash.c # End Source File # Begin Source File diff --git a/Zend/ZendTS.dsp b/Zend/ZendTS.dsp index 3494cd4..3be2c58 100644 --- a/Zend/ZendTS.dsp +++ b/Zend/ZendTS.dsp @@ -185,6 +185,10 @@ SOURCE=.\zend_extensions.c # End Source File # Begin Source File +SOURCE=.\zend_generators.c +# End Source File +# Begin Source File + SOURCE=.\zend_hash.c # End Source File # Begin Source File diff --git a/Zend/zend_default_classes.c b/Zend/zend_default_classes.c index 73a7658..bcc43ea 100644 --- a/Zend/zend_default_classes.c +++ b/Zend/zend_default_classes.c @@ -25,6 +25,7 @@ #include zend_interfaces.h #include zend_exceptions.h #include zend_closures.h +#include zend_generators.h ZEND_API void zend_register_default_classes(TSRMLS_D) @@ -33,6 +34,7 @@ ZEND_API void zend_register_default_classes(TSRMLS_D) zend_register_default_exception(TSRMLS_C); zend_register_iterator_wrapper(TSRMLS_C); zend_register_closure_ce(TSRMLS_C); + zend_register_generator_ce(TSRMLS_C); } /* diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c new file mode 100644 index 000..6f98dcb --- /dev/null +++ b/Zend/zend_generators.c @@ -0,0 +1,47 @@ +/* + +--+ + | Zend Engine | + +--+ + | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) | + +--+ + | This source file is subject to version 2.00 of the Zend license, | + | that is bundled with this package in the file LICENSE, and is| + | available through the world-wide-web at the following url: | + | http://www.zend.com/license/2_00.txt.| + | If you did not receive a copy of the Zend license and are unable to | + | obtain it through the world-wide-web, please send a note to | + | lice...@zend.com so we can mail you a copy immediately. | + +--+ + | Authors: Nikita Popov ni...@php.net| + +--+ +*/ + +/* $Id$ */ + +#include zend.h +#include zend_API.h +#include zend_generators.h + +ZEND_API zend_class_entry *zend_ce_generator; + +static const zend_function_entry generator_functions[] = { + ZEND_FE_END +}; + +void zend_register_generator_ce(TSRMLS_D) /* {{{ */ +{ + zend_class_entry ce; + + INIT_CLASS_ENTRY(ce, Generator, generator_functions); + zend_ce_generator = zend_register_internal_class(ce TSRMLS_CC); + zend_ce_generator-ce_flags |= ZEND_ACC_FINAL_CLASS; +} +/* }}} */ + +/* + * Local variables: + * tab-width: 4 + * c-basic-offset: 4 + * indent-tabs-mode: t + * End: + */ diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h new file mode 100644 index 000..6089907 --- /dev/null +++ b/Zend/zend_generators.h @@ -0,0 +1,40 @@ +/* + +--+ + | Zend Engine | + +--+ + | Copyright (c) 1998-2012 Zend Technologies Ltd. (http://www.zend.com) | + +--+ + | This source file is subject to version 2.00 of the Zend license,
[PHP-CVS] com php-src: Add error if yield is used outside a generator: Zend/tests/generators/yield_in_normal_function_error.phpt Zend/tests/generators/yield_outside_function_error.phpt Zend/zend_compi
Commit:fd2a109f86d18b93d29153c2ddfa605651c7df05 Author:Nikita Popov ni...@php.net Sat, 19 May 2012 18:49:27 +0200 Parents: 9b51a3b96d89dc10d4ea65ceacaad22fa3420ea7 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=fd2a109f86d18b93d29153c2ddfa605651c7df05 Log: Add error if yield is used outside a generator The yield statement can only be used in generator functions, which are marked with an asterix. Changed paths: A Zend/tests/generators/yield_in_normal_function_error.phpt A Zend/tests/generators/yield_outside_function_error.phpt M Zend/zend_compile.c Diff: diff --git a/Zend/tests/generators/yield_in_normal_function_error.phpt b/Zend/tests/generators/yield_in_normal_function_error.phpt new file mode 100644 index 000..802510d --- /dev/null +++ b/Zend/tests/generators/yield_in_normal_function_error.phpt @@ -0,0 +1,12 @@ +--TEST-- +Yield cannot be used in normal (non-generator) functions +--FILE-- +?php + +function foo() { +yield Test; +} + +? +--EXPECTF-- +Fatal error: The yield statement can only be used inside a generator function in %s on line %d diff --git a/Zend/tests/generators/yield_outside_function_error.phpt b/Zend/tests/generators/yield_outside_function_error.phpt new file mode 100644 index 000..fd7169d --- /dev/null +++ b/Zend/tests/generators/yield_outside_function_error.phpt @@ -0,0 +1,10 @@ +--TEST-- +Yield cannot be used outside of functions +--FILE-- +?php + +yield Test; + +? +--EXPECTF-- +Fatal error: The yield statement can only be used inside a generator function in %s on line %d diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 0d3ea10..d2b3536 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2660,7 +2660,11 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */ void zend_do_yield(znode *expr TSRMLS_DC) /* {{{ */ { -/* do nothing for now */ + if ((CG(active_op_array)-fn_flags ZEND_ACC_GENERATOR) == 0) { + zend_error(E_COMPILE_ERROR, The \yield\ statement can only be used inside a generator function); + } + + /* do nothing for now */ } /* }}} */ -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Minor code cleanup: Zend/zend_compile.c
Commit:9b51a3b96d89dc10d4ea65ceacaad22fa3420ea7 Author:Nikita Popov ni...@php.net Sat, 19 May 2012 14:21:49 +0200 Parents: 252f623464e7cf5cb794903ba07d652c9cea9a14 Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=9b51a3b96d89dc10d4ea65ceacaad22fa3420ea7 Log: Minor code cleanup The block for the foreach separator was nested unnecessary. This commit simply removes that nesting. Changed paths: M Zend/zend_compile.c Diff: diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 399a37c..0d3ea10 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -1725,7 +1725,7 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n } { - /* Push a seperator to the switch and foreach stacks */ + /* Push a seperator to the switch stack */ zend_switch_entry switch_entry; switch_entry.cond.op_type = IS_UNUSED; @@ -1733,16 +1733,16 @@ void zend_do_begin_function_declaration(znode *function_token, znode *function_n switch_entry.control_var = 0; zend_stack_push(CG(switch_cond_stack), (void *) switch_entry, sizeof(switch_entry)); + } - { - /* Foreach stack separator */ - zend_op dummy_opline; + { + /* Push a separator to the foreach stack */ + zend_op dummy_opline; - dummy_opline.result_type = IS_UNUSED; - dummy_opline.op1_type = IS_UNUSED; + dummy_opline.result_type = IS_UNUSED; + dummy_opline.op1_type = IS_UNUSED; - zend_stack_push(CG(foreach_copy_stack), (void *) dummy_opline, sizeof(zend_op)); - } + zend_stack_push(CG(foreach_copy_stack), (void *) dummy_opline, sizeof(zend_op)); } if (CG(doc_comment)) { -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Add T_YIELD yield keyword: Zend/zend_compile.c Zend/zend_language_parser.y Zend/zend_language_scanner.c Zend/zend_language_scanner.l Zend/zend_language_scanner_defs.h ext/stan
Commit:9b101ac8b364610c20f710b8c6c631db5e6230a5 Author:Nikita Popov ni...@php.net Tue, 15 May 2012 18:30:48 +0200 Parents: d0d7340d50f178691c8e436391168cf6cc1fea3e Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=9b101ac8b364610c20f710b8c6c631db5e6230a5 Log: Add T_YIELD yield keyword Changed paths: M Zend/zend_compile.c M Zend/zend_language_parser.y M Zend/zend_language_scanner.c M Zend/zend_language_scanner.l M Zend/zend_language_scanner_defs.h M ext/standard/url_scanner_ex.c Diff: Diff exceeded maximum size -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Drop obsolete test: tests/lang/foreachLoop.007.phpt
Commit:1b5b839312b2ec1f6d38f826a592edf83188fc1e Author:Nikita Popov ni...@php.net Sat, 1 Sep 2012 20:10:12 +0200 Parents: 53351d087dfa94569a7a65b9f4167e8f0765e05a Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=1b5b839312b2ec1f6d38f826a592edf83188fc1e Log: Drop obsolete test Changed paths: D tests/lang/foreachLoop.007.phpt Diff: diff --git a/tests/lang/foreachLoop.007.phpt b/tests/lang/foreachLoop.007.phpt deleted file mode 100644 index 269286d..000 --- a/tests/lang/foreachLoop.007.phpt +++ /dev/null @@ -1,11 +0,0 @@ ---TEST-- -Foreach loop tests - error case: reference to constant array. ---FILE-- -?php -echo \nReference to constant array\n; -foreach (array(1,2) as $v) { - var_dump($v); -} -? ---EXPECTF-- -Fatal error: Cannot create references to elements of a temporary array expression in %sforeachLoop.007.php on line %d -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Fix leak when yielding array as key: Zend/tests/generators/yield_array_key.phpt Zend/zend_vm_def.h Zend/zend_vm_execute.h
Commit:ddeb3df0b05e79213e52667f3061dc9d635e Author:Nikita Popov ni...@php.net Sat, 1 Sep 2012 20:31:40 +0200 Parents: 1b5b839312b2ec1f6d38f826a592edf83188fc1e Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=ddeb3df0b05e79213e52667f3061dc9d635e Log: Fix leak when yielding array as key The code was copy-pasted and I forgot to change OP1 to OP2 in that one place. Changed paths: A Zend/tests/generators/yield_array_key.phpt M Zend/zend_vm_def.h M Zend/zend_vm_execute.h Diff: diff --git a/Zend/tests/generators/yield_array_key.phpt b/Zend/tests/generators/yield_array_key.phpt new file mode 100644 index 000..5afba00 --- /dev/null +++ b/Zend/tests/generators/yield_array_key.phpt @@ -0,0 +1,18 @@ +--TEST-- +Array keys can be yielded from generators +--FILE-- +?php + +function gen() { +yield [] = 1; +} + +$gen = gen(); +var_dump($gen-key()); +var_dump($gen-current()); + +? +--EXPECT-- +array(0) { +} +int(1) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index ffd81b0..f683ff2 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -5511,7 +5511,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE INIT_PZVAL_COPY(copy, key); /* Temporary variables don't need ctor copying */ - if (!IS_OP1_TMP_FREE()) { + if (!IS_OP2_TMP_FREE()) { zval_copy_ctor(copy); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index b0e05b1..f8a8905 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -5005,7 +5005,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(ZEND_OPCODE_HANDLER_ INIT_PZVAL_COPY(copy, key); /* Temporary variables don't need ctor copying */ - if (!0) { + if (!1) { zval_copy_ctor(copy); } @@ -9553,7 +9553,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(ZEND_OPCODE_HANDLER_ INIT_PZVAL_COPY(copy, key); /* Temporary variables don't need ctor copying */ - if (!1) { + if (!0) { zval_copy_ctor(copy); } @@ -11266,7 +11266,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR INIT_PZVAL_COPY(copy, key); /* Temporary variables don't need ctor copying */ - if (!1) { + if (!0) { zval_copy_ctor(copy); } @@ -11846,7 +11846,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(ZEND_OPCODE_HANDLER INIT_PZVAL_COPY(copy, key); /* Temporary variables don't need ctor copying */ - if (!1) { + if (!0) { zval_copy_ctor(copy); } @@ -12537,7 +12537,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG INIT_PZVAL_COPY(copy, key); /* Temporary variables don't need ctor copying */ - if (!1) { + if (!0) { zval_copy_ctor(copy); } @@ -18543,7 +18543,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR INIT_PZVAL_COPY(copy, key); /* Temporary variables don't need ctor copying */ - if (!0) { + if (!1) { zval_copy_ctor(copy); } @@ -27081,7 +27081,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(ZEND_OPCODE_HANDLER INIT_PZVAL_COPY(copy, key); /* Temporary variables don't need ctor copying */ - if (!0) { + if (!1) { zval_copy_ctor(copy); } @@ -35600,7 +35600,7 @@ static int ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARG INIT_PZVAL_COPY(copy, key); /* Temporary variables don't need ctor copying */ - if (!0) { + if (!1) { zval_copy_ctor(copy); } -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: fix NEWS: NEWS
Commit:f7d51df5c65e47a5ef8a6d81f2e13044dd926492 Author:Stanislav Malyshev s...@php.net Sat, 1 Sep 2012 16:55:51 -0700 Parents: f3108b5f818b2757d2e518f37d3927e83858ae4f Branches: PHP-5.4 master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=f7d51df5c65e47a5ef8a6d81f2e13044dd926492 Log: fix NEWS Changed paths: M NEWS Diff: diff --git a/NEWS b/NEWS index 62e2038..60bb235 100644 --- a/NEWS +++ b/NEWS @@ -2,11 +2,21 @@ PHP NEWS ||| ?? ??? 2012, PHP 5.4.8 -?? ??? 2012, PHP 5.4.7 - - Core: + . Added optional second argument for assert() to specify custom message. Patch +by Lonny Kapelushnik (lo...@lonnylot.com). (Lars) . Fixed bug #62976 (Notice: could not be converted to int when comparing some builtin classes). (Laruence) + . Fixed bug #62955 (Only one directive is loaded from Per Directory Values +Windows registry). (aserbulov at parallels dot com) + +- SPL: + . Bug #62987 (Assigning to ArrayObject[null][something] overrides all +undefined variables). (Laruence) + +?? ??? 2012, PHP 5.4.7 + +- Core: . Fixed bug (segfault while build with zts and GOTO vm-kind). (Laruence) . Fixed bug #62844 (parse_url() does not recognize //). (Andrew Faulds). . Fixed bug #62829 (stdint.h included on platform where HAVE_STDINT_H is not @@ -25,8 +35,6 @@ PHP NEWS handler). (Lonny Kapelushnik) . Fixed bug #40459 (Stat and Dir stream wrapper methods do not call constructor). (Stas) - . Added optional second argument for assert() to specify custom message. Patch -by Lonny Kapelushnik (lo...@lonnylot.com). (Lars) - CURL: . Fixed bug #62912 (CURLINFO_PRIMARY_* AND CURLINFO_LOCAL_* not exposed). @@ -64,8 +72,6 @@ PHP NEWS when close handler call exit). (Laruence) - SPL: - . Bug #62987 (Assigning to ArrayObject[null][something] overrides all -undefined variables). (Laruence) . Fixed bug #62904 (Crash when cloning an object which inherits SplFixedArray) (Laruence) . Implemented FR #62840 (Add sort flag to ArrayObject::ksort). (Laruence) -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php
[PHP-CVS] com php-src: Fix test failed due to new Token T_YIELD: ext/tokenizer/tests/bug60097.phpt
Commit:4e84f725544153d5b6fff99adc274d11f79b9079 Author:Xinchen Hui larue...@php.net Sun, 2 Sep 2012 13:15:23 +0800 Parents: 664e763c2c59230dab99573d9291a9f45daecade Branches: master Link: http://git.php.net/?p=php-src.git;a=commitdiff;h=4e84f725544153d5b6fff99adc274d11f79b9079 Log: Fix test failed due to new Token T_YIELD Changed paths: M ext/tokenizer/tests/bug60097.phpt Diff: diff --git a/ext/tokenizer/tests/bug60097.phpt b/ext/tokenizer/tests/bug60097.phpt index e9f1bd6..2116866 100644 --- a/ext/tokenizer/tests/bug60097.phpt +++ b/ext/tokenizer/tests/bug60097.phpt @@ -17,7 +17,7 @@ array(14) { [0]= array(3) { [0]= -int(373) +int(374) [1]= string(6) ?php @@ -27,7 +27,7 @@ array(14) { [1]= array(3) { [0]= -int(377) +int(378) [1]= string(8) DOC1 @@ -37,7 +37,7 @@ array(14) { [2]= array(3) { [0]= -int(380) +int(381) [1]= string(1) { [2]= @@ -46,7 +46,7 @@ array(14) { [3]= array(3) { [0]= -int(309) +int(310) [1]= string(2) $s [2]= @@ -57,7 +57,7 @@ array(14) { [5]= array(3) { [0]= -int(377) +int(378) [1]= string(8) DOC2 @@ -67,7 +67,7 @@ array(14) { [6]= array(3) { [0]= -int(378) +int(379) [1]= string(4) DOC2 [2]= @@ -76,7 +76,7 @@ array(14) { [7]= array(3) { [0]= -int(376) +int(377) [1]= string(1) @@ -90,7 +90,7 @@ array(14) { [10]= array(3) { [0]= -int(314) +int(315) [1]= string(1) @@ -100,7 +100,7 @@ array(14) { [11]= array(3) { [0]= -int(378) +int(379) [1]= string(4) DOC1 [2]= @@ -111,7 +111,7 @@ array(14) { [13]= array(3) { [0]= -int(376) +int(377) [1]= string(1) -- PHP CVS Mailing List (http://www.php.net/) To unsubscribe, visit: http://www.php.net/unsub.php