Improved "finally" im[plementation

This commit is contained in:
Dmitry Stogov 2012-11-22 15:17:05 +04:00
parent a213caf4c3
commit eb4825b50b
8 changed files with 375 additions and 433 deletions

View File

@ -2709,6 +2709,7 @@ static int zend_add_try_element(zend_uint try_op TSRMLS_DC) /* {{{ */
CG(active_op_array)->try_catch_array = erealloc(CG(active_op_array)->try_catch_array, sizeof(zend_try_catch_element)*CG(active_op_array)->last_try_catch);
CG(active_op_array)->try_catch_array[try_catch_offset].try_op = try_op;
CG(active_op_array)->try_catch_array[try_catch_offset].catch_op = 0;
CG(active_op_array)->try_catch_array[try_catch_offset].finally_op = 0;
CG(active_op_array)->try_catch_array[try_catch_offset].finally_end = 0;
return try_catch_offset;
@ -2770,9 +2771,25 @@ void zend_do_try(znode *try_token TSRMLS_DC) /* {{{ */
}
/* }}} */
void zend_do_finally(znode *finally_token TSRMLS_DC) /* {{{ */ {
void zend_do_finally(znode *finally_token TSRMLS_DC) /* {{{ */
{
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
finally_token->u.op.opline_num = get_next_op_number(CG(active_op_array));
} /* }}} */
/* call the the "finally" block */
opline->opcode = ZEND_FAST_CALL;
SET_UNUSED(opline->op1);
opline->op1.opline_num = finally_token->u.op.opline_num + 1;
SET_UNUSED(opline->op2);
/* jump to code after the "finally" block,
* the actual jump address is going to be set in zend_do_end_finally()
*/
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_JMP;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
}
/* }}} */
void zend_do_begin_catch(znode *catch_token, znode *class_name, znode *catch_var, znode *first_catch TSRMLS_DC) /* {{{ */
{
@ -2837,18 +2854,19 @@ void zend_do_end_finally(znode *try_token, znode* catch_token, znode *finally_to
zend_error(E_COMPILE_ERROR, "Cannot use try without catch or finally");
}
if (finally_token->op_type != IS_UNUSED) {
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_op = finally_token->u.op.opline_num;
zend_op *opline;
CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_op = finally_token->u.op.opline_num + 1;
CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].finally_end = get_next_op_number(CG(active_op_array));
CG(active_op_array)->has_finally_block = 1;
opline->opcode = ZEND_LEAVE;
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
opline->opcode = ZEND_FAST_RET;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
CG(active_op_array)->opcodes[finally_token->u.op.opline_num].op1.opline_num = get_next_op_number(CG(active_op_array));
}
if (catch_token->op_type == IS_UNUSED) {
CG(active_op_array)->try_catch_array[try_token->u.op.opline_num].catch_op = 0;
}
}
/* }}} */

View File

@ -387,8 +387,7 @@ struct _zend_execute_data {
zend_class_entry *current_called_scope;
zval *current_this;
zval *current_object;
zend_uint leaving;
zend_uint leaving_dest;
struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
};
#define EX(element) execute_data.element
@ -826,6 +825,9 @@ int zend_add_literal(zend_op_array *op_array, const zval *zv TSRMLS_DC);
#define ZEND_RETURNS_FUNCTION 1<<0
#define ZEND_RETURNS_NEW 1<<1
#define ZEND_FAST_RET_TO_CATCH 1
#define ZEND_FAST_RET_TO_FINALLY 2
END_EXTERN_C()
#define ZEND_CLONE_FUNC_NAME "__clone"

View File

@ -60,7 +60,6 @@ void zend_generator_close(zend_generator *generator, zend_bool finished_executio
* the resume. */
if (finally_op_num) {
execute_data->opline = &op_array->opcodes[finally_op_num];
execute_data->leaving = ZEND_RETURN;
generator->flags |= ZEND_GENERATOR_FORCED_CLOSE;
zend_generator_resume(generator TSRMLS_CC);
return;

View File

@ -499,24 +499,168 @@ static void zend_extension_op_array_handler(zend_extension *extension, zend_op_a
}
}
static void zend_check_finally_breakout(zend_op_array *op_array, zend_op *opline, zend_uint dst_num TSRMLS_DC) {
zend_uint i, op_num = opline - op_array->opcodes;
for (i=0; i < op_array->last_try_catch; i++) {
static void zend_check_finally_breakout(zend_op_array *op_array, zend_uint op_num, zend_uint dst_num TSRMLS_DC)
{
zend_uint i;
for (i = 0; i < op_array->last_try_catch; i++) {
if (op_array->try_catch_array[i].try_op > op_num) {
break;
}
if ((op_num >= op_array->try_catch_array[i].finally_op
&& op_num < op_array->try_catch_array[i].finally_end)
&& (dst_num >= op_array->try_catch_array[i].finally_end
&& op_num <= op_array->try_catch_array[i].finally_end)
&& (dst_num > op_array->try_catch_array[i].finally_end
|| dst_num < op_array->try_catch_array[i].finally_op)) {
CG(in_compilation) = 1;
CG(active_op_array) = op_array;
CG(zend_lineno) = opline->lineno;
CG(zend_lineno) = op_array->opcodes[op_num].lineno;
zend_error(E_COMPILE_ERROR, "jump out of a finally block is disallowed");
}
}
}
static void zend_resolve_finally_call(zend_op_array *op_array, zend_uint op_num, zend_uint dst_num TSRMLS_DC)
{
zend_uint start_op;
zend_op *opline;
zend_uint i = op_array->last_try_catch;
if (dst_num != (zend_uint)-1) {
zend_check_finally_breakout(op_array, op_num, dst_num TSRMLS_CC);
}
/* the backward order is mater */
while (i > 0) {
i--;
if (op_array->try_catch_array[i].finally_op &&
op_num >= op_array->try_catch_array[i].try_op &&
op_num < op_array->try_catch_array[i].finally_op - 1 &&
(dst_num < op_array->try_catch_array[i].try_op ||
dst_num > op_array->try_catch_array[i].finally_end)) {
/* we have a jump out of try block that needs executing finally */
/* generate a FAST_CALL to finaly block */
start_op = get_next_op_number(op_array);
opline = get_next_op(op_array TSRMLS_CC);
opline->opcode = ZEND_FAST_CALL;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
opline->op1.opline_num = op_array->try_catch_array[i].finally_op;
if (op_array->try_catch_array[i].catch_op) {
opline->extended_value = 1;
opline->op2.opline_num = op_array->try_catch_array[i].catch_op;
}
/* generate a sequence of FAST_CALL to upward finaly block */
while (i > 0) {
i--;
if (op_array->try_catch_array[i].finally_op &&
op_num >= op_array->try_catch_array[i].try_op &&
op_num < op_array->try_catch_array[i].finally_op - 1 &&
(dst_num < op_array->try_catch_array[i].try_op ||
dst_num > op_array->try_catch_array[i].finally_end)) {
opline = get_next_op(op_array TSRMLS_CC);
opline->opcode = ZEND_FAST_CALL;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
opline->op1.opline_num = op_array->try_catch_array[i].finally_op;
}
}
/* Finish the sequence with original opcode */
opline = get_next_op(op_array TSRMLS_CC);
*opline = op_array->opcodes[op_num];
/* Replace original opcode with jump to this sequence */
opline = op_array->opcodes + op_num;
opline->opcode = ZEND_JMP;
SET_UNUSED(opline->op1);
SET_UNUSED(opline->op2);
opline->op1.opline_num = start_op;
break;
}
}
}
static void zend_resolve_finally_ret(zend_op_array *op_array, zend_uint op_num TSRMLS_DC)
{
int i;
zend_uint catch_op_num = 0, finally_op_num = 0;
for (i = 0; i < op_array->last_try_catch; i++) {
if (op_array->try_catch_array[i].try_op > op_num) {
break;
}
if (op_num < op_array->try_catch_array[i].finally_op) {
finally_op_num = op_array->try_catch_array[i].finally_op;
}
if (op_num < op_array->try_catch_array[i].catch_op) {
catch_op_num = op_array->try_catch_array[i].catch_op;
}
}
if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) {
/* in case of unhandled exception return to upward finally block */
op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_FINALLY;
op_array->opcodes[op_num].op2.opline_num = finally_op_num;
} else if (catch_op_num) {
/* in case of unhandled exception return to upward catch block */
op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_CATCH;
op_array->opcodes[op_num].op2.opline_num = catch_op_num;
}
}
static void zend_resolve_finally_calls(zend_op_array *op_array TSRMLS_DC)
{
zend_uint i;
zend_op *opline;
for (i = 0; i < op_array->last; i++) {
opline = op_array->opcodes + i;
switch (opline->opcode) {
case ZEND_RETURN:
case ZEND_RETURN_BY_REF:
zend_resolve_finally_call(op_array, i, (zend_uint)-1 TSRMLS_CC);
break;
case ZEND_BRK:
case ZEND_CONT:
{
int nest_levels, array_offset;
zend_brk_cont_element *jmp_to;
nest_levels = Z_LVAL(op_array->literals[opline->op2.constant].constant);
array_offset = opline->op1.opline_num;
do {
jmp_to = &op_array->brk_cont_array[array_offset];
if (nest_levels > 1) {
array_offset = jmp_to->parent;
}
} while (--nest_levels > 0);
zend_resolve_finally_call(op_array, i, opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont TSRMLS_CC);
break;
}
case ZEND_GOTO:
if (Z_TYPE(op_array->literals[opline->op2.constant].constant) != IS_LONG) {
zend_uint num = opline->op2.constant;
opline->op2.zv = &op_array->literals[opline->op2.constant].constant;
zend_resolve_goto_label(op_array, opline, 1 TSRMLS_CC);
opline->op2.constant = num;
}
/* break omitted intentionally */
case ZEND_JMP:
zend_resolve_finally_call(op_array, i, opline->op1.opline_num TSRMLS_CC);
break;
case ZEND_FAST_RET:
zend_resolve_finally_ret(op_array, i TSRMLS_CC);
break;
default:
break;
}
}
}
ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
{
zend_op *opline, *end;
@ -524,6 +668,9 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
if (op_array->type!=ZEND_USER_FUNCTION && op_array->type!=ZEND_EVAL_CODE) {
return 0;
}
if (op_array->has_finally_block) {
zend_resolve_finally_calls(op_array TSRMLS_CC);
}
if (CG(compiler_options) & ZEND_COMPILE_EXTENDED_INFO) {
zend_update_extended_info(op_array TSRMLS_CC);
}
@ -560,30 +707,9 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
}
/* break omitted intentionally */
case ZEND_JMP:
if (op_array->last_try_catch) {
zend_check_finally_breakout(op_array, opline, opline->op1.opline_num TSRMLS_CC);
}
case ZEND_FAST_CALL:
opline->op1.jmp_addr = &op_array->opcodes[opline->op1.opline_num];
break;
case ZEND_BRK:
case ZEND_CONT:
if (op_array->last_try_catch) {
int nest_levels, array_offset;
zend_brk_cont_element *jmp_to;
nest_levels = Z_LVAL_P(opline->op2.zv);
array_offset = opline->op1.opline_num;
do {
jmp_to = &op_array->brk_cont_array[array_offset];
if (nest_levels > 1) {
array_offset = jmp_to->parent;
}
} while (--nest_levels > 0);
if (op_array->last_try_catch) {
zend_check_finally_breakout(op_array, opline, jmp_to->brk TSRMLS_CC);
}
}
break;
case ZEND_JMPZ:
case ZEND_JMPNZ:
case ZEND_JMPZ_EX:

View File

@ -1845,6 +1845,12 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
zend_bool nested;
zend_op_array *op_array = EX(op_array);
if (EXPECTED(EG(exception) == NULL) &&
UNEXPECTED(EG(prev_exception) != NULL)) {
/* return from finally block called because of unhandled exception */
zend_exception_restore(TSRMLS_C);
}
/* 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 */
@ -2125,101 +2131,6 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HELPER_EX(zend_finally_handler_leaving, ANY, ANY, int type)
{
USE_OPLINE
zend_uint i, op_num = opline - EX(op_array)->opcodes;
zend_uint catch_op_num = 0, finally_op_num = 0;
SAVE_OPLINE();
switch (type) {
case ZEND_THROW:
case ZEND_RETURN:
case ZEND_RETURN_BY_REF:
case ZEND_LEAVE:
{
if (EG(prev_exception) || (type == ZEND_LEAVE && EG(exception))) {
for (i=0; i<EX(op_array)->last_try_catch; i++) {
if (EX(op_array)->try_catch_array[i].try_op > op_num) {
break;
}
if (op_num < EX(op_array)->try_catch_array[i].finally_op) {
finally_op_num = EX(op_array)->try_catch_array[i].finally_op;
}
if (op_num < EX(op_array)->try_catch_array[i].catch_op) {
catch_op_num = EX(op_array)->try_catch_array[i].catch_op;
}
}
} else {
for (i=0; i<EX(op_array)->last_try_catch; i++) {
if (EX(op_array)->try_catch_array[i].try_op > op_num) {
break;
}
if (op_num < EX(op_array)->try_catch_array[i].finally_op) {
finally_op_num = EX(op_array)->try_catch_array[i].finally_op;
}
}
}
if (catch_op_num && finally_op_num) {
/* EG(exception) || EG(prev_exception) */
if (catch_op_num > finally_op_num) {
zend_exception_save(TSRMLS_C);
EX(leaving) = ZEND_THROW;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
} else {
EX(leaving) = 0;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
}
} else if (catch_op_num) {
EX(leaving) = 0;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
} else if (finally_op_num) {
zend_exception_save(TSRMLS_C);
if (type != ZEND_LEAVE) {
EX(leaving) = type;
}
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
} else if (EX(leaving) && type != ZEND_LEAVE) {
/* leave it to ZEND_LEAVE */
EX(leaving) = type;
ZEND_VM_NEXT_OPCODE();
} else {
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
}
break;
case ZEND_JMP:
case ZEND_BRK:
case ZEND_CONT:
case ZEND_GOTO:
{
/* these can not occurred in exception context */
for (i=0; i<EG(active_op_array)->last_try_catch; i++) {
if (EG(active_op_array)->try_catch_array[i].try_op > op_num) {
break;
}
if (op_num < EG(active_op_array)->try_catch_array[i].finally_op
&& (EX(leaving_dest) < EG(active_op_array)->try_catch_array[i].try_op
|| EX(leaving_dest) >= EG(active_op_array)->try_catch_array[i].finally_end)) {
finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op;
}
}
if (finally_op_num) {
EX(leaving) = type;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
} else {
EX(leaving) = 0;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[EX(leaving_dest)]);
}
}
break;
}
ZEND_VM_CONTINUE();
}
ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY)
{
USE_OPLINE
@ -2227,12 +2138,8 @@ ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY)
#if DEBUG_ZEND>=2
printf("Jumping to %d\n", opline->op1.opline_num);
#endif
if (EXPECTED(!EX(op_array)->has_finally_block)) {
ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
EX(leaving_dest) = opline->op1.jmp_addr - EX(op_array)->opcodes;
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_JMP);
ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
ZEND_VM_CONTINUE();
}
ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMP|VAR|CV, ANY)
@ -2972,11 +2879,7 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
*EG(return_value_ptr_ptr) = ret;
}
FREE_OP1_IF_VAR();
if (EXPECTED(!EX(op_array)->has_finally_block)) {
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_RETURN);
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
@ -3048,18 +2951,11 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
} while (0);
FREE_OP1_IF_VAR();
if (EXPECTED(!EX(op_array)->has_finally_block)) {
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_DISPATCH_TO_HELPER(zend_leave_helper);
}
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);
}
@ -3404,11 +3300,7 @@ ZEND_VM_HANDLER(50, ZEND_BRK, ANY, CONST)
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
EX(op_array), EX_Ts() TSRMLS_CC);
FREE_OP2();
if (EXPECTED(!EX(op_array)->has_finally_block)) {
ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
}
EX(leaving_dest) = el->brk;
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_BRK);
ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
}
ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
@ -3420,11 +3312,7 @@ ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
EX(op_array), EX_Ts() TSRMLS_CC);
FREE_OP2();
if (EXPECTED(!EX(op_array)->has_finally_block)) {
ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
}
EX(leaving_dest) = el->cont;
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_CONT);
ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
}
ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
@ -3451,11 +3339,7 @@ ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
}
break;
}
if (EXPECTED(!EX(op_array)->has_finally_block)) {
ZEND_VM_JMP(opline->op1.jmp_addr);
}
EX(leaving_dest) = opline->op1.jmp_addr - EX(op_array)->opcodes;
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_GOTO);
ZEND_VM_JMP(opline->op1.jmp_addr);
}
ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
@ -5134,7 +5018,6 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes;
int i;
zend_uint catch_op_num = 0, finally_op_num = 0;
int catched = 0, finally = 0;
void **stack_frame;
/* Figure out where the next stack frame (which maybe contains pushed
@ -5167,11 +5050,9 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
}
if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) {
catch_op_num = EX(op_array)->try_catch_array[i].catch_op;
catched = i + 1;
}
if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) {
finally_op_num = EX(op_array)->try_catch_array[i].finally_op;
finally = i + 1;
}
}
@ -5199,7 +5080,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
/* further blocks will not be relevant... */
break;
} else if (op_num < EX(op_array)->brk_cont_array[i].brk) {
if (!catched ||
if (!catch_op_num ||
catch_op_num >= EX(op_array)->brk_cont_array[i].brk) {
zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk];
@ -5231,26 +5112,14 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
}
EX(old_error_reporting) = NULL;
if (catched && finally) {
if (finally_op_num > catch_op_num) {
EX(leaving) = 0;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
ZEND_VM_CONTINUE();
} else {
zend_exception_save(TSRMLS_C);
EX(leaving) = ZEND_THROW;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
ZEND_VM_CONTINUE();
}
} else if (catched) {
EX(leaving) = 0;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
ZEND_VM_CONTINUE();
} else if (finally) {
if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) {
zend_exception_save(TSRMLS_C);
EX(leaving) = ZEND_THROW;
EX(fast_ret) = NULL;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
ZEND_VM_CONTINUE();
} else if (catch_op_num) {
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
ZEND_VM_CONTINUE();
} else {
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
@ -5371,30 +5240,6 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED)
ZEND_VM_NEXT_OPCODE();
}
ZEND_VM_HANDLER(159, ZEND_LEAVE, ANY, ANY)
{
zend_exception_restore(TSRMLS_C);
if (!EX(leaving)) {
ZEND_VM_NEXT_OPCODE();
} else {
zend_uint leaving = EX(leaving);
switch (leaving) {
case ZEND_RETURN:
case ZEND_RETURN_BY_REF:
case ZEND_THROW:
leaving = ZEND_LEAVE;
case ZEND_JMP:
case ZEND_BRK:
case ZEND_CONT:
case ZEND_GOTO:
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, leaving);
break;
}
}
ZEND_VM_CONTINUE();
}
ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSED)
{
USE_OPLINE
@ -5552,4 +5397,42 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
ZEND_VM_RETURN();
}
ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY)
{
USE_OPLINE
if (opline->extended_value &&
UNEXPECTED(EG(prev_exception) != NULL)) {
/* in case of unhandled exception jump to catch block instead of finally */
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
}
EX(fast_ret) = opline + 1;
ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
ZEND_VM_CONTINUE();
}
ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY)
{
if (EX(fast_ret)) {
ZEND_VM_SET_OPCODE(EX(fast_ret));
ZEND_VM_CONTINUE();
} else {
/* special case for unhandled exceptions */
USE_OPLINE
if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) {
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
} else if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) {
zend_exception_restore(TSRMLS_C);
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
} else {
zend_exception_restore(TSRMLS_C);
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
}
}
ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper)

View File

@ -385,7 +385,6 @@ zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_arra
EX(prev_execute_data) = EG(current_execute_data);
EG(current_execute_data) = execute_data;
EX(nested) = nested;
EX(leaving) = 0;
if (!op_array->run_time_cache && op_array->last_cache_slot) {
op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
@ -466,6 +465,12 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
zend_bool nested;
zend_op_array *op_array = EX(op_array);
if (EXPECTED(EG(exception) == NULL) &&
UNEXPECTED(EG(prev_exception) != NULL)) {
/* return from finally block called because of unhandled exception */
zend_exception_restore(TSRMLS_C);
}
/* 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 */
@ -746,101 +751,6 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
ZEND_VM_NEXT_OPCODE();
}
static int ZEND_FASTCALL zend_finally_handler_leaving_SPEC(int type, ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zend_uint i, op_num = opline - EX(op_array)->opcodes;
zend_uint catch_op_num = 0, finally_op_num = 0;
SAVE_OPLINE();
switch (type) {
case ZEND_THROW:
case ZEND_RETURN:
case ZEND_RETURN_BY_REF:
case ZEND_LEAVE:
{
if (EG(prev_exception) || (type == ZEND_LEAVE && EG(exception))) {
for (i=0; i<EX(op_array)->last_try_catch; i++) {
if (EX(op_array)->try_catch_array[i].try_op > op_num) {
break;
}
if (op_num < EX(op_array)->try_catch_array[i].finally_op) {
finally_op_num = EX(op_array)->try_catch_array[i].finally_op;
}
if (op_num < EX(op_array)->try_catch_array[i].catch_op) {
catch_op_num = EX(op_array)->try_catch_array[i].catch_op;
}
}
} else {
for (i=0; i<EX(op_array)->last_try_catch; i++) {
if (EX(op_array)->try_catch_array[i].try_op > op_num) {
break;
}
if (op_num < EX(op_array)->try_catch_array[i].finally_op) {
finally_op_num = EX(op_array)->try_catch_array[i].finally_op;
}
}
}
if (catch_op_num && finally_op_num) {
/* EG(exception) || EG(prev_exception) */
if (catch_op_num > finally_op_num) {
zend_exception_save(TSRMLS_C);
EX(leaving) = ZEND_THROW;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
} else {
EX(leaving) = 0;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
}
} else if (catch_op_num) {
EX(leaving) = 0;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
} else if (finally_op_num) {
zend_exception_save(TSRMLS_C);
if (type != ZEND_LEAVE) {
EX(leaving) = type;
}
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
} else if (EX(leaving) && type != ZEND_LEAVE) {
/* leave it to ZEND_LEAVE */
EX(leaving) = type;
ZEND_VM_NEXT_OPCODE();
} else {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
break;
case ZEND_JMP:
case ZEND_BRK:
case ZEND_CONT:
case ZEND_GOTO:
{
/* these can not occurred in exception context */
for (i=0; i<EG(active_op_array)->last_try_catch; i++) {
if (EG(active_op_array)->try_catch_array[i].try_op > op_num) {
break;
}
if (op_num < EG(active_op_array)->try_catch_array[i].finally_op
&& (EX(leaving_dest) < EG(active_op_array)->try_catch_array[i].try_op
|| EX(leaving_dest) >= EG(active_op_array)->try_catch_array[i].finally_end)) {
finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op;
}
}
if (finally_op_num) {
EX(leaving) = type;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
} else {
EX(leaving) = 0;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[EX(leaving_dest)]);
}
}
break;
}
ZEND_VM_CONTINUE();
}
static int ZEND_FASTCALL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@ -848,12 +758,8 @@ static int ZEND_FASTCALL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
#if DEBUG_ZEND>=2
printf("Jumping to %d\n", opline->op1.opline_num);
#endif
if (EXPECTED(!EX(op_array)->has_finally_block)) {
ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
ZEND_VM_CONTINUE(); /* CHECK_ME */
}
EX(leaving_dest) = opline->op1.jmp_addr - EX(op_array)->opcodes;
return zend_finally_handler_leaving_SPEC(ZEND_JMP, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
ZEND_VM_CONTINUE();
}
static int ZEND_FASTCALL ZEND_INIT_STRING_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -880,9 +786,6 @@ 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)
{
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);
}
@ -1168,7 +1071,6 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
zend_uint op_num = EG(opline_before_exception)-EG(active_op_array)->opcodes;
int i;
zend_uint catch_op_num = 0, finally_op_num = 0;
int catched = 0, finally = 0;
void **stack_frame;
/* Figure out where the next stack frame (which maybe contains pushed
@ -1201,11 +1103,9 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
}
if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) {
catch_op_num = EX(op_array)->try_catch_array[i].catch_op;
catched = i + 1;
}
if (op_num < EG(active_op_array)->try_catch_array[i].finally_op) {
finally_op_num = EX(op_array)->try_catch_array[i].finally_op;
finally = i + 1;
}
}
@ -1233,7 +1133,7 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
/* further blocks will not be relevant... */
break;
} else if (op_num < EX(op_array)->brk_cont_array[i].brk) {
if (!catched ||
if (!catch_op_num ||
catch_op_num >= EX(op_array)->brk_cont_array[i].brk) {
zend_op *brk_opline = &EX(op_array)->opcodes[EX(op_array)->brk_cont_array[i].brk];
@ -1265,26 +1165,14 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER
}
EX(old_error_reporting) = NULL;
if (catched && finally) {
if (finally_op_num > catch_op_num) {
EX(leaving) = 0;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
ZEND_VM_CONTINUE();
} else {
zend_exception_save(TSRMLS_C);
EX(leaving) = ZEND_THROW;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
ZEND_VM_CONTINUE();
}
} else if (catched) {
EX(leaving) = 0;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_op_num]);
ZEND_VM_CONTINUE();
} else if (finally) {
if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) {
zend_exception_save(TSRMLS_C);
EX(leaving) = ZEND_THROW;
EX(fast_ret) = NULL;
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]);
ZEND_VM_CONTINUE();
} else if (catch_op_num) {
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);
}
@ -1325,28 +1213,42 @@ static int ZEND_FASTCALL ZEND_USER_OPCODE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS
}
}
static int ZEND_FASTCALL ZEND_LEAVE_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
static int ZEND_FASTCALL ZEND_FAST_CALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zend_exception_restore(TSRMLS_C);
if (!EX(leaving)) {
ZEND_VM_NEXT_OPCODE();
USE_OPLINE
if (opline->extended_value &&
UNEXPECTED(EG(prev_exception) != NULL)) {
/* in case of unhandled exception jump to catch block instead of finally */
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
}
EX(fast_ret) = opline + 1;
ZEND_VM_SET_OPCODE(opline->op1.jmp_addr);
ZEND_VM_CONTINUE();
}
static int ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
if (EX(fast_ret)) {
ZEND_VM_SET_OPCODE(EX(fast_ret));
ZEND_VM_CONTINUE();
} else {
zend_uint leaving = EX(leaving);
switch (leaving) {
case ZEND_RETURN:
case ZEND_RETURN_BY_REF:
case ZEND_THROW:
leaving = ZEND_LEAVE;
case ZEND_JMP:
case ZEND_BRK:
case ZEND_CONT:
case ZEND_GOTO:
return zend_finally_handler_leaving_SPEC(leaving, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
break;
/* special case for unhandled exceptions */
USE_OPLINE
if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) {
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
} else if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) {
zend_exception_restore(TSRMLS_C);
ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[opline->op2.opline_num]);
ZEND_VM_CONTINUE();
} else {
zend_exception_restore(TSRMLS_C);
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
}
ZEND_VM_CONTINUE();
}
static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -1587,11 +1489,7 @@ static int ZEND_FASTCALL ZEND_BRK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
EX(op_array), EX_Ts() TSRMLS_CC);
if (EXPECTED(!EX(op_array)->has_finally_block)) {
ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
}
EX(leaving_dest) = el->brk;
return zend_finally_handler_leaving_SPEC(ZEND_BRK, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
ZEND_VM_JMP(EX(op_array)->opcodes + el->brk);
}
static int ZEND_FASTCALL ZEND_CONT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -1603,11 +1501,7 @@ static int ZEND_FASTCALL ZEND_CONT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
el = zend_brk_cont(Z_LVAL_P(opline->op2.zv), opline->op1.opline_num,
EX(op_array), EX_Ts() TSRMLS_CC);
if (EXPECTED(!EX(op_array)->has_finally_block)) {
ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
}
EX(leaving_dest) = el->cont;
return zend_finally_handler_leaving_SPEC(ZEND_CONT, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
ZEND_VM_JMP(EX(op_array)->opcodes + el->cont);
}
static int ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -1634,11 +1528,7 @@ static int ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
}
break;
}
if (EXPECTED(!EX(op_array)->has_finally_block)) {
ZEND_VM_JMP(opline->op1.jmp_addr);
}
EX(leaving_dest) = opline->op1.jmp_addr - EX(op_array)->opcodes;
return zend_finally_handler_leaving_SPEC(ZEND_GOTO, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
ZEND_VM_JMP(opline->op1.jmp_addr);
}
static int ZEND_FASTCALL ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -2501,10 +2391,7 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
*EG(return_value_ptr_ptr) = ret;
}
if (EXPECTED(!EX(op_array)->has_finally_block)) {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
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_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -2575,10 +2462,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND
}
} while (0);
if (EXPECTED(!EX(op_array)->has_finally_block)) {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_finally_handler_leaving_SPEC(ZEND_RETURN_BY_REF, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -7822,10 +7706,7 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
*EG(return_value_ptr_ptr) = ret;
}
if (EXPECTED(!EX(op_array)->has_finally_block)) {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
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_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -7896,10 +7777,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE
}
} while (0);
if (EXPECTED(!EX(op_array)->has_finally_block)) {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_finally_handler_leaving_SPEC(ZEND_RETURN_BY_REF, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -13048,11 +12926,7 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
*EG(return_value_ptr_ptr) = ret;
}
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (EXPECTED(!EX(op_array)->has_finally_block)) {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
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_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -13124,11 +12998,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE
} while (0);
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
if (EXPECTED(!EX(op_array)->has_finally_block)) {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_finally_handler_leaving_SPEC(ZEND_RETURN_BY_REF, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -30620,10 +30490,7 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
*EG(return_value_ptr_ptr) = ret;
}
if (EXPECTED(!EX(op_array)->has_finally_block)) {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
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_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -30694,10 +30561,7 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER
}
} while (0);
if (EXPECTED(!EX(op_array)->has_finally_block)) {
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
return zend_finally_handler_leaving_SPEC(ZEND_RETURN_BY_REF, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
}
static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@ -44964,31 +44828,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_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_LEAVE_SPEC_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_YIELD_SPEC_CONST_CONST_HANDLER,
ZEND_YIELD_SPEC_CONST_TMP_HANDLER,
ZEND_YIELD_SPEC_CONST_VAR_HANDLER,
@ -45039,6 +44903,56 @@ void zend_init_opcodes_handlers(void)
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_GENERATOR_RETURN_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_CALL_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_FAST_RET_SPEC_HANDLER,
ZEND_NULL_HANDLER
};
zend_opcode_handlers = (opcode_handler_t*)labels;

View File

@ -46,7 +46,6 @@ zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_arra
EX(prev_execute_data) = EG(current_execute_data);
EG(current_execute_data) = execute_data;
EX(nested) = nested;
EX(leaving) = 0;
if (!op_array->run_time_cache && op_array->last_cache_slot) {
op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));

View File

@ -159,6 +159,7 @@
#define ZEND_SEPARATE 156
#define ZEND_QM_ASSIGN_VAR 157
#define ZEND_JMP_SET_VAR 158
#define ZEND_LEAVE 159
#define ZEND_YIELD 160
#define ZEND_GENERATOR_RETURN 161
#define ZEND_FAST_CALL 162
#define ZEND_FAST_RET 163