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
#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)
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;
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 */
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,
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) {
}
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);
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++;
}
}
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++;
}
}
}
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);
+ }
}
}
}
}
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);
+ }
}
}
}