summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ext/opcache/Optimizer/zend_cfg.c8
-rw-r--r--ext/opcache/jit/zend_jit.c18
-rw-r--r--ext/opcache/jit/zend_jit_trace.c39
-rw-r--r--ext/opcache/jit/zend_jit_x86.dasc12
4 files changed, 60 insertions, 17 deletions
diff --git a/ext/opcache/Optimizer/zend_cfg.c b/ext/opcache/Optimizer/zend_cfg.c
index 127fca5dca..f036950ffa 100644
--- a/ext/opcache/Optimizer/zend_cfg.c
+++ b/ext/opcache/Optimizer/zend_cfg.c
@@ -112,6 +112,10 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg *
zend_basic_block *blocks = cfg->blocks;
blocks[start].flags = ZEND_BB_START;
+ if (op_array->opcodes[0].opcode == ZEND_EXT_NOP
+ && (cfg->flags & ZEND_CFG_RECV_ENTRY)) {
+ blocks[1].flags |= ZEND_BB_RECV_ENTRY;
+ }
zend_mark_reachable(op_array->opcodes, cfg, blocks + start);
if (op_array->last_try_catch) {
@@ -287,6 +291,10 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b
/* Build CFG, Step 1: Find basic blocks starts, calculate number of blocks */
BB_START(0);
+ if (op_array->opcodes[0].opcode == ZEND_EXT_NOP
+ && (build_flags & ZEND_CFG_RECV_ENTRY)) {
+ BB_START(1);
+ }
for (i = 0; i < op_array->last; i++) {
zend_op *opline = op_array->opcodes + i;
switch (opline->opcode) {
diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c
index 3dad8e4f91..7c9704954a 100644
--- a/ext/opcache/jit/zend_jit.c
+++ b/ext/opcache/jit/zend_jit.c
@@ -2118,7 +2118,8 @@ static int zend_jit(const zend_op_array *op_array, zend_ssa *ssa, const zend_op
}
recv_emitted = 1;
} else if (opline->opcode == ZEND_RECV) {
- if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
+ if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)
+ && op_array->opcodes[0].opcode != ZEND_EXT_NOP) {
/* skip */
continue;
} else if (recv_emitted) {
@@ -3539,6 +3540,9 @@ static void ZEND_FASTCALL zend_runtime_jit(void)
/* restore original opcode handlers */
if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
+ if (opline->opcode == ZEND_EXT_NOP) {
+ opline++;
+ }
while (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT) {
opline++;
}
@@ -3572,6 +3576,9 @@ void zend_jit_check_funcs(HashTable *function_table, zend_bool is_method) {
op_array = &func->op_array;
opline = op_array->opcodes;
if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
+ if (opline->opcode == ZEND_EXT_NOP) {
+ opline++;
+ }
while (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT) {
opline++;
}
@@ -3644,6 +3651,9 @@ static int zend_jit_setup_hot_counters(zend_op_array *op_array)
if (JIT_G(hot_func)) {
if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
+ if (opline->opcode == ZEND_EXT_NOP) {
+ opline++;
+ }
while (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT) {
opline++;
}
@@ -3682,6 +3692,9 @@ ZEND_EXT_API int zend_jit_op_array(zend_op_array *op_array, zend_script *script)
/* Set run-time JIT handler */
ZEND_ASSERT(zend_jit_runtime_jit_handler != NULL);
if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
+ if (opline->opcode == ZEND_EXT_NOP) {
+ opline++;
+ }
while (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT) {
opline++;
}
@@ -3701,6 +3714,9 @@ ZEND_EXT_API int zend_jit_op_array(zend_op_array *op_array, zend_script *script)
ZEND_ASSERT(zend_jit_profile_jit_handler != NULL);
if (op_array->function_name) {
if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
+ if (opline->opcode == ZEND_EXT_NOP) {
+ opline++;
+ }
while (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT) {
opline++;
}
diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c
index 8fa26e700b..65b6f17c95 100644
--- a/ext/opcache/jit/zend_jit_trace.c
+++ b/ext/opcache/jit/zend_jit_trace.c
@@ -1743,7 +1743,8 @@ propagate_arg:
}
}
if (opline->opcode == ZEND_RECV_INIT
- && !(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
+ && !(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)
+ && op_array->opcodes[0].opcode != ZEND_EXT_NOP) {
/* RECV_INIT always copy the constant */
ssa_var_info[ssa_ops[idx].result_def].type = _const_op_type(RT_CONSTANT(opline, opline->op2));
} else if ((opline->opcode == ZEND_FE_FETCH_R || opline->opcode == ZEND_FE_FETCH_RW)
@@ -1805,7 +1806,8 @@ propagate_arg:
}
}
if (opline->opcode == ZEND_RECV_INIT
- && !(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
+ && !(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)
+ && op_array->opcodes[0].opcode != ZEND_EXT_NOP) {
/* RECV_INIT always copy the constant */
ssa_var_info[ssa_ops[idx].result_def].type = _const_op_type(RT_CONSTANT(opline, opline->op2));
} else {
@@ -1885,6 +1887,7 @@ propagate_arg:
ssa_var_info[v].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF;
}
if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)
+ && op_array->opcodes[0].opcode != ZEND_EXT_NOP
&& i < op_array->num_args) {
/* Propagate argument type */
ssa_var_info[v].type &= STACK_INFO(frame->stack, i);
@@ -5309,17 +5312,24 @@ done:
frame->call_opline = opline;
/* Check if SEND_UNPACK/SEND_ARRAY may cause enter at different opline */
- if (opline > op_array->opcodes
- && ((opline-1)->opcode == ZEND_SEND_ARRAY
- || (opline-1)->opcode == ZEND_SEND_UNPACK
- || (opline-1)->opcode == ZEND_CHECK_UNDEF_ARGS)
- && p->op_array->num_args
- && (p->op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0
- && ((p+1)->op == ZEND_JIT_TRACE_VM
- || (p+1)->op == ZEND_JIT_TRACE_END)
- && TRACE_FRAME_NUM_ARGS(call) < p->op_array->num_args
- && !zend_jit_trace_opline_guard(&dasm_state, (p+1)->opline)) {
- goto jit_failure;
+ if (opline > op_array->opcodes) {
+ const zend_op *prev_opline = opline - 1;
+
+ while (prev_opline->opcode == ZEND_EXT_FCALL_BEGIN || prev_opline->opcode == ZEND_TICKS) {
+ prev_opline--;
+ }
+ if ((prev_opline->opcode == ZEND_SEND_ARRAY
+ || prev_opline->opcode == ZEND_SEND_UNPACK
+ || prev_opline->opcode == ZEND_CHECK_UNDEF_ARGS)
+ && p->op_array->num_args
+ && (p->op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0
+ && (p->op_array->opcodes[0].opcode != ZEND_EXT_NOP)
+ && ((p+1)->op == ZEND_JIT_TRACE_VM
+ || (p+1)->op == ZEND_JIT_TRACE_END)
+ && TRACE_FRAME_NUM_ARGS(call) < p->op_array->num_args
+ && !zend_jit_trace_opline_guard(&dasm_state, (p+1)->opline)) {
+ goto jit_failure;
+ }
}
}
@@ -6804,6 +6814,9 @@ static int zend_jit_setup_hot_trace_counters(zend_op_array *op_array)
ZEND_ASSERT(zend_jit_func_trace_counter_handler != NULL);
opline = op_array->opcodes;
if (!(op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
+ if (opline->opcode == ZEND_EXT_NOP) {
+ opline++;
+ }
while (opline->opcode == ZEND_RECV || opline->opcode == ZEND_RECV_INIT) {
opline++;
}
diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc
index 20fe88e9c1..befc6717d9 100644
--- a/ext/opcache/jit/zend_jit_x86.dasc
+++ b/ext/opcache/jit/zend_jit_x86.dasc
@@ -9433,6 +9433,7 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
uint32_t call_num_args = 0;
zend_bool unknown_num_args = 0;
const void *exit_addr = NULL;
+ const zend_op *prev_opline;
if (RETURN_VALUE_USED(opline)) {
res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
@@ -9441,8 +9442,12 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_R4, TMP_ZVAL_OFFSET);
}
- if ((opline-1)->opcode == ZEND_SEND_UNPACK || (opline-1)->opcode == ZEND_SEND_ARRAY ||
- (opline-1)->opcode == ZEND_CHECK_UNDEF_ARGS) {
+ prev_opline = opline - 1;
+ while (prev_opline->opcode == ZEND_EXT_FCALL_BEGIN || prev_opline->opcode == ZEND_TICKS) {
+ prev_opline--;
+ }
+ if (prev_opline->opcode == ZEND_SEND_UNPACK || prev_opline->opcode == ZEND_SEND_ARRAY ||
+ prev_opline->opcode == ZEND_CHECK_UNDEF_ARGS) {
unknown_num_args = 1;
}
@@ -12194,7 +12199,8 @@ static int zend_jit_recv_init(dasm_State **Dst, const zend_op *opline, const zen
zend_jit_addr res_addr = ZEND_ADDR_MEM_ZVAL(ZREG_FP, opline->result.var);
if (JIT_G(trigger) != ZEND_JIT_ON_HOT_TRACE ||
- (op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS)) {
+ (op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) ||
+ op_array->opcodes[0].opcode == ZEND_EXT_NOP) {
| cmp dword EX->This.u2.num_args, arg_num
| jae >5
}