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;
/* 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;
}
/* }}} */
-void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */
+ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{ */
{
if (EG(exception)) {
return;
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
/* 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;
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)
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);
+ }
}
}
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:
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);
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)) {
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)
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);
+ }
}
}
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:
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);