From: Dmitry Stogov Date: Mon, 29 Jun 2020 18:40:49 +0000 (+0300) Subject: Tracing JIT support for include() and generators X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=24a8065f8bd58decf1f27ef0aa790c7a51b8d4db;p=php Tracing JIT support for include() and generators --- diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index 803627f9a1..2e32301a9b 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -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. diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index 5a29165aec..72b229af3d 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -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; diff --git a/ext/opcache/jit/zend_jit_trace.c b/ext/opcache/jit/zend_jit_trace.c index bae7799717..1400b78225 100644 --- a/ext/opcache/jit/zend_jit_trace.c +++ b/ext/opcache/jit/zend_jit_trace.c @@ -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; diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index 5ab2129a30..c7c7afba9d 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -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 diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index 30411d0724..35c536454a 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -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;