Skip to content

Commit afc93e4

Browse files
committed
JIT for ZEND_ISSET_ISEMPTY_CV
1 parent 28e24e7 commit afc93e4

File tree

3 files changed

+132
-0
lines changed

3 files changed

+132
-0
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2790,6 +2790,33 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
27902790
goto jit_failure;
27912791
}
27922792
goto done;
2793+
case ZEND_ISSET_ISEMPTY_CV:
2794+
if ((opline->extended_value & ZEND_ISEMPTY)) {
2795+
// TODO: support for empty() ???
2796+
break;
2797+
}
2798+
if ((opline->result_type & IS_TMP_VAR)
2799+
&& (i + 1) <= end
2800+
&& ((opline+1)->opcode == ZEND_JMPZ
2801+
|| (opline+1)->opcode == ZEND_JMPNZ
2802+
|| (opline+1)->opcode == ZEND_JMPZNZ)
2803+
&& (opline+1)->op1_type == IS_TMP_VAR
2804+
&& (opline+1)->op1.var == opline->result.var) {
2805+
i++;
2806+
smart_branch_opcode = (opline+1)->opcode;
2807+
target_label = ssa->cfg.blocks[b].successors[0];
2808+
target_label2 = ssa->cfg.blocks[b].successors[1];
2809+
} else {
2810+
smart_branch_opcode = 0;
2811+
target_label = target_label2 = (uint32_t)-1;
2812+
}
2813+
if (!zend_jit_isset_isempty_cv(&dasm_state, opline, op_array,
2814+
OP1_INFO(), OP1_REG_ADDR(),
2815+
smart_branch_opcode, target_label, target_label2,
2816+
NULL)) {
2817+
goto jit_failure;
2818+
}
2819+
goto done;
27932820
case ZEND_FETCH_DIM_R:
27942821
case ZEND_FETCH_DIM_IS:
27952822
if (PROFITABILITY_CHECKS && (!ssa->ops || !ssa->var_info)) {

ext/opcache/jit/zend_jit_trace.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1486,6 +1486,7 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
14861486
case ZEND_JMPNZ_EX:
14871487
case ZEND_BOOL:
14881488
case ZEND_BOOL_NOT:
1489+
case ZEND_ISSET_ISEMPTY_CV:
14891490
ADD_OP1_TRACE_GUARD();
14901491
break;
14911492
case ZEND_ISSET_ISEMPTY_DIM_OBJ:
@@ -3912,6 +3913,41 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
39123913
goto jit_failure;
39133914
}
39143915
goto done;
3916+
case ZEND_ISSET_ISEMPTY_CV:
3917+
if ((opline->extended_value & ZEND_ISEMPTY)) {
3918+
// TODO: support for empty() ???
3919+
break;
3920+
}
3921+
op1_info = OP1_INFO();
3922+
op1_addr = OP1_REG_ADDR();
3923+
if (orig_op1_type != IS_UNKNOWN
3924+
&& (orig_op1_type & IS_TRACE_REFERENCE)) {
3925+
if (!zend_jit_fetch_reference(&dasm_state, opline, orig_op1_type, &op1_info, &op1_addr, 1)) {
3926+
goto jit_failure;
3927+
}
3928+
} else {
3929+
CHECK_OP1_TRACE_TYPE();
3930+
}
3931+
if ((opline->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0) {
3932+
zend_bool exit_if_true = 0;
3933+
const zend_op *exit_opline = zend_jit_trace_get_exit_opline(p + 1, opline + 1, &exit_if_true);
3934+
uint32_t exit_point = zend_jit_trace_get_exit_point(opline, exit_opline, p + 1, 0);
3935+
3936+
exit_addr = zend_jit_trace_get_exit_addr(exit_point);
3937+
if (!exit_addr) {
3938+
goto jit_failure;
3939+
}
3940+
smart_branch_opcode = exit_if_true ? ZEND_JMPNZ : ZEND_JMPZ;
3941+
} else {
3942+
smart_branch_opcode = 0;
3943+
exit_addr = NULL;
3944+
}
3945+
if (!zend_jit_isset_isempty_cv(&dasm_state, opline, op_array,
3946+
op1_info, op1_addr,
3947+
smart_branch_opcode, -1, -1, exit_addr)) {
3948+
goto jit_failure;
3949+
}
3950+
goto done;
39153951
case ZEND_FETCH_DIM_FUNC_ARG:
39163952
if (!JIT_G(current_frame)
39173953
|| !JIT_G(current_frame)->call

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12159,6 +12159,75 @@ static zend_bool zend_jit_verify_return_type(dasm_State **Dst, const zend_op *op
1215912159
return 1;
1216012160
}
1216112161

12162+
static int zend_jit_isset_isempty_cv(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array, uint32_t op1_info, zend_jit_addr op1_addr, zend_uchar smart_branch_opcode, uint32_t target_label, uint32_t target_label2, const void *exit_addr)
12163+
{
12164+
zend_jit_addr res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
12165+
12166+
// TODO: support for empty() ???
12167+
ZEND_ASSERT(!(opline->extended_value & ZEND_ISEMPTY));
12168+
12169+
if (op1_info & MAY_BE_REF) {
12170+
if (Z_MODE(op1_addr) != IS_MEM_ZVAL || Z_REG(op1_addr) != ZREG_FCARG1a || Z_OFFSET(op1_addr) != 0) {
12171+
| LOAD_ZVAL_ADDR FCARG1a, op1_addr
12172+
op1_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FCARG1a, 0);
12173+
}
12174+
| ZVAL_DEREF FCARG1a, op1_info
12175+
|1:
12176+
}
12177+
12178+
if (!(op1_info & (MAY_BE_UNDEF|MAY_BE_NULL))) {
12179+
if (exit_addr) {
12180+
ZEND_ASSERT(smart_branch_opcode == ZEND_JMPZ);
12181+
} else if (smart_branch_opcode) {
12182+
if (smart_branch_opcode == ZEND_JMPNZ) {
12183+
| jmp =>target_label
12184+
} else if (smart_branch_opcode == ZEND_JMPZNZ) {
12185+
| jmp =>target_label2
12186+
}
12187+
} else {
12188+
| SET_ZVAL_TYPE_INFO res_addr, IS_TRUE
12189+
}
12190+
} else if (!(op1_info & (MAY_BE_ANY - MAY_BE_NULL))) {
12191+
if (exit_addr) {
12192+
ZEND_ASSERT(smart_branch_opcode == ZEND_JMPNZ);
12193+
} else if (smart_branch_opcode) {
12194+
if (smart_branch_opcode != ZEND_JMPNZ) {
12195+
| jmp =>target_label
12196+
}
12197+
} else {
12198+
| SET_ZVAL_TYPE_INFO res_addr, IS_FALSE
12199+
}
12200+
} else {
12201+
ZEND_ASSERT(Z_MODE(op1_addr) == IS_MEM_ZVAL);
12202+
| cmp byte [Ra(Z_REG(op1_addr))+Z_OFFSET(op1_addr)+offsetof(zval, u1.v.type)], IS_NULL
12203+
if (exit_addr) {
12204+
if (smart_branch_opcode == ZEND_JMPNZ) {
12205+
| jg &exit_addr
12206+
} else {
12207+
| jle &exit_addr
12208+
}
12209+
} else if (smart_branch_opcode) {
12210+
if (smart_branch_opcode == ZEND_JMPZ) {
12211+
| jle =>target_label
12212+
} else if (smart_branch_opcode == ZEND_JMPNZ) {
12213+
| jg =>target_label
12214+
} else if (smart_branch_opcode == ZEND_JMPZNZ) {
12215+
| jle =>target_label
12216+
| jmp =>target_label2
12217+
} else {
12218+
ZEND_UNREACHABLE();
12219+
}
12220+
} else {
12221+
| setg al
12222+
| movzx eax, al
12223+
| lea eax, [eax + IS_FALSE]
12224+
| SET_ZVAL_TYPE_INFO res_addr, eax
12225+
}
12226+
}
12227+
12228+
return 1;
12229+
}
12230+
1216212231
static zend_bool zend_jit_noref_guard(dasm_State **Dst, const zend_op *opline, zend_jit_addr var_addr)
1216312232
{
1216412233
int32_t exit_point = zend_jit_trace_get_exit_point(opline, opline, NULL, 0);

0 commit comments

Comments
 (0)