]> granicus.if.org Git - php/commitdiff
Reduced overhead of magic method calls (__get/__set/__unset/__isset/__dectructor...
authorDmitry Stogov <dmitry@zend.com>
Fri, 22 Jun 2018 11:29:54 +0000 (14:29 +0300)
committerDmitry Stogov <dmitry@zend.com>
Fri, 22 Jun 2018 11:29:54 +0000 (14:29 +0300)
Zend/zend_object_handlers.c
Zend/zend_objects.c

index 5a4c0c075e48e322da336a24f3b46746adcbaf03..1148944a18969e54015e9137501cfa73d5361ced 100644 (file)
@@ -179,6 +179,8 @@ static void zend_std_call_getter(zval *object, zval *member, zval *retval) /* {{
 {
        zend_class_entry *ce = Z_OBJCE_P(object);
        zend_class_entry *orig_fake_scope = EG(fake_scope);
+       zend_fcall_info fci;
+       zend_fcall_info_cache fcic;
 
        EG(fake_scope) = NULL;
 
@@ -187,7 +189,20 @@ static void zend_std_call_getter(zval *object, zval *member, zval *retval) /* {{
 
           it should return whether the call was successful or not
        */
-       zend_call_method_with_1_params(object, ce, &ce->__get, ZEND_GET_FUNC_NAME, retval, member);
+
+       fci.size = sizeof(fci);
+       fci.object = Z_OBJ_P(object);
+       fci.retval = retval;
+       fci.param_count = 1;
+       fci.params = member;
+       fci.no_separation = 1;
+       ZVAL_UNDEF(&fci.function_name); /* Unused */
+
+       fcic.function_handler = ce->__get;
+       fcic.called_scope = ce;
+       fcic.object = Z_OBJ_P(object);
+
+       zend_call_function(&fci, &fcic);
 
        EG(fake_scope) = orig_fake_scope;
 }
@@ -197,6 +212,9 @@ static void zend_std_call_setter(zval *object, zval *member, zval *value) /* {{{
 {
        zend_class_entry *ce = Z_OBJCE_P(object);
        zend_class_entry *orig_fake_scope = EG(fake_scope);
+       zend_fcall_info fci;
+       zend_fcall_info_cache fcic;
+       zval args[2], ret;
 
        EG(fake_scope) = NULL;
 
@@ -204,7 +222,25 @@ static void zend_std_call_setter(zval *object, zval *member, zval *value) /* {{{
             property name
             value to be set
        */
-       zend_call_method_with_2_params(object, ce, &ce->__set, ZEND_SET_FUNC_NAME, NULL, member, value);
+
+       ZVAL_COPY_VALUE(&args[0], member);
+       ZVAL_COPY_VALUE(&args[1], value);
+       ZVAL_UNDEF(&ret);
+
+       fci.size = sizeof(fci);
+       fci.object = Z_OBJ_P(object);
+       fci.retval = &ret;
+       fci.param_count = 2;
+       fci.params = args;
+       fci.no_separation = 1;
+       ZVAL_UNDEF(&fci.function_name); /* Unused */
+
+       fcic.function_handler = ce->__set;
+       fcic.called_scope = ce;
+       fcic.object = Z_OBJ_P(object);
+
+       zend_call_function(&fci, &fcic);
+       zval_ptr_dtor(&ret);
 
        EG(fake_scope) = orig_fake_scope;
 }
@@ -214,6 +250,9 @@ static void zend_std_call_unsetter(zval *object, zval *member) /* {{{ */
 {
        zend_class_entry *ce = Z_OBJCE_P(object);
        zend_class_entry *orig_fake_scope = EG(fake_scope);
+       zend_fcall_info fci;
+       zend_fcall_info_cache fcic;
+       zval ret;
 
        EG(fake_scope) = NULL;
 
@@ -221,7 +260,22 @@ static void zend_std_call_unsetter(zval *object, zval *member) /* {{{ */
              property name
        */
 
-       zend_call_method_with_1_params(object, ce, &ce->__unset, ZEND_UNSET_FUNC_NAME, NULL, member);
+       ZVAL_UNDEF(&ret);
+
+       fci.size = sizeof(fci);
+       fci.object = Z_OBJ_P(object);
+       fci.retval = &ret;
+       fci.param_count = 1;
+       fci.params = member;
+       fci.no_separation = 1;
+       ZVAL_UNDEF(&fci.function_name); /* Unused */
+
+       fcic.function_handler = ce->__unset;
+       fcic.called_scope = ce;
+       fcic.object = Z_OBJ_P(object);
+
+       zend_call_function(&fci, &fcic);
+       zval_ptr_dtor(&ret);
 
        EG(fake_scope) = orig_fake_scope;
 }
@@ -231,6 +285,8 @@ static void zend_std_call_issetter(zval *object, zval *member, zval *retval) /*
 {
        zend_class_entry *ce = Z_OBJCE_P(object);
        zend_class_entry *orig_fake_scope = EG(fake_scope);
+       zend_fcall_info fci;
+       zend_fcall_info_cache fcic;
 
        EG(fake_scope) = NULL;
 
@@ -240,7 +296,19 @@ static void zend_std_call_issetter(zval *object, zval *member, zval *retval) /*
           it should return whether the property is set or not
        */
 
-       zend_call_method_with_1_params(object, ce, &ce->__isset, ZEND_ISSET_FUNC_NAME, retval, member);
+       fci.size = sizeof(fci);
+       fci.object = Z_OBJ_P(object);
+       fci.retval = retval;
+       fci.param_count = 1;
+       fci.params = member;
+       fci.no_separation = 1;
+       ZVAL_UNDEF(&fci.function_name); /* Unused */
+
+       fcic.function_handler = ce->__isset;
+       fcic.called_scope = ce;
+       fcic.object = Z_OBJ_P(object);
+
+       zend_call_function(&fci, &fcic);
 
        EG(fake_scope) = orig_fake_scope;
 }
index 00d124ff24789440b46ab64769930eba43f2a6fa..496b46f5f82faa1964706ae73079c71651b0d107 100644 (file)
@@ -78,8 +78,10 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)
 
        if (destructor) {
                zend_object *old_exception;
-               zval obj;
                zend_class_entry *orig_fake_scope;
+               zend_fcall_info fci;
+               zend_fcall_info_cache fcic;
+               zval ret;
 
                if (destructor->op_array.fn_flags & (ZEND_ACC_PRIVATE|ZEND_ACC_PROTECTED)) {
                        if (destructor->op_array.fn_flags & ZEND_ACC_PRIVATE) {
@@ -124,7 +126,6 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)
                }
 
                GC_ADDREF(object);
-               ZVAL_OBJ(&obj, object);
 
                /* Make sure that destructors are protected from previously thrown exceptions.
                 * For example, if an exception was thrown in a function and when the function's
@@ -141,7 +142,24 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)
                }
                orig_fake_scope = EG(fake_scope);
                EG(fake_scope) = NULL;
-               zend_call_method_with_0_params(&obj, object->ce, &destructor, ZEND_DESTRUCTOR_FUNC_NAME, NULL);
+
+               ZVAL_UNDEF(&ret);
+
+               fci.size = sizeof(fci);
+               fci.object = object;
+               fci.retval = &ret;
+               fci.param_count = 0;
+               fci.params = NULL;
+               fci.no_separation = 1;
+               ZVAL_UNDEF(&fci.function_name); /* Unused */
+
+               fcic.function_handler = destructor;
+               fcic.called_scope = object->ce;
+               fcic.object = object;
+
+               zend_call_function(&fci, &fcic);
+               zval_ptr_dtor(&ret);
+
                if (old_exception) {
                        if (EG(exception)) {
                                zend_exception_set_previous(EG(exception), old_exception);
@@ -149,7 +167,7 @@ ZEND_API void zend_objects_destroy_object(zend_object *object)
                                EG(exception) = old_exception;
                        }
                }
-               zval_ptr_dtor(&obj);
+               OBJ_RELEASE(object);
                EG(fake_scope) = orig_fake_scope;
        }
 }
@@ -220,12 +238,29 @@ ZEND_API void ZEND_FASTCALL zend_objects_clone_members(zend_object *new_object,
        }
 
        if (old_object->ce->clone) {
-               zval new_obj;
+               zend_fcall_info fci;
+               zend_fcall_info_cache fcic;
+               zval ret;
+
+               GC_ADDREF(new_object);
+
+               ZVAL_UNDEF(&ret);
+
+               fci.size = sizeof(fci);
+               fci.object = new_object;
+               fci.retval = &ret;
+               fci.param_count = 0;
+               fci.params = NULL;
+               fci.no_separation = 1;
+               ZVAL_UNDEF(&fci.function_name); /* Unused */
+
+               fcic.function_handler = new_object->ce->clone;
+               fcic.called_scope = new_object->ce;
+               fcic.object = new_object;
 
-               ZVAL_OBJ(&new_obj, new_object);
-               Z_ADDREF(new_obj);
-               zend_call_method_with_0_params(&new_obj, old_object->ce, &old_object->ce->clone, ZEND_CLONE_FUNC_NAME, NULL);
-               zval_ptr_dtor(&new_obj);
+               zend_call_function(&fci, &fcic);
+               zval_ptr_dtor(&ret);
+               OBJ_RELEASE(new_object);
        }
 }