From: Dmitry Stogov Date: Wed, 11 Aug 2010 15:34:06 +0000 (+0000) Subject: Optimization of ASSIGN instruction X-Git-Tag: php-5.4.0alpha1~191^2~1113 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f48999ca3b9d6dd8f432e2b95c1a78c577e01ce7;p=php Optimization of ASSIGN instruction --- diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 92f2231a55..0a22ffa0dd 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -819,6 +819,7 @@ static inline int zend_assign_to_string_offset(const temp_variable *T, const zva static inline zval* zend_assign_tmp_to_variable(zval **variable_ptr_ptr, zval *value TSRMLS_DC) { zval *variable_ptr = *variable_ptr_ptr; + zval garbage; if (Z_TYPE_P(variable_ptr) == IS_OBJECT && UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) { @@ -826,26 +827,63 @@ static inline zval* zend_assign_tmp_to_variable(zval **variable_ptr_ptr, zval *v return variable_ptr; } - if (EXPECTED(!PZVAL_IS_REF(variable_ptr))) { - if (Z_REFCOUNT_P(variable_ptr)==1) { - zendi_zval_dtor(*variable_ptr); + if (UNEXPECTED(Z_REFCOUNT_P(variable_ptr) > 1) && + EXPECTED(!PZVAL_IS_REF(variable_ptr))) { + /* we need to split */ + Z_DELREF_P(variable_ptr); + GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr); + ALLOC_ZVAL(variable_ptr); + INIT_PZVAL_COPY(variable_ptr, value); + *variable_ptr_ptr = variable_ptr; + return variable_ptr; + } else { + if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) { + /* nothing to destroy */ ZVAL_COPY_VALUE(variable_ptr, value); - return variable_ptr; - } else { /* we need to split */ - Z_DELREF_P(variable_ptr); - GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr); - ALLOC_ZVAL(variable_ptr); - INIT_PZVAL_COPY(variable_ptr, value); - *variable_ptr_ptr = variable_ptr; - return variable_ptr; + } else { + ZVAL_COPY_VALUE(&garbage, variable_ptr); + ZVAL_COPY_VALUE(variable_ptr, value); + _zval_dtor_func(&garbage ZEND_FILE_LINE_CC); } - } else { - zendi_zval_dtor(*variable_ptr); - ZVAL_COPY_VALUE(variable_ptr, value); return variable_ptr; } } +static inline zval* zend_assign_const_to_variable(zval **variable_ptr_ptr, zval *value TSRMLS_DC) +{ + zval *variable_ptr = *variable_ptr_ptr; + zval garbage; + + if (Z_TYPE_P(variable_ptr) == IS_OBJECT && + UNEXPECTED(Z_OBJ_HANDLER_P(variable_ptr, set) != NULL)) { + Z_OBJ_HANDLER_P(variable_ptr, set)(variable_ptr_ptr, value TSRMLS_CC); + return variable_ptr; + } + + if (UNEXPECTED(Z_REFCOUNT_P(variable_ptr) > 1) && + EXPECTED(!PZVAL_IS_REF(variable_ptr))) { + /* we need to split */ + Z_DELREF_P(variable_ptr); + GC_ZVAL_CHECK_POSSIBLE_ROOT(variable_ptr); + ALLOC_ZVAL(variable_ptr); + INIT_PZVAL_COPY(variable_ptr, value); + zval_copy_ctor(variable_ptr); + *variable_ptr_ptr = variable_ptr; + return variable_ptr; + } else { + if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) { + /* nothing to destroy */ + ZVAL_COPY_VALUE(variable_ptr, value); + zendi_zval_copy_ctor(*variable_ptr); + } else { + ZVAL_COPY_VALUE(&garbage, variable_ptr); + ZVAL_COPY_VALUE(variable_ptr, value); + zendi_zval_copy_ctor(*variable_ptr); + _zval_dtor_func(&garbage ZEND_FILE_LINE_CC); + } + return variable_ptr; + } +} static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value TSRMLS_DC) { @@ -860,24 +898,21 @@ static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value if (EXPECTED(!PZVAL_IS_REF(variable_ptr))) { if (Z_REFCOUNT_P(variable_ptr)==1) { - if (variable_ptr==value) { - return variable_ptr; - } else if (PZVAL_IS_REF(value)) { - ZVAL_COPY_VALUE(&garbage, variable_ptr); - ZVAL_COPY_VALUE(variable_ptr, value); - zval_copy_ctor(variable_ptr); - zendi_zval_dtor(garbage); + if (UNEXPECTED(variable_ptr == value)) { return variable_ptr; - } else { - Z_DELREF_P(variable_ptr); + } else if (EXPECTED(!PZVAL_IS_REF(value))) { Z_ADDREF_P(value); *variable_ptr_ptr = value; - if (variable_ptr != &EG(uninitialized_zval)) { + if (EXPECTED(variable_ptr != &EG(uninitialized_zval))) { GC_REMOVE_ZVAL_FROM_BUFFER(variable_ptr); zval_dtor(variable_ptr); efree(variable_ptr); + } else { + Z_DELREF_P(variable_ptr); } return value; + } else { + goto copy_value; } } else { /* we need to split */ Z_DELREF_P(variable_ptr); @@ -897,16 +932,22 @@ static inline zval* zend_assign_to_variable(zval **variable_ptr_ptr, zval *value } } else { if (EXPECTED(variable_ptr != value)) { - ZVAL_COPY_VALUE(&garbage, variable_ptr); - ZVAL_COPY_VALUE(variable_ptr, value); - zendi_zval_copy_ctor(*variable_ptr); - zendi_zval_dtor(garbage); +copy_value: + if (EXPECTED(Z_TYPE_P(variable_ptr) <= IS_BOOL)) { + /* nothing to destroy */ + ZVAL_COPY_VALUE(variable_ptr, value); + zendi_zval_copy_ctor(*variable_ptr); + } else { + ZVAL_COPY_VALUE(&garbage, variable_ptr); + ZVAL_COPY_VALUE(variable_ptr, value); + zendi_zval_copy_ctor(*variable_ptr); + _zval_dtor_func(&garbage ZEND_FILE_LINE_CC); + } } return variable_ptr; } } - /* Utility Functions for Extensions */ static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array TSRMLS_DC) { diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index bd326022d6..f25599f5bc 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -1685,8 +1685,10 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMP|VAR|UNUSED|CV) AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (IS_TMP_FREE(free_op_data1)) { + if ((opline+1)->op1_type == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -1739,8 +1741,10 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV) AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (IS_OP2_TMP_FREE()) { + if (OP2_TYPE == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if (OP2_TYPE == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index f4669f9019..87cbfbc5f2 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -12782,8 +12782,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HAN AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (IS_TMP_FREE(free_op_data1)) { + if ((opline+1)->op1_type == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -12836,8 +12838,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (0) { + if (IS_CONST == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if (IS_CONST == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -14917,8 +14921,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDL AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (IS_TMP_FREE(free_op_data1)) { + if ((opline+1)->op1_type == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -14971,8 +14977,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_A AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (1) { + if (IS_TMP_VAR == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if (IS_TMP_VAR == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -16970,8 +16978,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDL AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (IS_TMP_FREE(free_op_data1)) { + if ((opline+1)->op1_type == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -17024,8 +17034,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_A AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (0) { + if (IS_VAR == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if (IS_VAR == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -18383,8 +18395,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HA AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (IS_TMP_FREE(free_op_data1)) { + if ((opline+1)->op1_type == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -20001,8 +20015,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLE AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (IS_TMP_FREE(free_op_data1)) { + if ((opline+1)->op1_type == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -20055,8 +20071,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_AR AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (0) { + if (IS_CV == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if (IS_CV == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -28290,8 +28308,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HAND AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (IS_TMP_FREE(free_op_data1)) { + if ((opline+1)->op1_type == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -28344,8 +28364,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (0) { + if (IS_CONST == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if (IS_CONST == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -30208,8 +30230,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLE AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (IS_TMP_FREE(free_op_data1)) { + if ((opline+1)->op1_type == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -30262,8 +30286,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (1) { + if (IS_TMP_VAR == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if (IS_TMP_VAR == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -32135,8 +32161,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLE AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (IS_TMP_FREE(free_op_data1)) { + if ((opline+1)->op1_type == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -32189,8 +32217,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (0) { + if (IS_VAR == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if (IS_VAR == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -33425,8 +33455,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HAN AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (IS_TMP_FREE(free_op_data1)) { + if ((opline+1)->op1_type == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -34924,8 +34956,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (IS_TMP_FREE(free_op_data1)) { + if ((opline+1)->op1_type == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if ((opline+1)->op1_type == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); } @@ -34978,8 +35012,10 @@ static int ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG AI_SET_PTR(&EX_T(opline->result.var), &EG(uninitialized_zval)); } } else { - if (0) { + if (IS_CV == IS_TMP_VAR) { value = zend_assign_tmp_to_variable(variable_ptr_ptr, value TSRMLS_CC); + } else if (IS_CV == IS_CONST) { + value = zend_assign_const_to_variable(variable_ptr_ptr, value TSRMLS_CC); } else { value = zend_assign_to_variable(variable_ptr_ptr, value TSRMLS_CC); }