@@ -366,6 +366,26 @@ static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op
366366 return 0 ;
367367}
368368
369+ static bool zend_jit_may_be_modified (const zend_function * func , const zend_op_array * called_from )
370+ {
371+ if (func -> type == ZEND_INTERNAL_FUNCTION ) {
372+ #ifdef _WIN32
373+ /* ASLR */
374+ return 1 ;
375+ #else
376+ return 0 ;
377+ #endif
378+ } else if (func -> type == ZEND_USER_FUNCTION ) {
379+ if (func -> common .fn_flags & ZEND_ACC_PRELOADED ) {
380+ return 0 ;
381+ }
382+ if (func -> op_array .filename == called_from -> filename && !func -> op_array .scope ) {
383+ return 0 ;
384+ }
385+ }
386+ return 1 ;
387+ }
388+
369389static zend_always_inline uint32_t zend_jit_trace_type_to_info_ex (zend_uchar type , uint32_t info )
370390{
371391 if (type == IS_UNKNOWN ) {
@@ -6081,10 +6101,11 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
60816101 if (!zend_jit_trace_handler (& dasm_state , op_array , opline , zend_may_throw (opline , ssa_op , op_array , ssa ), p + 1 )) {
60826102 goto jit_failure ;
60836103 }
6084- if ((opline -> opcode != ZEND_INIT_STATIC_METHOD_CALL
6104+ if ((p + 1 )-> op == ZEND_JIT_TRACE_INIT_CALL && (p + 1 )-> func
6105+ && (opline -> opcode != ZEND_INIT_STATIC_METHOD_CALL
60856106 || opline -> op1_type != IS_CONST
6086- || opline -> op2_type != IS_CONST )
6087- && ( p + 1 ) -> op == ZEND_JIT_TRACE_INIT_CALL && ( p + 1 )-> func ) {
6107+ || opline -> op2_type != IS_CONST
6108+ || zend_jit_may_be_modified (( p + 1 )-> func , op_array )) ) {
60886109 if (!zend_jit_init_fcall_guard (& dasm_state , 0 , (p + 1 )-> func , opline + 1 )) {
60896110 goto jit_failure ;
60906111 }
@@ -6094,8 +6115,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
60946115 if (!zend_jit_trace_handler (& dasm_state , op_array , opline , zend_may_throw (opline , ssa_op , op_array , ssa ), p + 1 )) {
60956116 goto jit_failure ;
60966117 }
6097- if (opline -> op2_type != IS_CONST
6098- && (p + 1 )-> op == ZEND_JIT_TRACE_INIT_CALL && (p + 1 )-> func ) {
6118+ if ((p + 1 )-> op == ZEND_JIT_TRACE_INIT_CALL && (p + 1 )-> func
6119+ && (opline -> op2_type != IS_CONST
6120+ || zend_jit_may_be_modified ((p + 1 )-> func , op_array ))) {
60996121 if (!zend_jit_init_fcall_guard (& dasm_state , 0 , (p + 1 )-> func , opline + 1 )) {
61006122 goto jit_failure ;
61016123 }
@@ -6105,8 +6127,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
61056127 if (!zend_jit_trace_handler (& dasm_state , op_array , opline , zend_may_throw (opline , ssa_op , op_array , ssa ), p + 1 )) {
61066128 goto jit_failure ;
61076129 }
6108- if (opline -> op1_type != IS_CONST
6109- && (p + 1 )-> op == ZEND_JIT_TRACE_INIT_CALL && (p + 1 )-> func ) {
6130+ if ((p + 1 )-> op == ZEND_JIT_TRACE_INIT_CALL && (p + 1 )-> func
6131+ && (opline -> op1_type != IS_CONST
6132+ || zend_jit_may_be_modified ((p + 1 )-> func , op_array ))) {
61106133 SET_STACK_TYPE (stack , EX_VAR_TO_NUM (opline -> result .var ), IS_OBJECT , 1 );
61116134 if (!zend_jit_init_fcall_guard (& dasm_state , 0 , (p + 1 )-> func , opline + 1 )) {
61126135 goto jit_failure ;
@@ -6672,8 +6695,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
66726695 call_info = call_info -> next_callee ;
66736696 }
66746697 if (!skip_guard
6675- && !zend_jit_may_be_polymorphic_call (init_opline )) {
6676- // TODO: recompilation may change target ???
6698+ && !zend_jit_may_be_polymorphic_call (init_opline )
6699+ && ! zend_jit_may_be_modified ( p -> func , op_array )) {
66776700 skip_guard = 1 ;
66786701 }
66796702 }
@@ -7006,6 +7029,7 @@ static zend_jit_trace_stop zend_jit_compile_root_trace(zend_jit_trace_rec *trace
70067029 t -> flags = 0 ;
70077030 t -> polymorphism = 0 ;
70087031 t -> jmp_table_size = 0 ;
7032+ t -> op_array = trace_buffer [0 ].op_array ;
70097033 t -> opline = trace_buffer [1 ].opline ;
70107034 t -> exit_info = exit_info ;
70117035 t -> stack_map = NULL ;
@@ -8034,6 +8058,35 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf
80348058 EX (opline )-> lineno );
80358059 }
80368060
8061+ if (t -> exit_info [exit_num ].flags & ZEND_JIT_EXIT_INVALIDATE ) {
8062+ zend_jit_op_array_trace_extension * jit_extension ;
8063+ uint32_t num = trace_num ;
8064+
8065+ while (t -> root != num ) {
8066+ num = t -> root ;
8067+ t = & zend_jit_traces [num ];
8068+ }
8069+
8070+ SHM_UNPROTECT ();
8071+ zend_jit_unprotect ();
8072+
8073+ jit_extension = (zend_jit_op_array_trace_extension * )ZEND_FUNC_INFO (t -> op_array );
8074+ if (ZEND_OP_TRACE_INFO (t -> opline , jit_extension -> offset )-> trace_flags & ZEND_JIT_TRACE_START_LOOP ) {
8075+ ((zend_op * )(t -> opline ))-> handler = (const void * )zend_jit_loop_trace_counter_handler ;
8076+ } else if (ZEND_OP_TRACE_INFO (t -> opline , jit_extension -> offset )-> trace_flags & ZEND_JIT_TRACE_START_ENTER ) {
8077+ ((zend_op * )(t -> opline ))-> handler = (const void * )zend_jit_func_trace_counter_handler ;
8078+ } else if (ZEND_OP_TRACE_INFO (t -> opline , jit_extension -> offset )-> trace_flags & ZEND_JIT_TRACE_START_RETURN ) {
8079+ ((zend_op * )(t -> opline ))-> handler = (const void * )zend_jit_ret_trace_counter_handler ;
8080+ }
8081+ ZEND_OP_TRACE_INFO (t -> opline , jit_extension -> offset )-> trace_flags &=
8082+ ZEND_JIT_TRACE_START_LOOP |ZEND_JIT_TRACE_START_ENTER |ZEND_JIT_TRACE_START_RETURN ;
8083+
8084+ zend_jit_protect ();
8085+ SHM_PROTECT ();
8086+
8087+ return 0 ;
8088+ }
8089+
80378090 if (t -> exit_info [exit_num ].flags & ZEND_JIT_EXIT_TO_VM ) {
80388091 if (zend_jit_trace_exit_is_bad (trace_num , exit_num )) {
80398092 zend_jit_blacklist_trace_exit (trace_num , exit_num );
0 commit comments