From: Dmitry Stogov Date: Fri, 11 Apr 2008 09:43:49 +0000 (+0000) Subject: Optimized ZEND_RETURN opcode to not allocate and copy return value if it is not X-Git-Tag: RELEASE_2_0_0b1~458 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=b287ccf508dc33ff36bbf4eab8d5b613b3e015a2;p=php Optimized ZEND_RETURN opcode to not allocate and copy return value if it is not used. --- diff --git a/Zend/zend.c b/Zend/zend.c index 2f1a7c3bf2..170bf560ee 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -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)); diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 549209b655..ae76c28bf0 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -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); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index ab25403154..25fbf6082a 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -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); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 9f3680cf76..4f6aae7109 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -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);