Commit:    703a4e390de277afb85d722a0792912d0b2d2d46
Author:    Xinchen Hui <larue...@php.net>         Wed, 22 Aug 2012 13:51:44 
+0800
Parents:   c4fecc1c5d44481a4088f6028ce6910f2ce4e0dc
Branches:  master

Link:       
http://git.php.net/?p=php-src.git;a=commitdiff;h=703a4e390de277afb85d722a0792912d0b2d2d46

Log:
stash

Changed paths:
  M  Zend/zend_compile.c
  M  Zend/zend_compile.h
  M  Zend/zend_opcode.c
  M  Zend/zend_vm_def.h
  M  Zend/zend_vm_execute.h

diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 33d1d37..2ae8cc5 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 8919fdc..80e02ab 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 7cbc15b..2552d2e 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 1da4c12..d921f81 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; 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)) {
+
+       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 b5a649d..9818583 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; 
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)) {
+
+       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; 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)
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to