]> granicus.if.org Git - php/commitdiff
Add STR_ALLOCA_* API, use in get_method and verify_arg
authorNikita Popov <nikic@php.net>
Fri, 2 May 2014 15:01:36 +0000 (17:01 +0200)
committerNikita Popov <nikic@php.net>
Sat, 3 May 2014 08:43:45 +0000 (10:43 +0200)
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
Zend/zend_object_handlers.c
Zend/zend_string.h

index 5ed46788eb63cfa849dcc34c55549d3e12d7bd4b..1979f59b09b959900356d42df1f6aad2c373554d 100644 (file)
@@ -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 ";
index 64ef01b9778d9e7c12971e4a01c31246e88a3411..2459746892193833066c93a2a679f0b9ee24327b 100644 (file)
@@ -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;
 }
index af83d4d3b53117aee60640ceb6a769ec61e7d5ca..dfdc74eda87865c22040fa8851cc47d33b808d1f 100644 (file)
@@ -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) {