From ae716939eb500f962336d37b96069cb7452c25df Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Mon, 13 Aug 2012 17:17:18 +0200 Subject: [PATCH] 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. --- Zend/zend_vm_def.h | 24 ++++++++++++------------ Zend/zend_vm_execute.h | 24 ++++++++++++------------ 2 files changed, 24 insertions(+), 24 deletions(-) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 83ae5c5ba43f9..49ee3148e3d03 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 495b520ecb22f..94c2a7cf166b4 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); } }