From a9cbdafa69c4762a0f22271f18e9f4a76eaaf0fb Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Thu, 17 Sep 2020 23:19:28 +0300 Subject: [PATCH] Support for ZEND_COMPILE_EXTENDED_STMT --- ext/opcache/Optimizer/zend_cfg.c | 8 +++++++ ext/opcache/jit/zend_jit.c | 18 +++++++++++++- ext/opcache/jit/zend_jit_trace.c | 39 ++++++++++++++++++++----------- ext/opcache/jit/zend_jit_x86.dasc | 12 +++++++--- 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 } -- 2.40.0