From a9a5f7aca61d4bec9ce2cf5dc967bb7c0ed651cd Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Tue, 11 Dec 2012 17:25:32 +0400 Subject: [PATCH] - generators API exported for extensions - improved RETURN sequence to avoid redundant check if op_array is a generator --- Zend/zend_generators.c | 6 +++--- Zend/zend_generators.h | 6 +++--- Zend/zend_vm_def.h | 42 +++++++++++++++++++++++++++--------------- Zend/zend_vm_execute.h | 42 +++++++++++++++++++++++++++--------------- 4 files changed, 60 insertions(+), 36 deletions(-) diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index dc7ae1479b..1844be86d5 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -27,7 +27,7 @@ ZEND_API zend_class_entry *zend_ce_generator; static zend_object_handlers zend_generator_handlers; -void zend_generator_close(zend_generator *generator, zend_bool finished_execution TSRMLS_DC) /* {{{ */ +ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished_execution TSRMLS_DC) /* {{{ */ { if (generator->execute_data) { zend_execute_data *execute_data = generator->execute_data; @@ -338,7 +338,7 @@ static zend_object_value zend_generator_create(zend_class_entry *class_type TSRM /* Requires globals EG(scope), EG(current_scope), EG(This), * EG(active_symbol_table) and EG(current_execute_data). */ -zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC) /* {{{ */ +ZEND_API zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC) /* {{{ */ { zval *return_value; zend_generator *generator; @@ -399,7 +399,7 @@ static zend_function *zend_generator_get_constructor(zval *object TSRMLS_DC) /* } /* }}} */ -void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */ +ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */ { if (EG(exception)) { return; diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h index 90f8160f71..7e6da1371f 100644 --- a/Zend/zend_generators.h +++ b/Zend/zend_generators.h @@ -62,9 +62,9 @@ static const zend_uchar ZEND_GENERATOR_FORCED_CLOSE = 0x2; static const zend_uchar ZEND_GENERATOR_AT_FIRST_YIELD = 0x4; void zend_register_generator_ce(TSRMLS_D); -zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC); -void zend_generator_close(zend_generator *generator, zend_bool finished_execution TSRMLS_DC); -void zend_generator_resume(zend_generator *generator TSRMLS_DC); +ZEND_API zval *zend_generator_create_zval(zend_op_array *op_array TSRMLS_DC); +ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished_execution TSRMLS_DC); +ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC); #endif diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index edbffe12c9..c5d1748cd2 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1850,18 +1850,6 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) /* return from finally block called because of unhandled exception */ zend_exception_restore(TSRMLS_C); } - - /* Generators go throw a different cleanup process */ - if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { - /* 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; @@ -2969,7 +2957,20 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY) ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, ANY, ANY) { - ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (EXPECTED(EG(exception) == NULL) && + UNEXPECTED(EG(prev_exception) != NULL)) { + /* return from finally block called because of unhandled exception */ + zend_exception_restore(TSRMLS_C); + } + + /* 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_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY) @@ -5124,7 +5125,11 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]); ZEND_VM_CONTINUE(); } else { - ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN); + } else { + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + } } } @@ -5151,7 +5156,11 @@ ZEND_VM_HANDLER(150, ZEND_USER_OPCODE, ANY, ANY) case ZEND_USER_OPCODE_CONTINUE: ZEND_VM_CONTINUE(); case ZEND_USER_OPCODE_RETURN: - ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN); + } else { + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + } case ZEND_USER_OPCODE_ENTER: ZEND_VM_ENTER(); case ZEND_USER_OPCODE_LEAVE: @@ -5444,6 +5453,9 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY) zend_exception_restore(TSRMLS_C); ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); ZEND_VM_CONTINUE(); + } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + zend_exception_restore(TSRMLS_C); + ZEND_VM_DISPATCH_TO_HANDLER(ZEND_GENERATOR_RETURN); } else { zend_exception_restore(TSRMLS_C); ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 80967bdfb3..7c11016c06 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -392,18 +392,6 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS) zend_exception_restore(TSRMLS_C); } - /* Generators go throw a different cleanup process */ - if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { - /* 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)) { @@ -705,7 +693,20 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(ZEND_OPCODE_HANDLER static int ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + /* The generator object is stored in return_value_ptr_ptr */ + zend_generator *generator = (zend_generator *) EG(return_value_ptr_ptr); + + if (EXPECTED(EG(exception) == NULL) && + UNEXPECTED(EG(prev_exception) != NULL)) { + /* return from finally block called because of unhandled exception */ + zend_exception_restore(TSRMLS_C); + } + + /* Close the generator to free up resources */ + zend_generator_close(generator, 1 TSRMLS_CC); + + /* Pass execution back to handling code */ + ZEND_VM_RETURN(); } static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -1086,7 +1087,11 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]); ZEND_VM_CONTINUE(); } else { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } } } @@ -1113,7 +1118,11 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS case ZEND_USER_OPCODE_CONTINUE: ZEND_VM_CONTINUE(); case ZEND_USER_OPCODE_RETURN: - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } else { + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } case ZEND_USER_OPCODE_ENTER: ZEND_VM_ENTER(); case ZEND_USER_OPCODE_LEAVE: @@ -1169,6 +1178,9 @@ static int ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) zend_exception_restore(TSRMLS_C); ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]); ZEND_VM_CONTINUE(); + } else if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_GENERATOR) != 0)) { + zend_exception_restore(TSRMLS_C); + return ZEND_GENERATOR_RETURN_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); } else { zend_exception_restore(TSRMLS_C); return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); -- 2.40.0