]> granicus.if.org Git - php/commitdiff
Support for ZEND_COMPILE_EXTENDED_STMT
authorDmitry Stogov <dmitry@zend.com>
Thu, 17 Sep 2020 20:19:28 +0000 (23:19 +0300)
committerDmitry Stogov <dmitry@zend.com>
Thu, 17 Sep 2020 20:19:28 +0000 (23:19 +0300)
ext/opcache/Optimizer/zend_cfg.c
ext/opcache/jit/zend_jit.c
ext/opcache/jit/zend_jit_trace.c
ext/opcache/jit/zend_jit_x86.dasc

index 127fca5dca879498bd883a33403c67b8c795ec37..f036950ffac4cb47d18af0d525f7504f0600882a 100644 (file)
@@ -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) {
index 3dad8e4f911151386936729d2fc1f332ec04bb24..7c9704954a354d049f4e572c5dcb207e14c7bec5 100644 (file)
@@ -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++;
                                }
index 8fa26e700bf2ddd5cd092ed979d17dd162374c19..65b6f17c95799d34c070055ac597f2ea9e749913 100644 (file)
@@ -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++;
                        }
index 20fe88e9c11f8adc1f907f491fd5a87679d4039d..befc6717d9d347c03fc8793a8849054352dd8dea 100644 (file)
@@ -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
        }