From: Xinchen Hui Date: Wed, 22 Aug 2012 05:51:44 +0000 (+0800) Subject: stash X-Git-Tag: php-5.5.0alpha1~20^2~30^2~2 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=703a4e390de277afb85d722a0792912d0b2d2d46;p=php stash --- diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 33d1d377ca..2ae8cc510f 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -2792,6 +2792,7 @@ void zend_do_end_finally(znode *try_token, znode* catch_token, znode *finally_to 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; 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; SET_UNUSED(opline->op1); diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 8919fdc6b8..80e02ab309 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -281,6 +281,7 @@ struct _zend_op_array { zend_try_catch_element *try_catch_array; int last_try_catch; + zend_bool has_finally_block; /* static variables support */ HashTable *static_variables; @@ -383,7 +384,8 @@ struct _zend_execute_data { zend_class_entry *current_called_scope; zval *current_this; zval *current_object; - zend_bool leaving; + zend_uint leaving; + zend_uint leaving_dest; }; #define EX(element) execute_data.element diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 7cbc15b0b0..2552d2ebd6 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -87,6 +87,7 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz op_array->static_variables = NULL; op_array->last_try_catch = 0; + op_array->has_finally_block = 0; op_array->this_var = -1; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 1da4c12440..d921f81efc 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2878,49 +2878,10 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY) } FREE_OP1_IF_VAR(); - if (!(EG(active_op_array)->last_try_catch)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); - } else { - zend_uint i, op_num = opline - EX(op_array)->opcodes; - zend_uint catch_op_num = 0, finally_op_num = 0; - for (i=0; ilast_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) { - finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; - } - if (EG(prev_exception)) { - /* leaving */ - if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { - catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; - } - } - } - - if (catch_op_num && finally_op_num) { - if (catch_op_num > finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else { - EX(leaving) = 0; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_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 if (finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else if (EX(leaving)) { - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); - } - } + if (EG(active_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); } ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY) @@ -2993,49 +2954,10 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY) FREE_OP1_IF_VAR(); - if (!(EG(active_op_array)->last_try_catch)) { - ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); - } else { - zend_uint i, op_num = opline - EX(op_array)->opcodes; - zend_uint catch_op_num = 0, finally_op_num = 0; - for (i=0; ilast_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) { - finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; - } - if (EG(prev_exception)) { - /* leaving */ - if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { - catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; - } - } - } - - if (catch_op_num && finally_op_num) { - if (catch_op_num > finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else { - EX(leaving) = 0; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_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 if (finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else if (EX(leaving)) { - ZEND_VM_NEXT_OPCODE(); - } else { - ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); - } - } + if (EG(active_op_array)->has_finally_block) { + 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(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY) @@ -3370,6 +3292,93 @@ ZEND_VM_HANDLER(52, ZEND_BOOL, CONST|TMP|VAR|CV, 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: + { + if (EG(prev_exception)) { + for (i=0; ilast_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) { + finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; + } + if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { + catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; + } + } + } else { + for (i=0; ilast_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) { + finally_op_num = EG(active_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) { + 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) { + EX(leaving) = type; + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); + } else if (EX(leaving)) { + /* leave it to ZEND_LEAVE */ + ZEND_VM_NEXT_OPCODE(); + } else { + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + } + } + break; + case ZEND_BRK: + case ZEND_CONT: + case ZEND_GOTO: + { + for (i=0; ilast_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(50, ZEND_BRK, ANY, CONST) { USE_OPLINE @@ -3379,6 +3388,10 @@ 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 (EG(active_op_array)->has_finally_block) { + 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); } @@ -3391,6 +3404,10 @@ 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 (EG(active_op_array)->has_finally_block) { + 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); } @@ -3418,6 +3435,10 @@ ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST) } break; } + if ((EG(active_op_array)->has_finally_block)) { + EX(leaving_dest) = opline->op1.jmp_addr - EG(active_op_array)->opcodes; + ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, ZEND_GOTO); + } ZEND_VM_JMP(opline->op1.jmp_addr); } @@ -5184,7 +5205,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) ZEND_VM_CONTINUE(); } else { zend_exception_save(TSRMLS_C); - EX(leaving) = finally; + EX(leaving) = ZEND_THROW; ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); ZEND_VM_CONTINUE(); } @@ -5194,7 +5215,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY) ZEND_VM_CONTINUE(); } else if (finally) { zend_exception_save(TSRMLS_C); - EX(leaving) = finally; + EX(leaving) = ZEND_THROW; ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); ZEND_VM_CONTINUE(); } else { @@ -5284,7 +5305,7 @@ ZEND_VM_HANDLER(153, ZEND_DECLARE_LAMBDA_FUNCTION, CONST, UNUSED) zend_function *op_array; SAVE_OPLINE(); - + if (UNEXPECTED(zend_hash_quick_find(EG(function_table), Z_STRVAL_P(opline->op1.zv), Z_STRLEN_P(opline->op1.zv), Z_HASH_P(opline->op1.zv), (void *) &op_array) == FAILURE) || UNEXPECTED(op_array->type != ZEND_USER_FUNCTION)) { zend_error_noreturn(E_ERROR, "Base lambda function for closure not found"); @@ -5320,47 +5341,68 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED) ZEND_VM_HANDLER(159, ZEND_LEAVE, ANY, ANY) { USE_OPLINE - zend_uint i, op_num = opline - EG(active_op_array)->opcodes; - - SAVE_OPLINE(); zend_exception_restore(TSRMLS_C); - if (EX(leaving)) { + + if (!EX(leaving)) { + ZEND_VM_NEXT_OPCODE(); + } else { + zend_uint i, op_num = opline - EX(op_array)->opcodes; zend_uint catch_op_num = 0, finally_op_num = 0; - for (i = 0; i < EX(leaving); 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) { - finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; - } - if (EG(exception)) { - if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { - catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; - } - } - } + switch (EX(leaving)) { + case ZEND_RETURN: + case ZEND_RETURN_BY_REF: + case ZEND_THROW: + { + if (EG(exception)) { + for (i = 0; i < EX(leaving); 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) { + finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; + } + if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { + catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; + } + } + } else { + for (i = 0; i < EX(leaving); 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) { + finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; + } + } + } - if (catch_op_num && finally_op_num) { - if (catch_op_num > finally_op_num) { - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else { - EX(leaving) = 0; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_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 if (finally_op_num) { - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else { - ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + if (catch_op_num && finally_op_num) { + if (catch_op_num > finally_op_num) { + 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_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); + } else { + ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); + } + } + break; + case ZEND_BRK: + case ZEND_CONT: + case ZEND_GOTO: + ZEND_VM_DISPATCH_TO_HELPER_EX(zend_finally_handler_leaving, type, EX(leaving)); + break; } - } else { - ZEND_VM_NEXT_OPCODE(); } + + ZEND_VM_CONTINUE(); } ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper) diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index b5a649d0a2..9818583334 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -794,6 +794,93 @@ static int ZEND_FASTCALL ZEND_RECV_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) 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: + { + if (EG(prev_exception)) { + for (i=0; ilast_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) { + finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; + } + if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { + catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; + } + } + } else { + for (i=0; ilast_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) { + finally_op_num = EG(active_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) { + 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) { + EX(leaving) = type; + ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); + } else if (EX(leaving)) { + /* leave it to ZEND_LEAVE */ + ZEND_VM_NEXT_OPCODE(); + } else { + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + } + break; + case ZEND_BRK: + case ZEND_CONT: + case ZEND_GOTO: + { + for (i=0; ilast_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_NEW_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -1122,7 +1209,7 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER ZEND_VM_CONTINUE(); } else { zend_exception_save(TSRMLS_C); - EX(leaving) = finally; + EX(leaving) = ZEND_THROW; ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); ZEND_VM_CONTINUE(); } @@ -1132,7 +1219,7 @@ static int ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(ZEND_OPCODE_HANDLER ZEND_VM_CONTINUE(); } else if (finally) { zend_exception_save(TSRMLS_C); - EX(leaving) = finally; + EX(leaving) = ZEND_THROW; ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); ZEND_VM_CONTINUE(); } else { @@ -1178,47 +1265,68 @@ 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) { USE_OPLINE - zend_uint i, op_num = opline - EG(active_op_array)->opcodes; - - SAVE_OPLINE(); zend_exception_restore(TSRMLS_C); - if (EX(leaving)) { + + if (!EX(leaving)) { + ZEND_VM_NEXT_OPCODE(); + } else { + zend_uint i, op_num = opline - EX(op_array)->opcodes; zend_uint catch_op_num = 0, finally_op_num = 0; - for (i = 0; i < EX(leaving); 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) { - finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; - } - if (EG(exception)) { - if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { - catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; - } - } - } + switch (EX(leaving)) { + case ZEND_RETURN: + case ZEND_RETURN_BY_REF: + case ZEND_THROW: + { + if (EG(exception)) { + for (i = 0; i < EX(leaving); 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) { + finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; + } + if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { + catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; + } + } + } else { + for (i = 0; i < EX(leaving); 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) { + finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; + } + } + } - if (catch_op_num && finally_op_num) { - if (catch_op_num > finally_op_num) { - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else { - EX(leaving) = 0; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_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 if (finally_op_num) { - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + if (catch_op_num && finally_op_num) { + if (catch_op_num > finally_op_num) { + 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_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); + } else { + return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } + } + break; + case ZEND_BRK: + case ZEND_CONT: + case ZEND_GOTO: + return zend_finally_handler_leaving_SPEC(EX(leaving), ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + break; } - } else { - ZEND_VM_NEXT_OPCODE(); } + + ZEND_VM_CONTINUE(); } static int ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -1455,6 +1563,10 @@ 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 (EG(active_op_array)->has_finally_block) { + 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); } @@ -1467,6 +1579,10 @@ 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 (EG(active_op_array)->has_finally_block) { + 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); } @@ -1494,6 +1610,10 @@ static int ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } break; } + if ((EG(active_op_array)->has_finally_block)) { + EX(leaving_dest) = opline->op1.jmp_addr - EG(active_op_array)->opcodes; + return zend_finally_handler_leaving_SPEC(ZEND_CONT, ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); + } ZEND_VM_JMP(opline->op1.jmp_addr); } @@ -2345,49 +2465,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG *EG(return_value_ptr_ptr) = ret; } - if (!(EG(active_op_array)->last_try_catch)) { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - zend_uint i, op_num = opline - EX(op_array)->opcodes; - zend_uint catch_op_num = 0, finally_op_num = 0; - for (i=0; ilast_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) { - finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; - } - if (EG(prev_exception)) { - /* leaving */ - if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { - catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; - } - } - } - - if (catch_op_num && finally_op_num) { - if (catch_op_num > finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else { - EX(leaving) = 0; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_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 if (finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else if (EX(leaving)) { - ZEND_VM_NEXT_OPCODE(); - } else { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } - } + if (EG(active_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); } static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -2458,49 +2539,10 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HAND } } while (0); - if (!(EG(active_op_array)->last_try_catch)) { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - zend_uint i, op_num = opline - EX(op_array)->opcodes; - zend_uint catch_op_num = 0, finally_op_num = 0; - for (i=0; ilast_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) { - finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; - } - if (EG(prev_exception)) { - /* leaving */ - if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { - catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; - } - } - } - - if (catch_op_num && finally_op_num) { - if (catch_op_num > finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else { - EX(leaving) = 0; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_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 if (finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else if (EX(leaving)) { - ZEND_VM_NEXT_OPCODE(); - } else { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } - } + if (EG(active_op_array)->has_finally_block) { + 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) @@ -6973,49 +7015,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) *EG(return_value_ptr_ptr) = ret; } - if (!(EG(active_op_array)->last_try_catch)) { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - zend_uint i, op_num = opline - EX(op_array)->opcodes; - zend_uint catch_op_num = 0, finally_op_num = 0; - for (i=0; ilast_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) { - finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; - } - if (EG(prev_exception)) { - /* leaving */ - if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { - catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; - } - } - } - - if (catch_op_num && finally_op_num) { - if (catch_op_num > finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else { - EX(leaving) = 0; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_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 if (finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else if (EX(leaving)) { - ZEND_VM_NEXT_OPCODE(); - } else { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } - } + if (EG(active_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); } static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -7086,49 +7089,10 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLE } } while (0); - if (!(EG(active_op_array)->last_try_catch)) { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - zend_uint i, op_num = opline - EX(op_array)->opcodes; - zend_uint catch_op_num = 0, finally_op_num = 0; - for (i=0; ilast_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) { - finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; - } - if (EG(prev_exception)) { - /* leaving */ - if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { - catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; - } - } - } - - if (catch_op_num && finally_op_num) { - if (catch_op_num > finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else { - EX(leaving) = 0; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_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 if (finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else if (EX(leaving)) { - ZEND_VM_NEXT_OPCODE(); - } else { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } - } + if (EG(active_op_array)->has_finally_block) { + 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) @@ -11507,49 +11471,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) } if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - if (!(EG(active_op_array)->last_try_catch)) { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - zend_uint i, op_num = opline - EX(op_array)->opcodes; - zend_uint catch_op_num = 0, finally_op_num = 0; - for (i=0; ilast_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) { - finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; - } - if (EG(prev_exception)) { - /* leaving */ - if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { - catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; - } - } - } - - if (catch_op_num && finally_op_num) { - if (catch_op_num > finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else { - EX(leaving) = 0; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_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 if (finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else if (EX(leaving)) { - ZEND_VM_NEXT_OPCODE(); - } else { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } - } + if (EG(active_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); } static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -11622,49 +11547,10 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLE if (free_op1.var) {zval_ptr_dtor(&free_op1.var);}; - if (!(EG(active_op_array)->last_try_catch)) { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - zend_uint i, op_num = opline - EX(op_array)->opcodes; - zend_uint catch_op_num = 0, finally_op_num = 0; - for (i=0; ilast_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) { - finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; - } - if (EG(prev_exception)) { - /* leaving */ - if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { - catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; - } - } - } - - if (catch_op_num && finally_op_num) { - if (catch_op_num > finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else { - EX(leaving) = 0; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_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 if (finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else if (EX(leaving)) { - ZEND_VM_NEXT_OPCODE(); - } else { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } - } + if (EG(active_op_array)->has_finally_block) { + 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) @@ -27604,49 +27490,10 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) *EG(return_value_ptr_ptr) = ret; } - if (!(EG(active_op_array)->last_try_catch)) { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - zend_uint i, op_num = opline - EX(op_array)->opcodes; - zend_uint catch_op_num = 0, finally_op_num = 0; - for (i=0; ilast_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) { - finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; - } - if (EG(prev_exception)) { - /* leaving */ - if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { - catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; - } - } - } - - if (catch_op_num && finally_op_num) { - if (catch_op_num > finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else { - EX(leaving) = 0; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_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 if (finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else if (EX(leaving)) { - ZEND_VM_NEXT_OPCODE(); - } else { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } - } + if (EG(active_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); } static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) @@ -27717,49 +27564,10 @@ static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER } } while (0); - if (!(EG(active_op_array)->last_try_catch)) { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } else { - zend_uint i, op_num = opline - EX(op_array)->opcodes; - zend_uint catch_op_num = 0, finally_op_num = 0; - for (i=0; ilast_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) { - finally_op_num = EG(active_op_array)->try_catch_array[i].finally_op; - } - if (EG(prev_exception)) { - /* leaving */ - if (op_num < EG(active_op_array)->try_catch_array[i].catch_op) { - catch_op_num = EG(active_op_array)->try_catch_array[i].catch_op; - } - } - } - - if (catch_op_num && finally_op_num) { - if (catch_op_num > finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else { - EX(leaving) = 0; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[catch_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 if (finally_op_num) { - EX(leaving) = 1; - ZEND_VM_SET_OPCODE(&EX(op_array)->opcodes[finally_op_num]); - ZEND_VM_CONTINUE(); - } else if (EX(leaving)) { - ZEND_VM_NEXT_OPCODE(); - } else { - return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); - } - } + if (EG(active_op_array)->has_finally_block) { + 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)