Browse Source

Reduced overhead of magic method calls (__get/__set/__unset/__isset/__dectructor/__clone).

pull/3303/merge
Dmitry Stogov 8 years ago
parent
commit
34e58a6447
  1. 76
      Zend/zend_object_handlers.c
  2. 53
      Zend/zend_objects.c

76
Zend/zend_object_handlers.c

@ -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;
}

53
Zend/zend_objects.c

@ -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);
}
}

Loading…
Cancel
Save