Skip to content

Commit b106463

Browse files
committed
JIT for IN_ARRAY instruction.
1 parent 59c645b commit b106463

File tree

3 files changed

+110
-0
lines changed

3 files changed

+110
-0
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2810,6 +2810,36 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
28102810
goto jit_failure;
28112811
}
28122812
goto done;
2813+
case ZEND_IN_ARRAY:
2814+
if (opline->op1_type == IS_VAR || opline->op1_type == IS_TMP_VAR) {
2815+
break;
2816+
}
2817+
op1_info = OP1_INFO();
2818+
if ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != MAY_BE_STRING) {
2819+
break;
2820+
}
2821+
if ((opline->result_type & IS_TMP_VAR)
2822+
&& (i + 1) <= end
2823+
&& ((opline+1)->opcode == ZEND_JMPZ
2824+
|| (opline+1)->opcode == ZEND_JMPNZ
2825+
|| (opline+1)->opcode == ZEND_JMPZNZ)
2826+
&& (opline+1)->op1_type == IS_TMP_VAR
2827+
&& (opline+1)->op1.var == opline->result.var) {
2828+
i++;
2829+
smart_branch_opcode = (opline+1)->opcode;
2830+
target_label = ssa->cfg.blocks[b].successors[0];
2831+
target_label2 = ssa->cfg.blocks[b].successors[1];
2832+
} else {
2833+
smart_branch_opcode = 0;
2834+
target_label = target_label2 = (uint32_t)-1;
2835+
}
2836+
if (!zend_jit_in_array(&dasm_state, opline,
2837+
op1_info, OP1_REG_ADDR(),
2838+
smart_branch_opcode, target_label, target_label2,
2839+
NULL)) {
2840+
goto jit_failure;
2841+
}
2842+
goto done;
28132843
case ZEND_FETCH_DIM_R:
28142844
case ZEND_FETCH_DIM_IS:
28152845
case ZEND_FETCH_LIST_R:

ext/opcache/jit/zend_jit_trace.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,6 +1518,12 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
15181518
}
15191519
ADD_OP1_TRACE_GUARD();
15201520
break;
1521+
case ZEND_IN_ARRAY:
1522+
if (opline->op1_type == IS_VAR || opline->op1_type == IS_TMP_VAR) {
1523+
break;
1524+
}
1525+
ADD_OP1_TRACE_GUARD();
1526+
break;
15211527
case ZEND_ISSET_ISEMPTY_DIM_OBJ:
15221528
if ((opline->extended_value & ZEND_ISEMPTY)) {
15231529
// TODO: support for empty() ???
@@ -4210,6 +4216,36 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
42104216
goto jit_failure;
42114217
}
42124218
goto done;
4219+
case ZEND_IN_ARRAY:
4220+
if (opline->op1_type == IS_VAR || opline->op1_type == IS_TMP_VAR) {
4221+
break;
4222+
}
4223+
op1_info = OP1_INFO();
4224+
op1_addr = OP1_REG_ADDR();
4225+
CHECK_OP1_TRACE_TYPE();
4226+
if ((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) != MAY_BE_STRING) {
4227+
break;
4228+
}
4229+
if ((opline->result_type & (IS_SMART_BRANCH_JMPZ|IS_SMART_BRANCH_JMPNZ)) != 0) {
4230+
zend_bool exit_if_true = 0;
4231+
const zend_op *exit_opline = zend_jit_trace_get_exit_opline(p + 1, opline + 1, &exit_if_true);
4232+
uint32_t exit_point = zend_jit_trace_get_exit_point(exit_opline, 0);
4233+
4234+
exit_addr = zend_jit_trace_get_exit_addr(exit_point);
4235+
if (!exit_addr) {
4236+
goto jit_failure;
4237+
}
4238+
smart_branch_opcode = exit_if_true ? ZEND_JMPNZ : ZEND_JMPZ;
4239+
} else {
4240+
smart_branch_opcode = 0;
4241+
exit_addr = NULL;
4242+
}
4243+
if (!zend_jit_in_array(&dasm_state, opline,
4244+
op1_info, op1_addr,
4245+
smart_branch_opcode, -1, -1, exit_addr)) {
4246+
goto jit_failure;
4247+
}
4248+
goto done;
42134249
case ZEND_FETCH_DIM_FUNC_ARG:
42144250
if (!JIT_G(current_frame)
42154251
|| !JIT_G(current_frame)->call

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12754,6 +12754,50 @@ static int zend_jit_fetch_constant(dasm_State **Dst, const zend_op *opline)
1275412754
return 1;
1275512755
}
1275612756

12757+
static int zend_jit_in_array(dasm_State **Dst, const zend_op *opline, 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)
12758+
{
12759+
HashTable *ht = Z_ARRVAL_P(RT_CONSTANT(opline, opline->op2));
12760+
zend_jit_addr res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
12761+
12762+
ZEND_ASSERT(opline->op1_type != IS_VAR && opline->op1_type != IS_TMP_VAR);
12763+
ZEND_ASSERT((op1_info & (MAY_BE_ANY|MAY_BE_UNDEF|MAY_BE_REF)) == MAY_BE_STRING);
12764+
12765+
| // result = zend_hash_find_ex(ht, Z_STR_P(op1), OP1_TYPE == IS_CONST);
12766+
| LOAD_ADDR FCARG1a, ht
12767+
| GET_ZVAL_PTR FCARG2a, op1_addr
12768+
if (opline->op1_type != IS_CONST) {
12769+
| EXT_CALL zend_hash_find, r0
12770+
} else {
12771+
| EXT_CALL _zend_hash_find_known_hash, r0
12772+
}
12773+
| test r0, r0
12774+
if (exit_addr) {
12775+
if (smart_branch_opcode == ZEND_JMPZ) {
12776+
| jz &exit_addr
12777+
} else {
12778+
| jnz &exit_addr
12779+
}
12780+
} else if (smart_branch_opcode) {
12781+
if (smart_branch_opcode == ZEND_JMPZ) {
12782+
| jz =>target_label
12783+
} else if (smart_branch_opcode == ZEND_JMPNZ) {
12784+
| jnz =>target_label
12785+
} else if (smart_branch_opcode == ZEND_JMPZNZ) {
12786+
| jz =>target_label
12787+
| jmp =>target_label2
12788+
} else {
12789+
ZEND_UNREACHABLE();
12790+
}
12791+
} else {
12792+
| setnz al
12793+
| movzx eax, al
12794+
| lea eax, [eax + IS_FALSE]
12795+
| SET_ZVAL_TYPE_INFO res_addr, eax
12796+
}
12797+
12798+
return 1;
12799+
}
12800+
1275712801
static zend_bool zend_jit_noref_guard(dasm_State **Dst, const zend_op *opline, zend_jit_addr var_addr)
1275812802
{
1275912803
int32_t exit_point = zend_jit_trace_get_exit_point(opline, 0);

0 commit comments

Comments
 (0)