mirror of
https://github.com/php/php-src.git
synced 2024-11-23 18:04:36 +08:00
Optimized ZEND_RETURN opcode to not allocate and copy return value if it is not
used.
This commit is contained in:
parent
ca3391f44c
commit
d9dd1b9e14
2
NEWS
2
NEWS
@ -91,6 +91,8 @@ PHP NEWS
|
||||
- Added forward_static_call(_array) to complete LSB. (Mike Lively)
|
||||
|
||||
- Improved PHP runtime speed and memory usage:
|
||||
. Optimized ZEND_RETURN opcode to not allocate and copy return value if it is
|
||||
not used. (Dmitry)
|
||||
. Replaced flex based scanner with re2c based scanner. (Marcus, Nuno, Scott)
|
||||
. Added garbage collector. (David Wang, Dmitry).
|
||||
. Improved PHP binary size and startup speed with GCC4 visibility control.
|
||||
|
10
Zend/zend.c
10
Zend/zend.c
@ -1150,7 +1150,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++) {
|
||||
@ -1165,7 +1164,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)) {
|
||||
if (EG(user_exception_handler)) {
|
||||
@ -1195,13 +1194,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));
|
||||
|
@ -1273,7 +1273,7 @@ ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSR
|
||||
Z_STRVAL(pv)[Z_STRLEN(pv)] = '\0';
|
||||
} else {
|
||||
Z_STRLEN(pv) = strlen(str);
|
||||
Z_STRVAL(pv) = estrndup(str, Z_STRLEN(pv));
|
||||
Z_STRVAL(pv) = str;
|
||||
}
|
||||
Z_TYPE(pv) = IS_STRING;
|
||||
|
||||
@ -1317,7 +1317,9 @@ ZEND_API int zend_eval_string(char *str, zval *retval_ptr, char *string_name TSR
|
||||
} else {
|
||||
retval = FAILURE;
|
||||
}
|
||||
zval_dtor(&pv);
|
||||
if (retval_ptr) {
|
||||
zval_dtor(&pv);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
/* }}} */
|
||||
@ -1339,7 +1341,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
|
||||
@ -1393,12 +1394,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);
|
||||
|
@ -2167,7 +2167,7 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
|
||||
zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
|
||||
/*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);
|
||||
@ -2177,8 +2177,6 @@ ZEND_VM_HELPER(zend_do_fcall_common_helper, ANY, ANY)
|
||||
if (!EX_T(opline->result.u.var).var.ptr && !EG(exception)) {
|
||||
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);
|
||||
@ -2313,16 +2311,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;
|
||||
@ -3115,7 +3119,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
|
||||
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;
|
||||
|
||||
@ -3130,11 +3134,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMP|VAR|CV, ANY)
|
||||
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);
|
||||
|
@ -214,7 +214,7 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
|
||||
zend_hash_init(EG(active_symbol_table), 0, NULL, ZVAL_PTR_DTOR, 0);
|
||||
/*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);
|
||||
@ -224,8 +224,6 @@ static int zend_do_fcall_common_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS)
|
||||
if (!EX_T(opline->result.u.var).var.ptr && !EG(exception)) {
|
||||
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);
|
||||
@ -1445,16 +1443,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;
|
||||
@ -1737,7 +1741,7 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
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;
|
||||
|
||||
@ -1752,11 +1756,7 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
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);
|
||||
@ -4603,16 +4603,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;
|
||||
@ -4904,7 +4910,7 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
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;
|
||||
|
||||
@ -4919,11 +4925,7 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
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);
|
||||
@ -7696,16 +7698,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;
|
||||
@ -8102,7 +8110,7 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
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;
|
||||
|
||||
@ -8117,11 +8125,7 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
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);
|
||||
@ -21368,16 +21372,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;
|
||||
@ -21764,7 +21774,7 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
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;
|
||||
|
||||
@ -21779,11 +21789,7 @@ static int ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
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);
|
||||
|
Loading…
Reference in New Issue
Block a user