This commit is contained in:
Xinchen Hui 2012-08-22 13:51:44 +08:00
parent c4fecc1c5d
commit 703a4e390d
5 changed files with 364 additions and 510 deletions

View File

@ -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);

View File

@ -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

View File

@ -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;

View File

@ -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; 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) {
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; 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) {
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; 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) {
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<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) {
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; 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(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)) {
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;
}
}
}
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);
}
} else {
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;
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) {
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;
}
}
ZEND_VM_CONTINUE();
}
ZEND_VM_EXPORT_HELPER(zend_do_fcall, zend_do_fcall_common_helper)

View File

@ -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; 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) {
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<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) {
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; 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_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)) {
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;
}
}
}
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);
}
} else {
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;
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) {
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;
}
}
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; 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) {
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; 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) {
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; 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) {
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; 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) {
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; 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) {
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; 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) {
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; 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) {
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; 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) {
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)