Skip to content

Commit 1c56b40

Browse files
committed
Eliminate some EX_CALL_INFO() checks
1 parent 88a8ebc commit 1c56b40

File tree

4 files changed

+108
-67
lines changed

4 files changed

+108
-67
lines changed

ext/opcache/jit/zend_jit.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2740,9 +2740,10 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
27402740
}
27412741
}
27422742
}
2743-
if (!zend_jit_leave_func(&dasm_state, op_array, NULL, NULL, 1)) {
2743+
if (!zend_jit_leave_func(&dasm_state, op_array, NULL, NULL,
2744+
(ssa->cfg.flags & ZEND_FUNC_INDIRECT_VAR_ACCESS) != 0, 1)) {
27442745
goto jit_failure;
2745-
}
2746+
}
27462747
}
27472748
goto done;
27482749
case ZEND_BOOL:

ext/opcache/jit/zend_jit_internal.h

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -379,17 +379,18 @@ struct _zend_jit_trace_stack_frame {
379379
zend_jit_trace_stack stack[1];
380380
};
381381

382-
#define TRACE_FRAME_SHIFT_NUM_ARGS 16
383-
#define TRACE_FRAME_MAX_NUM_ARGS 32767
382+
#define TRACE_FRAME_SHIFT_NUM_ARGS 16
383+
#define TRACE_FRAME_MAX_NUM_ARGS 32767
384384

385-
#define TRACE_FRAME_MASK_NUM_ARGS 0xffff0000
386-
#define TRACE_FRAME_MASK_NESTED 0x00000001
387-
#define TRACE_FRAME_MASK_LAST_SEND_BY_REF 0x00000002
388-
#define TRACE_FRAME_MASK_LAST_SEND_BY_VAL 0x00000004
389-
#define TRACE_FRAME_MASK_RETURN_VALUE_USED 0x00000008
390-
#define TRACE_FRAME_MASK_RETURN_VALUE_UNUSED 0x00000010
391-
#define TRACE_FRAME_MASK_THIS_CHECKED 0x00000020
392-
#define TRACE_FRAME_MASK_UNKNOWN_RETURN 0x00000040
385+
#define TRACE_FRAME_MASK_NUM_ARGS 0xffff0000
386+
#define TRACE_FRAME_MASK_NESTED 0x00000001
387+
#define TRACE_FRAME_MASK_LAST_SEND_BY_REF 0x00000002
388+
#define TRACE_FRAME_MASK_LAST_SEND_BY_VAL 0x00000004
389+
#define TRACE_FRAME_MASK_RETURN_VALUE_USED 0x00000008
390+
#define TRACE_FRAME_MASK_RETURN_VALUE_UNUSED 0x00000010
391+
#define TRACE_FRAME_MASK_THIS_CHECKED 0x00000020
392+
#define TRACE_FRAME_MASK_UNKNOWN_RETURN 0x00000040
393+
#define TRACE_FRAME_MASK_NO_NEED_RELEASE_THIS 0x00000080
393394

394395

395396
#define TRACE_FRAME_INIT(frame, _func, _flags, num_args) do { \
@@ -421,6 +422,8 @@ struct _zend_jit_trace_stack_frame {
421422
((frame)->_info & TRACE_FRAME_MASK_THIS_CHECKED)
422423
#define TRACE_FRAME_IS_UNKNOWN_RETURN(frame) \
423424
((frame)->_info & TRACE_FRAME_MASK_UNKNOWN_RETURN)
425+
#define TRACE_FRAME_NO_NEED_REKEASE_THIS(frame) \
426+
((frame)->_info & TRACE_FRAME_MASK_NO_NEED_RELEASE_THIS)
424427

425428
#define TRACE_FRAME_SET_RETURN_SSA_VAR(frame, var) do { \
426429
(frame)->_info = var; \
@@ -444,6 +447,9 @@ struct _zend_jit_trace_stack_frame {
444447
#define TRACE_FRAME_SET_THIS_CHECKED(frame) do { \
445448
(frame)->_info |= TRACE_FRAME_MASK_THIS_CHECKED; \
446449
} while (0)
450+
#define TRACE_FRAME_SET_NO_NEED_RELEASE_THIS(frame) do { \
451+
(frame)->_info |= TRACE_FRAME_MASK_NO_NEED_RELEASE_THIS; \
452+
} while (0)
447453

448454
ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_func_trace_helper(ZEND_OPCODE_HANDLER_ARGS);
449455
ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_jit_ret_trace_helper(ZEND_OPCODE_HANDLER_ARGS);

ext/opcache/jit/zend_jit_trace.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4058,7 +4058,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
40584058
}
40594059
}
40604060
}
4061-
if (!zend_jit_leave_func(&dasm_state, op_array, p + 1, &zend_jit_traces[ZEND_JIT_TRACE_NUM], may_throw)) {
4061+
if (!zend_jit_leave_func(&dasm_state, op_array, p + 1, &zend_jit_traces[ZEND_JIT_TRACE_NUM],
4062+
(op_array_ssa->cfg.flags & ZEND_FUNC_INDIRECT_VAR_ACCESS) != 0, may_throw)) {
40624063
goto jit_failure;
40634064
}
40644065
}
@@ -4876,6 +4877,17 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
48764877
if (!(p->info & ZEND_JIT_TRACE_FAKE_INIT_CALL)) {
48774878
TRACE_FRAME_SET_LAST_SEND_BY_VAL(call);
48784879
}
4880+
if (init_opline
4881+
&& init_opline->opcode != ZEND_NEW
4882+
&& (init_opline->opcode != ZEND_INIT_METHOD_CALL
4883+
|| init_opline->op1_type == IS_UNDEF)
4884+
&& (init_opline->opcode != ZEND_INIT_USER_CALL
4885+
|| init_opline->op2_type == IS_CONST) /* no closure */
4886+
&& (init_opline->opcode != ZEND_INIT_DYNAMIC_CALL
4887+
|| init_opline->op2_type == IS_CONST) /* no closure */
4888+
) {
4889+
TRACE_FRAME_SET_NO_NEED_RELEASE_THIS(call);
4890+
}
48794891
frame->call = call;
48804892
top = zend_jit_trace_call_frame(top, p->op_array);
48814893
if (p->func) {

ext/opcache/jit/zend_jit_x86.dasc

Lines changed: 76 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -10194,66 +10194,88 @@ static int zend_jit_free_op(dasm_State **Dst, const zend_op *opline, uint32_t in
1019410194
return 1;
1019510195
}
1019610196

10197-
static int zend_jit_leave_func(dasm_State **Dst, const zend_op_array *op_array, zend_jit_trace_rec *trace, zend_jit_trace_info *trace_info, int may_throw)
10198-
{
10199-
/* ZEND_CALL_FAKE_CLOSURE handled on slow path to eliminate check for ZEND_CALL_CLOSURE on fast path */
10200-
| mov FCARG1d, dword [FP + offsetof(zend_execute_data, This.u1.type_info)]
10201-
| test FCARG1d, (ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS|ZEND_CALL_FAKE_CLOSURE)
10202-
if (trace && trace->op != ZEND_JIT_TRACE_END) {
10203-
| jnz >1
10204-
|.cold_code
10205-
|1:
10206-
if (!GCC_GLOBAL_REGS) {
10207-
| mov FCARG2a, FP
10208-
}
10209-
| EXT_CALL zend_jit_leave_func_helper, r0
10197+
static int zend_jit_leave_func(dasm_State **Dst, const zend_op_array *op_array, zend_jit_trace_rec *trace, zend_jit_trace_info *trace_info, int indirect_var_access, int may_throw)
10198+
{
10199+
zend_bool may_be_top_frame =
10200+
JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE ||
10201+
!JIT_G(current_frame) ||
10202+
!TRACE_FRAME_IS_NESTED(JIT_G(current_frame));
10203+
zend_bool may_need_call_helper =
10204+
indirect_var_access || /* may have symbol table */
10205+
!op_array->function_name || /* may have symbol table */
10206+
may_be_top_frame ||
10207+
(op_array->fn_flags & ZEND_ACC_VARIADIC) || /* may have extra named args */
10208+
JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE ||
10209+
!JIT_G(current_frame) ||
10210+
TRACE_FRAME_NUM_ARGS(JIT_G(current_frame)) == -1 || /* unknown number of args */
10211+
(uint32_t)TRACE_FRAME_NUM_ARGS(JIT_G(current_frame)) > op_array->num_args; /* extra args */
10212+
zend_bool may_need_release_this =
10213+
!(op_array->fn_flags & ZEND_ACC_CLOSURE) &&
10214+
op_array->scope &&
10215+
!(op_array->fn_flags & ZEND_ACC_STATIC) &&
10216+
(JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE ||
10217+
!JIT_G(current_frame) ||
10218+
!TRACE_FRAME_NO_NEED_REKEASE_THIS(JIT_G(current_frame)));
10219+
10220+
if (may_need_call_helper || may_need_release_this) {
10221+
| mov FCARG1d, dword [FP + offsetof(zend_execute_data, This.u1.type_info)]
10222+
}
10223+
if (may_need_call_helper) {
10224+
/* ZEND_CALL_FAKE_CLOSURE handled on slow path to eliminate check for ZEND_CALL_CLOSURE on fast path */
10225+
| test FCARG1d, (ZEND_CALL_TOP|ZEND_CALL_HAS_SYMBOL_TABLE|ZEND_CALL_FREE_EXTRA_ARGS|ZEND_CALL_ALLOCATED|ZEND_CALL_HAS_EXTRA_NAMED_PARAMS|ZEND_CALL_FAKE_CLOSURE)
10226+
if (trace && trace->op != ZEND_JIT_TRACE_END) {
10227+
| jnz >1
10228+
|.cold_code
10229+
|1:
10230+
if (!GCC_GLOBAL_REGS) {
10231+
| mov FCARG2a, FP
10232+
}
10233+
| EXT_CALL zend_jit_leave_func_helper, r0
10234+
10235+
if (may_be_top_frame) {
10236+
// TODO: try to avoid this check ???
10237+
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
10238+
| cmp IP, zend_jit_halt_op
10239+
| je ->trace_halt
10240+
} else if (GCC_GLOBAL_REGS) {
10241+
| test IP, IP
10242+
| je ->trace_halt
10243+
} else {
10244+
| test eax, eax
10245+
| jl ->trace_halt
10246+
}
10247+
}
1021010248

10211-
if (JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE ||
10212-
!JIT_G(current_frame) ||
10213-
!TRACE_FRAME_IS_NESTED(JIT_G(current_frame))) {
10214-
// TODO: try to avoid this check ???
10215-
if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
10216-
| cmp IP, zend_jit_halt_op
10217-
| je ->trace_halt
10218-
} else if (GCC_GLOBAL_REGS) {
10219-
| test IP, IP
10220-
| je ->trace_halt
10221-
} else {
10222-
| test eax, eax
10223-
| jl ->trace_halt
10249+
if (!GCC_GLOBAL_REGS) {
10250+
| // execute_data = EG(current_execute_data)
10251+
| MEM_OP2_2_ZTS mov, FP, aword, executor_globals, current_execute_data, r0
1022410252
}
10253+
| jmp >8
10254+
|.code
10255+
} else {
10256+
| jnz ->leave_function_handler
1022510257
}
10258+
}
1022610259

10227-
if (!GCC_GLOBAL_REGS) {
10228-
| // execute_data = EG(current_execute_data)
10229-
| MEM_OP2_2_ZTS mov, FP, aword, executor_globals, current_execute_data, r0
10230-
}
10231-
| jmp >8
10232-
|.code
10233-
} else {
10234-
| jnz ->leave_function_handler
10235-
}
10236-
10237-
if ((op_array->scope && !(op_array->fn_flags & ZEND_ACC_STATIC)) ||
10238-
(op_array->fn_flags & ZEND_ACC_CLOSURE)) {
10239-
if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
10240-
| // OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
10241-
| mov FCARG1a, EX->func
10242-
| sub FCARG1a, sizeof(zend_object)
10243-
| OBJ_RELEASE ZREG_FCARG1a, >4
10244-
} else if (op_array->scope && !(op_array->fn_flags & ZEND_ACC_STATIC)) {
10245-
| // if (call_info & ZEND_CALL_RELEASE_THIS)
10246-
| test FCARG1d, ZEND_CALL_RELEASE_THIS
10247-
| je >4
10248-
| // zend_object *object = Z_OBJ(execute_data->This);
10249-
| mov FCARG1a, EX->This.value.obj
10250-
| // OBJ_RELEASE(object);
10251-
| OBJ_RELEASE ZREG_FCARG1a, >4
10252-
// TODO: avoid EG(excption) check for $this->foo() calls
10253-
may_throw = 1;
10254-
}
10260+
if (op_array->fn_flags & ZEND_ACC_CLOSURE) {
10261+
| // OBJ_RELEASE(ZEND_CLOSURE_OBJECT(EX(func)));
10262+
| mov FCARG1a, EX->func
10263+
| sub FCARG1a, sizeof(zend_object)
10264+
| OBJ_RELEASE ZREG_FCARG1a, >4
1025510265
|4:
10266+
} else if (may_need_release_this) {
10267+
| // if (call_info & ZEND_CALL_RELEASE_THIS)
10268+
| test FCARG1d, ZEND_CALL_RELEASE_THIS
10269+
| je >4
10270+
| // zend_object *object = Z_OBJ(execute_data->This);
10271+
| mov FCARG1a, EX->This.value.obj
10272+
| // OBJ_RELEASE(object);
10273+
| OBJ_RELEASE ZREG_FCARG1a, >4
10274+
|4:
10275+
// TODO: avoid EG(excption) check for $this->foo() calls
10276+
may_throw = 1;
1025610277
}
10278+
1025710279
| // EG(vm_stack_top) = (zval*)execute_data;
1025810280
| MEM_OP2_1_ZTS mov, aword, executor_globals, vm_stack_top, FP, r0
1025910281
| // execute_data = EX(prev_execute_data);

0 commit comments

Comments
 (0)