From af47c546383bab8cf1b3665b12b49dd9f2f9268f Mon Sep 17 00:00:00 2001 From: Vladimir Kolesnikov Date: Sun, 4 Aug 2013 19:51:10 +0300 Subject: [PATCH 1/3] Phalcon\Di optimizations --- ext/di.c | 286 +++++++++++++++++++++++++------------------------------ 1 file changed, 131 insertions(+), 155 deletions(-) diff --git a/ext/di.c b/ext/di.c index 891b5e1cf97..64547733691 100644 --- a/ext/di.c +++ b/ext/di.c @@ -121,29 +121,28 @@ PHP_METHOD(Phalcon_DI, __construct){ */ PHP_METHOD(Phalcon_DI, set){ - zval *name, *definition, *shared = NULL, *service; + zval *name, *definition, *shared = NULL; - PHALCON_MM_GROW(); - - phalcon_fetch_params(1, 2, 1, &name, &definition, &shared); - - if (!shared) { - PHALCON_INIT_VAR(shared); - ZVAL_BOOL(shared, 0); - } + phalcon_fetch_params(0, 2, 1, &name, &definition, &shared); if (Z_TYPE_P(name) != IS_STRING) { - PHALCON_THROW_EXCEPTION_STR(phalcon_di_exception_ce, "The service name must be a string"); + PHALCON_THROW_EXCEPTION_STRW(phalcon_di_exception_ce, "The service name must be a string"); return; } - PHALCON_INIT_VAR(service); - object_init_ex(service, phalcon_di_service_ce); - phalcon_call_method_p3_noret(service, "__construct", name, definition, shared); + PHALCON_MM_GROW(); + + if (!shared) { + PHALCON_INIT_VAR(shared); + ZVAL_FALSE(shared); + } + + object_init_ex(return_value, phalcon_di_service_ce); + phalcon_call_method_p3_noret(return_value, "__construct", name, definition, shared); - phalcon_update_property_array(this_ptr, SL("_services"), name, service TSRMLS_CC); + phalcon_update_property_array(this_ptr, SL("_services"), name, return_value TSRMLS_CC); - RETURN_CTOR(service); + PHALCON_MM_RESTORE(); } /** @@ -155,27 +154,26 @@ PHP_METHOD(Phalcon_DI, set){ */ PHP_METHOD(Phalcon_DI, setShared){ - zval *name, *definition, *shared, *service; - - PHALCON_MM_GROW(); + zval *name, *definition, *shared; - phalcon_fetch_params(1, 2, 0, &name, &definition); + phalcon_fetch_params(0, 2, 0, &name, &definition); if (Z_TYPE_P(name) != IS_STRING) { - PHALCON_THROW_EXCEPTION_STR(phalcon_di_exception_ce, "The service name must be a string"); + PHALCON_THROW_EXCEPTION_STRW(phalcon_di_exception_ce, "The service name must be a string"); return; } + PHALCON_MM_GROW(); + PHALCON_INIT_VAR(shared); - ZVAL_BOOL(shared, 1); + ZVAL_TRUE(shared); - PHALCON_INIT_VAR(service); - object_init_ex(service, phalcon_di_service_ce); - phalcon_call_method_p3_noret(service, "__construct", name, definition, shared); + object_init_ex(return_value, phalcon_di_service_ce); + phalcon_call_method_p3_noret(return_value, "__construct", name, definition, shared); - phalcon_update_property_array(this_ptr, SL("_services"), name, service TSRMLS_CC); + phalcon_update_property_array(this_ptr, SL("_services"), name, return_value TSRMLS_CC); - RETURN_CTOR(service); + PHALCON_MM_RESTORE(); } /** @@ -209,34 +207,31 @@ PHP_METHOD(Phalcon_DI, remove){ */ PHP_METHOD(Phalcon_DI, attempt){ - zval *name, *definition, *shared = NULL, *services, *service; + zval *name, *definition, *shared = NULL; + zval **services; - PHALCON_MM_GROW(); - - phalcon_fetch_params(1, 2, 1, &name, &definition, &shared); - - if (!shared) { - PHALCON_INIT_VAR(shared); - ZVAL_BOOL(shared, 0); - } + phalcon_fetch_params(0, 2, 1, &name, &definition, &shared); if (Z_TYPE_P(name) != IS_STRING) { - PHALCON_THROW_EXCEPTION_STR(phalcon_di_exception_ce, "The service name must be a string"); + PHALCON_THROW_EXCEPTION_STRW(phalcon_di_exception_ce, "The service name must be a string"); return; } - PHALCON_OBS_VAR(services); - phalcon_read_property_this(&services, this_ptr, SL("_services"), PH_NOISY_CC); - if (!phalcon_array_isset(services, name)) { - PHALCON_INIT_VAR(service); - object_init_ex(service, phalcon_di_service_ce); - phalcon_call_method_p3_noret(service, "__construct", name, definition, shared); + services = phalcon_fetch_nproperty_this(this_ptr, SL("_services"), PH_NOISY_CC); + if (!phalcon_array_isset(*services, name)) { + PHALCON_MM_GROW(); + + if (!shared) { + PHALCON_INIT_VAR(shared); + ZVAL_FALSE(shared); + } + + object_init_ex(return_value, phalcon_di_service_ce); + phalcon_call_method_p3_noret(return_value, "__construct", name, definition, shared); - phalcon_update_property_array(this_ptr, SL("_services"), name, service TSRMLS_CC); - RETURN_CTOR(service); + phalcon_update_property_array(this_ptr, SL("_services"), name, return_value TSRMLS_CC); + PHALCON_MM_RESTORE(); } - - RETURN_MM_NULL(); } /** @@ -274,23 +269,21 @@ PHP_METHOD(Phalcon_DI, setRaw){ */ PHP_METHOD(Phalcon_DI, getRaw){ - zval *name, *services, *service, *exception_message; + zval *name, *exception_message; + zval **services, **service; - PHALCON_MM_GROW(); + phalcon_fetch_params(0, 1, 0, &name); - phalcon_fetch_params(1, 1, 0, &name); - if (Z_TYPE_P(name) != IS_STRING) { - PHALCON_THROW_EXCEPTION_STR(phalcon_di_exception_ce, "The service name must be a string"); + PHALCON_THROW_EXCEPTION_STRW(phalcon_di_exception_ce, "The service name must be a string"); return; } - - PHALCON_OBS_VAR(services); - phalcon_read_property_this(&services, this_ptr, SL("_services"), PH_NOISY_CC); - if (phalcon_array_isset(services, name)) { - PHALCON_OBS_VAR(service); - phalcon_array_fetch(&service, services, name, PH_NOISY); - phalcon_call_method(return_value, service, "getdefinition"); + + PHALCON_MM_GROW(); + + services = phalcon_fetch_nproperty_this(this_ptr, SL("_services"), PH_NOISY_CC); + if (phalcon_array_isset_fetch(&service, *services, name)) { + phalcon_call_method(return_value, *service, "getdefinition"); RETURN_MM(); } @@ -308,25 +301,22 @@ PHP_METHOD(Phalcon_DI, getRaw){ */ PHP_METHOD(Phalcon_DI, getService){ - zval *name, *services, *service, *exception_message; + zval *name, *exception_message; + zval **services, **service; - PHALCON_MM_GROW(); - - phalcon_fetch_params(1, 1, 0, &name); + phalcon_fetch_params(0, 1, 0, &name); if (Z_TYPE_P(name) != IS_STRING) { - PHALCON_THROW_EXCEPTION_STR(phalcon_di_exception_ce, "The service name must be a string"); + PHALCON_THROW_EXCEPTION_STRW(phalcon_di_exception_ce, "The service name must be a string"); return; } - PHALCON_OBS_VAR(services); - phalcon_read_property_this(&services, this_ptr, SL("_services"), PH_NOISY_CC); - if (phalcon_array_isset(services, name)) { - PHALCON_OBS_VAR(service); - phalcon_array_fetch(&service, services, name, PH_NOISY); - RETURN_CCTOR(service); + services = phalcon_fetch_nproperty_this(this_ptr, SL("_services"), PH_NOISY_CC); + if (phalcon_array_isset_fetch(&service, *services, name)) { + RETURN_CTORW(*service); } + PHALCON_MM_GROW(); PHALCON_INIT_VAR(exception_message); PHALCON_CONCAT_SVS(exception_message, "Service '", name, "' wasn't found in the dependency injection container"); PHALCON_THROW_EXCEPTION_ZVAL(phalcon_di_exception_ce, exception_message); @@ -342,16 +332,11 @@ PHP_METHOD(Phalcon_DI, getService){ */ PHP_METHOD(Phalcon_DI, get){ - zval *name, *parameters = NULL, *services, *service, *instance = NULL; + zval *name, *parameters = NULL, *instance; zval *exception_message; + zval **services, **service; - PHALCON_MM_GROW(); - - phalcon_fetch_params(1, 1, 1, &name, ¶meters); - - if (!parameters) { - PHALCON_INIT_VAR(parameters); - } + phalcon_fetch_params(0, 1, 1, &name, ¶meters); /** * A valid service alias is a string @@ -361,31 +346,34 @@ PHP_METHOD(Phalcon_DI, get){ return; } - PHALCON_OBS_VAR(services); - phalcon_read_property_this(&services, this_ptr, SL("_services"), PH_NOISY_CC); - if (phalcon_array_isset(services, name)) { + PHALCON_MM_GROW(); + + if (!parameters) { + PHALCON_INIT_VAR(parameters); + } + + PHALCON_INIT_VAR(instance); + + services = phalcon_fetch_nproperty_this(this_ptr, SL("_services"), PH_NOISY_CC); + if (phalcon_array_isset_fetch(&service, *services, name)) { /** * The service is registered in the DI */ - PHALCON_OBS_VAR(service); - phalcon_array_fetch(&service, services, name, PH_NOISY); - - PHALCON_INIT_VAR(instance); - phalcon_call_method_p2(instance, service, "resolve", parameters, this_ptr); + phalcon_call_method_p2(instance, *service, "resolve", parameters, this_ptr); } else { /** * The DI also acts as builder for any class even if it isn't defined in the DI */ if (phalcon_class_exists(name, 1 TSRMLS_CC)) { - PHALCON_INIT_NVAR(instance); + int res; if (Z_TYPE_P(parameters) == IS_ARRAY) { - if (phalcon_create_instance_params(instance, name, parameters TSRMLS_CC) == FAILURE) { - RETURN_MM(); - } + res = phalcon_create_instance_params(instance, name, parameters TSRMLS_CC); } else { - if (phalcon_create_instance(instance, name TSRMLS_CC) == FAILURE) { - RETURN_MM(); - } + res = phalcon_create_instance(instance, name TSRMLS_CC); + } + + if (res == FAILURE) { + RETURN_MM(); } } else { PHALCON_INIT_VAR(exception_message); @@ -416,18 +404,13 @@ PHP_METHOD(Phalcon_DI, get){ */ PHP_METHOD(Phalcon_DI, getShared){ - zval *name, *parameters = NULL, *shared_instances, *instance = NULL; - - PHALCON_MM_GROW(); + zval *name, *parameters = NULL, *inst; + zval **shared_instances, **instance; - phalcon_fetch_params(1, 1, 1, &name, ¶meters); - - if (!parameters) { - PHALCON_INIT_VAR(parameters); - } + phalcon_fetch_params(0, 1, 1, &name, ¶meters); if (Z_TYPE_P(name) != IS_STRING) { - PHALCON_THROW_EXCEPTION_STR(phalcon_di_exception_ce, "The service alias must be a string"); + PHALCON_THROW_EXCEPTION_STRW(phalcon_di_exception_ce, "The service alias must be a string"); return; } @@ -435,27 +418,29 @@ PHP_METHOD(Phalcon_DI, getShared){ * This method provides a first level to shared instances allowing to use * non-shared services as shared */ - PHALCON_OBS_VAR(shared_instances); - phalcon_read_property_this(&shared_instances, this_ptr, SL("_sharedInstances"), PH_NOISY_CC); - if (phalcon_array_isset(shared_instances, name)) { - PHALCON_OBS_VAR(instance); - phalcon_array_fetch(&instance, shared_instances, name, PH_NOISY); + shared_instances = phalcon_fetch_nproperty_this(this_ptr, SL("_sharedInstances"), PH_NOISY_CC); + if (phalcon_array_isset_fetch(&instance, *shared_instances, name)) { phalcon_update_property_bool(this_ptr, SL("_freshInstance"), 0 TSRMLS_CC); - } else { - /** - * Resolve the instance normally - */ - PHALCON_INIT_NVAR(instance); - phalcon_call_method_p2(instance, this_ptr, "get", name, parameters); - - /** - * Save the instance in the first level shared - */ - phalcon_update_property_array(this_ptr, SL("_sharedInstances"), name, instance TSRMLS_CC); - phalcon_update_property_bool(this_ptr, SL("_freshInstance"), 1 TSRMLS_CC); + RETURN_CTORW(*instance); } - RETURN_CCTOR(instance); + PHALCON_MM_GROW(); + + if (!parameters) { + PHALCON_INIT_VAR(parameters); + } + + /** + * Resolve the instance normally + */ + phalcon_call_method_p2(return_value, this_ptr, "get", name, parameters); + + /** + * Save the instance in the first level shared + */ + phalcon_update_property_array(this_ptr, SL("_sharedInstances"), name, return_value TSRMLS_CC); + phalcon_update_property_bool(this_ptr, SL("_freshInstance"), 1 TSRMLS_CC); + PHALCON_MM_RESTORE(); } /** @@ -466,26 +451,18 @@ PHP_METHOD(Phalcon_DI, getShared){ */ PHP_METHOD(Phalcon_DI, has){ - zval *name, *services, *is_set_service = NULL; - zval *r0 = NULL; - - PHALCON_MM_GROW(); + zval *name; + zval **services; - phalcon_fetch_params(1, 1, 0, &name); + phalcon_fetch_params(0, 1, 0, &name); if (Z_TYPE_P(name) != IS_STRING) { - PHALCON_THROW_EXCEPTION_STR(phalcon_di_exception_ce, "The service alias must be a string"); + PHALCON_THROW_EXCEPTION_STRW(phalcon_di_exception_ce, "The service alias must be a string"); return; } - PHALCON_OBS_VAR(services); - phalcon_read_property_this(&services, this_ptr, SL("_services"), PH_NOISY_CC); - - PHALCON_INIT_VAR(r0); - ZVAL_BOOL(r0, phalcon_array_isset(services, name)); - PHALCON_CPY_WRT(is_set_service, r0); - - RETURN_NCTOR(is_set_service); + services = phalcon_fetch_nproperty_this(this_ptr, SL("_services"), PH_NOISY_CC); + RETURN_BOOL(phalcon_array_isset(*services, name)); } /** @@ -562,8 +539,9 @@ PHALCON_DOC_METHOD(Phalcon_DI, offsetUnset); */ PHP_METHOD(Phalcon_DI, __call){ - zval *method, *arguments = NULL, *services, *service_name = NULL; - zval *possible_service = NULL, *handler, *exception_message; + zval *method, *arguments = NULL, *service_name = NULL; + zval *exception_message; + zval **services, **handler; PHALCON_MM_GROW(); @@ -578,20 +556,22 @@ PHP_METHOD(Phalcon_DI, __call){ */ if (phalcon_start_with_str(method, SL("get"))) { - PHALCON_OBS_VAR(services); - phalcon_read_property_this(&services, this_ptr, SL("_services"), PH_NOISY_CC); + services = phalcon_fetch_nproperty_this(this_ptr, SL("_services"), PH_NOISY_CC); PHALCON_INIT_VAR(service_name); phalcon_substr(service_name, method, 3, 0); + if (likely(Z_STRLEN_P(service_name) > 0)) { + Z_STRVAL_P(service_name)[0] = tolower(Z_STRVAL_P(service_name)[0]); + } - PHALCON_INIT_VAR(possible_service); - phalcon_lcfirst(possible_service, service_name); - if (phalcon_array_isset(services, possible_service)) { + if (phalcon_array_isset(*services, service_name)) { if (phalcon_fast_count_ev(arguments TSRMLS_CC)) { - phalcon_call_method_p2(return_value, this_ptr, "get", possible_service, arguments); - RETURN_MM(); + phalcon_call_method_p2(return_value, this_ptr, "get", service_name, arguments); } - phalcon_call_method_p1(return_value, this_ptr, "get", possible_service); + else { + phalcon_call_method_p1(return_value, this_ptr, "get", service_name); + } + RETURN_MM(); } } @@ -600,16 +580,15 @@ PHP_METHOD(Phalcon_DI, __call){ * If the magic method starts with 'set' we try to set a service using that name */ if (phalcon_start_with_str(method, SL("set"))) { - if (phalcon_array_isset_long(arguments, 0)) { + if (phalcon_array_isset_long_fetch(&handler, arguments, 0)) { PHALCON_INIT_NVAR(service_name); phalcon_substr(service_name, method, 3, 0); - PHALCON_INIT_NVAR(possible_service); - phalcon_lcfirst(possible_service, service_name); - - PHALCON_OBS_VAR(handler); - phalcon_array_fetch_long(&handler, arguments, 0, PH_NOISY); - phalcon_call_method_p2_noret(this_ptr, "set", possible_service, handler); + if (likely(Z_STRLEN_P(service_name) > 0)) { + Z_STRVAL_P(service_name)[0] = tolower(Z_STRVAL_P(service_name)[0]); + } + + phalcon_call_method_p2_noret(this_ptr, "set", service_name, *handler); RETURN_MM_NULL(); } } @@ -661,11 +640,8 @@ PHP_METHOD(Phalcon_DI, reset){ zval *null_value; - PHALCON_MM_GROW(); - - PHALCON_INIT_VAR(null_value); + ALLOC_INIT_ZVAL(null_value); phalcon_update_static_property(SL("phalcon\\di"), SL("_default"), null_value TSRMLS_CC); - - PHALCON_MM_RESTORE(); + zval_ptr_dtor(&null_value); } From 07672f8a8c65313a2191b6e403d6272f2be85a88 Mon Sep 17 00:00:00 2001 From: Vladimir Kolesnikov Date: Sun, 4 Aug 2013 19:51:23 +0300 Subject: [PATCH 2/3] phalcon_fetch_static_property_ce() --- ext/kernel/object.c | 7 ++++++- ext/kernel/object.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ext/kernel/object.c b/ext/kernel/object.c index 8c7ab2aed5c..e3917536a4f 100644 --- a/ext/kernel/object.c +++ b/ext/kernel/object.c @@ -1216,10 +1216,15 @@ int phalcon_method_quick_exists_ex(const zval *object, const char *method_name, return FAILURE; } +zval* phalcon_fetch_static_property_ce(zend_class_entry *ce, char *property, int len TSRMLS_DC) { + assert(ce != NULL); + return zend_read_static_property(ce, property, len, (zend_bool)ZEND_FETCH_CLASS_SILENT TSRMLS_CC); +} + int phalcon_read_static_property_ce(zval **result, zend_class_entry *ce, char *property, int len TSRMLS_DC) { assert(ce != NULL); - *result = zend_read_static_property(ce, property, len, (zend_bool)ZEND_FETCH_CLASS_SILENT TSRMLS_CC); + *result = phalcon_fetch_static_property_ce(ce, property, len TSRMLS_CC); if (*result) { Z_ADDREF_PP(result); return SUCCESS; diff --git a/ext/kernel/object.h b/ext/kernel/object.h index 2a7feec809b..103631c843a 100644 --- a/ext/kernel/object.h +++ b/ext/kernel/object.h @@ -86,6 +86,7 @@ int phalcon_update_static_property_ce(zend_class_entry *ce, char *name, int len, int phalcon_update_static_property(const char *class_name, unsigned int class_length, char *name, unsigned int name_length, zval *value TSRMLS_DC); int phalcon_read_static_property_ce(zval **result, zend_class_entry *ce, char *property, int len TSRMLS_DC); int phalcon_read_class_property(zval **result, int type, char *property, int len TSRMLS_DC); +zval* phalcon_fetch_static_property_ce(zend_class_entry *ce, char *property, int len TSRMLS_DC); /** Create instances */ extern int phalcon_create_instance(zval *return_value, const zval *class_name TSRMLS_DC); From 934c03991425bb795e33597a88b4058263703c54 Mon Sep 17 00:00:00 2001 From: Vladimir Kolesnikov Date: Sun, 4 Aug 2013 19:51:47 +0300 Subject: [PATCH 3/3] More Phalcon\Di optimizations --- ext/di.c | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/ext/di.c b/ext/di.c index 64547733691..d5388217598 100644 --- a/ext/di.c +++ b/ext/di.c @@ -100,15 +100,10 @@ PHP_METHOD(Phalcon_DI, __construct){ zval *default_di; - PHALCON_MM_GROW(); - - PHALCON_OBS_VAR(default_di); - phalcon_read_static_property(&default_di, SL("phalcon\\di"), SL("_default") TSRMLS_CC); + default_di = phalcon_fetch_static_property_ce(phalcon_di_ce, SL("_default") TSRMLS_CC); if (!zend_is_true(default_di)) { phalcon_update_static_property(SL("phalcon\\di"), SL("_default"), this_ptr TSRMLS_CC); } - - PHALCON_MM_RESTORE(); } /** @@ -626,11 +621,8 @@ PHP_METHOD(Phalcon_DI, getDefault){ zval *default_di; - PHALCON_MM_GROW(); - - PHALCON_OBS_VAR(default_di); - phalcon_read_static_property(&default_di, SL("phalcon\\di"), SL("_default") TSRMLS_CC); - RETURN_CCTOR(default_di); + default_di = phalcon_fetch_static_property_ce(phalcon_di_ce, SL("_default") TSRMLS_CC); + RETURN_CTORW(default_di); } /**