]> granicus.if.org Git - php/commitdiff
Tracing JIT support for include() and generators
authorDmitry Stogov <dmitry@zend.com>
Mon, 29 Jun 2020 18:40:49 +0000 (21:40 +0300)
committerDmitry Stogov <dmitry@zend.com>
Mon, 29 Jun 2020 18:40:49 +0000 (21:40 +0300)
Zend/zend_generators.c
ext/opcache/Optimizer/zend_inference.c
ext/opcache/jit/zend_jit_trace.c
ext/opcache/jit/zend_jit_vm_helpers.c
ext/opcache/jit/zend_jit_x86.dasc

index 803627f9a1d19afc91c5b1629a3a3f102970eace..2e32301a9b68245160873782dd1ae469f2b36333 100644 (file)
@@ -742,9 +742,11 @@ try_again:
        {
                /* Backup executor globals */
                zend_execute_data *original_execute_data = EG(current_execute_data);
+               uint32_t original_jit_trace_num = EG(jit_trace_num);
 
                /* Set executor globals */
                EG(current_execute_data) = generator->execute_data;
+               EG(jit_trace_num) = 0;
 
                /* We want the backtrace to look as if the generator function was
                 * called from whatever method we are current running (e.g. next()).
@@ -777,6 +779,7 @@ try_again:
 
                /* Restore executor globals */
                EG(current_execute_data) = original_execute_data;
+               EG(jit_trace_num) = original_jit_trace_num;
 
                /* If an exception was thrown in the generator we have to internally
                 * rethrow it in the parent scope.
index 5a29165aec0fb3450ff0a7dd6416bfa1ce9d43be..72b229af3ded6b620b4a62163a844a0fac1234ac 100644 (file)
@@ -3511,7 +3511,6 @@ static zend_always_inline int _zend_update_type_info(
                        }
                        break;
                case ZEND_CATCH:
-               case ZEND_INCLUDE_OR_EVAL:
                        /* Forbidden opcodes */
                        ZEND_UNREACHABLE();
                        break;
index bae77997178a9832646fee994c0ee10295ab9fd6..1400b782251023225c42cba4928bf03394a26aa4 100644 (file)
@@ -4456,10 +4456,16 @@ done:
                                }
                        }
                } else if (p->stop == ZEND_JIT_TRACE_STOP_LINK
+                       || p->stop == ZEND_JIT_TRACE_STOP_RETURN_HALT
                        || p->stop == ZEND_JIT_TRACE_STOP_INTERPRETER) {
                        if (opline->opcode == ZEND_DO_UCALL
                         || opline->opcode == ZEND_DO_FCALL
-                        || opline->opcode == ZEND_DO_FCALL_BY_NAME) {
+                        || opline->opcode == ZEND_DO_FCALL_BY_NAME
+                        || opline->opcode == ZEND_GENERATOR_CREATE
+                        || opline->opcode == ZEND_GENERATOR_RETURN
+                        || opline->opcode == ZEND_YIELD
+                        || opline->opcode == ZEND_YIELD_FROM
+                        || opline->opcode == ZEND_INCLUDE_OR_EVAL) {
                                zend_jit_trace_setup_ret_counter(opline, jit_extension->offset);
                        }
                        if (JIT_G(current_frame)
@@ -5499,12 +5505,6 @@ static zend_always_inline uint8_t zend_jit_trace_supported(const zend_op *opline
                case ZEND_CATCH:
                case ZEND_FAST_CALL:
                case ZEND_FAST_RET:
-               case ZEND_GENERATOR_CREATE:
-               case ZEND_GENERATOR_RETURN:
-               case ZEND_EXIT:
-               case ZEND_YIELD:
-               case ZEND_YIELD_FROM:
-               case ZEND_INCLUDE_OR_EVAL:
                        return ZEND_JIT_TRACE_UNSUPPORTED;
                default:
                        return ZEND_JIT_TRACE_SUPPORTED;
index 5ab2129a307b498c997d3bf70c49170886bc3674..c7c7afba9d01409679e3c88b1883c4238c94d8cb 100644 (file)
@@ -713,6 +713,9 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex,
                        if (EX(call)->func->type == ZEND_INTERNAL_FUNCTION) {
                                TRACE_RECORD(ZEND_JIT_TRACE_DO_ICALL, 0, EX(call)->func);
                        }
+               } else if (opline->opcode == ZEND_INCLUDE_OR_EVAL) {
+                       stop = ZEND_JIT_TRACE_STOP_INTERPRETER;
+                       break;
                }
 
                handler = (zend_vm_opcode_handler_t)ZEND_OP_TRACE_INFO(opline, offset)->call_handler;
@@ -975,7 +978,8 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex,
        TRACE_END(ZEND_JIT_TRACE_END, stop, end_opline);
 
 #ifdef HAVE_GCC_GLOBAL_REGS
-       if (stop != ZEND_JIT_TRACE_STOP_HALT) {
+       if (stop != ZEND_JIT_TRACE_STOP_HALT
+        && stop != ZEND_JIT_TRACE_STOP_RETURN_HALT) {
                EX(opline) = opline;
        }
 #endif
index 30411d0724bcedfc995113e299917fe015940dbc..35c536454a0f0d2acfd06b9d2d023b3d34b5e6cd 100644 (file)
@@ -3183,7 +3183,10 @@ static int zend_jit_trace_handler(dasm_State **Dst, const zend_op_array *op_arra
 
        if (zend_jit_trace_may_exit(op_array, opline)) {
                // TODO: try to avoid this check ???
-               if (opline->opcode == ZEND_RETURN || opline->opcode == ZEND_RETURN_BY_REF) {
+               if (opline->opcode == ZEND_RETURN ||
+                   opline->opcode == ZEND_RETURN_BY_REF ||
+                   opline->opcode == ZEND_GENERATOR_CREATE) {
+
                        if (zend_jit_vm_kind == ZEND_VM_KIND_HYBRID) {
                                |       cmp IP, zend_jit_halt_op
                                |       je ->trace_halt
@@ -3194,8 +3197,17 @@ static int zend_jit_trace_handler(dasm_State **Dst, const zend_op_array *op_arra
                                |       test eax, eax
                                |       jl ->trace_halt
                        }
+               } else if (opline->opcode == ZEND_EXIT ||
+                          opline->opcode == ZEND_GENERATOR_RETURN ||
+                          opline->opcode == ZEND_YIELD ||
+                          opline->opcode == ZEND_YIELD_FROM) {
+                       |       jmp ->trace_halt
                }
-               if (trace->op != ZEND_JIT_TRACE_END || trace->stop != ZEND_JIT_TRACE_STOP_RETURN) {
+               if (trace->op != ZEND_JIT_TRACE_END ||
+                   (trace->stop != ZEND_JIT_TRACE_STOP_RETURN &&
+                    trace->stop != ZEND_JIT_TRACE_STOP_RETURN_HALT &&
+                    trace->stop != ZEND_JIT_TRACE_STOP_INTERPRETER)) {
+
                        const zend_op *next_opline = trace->opline;
                        const zend_op *exit_opline = NULL;
                        uint32_t exit_point;