From 65f488ece3f946d53b12b8c265185a483b079dfb Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 2 May 2014 17:01:36 +0200 Subject: [PATCH] Add STR_ALLOCA_* API, use in get_method and verify_arg This avoid unnecessary allocations when using dynamic method dispatch and class typehints. Probably there are other places where this should be done as well, those just stood out for my usage. --- Zend/zend_execute.c | 8 ++++++-- Zend/zend_object_handlers.c | 7 ++++--- Zend/zend_string.h | 14 ++++++++++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 5ed46788eb..1979f59b09 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -519,9 +519,13 @@ static inline zval* make_real_object(zval *object_ptr TSRMLS_DC) ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, ulong fetch_type, char **class_name, zend_class_entry **pce TSRMLS_DC) { - zend_string *key = STR_INIT(cur_arg_info->class_name, cur_arg_info->class_name_len, 0); + zend_string *key; + ALLOCA_FLAG(use_heap); + + STR_ALLOCA_INIT(key, cur_arg_info->class_name, cur_arg_info->class_name_len, use_heap); *pce = zend_fetch_class(key, (fetch_type | ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD) TSRMLS_CC); - STR_FREE(key); + STR_ALLOCA_FREE(key, use_heap); + *class_name = (*pce) ? (*pce)->name->val : (char*)cur_arg_info->class_name; if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) { return "implement interface "; diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 64ef01b977..2459746892 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1046,17 +1046,18 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str zval *func; zend_function *fbc; zend_string *lc_method_name; + ALLOCA_FLAG(use_heap); if (EXPECTED(key != NULL)) { lc_method_name = Z_STR_P(key); } else { - lc_method_name = STR_ALLOC(method_name->len, 0); + STR_ALLOCA_ALLOC(lc_method_name, method_name->len, use_heap); zend_str_tolower_copy(lc_method_name->val, method_name->val, method_name->len); } if (UNEXPECTED((func = zend_hash_find(&zobj->ce->function_table, lc_method_name)) == NULL)) { if (UNEXPECTED(!key)) { - STR_FREE(lc_method_name); + STR_ALLOCA_FREE(lc_method_name, use_heap); } if (zobj->ce->__call) { return zend_get_user_call_function(zobj->ce, method_name); @@ -1113,7 +1114,7 @@ static union _zend_function *zend_std_get_method(zend_object **obj_ptr, zend_str } if (UNEXPECTED(!key)) { - STR_FREE(lc_method_name); + STR_ALLOCA_FREE(lc_method_name, use_heap); } return fbc; } diff --git a/Zend/zend_string.h b/Zend/zend_string.h index af83d4d3b5..dfdc74eda8 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -56,6 +56,20 @@ END_EXTERN_C() #define _STR_HEADER_SIZE XtOffsetOf(zend_string, val) +#define STR_ALLOCA_ALLOC(str, _len, use_heap) do { \ + (str) = do_alloca(_STR_HEADER_SIZE + (_len) + 1, (use_heap)); \ + GC_REFCOUNT(str) = 1; \ + (str)->h = 0; \ + (str)->len = (_len); \ +} while (0) +#define STR_ALLOCA_INIT(str, s, len, use_heap) do { \ + STR_ALLOCA_ALLOC(str, len, use_heap); \ + memcpy((str)->val, (s), (len)); \ + (str)->val[(len)] = '\0'; \ +} while (0) + +#define STR_ALLOCA_FREE(str, use_heap) free_alloca(str, use_heap) + static zend_always_inline zend_ulong zend_str_hash_val(zend_string *s) { if (!s->h) { -- 2.40.0