]> granicus.if.org Git - php/commitdiff
Improved ternary operator performance when returning arrays
authorArnaud Le Blanc <lbarnaud@php.net>
Tue, 18 Oct 2011 19:42:42 +0000 (19:42 +0000)
committerArnaud Le Blanc <lbarnaud@php.net>
Tue, 18 Oct 2011 19:42:42 +0000 (19:42 +0000)
NEWS
Zend/micro_bench.php
Zend/zend_compile.c
Zend/zend_execute_API.c
Zend/zend_opcode.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_opcodes.h

diff --git a/NEWS b/NEWS
index 6fe03ac40fe91d64c3eff45348474b4a41e8918c..9c8c2f5e712dc16db7c03cb2de0a6af5967b0191 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -3,6 +3,7 @@ PHP                                                                        NEWS
 ?? ??? 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:
index 87a1b158c22a1425268505083af993d76f83595d..70525882ebad93a9731a96faf6d2bc741209f4ca 100644 (file)
@@ -202,6 +202,35 @@ function read_str_offset($n) {
        }
 }
 
+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 @@ read_hash(N);
 $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");
index a9eb91a9744446dcbcf5cf3f4aaa6c3f8676cec7..727380dac9a484d37cf20cfe5874777d71cb2ad5 100644 (file)
@@ -1469,7 +1469,8 @@ void zend_do_free(znode *op1 TSRMLS_DC) /* {{{ */
                        && 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 @@ void zend_do_jmp_set(const znode *value, znode *jmp_token, znode *colon_token TS
        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 @@ void zend_do_jmp_set_else(znode *result, const znode *false_value, const znode *
 {
        zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
 
-       opline->opcode = ZEND_QM_ASSIGN;
-       opline->extended_value = 0;
        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->op1, false_value);
        SET_UNUSED(opline->op2);
        
@@ -6363,8 +6380,13 @@ void zend_do_qm_true(const znode *true_value, znode *qm_token, znode *colon_toke
 
        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 @@ void zend_do_qm_false(znode *result, const znode *false_value, const znode *qm_t
 {
        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);
 
index 5ae15f40e0a9ba7b47c8aec77c5f4ab894ef1567..888058de98df5c1fed8b8df38d48945dcae061b5 100644 (file)
@@ -1299,6 +1299,7 @@ void execute_new_code(TSRMLS_D) /* {{{ */
                        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;
                }
index 9d4f3e715f93220391913d3586f3ff8c4d3f1702..65b9aa5fc007a9a195ef7dc0ad63df1ea8a1da97 100644 (file)
@@ -529,6 +529,7 @@ ZEND_API int pass_two(zend_op_array *op_array TSRMLS_DC)
                        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;
                }
index 4e944a13509e56b8534ee6b22f0d884df6b943d3..238864ec7a71cf329ac497ebfd70739f60103f7e 100644 (file)
@@ -4661,8 +4661,45 @@ ZEND_VM_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, ANY)
 
        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
+               ZEND_VM_JMP(opline->op2.jmp_addr);
+       }
+
+       FREE_OP1();
+       CHECK_EXCEPTION();
+       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
@@ -4692,6 +4729,34 @@ ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
        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();
index af40d57d0ebf17413b51d02cd9d7957f853119a8..d90053a55eb7611b2132eb4493410ae17533aae0 100644 (file)
@@ -2836,7 +2836,43 @@ static int ZEND_FASTCALL  ZEND_JMP_SET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_AR
 
        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);
+#endif
+               ZEND_VM_JMP(opline->op2.jmp_addr);
+       }
+
+       CHECK_EXCEPTION();
+       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);
@@ -2866,6 +2902,33 @@ static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_
        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,45 @@ static int ZEND_FASTCALL  ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS
 
        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
+               ZEND_VM_JMP(opline->op2.jmp_addr);
+       }
+
+       zval_dtor(free_op1.var);
+       CHECK_EXCEPTION();
+       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
@@ -7163,6 +7263,33 @@ static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_AR
        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,44 @@ static int ZEND_FASTCALL  ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS
 
        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);
+#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_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);
@@ -11570,6 +11734,34 @@ static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_AR
        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,43 @@ static int ZEND_FASTCALL  ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 
        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);
+#endif
+               ZEND_VM_JMP(opline->op2.jmp_addr);
+       }
+
+       CHECK_EXCEPTION();
+       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);
@@ -27157,6 +27385,33 @@ static int ZEND_FASTCALL  ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARG
        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 @@ void zend_init_opcodes_handlers(void)
        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;
index ed80ddc7a5142afe5e72ea317bb61ba3625ff29b..9b76b0eb34a799ca7ce4fe00a654a7ed1144f99a 100644 (file)
 #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