From 5faedf5b3e05f0a8c226ac15d90be3d9ade38518 Mon Sep 17 00:00:00 2001 From: Nikita Popov Date: Fri, 5 Feb 2016 15:23:23 +0100 Subject: [PATCH] Remove EXT_TYPE_UNUSED in favor of IS_UNUSED This means we no longer allocate an unused VAR for the retval of instructions that support unused results. Nearly all instructions already used the result variable only if it was used. The only exception to this was the return value variable for internal function call results. I've adjusted the code to use a stack zval for the unused return case now. As we have retval specialization now, we know that it doesn't matter. --- Zend/zend.h | 2 +- Zend/zend_compile.c | 7 +- Zend/zend_compile.h | 2 - Zend/zend_execute.c | 2 +- Zend/zend_opcode.c | 4 +- Zend/zend_vm_def.h | 33 ++++++---- Zend/zend_vm_execute.h | 66 +++++++++++-------- Zend/zend_vm_gen.php | 2 +- ext/opcache/Optimizer/block_pass.c | 6 +- ext/opcache/Optimizer/dfa_pass.c | 8 +-- ext/opcache/Optimizer/optimize_temp_vars_5.c | 13 ++-- ext/opcache/Optimizer/pass3.c | 2 +- ext/opcache/Optimizer/zend_cfg.h | 2 +- ext/opcache/Optimizer/zend_dump.c | 4 -- ext/opcache/Optimizer/zend_dump.h | 2 +- .../Optimizer/zend_optimizer_internal.h | 2 +- 16 files changed, 79 insertions(+), 78 deletions(-) diff --git a/Zend/zend.h b/Zend/zend.h index 5a12374335..b1bd8a1cd0 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -61,7 +61,7 @@ #define USED_RET() \ (!EX(prev_execute_data) || \ !ZEND_USER_CODE(EX(prev_execute_data)->func->common.type) || \ - !(EX(prev_execute_data)->opline->result_type & EXT_TYPE_UNUSED)) + (EX(prev_execute_data)->opline->result_type != IS_UNUSED)) #ifdef ZEND_ENABLE_STATIC_TSRMLS_CACHE #define ZEND_TSRMG TSRMG_STATIC diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index f324e52874..bc871ed454 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -743,7 +743,7 @@ void zend_do_free(znode *op1) /* {{{ */ their selves */ zend_emit_op(NULL, ZEND_FREE, op1, NULL); } else { - opline->result_type |= EXT_TYPE_UNUSED; + opline->result_type = IS_UNUSED; } } else { while (opline >= CG(active_op_array)->opcodes) { @@ -756,7 +756,7 @@ void zend_do_free(znode *op1) /* {{{ */ if (opline->result_type==IS_VAR && opline->result.var == op1->u.op.var) { if (opline->opcode == ZEND_NEW) { - opline->result_type |= EXT_TYPE_UNUSED; + opline->result_type = IS_UNUSED; opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1]; while (opline->opcode != ZEND_DO_FCALL || opline->op1.num != ZEND_CALL_CTOR) { opline--; @@ -2904,9 +2904,6 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */ } opline = zend_emit_op(result, ZEND_ASSIGN_REF, &target_node, &source_node); - if (!result) { - opline->result_type |= EXT_TYPE_UNUSED; - } if (zend_is_call(source_ast)) { opline->extended_value = ZEND_RETURNS_FUNCTION; diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 5b5f19995a..30260eafd0 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -683,8 +683,6 @@ struct _zend_execute_data { #define IS_UNUSED (1<<3) /* Unused variable */ #define IS_CV (1<<4) /* Compiled variable */ -#define EXT_TYPE_UNUSED (1<<5) - #include "zend_globals.h" BEGIN_EXTERN_C() diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 3f02177b74..d14795de9a 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -68,7 +68,7 @@ static void zend_extension_statement_handler(const zend_extension *extension, ze static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array); static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array); -#define RETURN_VALUE_USED(opline) (!((opline)->result_type & EXT_TYPE_UNUSED)) +#define RETURN_VALUE_USED(opline) ((opline)->result_type != IS_UNUSED) static ZEND_FUNCTION(pass) { diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index d58e59b1c1..ab67a88272 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -680,8 +680,8 @@ ZEND_API int pass_two(zend_op_array *op_array) break; case ZEND_ASSERT_CHECK: /* If result of assert is unused, result of check is unused as well */ - if (op_array->opcodes[opline->op2.opline_num - 1].result_type & EXT_TYPE_UNUSED) { - opline->result_type |= EXT_TYPE_UNUSED; + if (op_array->opcodes[opline->op2.opline_num - 1].result_type == IS_UNUSED) { + opline->result_type = IS_UNUSED; } ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2); break; diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index d6f8c2fcc6..668e366c43 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3627,6 +3627,7 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL)) zend_execute_data *call = EX(call); zend_function *fbc = call->func; zval *ret; + zval retval; SAVE_OPLINE(); EX(call) = call->prev_execute_data; @@ -3634,7 +3635,7 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL)) call->prev_execute_data = execute_data; EG(current_execute_data) = call; - ret = EX_VAR(opline->result.var); + ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = 0; @@ -3644,7 +3645,7 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL)) ZEND_ASSERT( EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; @@ -3652,7 +3653,7 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL)) zend_vm_stack_free_call_frame(call); if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } if (UNEXPECTED(EG(exception) != NULL)) { @@ -3730,6 +3731,7 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL)) } EG(scope) = EX(func)->op_array.scope; } else { + zval retval; ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { @@ -3762,7 +3764,7 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL)) } } - ret = EX_VAR(opline->result.var); + ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; @@ -3772,7 +3774,7 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL)) ZEND_ASSERT( EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; @@ -3780,7 +3782,7 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL)) zend_vm_stack_free_call_frame(call); if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } } @@ -3857,6 +3859,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) } } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { int should_change_scope = 0; + zval retval; if (fbc->common.scope) { should_change_scope = 1; @@ -3888,7 +3891,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) } } - ret = EX_VAR(opline->result.var); + ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; @@ -3903,14 +3906,14 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) ZEND_ASSERT( EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } if (UNEXPECTED(should_change_scope)) { @@ -3919,6 +3922,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) ZEND_VM_C_GOTO(fcall_end); } } else { /* ZEND_OVERLOADED_FUNCTION */ + zval retval; /* Not sure what should be done here if it's a static method */ object = Z_OBJ(call->This); if (UNEXPECTED(object == NULL)) { @@ -3935,11 +3939,12 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) EG(scope) = fbc->common.scope; - ZVAL_NULL(EX_VAR(opline->result.var)); + ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); call->prev_execute_data = execute_data; EG(current_execute_data) = call; - object->handlers->call_method(fbc->common.function_name, object, call, EX_VAR(opline->result.var)); + object->handlers->call_method(fbc->common.function_name, object, call, ret); EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -3950,9 +3955,9 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) efree(fbc); if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } else { - Z_VAR_FLAGS_P(EX_VAR(opline->result.var)) = 0; + Z_VAR_FLAGS_P(ret) = 0; } } @@ -8106,7 +8111,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) ZEND_ASSERT( EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 351ec0cce2..1c2252ac21 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -580,6 +580,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HA zend_execute_data *call = EX(call); zend_function *fbc = call->func; zval *ret; + zval retval; SAVE_OPLINE(); EX(call) = call->prev_execute_data; @@ -587,7 +588,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HA call->prev_execute_data = execute_data; EG(current_execute_data) = call; - ret = EX_VAR(opline->result.var); + ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = 0; @@ -597,7 +598,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HA ZEND_ASSERT( EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; @@ -605,7 +606,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HA zend_vm_stack_free_call_frame(call); if (!0) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } if (UNEXPECTED(EG(exception) != NULL)) { @@ -626,6 +627,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_USED_HAND zend_execute_data *call = EX(call); zend_function *fbc = call->func; zval *ret; + zval retval; SAVE_OPLINE(); EX(call) = call->prev_execute_data; @@ -633,7 +635,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_USED_HAND call->prev_execute_data = execute_data; EG(current_execute_data) = call; - ret = EX_VAR(opline->result.var); + ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = 0; @@ -643,7 +645,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_USED_HAND ZEND_ASSERT( EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; @@ -651,7 +653,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_USED_HAND zend_vm_stack_free_call_frame(call); if (!1) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } if (UNEXPECTED(EG(exception) != NULL)) { @@ -754,6 +756,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U } EG(scope) = EX(func)->op_array.scope; } else { + zval retval; ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { @@ -786,7 +789,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U } } - ret = EX_VAR(opline->result.var); + ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; @@ -796,7 +799,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U ZEND_ASSERT( EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; @@ -804,7 +807,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U zend_vm_stack_free_call_frame(call); if (!0) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } } @@ -857,6 +860,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U } EG(scope) = EX(func)->op_array.scope; } else { + zval retval; ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { @@ -889,7 +893,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U } } - ret = EX_VAR(opline->result.var); + ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; @@ -899,7 +903,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U ZEND_ASSERT( EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; @@ -907,7 +911,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U zend_vm_stack_free_call_frame(call); if (!1) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } } @@ -984,6 +988,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA } } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { int should_change_scope = 0; + zval retval; if (fbc->common.scope) { should_change_scope = 1; @@ -1015,7 +1020,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA } } - ret = EX_VAR(opline->result.var); + ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; @@ -1030,14 +1035,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA ZEND_ASSERT( EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); if (!0) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } if (UNEXPECTED(should_change_scope)) { @@ -1046,6 +1051,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA goto fcall_end; } } else { /* ZEND_OVERLOADED_FUNCTION */ + zval retval; /* Not sure what should be done here if it's a static method */ object = Z_OBJ(call->This); if (UNEXPECTED(object == NULL)) { @@ -1062,11 +1068,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA EG(scope) = fbc->common.scope; - ZVAL_NULL(EX_VAR(opline->result.var)); + ret = 0 ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); call->prev_execute_data = execute_data; EG(current_execute_data) = call; - object->handlers->call_method(fbc->common.function_name, object, call, EX_VAR(opline->result.var)); + object->handlers->call_method(fbc->common.function_name, object, call, ret); EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -1077,9 +1084,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA efree(fbc); if (!0) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } else { - Z_VAR_FLAGS_P(EX_VAR(opline->result.var)) = 0; + Z_VAR_FLAGS_P(ret) = 0; } } @@ -1179,6 +1186,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND } } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { int should_change_scope = 0; + zval retval; if (fbc->common.scope) { should_change_scope = 1; @@ -1210,7 +1218,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND } } - ret = EX_VAR(opline->result.var); + ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; @@ -1225,14 +1233,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND ZEND_ASSERT( EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); if (!1) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } if (UNEXPECTED(should_change_scope)) { @@ -1241,6 +1249,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND goto fcall_end; } } else { /* ZEND_OVERLOADED_FUNCTION */ + zval retval; /* Not sure what should be done here if it's a static method */ object = Z_OBJ(call->This); if (UNEXPECTED(object == NULL)) { @@ -1257,11 +1266,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND EG(scope) = fbc->common.scope; - ZVAL_NULL(EX_VAR(opline->result.var)); + ret = 1 ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); call->prev_execute_data = execute_data; EG(current_execute_data) = call; - object->handlers->call_method(fbc->common.function_name, object, call, EX_VAR(opline->result.var)); + object->handlers->call_method(fbc->common.function_name, object, call, ret); EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -1272,9 +1282,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND efree(fbc); if (!1) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } else { - Z_VAR_FLAGS_P(EX_VAR(opline->result.var)) = 0; + Z_VAR_FLAGS_P(ret) = 0; } } @@ -2153,7 +2163,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z ZEND_ASSERT( EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; @@ -57293,7 +57303,7 @@ static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* if (spec & SPEC_RULE_OP1) offset = offset * 5 + zend_vm_decode[op->op1_type]; if (spec & SPEC_RULE_OP2) offset = offset * 5 + zend_vm_decode[op->op2_type]; if (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type]; - if (spec & SPEC_RULE_RETVAL) offset = offset * 2 + ((op->result_type & EXT_TYPE_UNUSED) == 0); + if (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED); if (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num < MAX_ARG_FLAG_NUM); return zend_opcode_handlers[(spec & SPEC_START_MASK) + offset]; } diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 1b0ade5b60..bbb69cad8d 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -2031,7 +2031,7 @@ function gen_vm($def, $skel) { out($f, "\tif (spec & SPEC_RULE_OP1) offset = offset * 5 + zend_vm_decode[op->op1_type];\n"); out($f, "\tif (spec & SPEC_RULE_OP2) offset = offset * 5 + zend_vm_decode[op->op2_type];\n"); out($f, "\tif (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type];\n"); - out($f, "\tif (spec & SPEC_RULE_RETVAL) offset = offset * 2 + ((op->result_type & EXT_TYPE_UNUSED) == 0);\n"); + out($f, "\tif (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED);\n"); out($f, "\tif (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num < MAX_ARG_FLAG_NUM);\n"); out($f, "\treturn zend_opcode_handlers[(spec & SPEC_START_MASK) + offset];\n"); } diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index f0913a8bca..665515de01 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -257,7 +257,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array /* mark as removed (empty live range) */ op_array->live_range[opline->op2.num].var = (uint32_t)-1; } - ZEND_RESULT_TYPE(src) |= EXT_TYPE_UNUSED; + ZEND_RESULT_TYPE(src) = IS_UNUSED; MAKE_NOP(opline); } } @@ -1612,7 +1612,7 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use case ZEND_DO_ICALL: case ZEND_DO_UCALL: case ZEND_DO_FCALL_BY_NAME: - opline->result_type |= EXT_TYPE_UNUSED; + opline->result_type = IS_UNUSED; break; } } else { @@ -1624,7 +1624,7 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use case ZEND_POST_INC: case ZEND_POST_DEC: opline->opcode -= 2; - opline->result_type = IS_VAR | EXT_TYPE_UNUSED; + opline->result_type = IS_UNUSED; break; case ZEND_QM_ASSIGN: case ZEND_BOOL: diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c index 3d8b2b6b00..98db4ea23e 100644 --- a/ext/opcache/Optimizer/dfa_pass.c +++ b/ext/opcache/Optimizer/dfa_pass.c @@ -56,7 +56,7 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, } if (ctx->debug_level & ZEND_DUMP_DFA_CFG) { - zend_dump_op_array(op_array, ZEND_DUMP_CFG | ZEND_DUMP_HIDE_UNUSED_VARS, "dfa cfg", &ssa->cfg); + zend_dump_op_array(op_array, ZEND_DUMP_CFG, "dfa cfg", &ssa->cfg); } /* Compute Dominators Tree */ @@ -85,7 +85,7 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, } if (ctx->debug_level & ZEND_DUMP_DFA_SSA) { - zend_dump_op_array(op_array, ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS, "before dfa pass", ssa); + zend_dump_op_array(op_array, ZEND_DUMP_SSA, "before dfa pass", ssa); } @@ -115,7 +115,7 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, zend_ssa *ssa) { if (ctx->debug_level & ZEND_DUMP_BEFORE_DFA_PASS) { - zend_dump_op_array(op_array, ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS, "before dfa pass", ssa); + zend_dump_op_array(op_array, ZEND_DUMP_SSA, "before dfa pass", ssa); } if (ssa->var_info) { @@ -217,7 +217,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx } if (ctx->debug_level & ZEND_DUMP_AFTER_DFA_PASS) { - zend_dump_op_array(op_array, ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS, "after dfa pass", ssa); + zend_dump_op_array(op_array, ZEND_DUMP_SSA, "after dfa pass", ssa); } } diff --git a/ext/opcache/Optimizer/optimize_temp_vars_5.c b/ext/opcache/Optimizer/optimize_temp_vars_5.c index 108bdda6d7..f0e5747dc6 100644 --- a/ext/opcache/Optimizer/optimize_temp_vars_5.c +++ b/ext/opcache/Optimizer/optimize_temp_vars_5.c @@ -170,16 +170,11 @@ void zend_optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_c } } } - } else { /* Au still needs to be assigned a T which is a bit dumb. Should consider changing Zend */ + } else { + /* Code which gets here is using a wrongly built opcode such as RECV() */ GET_AVAILABLE_T(); - - if (RESULT_UNUSED(opline)) { - zend_bitset_excl(taken_T, i); - } else { - /* Code which gets here is using a wrongly built opcode such as RECV() */ - map_T[currT] = i; - zend_bitset_incl(valid_T, currT); - } + map_T[currT] = i; + zend_bitset_incl(valid_T, currT); ZEND_RESULT(opline).var = NUM_VAR(i + offset); } } diff --git a/ext/opcache/Optimizer/pass3.c b/ext/opcache/Optimizer/pass3.c index e3c09dc045..ce04e4f7cb 100644 --- a/ext/opcache/Optimizer/pass3.c +++ b/ext/opcache/Optimizer/pass3.c @@ -418,7 +418,7 @@ continue_jmpznz_optimization: ZEND_OP1(next_op).var == ZEND_RESULT(opline).var) { MAKE_NOP(next_op); opline->opcode -= 2; - ZEND_RESULT_TYPE(opline) = IS_VAR | EXT_TYPE_UNUSED; + ZEND_RESULT_TYPE(opline) = IS_UNUSED; } } break; diff --git a/ext/opcache/Optimizer/zend_cfg.h b/ext/opcache/Optimizer/zend_cfg.h index 2a93ffd2c5..de94997dd5 100644 --- a/ext/opcache/Optimizer/zend_cfg.h +++ b/ext/opcache/Optimizer/zend_cfg.h @@ -108,7 +108,7 @@ typedef struct _zend_cfg { CRT_CONSTANT_EX(op_array, node, (build_flags & ZEND_RT_CONSTANTS)) #define RETURN_VALUE_USED(opline) \ - (!((opline)->result_type & EXT_TYPE_UNUSED)) + ((opline)->result_type != IS_UNUSED) BEGIN_EXTERN_C() diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c index 7cacdd01e2..b0607c61b4 100644 --- a/ext/opcache/Optimizer/zend_dump.c +++ b/ext/opcache/Optimizer/zend_dump.c @@ -404,10 +404,6 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block * zend_dump_var(op_array, opline->result_type, EX_VAR_TO_NUM(opline->result.var)); } fprintf(stderr, " = "); - } else if (!(dump_flags & ZEND_DUMP_HIDE_UNUSED_VARS) && - (opline->result_type & IS_VAR) && - (opline->result_type & EXT_TYPE_UNUSED)) { - fprintf(stderr, "U%u = ", EX_VAR_TO_NUM(opline->result.var)); } } diff --git a/ext/opcache/Optimizer/zend_dump.h b/ext/opcache/Optimizer/zend_dump.h index 44dd79fd04..0e4376edb1 100644 --- a/ext/opcache/Optimizer/zend_dump.h +++ b/ext/opcache/Optimizer/zend_dump.h @@ -23,7 +23,7 @@ #include "zend_dfg.h" #define ZEND_DUMP_HIDE_UNREACHABLE (1<<0) -#define ZEND_DUMP_HIDE_UNUSED_VARS (1<<1) +/* Unused flag (1<<1) */ #define ZEND_DUMP_CFG (1<<2) #define ZEND_DUMP_SSA (1<<3) #define ZEND_DUMP_RT_CONSTANTS ZEND_RT_CONSTANTS diff --git a/ext/opcache/Optimizer/zend_optimizer_internal.h b/ext/opcache/Optimizer/zend_optimizer_internal.h index 6483d0bc0a..220a00d6c4 100644 --- a/ext/opcache/Optimizer/zend_optimizer_internal.h +++ b/ext/opcache/Optimizer/zend_optimizer_internal.h @@ -43,7 +43,7 @@ #define INV_COND_EX(op) ((op) == ZEND_JMPZ ? ZEND_JMPNZ_EX : ZEND_JMPZ_EX) #define INV_EX_COND_EX(op) ((op) == ZEND_JMPZ_EX ? ZEND_JMPNZ_EX : ZEND_JMPZ_EX) -#define RESULT_UNUSED(op) ((op->result_type & EXT_TYPE_UNUSED) != 0) +#define RESULT_UNUSED(op) (op->result_type == IS_UNUSED) #define SAME_VAR(op1, op2) (op1 ## _type == op2 ## _type && op1.var == op2.var) typedef struct _zend_optimizer_ctx { -- 2.50.1