diff options
author | Nikita Popov <nikic@php.net> | 2016-04-10 13:01:54 +0200 |
---|---|---|
committer | Nikita Popov <nikic@php.net> | 2016-04-15 15:32:20 +0200 |
commit | 64f91774f225e78a79c3623b185ae8b64ef9e30b (patch) | |
tree | a0947c110c53409cbdc585b20a9800adf11e5fac | |
parent | fd2cd354291d77f8949f905b50218e74463f3e7a (diff) | |
download | php-git-64f91774f225e78a79c3623b185ae8b64ef9e30b.tar.gz |
Remove IS_VAR_RET_REF flag
Instead decide whether a function returned by reference or by value
by checking whether the return value has REFERENCE type. This means
that functions returning by reference must always return a reference
and functions returning by value must not return a reference.
-rw-r--r-- | Zend/zend_execute.c | 1 | ||||
-rw-r--r-- | Zend/zend_operators.c | 11 | ||||
-rw-r--r-- | Zend/zend_operators.h | 12 | ||||
-rw-r--r-- | Zend/zend_types.h | 7 | ||||
-rw-r--r-- | Zend/zend_vm_def.h | 67 | ||||
-rw-r--r-- | Zend/zend_vm_execute.h | 224 | ||||
-rw-r--r-- | ext/opcache/Optimizer/zend_func_info.c | 2 | ||||
-rw-r--r-- | ext/reflection/php_reflection.c | 7 | ||||
-rw-r--r-- | ext/standard/var.c | 5 |
9 files changed, 160 insertions, 176 deletions
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index a23b843bc6..f14434bff9 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -2978,7 +2978,6 @@ static zend_never_inline int zend_do_fcall_overloaded(zend_function *fbc, zend_e EG(scope) = fbc->common.scope; ZVAL_NULL(ret); - Z_VAR_FLAGS_P(ret) = 0; EG(current_execute_data) = call; object->handlers->call_method(fbc->common.function_name, object, call, ret); diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c index 06a0f75386..c1a7986650 100644 --- a/Zend/zend_operators.c +++ b/Zend/zend_operators.c @@ -136,17 +136,6 @@ ZEND_API zend_long ZEND_FASTCALL zend_atol(const char *str, int str_len) /* {{{ } /* }}} */ -static zend_always_inline void zend_unwrap_reference(zval *op) /* {{{ */ -{ - if (Z_REFCOUNT_P(op) == 1) { - ZVAL_UNREF(op); - } else { - Z_DELREF_P(op); - ZVAL_COPY(op, Z_REFVAL_P(op)); - } -} -/* }}} */ - void ZEND_FASTCALL _convert_scalar_to_number(zval *op, zend_bool silent) /* {{{ */ { try_again: diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index db6162a4e5..405ca0926f 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -821,6 +821,18 @@ static zend_always_inline char *zend_print_long_to_buf(char *buf, zend_long num) ZEND_API zend_string* ZEND_FASTCALL zend_long_to_str(zend_long num); +static zend_always_inline void zend_unwrap_reference(zval *op) /* {{{ */ +{ + if (Z_REFCOUNT_P(op) == 1) { + ZVAL_UNREF(op); + } else { + Z_DELREF_P(op); + ZVAL_COPY(op, Z_REFVAL_P(op)); + } +} +/* }}} */ + + END_EXTERN_C() #endif diff --git a/Zend/zend_types.h b/Zend/zend_types.h index d3fa56080b..9545b53e33 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -131,7 +131,6 @@ struct _zval_struct { uint32_t type_info; } u1; union { - uint32_t var_flags; uint32_t next; /* hash collision chain */ uint32_t cache_slot; /* literal cache slot */ uint32_t lineno; /* line number (for ast nodes) */ @@ -345,9 +344,6 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { #define Z_CONST_FLAGS(zval) (zval).u1.v.const_flags #define Z_CONST_FLAGS_P(zval_p) Z_CONST_FLAGS(*(zval_p)) -#define Z_VAR_FLAGS(zval) (zval).u2.var_flags -#define Z_VAR_FLAGS_P(zval_p) Z_VAR_FLAGS(*(zval_p)) - #define Z_TYPE_INFO(zval) (zval).u1.type_info #define Z_TYPE_INFO_P(zval_p) Z_TYPE_INFO(*(zval_p)) @@ -416,9 +412,6 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { #define IS_CONSTANT_CLASS 0x080 /* __CLASS__ in trait */ #define IS_CONSTANT_IN_NAMESPACE 0x100 /* used only in opline->extended_value */ -/* zval.u2.var_flags */ -#define IS_VAR_RET_REF (1<<0) /* return by by reference */ - /* string flags (zval.value->gc.u.flags) */ #define IS_STR_PERSISTENT (1<<0) /* allocated using malloc */ #define IS_STR_INTERNED (1<<1) /* interned string */ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index c1f3fad2ed..6c9adea30b 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -2449,8 +2449,7 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC) } else if (OP2_TYPE == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && - UNEXPECTED(!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { - + UNEXPECTED(!Z_ISREF_P(value_ptr))) { zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { FREE_OP2_VAR_PTR(); @@ -3551,7 +3550,6 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL)) ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); - Z_VAR_FLAGS_P(ret) = 0; fbc->internal_function.handler(call, ret); @@ -3560,6 +3558,7 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL)) EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); + ZEND_ASSERT(!Z_ISREF_P(ret)); #endif EG(current_execute_data) = call->prev_execute_data; @@ -3598,7 +3597,6 @@ ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL)) if (RETURN_VALUE_USED(opline)) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); - Z_VAR_FLAGS_P(ret) = 0; } call->prev_execute_data = execute_data; @@ -3623,7 +3621,6 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL)) if (EXPECTED(RETURN_VALUE_USED(opline))) { ret = EX_VAR(opline->result.var); zend_generator_create_zval(call, &fbc->op_array, ret); - Z_VAR_FLAGS_P(ret) = 0; } else { zend_vm_stack_free_args(call); } @@ -3635,7 +3632,6 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL)) if (RETURN_VALUE_USED(opline)) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); - Z_VAR_FLAGS_P(ret) = 0; } call->prev_execute_data = execute_data; @@ -3670,15 +3666,16 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL)) 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; fbc->internal_function.handler(call, ret); #if ZEND_DEBUG - ZEND_ASSERT( - EG(exception) || !call->func || - !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (!EG(exception) && call->func) { + ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || + zend_verify_internal_return_type(call->func, ret)); + ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) + ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); + } #endif EG(current_execute_data) = call->prev_execute_data; @@ -3735,7 +3732,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) if (EXPECTED(RETURN_VALUE_USED(opline))) { ret = EX_VAR(opline->result.var); zend_generator_create_zval(call, &fbc->op_array, ret); - Z_VAR_FLAGS_P(ret) = 0; } else { if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE)) { OBJ_RELEASE((zend_object*)fbc->op_array.prototype); @@ -3748,7 +3744,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) if (RETURN_VALUE_USED(opline)) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); - Z_VAR_FLAGS_P(ret) = 0; } call->prev_execute_data = execute_data; @@ -3787,7 +3782,6 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) 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; if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ @@ -3797,10 +3791,12 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) } #if ZEND_DEBUG - ZEND_ASSERT( - EG(exception) || !call->func || - !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (!EG(exception) && call->func) { + ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || + zend_verify_internal_return_type(call->func, ret)); + ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) + ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); + } #endif EG(current_execute_data) = call->prev_execute_data; @@ -3998,14 +3994,16 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC) retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R); if (!EX(return_value)) { - if (OP1_TYPE == IS_TMP_VAR) { - FREE_OP1(); - } + FREE_OP1(); } else { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (OP1_TYPE != IS_TMP_VAR) { - zval_opt_copy_ctor_no_imm(EX(return_value)); + if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + break; + } + + ZVAL_NEW_REF(EX(return_value), retval_ptr); + if (OP1_TYPE == IS_CONST) { + if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } } break; @@ -4015,13 +4013,12 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC) if (OP1_TYPE == IS_VAR) { if (retval_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { + (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr))) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); + } else { + FREE_OP1_VAR_PTR(); } break; } @@ -4031,11 +4028,11 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC) ZVAL_MAKE_REF(retval_ptr); Z_ADDREF_P(retval_ptr); ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; } + + FREE_OP1_VAR_PTR(); } while (0); - FREE_OP1_VAR_PTR(); ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); } @@ -4276,7 +4273,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR, NUM, SEND) varptr = GET_OP1_ZVAL_PTR(BP_VAR_R); if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) || - (Z_VAR_FLAGS_P(varptr) & IS_VAR_RET_REF)) && + Z_ISREF_P(varptr)) && (Z_ISREF_P(varptr) || Z_TYPE_P(varptr) == IS_OBJECT)) { ZVAL_MAKE_REF(varptr); @@ -7300,9 +7297,6 @@ ZEND_VM_HANDLER(156, ZEND_SEPARATE, VAR, UNUSED) if (UNEXPECTED(Z_ISREF_P(var_ptr))) { if (UNEXPECTED(Z_REFCOUNT_P(var_ptr) == 1)) { ZVAL_UNREF(var_ptr); - } else if (!(Z_VAR_FLAGS_P(var_ptr) & IS_VAR_RET_REF)) { - Z_DELREF_P(var_ptr); - ZVAL_COPY(var_ptr, Z_REFVAL_P(var_ptr)); } } @@ -7356,7 +7350,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE if (OP1_TYPE == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -7935,7 +7929,6 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) ZVAL_NULL(&retval); ret = &retval; } - Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 6128e6c4fc..0fc6899535 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -611,7 +611,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HA ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); - Z_VAR_FLAGS_P(ret) = 0; fbc->internal_function.handler(call, ret); @@ -620,6 +619,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HA EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); + ZEND_ASSERT(!Z_ISREF_P(ret)); #endif EG(current_execute_data) = call->prev_execute_data; @@ -658,7 +658,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_USED_HAND ret = 1 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); - Z_VAR_FLAGS_P(ret) = 0; fbc->internal_function.handler(call, ret); @@ -667,6 +666,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_USED_HAND EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || zend_verify_internal_return_type(call->func, ret)); + ZEND_ASSERT(!Z_ISREF_P(ret)); #endif EG(current_execute_data) = call->prev_execute_data; @@ -705,7 +705,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_HA if (0) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); - Z_VAR_FLAGS_P(ret) = 0; } call->prev_execute_data = execute_data; @@ -730,7 +729,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETVAL_USED_HAND if (1) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); - Z_VAR_FLAGS_P(ret) = 0; } call->prev_execute_data = execute_data; @@ -755,7 +753,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U if (EXPECTED(0)) { ret = EX_VAR(opline->result.var); zend_generator_create_zval(call, &fbc->op_array, ret); - Z_VAR_FLAGS_P(ret) = 0; } else { zend_vm_stack_free_args(call); } @@ -767,7 +764,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U if (0) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); - Z_VAR_FLAGS_P(ret) = 0; } call->prev_execute_data = execute_data; @@ -802,15 +798,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U 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; fbc->internal_function.handler(call, ret); #if ZEND_DEBUG - ZEND_ASSERT( - EG(exception) || !call->func || - !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (!EG(exception) && call->func) { + ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || + zend_verify_internal_return_type(call->func, ret)); + ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) + ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); + } #endif EG(current_execute_data) = call->prev_execute_data; @@ -849,7 +846,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U if (EXPECTED(1)) { ret = EX_VAR(opline->result.var); zend_generator_create_zval(call, &fbc->op_array, ret); - Z_VAR_FLAGS_P(ret) = 0; } else { zend_vm_stack_free_args(call); } @@ -861,7 +857,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U if (1) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); - Z_VAR_FLAGS_P(ret) = 0; } call->prev_execute_data = execute_data; @@ -896,15 +891,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_U 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; fbc->internal_function.handler(call, ret); #if ZEND_DEBUG - ZEND_ASSERT( - EG(exception) || !call->func || - !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (!EG(exception) && call->func) { + ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || + zend_verify_internal_return_type(call->func, ret)); + ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) + ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); + } #endif EG(current_execute_data) = call->prev_execute_data; @@ -961,7 +957,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA if (EXPECTED(0)) { ret = EX_VAR(opline->result.var); zend_generator_create_zval(call, &fbc->op_array, ret); - Z_VAR_FLAGS_P(ret) = 0; } else { if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE)) { OBJ_RELEASE((zend_object*)fbc->op_array.prototype); @@ -974,7 +969,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA if (0) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); - Z_VAR_FLAGS_P(ret) = 0; } call->prev_execute_data = execute_data; @@ -1013,7 +1007,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA 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; if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ @@ -1023,10 +1016,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HA } #if ZEND_DEBUG - ZEND_ASSERT( - EG(exception) || !call->func || - !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (!EG(exception) && call->func) { + ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || + zend_verify_internal_return_type(call->func, ret)); + ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) + ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); + } #endif EG(current_execute_data) = call->prev_execute_data; @@ -1122,7 +1117,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND if (EXPECTED(1)) { ret = EX_VAR(opline->result.var); zend_generator_create_zval(call, &fbc->op_array, ret); - Z_VAR_FLAGS_P(ret) = 0; } else { if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE)) { OBJ_RELEASE((zend_object*)fbc->op_array.prototype); @@ -1135,7 +1129,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND if (1) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); - Z_VAR_FLAGS_P(ret) = 0; } call->prev_execute_data = execute_data; @@ -1174,7 +1167,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND 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; if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ @@ -1184,10 +1176,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HAND } #if ZEND_DEBUG - ZEND_ASSERT( - EG(exception) || !call->func || - !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, ret)); + if (!EG(exception) && call->func) { + ZEND_ASSERT(!(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || + zend_verify_internal_return_type(call->func, ret)); + ZEND_ASSERT((call->func->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) + ? Z_ISREF_P(ret) : !Z_ISREF_P(ret)); + } #endif EG(current_execute_data) = call->prev_execute_data; @@ -2073,7 +2067,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z ZVAL_NULL(&retval); ret = &retval; } - Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; if (!zend_execute_internal) { /* saves one function call if zend_execute_internal is not used */ @@ -2960,14 +2953,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDL retval_ptr = EX_CONSTANT(opline->op1); if (!EX(return_value)) { - if (IS_CONST == IS_TMP_VAR) { - } } else { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (IS_CONST != IS_TMP_VAR) { - zval_opt_copy_ctor_no_imm(EX(return_value)); + if (IS_CONST == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + break; + } + + ZVAL_NEW_REF(EX(return_value), retval_ptr); + if (IS_CONST == IS_CONST) { + if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } } break; @@ -2977,13 +2972,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDL if (IS_CONST == IS_VAR) { if (retval_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { + (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr))) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); + } else { + } break; } @@ -2993,8 +2987,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDL ZVAL_MAKE_REF(retval_ptr); Z_ADDREF_P(retval_ptr); ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; } + } while (0); ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -6236,7 +6230,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER if (IS_CONST == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -6407,7 +6401,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(Z if (IS_CONST == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -6858,7 +6852,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z if (IS_CONST == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -7913,7 +7907,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE if (IS_CONST == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -9786,7 +9780,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE if (IS_CONST == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -12058,14 +12052,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER retval_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); if (!EX(return_value)) { - if (IS_TMP_VAR == IS_TMP_VAR) { - zval_ptr_dtor_nogc(free_op1); - } + zval_ptr_dtor_nogc(free_op1); } else { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (IS_TMP_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor_no_imm(EX(return_value)); + if (IS_TMP_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + break; + } + + ZVAL_NEW_REF(EX(return_value), retval_ptr); + if (IS_TMP_VAR == IS_CONST) { + if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } } break; @@ -12075,13 +12071,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER if (IS_TMP_VAR == IS_VAR) { if (retval_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { + (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr))) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); + } else { + } break; } @@ -12091,8 +12086,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER ZVAL_MAKE_REF(retval_ptr); Z_ADDREF_P(retval_ptr); ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; } + } while (0); ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -13319,7 +13314,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z if (IS_TMP_VAR == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -13490,7 +13485,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN if (IS_TMP_VAR == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -13661,7 +13656,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEN if (IS_TMP_VAR == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -14013,7 +14008,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( if (IS_TMP_VAR == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -14541,7 +14536,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND if (IS_TMP_VAR == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -15325,14 +15320,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER retval_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); if (!EX(return_value)) { - if (IS_VAR == IS_TMP_VAR) { - zval_ptr_dtor_nogc(free_op1); - } + zval_ptr_dtor_nogc(free_op1); } else { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (IS_VAR != IS_TMP_VAR) { - zval_opt_copy_ctor_no_imm(EX(return_value)); + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + break; + } + + ZVAL_NEW_REF(EX(return_value), retval_ptr); + if (IS_VAR == IS_CONST) { + if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } } break; @@ -15342,13 +15339,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER if (IS_VAR == IS_VAR) { if (retval_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { + (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr))) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); + } else { + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; } break; } @@ -15358,11 +15354,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER ZVAL_MAKE_REF(retval_ptr); Z_ADDREF_P(retval_ptr); ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; } + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; } while (0); - if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -15505,7 +15501,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDL varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); if ((!(opline->extended_value & ZEND_ARG_SEND_FUNCTION) || - (Z_VAR_FLAGS_P(varptr) & IS_VAR_RET_REF)) && + Z_ISREF_P(varptr)) && (Z_ISREF_P(varptr) || Z_TYPE_P(varptr) == IS_OBJECT)) { ZVAL_MAKE_REF(varptr); @@ -19366,7 +19362,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z if (IS_VAR == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -19594,7 +19590,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN if (IS_VAR == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -19797,8 +19793,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLE } else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && - UNEXPECTED(!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { - + UNEXPECTED(!Z_ISREF_P(value_ptr))) { zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; @@ -19878,7 +19873,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEN if (IS_VAR == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -21154,9 +21149,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDL if (UNEXPECTED(Z_ISREF_P(var_ptr))) { if (UNEXPECTED(Z_REFCOUNT_P(var_ptr) == 1)) { ZVAL_UNREF(var_ptr); - } else if (!(Z_VAR_FLAGS_P(var_ptr) & IS_VAR_RET_REF)) { - Z_DELREF_P(var_ptr); - ZVAL_COPY(var_ptr, Z_REFVAL_P(var_ptr)); } } @@ -21210,7 +21202,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( if (IS_VAR == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -23385,8 +23377,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER } else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && - UNEXPECTED(!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { - + UNEXPECTED(!Z_ISREF_P(value_ptr))) { zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { @@ -23882,7 +23873,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND if (IS_VAR == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -28871,7 +28862,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE if (IS_UNUSED == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -29006,7 +28997,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER( if (IS_UNUSED == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -29141,7 +29132,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER( if (IS_UNUSED == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -29863,7 +29854,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL if (IS_UNUSED == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -32161,7 +32152,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z if (IS_UNUSED == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -34977,14 +34968,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( retval_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); if (!EX(return_value)) { - if (IS_CV == IS_TMP_VAR) { - } } else { - ZVAL_COPY_VALUE(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (IS_CV != IS_TMP_VAR) { - zval_opt_copy_ctor_no_imm(EX(return_value)); + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISREF_P(retval_ptr))) { + ZVAL_COPY_VALUE(EX(return_value), retval_ptr); + break; + } + + ZVAL_NEW_REF(EX(return_value), retval_ptr); + if (IS_CV == IS_CONST) { + if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); } } break; @@ -34994,13 +34987,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( if (IS_CV == IS_VAR) { if (retval_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(retval_ptr) & IS_VAR_RET_REF))) { + (opline->extended_value == ZEND_RETURNS_FUNCTION && !Z_ISREF_P(retval_ptr))) { zend_error(E_NOTICE, "Only variable references should be returned by reference"); if (EX(return_value)) { ZVAL_NEW_REF(EX(return_value), retval_ptr); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; - if (Z_REFCOUNTED_P(retval_ptr)) Z_ADDREF_P(retval_ptr); + } else { + } break; } @@ -35010,8 +35002,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( ZVAL_MAKE_REF(retval_ptr); Z_ADDREF_P(retval_ptr); ZVAL_REF(EX(return_value), Z_REF_P(retval_ptr)); - Z_VAR_FLAGS_P(EX(return_value)) = IS_VAR_RET_REF; } + } while (0); ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); @@ -40018,7 +40010,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE if (IS_CV == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -40387,7 +40379,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND if (IS_CV == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -40728,8 +40720,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER } else if (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && - UNEXPECTED(!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { - + UNEXPECTED(!Z_ISREF_P(value_ptr))) { zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; @@ -41000,7 +40991,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND if (IS_CV == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -42721,7 +42712,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z if (IS_CV == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); @@ -45609,8 +45600,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER( } else if (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_FUNCTION && - UNEXPECTED(!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { - + UNEXPECTED(!Z_ISREF_P(value_ptr))) { zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { @@ -46396,7 +46386,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_ if (IS_CV == IS_VAR && (value_ptr == &EG(uninitialized_zval) || (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { + !Z_ISREF_P(value_ptr)))) { zend_error(E_NOTICE, "Only variable references should be yielded by reference"); } else { ZVAL_MAKE_REF(value_ptr); diff --git a/ext/opcache/Optimizer/zend_func_info.c b/ext/opcache/Optimizer/zend_func_info.c index 2aa3ecb928..a684a16e73 100644 --- a/ext/opcache/Optimizer/zend_func_info.c +++ b/ext/opcache/Optimizer/zend_func_info.c @@ -529,7 +529,7 @@ static const func_info_t func_infos[] = { F1("forward_static_call", UNKNOWN_INFO), F1("forward_static_call_array", UNKNOWN_INFO), F1("serialize", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_STRING), - FX("unserialize", UNKNOWN_INFO), + FN("unserialize", UNKNOWN_INFO), F1("var_dump", MAY_BE_NULL), F1("var_export", MAY_BE_NULL | MAY_BE_STRING), F1("debug_zval_dump", MAY_BE_NULL), diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index dd3bd6e94d..186df87fd7 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -5647,7 +5647,9 @@ ZEND_METHOD(reflection_property, getValue) php_error_docref(NULL, E_ERROR, "Internal error: Could not find the property %s::%s", ZSTR_VAL(intern->ce->name), ZSTR_VAL(ref->prop.name)); /* Bails out */ } - ZVAL_DUP(return_value, &CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]); + member_p = &CE_STATIC_MEMBERS(intern->ce)[ref->prop.offset]; + ZVAL_DEREF(member_p); + ZVAL_COPY(return_value, member_p); } else { const char *class_name, *prop_name; size_t prop_name_len; @@ -5659,7 +5661,8 @@ ZEND_METHOD(reflection_property, getValue) zend_unmangle_property_name_ex(ref->prop.name, &class_name, &prop_name, &prop_name_len); member_p = zend_read_property(ref->ce, object, prop_name, prop_name_len, 1, &rv); - ZVAL_DUP(return_value, member_p); + ZVAL_DEREF(member_p); + ZVAL_COPY(return_value, member_p); } } /* }}} */ diff --git a/ext/standard/var.c b/ext/standard/var.c index acb1d40c01..76d92a5fd3 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -1080,6 +1080,11 @@ PHP_FUNCTION(unserialize) in case nesting calls to unserialize */ var_push_dtor(&var_hash, return_value); + /* Ensure return value is a value */ + if (Z_ISREF_P(return_value)) { + zend_unwrap_reference(return_value); + } + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); if (class_hash) { zend_hash_destroy(class_hash); |