Skip to content

Commit 8e879b9

Browse files
committed
JIT for ZEND_CHECK_FUNC_ARG
1 parent bb6f374 commit 8e879b9

File tree

5 files changed

+82
-0
lines changed

5 files changed

+82
-0
lines changed

ext/opcache/Optimizer/zend_inference.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4327,6 +4327,7 @@ int zend_may_throw(const zend_op *opline, const zend_ssa_op *ssa_op, const zend_
43274327
case ZEND_FUNC_NUM_ARGS:
43284328
case ZEND_FUNC_GET_ARGS:
43294329
case ZEND_COPY_TMP:
4330+
case ZEND_CHECK_FUNC_ARG:
43304331
return 0;
43314332
case ZEND_INIT_FCALL:
43324333
/* can't throw, because call is resolved at compile time */

ext/opcache/jit/zend_jit.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2480,6 +2480,14 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
24802480
goto jit_failure;
24812481
}
24822482
goto done;
2483+
case ZEND_CHECK_FUNC_ARG:
2484+
if (opline->op2.num > MAX_ARG_FLAG_NUM) {
2485+
break;
2486+
}
2487+
if (!zend_jit_check_func_arg(&dasm_state, opline, op_array)) {
2488+
goto jit_failure;
2489+
}
2490+
goto done;
24832491
case ZEND_DO_UCALL:
24842492
is_terminated = 1;
24852493
/* break missing intentionally */

ext/opcache/jit/zend_jit_internal.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,7 @@ struct _zend_jit_trace_stack_frame {
336336
int8_t return_value_used;
337337
int8_t nested;
338338
int8_t num_args;
339+
int8_t last_send_by_ref;
339340
};
340341
int return_ssa_var;
341342
};

ext/opcache/jit/zend_jit_trace.c

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1664,6 +1664,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
16641664
frame->return_value_used = -1;
16651665
frame->nested = 0;
16661666
frame->num_args = -1;
1667+
frame->last_send_by_ref = -1;
16671668
stack = frame->stack;
16681669

16691670
if (trace_buffer->start == ZEND_JIT_TRACE_START_ENTER) {
@@ -2232,6 +2233,17 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
22322233
}
22332234
}
22342235
goto done;
2236+
case ZEND_CHECK_FUNC_ARG:
2237+
if (opline->op2.num > MAX_ARG_FLAG_NUM
2238+
&& (!JIT_G(current_frame)
2239+
|| !JIT_G(current_frame)->call
2240+
|| !JIT_G(current_frame)->call->func)) {
2241+
break;
2242+
}
2243+
if (!zend_jit_check_func_arg(&dasm_state, opline, op_array)) {
2244+
goto jit_failure;
2245+
}
2246+
goto done;
22352247
case ZEND_DO_UCALL:
22362248
case ZEND_DO_ICALL:
22372249
case ZEND_DO_FCALL_BY_NAME:
@@ -2861,6 +2873,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
28612873
call->func = (const zend_function*)op_array;
28622874
call->nested = 0;
28632875
call->num_args = -1; // TODO: should be possible to get the real number ???
2876+
call->last_send_by_ref = -1;
28642877
top = zend_jit_trace_call_frame(top, op_array);
28652878
i = 0;
28662879
while (i < p->op_array->num_args) {
@@ -2908,6 +2921,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
29082921
frame->return_value_used = -1;
29092922
frame->nested = 0;
29102923
frame->num_args = -1;
2924+
frame->last_send_by_ref = -1;
29112925
stack = frame->stack;
29122926
for (i = 0; i < op_array->last_var + op_array->T; i++) {
29132927
/* Initialize abstract stack using SSA */
@@ -2937,6 +2951,7 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
29372951
call->func = p->func;
29382952
call->nested = 1;
29392953
call->num_args = find_call_num_args(p-1);
2954+
call->last_send_by_ref = p->fake ? -1 : 0;
29402955
frame->call = call;
29412956
top = zend_jit_trace_call_frame(top, p->op_array);
29422957
if (p->func->type == ZEND_USER_FUNCTION) {

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8728,6 +8728,63 @@ static int zend_jit_send_var(dasm_State **Dst, const zend_op *opline, const zend
87288728
return 1;
87298729
}
87308730

8731+
static int zend_jit_check_func_arg(dasm_State **Dst, const zend_op *opline, const zend_op_array *op_array)
8732+
{
8733+
uint32_t arg_num = opline->op2.num;
8734+
8735+
if (zend_jit_trigger == ZEND_JIT_ON_HOT_TRACE
8736+
&& JIT_G(current_frame)
8737+
&& JIT_G(current_frame)->call
8738+
&& JIT_G(current_frame)->call->func) {
8739+
if (ARG_SHOULD_BE_SENT_BY_REF(JIT_G(current_frame)->call->func, arg_num)) {
8740+
if (JIT_G(current_frame)->call->last_send_by_ref != 1) {
8741+
JIT_G(current_frame)->call->last_send_by_ref = 1;
8742+
| // ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
8743+
|| if (reuse_ip) {
8744+
| or dword [RX + offsetof(zend_execute_data, This.u1.type_info)], ZEND_CALL_SEND_ARG_BY_REF
8745+
|| } else {
8746+
| mov r0, EX->call
8747+
| or dword [r0 + offsetof(zend_execute_data, This.u1.type_info)], ZEND_CALL_SEND_ARG_BY_REF
8748+
|| }
8749+
}
8750+
} else {
8751+
if (JIT_G(current_frame)->call->last_send_by_ref != 0) {
8752+
JIT_G(current_frame)->call->last_send_by_ref = 0;
8753+
| // ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
8754+
|| if (reuse_ip) {
8755+
| and dword [RX + offsetof(zend_execute_data, This.u1.type_info)], ~ZEND_CALL_SEND_ARG_BY_REF
8756+
|| } else {
8757+
| mov r0, EX->call
8758+
| and dword [r0 + offsetof(zend_execute_data, This.u1.type_info)], ~ZEND_CALL_SEND_ARG_BY_REF
8759+
|| }
8760+
}
8761+
}
8762+
} else {
8763+
// if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
8764+
uint32_t mask = (ZEND_SEND_BY_REF|ZEND_SEND_PREFER_REF) << ((arg_num + 3) * 2);
8765+
8766+
if (!reuse_ip) {
8767+
zend_jit_start_reuse_ip();
8768+
| // call = EX(call);
8769+
| mov RX, EX->call
8770+
}
8771+
| mov r0, EX:RX->func
8772+
| test dword [r0 + offsetof(zend_function, quick_arg_flags)], mask
8773+
| jnz >1
8774+
|.cold_code
8775+
|1:
8776+
| // ZEND_ADD_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
8777+
| or dword [RX + offsetof(zend_execute_data, This.u1.type_info)], ZEND_CALL_SEND_ARG_BY_REF
8778+
| jmp >1
8779+
|.code
8780+
| // ZEND_DEL_CALL_FLAG(EX(call), ZEND_CALL_SEND_ARG_BY_REF);
8781+
| and dword [RX + offsetof(zend_execute_data, This.u1.type_info)], ~ZEND_CALL_SEND_ARG_BY_REF
8782+
|1:
8783+
}
8784+
8785+
return 1;
8786+
}
8787+
87318788
static int zend_jit_smart_true(dasm_State **Dst, const zend_op *opline, int jmp, zend_uchar smart_branch_opcode, uint32_t target_label, uint32_t target_label2)
87328789
{
87338790
if (smart_branch_opcode) {

0 commit comments

Comments
 (0)