Skip to content

Commit 45f6b4c

Browse files
committed
- MFH Improved version of ternary shortcut (Marcus)
1 parent f83871a commit 45f6b4c

File tree

9 files changed

+203
-3
lines changed

9 files changed

+203
-3
lines changed

Zend/tests/021.phpt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,12 @@ var_dump($a ?: $b);
1616
var_dump($c ?: $d);
1717

1818
var_dump(1 ?: print(2));
19+
20+
$e = array();
21+
22+
$e['e'] = 'e';
23+
$e['e'] = $e['e'] ?: 'e';
24+
print_r($e);
1925
?>
2026
--EXPECT--
2127
bool(true)
@@ -25,3 +31,7 @@ string(3) "bar"
2531
int(23)
2632
float(23.5)
2733
int(1)
34+
Array
35+
(
36+
[e] => e
37+
)

Zend/zend_compile.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4332,6 +4332,43 @@ void zend_do_end_silence(znode *strudel_token TSRMLS_DC)
43324332
}
43334333

43344334

4335+
void zend_do_jmp_set(znode *value, znode *jmp_token, znode *colon_token TSRMLS_DC)
4336+
{
4337+
int op_number = get_next_op_number(CG(active_op_array));
4338+
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4339+
4340+
opline->opcode = ZEND_JMP_SET;
4341+
opline->result.op_type = IS_TMP_VAR;
4342+
opline->result.u.var = get_temporary_variable(CG(active_op_array));
4343+
opline->op1 = *value;
4344+
SET_UNUSED(opline->op2);
4345+
4346+
*colon_token = opline->result;
4347+
4348+
jmp_token->u.opline_num = op_number;
4349+
4350+
INC_BPC(CG(active_op_array));
4351+
}
4352+
4353+
4354+
void zend_do_jmp_set_else(znode *result, znode *false_value, znode *jmp_token, znode *colon_token TSRMLS_DC)
4355+
{
4356+
zend_op *opline = get_next_op(CG(active_op_array) TSRMLS_CC);
4357+
4358+
opline->opcode = ZEND_QM_ASSIGN;
4359+
opline->extended_value = 0;
4360+
opline->result = *colon_token;
4361+
opline->op1 = *false_value;
4362+
SET_UNUSED(opline->op2);
4363+
4364+
*result = opline->result;
4365+
4366+
CG(active_op_array)->opcodes[jmp_token->u.opline_num].op2.u.opline_num = get_next_op_number(CG(active_op_array));
4367+
4368+
DEC_BPC(CG(active_op_array));
4369+
}
4370+
4371+
43354372
void zend_do_begin_qm_op(znode *cond, znode *qm_token TSRMLS_DC)
43364373
{
43374374
int jmpz_op_number = get_next_op_number(CG(active_op_array));

Zend/zend_compile.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -491,6 +491,9 @@ void zend_do_exit(znode *result, znode *message TSRMLS_DC);
491491
void zend_do_begin_silence(znode *strudel_token TSRMLS_DC);
492492
void zend_do_end_silence(znode *strudel_token TSRMLS_DC);
493493

494+
void zend_do_jmp_set(znode *value, znode *jmp_token, znode *colon_token TSRMLS_DC);
495+
void zend_do_jmp_set_else(znode *result, znode *false_value, znode *jmp_token, znode *colon_token TSRMLS_DC);
496+
494497
void zend_do_begin_qm_op(znode *cond, znode *qm_token TSRMLS_DC);
495498
void zend_do_qm_true(znode *true_value, znode *qm_token, znode *colon_token TSRMLS_DC);
496499
void zend_do_qm_false(znode *result, znode *false_value, znode *qm_token, znode *colon_token TSRMLS_DC);

Zend/zend_execute_API.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1309,6 +1309,7 @@ void execute_new_code(TSRMLS_D) /* {{{ */
13091309
case ZEND_JMPNZ:
13101310
case ZEND_JMPZ_EX:
13111311
case ZEND_JMPNZ_EX:
1312+
case ZEND_JMP_SET:
13121313
opline->op2.u.jmp_addr = &CG(active_op_array)->opcodes[opline->op2.u.opline_num];
13131314
break;
13141315
}

Zend/zend_language_parser.y

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -611,9 +611,8 @@ expr_without_variable:
611611
| expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
612612
expr ':' { zend_do_qm_true(&$4, &$2, &$5 TSRMLS_CC); }
613613
expr { zend_do_qm_false(&$$, &$7, &$2, &$5 TSRMLS_CC); }
614-
| expr '?' { zend_do_begin_qm_op(&$1, &$2 TSRMLS_CC); }
615-
':' { zend_do_qm_true(&$1, &$2, &$4 TSRMLS_CC); }
616-
expr { zend_do_qm_false(&$$, &$6, &$2, &$4 TSRMLS_CC); }
614+
| expr '?' ':' { zend_do_jmp_set(&$1, &$2, &$3 TSRMLS_CC); }
615+
expr { zend_do_jmp_set_else(&$$, &$5, &$2, &$3 TSRMLS_CC); }
617616
| internal_functions_in_yacc { $$ = $1; }
618617
| T_INT_CAST expr { zend_do_cast(&$$, &$2, IS_LONG TSRMLS_CC); }
619618
| T_DOUBLE_CAST expr { zend_do_cast(&$$, &$2, IS_DOUBLE TSRMLS_CC); }

Zend/zend_opcode.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,7 @@ int pass_two(zend_op_array *op_array TSRMLS_DC)
395395
case ZEND_JMPNZ:
396396
case ZEND_JMPZ_EX:
397397
case ZEND_JMPNZ_EX:
398+
case ZEND_JMP_SET:
398399
opline->op2.u.jmp_addr = &op_array->opcodes[opline->op2.u.opline_num];
399400
break;
400401
}

Zend/zend_vm_def.h

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3749,6 +3749,26 @@ ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY)
37493749
ZEND_VM_NEXT_OPCODE();
37503750
}
37513751

3752+
ZEND_VM_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, ANY)
3753+
{
3754+
zend_op *opline = EX(opline);
3755+
zend_free_op free_op1;
3756+
zval *value = GET_OP1_ZVAL_PTR(BP_VAR_R);
3757+
3758+
if (i_zend_is_true(value)) {
3759+
EX_T(opline->result.u.var).tmp_var = *value;
3760+
zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
3761+
FREE_OP1();
3762+
#if DEBUG_ZEND>=2
3763+
printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
3764+
#endif
3765+
ZEND_VM_JMP(opline->op2.u.jmp_addr);
3766+
}
3767+
3768+
FREE_OP1();
3769+
ZEND_VM_NEXT_OPCODE();
3770+
}
3771+
37523772
ZEND_VM_HANDLER(22, ZEND_QM_ASSIGN, CONST|TMP|VAR|CV, ANY)
37533773
{
37543774
zend_op *opline = EX(opline);

Zend/zend_vm_execute.h

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2101,6 +2101,25 @@ static int ZEND_EXIT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
21012101
ZEND_VM_NEXT_OPCODE();
21022102
}
21032103

2104+
static int ZEND_JMP_SET_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
2105+
{
2106+
zend_op *opline = EX(opline);
2107+
2108+
zval *value = &opline->op1.u.constant;
2109+
2110+
if (i_zend_is_true(value)) {
2111+
EX_T(opline->result.u.var).tmp_var = *value;
2112+
zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
2113+
2114+
#if DEBUG_ZEND>=2
2115+
printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
2116+
#endif
2117+
ZEND_VM_JMP(opline->op2.u.jmp_addr);
2118+
}
2119+
2120+
ZEND_VM_NEXT_OPCODE();
2121+
}
2122+
21042123
static int ZEND_QM_ASSIGN_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
21052124
{
21062125
zend_op *opline = EX(opline);
@@ -5198,6 +5217,26 @@ static int ZEND_END_SILENCE_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
51985217
ZEND_VM_NEXT_OPCODE();
51995218
}
52005219

5220+
static int ZEND_JMP_SET_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
5221+
{
5222+
zend_op *opline = EX(opline);
5223+
zend_free_op free_op1;
5224+
zval *value = _get_zval_ptr_tmp(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
5225+
5226+
if (i_zend_is_true(value)) {
5227+
EX_T(opline->result.u.var).tmp_var = *value;
5228+
zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
5229+
zval_dtor(free_op1.var);
5230+
#if DEBUG_ZEND>=2
5231+
printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
5232+
#endif
5233+
ZEND_VM_JMP(opline->op2.u.jmp_addr);
5234+
}
5235+
5236+
zval_dtor(free_op1.var);
5237+
ZEND_VM_NEXT_OPCODE();
5238+
}
5239+
52015240
static int ZEND_QM_ASSIGN_SPEC_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
52025241
{
52035242
zend_op *opline = EX(opline);
@@ -8484,6 +8523,26 @@ static int ZEND_EXIT_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
84848523
ZEND_VM_NEXT_OPCODE();
84858524
}
84868525

8526+
static int ZEND_JMP_SET_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
8527+
{
8528+
zend_op *opline = EX(opline);
8529+
zend_free_op free_op1;
8530+
zval *value = _get_zval_ptr_var(&opline->op1, EX(Ts), &free_op1 TSRMLS_CC);
8531+
8532+
if (i_zend_is_true(value)) {
8533+
EX_T(opline->result.u.var).tmp_var = *value;
8534+
zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
8535+
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
8536+
#if DEBUG_ZEND>=2
8537+
printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
8538+
#endif
8539+
ZEND_VM_JMP(opline->op2.u.jmp_addr);
8540+
}
8541+
8542+
if (free_op1.var) {zval_ptr_dtor(&free_op1.var);};
8543+
ZEND_VM_NEXT_OPCODE();
8544+
}
8545+
84878546
static int ZEND_QM_ASSIGN_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
84888547
{
84898548
zend_op *opline = EX(opline);
@@ -21264,6 +21323,25 @@ static int ZEND_EXIT_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
2126421323
ZEND_VM_NEXT_OPCODE();
2126521324
}
2126621325

21326+
static int ZEND_JMP_SET_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
21327+
{
21328+
zend_op *opline = EX(opline);
21329+
21330+
zval *value = _get_zval_ptr_cv(&opline->op1, EX(Ts), BP_VAR_R TSRMLS_CC);
21331+
21332+
if (i_zend_is_true(value)) {
21333+
EX_T(opline->result.u.var).tmp_var = *value;
21334+
zendi_zval_copy_ctor(EX_T(opline->result.u.var).tmp_var);
21335+
21336+
#if DEBUG_ZEND>=2
21337+
printf("Conditional jmp to %d\n", opline->op2.u.opline_num);
21338+
#endif
21339+
ZEND_VM_JMP(opline->op2.u.jmp_addr);
21340+
}
21341+
21342+
ZEND_VM_NEXT_OPCODE();
21343+
}
21344+
2126721345
static int ZEND_QM_ASSIGN_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
2126821346
{
2126921347
zend_op *opline = EX(opline);
@@ -31709,6 +31787,56 @@ void zend_init_opcodes_handlers(void)
3170931787
ZEND_USER_OPCODE_SPEC_HANDLER,
3171031788
ZEND_USER_OPCODE_SPEC_HANDLER,
3171131789
ZEND_USER_OPCODE_SPEC_HANDLER,
31790+
ZEND_NULL_HANDLER,
31791+
ZEND_NULL_HANDLER,
31792+
ZEND_NULL_HANDLER,
31793+
ZEND_NULL_HANDLER,
31794+
ZEND_NULL_HANDLER,
31795+
ZEND_NULL_HANDLER,
31796+
ZEND_NULL_HANDLER,
31797+
ZEND_NULL_HANDLER,
31798+
ZEND_NULL_HANDLER,
31799+
ZEND_NULL_HANDLER,
31800+
ZEND_NULL_HANDLER,
31801+
ZEND_NULL_HANDLER,
31802+
ZEND_NULL_HANDLER,
31803+
ZEND_NULL_HANDLER,
31804+
ZEND_NULL_HANDLER,
31805+
ZEND_NULL_HANDLER,
31806+
ZEND_NULL_HANDLER,
31807+
ZEND_NULL_HANDLER,
31808+
ZEND_NULL_HANDLER,
31809+
ZEND_NULL_HANDLER,
31810+
ZEND_NULL_HANDLER,
31811+
ZEND_NULL_HANDLER,
31812+
ZEND_NULL_HANDLER,
31813+
ZEND_NULL_HANDLER,
31814+
ZEND_NULL_HANDLER,
31815+
ZEND_JMP_SET_SPEC_CONST_HANDLER,
31816+
ZEND_JMP_SET_SPEC_CONST_HANDLER,
31817+
ZEND_JMP_SET_SPEC_CONST_HANDLER,
31818+
ZEND_JMP_SET_SPEC_CONST_HANDLER,
31819+
ZEND_JMP_SET_SPEC_CONST_HANDLER,
31820+
ZEND_JMP_SET_SPEC_TMP_HANDLER,
31821+
ZEND_JMP_SET_SPEC_TMP_HANDLER,
31822+
ZEND_JMP_SET_SPEC_TMP_HANDLER,
31823+
ZEND_JMP_SET_SPEC_TMP_HANDLER,
31824+
ZEND_JMP_SET_SPEC_TMP_HANDLER,
31825+
ZEND_JMP_SET_SPEC_VAR_HANDLER,
31826+
ZEND_JMP_SET_SPEC_VAR_HANDLER,
31827+
ZEND_JMP_SET_SPEC_VAR_HANDLER,
31828+
ZEND_JMP_SET_SPEC_VAR_HANDLER,
31829+
ZEND_JMP_SET_SPEC_VAR_HANDLER,
31830+
ZEND_NULL_HANDLER,
31831+
ZEND_NULL_HANDLER,
31832+
ZEND_NULL_HANDLER,
31833+
ZEND_NULL_HANDLER,
31834+
ZEND_NULL_HANDLER,
31835+
ZEND_JMP_SET_SPEC_CV_HANDLER,
31836+
ZEND_JMP_SET_SPEC_CV_HANDLER,
31837+
ZEND_JMP_SET_SPEC_CV_HANDLER,
31838+
ZEND_JMP_SET_SPEC_CV_HANDLER,
31839+
ZEND_JMP_SET_SPEC_CV_HANDLER,
3171231840
ZEND_NULL_HANDLER
3171331841
};
3171431842
zend_opcode_handlers = (opcode_handler_t*)labels;

Zend/zend_vm_opcodes.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,3 +148,4 @@
148148
#define ZEND_ISSET_ISEMPTY_PROP_OBJ 148
149149
#define ZEND_HANDLE_EXCEPTION 149
150150
#define ZEND_USER_OPCODE 150
151+
#define ZEND_JMP_SET 152

0 commit comments

Comments
 (0)