]> granicus.if.org Git - php/commitdiff
Optimization of ASSIGN instruction
authorDmitry Stogov <dmitry@php.net>
Wed, 11 Aug 2010 15:34:06 +0000 (15:34 +0000)
committerDmitry Stogov <dmitry@php.net>
Wed, 11 Aug 2010 15:34:06 +0000 (15:34 +0000)
Zend/zend_execute.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 92f2231a55c66db605fbe59482637c9d2abdd557..0a22ffa0ddc04778beaad459f34b25d84da8df84 100644 (file)
@@ -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)
 {
index bd326022d6601c50231cc4549057331c9ca45766..f25599f5bcee2ab04837c90340a347a34d36a3ad 100644 (file)
@@ -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);
                }
index f4669f9019e8b42b349b189fc4dde1e25e298e7e..87cbfbc5f21d3f7fe42563ecbca4cb0441c6d063 100644 (file)
@@ -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);
                }