]> granicus.if.org Git - php/commitdiff
Optimized zend_leave_helper()
authorDmitry Stogov <dmitry@zend.com>
Fri, 18 Apr 2014 09:46:36 +0000 (13:46 +0400)
committerDmitry Stogov <dmitry@zend.com>
Fri, 18 Apr 2014 09:46:36 +0000 (13:46 +0400)
Zend/zend_API.h
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute.h
Zend/zend_execute_API.c
Zend/zend_generators.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_execute.skl
sapi/phpdbg/phpdbg_prompt.c

index 6295d8a89011d53672066788639aab4b2737ccb8..43c205c659323d555fc40e629744dd555364f920 100644 (file)
@@ -520,8 +520,8 @@ ZEND_API int zend_set_hash_symbol(zval *symbol, const char *name, int name_lengt
 ZEND_API int zend_delete_global_variable(zend_string *name TSRMLS_DC);
 
 ZEND_API void zend_rebuild_symbol_table(TSRMLS_D);
-ZEND_API void zend_attach_symbol_table(TSRMLS_D);
-ZEND_API void zend_detach_symbol_table(TSRMLS_D);
+ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data);
+ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data);
 ZEND_API int zend_set_local_var(zend_string *name, zval *value, int force TSRMLS_DC);
 ZEND_API int zend_set_local_var_str(const char *name, int len, zval *value, int force TSRMLS_DC);
 
index 0c3f20f354dd952cac92e69b3a7d9d797941e766..668145599290765cb8031218e6296c9a7c9a85bd 100644 (file)
@@ -366,6 +366,13 @@ typedef struct _call_slot {
        zend_bool          is_ctor_result_used;
 } call_slot;
 
+typedef enum _vm_frame_kind {
+       VM_FRAME_NESTED_FUNCTION,       /* stackless VM call to function */
+       VM_FRAME_NESTED_CODE,           /* stackless VM call to include/require/eval */
+       VM_FRAME_TOP_FUNCTION,          /* direct VM call to function from external C code */
+       VM_FRAME_TOP_CODE                       /* direct VM call to "main" code from external C code */
+} vm_frame_kind;
+
 struct _zend_execute_data {
        struct _zend_op *opline;
        void **run_time_cache;
@@ -375,7 +382,7 @@ struct _zend_execute_data {
        zend_array *symbol_table;
        struct _zend_execute_data *prev_execute_data;
        zval old_error_reporting;
-       zend_bool nested;
+       vm_frame_kind frame_kind;
        zval *return_value;
        // TODO: simplify call sequence and remove current_* and call_* ???
        zend_class_entry *current_scope;
index 7302aeec340ac0ea591b7b007db2a20afb58faab..b6a40312214265f99a894cb200c8f8cda3c7c647 100644 (file)
@@ -1560,7 +1560,7 @@ void zend_free_compiled_variables(zend_execute_data *execute_data TSRMLS_DC) /*
  *                             +----------------------------------------+
  */
 
-static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, zend_bool nested TSRMLS_DC) /* {{{ */
+static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
 {
        zend_execute_data *execute_data;
 
@@ -1650,7 +1650,7 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
        EX(symbol_table) = EG(active_symbol_table);
        EX(call) = NULL;
        EG(current_execute_data) = execute_data;
-       EX(nested) = nested;
+       EX(frame_kind) = frame_kind;
        EX(delayed_exception) = NULL;
        EX(return_value) = return_value;
 
@@ -1659,8 +1659,8 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
        }
        EX(run_time_cache) = op_array->run_time_cache;
 
-       if (EG(active_symbol_table)) {
-               zend_attach_symbol_table(TSRMLS_C);
+       if (EX(symbol_table)) {
+               zend_attach_symbol_table(execute_data);
        }
 
        if (op_array->this_var != -1 && Z_OBJ(EG(This))) {
@@ -1677,9 +1677,9 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
 }
 /* }}} */
 
-ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, zend_bool nested TSRMLS_DC) /* {{{ */
+ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
 {
-       return i_create_execute_data_from_op_array(op_array, return_value, nested TSRMLS_CC);
+       return i_create_execute_data_from_op_array(op_array, return_value, frame_kind TSRMLS_CC);
 }
 /* }}} */
 
index 417f3acbd9eb853d2e10a9b825522737026cf255..d632a978409506b1aa9400841383888ad3b56c3c 100644 (file)
@@ -35,7 +35,7 @@ ZEND_API extern void (*zend_execute_internal)(zend_execute_data *execute_data_pt
 void init_executor(TSRMLS_D);
 void shutdown_executor(TSRMLS_D);
 void shutdown_destructors(TSRMLS_D);
-ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, zend_bool nested TSRMLS_DC);
+ZEND_API zend_execute_data *zend_create_execute_data_from_op_array(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC);
 ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC);
 ZEND_API void execute_ex(zend_execute_data *execute_data TSRMLS_DC);
 ZEND_API void execute_internal(zend_execute_data *execute_data_ptr, struct _zend_fcall_info *fci TSRMLS_DC);
index 0c6861c14da1412c44667f05e8b73b9e237757e0..8d5b55c84d50aac908a2bfaf1517a61daf9d91d2 100644 (file)
@@ -935,12 +935,12 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
                        zend_execute(EG(active_op_array), fci->retval TSRMLS_CC);
                }
 
+               EG(active_op_array) = original_op_array;
+               EG(opline_ptr) = original_opline_ptr;
                if (!fci->symbol_table && EG(active_symbol_table)) {
                        zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
                }
                EG(active_symbol_table) = calling_symbol_table;
-               EG(active_op_array) = original_op_array;
-               EG(opline_ptr) = original_opline_ptr;
        } else if (EX(function_state).function->type == ZEND_INTERNAL_FUNCTION) {
                int call_via_handler = (EX(function_state).function->common.fn_flags & ZEND_ACC_CALL_VIA_HANDLER) != 0;
                ZVAL_NULL(fci->retval);
@@ -1695,12 +1695,11 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
 }
 /* }}} */
 
-ZEND_API void zend_attach_symbol_table(TSRMLS_D) /* {{{ */
+ZEND_API void zend_attach_symbol_table(zend_execute_data *execute_data) /* {{{ */
 {
        int i;
-       zend_execute_data *execute_data = EG(current_execute_data);
        zend_op_array *op_array = execute_data->op_array;
-       HashTable *ht = &EG(active_symbol_table)->ht;
+       HashTable *ht = &execute_data->symbol_table->ht;
        
        /* copy real values from symbol table into CV slots and create
           INDIRECT references to CV in symbol table  */
@@ -1727,12 +1726,11 @@ ZEND_API void zend_attach_symbol_table(TSRMLS_D) /* {{{ */
 }
 /* }}} */
 
-ZEND_API void zend_detach_symbol_table(TSRMLS_D) /* {{{ */
+ZEND_API void zend_detach_symbol_table(zend_execute_data *execute_data) /* {{{ */
 {
        int i;
-       zend_execute_data *execute_data = EG(current_execute_data);
        zend_op_array *op_array = execute_data->op_array;
-       HashTable *ht = &EG(active_symbol_table)->ht;
+       HashTable *ht = &execute_data->symbol_table->ht;
        
        /* copy real values from CV slots into symbol table */
        for (i = 0; i < op_array->last_var; i++) {
index 29941c12e3442755efeac0d109c5806c3ac9e09e..74df4cdb7b898509ed170c2f8843ef1b825d31d2 100644 (file)
@@ -287,7 +287,7 @@ ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_v
        opline_ptr = EG(opline_ptr);
        current_symbol_table = EG(active_symbol_table);
        EG(active_symbol_table) = NULL;
-       execute_data = zend_create_execute_data_from_op_array(op_array, return_value, 0 TSRMLS_CC);
+       execute_data = zend_create_execute_data_from_op_array(op_array, return_value, VM_FRAME_TOP_FUNCTION TSRMLS_CC);
        EG(active_symbol_table) = current_symbol_table;
        EG(current_execute_data) = current_execute_data;
        EG(opline_ptr) = opline_ptr;
index aa8b2a5e839bcbd23f01b52321760b777c546faa..d6723fbd5aeb17281390b21abaaa7e308c79c1f0 100644 (file)
@@ -1748,96 +1748,103 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
 
 ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
 {
-       zend_bool nested = EX(nested);
-       zend_op_array *op_array = EX(op_array);
+       vm_frame_kind frame_kind = EX(frame_kind);
 
-       if ((nested && EX(prev_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL) ||
-           EG(active_symbol_table) == &EG(symbol_table)) {
-               zend_detach_symbol_table(TSRMLS_C);
-       }
-       
        EG(current_execute_data) = EX(prev_execute_data);
-       EG(opline_ptr) = NULL;
-       
-       if (EG(active_symbol_table) != &EG(symbol_table)) {
-               i_free_compiled_variables(execute_data TSRMLS_CC);
-       }
-
-       zend_vm_stack_free((char*)execute_data TSRMLS_CC);
 
-       if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) {
-               zval_ptr_dtor((zval*)op_array->prototype);
-       }
+       if (frame_kind == VM_FRAME_NESTED_FUNCTION) {
+               i_free_compiled_variables(execute_data TSRMLS_CC);
+               if (UNEXPECTED(EX(symbol_table) != NULL)) {
+                       zend_clean_and_cache_symbol_table(EX(symbol_table) TSRMLS_CC);
+               }
+               if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(op_array)->prototype) {
+                       zval_ptr_dtor((zval*)EX(op_array)->prototype);
+               }
+               zend_vm_stack_free((char*)execute_data TSRMLS_CC);
 
-       if (nested) {
                execute_data = EG(current_execute_data);
-       }
-       if (nested) {
-               USE_OPLINE
-
-               LOAD_REGS();
-               LOAD_OPLINE();
-               if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) {
-
-                       zend_attach_symbol_table(TSRMLS_C);
+               EG(opline_ptr) = &EX(opline);
+               EG(active_op_array) = EX(op_array);
+               EG(active_symbol_table) = EX(symbol_table);
 
-                       EX(function_state).function = (zend_function *) EX(op_array);
-                       EX(function_state).arguments = NULL;
+               EX(function_state).function = (zend_function *) EX(op_array);
+               EX(function_state).arguments = NULL;
 
-                       EG(opline_ptr) = &EX(opline);
-                       EG(active_op_array) = EX(op_array);
-                       destroy_op_array(op_array TSRMLS_CC);
-                       efree(op_array);
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               zend_throw_exception_internal(NULL TSRMLS_CC);
-                               HANDLE_EXCEPTION_LEAVE();
+               if (Z_OBJ(EG(This))) {
+                       if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
+                               if (EX(call)->is_ctor_result_used) {
+                                       Z_DELREF(EG(This));
+                               }
+                               if (Z_REFCOUNT(EG(This)) == 1) {
+                                       zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
+                               }
                        }
+                       zval_ptr_dtor(&EG(This));
+               }
+               Z_OBJ(EG(This)) = EX(current_this);
+               EG(scope) = EX(current_scope);
+               EG(called_scope) = EX(current_called_scope);
 
-                       ZEND_VM_INC_OPCODE();
-                       ZEND_VM_LEAVE();
-               } else {
-                       EG(opline_ptr) = &EX(opline);
-                       EG(active_op_array) = EX(op_array);
-                       if (EG(active_symbol_table)) {
-                               zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
-                       }
-                       EG(active_symbol_table) = EX(symbol_table);
+               EX(call)--;
 
-                       EX(function_state).function = (zend_function *) EX(op_array);
-                       EX(function_state).arguments = NULL;
+               zend_vm_stack_clear_multiple(1 TSRMLS_CC);
 
-                       if (Z_OBJ(EG(This))) {
-                               if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
-                                       if (EX(call)->is_ctor_result_used) {
-                                               Z_DELREF(EG(This));
-                                       }
-                                       if (Z_REFCOUNT(EG(This)) == 1) {
-                                               zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
-                                       }
-                               }
-                               zval_ptr_dtor(&EG(This));
+               if (UNEXPECTED(EG(exception) != NULL)) {
+                       zend_op *opline = EX(opline);
+                       zend_throw_exception_internal(NULL TSRMLS_CC);
+                       if (RETURN_VALUE_USED(opline)) {
+                               zval_ptr_dtor(EX_VAR(opline->result.var));
                        }
-                       Z_OBJ(EG(This)) = EX(current_this);
-                       EG(scope) = EX(current_scope);
-                       EG(called_scope) = EX(current_called_scope);
+                       HANDLE_EXCEPTION_LEAVE();
+               }
 
-                       EX(call)--;
+               ZEND_VM_INC_OPCODE();
+               ZEND_VM_LEAVE();
+       } else if (frame_kind == VM_FRAME_NESTED_CODE) {
+               zend_detach_symbol_table(execute_data);
+               destroy_op_array(EX(op_array) TSRMLS_CC);
+               efree(EX(op_array));
+               zend_vm_stack_free((char*)execute_data TSRMLS_CC);
 
-                       zend_vm_stack_clear_multiple(1 TSRMLS_CC);
+               execute_data = EG(current_execute_data);
+               zend_attach_symbol_table(execute_data);
+               EX(function_state).function = (zend_function *) EX(op_array);
+               EX(function_state).arguments = NULL;
+               EG(opline_ptr) = &EX(opline);
+               EG(active_op_array) = EX(op_array);
+               if (UNEXPECTED(EG(exception) != NULL)) {
+                       zend_throw_exception_internal(NULL TSRMLS_CC);
+                       HANDLE_EXCEPTION_LEAVE();
+               }
 
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               zend_throw_exception_internal(NULL TSRMLS_CC);
-                               if (RETURN_VALUE_USED(opline)) {
-                                       zval_ptr_dtor(EX_VAR(opline->result.var));
+               ZEND_VM_INC_OPCODE();
+               ZEND_VM_LEAVE();
+       } else {
+               if (frame_kind == VM_FRAME_TOP_FUNCTION) {
+                       i_free_compiled_variables(execute_data TSRMLS_CC);
+               } else /* if (frame_kind == VM_FRAME_TOP_CODE) */ {
+                       zend_array *symbol_table = EX(symbol_table);
+                       zend_execute_data *old_execute_data;
+
+                       zend_detach_symbol_table(execute_data);
+                       old_execute_data = EX(prev_execute_data);
+                       while (old_execute_data) {
+                               if (old_execute_data->op_array) {
+                                       if (old_execute_data->symbol_table == symbol_table) {
+                                               zend_attach_symbol_table(old_execute_data);
+                                       }
+                                       break;
                                }
-                               HANDLE_EXCEPTION_LEAVE();
+                               old_execute_data = old_execute_data->prev_execute_data;
                        }
-
-                       ZEND_VM_INC_OPCODE();
-                       ZEND_VM_LEAVE();
                }
-       }
-       ZEND_VM_RETURN();
+               if ((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) && EX(op_array)->prototype) {
+                       zval_ptr_dtor((zval*)EX(op_array)->prototype);
+               }
+               zend_vm_stack_free((char*)execute_data TSRMLS_CC);
+               EG(opline_ptr) = NULL;
+               ZEND_VM_RETURN();
+       }               
 }
 
 ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
@@ -1951,7 +1958,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
                        }
                } else if (EXPECTED(zend_execute_ex == execute_ex)) {
                        if (EXPECTED(EG(exception) == NULL)) {
-                               i_create_execute_data_from_op_array(EG(active_op_array), return_value, 1 TSRMLS_CC);
+                               i_create_execute_data_from_op_array(EG(active_op_array), return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC);
                                ZEND_VM_ENTER();
                        }
                } else {
@@ -1960,7 +1967,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
 
                EG(opline_ptr) = &EX(opline);
                EG(active_op_array) = EX(op_array);
-               if (EG(active_symbol_table)) {
+               if (UNEXPECTED(EG(active_symbol_table) != NULL)) {
                        zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
                }
                EG(active_symbol_table) = EX(symbol_table);
@@ -3894,7 +3901,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
                }
 
                if (EXPECTED(zend_execute_ex == execute_ex)) {
-                   i_create_execute_data_from_op_array(new_op_array, return_value, 1 TSRMLS_CC);
+                   i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
                        ZEND_VM_ENTER();
                } else {
                        zend_execute(new_op_array, return_value TSRMLS_CC);
index 24e6ef1658ba93f4ad4415ab666f42e8ca4f1fef..9217e1113bcde24e93974461b3fb30b3afc16d18 100644 (file)
@@ -378,101 +378,108 @@ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value TSRMLS_DC
        if (EG(exception) != NULL) {
                return;
        } 
-       zend_execute_ex(i_create_execute_data_from_op_array(op_array, return_value, 0 TSRMLS_CC) TSRMLS_CC);
+       zend_execute_ex(i_create_execute_data_from_op_array(op_array, return_value, EG(active_symbol_table) ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC) TSRMLS_CC);
 }
 
 static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
 {
-       zend_bool nested = EX(nested);
-       zend_op_array *op_array = EX(op_array);
-
-       if ((nested && EX(prev_execute_data)->opline->opcode == ZEND_INCLUDE_OR_EVAL) ||
-           EG(active_symbol_table) == &EG(symbol_table)) {
-               zend_detach_symbol_table(TSRMLS_C);
-       }
+       vm_frame_kind frame_kind = EX(frame_kind);
 
        EG(current_execute_data) = EX(prev_execute_data);
-       EG(opline_ptr) = NULL;
 
-       if (EG(active_symbol_table) != &EG(symbol_table)) {
+       if (frame_kind == VM_FRAME_NESTED_FUNCTION) {
                i_free_compiled_variables(execute_data TSRMLS_CC);
-       }
-
-       zend_vm_stack_free((char*)execute_data TSRMLS_CC);
-
-       if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->prototype) {
-               zval_ptr_dtor((zval*)op_array->prototype);
-       }
+               if (UNEXPECTED(EX(symbol_table) != NULL)) {
+                       zend_clean_and_cache_symbol_table(EX(symbol_table) TSRMLS_CC);
+               }
+               if (UNEXPECTED((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) != 0) && EX(op_array)->prototype) {
+                       zval_ptr_dtor((zval*)EX(op_array)->prototype);
+               }
+               zend_vm_stack_free((char*)execute_data TSRMLS_CC);
 
-       if (nested) {
                execute_data = EG(current_execute_data);
-       }
-       if (nested) {
-               USE_OPLINE
-
-               LOAD_REGS();
-               LOAD_OPLINE();
-               if (UNEXPECTED(opline->opcode == ZEND_INCLUDE_OR_EVAL)) {
-
-                       zend_attach_symbol_table(TSRMLS_C);
+               EG(opline_ptr) = &EX(opline);
+               EG(active_op_array) = EX(op_array);
+               EG(active_symbol_table) = EX(symbol_table);
 
-                       EX(function_state).function = (zend_function *) EX(op_array);
-                       EX(function_state).arguments = NULL;
+               EX(function_state).function = (zend_function *) EX(op_array);
+               EX(function_state).arguments = NULL;
 
-                       EG(opline_ptr) = &EX(opline);
-                       EG(active_op_array) = EX(op_array);
-                       destroy_op_array(op_array TSRMLS_CC);
-                       efree(op_array);
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               zend_throw_exception_internal(NULL TSRMLS_CC);
-                               HANDLE_EXCEPTION_LEAVE();
+               if (Z_OBJ(EG(This))) {
+                       if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
+                               if (EX(call)->is_ctor_result_used) {
+                                       Z_DELREF(EG(This));
+                               }
+                               if (Z_REFCOUNT(EG(This)) == 1) {
+                                       zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
+                               }
                        }
+                       zval_ptr_dtor(&EG(This));
+               }
+               Z_OBJ(EG(This)) = EX(current_this);
+               EG(scope) = EX(current_scope);
+               EG(called_scope) = EX(current_called_scope);
 
-                       ZEND_VM_INC_OPCODE();
-                       ZEND_VM_LEAVE();
-               } else {
-                       EG(opline_ptr) = &EX(opline);
-                       EG(active_op_array) = EX(op_array);
-                       if (EG(active_symbol_table)) {
-                               zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
-                       }
-                       EG(active_symbol_table) = EX(symbol_table);
+               EX(call)--;
 
-                       EX(function_state).function = (zend_function *) EX(op_array);
-                       EX(function_state).arguments = NULL;
+               zend_vm_stack_clear_multiple(1 TSRMLS_CC);
 
-                       if (Z_OBJ(EG(This))) {
-                               if (UNEXPECTED(EG(exception) != NULL) && EX(call)->is_ctor_call) {
-                                       if (EX(call)->is_ctor_result_used) {
-                                               Z_DELREF(EG(This));
-                                       }
-                                       if (Z_REFCOUNT(EG(This)) == 1) {
-                                               zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
-                                       }
-                               }
-                               zval_ptr_dtor(&EG(This));
+               if (UNEXPECTED(EG(exception) != NULL)) {
+                       zend_op *opline = EX(opline);
+                       zend_throw_exception_internal(NULL TSRMLS_CC);
+                       if (RETURN_VALUE_USED(opline)) {
+                               zval_ptr_dtor(EX_VAR(opline->result.var));
                        }
-                       Z_OBJ(EG(This)) = EX(current_this);
-                       EG(scope) = EX(current_scope);
-                       EG(called_scope) = EX(current_called_scope);
+                       HANDLE_EXCEPTION_LEAVE();
+               }
 
-                       EX(call)--;
+               ZEND_VM_INC_OPCODE();
+               ZEND_VM_LEAVE();
+       } else if (frame_kind == VM_FRAME_NESTED_CODE) {
+               zend_detach_symbol_table(execute_data);
+               destroy_op_array(EX(op_array) TSRMLS_CC);
+               efree(EX(op_array));
+               zend_vm_stack_free((char*)execute_data TSRMLS_CC);
 
-                       zend_vm_stack_clear_multiple(1 TSRMLS_CC);
+               execute_data = EG(current_execute_data);
+               zend_attach_symbol_table(execute_data);
+               EX(function_state).function = (zend_function *) EX(op_array);
+               EX(function_state).arguments = NULL;
+               EG(opline_ptr) = &EX(opline);
+               EG(active_op_array) = EX(op_array);
+               if (UNEXPECTED(EG(exception) != NULL)) {
+                       zend_throw_exception_internal(NULL TSRMLS_CC);
+                       HANDLE_EXCEPTION_LEAVE();
+               }
 
-                       if (UNEXPECTED(EG(exception) != NULL)) {
-                               zend_throw_exception_internal(NULL TSRMLS_CC);
-                               if (RETURN_VALUE_USED(opline)) {
-                                       zval_ptr_dtor(EX_VAR(opline->result.var));
+               ZEND_VM_INC_OPCODE();
+               ZEND_VM_LEAVE();
+       } else {
+               if (frame_kind == VM_FRAME_TOP_FUNCTION) {
+                       i_free_compiled_variables(execute_data TSRMLS_CC);
+               } else /* if (frame_kind == VM_FRAME_TOP_CODE) */ {
+                       zend_array *symbol_table = EX(symbol_table);
+                       zend_execute_data *old_execute_data;
+
+                       zend_detach_symbol_table(execute_data);
+                       old_execute_data = EX(prev_execute_data);
+                       while (old_execute_data) {
+                               if (old_execute_data->op_array) {
+                                       if (old_execute_data->symbol_table == symbol_table) {
+                                               zend_attach_symbol_table(old_execute_data);
+                                       }
+                                       break;
                                }
-                               HANDLE_EXCEPTION_LEAVE();
+                               old_execute_data = old_execute_data->prev_execute_data;
                        }
-
-                       ZEND_VM_INC_OPCODE();
-                       ZEND_VM_LEAVE();
                }
+               if ((EX(op_array)->fn_flags & ZEND_ACC_CLOSURE) && EX(op_array)->prototype) {
+                       zval_ptr_dtor((zval*)EX(op_array)->prototype);
+               }
+               zend_vm_stack_free((char*)execute_data TSRMLS_CC);
+               EG(opline_ptr) = NULL;
+               ZEND_VM_RETURN();
        }
-       ZEND_VM_RETURN();
 }
 
 static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
@@ -586,7 +593,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
                        }
                } else if (EXPECTED(zend_execute_ex == execute_ex)) {
                        if (EXPECTED(EG(exception) == NULL)) {
-                               i_create_execute_data_from_op_array(EG(active_op_array), return_value, 1 TSRMLS_CC);
+                               i_create_execute_data_from_op_array(EG(active_op_array), return_value, VM_FRAME_NESTED_FUNCTION TSRMLS_CC);
                                ZEND_VM_ENTER();
                        }
                } else {
@@ -595,7 +602,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
 
                EG(opline_ptr) = &EX(opline);
                EG(active_op_array) = EX(op_array);
-               if (EG(active_symbol_table)) {
+               if (UNEXPECTED(EG(active_symbol_table) != NULL)) {
                        zend_clean_and_cache_symbol_table(EG(active_symbol_table) TSRMLS_CC);
                }
                EG(active_symbol_table) = EX(symbol_table);
@@ -2924,7 +2931,7 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
                }
 
                if (EXPECTED(zend_execute_ex == execute_ex)) {
-                   i_create_execute_data_from_op_array(new_op_array, return_value, 1 TSRMLS_CC);
+                   i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
                        ZEND_VM_ENTER();
                } else {
                        zend_execute(new_op_array, return_value TSRMLS_CC);
@@ -7872,7 +7879,7 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
                }
 
                if (EXPECTED(zend_execute_ex == execute_ex)) {
-                   i_create_execute_data_from_op_array(new_op_array, return_value, 1 TSRMLS_CC);
+                   i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
                        ZEND_VM_ENTER();
                } else {
                        zend_execute(new_op_array, return_value TSRMLS_CC);
@@ -12862,7 +12869,7 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
                }
 
                if (EXPECTED(zend_execute_ex == execute_ex)) {
-                   i_create_execute_data_from_op_array(new_op_array, return_value, 1 TSRMLS_CC);
+                   i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
                        ZEND_VM_ENTER();
                } else {
                        zend_execute(new_op_array, return_value TSRMLS_CC);
@@ -29382,7 +29389,7 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
                }
 
                if (EXPECTED(zend_execute_ex == execute_ex)) {
-                   i_create_execute_data_from_op_array(new_op_array, return_value, 1 TSRMLS_CC);
+                   i_create_execute_data_from_op_array(new_op_array, return_value, VM_FRAME_NESTED_CODE TSRMLS_CC);
                        ZEND_VM_ENTER();
                } else {
                        zend_execute(new_op_array, return_value TSRMLS_CC);
index e017abbce6258dfca36c15f5cf2a986e4e4cd017..fa976cb6783001698b4d8338f1a92b752584c8fc 100644 (file)
@@ -36,7 +36,7 @@ ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value
        if (EG(exception) != NULL) {
                return;
        } 
-       zend_{%EXECUTOR_NAME%}_ex(i_create_execute_data_from_op_array(op_array, return_value, 0 TSRMLS_CC) TSRMLS_CC);
+       zend_{%EXECUTOR_NAME%}_ex(i_create_execute_data_from_op_array(op_array, return_value, EG(active_symbol_table) ? VM_FRAME_TOP_CODE : VM_FRAME_TOP_FUNCTION TSRMLS_CC) TSRMLS_CC);
 }
 
 {%EXTERNAL_EXECUTOR%}
index f4abb97a90437b7d75feba51cb682cc80ee1ebe8..7aea80afddc8c7a401d25853058701f829adb074 100644 (file)
@@ -1079,10 +1079,10 @@ void phpdbg_clean(zend_bool full TSRMLS_DC) /* {{{ */
        }
 } /* }}} */
 
-static inline zend_execute_data *phpdbg_create_execute_data(zend_op_array *op_array, zval *return_value, zend_bool nested TSRMLS_DC) /* {{{ */
+static inline zend_execute_data *phpdbg_create_execute_data(zend_op_array *op_array, zval *return_value, vm_frame_kind frame_kind TSRMLS_DC) /* {{{ */
 {
 #if PHP_VERSION_ID >= 50500
-       return zend_create_execute_data_from_op_array(op_array, return_value, nested TSRMLS_CC);
+       return zend_create_execute_data_from_op_array(op_array, return_value, frame_kind TSRMLS_CC);
 #else
 
 #undef EX