]> granicus.if.org Git - php/commitdiff
Don't propogate "fake" EX(called_scope) and EX(This) into each internal function.
authorDmitry Stogov <dmitry@zend.com>
Thu, 23 Apr 2015 09:16:37 +0000 (12:16 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 23 Apr 2015 09:16:37 +0000 (12:16 +0300)
They need quite seldom and it's cheaper to get them from corresponfing upper stack frame.

Zend/zend_API.c
Zend/zend_builtin_functions.c
Zend/zend_constants.c
Zend/zend_execute.h
Zend/zend_execute_API.c
Zend/zend_interfaces.c
Zend/zend_object_handlers.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_execute.skl
ext/standard/basic_functions.c

index dc517138073dd54225268761c56fb03288b3c38c..f028756a937585ff27d7bbe20ab0697db10898af 100644 (file)
@@ -2864,10 +2864,10 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
                if (!EG(scope)) {
                        if (error) *error = estrdup("cannot access self:: when no class scope is active");
                } else {
-                       fcc->called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL;
+                       fcc->called_scope = zend_get_called_scope(EG(current_execute_data));
                        fcc->calling_scope = EG(scope);
-                       if (!fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This)) {
-                               fcc->object = Z_OBJ(EG(current_execute_data)->This);
+                       if (!fcc->object) {
+                               fcc->object = zend_get_this_object(EG(current_execute_data));
                        }
                        ret = 1;
                }
@@ -2877,22 +2877,24 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
                } else if (!EG(scope)->parent) {
                        if (error) *error = estrdup("cannot access parent:: when current class scope has no parent");
                } else {
-                       fcc->called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL;
+                       fcc->called_scope = zend_get_called_scope(EG(current_execute_data));
                        fcc->calling_scope = EG(scope)->parent;
-                       if (!fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This)) {
-                               fcc->object = Z_OBJ(EG(current_execute_data)->This);
+                       if (!fcc->object) {
+                               fcc->object = zend_get_this_object(EG(current_execute_data));
                        }
                        *strict_class = 1;
                        ret = 1;
                }
        } else if (zend_string_equals_literal(lcname, "static")) {
-               if (!EG(current_execute_data) || !EG(current_execute_data)->called_scope) {
+               zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));
+
+               if (!called_scope) {
                        if (error) *error = estrdup("cannot access static:: when no class scope is active");
                } else {
-                       fcc->called_scope = EG(current_execute_data)->called_scope;
-                       fcc->calling_scope = EG(current_execute_data)->called_scope;
-                       if (!fcc->object && Z_OBJ(EG(current_execute_data)->This)) {
-                               fcc->object = Z_OBJ(EG(current_execute_data)->This);
+                       fcc->called_scope = called_scope;
+                       fcc->calling_scope = called_scope;
+                       if (!fcc->object) {
+                               fcc->object = zend_get_this_object(EG(current_execute_data));
                        }
                        *strict_class = 1;
                        ret = 1;
@@ -2906,11 +2908,17 @@ static int zend_is_callable_check_class(zend_string *name, zend_fcall_info_cache
                }
                scope = ex ? ex->func->common.scope : NULL;
                fcc->calling_scope = ce;
-               if (scope && !fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This) &&
-                   instanceof_function(Z_OBJCE(EG(current_execute_data)->This), scope) &&
-                   instanceof_function(scope, fcc->calling_scope)) {
-                       fcc->object = Z_OBJ(EG(current_execute_data)->This);
-                       fcc->called_scope = Z_OBJCE(EG(current_execute_data)->This);
+               if (scope && !fcc->object) {
+                       zend_object *object = zend_get_this_object(EG(current_execute_data));
+
+                       if (object &&
+                           instanceof_function(object->ce, scope) &&
+                           instanceof_function(scope, fcc->calling_scope)) {
+                               fcc->object = object;
+                               fcc->called_scope = object->ce;
+                       } else {
+                               fcc->called_scope = fcc->calling_scope;
+                       }
                } else {
                        fcc->called_scope = fcc->object ? fcc->object->ce : fcc->calling_scope;
                }
@@ -3101,9 +3109,12 @@ get_function_via_handler:
                        if (fcc->function_handler) {
                                retval = 1;
                                call_via_handler = (fcc->function_handler->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE) != 0;
-                               if (call_via_handler && !fcc->object && EG(current_execute_data) && Z_OBJ(EG(current_execute_data)->This) &&
-                                   instanceof_function(Z_OBJCE(EG(current_execute_data)->This), fcc->calling_scope)) {
-                                       fcc->object = Z_OBJ(EG(current_execute_data)->This);
+                               if (call_via_handler && !fcc->object) {
+                                       zend_object *object = zend_get_this_object(EG(current_execute_data));
+                                       if (object &&
+                                           instanceof_function(object->ce, fcc->calling_scope)) {
+                                               fcc->object = object;
+                                       }
                                }
                        }
                }
index 996c11b24d80a4f764152af5badd0698c2c23ba1..7313b3206584461cc7a7d0b8c9e94842a8615c00 100644 (file)
@@ -916,12 +916,15 @@ ZEND_FUNCTION(get_class)
    Retrieves the "Late Static Binding" class name */
 ZEND_FUNCTION(get_called_class)
 {
+       zend_class_entry *called_scope;
+
        if (zend_parse_parameters_none() == FAILURE) {
                return;
        }
 
-       if (EX(called_scope)) {
-               RETURN_STR_COPY(EX(called_scope)->name);
+       called_scope = zend_get_called_scope(execute_data);
+       if (called_scope) {
+               RETURN_STR_COPY(called_scope->name);
        } else if (!EG(scope))  {
                zend_error(E_WARNING, "get_called_class() called from outside a class");
        }
@@ -2304,12 +2307,6 @@ ZEND_FUNCTION(debug_print_backtrace)
 
                /* $this may be passed into regular internal functions */
                object = Z_OBJ(call->This);
-               if (object &&
-                       call &&
-                   call->func->type == ZEND_INTERNAL_FUNCTION &&
-                   !call->func->common.scope) {
-                       object = NULL;
-               }
 
                if (call->func) {
                        func = call->func;
@@ -2527,12 +2524,6 @@ ZEND_API void zend_fetch_debug_backtrace(zval *return_value, int skip_last, int
 
                /* $this may be passed into regular internal functions */
                object = call ? Z_OBJ(call->This) : NULL;
-               if (object &&
-                   call->func &&
-                   call->func->type == ZEND_INTERNAL_FUNCTION &&
-                   !call->func->common.scope) {
-                       object = NULL;
-               }
 
                if (call && call->func) {
                        func = call->func;
index 32f249ce08685dd371411fd2b11182df599aeb36..f8205fac0d657079db03edae51273bf46425fcc6 100644 (file)
@@ -349,12 +349,11 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope,
                        }
                } else if (class_name_len == sizeof("static")-1 &&
                           !memcmp(lcname, "static", sizeof("static")-1)) {
-                       if (UNEXPECTED(!EG(current_execute_data)) ||
-                           UNEXPECTED(!EG(current_execute_data)->called_scope)) {
+                       ce = zend_get_called_scope(EG(current_execute_data));
+                       if (UNEXPECTED(!ce)) {
                                zend_error(E_EXCEPTION | E_ERROR, "Cannot access static:: when no class scope is active");
                                return NULL;
                        }
-                       ce = EG(current_execute_data)->called_scope;
                } else {
                        ce = zend_fetch_class(class_name, flags);
                }
index 67958cf32c97dfadea2a0a9f826fb8d1acc35d0a..9e8dde5c3c505a1aff32bf21f53039ec1108e83a 100644 (file)
@@ -42,6 +42,8 @@ ZEND_API void execute_ex(zend_execute_data *execute_data);
 ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_value);
 ZEND_API zend_class_entry *zend_lookup_class(zend_string *name);
 ZEND_API zend_class_entry *zend_lookup_class_ex(zend_string *name, const zval *key, int use_autoload);
+ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex);
+ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex);
 ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name);
 ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char *string_name);
 ZEND_API int zend_eval_string_ex(char *str, zval *retval_ptr, char *string_name, int handle_exceptions);
index 37a27150e5a1619da2d5e8423d4f600eda7f9ac8..61ee1e103eb6eaa3f88cad438e7781473098367a 100644 (file)
@@ -1055,6 +1055,38 @@ ZEND_API zend_class_entry *zend_lookup_class(zend_string *name) /* {{{ */
 }
 /* }}} */
 
+ZEND_API zend_class_entry *zend_get_called_scope(zend_execute_data *ex) /* {{{ */
+{
+       while (ex) {
+               if (ex->called_scope) {
+                       return ex->called_scope;
+               } else if (ex->func) {
+                       if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
+                               return ex->called_scope;
+                       }
+               }
+               ex = ex->prev_execute_data;
+       }
+       return NULL;
+}
+/* }}} */
+
+ZEND_API zend_object *zend_get_this_object(zend_execute_data *ex) /* {{{ */
+{
+       while (ex) {
+               if (Z_OBJ(ex->This)) {
+                       return Z_OBJ(ex->This);
+               } else if (ex->func) {
+                       if (ex->func->type != ZEND_INTERNAL_FUNCTION || ex->func->common.scope) {
+                               return Z_OBJ(ex->This);
+                       }
+               }
+               ex = ex->prev_execute_data;
+       }
+       return NULL;
+}
+/* }}} */
+
 ZEND_API int zend_eval_stringl(char *str, size_t str_len, zval *retval_ptr, char *string_name) /* {{{ */
 {
        zval pv;
@@ -1311,13 +1343,14 @@ check_fetch_type:
                        }
                        return EG(scope)->parent;
                case ZEND_FETCH_CLASS_STATIC:
-                       if (UNEXPECTED(!EG(current_execute_data)) || UNEXPECTED(!EG(current_execute_data)->called_scope)) {
+                       ce = zend_get_called_scope(EG(current_execute_data));
+                       if (UNEXPECTED(!ce)) {
                                int error_type = (fetch_type & ZEND_FETCH_CLASS_EXCEPTION) ?
                                                (E_EXCEPTION | E_ERROR) : E_ERROR;
                                zend_error(error_type, "Cannot access static:: when no class scope is active");
                                return NULL;
                        }
-                       return EG(current_execute_data)->called_scope;
+                       return ce;
                case ZEND_FETCH_CLASS_AUTO: {
                                fetch_sub_type = zend_get_class_fetch_type(class_name);
                                if (UNEXPECTED(fetch_sub_type != ZEND_FETCH_CLASS_DEFAULT)) {
index 5cb7024706edb9766d64e143004ad9303516e0ab..54f8f8c1172457e8f0249b4bc9f929c77b6c8913 100644 (file)
@@ -89,13 +89,16 @@ ZEND_API zval* zend_call_method(zval *object, zend_class_entry *obj_ce, zend_fun
                fcic.calling_scope = obj_ce;
                if (object) {
                        fcic.called_scope = Z_OBJCE_P(object);
-               } else if (obj_ce &&
-                          !(EG(current_execute_data) &&
-                            EG(current_execute_data)->called_scope &&
-                            instanceof_function(EG(current_execute_data)->called_scope, obj_ce))) {
-                       fcic.called_scope = obj_ce;
                } else {
-                       fcic.called_scope = EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL;
+                       zend_class_entry *called_scope = zend_get_called_scope(EG(current_execute_data));
+
+                       if (obj_ce &&
+                           (!called_scope ||
+                            !instanceof_function(called_scope, obj_ce))) {
+                               fcic.called_scope = obj_ce;
+                       } else {
+                               fcic.called_scope = called_scope;
+                       }
                }
                fcic.object = object ? Z_OBJ_P(object) : NULL;
                result = zend_call_function(&fci, &fcic);
index a14f60080b2751b5442296c5ae4554731fe77bb9..52c3b4ce1c9bc43b69b8088dcbc77f00ddbe2357 100644 (file)
@@ -1137,6 +1137,7 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
        zend_function *fbc = NULL;
        char *lc_class_name;
        zend_string *lc_function_name;
+       zend_object *object;
 
        if (EXPECTED(key != NULL)) {
                lc_function_name = Z_STR_P(key);
@@ -1164,12 +1165,12 @@ ZEND_API zend_function *zend_std_get_static_method(zend_class_entry *ce, zend_st
                                zend_string_release(lc_function_name);
                        }
                        if (ce->__call &&
-                           Z_OBJ(EG(current_execute_data)->This) &&
-                           instanceof_function(Z_OBJCE(EG(current_execute_data)->This), ce)) {
+                               (object = zend_get_this_object(EG(current_execute_data))) != NULL &&
+                           instanceof_function(object->ce, ce)) {
                                /* Call the top-level defined __call().
                                 * see: tests/classes/__call_004.phpt  */
 
-                               zend_class_entry *call_ce = Z_OBJCE(EG(current_execute_data)->This);
+                               zend_class_entry *call_ce = object->ce;
 
                                while (!call_ce->__call) {
                                        call_ce = call_ce->parent;
index 9a50c9b7d538400396ac3f09ca250418104d6860..899b18a89db07fd010437edd49de3de81843ac22 100644 (file)
@@ -3391,9 +3391,6 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY)
        SAVE_OPLINE();
        EX(call) = call->prev_execute_data;
 
-       call->called_scope = EX(called_scope);
-       Z_OBJ(call->This) = Z_OBJ(EX(This));
-
        call->prev_execute_data = execute_data;
        EG(current_execute_data) = call;
 
@@ -3505,9 +3502,6 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY)
                        }
                }
 
-               call->called_scope = EX(called_scope);
-               Z_OBJ(call->This) = Z_OBJ(EX(This));
-
                call->prev_execute_data = execute_data;
                EG(current_execute_data) = call;
 
@@ -3627,9 +3621,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY)
                if (fbc->common.scope) {
                        should_change_scope = 1;
                        EG(scope) = fbc->common.scope;
-               } else {
-                       call->called_scope = EX(called_scope);
-                       Z_OBJ(call->This) = Z_OBJ(EX(This));
                }
 
                call->prev_execute_data = execute_data;
index 9f224ee0ddc60013aed07f535daa1ad0f1a43d5b..3a2ed291eb95e80c2e7bc74f5737165ef1e5ba31 100644 (file)
@@ -423,7 +423,7 @@ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value)
        }
 
        execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE,
-               (zend_function*)op_array, 0, EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL, EG(current_execute_data) ? Z_OBJ(EG(current_execute_data)->This) : NULL);
+               (zend_function*)op_array, 0, zend_get_called_scope(EG(current_execute_data)), zend_get_this_object(EG(current_execute_data)));
        if (EG(current_execute_data)) {
                execute_data->symbol_table = zend_rebuild_symbol_table();
        } else {
@@ -548,9 +548,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_HANDLER(ZEND_OPC
        SAVE_OPLINE();
        EX(call) = call->prev_execute_data;
 
-       call->called_scope = EX(called_scope);
-       Z_OBJ(call->This) = Z_OBJ(EX(This));
-
        call->prev_execute_data = execute_data;
        EG(current_execute_data) = call;
 
@@ -662,9 +659,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(
                        }
                }
 
-               call->called_scope = EX(called_scope);
-               Z_OBJ(call->This) = Z_OBJ(EX(This));
-
                call->prev_execute_data = execute_data;
                EG(current_execute_data) = call;
 
@@ -784,9 +778,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC
                if (fbc->common.scope) {
                        should_change_scope = 1;
                        EG(scope) = fbc->common.scope;
-               } else {
-                       call->called_scope = EX(called_scope);
-                       Z_OBJ(call->This) = Z_OBJ(EX(This));
                }
 
                call->prev_execute_data = execute_data;
index 5bbc390f5b33c8de6174be368b83316fbe7fd5a6..02fe6bdc36081f3ec383214136c7330d7b522c0f 100644 (file)
@@ -29,7 +29,7 @@ ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value
        }
 
        execute_data = zend_vm_stack_push_call_frame(ZEND_CALL_TOP_CODE,
-               (zend_function*)op_array, 0, EG(current_execute_data) ? EG(current_execute_data)->called_scope : NULL, EG(current_execute_data) ? Z_OBJ(EG(current_execute_data)->This) : NULL);
+               (zend_function*)op_array, 0, zend_get_called_scope(EG(current_execute_data)), zend_get_this_object(EG(current_execute_data)));
        if (EG(current_execute_data)) {
                execute_data->symbol_table = zend_rebuild_symbol_table();
        } else {
index ebeca422df3d98ea6b5f1e3fd9fb7603fa499947..693ac4c8e39f61346425a48c05a6be5fd46b459f 100644 (file)
@@ -4800,6 +4800,7 @@ PHP_FUNCTION(forward_static_call)
        zval retval;
        zend_fcall_info fci;
        zend_fcall_info_cache fci_cache;
+       zend_class_entry *called_scope;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "f*", &fci, &fci_cache, &fci.params, &fci.param_count) == FAILURE) {
                return;
@@ -4811,9 +4812,10 @@ PHP_FUNCTION(forward_static_call)
 
        fci.retval = &retval;
 
-       if (EX(called_scope) &&
-               instanceof_function(EX(called_scope), fci_cache.calling_scope)) {
-                       fci_cache.called_scope = EX(called_scope);
+       called_scope = zend_get_called_scope(execute_data);
+       if (called_scope &&
+               instanceof_function(called_scope, fci_cache.calling_scope)) {
+                       fci_cache.called_scope = called_scope;
        }
 
        if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {
@@ -4829,6 +4831,7 @@ PHP_FUNCTION(forward_static_call_array)
        zval *params, retval;
        zend_fcall_info fci;
        zend_fcall_info_cache fci_cache;
+       zend_class_entry *called_scope;
 
        if (zend_parse_parameters(ZEND_NUM_ARGS(), "fa/", &fci, &fci_cache, &params) == FAILURE) {
                return;
@@ -4837,9 +4840,10 @@ PHP_FUNCTION(forward_static_call_array)
        zend_fcall_info_args(&fci, params);
        fci.retval = &retval;
 
-       if (EX(called_scope) &&
-               instanceof_function(EX(called_scope), fci_cache.calling_scope)) {
-                       fci_cache.called_scope = EX(called_scope);
+       called_scope = zend_get_called_scope(execute_data);
+       if (called_scope &&
+               instanceof_function(called_scope, fci_cache.calling_scope)) {
+                       fci_cache.called_scope = called_scope;
        }
 
        if (zend_call_function(&fci, &fci_cache) == SUCCESS && Z_TYPE(retval) != IS_UNDEF) {