lbarnaud                                 Tue, 18 Oct 2011 19:42:42 +0000

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

Log:
Improved ternary operator performance when returning arrays

Changed paths:
    U   php/php-src/branches/PHP_5_4/NEWS
    U   php/php-src/branches/PHP_5_4/Zend/micro_bench.php
    U   php/php-src/branches/PHP_5_4/Zend/zend_compile.c
    U   php/php-src/branches/PHP_5_4/Zend/zend_execute_API.c
    U   php/php-src/branches/PHP_5_4/Zend/zend_opcode.c
    U   php/php-src/branches/PHP_5_4/Zend/zend_vm_def.h
    U   php/php-src/branches/PHP_5_4/Zend/zend_vm_execute.h
    U   php/php-src/branches/PHP_5_4/Zend/zend_vm_opcodes.h
    U   php/php-src/trunk/Zend/micro_bench.php
    U   php/php-src/trunk/Zend/zend_compile.c
    U   php/php-src/trunk/Zend/zend_execute_API.c
    U   php/php-src/trunk/Zend/zend_opcode.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/branches/PHP_5_4/NEWS
===================================================================
--- php/php-src/branches/PHP_5_4/NEWS	2011-10-18 14:54:32 UTC (rev 318190)
+++ php/php-src/branches/PHP_5_4/NEWS	2011-10-18 19:42:42 UTC (rev 318191)
@@ -3,6 +3,7 @@
 ?? ??? 2011, PHP 5.4.0 RC1
 - General improvements:
   . Improve the warning message of incompatible arguments. (Laruence)
+  . Improve ternary operator performance when returning arrays. (Arnaud, Dmitry)


 - Core:

Modified: php/php-src/branches/PHP_5_4/Zend/micro_bench.php
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/micro_bench.php	2011-10-18 14:54:32 UTC (rev 318190)
+++ php/php-src/branches/PHP_5_4/Zend/micro_bench.php	2011-10-18 19:42:42 UTC (rev 318191)
@@ -202,6 +202,35 @@
 	}
 }

+function issetor($n) {
+	$val = array(0,1,2,3,4,5,6,7,8,9);
+	for ($i = 0; $i < $n; ++$i) {
+		$x = $val ?: null;
+	}
+}
+
+function issetor2($n) {
+	$f = false; $j = 0;
+	for ($i = 0; $i < $n; ++$i) {
+		$x = $f ?: $j + 1;
+	}
+}
+
+function ternary($n) {
+	$val = array(0,1,2,3,4,5,6,7,8,9);
+	$f = false;
+	for ($i = 0; $i < $n; ++$i) {
+		$x = $f ? null : $val;
+	}
+}
+
+function ternary2($n) {
+	$f = false; $j = 0;
+	for ($i = 0; $i < $n; ++$i) {
+		$x = $f ? $f : $j + 1;
+	}
+}
+
 /*****/

 function empty_loop($n) {
@@ -318,4 +347,12 @@
 $t = end_test($t, '$x = $hash[\'v\']', $overhead);
 read_str_offset(N);
 $t = end_test($t, '$x = $str[0]', $overhead);
+issetor(N);
+$t = end_test($t, '$x = $a ?: null', $overhead);
+issetor2(N);
+$t = end_test($t, '$x = $f ?: tmp', $overhead);
+ternary(N);
+$t = end_test($t, '$x = $f ? $f : $a', $overhead);
+ternary2(N);
+$t = end_test($t, '$x = $f ? $f : tmp', $overhead);
 total($t0, "Total");

Modified: php/php-src/branches/PHP_5_4/Zend/zend_compile.c
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/zend_compile.c	2011-10-18 14:54:32 UTC (rev 318190)
+++ php/php-src/branches/PHP_5_4/Zend/zend_compile.c	2011-10-18 19:42:42 UTC (rev 318191)
@@ -1469,7 +1469,8 @@
 			&& opline->result.var == op1->u.op.var) {
 			if (opline->opcode == ZEND_FETCH_R ||
 			    opline->opcode == ZEND_FETCH_DIM_R ||
-			    opline->opcode == ZEND_FETCH_OBJ_R) {
+			    opline->opcode == ZEND_FETCH_OBJ_R ||
+			    opline->opcode == ZEND_QM_ASSIGN_VAR) {
 				/* It's very rare and useless case. It's better to use
 				   additional FREE opcode and simplify the FETCH handlers
 				   their selves */
@@ -6308,8 +6309,13 @@
 	int op_number = get_next_op_number(CG(active_op_array));
 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);

-	opline->opcode = ZEND_JMP_SET;
-	opline->result_type = IS_TMP_VAR;
+	if (value->op_type == IS_VAR || value->op_type == IS_CV) {
+		opline->opcode = ZEND_JMP_SET_VAR;
+		opline->result_type = IS_VAR;
+	} else {
+		opline->opcode = ZEND_JMP_SET;
+		opline->result_type = IS_TMP_VAR;
+	}
 	opline->result.var = get_temporary_variable(CG(active_op_array));
 	SET_NODE(opline->op1, value);
 	SET_UNUSED(opline->op2);
@@ -6326,9 +6332,20 @@
 {
 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);

-	opline->opcode = ZEND_QM_ASSIGN;
+	SET_NODE(opline->result, colon_token);
+	if (colon_token->op_type == IS_TMP_VAR) {
+		if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) {
+			CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].opcode = ZEND_JMP_SET_VAR;
+			CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].result_type = IS_VAR;
+			opline->opcode = ZEND_QM_ASSIGN_VAR;
+			opline->result_type = IS_VAR;
+		} else {
+			opline->opcode = ZEND_QM_ASSIGN;
+		}
+	} else {
+		opline->opcode = ZEND_QM_ASSIGN_VAR;
+	}
 	opline->extended_value = 0;
-	SET_NODE(opline->result, colon_token);
 	SET_NODE(opline->op1, false_value);
 	SET_UNUSED(opline->op2);

@@ -6363,8 +6380,13 @@

 	CG(active_op_array)->opcodes[qm_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array))+1; /* jmp over the ZEND_JMP */

-	opline->opcode = ZEND_QM_ASSIGN;
-	opline->result_type = IS_TMP_VAR;
+	if (true_value->op_type == IS_VAR || true_value->op_type == IS_CV) {
+		opline->opcode = ZEND_QM_ASSIGN_VAR;
+		opline->result_type = IS_VAR;
+	} else {
+		opline->opcode = ZEND_QM_ASSIGN;
+		opline->result_type = IS_TMP_VAR;
+	}
 	opline->result.var = get_temporary_variable(CG(active_op_array));
 	SET_NODE(opline->op1, true_value);
 	SET_UNUSED(opline->op2);
@@ -6383,8 +6405,19 @@
 {
 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);

-	opline->opcode = ZEND_QM_ASSIGN;
 	SET_NODE(opline->result, qm_token);
+	if (qm_token->op_type == IS_TMP_VAR) {
+		if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) {
+			CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].opcode = ZEND_QM_ASSIGN_VAR;
+			CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].result_type = IS_VAR;
+			opline->opcode = ZEND_QM_ASSIGN_VAR;
+			opline->result_type = IS_VAR;
+		} else {
+			opline->opcode = ZEND_QM_ASSIGN;
+		}
+	} else {
+		opline->opcode = ZEND_QM_ASSIGN_VAR;
+	}
 	SET_NODE(opline->op1, false_value);
 	SET_UNUSED(opline->op2);


Modified: php/php-src/branches/PHP_5_4/Zend/zend_execute_API.c
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/zend_execute_API.c	2011-10-18 14:54:32 UTC (rev 318190)
+++ php/php-src/branches/PHP_5_4/Zend/zend_execute_API.c	2011-10-18 19:42:42 UTC (rev 318191)
@@ -1299,6 +1299,7 @@
 			case ZEND_JMPZ_EX:
 			case ZEND_JMPNZ_EX:
 			case ZEND_JMP_SET:
+			case ZEND_JMP_SET_VAR:
 				opline->op2.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.opline_num];
 				break;
 		}

Modified: php/php-src/branches/PHP_5_4/Zend/zend_opcode.c
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/zend_opcode.c	2011-10-18 14:54:32 UTC (rev 318190)
+++ php/php-src/branches/PHP_5_4/Zend/zend_opcode.c	2011-10-18 19:42:42 UTC (rev 318191)
@@ -529,6 +529,7 @@
 			case ZEND_JMPZ_EX:
 			case ZEND_JMPNZ_EX:
 			case ZEND_JMP_SET:
+			case ZEND_JMP_SET_VAR:
 				opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num];
 				break;
 		}

Modified: php/php-src/branches/PHP_5_4/Zend/zend_vm_def.h
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/zend_vm_def.h	2011-10-18 14:54:32 UTC (rev 318190)
+++ php/php-src/branches/PHP_5_4/Zend/zend_vm_def.h	2011-10-18 19:42:42 UTC (rev 318191)
@@ -4661,8 +4661,10 @@

 	if (i_zend_is_true(value)) {
 		ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
-		zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
-		FREE_OP1();
+		if (!IS_OP1_TMP_FREE()) {
+			zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		}
+		FREE_OP1_IF_VAR();
 #if DEBUG_ZEND>=2
 		printf("Conditional jmp to %d\n", opline->op2.opline_num);
 #endif
@@ -4674,6 +4676,41 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+ZEND_VM_HANDLER(158, ZEND_JMP_SET_VAR, CONST|TMP|VAR|CV, ANY)
+{
+	USE_OPLINE
+	zend_free_op free_op1;
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+	if (i_zend_is_true(value)) {
+		if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
+			Z_ADDREF_P(value);
+			EX_T(opline->result.var).var.ptr = value;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+		} else {
+			ALLOC_ZVAL(ret);
+			INIT_PZVAL_COPY(ret, value);
+			EX_T(opline->result.var).var.ptr = ret;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+			if (!IS_OP1_TMP_FREE()) {
+				zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+			}
+		}
+		FREE_OP1_IF_VAR();
+#if DEBUG_ZEND>=2
+		printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+		ZEND_VM_JMP(opline->op2.jmp_addr);
+	}
+
+	FREE_OP1();
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
 {
 	USE_OPLINE
@@ -4692,6 +4729,34 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+ZEND_VM_HANDLER(157, ZEND_QM_ASSIGN_VAR, CONST|TMP|VAR|CV, ANY)
+{
+	USE_OPLINE
+	zend_free_op free_op1;
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+	if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
+		Z_ADDREF_P(value);
+		EX_T(opline->result.var).var.ptr = value;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+	} else {
+		ALLOC_ZVAL(ret);
+		INIT_PZVAL_COPY(ret, value);
+		EX_T(opline->result.var).var.ptr = ret;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+		if (!IS_OP1_TMP_FREE()) {
+			zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+		}
+	}
+
+	FREE_OP1_IF_VAR();
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 ZEND_VM_HANDLER(101, ZEND_EXT_STMT, ANY, ANY)
 {
 	SAVE_OPLINE();

Modified: php/php-src/branches/PHP_5_4/Zend/zend_vm_execute.h
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/zend_vm_execute.h	2011-10-18 14:54:32 UTC (rev 318190)
+++ php/php-src/branches/PHP_5_4/Zend/zend_vm_execute.h	2011-10-18 19:42:42 UTC (rev 318191)
@@ -2836,7 +2836,9 @@

 	if (i_zend_is_true(value)) {
 		ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
-		zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		if (!0) {
+			zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		}

 #if DEBUG_ZEND>=2
 		printf("Conditional jmp to %d\n", opline->op2.opline_num);
@@ -2848,6 +2850,40 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = opline->op1.zv;
+
+	if (i_zend_is_true(value)) {
+		if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+			Z_ADDREF_P(value);
+			EX_T(opline->result.var).var.ptr = value;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+		} else {
+			ALLOC_ZVAL(ret);
+			INIT_PZVAL_COPY(ret, value);
+			EX_T(opline->result.var).var.ptr = ret;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+			if (!0) {
+				zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+			}
+		}
+
+#if DEBUG_ZEND>=2
+		printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+		ZEND_VM_JMP(opline->op2.jmp_addr);
+	}
+
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -2866,6 +2902,33 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = opline->op1.zv;
+
+	if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+		Z_ADDREF_P(value);
+		EX_T(opline->result.var).var.ptr = value;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+	} else {
+		ALLOC_ZVAL(ret);
+		INIT_PZVAL_COPY(ret, value);
+		EX_T(opline->result.var).var.ptr = ret;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+		if (!0) {
+			zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+		}
+	}
+
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -7132,8 +7195,10 @@

 	if (i_zend_is_true(value)) {
 		ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
-		zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
-		zval_dtor(free_op1.var);
+		if (!1) {
+			zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		}
+
 #if DEBUG_ZEND>=2
 		printf("Conditional jmp to %d\n", opline->op2.opline_num);
 #endif
@@ -7145,6 +7210,41 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+	zend_free_op free_op1;
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+	if (i_zend_is_true(value)) {
+		if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+			Z_ADDREF_P(value);
+			EX_T(opline->result.var).var.ptr = value;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+		} else {
+			ALLOC_ZVAL(ret);
+			INIT_PZVAL_COPY(ret, value);
+			EX_T(opline->result.var).var.ptr = ret;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+			if (!1) {
+				zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+			}
+		}
+
+#if DEBUG_ZEND>=2
+		printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+		ZEND_VM_JMP(opline->op2.jmp_addr);
+	}
+
+	zval_dtor(free_op1.var);
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -7163,6 +7263,33 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+	zend_free_op free_op1;
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+	if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+		Z_ADDREF_P(value);
+		EX_T(opline->result.var).var.ptr = value;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+	} else {
+		ALLOC_ZVAL(ret);
+		INIT_PZVAL_COPY(ret, value);
+		EX_T(opline->result.var).var.ptr = ret;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+		if (!1) {
+			zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+		}
+	}
+
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_INSTANCEOF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -11539,7 +11666,9 @@

 	if (i_zend_is_true(value)) {
 		ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
-		zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		if (!0) {
+			zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		}
 		if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
 #if DEBUG_ZEND>=2
 		printf("Conditional jmp to %d\n", opline->op2.opline_num);
@@ -11552,6 +11681,41 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+	zend_free_op free_op1;
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+	if (i_zend_is_true(value)) {
+		if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+			Z_ADDREF_P(value);
+			EX_T(opline->result.var).var.ptr = value;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+		} else {
+			ALLOC_ZVAL(ret);
+			INIT_PZVAL_COPY(ret, value);
+			EX_T(opline->result.var).var.ptr = ret;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+			if (!0) {
+				zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+			}
+		}
+		if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+#if DEBUG_ZEND>=2
+		printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+		ZEND_VM_JMP(opline->op2.jmp_addr);
+	}
+
+	if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -11570,6 +11734,34 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+	zend_free_op free_op1;
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+	if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+		Z_ADDREF_P(value);
+		EX_T(opline->result.var).var.ptr = value;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+	} else {
+		ALLOC_ZVAL(ret);
+		INIT_PZVAL_COPY(ret, value);
+		EX_T(opline->result.var).var.ptr = ret;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+		if (!0) {
+			zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+		}
+	}
+
+	if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_INSTANCEOF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -27127,7 +27319,9 @@

 	if (i_zend_is_true(value)) {
 		ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
-		zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		if (!0) {
+			zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		}

 #if DEBUG_ZEND>=2
 		printf("Conditional jmp to %d\n", opline->op2.opline_num);
@@ -27139,6 +27333,40 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_JMP_SET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+	if (i_zend_is_true(value)) {
+		if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+			Z_ADDREF_P(value);
+			EX_T(opline->result.var).var.ptr = value;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+		} else {
+			ALLOC_ZVAL(ret);
+			INIT_PZVAL_COPY(ret, value);
+			EX_T(opline->result.var).var.ptr = ret;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+			if (!0) {
+				zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+			}
+		}
+
+#if DEBUG_ZEND>=2
+		printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+		ZEND_VM_JMP(opline->op2.jmp_addr);
+	}
+
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -27157,6 +27385,33 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+	if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+		Z_ADDREF_P(value);
+		EX_T(opline->result.var).var.ptr = value;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+	} else {
+		ALLOC_ZVAL(ret);
+		INIT_PZVAL_COPY(ret, value);
+		EX_T(opline->result.var).var.ptr = ret;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+		if (!0) {
+			zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+		}
+	}
+
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_INSTANCEOF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -39759,6 +40014,56 @@
   	ZEND_NULL_HANDLER,
   	ZEND_NULL_HANDLER,
   	ZEND_NULL_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
   	ZEND_NULL_HANDLER
   };
   zend_opcode_handlers = (opcode_handler_t*)labels;

Modified: php/php-src/branches/PHP_5_4/Zend/zend_vm_opcodes.h
===================================================================
--- php/php-src/branches/PHP_5_4/Zend/zend_vm_opcodes.h	2011-10-18 14:54:32 UTC (rev 318190)
+++ php/php-src/branches/PHP_5_4/Zend/zend_vm_opcodes.h	2011-10-18 19:42:42 UTC (rev 318191)
@@ -157,3 +157,5 @@
 #define ZEND_ADD_TRAIT                       154
 #define ZEND_BIND_TRAITS                     155
 #define ZEND_SEPARATE                        156
+#define ZEND_QM_ASSIGN_VAR                   157
+#define ZEND_JMP_SET_VAR                     158

Modified: php/php-src/trunk/Zend/micro_bench.php
===================================================================
--- php/php-src/trunk/Zend/micro_bench.php	2011-10-18 14:54:32 UTC (rev 318190)
+++ php/php-src/trunk/Zend/micro_bench.php	2011-10-18 19:42:42 UTC (rev 318191)
@@ -202,6 +202,35 @@
 	}
 }

+function issetor($n) {
+	$val = array(0,1,2,3,4,5,6,7,8,9);
+	for ($i = 0; $i < $n; ++$i) {
+		$x = $val ?: null;
+	}
+}
+
+function issetor2($n) {
+	$f = false; $j = 0;
+	for ($i = 0; $i < $n; ++$i) {
+		$x = $f ?: $j + 1;
+	}
+}
+
+function ternary($n) {
+	$val = array(0,1,2,3,4,5,6,7,8,9);
+	$f = false;
+	for ($i = 0; $i < $n; ++$i) {
+		$x = $f ? null : $val;
+	}
+}
+
+function ternary2($n) {
+	$f = false; $j = 0;
+	for ($i = 0; $i < $n; ++$i) {
+		$x = $f ? $f : $j + 1;
+	}
+}
+
 /*****/

 function empty_loop($n) {
@@ -318,4 +347,12 @@
 $t = end_test($t, '$x = $hash[\'v\']', $overhead);
 read_str_offset(N);
 $t = end_test($t, '$x = $str[0]', $overhead);
+issetor(N);
+$t = end_test($t, '$x = $a ?: null', $overhead);
+issetor2(N);
+$t = end_test($t, '$x = $f ?: tmp', $overhead);
+ternary(N);
+$t = end_test($t, '$x = $f ? $f : $a', $overhead);
+ternary2(N);
+$t = end_test($t, '$x = $f ? $f : tmp', $overhead);
 total($t0, "Total");

Modified: php/php-src/trunk/Zend/zend_compile.c
===================================================================
--- php/php-src/trunk/Zend/zend_compile.c	2011-10-18 14:54:32 UTC (rev 318190)
+++ php/php-src/trunk/Zend/zend_compile.c	2011-10-18 19:42:42 UTC (rev 318191)
@@ -1469,7 +1469,8 @@
 			&& opline->result.var == op1->u.op.var) {
 			if (opline->opcode == ZEND_FETCH_R ||
 			    opline->opcode == ZEND_FETCH_DIM_R ||
-			    opline->opcode == ZEND_FETCH_OBJ_R) {
+			    opline->opcode == ZEND_FETCH_OBJ_R ||
+			    opline->opcode == ZEND_QM_ASSIGN_VAR) {
 				/* It's very rare and useless case. It's better to use
 				   additional FREE opcode and simplify the FETCH handlers
 				   their selves */
@@ -6308,8 +6309,13 @@
 	int op_number = get_next_op_number(CG(active_op_array));
 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);

-	opline->opcode = ZEND_JMP_SET;
-	opline->result_type = IS_TMP_VAR;
+	if (value->op_type == IS_VAR || value->op_type == IS_CV) {
+		opline->opcode = ZEND_JMP_SET_VAR;
+		opline->result_type = IS_VAR;
+	} else {
+		opline->opcode = ZEND_JMP_SET;
+		opline->result_type = IS_TMP_VAR;
+	}
 	opline->result.var = get_temporary_variable(CG(active_op_array));
 	SET_NODE(opline->op1, value);
 	SET_UNUSED(opline->op2);
@@ -6326,9 +6332,20 @@
 {
 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);

-	opline->opcode = ZEND_QM_ASSIGN;
+	SET_NODE(opline->result, colon_token);
+	if (colon_token->op_type == IS_TMP_VAR) {
+		if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) {
+			CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].opcode = ZEND_JMP_SET_VAR;
+			CG(active_op_array)->opcodes[jmp_token->u.op.opline_num].result_type = IS_VAR;
+			opline->opcode = ZEND_QM_ASSIGN_VAR;
+			opline->result_type = IS_VAR;
+		} else {
+			opline->opcode = ZEND_QM_ASSIGN;
+		}
+	} else {
+		opline->opcode = ZEND_QM_ASSIGN_VAR;
+	}
 	opline->extended_value = 0;
-	SET_NODE(opline->result, colon_token);
 	SET_NODE(opline->op1, false_value);
 	SET_UNUSED(opline->op2);

@@ -6363,8 +6380,13 @@

 	CG(active_op_array)->opcodes[qm_token->u.op.opline_num].op2.opline_num = get_next_op_number(CG(active_op_array))+1; /* jmp over the ZEND_JMP */

-	opline->opcode = ZEND_QM_ASSIGN;
-	opline->result_type = IS_TMP_VAR;
+	if (true_value->op_type == IS_VAR || true_value->op_type == IS_CV) {
+		opline->opcode = ZEND_QM_ASSIGN_VAR;
+		opline->result_type = IS_VAR;
+	} else {
+		opline->opcode = ZEND_QM_ASSIGN;
+		opline->result_type = IS_TMP_VAR;
+	}
 	opline->result.var = get_temporary_variable(CG(active_op_array));
 	SET_NODE(opline->op1, true_value);
 	SET_UNUSED(opline->op2);
@@ -6383,8 +6405,19 @@
 {
 	zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);

-	opline->opcode = ZEND_QM_ASSIGN;
 	SET_NODE(opline->result, qm_token);
+	if (qm_token->op_type == IS_TMP_VAR) {
+		if (false_value->op_type == IS_VAR || false_value->op_type == IS_CV) {
+			CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].opcode = ZEND_QM_ASSIGN_VAR;
+			CG(active_op_array)->opcodes[colon_token->u.op.opline_num - 1].result_type = IS_VAR;
+			opline->opcode = ZEND_QM_ASSIGN_VAR;
+			opline->result_type = IS_VAR;
+		} else {
+			opline->opcode = ZEND_QM_ASSIGN;
+		}
+	} else {
+		opline->opcode = ZEND_QM_ASSIGN_VAR;
+	}
 	SET_NODE(opline->op1, false_value);
 	SET_UNUSED(opline->op2);


Modified: php/php-src/trunk/Zend/zend_execute_API.c
===================================================================
--- php/php-src/trunk/Zend/zend_execute_API.c	2011-10-18 14:54:32 UTC (rev 318190)
+++ php/php-src/trunk/Zend/zend_execute_API.c	2011-10-18 19:42:42 UTC (rev 318191)
@@ -1299,6 +1299,7 @@
 			case ZEND_JMPZ_EX:
 			case ZEND_JMPNZ_EX:
 			case ZEND_JMP_SET:
+			case ZEND_JMP_SET_VAR:
 				opline->op2.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.opline_num];
 				break;
 		}

Modified: php/php-src/trunk/Zend/zend_opcode.c
===================================================================
--- php/php-src/trunk/Zend/zend_opcode.c	2011-10-18 14:54:32 UTC (rev 318190)
+++ php/php-src/trunk/Zend/zend_opcode.c	2011-10-18 19:42:42 UTC (rev 318191)
@@ -529,6 +529,7 @@
 			case ZEND_JMPZ_EX:
 			case ZEND_JMPNZ_EX:
 			case ZEND_JMP_SET:
+			case ZEND_JMP_SET_VAR:
 				opline->op2.jmp_addr = &op_array->opcodes[opline->op2.opline_num];
 				break;
 		}

Modified: php/php-src/trunk/Zend/zend_vm_def.h
===================================================================
--- php/php-src/trunk/Zend/zend_vm_def.h	2011-10-18 14:54:32 UTC (rev 318190)
+++ php/php-src/trunk/Zend/zend_vm_def.h	2011-10-18 19:42:42 UTC (rev 318191)
@@ -4661,8 +4661,10 @@

 	if (i_zend_is_true(value)) {
 		ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
-		zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
-		FREE_OP1();
+		if (!IS_OP1_TMP_FREE()) {
+			zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		}
+		FREE_OP1_IF_VAR();
 #if DEBUG_ZEND>=2
 		printf("Conditional jmp to %d\n", opline->op2.opline_num);
 #endif
@@ -4674,6 +4676,41 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+ZEND_VM_HANDLER(158, ZEND_JMP_SET_VAR, CONST|TMP|VAR|CV, ANY)
+{
+	USE_OPLINE
+	zend_free_op free_op1;
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+	if (i_zend_is_true(value)) {
+		if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
+			Z_ADDREF_P(value);
+			EX_T(opline->result.var).var.ptr = value;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+		} else {
+			ALLOC_ZVAL(ret);
+			INIT_PZVAL_COPY(ret, value);
+			EX_T(opline->result.var).var.ptr = ret;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+			if (!IS_OP1_TMP_FREE()) {
+				zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+			}
+		}
+		FREE_OP1_IF_VAR();
+#if DEBUG_ZEND>=2
+		printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+		ZEND_VM_JMP(opline->op2.jmp_addr);
+	}
+
+	FREE_OP1();
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
 {
 	USE_OPLINE
@@ -4692,6 +4729,34 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+ZEND_VM_HANDLER(157, ZEND_QM_ASSIGN_VAR, CONST|TMP|VAR|CV, ANY)
+{
+	USE_OPLINE
+	zend_free_op free_op1;
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+	if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) {
+		Z_ADDREF_P(value);
+		EX_T(opline->result.var).var.ptr = value;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+	} else {
+		ALLOC_ZVAL(ret);
+		INIT_PZVAL_COPY(ret, value);
+		EX_T(opline->result.var).var.ptr = ret;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+		if (!IS_OP1_TMP_FREE()) {
+			zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+		}
+	}
+
+	FREE_OP1_IF_VAR();
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 ZEND_VM_HANDLER(101, ZEND_EXT_STMT, ANY, ANY)
 {
 	SAVE_OPLINE();

Modified: php/php-src/trunk/Zend/zend_vm_execute.h
===================================================================
--- php/php-src/trunk/Zend/zend_vm_execute.h	2011-10-18 14:54:32 UTC (rev 318190)
+++ php/php-src/trunk/Zend/zend_vm_execute.h	2011-10-18 19:42:42 UTC (rev 318191)
@@ -2836,7 +2836,9 @@

 	if (i_zend_is_true(value)) {
 		ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
-		zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		if (!0) {
+			zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		}

 #if DEBUG_ZEND>=2
 		printf("Conditional jmp to %d\n", opline->op2.opline_num);
@@ -2848,6 +2850,40 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = opline->op1.zv;
+
+	if (i_zend_is_true(value)) {
+		if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+			Z_ADDREF_P(value);
+			EX_T(opline->result.var).var.ptr = value;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+		} else {
+			ALLOC_ZVAL(ret);
+			INIT_PZVAL_COPY(ret, value);
+			EX_T(opline->result.var).var.ptr = ret;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+			if (!0) {
+				zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+			}
+		}
+
+#if DEBUG_ZEND>=2
+		printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+		ZEND_VM_JMP(opline->op2.jmp_addr);
+	}
+
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -2866,6 +2902,33 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = opline->op1.zv;
+
+	if (IS_CONST == IS_VAR || IS_CONST == IS_CV) {
+		Z_ADDREF_P(value);
+		EX_T(opline->result.var).var.ptr = value;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+	} else {
+		ALLOC_ZVAL(ret);
+		INIT_PZVAL_COPY(ret, value);
+		EX_T(opline->result.var).var.ptr = ret;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+		if (!0) {
+			zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+		}
+	}
+
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_ADD_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -7132,8 +7195,10 @@

 	if (i_zend_is_true(value)) {
 		ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
-		zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
-		zval_dtor(free_op1.var);
+		if (!1) {
+			zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		}
+
 #if DEBUG_ZEND>=2
 		printf("Conditional jmp to %d\n", opline->op2.opline_num);
 #endif
@@ -7145,6 +7210,41 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+	zend_free_op free_op1;
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+	if (i_zend_is_true(value)) {
+		if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+			Z_ADDREF_P(value);
+			EX_T(opline->result.var).var.ptr = value;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+		} else {
+			ALLOC_ZVAL(ret);
+			INIT_PZVAL_COPY(ret, value);
+			EX_T(opline->result.var).var.ptr = ret;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+			if (!1) {
+				zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+			}
+		}
+
+#if DEBUG_ZEND>=2
+		printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+		ZEND_VM_JMP(opline->op2.jmp_addr);
+	}
+
+	zval_dtor(free_op1.var);
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -7163,6 +7263,33 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+	zend_free_op free_op1;
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = _get_zval_ptr_tmp(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+	if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) {
+		Z_ADDREF_P(value);
+		EX_T(opline->result.var).var.ptr = value;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+	} else {
+		ALLOC_ZVAL(ret);
+		INIT_PZVAL_COPY(ret, value);
+		EX_T(opline->result.var).var.ptr = ret;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+		if (!1) {
+			zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+		}
+	}
+
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_INSTANCEOF_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -11539,7 +11666,9 @@

 	if (i_zend_is_true(value)) {
 		ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
-		zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		if (!0) {
+			zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		}
 		if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
 #if DEBUG_ZEND>=2
 		printf("Conditional jmp to %d\n", opline->op2.opline_num);
@@ -11552,6 +11681,41 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+	zend_free_op free_op1;
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+	if (i_zend_is_true(value)) {
+		if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+			Z_ADDREF_P(value);
+			EX_T(opline->result.var).var.ptr = value;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+		} else {
+			ALLOC_ZVAL(ret);
+			INIT_PZVAL_COPY(ret, value);
+			EX_T(opline->result.var).var.ptr = ret;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+			if (!0) {
+				zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+			}
+		}
+		if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+#if DEBUG_ZEND>=2
+		printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+		ZEND_VM_JMP(opline->op2.jmp_addr);
+	}
+
+	if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -11570,6 +11734,34 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+	zend_free_op free_op1;
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = _get_zval_ptr_var(opline->op1.var, EX_Ts(), &free_op1 TSRMLS_CC);
+
+	if (IS_VAR == IS_VAR || IS_VAR == IS_CV) {
+		Z_ADDREF_P(value);
+		EX_T(opline->result.var).var.ptr = value;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+	} else {
+		ALLOC_ZVAL(ret);
+		INIT_PZVAL_COPY(ret, value);
+		EX_T(opline->result.var).var.ptr = ret;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+		if (!0) {
+			zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+		}
+	}
+
+	if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_INSTANCEOF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -27127,7 +27319,9 @@

 	if (i_zend_is_true(value)) {
 		ZVAL_COPY_VALUE(&EX_T(opline->result.var).tmp_var, value);
-		zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		if (!0) {
+			zendi_zval_copy_ctor(EX_T(opline->result.var).tmp_var);
+		}

 #if DEBUG_ZEND>=2
 		printf("Conditional jmp to %d\n", opline->op2.opline_num);
@@ -27139,6 +27333,40 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_JMP_SET_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+	if (i_zend_is_true(value)) {
+		if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+			Z_ADDREF_P(value);
+			EX_T(opline->result.var).var.ptr = value;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+		} else {
+			ALLOC_ZVAL(ret);
+			INIT_PZVAL_COPY(ret, value);
+			EX_T(opline->result.var).var.ptr = ret;
+			EX_T(opline->result.var).var.ptr_ptr = NULL;
+			if (!0) {
+				zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+			}
+		}
+
+#if DEBUG_ZEND>=2
+		printf("Conditional jmp to %d\n", opline->op2.opline_num);
+#endif
+		ZEND_VM_JMP(opline->op2.jmp_addr);
+	}
+
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -27157,6 +27385,33 @@
 	ZEND_VM_NEXT_OPCODE();
 }

+static int ZEND_FASTCALL  ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+	USE_OPLINE
+
+	zval *value, *ret;
+
+	SAVE_OPLINE();
+	value = _get_zval_ptr_cv_BP_VAR_R(EX_CVs(), opline->op1.var TSRMLS_CC);
+
+	if (IS_CV == IS_VAR || IS_CV == IS_CV) {
+		Z_ADDREF_P(value);
+		EX_T(opline->result.var).var.ptr = value;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+	} else {
+		ALLOC_ZVAL(ret);
+		INIT_PZVAL_COPY(ret, value);
+		EX_T(opline->result.var).var.ptr = ret;
+		EX_T(opline->result.var).var.ptr_ptr = NULL;
+		if (!0) {
+			zval_copy_ctor(EX_T(opline->result.var).var.ptr);
+		}
+	}
+
+	CHECK_EXCEPTION();
+	ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_FASTCALL  ZEND_INSTANCEOF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
 	USE_OPLINE
@@ -39759,6 +40014,56 @@
   	ZEND_NULL_HANDLER,
   	ZEND_NULL_HANDLER,
   	ZEND_NULL_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CONST_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_TMP_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_VAR_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
+  	ZEND_QM_ASSIGN_VAR_SPEC_CV_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CONST_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_TMP_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_VAR_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_NULL_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
+  	ZEND_JMP_SET_VAR_SPEC_CV_HANDLER,
   	ZEND_NULL_HANDLER
   };
   zend_opcode_handlers = (opcode_handler_t*)labels;

Modified: php/php-src/trunk/Zend/zend_vm_opcodes.h
===================================================================
--- php/php-src/trunk/Zend/zend_vm_opcodes.h	2011-10-18 14:54:32 UTC (rev 318190)
+++ php/php-src/trunk/Zend/zend_vm_opcodes.h	2011-10-18 19:42:42 UTC (rev 318191)
@@ -157,3 +157,5 @@
 #define ZEND_ADD_TRAIT                       154
 #define ZEND_BIND_TRAITS                     155
 #define ZEND_SEPARATE                        156
+#define ZEND_QM_ASSIGN_VAR                   157
+#define ZEND_JMP_SET_VAR                     158
-- 
PHP CVS Mailing List (http://www.php.net/)
To unsubscribe, visit: http://www.php.net/unsub.php

Reply via email to