]> granicus.if.org Git - php/commitdiff
Redesigned zend_execute_data layout now EX(object), EX(scope) and EX(called_scope...
authorDmitry Stogov <dmitry@zend.com>
Thu, 24 Apr 2014 11:53:20 +0000 (15:53 +0400)
committerDmitry Stogov <dmitry@zend.com>
Thu, 24 Apr 2014 11:53:20 +0000 (15:53 +0400)
ntext. They are set during zend_execute_data initialization and never changed.

Zend/zend_builtin_functions.c
Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute_API.c
Zend/zend_generators.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
sapi/phpdbg/phpdbg.c
sapi/phpdbg/phpdbg_frame.c

index 22076104f000bba81f70c6b13049b8a3eb66285d..1d066deb417d220d447fed9e1b388e623d15dc24 100644 (file)
@@ -1991,6 +1991,7 @@ void debug_print_backtrace_args(zval *arg_array TSRMLS_DC)
 ZEND_FUNCTION(debug_print_backtrace)
 {
        zend_execute_data *ptr, *skip;
+       zend_object *object;
        int lineno, frameno = 0;
        const char *function_name;
        const char *filename;
@@ -2010,6 +2011,7 @@ ZEND_FUNCTION(debug_print_backtrace)
        ptr = EG(current_execute_data);
 
        /* skip debug_backtrace() */
+       object = ptr->object;
        ptr = ptr->prev_execute_data;
 
        while (ptr && (limit == 0 || frameno < limit)) {
@@ -2037,11 +2039,18 @@ ZEND_FUNCTION(debug_print_backtrace)
                        lineno = 0;
                }
 
+               /* $this may be passed into regular internal functions */
+               if (object &&
+                   ptr->function_state.function->type == ZEND_INTERNAL_FUNCTION &&
+                   !ptr->function_state.function->common.scope) {
+                       object = NULL;
+               }
+
                function_name = (ptr->function_state.function->common.scope &&
                        ptr->function_state.function->common.scope->trait_aliases) ?
                                zend_resolve_method_name(
-                                       ptr->object ?
-                                               zend_get_class_entry(ptr->object TSRMLS_CC) : 
+                                       object ?
+                                               zend_get_class_entry(object TSRMLS_CC) : 
                                                ptr->function_state.function->common.scope,
                                        ptr->function_state.function)->val :
                                (ptr->function_state.function->common.function_name ?
@@ -2049,11 +2058,11 @@ ZEND_FUNCTION(debug_print_backtrace)
                                 NULL);
 
                if (function_name) {
-                       if (ptr->object) {
+                       if (object) {
                                if (ptr->function_state.function->common.scope) {
                                        class_name = ptr->function_state.function->common.scope->name;
                                } else {
-                                       class_name = zend_get_object_classname(ptr->object TSRMLS_CC);
+                                       class_name = zend_get_object_classname(object TSRMLS_CC);
                                }
 
                                call_type = "->";
@@ -2141,6 +2150,7 @@ ZEND_FUNCTION(debug_print_backtrace)
                        }
                }
                include_filename = filename;
+               object = skip->object;
                ptr = skip->prev_execute_data;
                ++indent;
        }
@@ -2151,6 +2161,7 @@ ZEND_FUNCTION(debug_print_backtrace)
 ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int options, int limit TSRMLS_DC)
 {
        zend_execute_data *ptr, *skip;
+       zend_object *object = Z_OBJ(EG(This));
        int lineno, frameno = 0;
        const char *function_name;
        const char *filename;
@@ -2162,11 +2173,13 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
 
        /* skip "new Exception()" */
        if (ptr && (skip_last == 0) && ptr->opline && (ptr->opline->opcode == ZEND_NEW)) {
+               object = ptr->object;
                ptr = ptr->prev_execute_data;
        }
 
        /* skip debug_backtrace() */
        if (skip_last-- && ptr) {
+               object = ptr->object;
                ptr = ptr->prev_execute_data;
        }
 
@@ -2217,11 +2230,18 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
                        filename = NULL;
                }
 
+               /* $this may be passed into regular internal functions */
+               if (object &&
+                   ptr->function_state.function->type == ZEND_INTERNAL_FUNCTION &&
+                   !ptr->function_state.function->common.scope) {
+                       object = NULL;
+               }
+
                function_name = (ptr->function_state.function->common.scope &&
                        ptr->function_state.function->common.scope->trait_aliases) ?
                                zend_resolve_method_name(
-                                       ptr->object ?
-                                               zend_get_class_entry(ptr->object TSRMLS_CC) : 
+                                       object ?
+                                               zend_get_class_entry(object TSRMLS_CC) : 
                                                ptr->function_state.function->common.scope,
                                        ptr->function_state.function)->val :
                                (ptr->function_state.function->common.function_name ?
@@ -2231,19 +2251,19 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
                if (function_name) {
                        add_assoc_string_ex(&stack_frame, "function", sizeof("function")-1, (char*)function_name);
 
-                       if (ptr->object) {
+                       if (object) {
                                if (ptr->function_state.function->common.scope) {
                                        add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(ptr->function_state.function->common.scope->name));
                                } else {
-                                       class_name = zend_get_object_classname(ptr->object TSRMLS_CC);
+                                       class_name = zend_get_object_classname(object TSRMLS_CC);
                                        add_assoc_str_ex(&stack_frame, "class", sizeof("class")-1, STR_COPY(class_name));
                                        
                                }
                                if ((options & DEBUG_BACKTRACE_PROVIDE_OBJECT) != 0) {
-                                       zval object;
-                                       ZVAL_OBJ(&object, ptr->object);
-                                       add_assoc_zval_ex(&stack_frame, "object", sizeof("object")-1, &object);
-                                       Z_ADDREF(object);
+                                       zval zv;
+                                       ZVAL_OBJ(&zv, object);
+                                       add_assoc_zval_ex(&stack_frame, "object", sizeof("object")-1, &zv);
+                                       Z_ADDREF(zv);
                                }
 
                                add_assoc_string_ex(&stack_frame, "type", sizeof("type")-1, "->");
@@ -2314,6 +2334,7 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
 
                include_filename = filename; 
 
+               object = skip->object;
                ptr = skip->prev_execute_data;
        }
 }
index 35559a21d48dfe65b0f7c5e026933d3477163143..24f06c426f7297cbb74857fa73fa410ba6ab05cd 100644 (file)
@@ -374,20 +374,19 @@ typedef enum _vm_frame_kind {
 } vm_frame_kind;
 
 struct _zend_execute_data {
-       struct _zend_op *opline;
-       void **run_time_cache;
-       zend_function_state function_state;
-       zend_op_array *op_array;
-       zend_object *object;
-       zend_array *symbol_table;
-       struct _zend_execute_data *prev_execute_data;
+       struct _zend_op     *opline;           /* executed opline                */
+       zend_op_array       *op_array;         /* executed op_array              */
+       zend_function_state  function_state;   /* called function and arguments  */
+       zend_object         *object;           /* current $this                  */
+       zend_class_entry    *scope;            /* function scope (self)          */
+       zend_class_entry    *called_scope;     /* function called scope (static) */
+       zend_array          *symbol_table;
+       void               **run_time_cache;
+       zend_execute_data   *prev_execute_data;
+       zval                *return_value;
+       vm_frame_kind        frame_kind;
+       // TODO: simplify call sequence and remove call_* ???
        zval old_error_reporting;
-       vm_frame_kind frame_kind;
-       zval *return_value;
-       // TODO: simplify call sequence and remove current_* and call_* ???
-       zend_class_entry *current_scope;
-       zend_class_entry *current_called_scope;
-       zend_object *current_this;
        struct _zend_op *fast_ret; /* used by FAST_CALL/FAST_RET (finally keyword) */
        zend_object *delayed_exception;
        call_slot *call_slots;
index 2866f841d6e15ea2167e41b3a154673b4de61d33..2dc3c22414ff0d1158facdc731e6211678c059f1 100644 (file)
@@ -1624,52 +1624,50 @@ static zend_always_inline zend_execute_data *i_create_execute_data_from_op_array
                EX(prev_execute_data) = EG(current_execute_data);
        }
 
-       do {
-               /* Initialize CV variables */
-               zval *var = EX_VAR_NUM(0);
-               zval *end = var + op_array->last_var;
-
-               while (var != end) {
-                       ZVAL_UNDEF(var);
-                       var++;
-               }
-       } while (0);
-
+       EX(return_value) = return_value;
+       EX(frame_kind) = frame_kind;
+       ZVAL_UNDEF(&EX(old_error_reporting));
+       EX(delayed_exception) = NULL;
        EX(call_slots) = (call_slot*)((char *)execute_data + execute_data_size + vars_size);
+       EX(call) = NULL;
 
-
+       EG(opline_ptr) = &EX(opline);
+       EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
+       EX(function_state).function = (zend_function *) op_array;
+       EX(function_state).arguments = NULL;
        EX(op_array) = op_array;
-
-       EG(argument_stack)->top = (zval*)zend_vm_stack_frame_base(execute_data);
-
-       EX(object) = NULL;
-       EX(current_this) = NULL;
-       ZVAL_UNDEF(&EX(old_error_reporting));
+       EX(object) = Z_OBJ(EG(This));
+       EX(scope) = EG(scope);
+       EX(called_scope) = EG(called_scope);
        EX(symbol_table) = EG(active_symbol_table);
-       EX(call) = NULL;
-       EG(current_execute_data) = execute_data;
-       EX(frame_kind) = frame_kind;
-       EX(delayed_exception) = NULL;
-       EX(return_value) = return_value;
-
-       if (!op_array->run_time_cache && op_array->last_cache_slot) {
-               op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
-       }
-       EX(run_time_cache) = op_array->run_time_cache;
 
        if (EX(symbol_table)) {
                zend_attach_symbol_table(execute_data);
-       }
+       } else {
+               do {
+                       /* Initialize CV variables */
+                       zval *var = EX_VAR_NUM(0);
+                       zval *end = var + op_array->last_var;
+
+                       while (var != end) {
+                               ZVAL_UNDEF(var);
+                               var++;
+                       }
+               } while (0);
 
-       if (op_array->this_var != -1 && Z_OBJ(EG(This))) {
-               ZVAL_COPY(EX_VAR(op_array->this_var), &EG(This));
+               if (op_array->this_var != -1 && Z_OBJ(EG(This))) {
+                       ZVAL_OBJ(EX_VAR(op_array->this_var), Z_OBJ(EG(This)));
+                       Z_ADDREF(EG(This));
+               }
        }
 
-       EX(opline) = UNEXPECTED((op_array->fn_flags & ZEND_ACC_INTERACTIVE) != 0) && EG(start_op) ? EG(start_op) : op_array->opcodes;
-       EG(opline_ptr) = &EX(opline);
+       if (!op_array->run_time_cache && op_array->last_cache_slot) {
+               op_array->run_time_cache = ecalloc(op_array->last_cache_slot, sizeof(void*));
+       }
+       EX(run_time_cache) = op_array->run_time_cache;
 
-       EX(function_state).function = (zend_function *) op_array;
-       EX(function_state).arguments = NULL;
+       EG(argument_stack)->top = (zval*)zend_vm_stack_frame_base(execute_data);
+       EG(current_execute_data) = execute_data;
 
        return execute_data;
 }
index 0091fea00de0ccc44a141ac717c115acb7f83948..d2fefa7f711c9ff2f58b91ea81e0895445e307c5 100644 (file)
@@ -770,11 +770,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
        zend_array *calling_symbol_table;
        zend_op_array *original_op_array;
        zend_op **original_opline_ptr;
-       zend_class_entry *current_scope;
-       zend_class_entry *current_called_scope;
        zend_class_entry *calling_scope = NULL;
        zend_class_entry *called_scope = NULL;
-       zend_object *current_this;
        zend_execute_data execute_data;
        zend_fcall_info_cache fci_cache_local;
        zval tmp;
@@ -800,9 +797,11 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
        /* Initialize execute_data */
        if (EG(current_execute_data)) {
                execute_data = *EG(current_execute_data);
+               EX(object) = Z_OBJ(EG(This));
+               EX(scope) = EG(scope);
+               EX(called_scope) = EG(called_scope);
                EX(op_array) = NULL;
                EX(opline) = NULL;
-               EX(object) = NULL;
        } else {
                /* This only happens when we're called outside any execute()'s
                 * It shouldn't be strictly necessary to NULL execute_data out,
@@ -842,7 +841,7 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
        EX(function_state).function = fci_cache->function_handler;
        calling_scope = fci_cache->calling_scope;
        called_scope = fci_cache->called_scope;
-       EX(object) = fci->object = fci_cache->object;
+       fci->object = fci_cache->object;
        if (fci->object &&
            (!EG(objects_store).object_buckets ||
             !IS_OBJ_VALID(EG(objects_store).object_buckets[fci->object->handle]))) {
@@ -916,18 +915,8 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
        ZVAL_LONG(&tmp, fci->param_count);
        zend_vm_stack_push(&tmp TSRMLS_CC);
 
-       current_scope = EG(scope);
        EG(scope) = calling_scope;
-
-       current_this = Z_OBJ(EG(This));
-
-       current_called_scope = EG(called_scope);
-       if (called_scope) {
-               EG(called_scope) = called_scope;
-       } else if (EX(function_state).function->type != ZEND_INTERNAL_FUNCTION) {
-               EG(called_scope) = NULL;
-       }
-
+       EG(called_scope) = called_scope;
        if (!fci->object ||
            (EX(function_state).function->common.fn_flags & ZEND_ACC_STATIC)) {
                Z_OBJ(EG(This)) = NULL;
@@ -1016,9 +1005,10 @@ int zend_call_function(zend_fcall_info *fci, zend_fcall_info_cache *fci_cache TS
        if (Z_OBJ(EG(This))) {
                zval_ptr_dtor(&EG(This));
        }
-       EG(called_scope) = current_called_scope;
-       EG(scope) = current_scope;
-       Z_OBJ(EG(This)) = current_this;
+
+       Z_OBJ(EG(This)) = EX(object);
+       EG(scope) = EX(scope);
+       EG(called_scope) = EX(called_scope);
        EG(current_execute_data) = EX(prev_execute_data);
 
        if (EG(exception)) {
@@ -1711,12 +1701,6 @@ ZEND_API void zend_rebuild_symbol_table(TSRMLS_D) /* {{{ */
                                /*printf("Cache miss!  Initialized %x\n", EG(active_symbol_table));*/
                        }
                        ex->symbol_table = EG(active_symbol_table);
-
-                       if (ex->op_array->this_var != -1 &&
-                           Z_TYPE_P(EX_VAR_2(ex, ex->op_array->this_var)) == IS_UNDEF &&
-                           Z_OBJ(EG(This))) {
-                           ZVAL_COPY_VALUE(EX_VAR_2(ex, ex->op_array->this_var), &EG(This));
-                       }
                        for (i = 0; i < ex->op_array->last_var; i++) {
                                zval zv;
                                        
index 74df4cdb7b898509ed170c2f8843ef1b825d31d2..0f19e84041a89f5cb40ab59dd82198b4f16461e1 100644 (file)
@@ -118,8 +118,8 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
                        zend_clean_and_cache_symbol_table(execute_data->symbol_table TSRMLS_CC);
                }
 
-               if (execute_data->current_this) {
-                       OBJ_RELEASE(execute_data->current_this);
+               if (execute_data->object) {
+                       OBJ_RELEASE(execute_data->object);
                }
 
                /* A fatal error / die occurred during the generator execution. Trying to clean
@@ -298,13 +298,8 @@ ZEND_API void zend_generator_create_zval(zend_op_array *op_array, zval *return_v
                Z_ADDREF(EG(This));
        }
 
-       /* Back up executor globals. */
-       execute_data->current_scope = EG(scope);
-       execute_data->current_called_scope = EG(called_scope);
-       execute_data->symbol_table = EG(active_symbol_table);
-       execute_data->current_this = Z_OBJ(EG(This));
-
        /* Save execution context in generator object. */
+       execute_data->prev_execute_data->object = Z_OBJ_P(return_value);
        generator = (zend_generator *) Z_OBJ_P(return_value);
        generator->execute_data = execute_data;
        generator->stack = EG(argument_stack);
@@ -355,9 +350,9 @@ ZEND_API void zend_generator_resume(zend_generator *generator TSRMLS_DC) /* {{{
                EG(opline_ptr) = &generator->execute_data->opline;
                EG(active_op_array) = generator->execute_data->op_array;
                EG(active_symbol_table) = generator->execute_data->symbol_table;
-               Z_OBJ(EG(This)) = generator->execute_data->current_this;
-               EG(scope) = generator->execute_data->current_scope;
-               EG(called_scope) = generator->execute_data->current_called_scope;
+               Z_OBJ(EG(This)) = generator->execute_data->object;
+               EG(scope) = generator->execute_data->scope;
+               EG(called_scope) = generator->execute_data->called_scope;
                EG(argument_stack) = generator->stack;
 
                /* We want the backtrace to look as if the generator function was
index 7808b441fdf1c39a56545c44c68d4e565ea17e55..2d4771c004f4f11bb82070f58eb3ffe366f7041a 100644 (file)
@@ -1805,11 +1805,15 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
                                        zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
                                }
                        }
-                       zval_ptr_dtor(&EG(This));
+                       if (!Z_DELREF(EG(This))) {
+                               _zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
+                       } else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
+                               gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
+                       }
                }
-               Z_OBJ(EG(This)) = EX(current_this);
-               EG(scope) = EX(current_scope);
-               EG(called_scope) = EX(current_called_scope);
+               Z_OBJ(EG(This)) = EX(object);
+               EG(scope) = EX(scope);
+               EG(called_scope) = EX(called_scope);
 
                EX(call)--;
 
@@ -1878,12 +1882,12 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
 ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
 {
        USE_OPLINE
-       zend_bool should_change_scope = 0;
        zend_function *fbc = EX(function_state).function;
+       zend_object *object;
        zend_uint num_args;
 
        SAVE_OPLINE();
-       EX(object) = EX(call)->object;
+       object = EX(call)->object;
        if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
                if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
                        zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val);
@@ -1900,7 +1904,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
        }
        if (fbc->common.scope &&
                !(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
-               !EX(object)) {
+               !object) {
 
                if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
                        /* FIXME: output identifiers properly */
@@ -1915,17 +1919,6 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
                }
        }
 
-       if (fbc->type == ZEND_USER_FUNCTION || fbc->common.scope) {
-               should_change_scope = 1;
-               EX(current_this) = Z_OBJ(EG(This));
-               EX(current_scope) = EG(scope);
-               EX(current_called_scope) = EG(called_scope);
-               Z_OBJ(EG(This)) = EX(object);
-//???          EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL;
-               EG(scope) = fbc->common.scope;
-               EG(called_scope) = EX(call)->called_scope;
-       }
-
        if (UNEXPECTED(EX(call)->num_additional_args != 0)) {
                num_args = opline->extended_value + EX(call)->num_additional_args;
                EX(function_state).arguments = zend_vm_stack_push_args(num_args TSRMLS_CC);
@@ -1940,6 +1933,17 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
        LOAD_OPLINE();
 
        if (fbc->type == ZEND_INTERNAL_FUNCTION) {
+               int should_change_scope = 0;
+               zval *ret;
+
+               if (fbc->common.scope) {
+                       should_change_scope = 1;
+                       Z_OBJ(EG(This)) = object;
+//???                  EG(scope) = (object) ? NULL : fbc->common.scope;
+                       EG(scope) = fbc->common.scope;
+                       EG(called_scope) = EX(call)->called_scope;
+               }
+
                if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
                        zend_uint i;
                        zval *p = EX(function_state).arguments - num_args;
@@ -1947,30 +1951,44 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
                        for (i = 0; i < num_args; ++i, ++p) {
                                zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC);
                        }
+                       if (UNEXPECTED(EG(exception) != NULL)) {
+                               if (RETURN_VALUE_USED(opline)) {
+                                       ZVAL_UNDEF(EX_VAR(opline->result.var));
+                               }
+                               if (UNEXPECTED(should_change_scope)) {
+                                       ZEND_VM_C_GOTO(fcall_end_change_scope);
+                               } else {
+                                       ZEND_VM_C_GOTO(fcall_end);
+                               }
+                       }
                }
 
-               if (EXPECTED(EG(exception) == NULL)) {
-                       zval *ret = EX_VAR(opline->result.var);
+               ret = EX_VAR(opline->result.var);
+               ZVAL_NULL(ret);
+               Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
 
-                       ZVAL_NULL(ret);
-                       Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
+               if (!zend_execute_internal) {
+                       /* saves one function call if zend_execute_internal is not used */
+                       fbc->internal_function.handler(num_args, ret TSRMLS_CC);
+               } else {
+                       zend_execute_internal(execute_data, NULL TSRMLS_CC);
+               }
 
-                       if (!zend_execute_internal) {
-                               /* saves one function call if zend_execute_internal is not used */
-                               fbc->internal_function.handler(num_args, ret TSRMLS_CC);
-                       } else {
-                               zend_execute_internal(execute_data, NULL TSRMLS_CC);
-                       }
+               if (!RETURN_VALUE_USED(opline)) {
+                       zval_ptr_dtor(ret);
+               }
 
-                       if (!RETURN_VALUE_USED(opline)) {
-                               zval_ptr_dtor(ret);
-                       }
-               } else if (RETURN_VALUE_USED(opline)) {
-                       ZVAL_UNDEF(EX_VAR(opline->result.var));
+               if (UNEXPECTED(should_change_scope)) {
+                       ZEND_VM_C_GOTO(fcall_end_change_scope);
+               } else {
+                       ZEND_VM_C_GOTO(fcall_end);
                }
        } else if (fbc->type == ZEND_USER_FUNCTION) {
                zval *return_value = NULL;
 
+               Z_OBJ(EG(This)) = object;
+               EG(scope) = fbc->common.scope;
+               EG(called_scope) = EX(call)->called_scope;
                EG(active_symbol_table) = NULL;
                EG(active_op_array) = &fbc->op_array;
                if (RETURN_VALUE_USED(opline)) {
@@ -2000,11 +2018,16 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
                }
                EG(active_symbol_table) = EX(symbol_table);
        } else { /* ZEND_OVERLOADED_FUNCTION */
+               Z_OBJ(EG(This)) = object;
+//???          EG(scope) = NULL;
+               EG(scope) = fbc->common.scope;
+               EG(called_scope) = EX(call)->called_scope;
+
                ZVAL_NULL(EX_VAR(opline->result.var));
 
                /* Not sure what should be done here if it's a static method */
-               if (EXPECTED(EX(object) != NULL)) {
-                       EX(object)->handlers->call_method(fbc->common.function_name, EX(object), num_args, EX_VAR(opline->result.var) TSRMLS_CC);
+               if (EXPECTED(object != NULL)) {
+                       object->handlers->call_method(fbc->common.function_name, object, num_args, EX_VAR(opline->result.var) TSRMLS_CC);
                } else {
                        zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
                }
@@ -2023,26 +2046,31 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
                }
        }
 
-       EX(function_state).function = (zend_function *) EX(op_array);
-       EX(function_state).arguments = NULL;
-
-       if (should_change_scope) {
-               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);
-                               }
+ZEND_VM_C_LABEL(fcall_end_change_scope):
+       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);
+               if (!Z_DELREF(EG(This))) {
+                       EX(function_state).function = (zend_function *) EX(op_array);
+                       EX(function_state).arguments = NULL;
+                       _zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
+               } else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
+                       gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
+               }
        }
+       Z_OBJ(EG(This)) = EX(object);
+       EG(scope) = EX(scope);
+       EG(called_scope) = EX(called_scope);
 
+ZEND_VM_C_LABEL(fcall_end):
+       EX(function_state).function = (zend_function *) EX(op_array);
+       EX(function_state).arguments = NULL;
        EX(call)--;
 
        zend_vm_stack_clear_multiple(1 TSRMLS_CC);
@@ -3923,7 +3951,6 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
                }
 
                EX(function_state).function = (zend_function *) new_op_array;
-               EX(object) = NULL;
 
                if (!EG(active_symbol_table)) {
                        zend_rebuild_symbol_table(TSRMLS_C);
index c0ff942e20207a30858cf6dd3ce1ce40a5e2e9fc..1ec6d973437969e5e9ab701195ad6efdfc228550 100644 (file)
@@ -414,11 +414,15 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
                                        zend_object_store_ctor_failed(Z_OBJ(EG(This)) TSRMLS_CC);
                                }
                        }
-                       zval_ptr_dtor(&EG(This));
+                       if (!Z_DELREF(EG(This))) {
+                               _zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
+                       } else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
+                               gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
+                       }
                }
-               Z_OBJ(EG(This)) = EX(current_this);
-               EG(scope) = EX(current_scope);
-               EG(called_scope) = EX(current_called_scope);
+               Z_OBJ(EG(This)) = EX(object);
+               EG(scope) = EX(scope);
+               EG(called_scope) = EX(called_scope);
 
                EX(call)--;
 
@@ -487,12 +491,12 @@ static int ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
 static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
 {
        USE_OPLINE
-       zend_bool should_change_scope = 0;
        zend_function *fbc = EX(function_state).function;
+       zend_object *object;
        zend_uint num_args;
 
        SAVE_OPLINE();
-       EX(object) = EX(call)->object;
+       object = EX(call)->object;
        if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) {
                if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) {
                        zend_error_noreturn(E_ERROR, "Cannot call abstract method %s::%s()", fbc->common.scope->name->val, fbc->common.function_name->val);
@@ -509,7 +513,7 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
        }
        if (fbc->common.scope &&
                !(fbc->common.fn_flags & ZEND_ACC_STATIC) &&
-               !EX(object)) {
+               !object) {
 
                if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
                        /* FIXME: output identifiers properly */
@@ -524,17 +528,6 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
                }
        }
 
-       if (fbc->type == ZEND_USER_FUNCTION || fbc->common.scope) {
-               should_change_scope = 1;
-               EX(current_this) = Z_OBJ(EG(This));
-               EX(current_scope) = EG(scope);
-               EX(current_called_scope) = EG(called_scope);
-               Z_OBJ(EG(This)) = EX(object);
-//???          EG(scope) = (fbc->type == ZEND_USER_FUNCTION || !EX(object)) ? fbc->common.scope : NULL;
-               EG(scope) = fbc->common.scope;
-               EG(called_scope) = EX(call)->called_scope;
-       }
-
        if (UNEXPECTED(EX(call)->num_additional_args != 0)) {
                num_args = opline->extended_value + EX(call)->num_additional_args;
                EX(function_state).arguments = zend_vm_stack_push_args(num_args TSRMLS_CC);
@@ -549,6 +542,17 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
        LOAD_OPLINE();
 
        if (fbc->type == ZEND_INTERNAL_FUNCTION) {
+               int should_change_scope = 0;
+               zval *ret;
+
+               if (fbc->common.scope) {
+                       should_change_scope = 1;
+                       Z_OBJ(EG(This)) = object;
+//???                  EG(scope) = (object) ? NULL : fbc->common.scope;
+                       EG(scope) = fbc->common.scope;
+                       EG(called_scope) = EX(call)->called_scope;
+               }
+
                if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) {
                        zend_uint i;
                        zval *p = EX(function_state).arguments - num_args;
@@ -556,30 +560,44 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
                        for (i = 0; i < num_args; ++i, ++p) {
                                zend_verify_arg_type(fbc, i + 1, p, 0 TSRMLS_CC);
                        }
+                       if (UNEXPECTED(EG(exception) != NULL)) {
+                               if (RETURN_VALUE_USED(opline)) {
+                                       ZVAL_UNDEF(EX_VAR(opline->result.var));
+                               }
+                               if (UNEXPECTED(should_change_scope)) {
+                                       goto fcall_end_change_scope;
+                               } else {
+                                       goto fcall_end;
+                               }
+                       }
                }
 
-               if (EXPECTED(EG(exception) == NULL)) {
-                       zval *ret = EX_VAR(opline->result.var);
+               ret = EX_VAR(opline->result.var);
+               ZVAL_NULL(ret);
+               Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
 
-                       ZVAL_NULL(ret);
-                       Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0;
+               if (!zend_execute_internal) {
+                       /* saves one function call if zend_execute_internal is not used */
+                       fbc->internal_function.handler(num_args, ret TSRMLS_CC);
+               } else {
+                       zend_execute_internal(execute_data, NULL TSRMLS_CC);
+               }
 
-                       if (!zend_execute_internal) {
-                               /* saves one function call if zend_execute_internal is not used */
-                               fbc->internal_function.handler(num_args, ret TSRMLS_CC);
-                       } else {
-                               zend_execute_internal(execute_data, NULL TSRMLS_CC);
-                       }
+               if (!RETURN_VALUE_USED(opline)) {
+                       zval_ptr_dtor(ret);
+               }
 
-                       if (!RETURN_VALUE_USED(opline)) {
-                               zval_ptr_dtor(ret);
-                       }
-               } else if (RETURN_VALUE_USED(opline)) {
-                       ZVAL_UNDEF(EX_VAR(opline->result.var));
+               if (UNEXPECTED(should_change_scope)) {
+                       goto fcall_end_change_scope;
+               } else {
+                       goto fcall_end;
                }
        } else if (fbc->type == ZEND_USER_FUNCTION) {
                zval *return_value = NULL;
 
+               Z_OBJ(EG(This)) = object;
+               EG(scope) = fbc->common.scope;
+               EG(called_scope) = EX(call)->called_scope;
                EG(active_symbol_table) = NULL;
                EG(active_op_array) = &fbc->op_array;
                if (RETURN_VALUE_USED(opline)) {
@@ -609,11 +627,16 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
                }
                EG(active_symbol_table) = EX(symbol_table);
        } else { /* ZEND_OVERLOADED_FUNCTION */
+               Z_OBJ(EG(This)) = object;
+//???          EG(scope) = NULL;
+               EG(scope) = fbc->common.scope;
+               EG(called_scope) = EX(call)->called_scope;
+
                ZVAL_NULL(EX_VAR(opline->result.var));
 
                /* Not sure what should be done here if it's a static method */
-               if (EXPECTED(EX(object) != NULL)) {
-                       EX(object)->handlers->call_method(fbc->common.function_name, EX(object), num_args, EX_VAR(opline->result.var) TSRMLS_CC);
+               if (EXPECTED(object != NULL)) {
+                       object->handlers->call_method(fbc->common.function_name, object, num_args, EX_VAR(opline->result.var) TSRMLS_CC);
                } else {
                        zend_error_noreturn(E_ERROR, "Cannot call overloaded function for non-object");
                }
@@ -632,26 +655,31 @@ static int ZEND_FASTCALL zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_AR
                }
        }
 
-       EX(function_state).function = (zend_function *) EX(op_array);
-       EX(function_state).arguments = NULL;
-
-       if (should_change_scope) {
-               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);
-                               }
+fcall_end_change_scope:
+       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);
+               if (!Z_DELREF(EG(This))) {
+                       EX(function_state).function = (zend_function *) EX(op_array);
+                       EX(function_state).arguments = NULL;
+                       _zval_dtor_func_for_ptr(Z_COUNTED(EG(This)) ZEND_FILE_LINE_CC);
+               } else if (UNEXPECTED(!Z_GC_INFO(EG(This)))) {
+                       gc_possible_root(Z_COUNTED(EG(This)) TSRMLS_CC);
+               }
        }
+       Z_OBJ(EG(This)) = EX(object);
+       EG(scope) = EX(scope);
+       EG(called_scope) = EX(called_scope);
 
+fcall_end:
+       EX(function_state).function = (zend_function *) EX(op_array);
+       EX(function_state).arguments = NULL;
        EX(call)--;
 
        zend_vm_stack_clear_multiple(1 TSRMLS_CC);
@@ -2916,7 +2944,6 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HA
                }
 
                EX(function_state).function = (zend_function *) new_op_array;
-               EX(object) = NULL;
 
                if (!EG(active_symbol_table)) {
                        zend_rebuild_symbol_table(TSRMLS_C);
@@ -7953,7 +7980,6 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HAND
                }
 
                EX(function_state).function = (zend_function *) new_op_array;
-               EX(object) = NULL;
 
                if (!EG(active_symbol_table)) {
                        zend_rebuild_symbol_table(TSRMLS_C);
@@ -13058,7 +13084,6 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HAND
                }
 
                EX(function_state).function = (zend_function *) new_op_array;
-               EX(object) = NULL;
 
                if (!EG(active_symbol_table)) {
                        zend_rebuild_symbol_table(TSRMLS_C);
@@ -29866,7 +29891,6 @@ static int ZEND_FASTCALL  ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDL
                }
 
                EX(function_state).function = (zend_function *) new_op_array;
-               EX(object) = NULL;
 
                if (!EG(active_symbol_table)) {
                        zend_rebuild_symbol_table(TSRMLS_C);
index 64babced64badcffbe62c003e2990e146dcc907f..f20ad3f222ff5faff35a6747dc26cb9e2c78c21a 100644 (file)
@@ -613,7 +613,6 @@ const char phpdbg_ini_hardcoded[] =
 
 /* overwriteable ini defaults must be set in phpdbg_ini_defaults() */
 #define INI_DEFAULT(name, value) \
-        Z_SET_REFCOUNT(tmp, 0); \
         ZVAL_STRINGL(&tmp, value, sizeof(value) - 1); \
         zend_hash_str_update(configuration_hash, name, sizeof(name) - 1, &tmp);
 
index 965e9bc2e24612a09e9fa91b95db8719e10deaf7..2c2d9e61779c049b720139216cbe5bed1352df08 100644 (file)
@@ -40,9 +40,9 @@ void phpdbg_restore_frame(TSRMLS_D) /* {{{ */
        EG(opline_ptr) = &PHPDBG_EX(opline);
        EG(active_op_array) = PHPDBG_EX(op_array);
        EG(active_symbol_table) = PHPDBG_EX(symbol_table);
-       Z_OBJ(EG(This)) = PHPDBG_EX(current_this);
-       EG(scope) = PHPDBG_EX(current_scope);
-       EG(called_scope) = PHPDBG_EX(current_called_scope);
+       Z_OBJ(EG(This)) = PHPDBG_EX(object);
+       EG(scope) = PHPDBG_EX(scope);
+       EG(called_scope) = PHPDBG_EX(called_scope);
 } /* }}} */
 
 void phpdbg_switch_frame(int frame TSRMLS_DC) /* {{{ */
@@ -82,9 +82,9 @@ void phpdbg_switch_frame(int frame TSRMLS_DC) /* {{{ */
                EG(opline_ptr) = &PHPDBG_EX(opline);
                EG(active_op_array) = PHPDBG_EX(op_array);
                EG(active_symbol_table) = PHPDBG_EX(symbol_table);
-               Z_OBJ(EG(This)) = PHPDBG_EX(current_this);
-               EG(scope) = PHPDBG_EX(current_scope);
-               EG(called_scope) = PHPDBG_EX(current_called_scope);
+               Z_OBJ(EG(This)) = PHPDBG_EX(object);
+               EG(scope) = PHPDBG_EX(scope);
+               EG(called_scope) = PHPDBG_EX(called_scope);
        }
 
        phpdbg_notice("Switched to frame #%d", frame);