mirror of
https://github.com/php/php-src.git
synced 2026-04-07 16:13:32 +02:00
ZEND_RETURN is splitted into two new instructions ZEND_RETURN and ZEND_RETURN_BY_REF
This commit is contained in:
2
NEWS
2
NEWS
@@ -8,6 +8,8 @@
|
||||
. ZEND_RECV now always has IS_CV as its result
|
||||
. ZEND_CATCH now has to be used only with constant class names
|
||||
. ZEND_FETCH_DIM_? may fetch array and dimension operans in a different order
|
||||
. ZEND_RETURN is splitted into two new instructions ZEND_RETURN and
|
||||
ZEND_RETURN_BY_REF
|
||||
- Added concept of interned strings. All strings constants known at compile
|
||||
time are allocated in a single copy and never changed. (Dmitry)
|
||||
- Added an optimization which saves memory and emalloc/efree calls for empty
|
||||
|
||||
@@ -2439,7 +2439,7 @@ void zend_do_return(znode *expr, int do_end_vparse TSRMLS_DC) /* {{{ */
|
||||
|
||||
opline = get_next_op(CG(active_op_array) TSRMLS_CC);
|
||||
|
||||
opline->opcode = ZEND_RETURN;
|
||||
opline->opcode = (CG(active_op_array)->return_reference == ZEND_RETURN_REF) ? ZEND_RETURN_BY_REF : ZEND_RETURN;
|
||||
|
||||
if (expr) {
|
||||
SET_NODE(opline->op1, expr);
|
||||
|
||||
@@ -2705,6 +2705,43 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, CONST, ANY)
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *retval_ptr;
|
||||
zend_free_op free_op1;
|
||||
|
||||
SAVE_OPLINE();
|
||||
retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
|
||||
|
||||
if (!EG(return_value_ptr_ptr)) {
|
||||
if (OP1_TYPE == IS_TMP_VAR) {
|
||||
FREE_OP1();
|
||||
}
|
||||
} else if (!IS_OP1_TMP_FREE()) { /* Not a temp var */
|
||||
if (OP1_TYPE == IS_CONST ||
|
||||
(PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
zval_copy_ctor(ret);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
} else {
|
||||
*EG(return_value_ptr_ptr) = retval_ptr;
|
||||
Z_ADDREF_P(retval_ptr);
|
||||
}
|
||||
} else {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
}
|
||||
FREE_OP1_IF_VAR();
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *retval_ptr;
|
||||
@@ -2712,12 +2749,32 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
|
||||
zend_free_op free_op1;
|
||||
|
||||
SAVE_OPLINE();
|
||||
if (UNEXPECTED(EG(active_op_array)->return_reference == ZEND_RETURN_REF)) {
|
||||
|
||||
do {
|
||||
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
|
||||
/* Not supposed to happen, but we'll allow it */
|
||||
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
||||
ZEND_VM_C_GOTO(return_by_value);
|
||||
|
||||
retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
|
||||
if (!EG(return_value_ptr_ptr)) {
|
||||
if (OP1_TYPE == IS_TMP_VAR) {
|
||||
FREE_OP1();
|
||||
}
|
||||
} else if (!IS_OP1_TMP_FREE()) { /* Not a temp var */
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
zval_copy_ctor(ret);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
} else {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
retval_ptr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
|
||||
@@ -2730,11 +2787,13 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
|
||||
if (opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
||||
EX_T(opline->op1.var).var.fcall_returned_reference) {
|
||||
} else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
|
||||
if (OP1_TYPE == IS_VAR && !OP1_FREE) {
|
||||
PZVAL_LOCK(*retval_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
|
||||
}
|
||||
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
||||
ZEND_VM_C_GOTO(return_by_value);
|
||||
if (EG(return_value_ptr_ptr)) {
|
||||
retval_ptr = *retval_ptr_ptr;
|
||||
*EG(return_value_ptr_ptr) = retval_ptr;
|
||||
Z_ADDREF_P(retval_ptr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2742,43 +2801,12 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
|
||||
SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
|
||||
Z_ADDREF_PP(retval_ptr_ptr);
|
||||
|
||||
(*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
|
||||
*EG(return_value_ptr_ptr) = *retval_ptr_ptr;
|
||||
}
|
||||
FREE_OP1_IF_VAR();
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
|
||||
} else {
|
||||
ZEND_VM_C_LABEL(return_by_value):
|
||||
} while (0);
|
||||
|
||||
retval_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
|
||||
|
||||
if (!EG(return_value_ptr_ptr)) {
|
||||
if (OP1_TYPE == IS_TMP_VAR) {
|
||||
FREE_OP1();
|
||||
}
|
||||
} else if (!IS_OP1_TMP_FREE()) { /* Not a temp var */
|
||||
if (OP1_TYPE == IS_CONST ||
|
||||
EG(active_op_array)->return_reference == ZEND_RETURN_REF ||
|
||||
(PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
zval_copy_ctor(ret);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
} else {
|
||||
*EG(return_value_ptr_ptr) = retval_ptr;
|
||||
Z_ADDREF_P(retval_ptr);
|
||||
}
|
||||
} else {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
}
|
||||
FREE_OP1_IF_VAR();
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
|
||||
}
|
||||
FREE_OP1_IF_VAR();
|
||||
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
|
||||
}
|
||||
|
||||
ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY)
|
||||
|
||||
@@ -1765,6 +1765,43 @@ static int ZEND_FASTCALL ZEND_DO_FCALL_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_A
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *retval_ptr;
|
||||
|
||||
|
||||
SAVE_OPLINE();
|
||||
retval_ptr = opline->op1.zv;
|
||||
|
||||
if (!EG(return_value_ptr_ptr)) {
|
||||
if (IS_CONST == IS_TMP_VAR) {
|
||||
|
||||
}
|
||||
} else if (!0) { /* Not a temp var */
|
||||
if (IS_CONST == IS_CONST ||
|
||||
(PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
zval_copy_ctor(ret);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
} else {
|
||||
*EG(return_value_ptr_ptr) = retval_ptr;
|
||||
Z_ADDREF_P(retval_ptr);
|
||||
}
|
||||
} else {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
}
|
||||
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *retval_ptr;
|
||||
@@ -1772,12 +1809,32 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
|
||||
|
||||
|
||||
SAVE_OPLINE();
|
||||
if (UNEXPECTED(EG(active_op_array)->return_reference == ZEND_RETURN_REF)) {
|
||||
|
||||
do {
|
||||
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
|
||||
/* Not supposed to happen, but we'll allow it */
|
||||
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
||||
goto return_by_value;
|
||||
|
||||
retval_ptr = opline->op1.zv;
|
||||
if (!EG(return_value_ptr_ptr)) {
|
||||
if (IS_CONST == IS_TMP_VAR) {
|
||||
|
||||
}
|
||||
} else if (!0) { /* Not a temp var */
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
zval_copy_ctor(ret);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
} else {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
retval_ptr_ptr = NULL;
|
||||
@@ -1790,11 +1847,13 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
|
||||
if (opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
||||
EX_T(opline->op1.var).var.fcall_returned_reference) {
|
||||
} else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
|
||||
if (IS_CONST == IS_VAR && !0) {
|
||||
PZVAL_LOCK(*retval_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
|
||||
}
|
||||
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
||||
goto return_by_value;
|
||||
if (EG(return_value_ptr_ptr)) {
|
||||
retval_ptr = *retval_ptr_ptr;
|
||||
*EG(return_value_ptr_ptr) = retval_ptr;
|
||||
Z_ADDREF_P(retval_ptr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1802,43 +1861,11 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARG
|
||||
SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
|
||||
Z_ADDREF_PP(retval_ptr_ptr);
|
||||
|
||||
(*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
|
||||
*EG(return_value_ptr_ptr) = *retval_ptr_ptr;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
} else {
|
||||
return_by_value:
|
||||
|
||||
retval_ptr = opline->op1.zv;
|
||||
|
||||
if (!EG(return_value_ptr_ptr)) {
|
||||
if (IS_CONST == IS_TMP_VAR) {
|
||||
|
||||
}
|
||||
} else if (!0) { /* Not a temp var */
|
||||
if (IS_CONST == IS_CONST ||
|
||||
EG(active_op_array)->return_reference == ZEND_RETURN_REF ||
|
||||
(PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
zval_copy_ctor(ret);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
} else {
|
||||
*EG(return_value_ptr_ptr) = retval_ptr;
|
||||
Z_ADDREF_P(retval_ptr);
|
||||
}
|
||||
} else {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
}
|
||||
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
}
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
@@ -5305,6 +5332,43 @@ static int ZEND_FASTCALL ZEND_FREE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *retval_ptr;
|
||||
zend_free_op free_op1;
|
||||
|
||||
SAVE_OPLINE();
|
||||
retval_ptr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
|
||||
|
||||
if (!EG(return_value_ptr_ptr)) {
|
||||
if (IS_TMP_VAR == IS_TMP_VAR) {
|
||||
zval_dtor(free_op1.var);
|
||||
}
|
||||
} else if (!1) { /* Not a temp var */
|
||||
if (IS_TMP_VAR == IS_CONST ||
|
||||
(PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
zval_copy_ctor(ret);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
} else {
|
||||
*EG(return_value_ptr_ptr) = retval_ptr;
|
||||
Z_ADDREF_P(retval_ptr);
|
||||
}
|
||||
} else {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
}
|
||||
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *retval_ptr;
|
||||
@@ -5312,12 +5376,32 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
zend_free_op free_op1;
|
||||
|
||||
SAVE_OPLINE();
|
||||
if (UNEXPECTED(EG(active_op_array)->return_reference == ZEND_RETURN_REF)) {
|
||||
|
||||
do {
|
||||
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
|
||||
/* Not supposed to happen, but we'll allow it */
|
||||
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
||||
goto return_by_value;
|
||||
|
||||
retval_ptr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
|
||||
if (!EG(return_value_ptr_ptr)) {
|
||||
if (IS_TMP_VAR == IS_TMP_VAR) {
|
||||
zval_dtor(free_op1.var);
|
||||
}
|
||||
} else if (!1) { /* Not a temp var */
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
zval_copy_ctor(ret);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
} else {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
retval_ptr_ptr = NULL;
|
||||
@@ -5330,11 +5414,13 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
if (opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
||||
EX_T(opline->op1.var).var.fcall_returned_reference) {
|
||||
} else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
|
||||
if (IS_TMP_VAR == IS_VAR && !1) {
|
||||
PZVAL_LOCK(*retval_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
|
||||
}
|
||||
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
||||
goto return_by_value;
|
||||
if (EG(return_value_ptr_ptr)) {
|
||||
retval_ptr = *retval_ptr_ptr;
|
||||
*EG(return_value_ptr_ptr) = retval_ptr;
|
||||
Z_ADDREF_P(retval_ptr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5342,43 +5428,11 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
|
||||
Z_ADDREF_PP(retval_ptr_ptr);
|
||||
|
||||
(*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
|
||||
*EG(return_value_ptr_ptr) = *retval_ptr_ptr;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
} else {
|
||||
return_by_value:
|
||||
|
||||
retval_ptr = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
|
||||
|
||||
if (!EG(return_value_ptr_ptr)) {
|
||||
if (IS_TMP_VAR == IS_TMP_VAR) {
|
||||
zval_dtor(free_op1.var);
|
||||
}
|
||||
} else if (!1) { /* Not a temp var */
|
||||
if (IS_TMP_VAR == IS_CONST ||
|
||||
EG(active_op_array)->return_reference == ZEND_RETURN_REF ||
|
||||
(PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
zval_copy_ctor(ret);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
} else {
|
||||
*EG(return_value_ptr_ptr) = retval_ptr;
|
||||
Z_ADDREF_P(retval_ptr);
|
||||
}
|
||||
} else {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
}
|
||||
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
}
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
@@ -8828,6 +8882,43 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARG
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *retval_ptr;
|
||||
zend_free_op free_op1;
|
||||
|
||||
SAVE_OPLINE();
|
||||
retval_ptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
|
||||
|
||||
if (!EG(return_value_ptr_ptr)) {
|
||||
if (IS_VAR == IS_TMP_VAR) {
|
||||
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
|
||||
}
|
||||
} else if (!0) { /* Not a temp var */
|
||||
if (IS_VAR == IS_CONST ||
|
||||
(PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
zval_copy_ctor(ret);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
} else {
|
||||
*EG(return_value_ptr_ptr) = retval_ptr;
|
||||
Z_ADDREF_P(retval_ptr);
|
||||
}
|
||||
} else {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
}
|
||||
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *retval_ptr;
|
||||
@@ -8835,12 +8926,32 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
zend_free_op free_op1;
|
||||
|
||||
SAVE_OPLINE();
|
||||
if (UNEXPECTED(EG(active_op_array)->return_reference == ZEND_RETURN_REF)) {
|
||||
|
||||
do {
|
||||
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
|
||||
/* Not supposed to happen, but we'll allow it */
|
||||
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
||||
goto return_by_value;
|
||||
|
||||
retval_ptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
|
||||
if (!EG(return_value_ptr_ptr)) {
|
||||
if (IS_VAR == IS_TMP_VAR) {
|
||||
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
|
||||
}
|
||||
} else if (!0) { /* Not a temp var */
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
zval_copy_ctor(ret);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
} else {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
retval_ptr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
|
||||
@@ -8853,11 +8964,13 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
if (opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
||||
EX_T(opline->op1.var).var.fcall_returned_reference) {
|
||||
} else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
|
||||
if (IS_VAR == IS_VAR && !(free_op1.var != NULL)) {
|
||||
PZVAL_LOCK(*retval_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
|
||||
}
|
||||
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
||||
goto return_by_value;
|
||||
if (EG(return_value_ptr_ptr)) {
|
||||
retval_ptr = *retval_ptr_ptr;
|
||||
*EG(return_value_ptr_ptr) = retval_ptr;
|
||||
Z_ADDREF_P(retval_ptr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8865,43 +8978,12 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
|
||||
Z_ADDREF_PP(retval_ptr_ptr);
|
||||
|
||||
(*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
|
||||
*EG(return_value_ptr_ptr) = *retval_ptr_ptr;
|
||||
}
|
||||
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
} else {
|
||||
return_by_value:
|
||||
} while (0);
|
||||
|
||||
retval_ptr = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
|
||||
|
||||
if (!EG(return_value_ptr_ptr)) {
|
||||
if (IS_VAR == IS_TMP_VAR) {
|
||||
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
|
||||
}
|
||||
} else if (!0) { /* Not a temp var */
|
||||
if (IS_VAR == IS_CONST ||
|
||||
EG(active_op_array)->return_reference == ZEND_RETURN_REF ||
|
||||
(PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
zval_copy_ctor(ret);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
} else {
|
||||
*EG(return_value_ptr_ptr) = retval_ptr;
|
||||
Z_ADDREF_P(retval_ptr);
|
||||
}
|
||||
} else {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
}
|
||||
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
}
|
||||
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
@@ -23941,6 +24023,43 @@ static int ZEND_FASTCALL ZEND_JMPNZ_EX_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *retval_ptr;
|
||||
|
||||
|
||||
SAVE_OPLINE();
|
||||
retval_ptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
|
||||
|
||||
if (!EG(return_value_ptr_ptr)) {
|
||||
if (IS_CV == IS_TMP_VAR) {
|
||||
|
||||
}
|
||||
} else if (!0) { /* Not a temp var */
|
||||
if (IS_CV == IS_CONST ||
|
||||
(PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
zval_copy_ctor(ret);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
} else {
|
||||
*EG(return_value_ptr_ptr) = retval_ptr;
|
||||
Z_ADDREF_P(retval_ptr);
|
||||
}
|
||||
} else {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
}
|
||||
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
{
|
||||
USE_OPLINE
|
||||
zval *retval_ptr;
|
||||
@@ -23948,12 +24067,32 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
|
||||
|
||||
SAVE_OPLINE();
|
||||
if (UNEXPECTED(EG(active_op_array)->return_reference == ZEND_RETURN_REF)) {
|
||||
|
||||
do {
|
||||
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
|
||||
/* Not supposed to happen, but we'll allow it */
|
||||
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
||||
goto return_by_value;
|
||||
|
||||
retval_ptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
|
||||
if (!EG(return_value_ptr_ptr)) {
|
||||
if (IS_CV == IS_TMP_VAR) {
|
||||
|
||||
}
|
||||
} else if (!0) { /* Not a temp var */
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
zval_copy_ctor(ret);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
} else {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
retval_ptr_ptr = _get_zval_ptr_ptr_cv_BP_VAR_W(EX_CVs(), opline->op1.var TSRMLS_CC);
|
||||
@@ -23966,11 +24105,13 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
if (opline->extended_value == ZEND_RETURNS_FUNCTION &&
|
||||
EX_T(opline->op1.var).var.fcall_returned_reference) {
|
||||
} else if (EX_T(opline->op1.var).var.ptr_ptr == &EX_T(opline->op1.var).var.ptr) {
|
||||
if (IS_CV == IS_VAR && !0) {
|
||||
PZVAL_LOCK(*retval_ptr_ptr); /* undo the effect of get_zval_ptr_ptr() */
|
||||
}
|
||||
zend_error(E_NOTICE, "Only variable references should be returned by reference");
|
||||
goto return_by_value;
|
||||
if (EG(return_value_ptr_ptr)) {
|
||||
retval_ptr = *retval_ptr_ptr;
|
||||
*EG(return_value_ptr_ptr) = retval_ptr;
|
||||
Z_ADDREF_P(retval_ptr);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23978,43 +24119,11 @@ static int ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
SEPARATE_ZVAL_TO_MAKE_IS_REF(retval_ptr_ptr);
|
||||
Z_ADDREF_PP(retval_ptr_ptr);
|
||||
|
||||
(*EG(return_value_ptr_ptr)) = (*retval_ptr_ptr);
|
||||
*EG(return_value_ptr_ptr) = *retval_ptr_ptr;
|
||||
}
|
||||
} while (0);
|
||||
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
} else {
|
||||
return_by_value:
|
||||
|
||||
retval_ptr = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
|
||||
|
||||
if (!EG(return_value_ptr_ptr)) {
|
||||
if (IS_CV == IS_TMP_VAR) {
|
||||
|
||||
}
|
||||
} else if (!0) { /* Not a temp var */
|
||||
if (IS_CV == IS_CONST ||
|
||||
EG(active_op_array)->return_reference == ZEND_RETURN_REF ||
|
||||
(PZVAL_IS_REF(retval_ptr) && Z_REFCOUNT_P(retval_ptr) > 0)) {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
zval_copy_ctor(ret);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
} else {
|
||||
*EG(return_value_ptr_ptr) = retval_ptr;
|
||||
Z_ADDREF_P(retval_ptr);
|
||||
}
|
||||
} else {
|
||||
zval *ret;
|
||||
|
||||
ALLOC_ZVAL(ret);
|
||||
INIT_PZVAL_COPY(ret, retval_ptr);
|
||||
*EG(return_value_ptr_ptr) = ret;
|
||||
}
|
||||
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
}
|
||||
return zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU);
|
||||
}
|
||||
|
||||
static int ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
|
||||
@@ -35483,31 +35592,31 @@ void zend_init_opcodes_handlers(void)
|
||||
ZEND_CLONE_SPEC_CV_HANDLER,
|
||||
ZEND_CLONE_SPEC_CV_HANDLER,
|
||||
ZEND_CLONE_SPEC_CV_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_CV_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_CV_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_CV_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_CV_HANDLER,
|
||||
ZEND_RETURN_BY_REF_SPEC_CV_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
ZEND_NULL_HANDLER,
|
||||
|
||||
@@ -129,6 +129,7 @@
|
||||
#define ZEND_THROW 108
|
||||
#define ZEND_FETCH_CLASS 109
|
||||
#define ZEND_CLONE 110
|
||||
#define ZEND_RETURN_BY_REF 111
|
||||
#define ZEND_INIT_METHOD_CALL 112
|
||||
#define ZEND_INIT_STATIC_METHOD_CALL 113
|
||||
#define ZEND_ISSET_ISEMPTY_VAR 114
|
||||
|
||||
Reference in New Issue
Block a user