]> granicus.if.org Git - php/commitdiff
Optimized destruction of extra arguments passed to user functions.
authorDmitry Stogov <dmitry@zend.com>
Fri, 26 Dec 2014 19:34:44 +0000 (22:34 +0300)
committerDmitry Stogov <dmitry@zend.com>
Fri, 26 Dec 2014 19:34:44 +0000 (22:34 +0300)
If no refcounted arguments are passed, then destruction code is not triggered at all.
(Full rebuild required)

Zend/zend_compile.h
Zend/zend_execute.c
Zend/zend_execute.h
Zend/zend_types.h

index f56005450ce898168fe1c63562f72dd2c6ec5037..7909e9800ac8805a8f159847fe93078c533524bd 100644 (file)
@@ -412,8 +412,9 @@ struct _zend_execute_data {
 #define ZEND_CALL_CODE               (1 << 0)
 #define ZEND_CALL_NESTED             (0 << 1)
 #define ZEND_CALL_TOP                (1 << 1)
-#define ZEND_CALL_CTOR               (1 << 2)
-#define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 3)
+#define ZEND_CALL_FREE_EXTRA_ARGS    (1 << 2) /* equal to IS_TYPE_REFCOUNTED */
+#define ZEND_CALL_CTOR               (1 << 3)
+#define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 4)
 
 #define ZEND_CALL_INFO(call) \
        (Z_TYPE_INFO((call)->This) >> 24)
index 35dd10feb2fdd420fb5ef852449cf805299d857e..3c01b28c48850e5c0f97be1ae43a9a1d70da26a6 100644 (file)
@@ -1617,6 +1617,7 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu
        num_args = EX_NUM_ARGS();
        if (UNEXPECTED(num_args > first_extra_arg)) {
                zval *end, *src, *dst;
+               uint32_t type_flags = 0;
 
                if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
                        /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
@@ -1629,12 +1630,19 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu
                dst = src + (op_array->last_var + op_array->T - first_extra_arg);
                if (EXPECTED(src != dst)) {
                        do {
+                               type_flags |= Z_TYPE_INFO_P(src);
                                ZVAL_COPY_VALUE(dst, src);
                                ZVAL_UNDEF(src);
                                src--;
                                dst--;
                        } while (src != end);
+               } else {
+                       do {
+                               type_flags |= Z_TYPE_INFO_P(src);
+                               src--;
+                       } while (src != end);
                }
+               ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED));
        } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
                /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
                EX(opline) += num_args;
@@ -1709,6 +1717,7 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da
                num_args = EX_NUM_ARGS();
                if (UNEXPECTED(num_args > first_extra_arg)) {
                        zval *end, *src, *dst;
+                       uint32_t type_flags = 0;
 
                        if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
                                /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
@@ -1721,12 +1730,19 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da
                        dst = src + (op_array->last_var + op_array->T - first_extra_arg);
                        if (EXPECTED(src != dst)) {
                                do {
+                                       type_flags |= Z_TYPE_INFO_P(src);
                                        ZVAL_COPY_VALUE(dst, src);
                                        ZVAL_UNDEF(src);
                                        src--;
                                        dst--;
                                } while (src != end);
+                       } else {
+                               do {
+                                       type_flags |= Z_TYPE_INFO_P(src);
+                                       src--;
+                               } while (src != end);
                        }
+                       ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED));
                } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) {
                        /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */
                        EX(opline) += num_args;
index 9197e4c9e574e74f840384fc3671f0594caf4ea2..a94299fd0698469a04924e86152810e6dcd29189 100644 (file)
@@ -176,11 +176,9 @@ static zend_always_inline zend_execute_data *zend_vm_stack_push_call_frame(uint3
 
 static zend_always_inline void zend_vm_stack_free_extra_args(zend_execute_data *call)
 {
-       uint32_t first_extra_arg = call->func->op_array.num_args;
-
-       if (UNEXPECTED(ZEND_CALL_NUM_ARGS(call) > first_extra_arg)) {
-               zval *end = ZEND_CALL_VAR_NUM(call, call->func->op_array.last_var + call->func->op_array.T);
-               zval *p = end + (ZEND_CALL_NUM_ARGS(call) - first_extra_arg);
+       if (ZEND_CALL_INFO(call) & ZEND_CALL_FREE_EXTRA_ARGS) {
+               zval *end = ZEND_CALL_VAR_NUM(call, call->func->op_array.last_var + call->func->op_array.T);
+               zval *p = end + (ZEND_CALL_NUM_ARGS(call) - call->func->op_array.num_args);
                do {
                        p--;
                        zval_ptr_dtor_nogc(p);
index 1f7978b68889eabae23ceba9d68ac0c4d0d3a4b2..28885db75aeb1cae4288067baa85a2bee6437e84 100644 (file)
@@ -264,7 +264,7 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
 #define Z_COUNTED_P(zval_p)                    Z_COUNTED(*(zval_p))
 
 #define Z_TYPE_FLAGS_SHIFT                     8
-#define Z_CONST_FLAGS_SHIFT                    8
+#define Z_CONST_FLAGS_SHIFT                    16
 
 #define GC_REFCOUNT(p)                         ((zend_refcounted*)(p))->refcount
 #define GC_TYPE(p)                                     ((zend_refcounted*)(p))->u.v.type
@@ -286,10 +286,10 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) {
 
 /* zval.u1.v.type_flags */
 #define IS_TYPE_CONSTANT                       (1<<0)
-#define IS_TYPE_REFCOUNTED                     (1<<1)
-#define IS_TYPE_COLLECTABLE                    (1<<2)
-#define IS_TYPE_COPYABLE                       (1<<3)
-#define IS_TYPE_IMMUTABLE                      (1<<4)
+#define IS_TYPE_IMMUTABLE                      (1<<1)
+#define IS_TYPE_REFCOUNTED                     (1<<2)
+#define IS_TYPE_COLLECTABLE                    (1<<3)
+#define IS_TYPE_COPYABLE                       (1<<4)
 
 /* extended types */
 #define IS_INTERNED_STRING_EX          IS_STRING