dmitry                                   Thu, 22 Apr 2010 11:56:45 +0000

Revision: http://svn.php.net/viewvc?view=revision&revision=298315

Log:
ZEND_RETURN is splitted into two new instructions ZEND_RETURN and 
ZEND_RETURN_BY_REF

Changed paths:
    U   php/php-src/trunk/NEWS
    U   php/php-src/trunk/Zend/zend_compile.c
    U   php/php-src/trunk/Zend/zend_vm_def.h
    U   php/php-src/trunk/Zend/zend_vm_execute.h
    U   php/php-src/trunk/Zend/zend_vm_opcodes.h

Modified: php/php-src/trunk/NEWS
===================================================================
--- php/php-src/trunk/NEWS	2010-04-22 11:56:08 UTC (rev 298314)
+++ php/php-src/trunk/NEWS	2010-04-22 11:56:45 UTC (rev 298315)
@@ -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

Modified: php/php-src/trunk/Zend/zend_compile.c
===================================================================
--- php/php-src/trunk/Zend/zend_compile.c	2010-04-22 11:56:08 UTC (rev 298314)
+++ php/php-src/trunk/Zend/zend_compile.c	2010-04-22 11:56:45 UTC (rev 298315)
@@ -2439,7 +2439,7 @@

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

Modified: php/php-src/trunk/Zend/zend_vm_def.h
===================================================================
--- php/php-src/trunk/Zend/zend_vm_def.h	2010-04-22 11:56:08 UTC (rev 298314)
+++ php/php-src/trunk/Zend/zend_vm_def.h	2010-04-22 11:56:45 UTC (rev 298315)
@@ -2708,16 +2708,73 @@
 {
 	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;
 	zval **retval_ptr_ptr;
 	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 @@
 			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");
+				if (EG(return_value_ptr_ptr)) {
+					retval_ptr = *retval_ptr_ptr;
+					*EG(return_value_ptr_ptr) = retval_ptr;
+					Z_ADDREF_P(retval_ptr);
 				}
-				zend_error(E_NOTICE, "Only variable references should be returned by reference");
-				ZEND_VM_C_GOTO(return_by_value);
+				break;
 			}
 		}

@@ -2742,43 +2801,12 @@
 			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)

Modified: php/php-src/trunk/Zend/zend_vm_execute.h
===================================================================
--- php/php-src/trunk/Zend/zend_vm_execute.h	2010-04-22 11:56:08 UTC (rev 298314)
+++ php/php-src/trunk/Zend/zend_vm_execute.h	2010-04-22 11:56:45 UTC (rev 298315)
@@ -1768,16 +1768,73 @@
 {
 	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;
 	zval **retval_ptr_ptr;


 	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 @@
 			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");
+				if (EG(return_value_ptr_ptr)) {
+					retval_ptr = *retval_ptr_ptr;
+					*EG(return_value_ptr_ptr) = retval_ptr;
+					Z_ADDREF_P(retval_ptr);
 				}
-				zend_error(E_NOTICE, "Only variable references should be returned by reference");
-				goto return_by_value;
+				break;
 			}
 		}

@@ -1802,43 +1861,11 @@
 			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)
@@ -5308,16 +5335,73 @@
 {
 	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;
 	zval **retval_ptr_ptr;
 	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 @@
 			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");
+				if (EG(return_value_ptr_ptr)) {
+					retval_ptr = *retval_ptr_ptr;
+					*EG(return_value_ptr_ptr) = retval_ptr;
+					Z_ADDREF_P(retval_ptr);
 				}
-				zend_error(E_NOTICE, "Only variable references should be returned by reference");
-				goto return_by_value;
+				break;
 			}
 		}

@@ -5342,43 +5428,11 @@
 			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)
@@ -8831,16 +8885,73 @@
 {
 	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;
 	zval **retval_ptr_ptr;
 	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 @@
 			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");
+				if (EG(return_value_ptr_ptr)) {
+					retval_ptr = *retval_ptr_ptr;
+					*EG(return_value_ptr_ptr) = retval_ptr;
+					Z_ADDREF_P(retval_ptr);
 				}
-				zend_error(E_NOTICE, "Only variable references should be returned by reference");
-				goto return_by_value;
+				break;
 			}
 		}

@@ -8865,43 +8978,12 @@
 			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)
@@ -23944,16 +24026,73 @@
 {
 	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;
 	zval **retval_ptr_ptr;


 	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 @@
 			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");
+				if (EG(return_value_ptr_ptr)) {
+					retval_ptr = *retval_ptr_ptr;
+					*EG(return_value_ptr_ptr) = retval_ptr;
+					Z_ADDREF_P(retval_ptr);
 				}
-				zend_error(E_NOTICE, "Only variable references should be returned by reference");
-				goto return_by_value;
+				break;
 			}
 		}

@@ -23978,43 +24119,11 @@
 			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,36 +35592,36 @@
   	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_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,
   	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_INIT_METHOD_CALL_SPEC_TMP_CONST_HANDLER,
   	ZEND_INIT_METHOD_CALL_SPEC_TMP_TMP_HANDLER,
   	ZEND_INIT_METHOD_CALL_SPEC_TMP_VAR_HANDLER,

Modified: php/php-src/trunk/Zend/zend_vm_opcodes.h
===================================================================
--- php/php-src/trunk/Zend/zend_vm_opcodes.h	2010-04-22 11:56:08 UTC (rev 298314)
+++ php/php-src/trunk/Zend/zend_vm_opcodes.h	2010-04-22 11:56:45 UTC (rev 298315)
@@ -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
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to