From: Bob Weinand Date: Fri, 12 Jun 2015 15:26:41 +0000 (+0200) Subject: Cache the class_name typehint key in arg_info X-Git-Tag: php-7.0.0alpha2~2^2~157^2~1 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=7c2a0157c7c71a55dce2d4dade854a4d6ccb03e9;p=php Cache the class_name typehint key in arg_info This leads to up to 2% improvement on one tested real world application by not having to always recalculate the lowercased string and its hash --- diff --git a/Zend/zend_API.h b/Zend/zend_API.h index b01b041859..83e5265fd4 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -68,9 +68,9 @@ typedef struct _zend_fcall_info_cache { #define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name)) #define ZEND_METHOD(classname, name) ZEND_NAMED_FUNCTION(ZEND_MN(classname##_##name)) -#define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags }, +#define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags }, -#define ZEND_RAW_FENTRY(zend_name, name, arg_info, flags) { zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags }, +#define ZEND_RAW_FENTRY(zend_name, name, arg_info, flags) { zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags }, #define ZEND_RAW_NAMED_FE(zend_name, name, arg_info) ZEND_RAW_FENTRY(#zend_name, name, arg_info, 0) #define ZEND_NAMED_FE(zend_name, name, arg_info) ZEND_FENTRY(zend_name, name, arg_info, 0) diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 902d37c503..a649f8fcaf 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -4238,9 +4238,11 @@ static void zend_compile_typename(zend_ast *ast, zend_arg_info *arg_info) /* {{{ if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) { class_name = zend_resolve_class_name_ast(ast); zend_assert_valid_class_name(class_name); + arg_info->lower_class_name = zend_string_tolower(class_name); } else { zend_ensure_valid_class_fetch_type(fetch_type); zend_string_addref(class_name); + arg_info->lower_class_name = NULL; } arg_info->type_hint = IS_OBJECT; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index d258289a13..eccbb84aff 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -297,6 +297,7 @@ typedef struct _zend_internal_arg_info { zend_uchar pass_by_reference; zend_bool allow_null; zend_bool is_variadic; + void *reserved; /* to align with zend_arg_info */ } zend_internal_arg_info; /* arg_info for user functions */ @@ -307,6 +308,7 @@ typedef struct _zend_arg_info { zend_uchar pass_by_reference; zend_bool allow_null; zend_bool is_variadic; + zend_string *lower_class_name; } zend_arg_info; /* the following structure repeats the layout of zend_internal_arg_info, diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 386ddf3989..e63fc2dd32 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -587,7 +587,12 @@ ZEND_API char * zend_verify_internal_arg_class_kind(const zend_internal_arg_info ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce) { - *pce = zend_fetch_class(cur_arg_info->class_name, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD)); + /* optimization to not always recalculate the lowercase name and hash */ + if (cur_arg_info->lower_class_name) { + *pce = zend_hash_find_ptr(EG(class_table), cur_arg_info->lower_class_name); + } else { /* "extra" fetch type */ + *pce = zend_fetch_class(cur_arg_info->class_name, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD)); + } *class_name = (*pce) ? (*pce)->name->val : cur_arg_info->class_name->val; if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) { diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 1c760c5902..abb91b1ee3 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -410,6 +410,10 @@ ZEND_API void destroy_op_array(zend_op_array *op_array) } if (arg_info[i].class_name) { zend_string_release(arg_info[i].class_name); + + if (arg_info[i].lower_class_name) { + zend_string_release(arg_info[i].lower_class_name); + } } } efree(arg_info); diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 219bb50820..10a149c9f6 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -438,6 +438,9 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra if (!IS_SERIALIZED(p->class_name)) { SERIALIZE_STR(p->class_name); } + if (p->class_name && !IS_SERIALIZED(p->lower_class_name)) { + SERIALIZE_STR(p->lower_class_name); + } p++; } } @@ -962,6 +965,9 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr if (!IS_UNSERIALIZED(p->class_name)) { UNSERIALIZE_STR(p->class_name); } + if (p->class_name && !IS_UNSERIALIZED(p->lower_class_name)) { + UNSERIALIZE_STR(p->lower_class_name); + } p++; } } diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 09eebe0d02..585c34f46e 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -581,6 +581,9 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc } if (arg_info[i].class_name) { zend_accel_store_interned_string(arg_info[i].class_name); + if (arg_info[i].lower_class_name) { + zend_accel_store_interned_string(arg_info[i].lower_class_name); + } } } } diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index 98412109a5..d721db2feb 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -225,6 +225,9 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array) } if (arg_info[i].class_name) { ADD_INTERNED_STRING(arg_info[i].class_name, 1); + if (arg_info[i].lower_class_name) { + ADD_INTERNED_STRING(arg_info[i].lower_class_name, 1); + } } } }