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.
This commit is contained in:
Nikita Popov 2012-08-13 17:17:18 +02:00
parent f4ce364628
commit ae716939eb
2 changed files with 24 additions and 24 deletions

View file

@ -2513,6 +2513,18 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
zend_bool nested; zend_bool nested;
zend_op_array *op_array = EX(op_array); 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(current_execute_data) = EX(prev_execute_data);
EG(opline_ptr) = NULL; EG(opline_ptr) = NULL;
if (!EG(active_symbol_table)) { 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_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
ZEND_VM_CONTINUE(); ZEND_VM_CONTINUE();
} else { } 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); ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
} }
} }

View file

@ -496,6 +496,18 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
zend_bool nested; zend_bool nested;
zend_op_array *op_array = EX(op_array); 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(current_execute_data) = EX(prev_execute_data);
EG(opline_ptr) = NULL; EG(opline_ptr) = NULL;
if (!EG(active_symbol_table)) { 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_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
ZEND_VM_CONTINUE(); ZEND_VM_CONTINUE();
} else { } 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); return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
} }
} }