From: Dmitry Stogov <dmitry@zend.com> Date: Fri, 26 Dec 2014 19:34:44 +0000 (+0300) Subject: Optimized destruction of extra arguments passed to user functions. X-Git-Tag: PRE_PHP7_REMOVALS~35^2~5 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=ab0b15b8ff90a292dcf0af2eb95d426ba4662095;p=php Optimized destruction of extra arguments passed to user functions. If no refcounted arguments are passed, then destruction code is not triggered at all. (Full rebuild required) --- diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index f56005450c..7909e9800a 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -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) diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 35dd10feb2..3c01b28c48 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -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; diff --git a/Zend/zend_execute.h b/Zend/zend_execute.h index 9197e4c9e5..a94299fd06 100644 --- a/Zend/zend_execute.h +++ b/Zend/zend_execute.h @@ -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); diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 1f7978b688..28885db75a 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -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