]> granicus.if.org Git - php/commitdiff
Optimized ZEND_RETURN opcode to not allocate and copy return value if it is not
authorDmitry Stogov <dmitry@php.net>
Fri, 11 Apr 2008 09:43:49 +0000 (09:43 +0000)
committerDmitry Stogov <dmitry@php.net>
Fri, 11 Apr 2008 09:43:49 +0000 (09:43 +0000)
used.

Zend/zend.c
Zend/zend_execute_API.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h

index 2f1a7c3bf24c3f57e756ea3505c3616fce55fdf0..170bf560ee4e61c3f54c8dc69ffadc88ce76be65 100644 (file)
@@ -1668,7 +1668,6 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_co
        zend_file_handle *file_handle;
        zend_op_array *orig_op_array = EG(active_op_array);
        zval **orig_retval_ptr_ptr = EG(return_value_ptr_ptr);
-       zval *local_retval = NULL;
 
        va_start(files, file_count);
        for (i = 0; i < file_count; i++) {
@@ -1683,7 +1682,7 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_co
                }
                zend_destroy_file_handle(file_handle TSRMLS_CC);
                if (EG(active_op_array)) {
-                       EG(return_value_ptr_ptr) = retval ? retval : &local_retval;
+                       EG(return_value_ptr_ptr) = retval ? retval : NULL;
                        zend_execute(EG(active_op_array) TSRMLS_CC);
                        if (EG(exception)) {
                                EG(opline_ptr) = NULL;
@@ -1714,13 +1713,6 @@ ZEND_API int zend_execute_scripts(int type TSRMLS_DC, zval **retval, int file_co
                                } else {
                                        zend_exception_error(EG(exception) TSRMLS_CC);
                                }
-                               if (retval == NULL && *EG(return_value_ptr_ptr) != NULL) {
-                                       zval_ptr_dtor(EG(return_value_ptr_ptr));
-                                       local_retval = NULL;
-                               }
-                       } else if (!retval && *EG(return_value_ptr_ptr)) {
-                               zval_ptr_dtor(EG(return_value_ptr_ptr));
-                               local_retval = NULL;
                        }
                        destroy_op_array(EG(active_op_array) TSRMLS_CC);
                        efree(EG(active_op_array));
index 549209b655998377397c0f705c2c1ffa689bb3bf..ae76c28bf00e2f58042b892419d2a17609bfa0fa 100644 (file)
@@ -1423,7 +1423,7 @@ ZEND_API int zend_u_eval_string(zend_uchar type, zstr string, zval *retval_ptr,
                        u_strcat(Z_USTRVAL(pv), u_semicolon);
                } else {
                        Z_USTRLEN(pv) = u_strlen(str);
-                       Z_USTRVAL(pv) = eustrndup(str, Z_USTRLEN(pv));
+                       Z_USTRVAL(pv) = str;
                }
        } else {
                char *str = string.s;
@@ -1436,7 +1436,7 @@ ZEND_API int zend_u_eval_string(zend_uchar type, zstr string, zval *retval_ptr,
                        strcat(Z_STRVAL(pv), " ;");
                } else {
                        Z_STRLEN(pv) = strlen(str);
-                       Z_STRVAL(pv) = estrndup(str, Z_STRLEN(pv));
+                       Z_STRVAL(pv) = str;
                }
        }
        Z_TYPE(pv) = type;
@@ -1481,7 +1481,9 @@ ZEND_API int zend_u_eval_string(zend_uchar type, zstr string, zval *retval_ptr,
        } else {
                retval = FAILURE;
        }
-       zval_dtor(&pv);
+       if (retval_ptr) {
+               zval_dtor(&pv);
+       }
        return retval;
 }
 /* }}} */
@@ -1515,7 +1517,6 @@ void execute_new_code(TSRMLS_D) /* {{{ */
 {
        zend_op *opline, *end;
        zend_op *ret_opline;
-       zval *local_retval=NULL;
 
        if (!(CG(active_op_array)->fn_flags & ZEND_ACC_INTERACTIVE)
                || CG(active_op_array)->backpatch_count>0
@@ -1569,12 +1570,9 @@ void execute_new_code(TSRMLS_D) /* {{{ */
 
        zend_release_labels(TSRMLS_C);
 
-       EG(return_value_ptr_ptr) = &local_retval;
+       EG(return_value_ptr_ptr) = NULL;
        EG(active_op_array) = CG(active_op_array);
        zend_execute(CG(active_op_array) TSRMLS_CC);
-       if (local_retval) {
-               zval_ptr_dtor(&local_retval);
-       }
 
        if (EG(exception)) {
                zend_exception_error(EG(exception) TSRMLS_CC);
index ab25403154a216ae5e36cb60bc85d8d6b64e019c..25fbf6082aff0f87488d367ebcff516d6e7d52a6 100644 (file)
@@ -2229,7 +2229,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
                        zend_u_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
                        /*printf("Cache miss!  Initialized %x\n", EG(active_symbol_table));*/
                }
-               EG(return_value_ptr_ptr) = &EX_T(opline->result.u.var).var.ptr;
+               EG(return_value_ptr_ptr) = RETURN_VALUE_USED(opline) ? &EX_T(opline->result.u.var).var.ptr : NULL;
                EG(active_op_array) = (zend_op_array *) EX(function_state).function;
 
                zend_execute(EG(active_op_array) TSRMLS_CC);
@@ -2239,8 +2239,6 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
                        if (!EG(exception) && !EX_T(opline->result.u.var).var.ptr) {
                                ALLOC_INIT_ZVAL(EX_T(opline->result.u.var).var.ptr);
                        }
-               } else if (EX_T(opline->result.u.var).var.ptr) {
-                       zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
                }
 
                EG(opline_ptr) = &EX(opline);
@@ -2377,16 +2375,22 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
                        }
                }
 
-               SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
-               Z_ADDREF_PP(retval_ptr_ptr);
+               if (EG(return_value_ptr_ptr)) {
+                       SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
+                       Z_ADDREF_PP(retval_ptr_ptr);
 
-               (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
+                       (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
+               }
        } else {
 ZEND_VM_C_LABEL(return_by_value):
 
                retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
 
-               if (!IS_OP1_TMP_FREE()) { /* Not a temp var */
+               if (!EG(return_value_ptr_ptr)) {
+                       if (OP1_TYPE == IS_TMP_VAR) {
+                               FREE_OP1();
+                       }
+               } else if (!IS_OP1_TMP_FREE()) { /* Not a temp var */
                        if (EG(active_op_array)->return_reference == ZEND_RETURN_REF ||
                            (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
                                zval *ret;
@@ -3214,7 +3218,7 @@ skip_compile:
                zval *saved_object;
                zend_function *saved_function;
 
-               EG(return_value_ptr_ptr) = EX_T(opline->result.u.var).var.ptr_ptr;
+               EG(return_value_ptr_ptr) = return_value_used ? EX_T(opline->result.u.var).var.ptr_ptr : NULL;
                EG(active_op_array) = new_op_array;
                EX_T(opline->result.u.var).var.ptr = NULL;
 
@@ -3229,11 +3233,7 @@ skip_compile:
                EX(function_state).function = saved_function;
                EX(object) = saved_object;
 
-               if (!return_value_used) {
-                       if (EX_T(opline->result.u.var).var.ptr) {
-                               zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
-                       }
-               } else { /* return value is used */
+               if (return_value_used) {
                        if (!EX_T(opline->result.u.var).var.ptr) { /* there was no return statement */
                                ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
                                INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
index 9f3680cf761512db8a6c8afc15b9d420ecdcd330..4f6aae710937042277507e89acb7dcd426922ab6 100644 (file)
@@ -222,7 +222,7 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
                        zend_u_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0, UG(unicode));
                        /*printf("Cache miss!  Initialized %x\n", EG(active_symbol_table));*/
                }
-               EG(return_value_ptr_ptr) = &EX_T(opline->result.u.var).var.ptr;
+               EG(return_value_ptr_ptr) = RETURN_VALUE_USED(opline) ? &EX_T(opline->result.u.var).var.ptr : NULL;
                EG(active_op_array) = (zend_op_array *) EX(function_state).function;
 
                zend_execute(EG(active_op_array) TSRMLS_CC);
@@ -232,8 +232,6 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
                        if (!EG(exception) && !EX_T(opline->result.u.var).var.ptr) {
                                ALLOC_INIT_ZVAL(EX_T(opline->result.u.var).var.ptr);
                        }
-               } else if (EX_T(opline->result.u.var).var.ptr) {
-                       zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
                }
 
                EG(opline_ptr) = &EX(opline);
@@ -1438,16 +1436,22 @@ static int ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        }
                }
 
-               SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
-               Z_ADDREF_PP(retval_ptr_ptr);
+               if (EG(return_value_ptr_ptr)) {
+                       SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
+                       Z_ADDREF_PP(retval_ptr_ptr);
 
-               (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
+                       (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
+               }
        } else {
 return_by_value:
 
                retval_ptr = &opline->op1.u.constant;
 
-               if (!0) { /* Not a temp var */
+               if (!EG(return_value_ptr_ptr)) {
+                       if (IS_CONST == IS_TMP_VAR) {
+
+                       }
+               } else if (!0) { /* Not a temp var */
                        if (EG(active_op_array)->return_reference == ZEND_RETURN_REF ||
                            (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
                                zval *ret;
@@ -1768,7 +1772,7 @@ skip_compile:
                zval *saved_object;
                zend_function *saved_function;
 
-               EG(return_value_ptr_ptr) = EX_T(opline->result.u.var).var.ptr_ptr;
+               EG(return_value_ptr_ptr) = return_value_used ? EX_T(opline->result.u.var).var.ptr_ptr : NULL;
                EG(active_op_array) = new_op_array;
                EX_T(opline->result.u.var).var.ptr = NULL;
 
@@ -1783,11 +1787,7 @@ skip_compile:
                EX(function_state).function = saved_function;
                EX(object) = saved_object;
 
-               if (!return_value_used) {
-                       if (EX_T(opline->result.u.var).var.ptr) {
-                               zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
-                       }
-               } else { /* return value is used */
+               if (return_value_used) {
                        if (!EX_T(opline->result.u.var).var.ptr) { /* there was no return statement */
                                ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
                                INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
@@ -4736,16 +4736,22 @@ static int ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        }
                }
 
-               SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
-               Z_ADDREF_PP(retval_ptr_ptr);
+               if (EG(return_value_ptr_ptr)) {
+                       SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
+                       Z_ADDREF_PP(retval_ptr_ptr);
 
-               (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
+                       (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
+               }
        } else {
 return_by_value:
 
                retval_ptr = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
 
-               if (!1) { /* Not a temp var */
+               if (!EG(return_value_ptr_ptr)) {
+                       if (IS_TMP_VAR == IS_TMP_VAR) {
+                               zval_dtor(free_op1.var);
+                       }
+               } else if (!1) { /* Not a temp var */
                        if (EG(active_op_array)->return_reference == ZEND_RETURN_REF ||
                            (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
                                zval *ret;
@@ -5075,7 +5081,7 @@ skip_compile:
                zval *saved_object;
                zend_function *saved_function;
 
-               EG(return_value_ptr_ptr) = EX_T(opline->result.u.var).var.ptr_ptr;
+               EG(return_value_ptr_ptr) = return_value_used ? EX_T(opline->result.u.var).var.ptr_ptr : NULL;
                EG(active_op_array) = new_op_array;
                EX_T(opline->result.u.var).var.ptr = NULL;
 
@@ -5090,11 +5096,7 @@ skip_compile:
                EX(function_state).function = saved_function;
                EX(object) = saved_object;
 
-               if (!return_value_used) {
-                       if (EX_T(opline->result.u.var).var.ptr) {
-                               zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
-                       }
-               } else { /* return value is used */
+               if (return_value_used) {
                        if (!EX_T(opline->result.u.var).var.ptr) { /* there was no return statement */
                                ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
                                INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
@@ -7972,16 +7974,22 @@ static int ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        }
                }
 
-               SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
-               Z_ADDREF_PP(retval_ptr_ptr);
+               if (EG(return_value_ptr_ptr)) {
+                       SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
+                       Z_ADDREF_PP(retval_ptr_ptr);
 
-               (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
+                       (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
+               }
        } else {
 return_by_value:
 
                retval_ptr = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
 
-               if (!0) { /* Not a temp var */
+               if (!EG(return_value_ptr_ptr)) {
+                       if (IS_VAR == IS_TMP_VAR) {
+                               if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+                       }
+               } else if (!0) { /* Not a temp var */
                        if (EG(active_op_array)->return_reference == ZEND_RETURN_REF ||
                            (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
                                zval *ret;
@@ -8416,7 +8424,7 @@ skip_compile:
                zval *saved_object;
                zend_function *saved_function;
 
-               EG(return_value_ptr_ptr) = EX_T(opline->result.u.var).var.ptr_ptr;
+               EG(return_value_ptr_ptr) = return_value_used ? EX_T(opline->result.u.var).var.ptr_ptr : NULL;
                EG(active_op_array) = new_op_array;
                EX_T(opline->result.u.var).var.ptr = NULL;
 
@@ -8431,11 +8439,7 @@ skip_compile:
                EX(function_state).function = saved_function;
                EX(object) = saved_object;
 
-               if (!return_value_used) {
-                       if (EX_T(opline->result.u.var).var.ptr) {
-                               zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
-                       }
-               } else { /* return value is used */
+               if (return_value_used) {
                        if (!EX_T(opline->result.u.var).var.ptr) { /* there was no return statement */
                                ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
                                INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);
@@ -22238,16 +22242,22 @@ static int ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
                        }
                }
 
-               SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
-               Z_ADDREF_PP(retval_ptr_ptr);
+               if (EG(return_value_ptr_ptr)) {
+                       SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
+                       Z_ADDREF_PP(retval_ptr_ptr);
 
-               (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
+                       (*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
+               }
        } else {
 return_by_value:
 
                retval_ptr = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
 
-               if (!0) { /* Not a temp var */
+               if (!EG(return_value_ptr_ptr)) {
+                       if (IS_CV == IS_TMP_VAR) {
+
+                       }
+               } else if (!0) { /* Not a temp var */
                        if (EG(active_op_array)->return_reference == ZEND_RETURN_REF ||
                            (PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
                                zval *ret;
@@ -22672,7 +22682,7 @@ skip_compile:
                zval *saved_object;
                zend_function *saved_function;
 
-               EG(return_value_ptr_ptr) = EX_T(opline->result.u.var).var.ptr_ptr;
+               EG(return_value_ptr_ptr) = return_value_used ? EX_T(opline->result.u.var).var.ptr_ptr : NULL;
                EG(active_op_array) = new_op_array;
                EX_T(opline->result.u.var).var.ptr = NULL;
 
@@ -22687,11 +22697,7 @@ skip_compile:
                EX(function_state).function = saved_function;
                EX(object) = saved_object;
 
-               if (!return_value_used) {
-                       if (EX_T(opline->result.u.var).var.ptr) {
-                               zval_ptr_dtor(&EX_T(opline->result.u.var).var.ptr);
-                       }
-               } else { /* return value is used */
+               if (return_value_used) {
                        if (!EX_T(opline->result.u.var).var.ptr) { /* there was no return statement */
                                ALLOC_ZVAL(EX_T(opline->result.u.var).var.ptr);
                                INIT_PZVAL(EX_T(opline->result.u.var).var.ptr);