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.
This commit is contained in:
Nikita Popov 2016-02-05 15:23:23 +01:00
parent f75be35312
commit 5faedf5b3e
16 changed files with 79 additions and 78 deletions

View File

@ -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

View File

@ -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;

View File

@ -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()

View File

@ -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)
{

View File

@ -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;

View File

@ -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;

View File

@ -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];
}

View File

@ -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");
}

View File

@ -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:

View File

@ -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);
}
}

View File

@ -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 */
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() */
GET_AVAILABLE_T();
map_T[currT] = i;
zend_bitset_incl(valid_T, currT);
}
ZEND_RESULT(opline).var = NUM_VAR(i + offset);
}
}

View File

@ -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;

View File

@ -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()

View File

@ -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));
}
}

View File

@ -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

View File

@ -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 {