]> granicus.if.org Git - php/commitdiff
- MFH Improved version of ternary shortcut (Marcus)
authorJohannes Schlüter <johannes@php.net>
Wed, 21 Nov 2007 09:41:35 +0000 (09:41 +0000)
committerJohannes Schlüter <johannes@php.net>
Wed, 21 Nov 2007 09:41:35 +0000 (09:41 +0000)
Zend/tests/021.phpt
Zend/zend_compile.c
Zend/zend_compile.h
Zend/zend_execute_API.c
Zend/zend_language_parser.y
Zend/zend_opcode.c
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_opcodes.h

index 99fdb50258d7f07682ffcb0a51793012204e29fc..a40a41100baecadb60b0f915ecd42fb58000d599 100644 (file)
@@ -16,6 +16,12 @@ var_dump($a ?: $b);
 var_dump($c ?: $d);
 
 var_dump(1 ?: print(2));
+
+$e = array();
+
+$e['e'] = 'e';
+$e['e'] = $e['e'] ?: 'e';
+print_r($e);
 ?>
 --EXPECT--
 bool(true)
@@ -25,3 +31,7 @@ string(3) "bar"
 int(23)
 float(23.5)
 int(1)
+Array
+(
+    [e] => e
+)
index 31373c71c2b89596366054103711267ea661a3cd..761e56b3ccad0af2109c648fb4e12009456f5b9d 100644 (file)
@@ -4332,6 +4332,43 @@ void zend_do_end_silence(znode *strudel_token TSRMLS_DC)
 }
 
 
+void zend_do_jmp_set(znode *value, znode *jmp_token, znode *colon_token TSRMLS_DC)
+{
+       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.op_type = IS_TMP_VAR;
+       opline->result.u.var = get_temporary_variable(CG(active_op_array));
+       opline->op1 = *value;
+       SET_UNUSED(opline->op2);
+       
+       *colon_token = opline->result;
+
+       jmp_token->u.opline_num = op_number;
+
+       INC_BPC(CG(active_op_array));
+}
+
+
+void zend_do_jmp_set_else(znode *result, znode *false_value, znode *jmp_token, znode *colon_token TSRMLS_DC)
+{
+       zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
+
+       opline->opcode = ZEND_QM_ASSIGN;
+       opline->extended_value = 0;
+       opline->result = *colon_token;
+       opline->op1 = *false_value;
+       SET_UNUSED(opline->op2);
+       
+       *result = opline->result;
+
+       CG(active_op_array)->opcodes[jmp_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
+       
+       DEC_BPC(CG(active_op_array));
+}
+
+
 void zend_do_begin_qm_op(znode *cond, znode *qm_token TSRMLS_DC)
 {
        int jmpz_op_number = get_next_op_number(CG(active_op_array));
index b2ab1ae5abcb2eeaef32cb6917f20f148f0acfa6..9056c1bb1db72df302daded3aeb2d2b06a090ecb 100644 (file)
@@ -491,6 +491,9 @@ void zend_do_exit(znode *result, znode *message TSRMLS_DC);
 void zend_do_begin_silence(znode *strudel_token TSRMLS_DC);
 void zend_do_end_silence(znode *strudel_token TSRMLS_DC);
 
+void zend_do_jmp_set(znode *value, znode *jmp_token, znode *colon_token TSRMLS_DC);
+void zend_do_jmp_set_else(znode *result, znode *false_value, znode *jmp_token, znode *colon_token TSRMLS_DC);
+
 void zend_do_begin_qm_op(znode *cond, znode *qm_token TSRMLS_DC);
 void zend_do_qm_true(znode *true_value, znode *qm_token, znode *colon_token TSRMLS_DC);
 void zend_do_qm_false(znode *result, znode *false_value, znode *qm_token, znode *colon_token TSRMLS_DC);
index c3169c430ad0885e68d79b0b7c0284cba573db47..fdff4d9acccce97b3f1ae33452367ffe95e6048d 100644 (file)
@@ -1309,6 +1309,7 @@ void execute_new_code(TSRMLS_D) /* {{{ */
                        case ZEND_JMPNZ:
                        case ZEND_JMPZ_EX:
                        case ZEND_JMPNZ_EX:
+                       case ZEND_JMP_SET:
                                opline->op2.u.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.u.opline_num];
                                break;
                }
index 2b32b3a35feb58204fc26ffa07ea86df6494715b..343f81d3b3807458167d5230d4b17c78f8b01b4f 100644 (file)
@@ -611,9 +611,8 @@ expr_without_variable:
        |       expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
                expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); }
                expr     { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); }
-       |       expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
-               ':'      { zend_do_qm_true(&$1, &$2, &$4 TSRMLS_CC); }
-               expr     { zend_do_qm_false(&$$, &$6, &$2, &$4 TSRMLS_CC); }
+       |       expr '?' ':' { zend_do_jmp_set(&$1, &$2, &$3 TSRMLS_CC); }
+               expr     { zend_do_jmp_set_else(&$$, &$5, &$2, &$3 TSRMLS_CC); }
        |       internal_functions_in_yacc { $$ = $1; }
        |       T_INT_CAST expr         { zend_do_cast(&$$, &$2, IS_LONG TSRMLS_CC); }
        |       T_DOUBLE_CAST expr      { zend_do_cast(&$$, &$2, IS_DOUBLE TSRMLS_CC); }
index edabb98ada61d3245729af6638e91ba9c001193d..a30af32be5a02f44be303dc4e8cc8cce37a94706 100644 (file)
@@ -395,6 +395,7 @@ int pass_two(zend_op_array *op_array TSRMLS_DC)
                        case ZEND_JMPNZ:
                        case ZEND_JMPZ_EX:
                        case ZEND_JMPNZ_EX:
+                       case ZEND_JMP_SET:
                                opline->op2.u.jmp_addr = &op_array->opcodes[opline->op2.u.opline_num];
                                break;
                }
index ef18499924afd6c9f48b4df80ff5c179636b6924..2597acec069670e1ad9d4a4a664822f24535f3d9 100644 (file)
@@ -3749,6 +3749,26 @@ ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY)
        ZEND_VM_NEXT_OPCODE();
 }
 
+ZEND_VM_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, ANY)
+{
+       zend_op *opline = EX(opline);
+       zend_free_op free_op1;
+       zval *value = GET_OP1_ZVAL_PTR(BP_VAR_R);
+
+       if (i_zend_is_true(value)) {
+               EX_T(opline->result.u.var).tmp_var = *value;
+               zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
+               FREE_OP1();
+#if DEBUG_ZEND>=2
+               printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+#endif
+               ZEND_VM_JMP(opline->op2.u.jmp_addr);
+       }
+
+       FREE_OP1();
+       ZEND_VM_NEXT_OPCODE();
+}
+
 ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
 {
        zend_op *opline = EX(opline);
index e98a83f3241cbd7af311425d5ae699f19c3f55bb..5d9f3a2cae35541a3c16bb2db6451f887b601cd7 100644 (file)
@@ -2101,6 +2101,25 @@ static int ZEND_EXIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_JMP_SET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       zend_op *opline = EX(opline);
+
+       zval *value = &opline->op1.u.constant;
+
+       if (i_zend_is_true(value)) {
+               EX_T(opline->result.u.var).tmp_var = *value;
+               zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
+
+#if DEBUG_ZEND>=2
+               printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+#endif
+               ZEND_VM_JMP(opline->op2.u.jmp_addr);
+       }
+
+       ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
@@ -5198,6 +5217,26 @@ static int ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       zend_op *opline = EX(opline);
+       zend_free_op free_op1;
+       zval *value = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+
+       if (i_zend_is_true(value)) {
+               EX_T(opline->result.u.var).tmp_var = *value;
+               zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
+               zval_dtor(free_op1.var);
+#if DEBUG_ZEND>=2
+               printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+#endif
+               ZEND_VM_JMP(opline->op2.u.jmp_addr);
+       }
+
+       zval_dtor(free_op1.var);
+       ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
@@ -8484,6 +8523,26 @@ static int ZEND_EXIT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       zend_op *opline = EX(opline);
+       zend_free_op free_op1;
+       zval *value = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
+
+       if (i_zend_is_true(value)) {
+               EX_T(opline->result.u.var).tmp_var = *value;
+               zendi_zval_copy_ctor(EX_T(opline->result.u.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.u.opline_num);
+#endif
+               ZEND_VM_JMP(opline->op2.u.jmp_addr);
+       }
+
+       if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
+       ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
@@ -21264,6 +21323,25 @@ static int ZEND_EXIT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
        ZEND_VM_NEXT_OPCODE();
 }
 
+static int ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+       zend_op *opline = EX(opline);
+
+       zval *value = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
+
+       if (i_zend_is_true(value)) {
+               EX_T(opline->result.u.var).tmp_var = *value;
+               zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
+
+#if DEBUG_ZEND>=2
+               printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
+#endif
+               ZEND_VM_JMP(opline->op2.u.jmp_addr);
+       }
+
+       ZEND_VM_NEXT_OPCODE();
+}
+
 static int ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
 {
        zend_op *opline = EX(opline);
@@ -31709,6 +31787,56 @@ void zend_init_opcodes_handlers(void)
        ZEND_USER_OPCODE_SPEC_HANDLER,
        ZEND_USER_OPCODE_SPEC_HANDLER,
        ZEND_USER_OPCODE_SPEC_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_JMP_SET_SPEC_CONST_HANDLER,
+       ZEND_JMP_SET_SPEC_CONST_HANDLER,
+       ZEND_JMP_SET_SPEC_CONST_HANDLER,
+       ZEND_JMP_SET_SPEC_CONST_HANDLER,
+       ZEND_JMP_SET_SPEC_CONST_HANDLER,
+       ZEND_JMP_SET_SPEC_TMP_HANDLER,
+       ZEND_JMP_SET_SPEC_TMP_HANDLER,
+       ZEND_JMP_SET_SPEC_TMP_HANDLER,
+       ZEND_JMP_SET_SPEC_TMP_HANDLER,
+       ZEND_JMP_SET_SPEC_TMP_HANDLER,
+       ZEND_JMP_SET_SPEC_VAR_HANDLER,
+       ZEND_JMP_SET_SPEC_VAR_HANDLER,
+       ZEND_JMP_SET_SPEC_VAR_HANDLER,
+       ZEND_JMP_SET_SPEC_VAR_HANDLER,
+       ZEND_JMP_SET_SPEC_VAR_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_NULL_HANDLER,
+       ZEND_JMP_SET_SPEC_CV_HANDLER,
+       ZEND_JMP_SET_SPEC_CV_HANDLER,
+       ZEND_JMP_SET_SPEC_CV_HANDLER,
+       ZEND_JMP_SET_SPEC_CV_HANDLER,
+       ZEND_JMP_SET_SPEC_CV_HANDLER,
        ZEND_NULL_HANDLER
   };
   zend_opcode_handlers = (opcode_handler_t*)labels;
index 82fbeda4f453abb75a046421018dcdda758cbd21..d663ea6d5559a845a820c9cd225bf92497bbad43 100644 (file)
 #define ZEND_ISSET_ISEMPTY_PROP_OBJ  148
 #define ZEND_HANDLE_EXCEPTION        149
 #define ZEND_USER_OPCODE             150
+#define ZEND_JMP_SET                 152