@@ -365,6 +365,26 @@ static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op
365365 return 0 ;
366366}
367367
368+ static bool zend_jit_may_be_modified (const zend_function * func , const zend_op_array * called_from )
369+ {
370+ if (func -> type == ZEND_INTERNAL_FUNCTION ) {
371+ #ifdef _WIN32
372+ /* ASLR */
373+ return 1 ;
374+ #else
375+ return 0 ;
376+ #endif
377+ } else if (func -> type == ZEND_USER_FUNCTION ) {
378+ if (func -> common .fn_flags & ZEND_ACC_PRELOADED ) {
379+ return 0 ;
380+ }
381+ if (func -> op_array .filename == called_from -> filename && !func -> op_array .scope ) {
382+ return 0 ;
383+ }
384+ }
385+ return 1 ;
386+ }
387+
368388static zend_always_inline uint32_t zend_jit_trace_type_to_info_ex (zend_uchar type , uint32_t info )
369389{
370390 if (type == IS_UNKNOWN ) {
@@ -6085,10 +6105,11 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
60856105 if (!zend_jit_trace_handler (& dasm_state , op_array , opline , zend_may_throw (opline , ssa_op , op_array , ssa ), p + 1 )) {
60866106 goto jit_failure ;
60876107 }
6088- if ((opline -> opcode != ZEND_INIT_STATIC_METHOD_CALL
6108+ if ((p + 1 )-> op == ZEND_JIT_TRACE_INIT_CALL && (p + 1 )-> func
6109+ && (opline -> opcode != ZEND_INIT_STATIC_METHOD_CALL
60896110 || opline -> op1_type != IS_CONST
6090- || opline -> op2_type != IS_CONST )
6091- && ( p + 1 ) -> op == ZEND_JIT_TRACE_INIT_CALL && ( p + 1 )-> func ) {
6111+ || opline -> op2_type != IS_CONST
6112+ || zend_jit_may_be_modified (( p + 1 )-> func , op_array )) ) {
60926113 if (!zend_jit_init_fcall_guard (& dasm_state , 0 , (p + 1 )-> func , opline + 1 )) {
60936114 goto jit_failure ;
60946115 }
@@ -6098,8 +6119,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
60986119 if (!zend_jit_trace_handler (& dasm_state , op_array , opline , zend_may_throw (opline , ssa_op , op_array , ssa ), p + 1 )) {
60996120 goto jit_failure ;
61006121 }
6101- if (opline -> op2_type != IS_CONST
6102- && (p + 1 )-> op == ZEND_JIT_TRACE_INIT_CALL && (p + 1 )-> func ) {
6122+ if ((p + 1 )-> op == ZEND_JIT_TRACE_INIT_CALL && (p + 1 )-> func
6123+ && (opline -> op2_type != IS_CONST
6124+ || zend_jit_may_be_modified ((p + 1 )-> func , op_array ))) {
61036125 if (!zend_jit_init_fcall_guard (& dasm_state , 0 , (p + 1 )-> func , opline + 1 )) {
61046126 goto jit_failure ;
61056127 }
@@ -6109,8 +6131,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
61096131 if (!zend_jit_trace_handler (& dasm_state , op_array , opline , zend_may_throw (opline , ssa_op , op_array , ssa ), p + 1 )) {
61106132 goto jit_failure ;
61116133 }
6112- if (opline -> op1_type != IS_CONST
6113- && (p + 1 )-> op == ZEND_JIT_TRACE_INIT_CALL && (p + 1 )-> func ) {
6134+ if ((p + 1 )-> op == ZEND_JIT_TRACE_INIT_CALL && (p + 1 )-> func
6135+ && (opline -> op1_type != IS_CONST
6136+ || zend_jit_may_be_modified ((p + 1 )-> func , op_array ))) {
61146137 SET_STACK_TYPE (stack , EX_VAR_TO_NUM (opline -> result .var ), IS_OBJECT , 1 );
61156138 if (!zend_jit_init_fcall_guard (& dasm_state , 0 , (p + 1 )-> func , opline + 1 )) {
61166139 goto jit_failure ;
@@ -6689,8 +6712,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
66896712 call_info = call_info -> next_callee ;
66906713 }
66916714 if (!skip_guard
6692- && !zend_jit_may_be_polymorphic_call (init_opline )) {
6693- // TODO: recompilation may change target ???
6715+ && !zend_jit_may_be_polymorphic_call (init_opline )
6716+ && ! zend_jit_may_be_modified ( p -> func , op_array )) {
66946717 skip_guard = 1 ;
66956718 }
66966719 }
@@ -7023,6 +7046,7 @@ static zend_jit_trace_stop zend_jit_compile_root_trace(zend_jit_trace_rec *trace
70237046 t -> flags = 0 ;
70247047 t -> polymorphism = 0 ;
70257048 t -> jmp_table_size = 0 ;
7049+ t -> op_array = trace_buffer [0 ].op_array ;
70267050 t -> opline = trace_buffer [1 ].opline ;
70277051 t -> exit_info = exit_info ;
70287052 t -> stack_map = NULL ;
@@ -8051,6 +8075,35 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf
80518075 EX (opline )-> lineno );
80528076 }
80538077
8078+ if (t -> exit_info [exit_num ].flags & ZEND_JIT_EXIT_INVALIDATE ) {
8079+ zend_jit_op_array_trace_extension * jit_extension ;
8080+ uint32_t num = trace_num ;
8081+
8082+ while (t -> root != num ) {
8083+ num = t -> root ;
8084+ t = & zend_jit_traces [num ];
8085+ }
8086+
8087+ SHM_UNPROTECT ();
8088+ zend_jit_unprotect ();
8089+
8090+ jit_extension = (zend_jit_op_array_trace_extension * )ZEND_FUNC_INFO (t -> op_array );
8091+ if (ZEND_OP_TRACE_INFO (t -> opline , jit_extension -> offset )-> trace_flags & ZEND_JIT_TRACE_START_LOOP ) {
8092+ ((zend_op * )(t -> opline ))-> handler = (const void * )zend_jit_loop_trace_counter_handler ;
8093+ } else if (ZEND_OP_TRACE_INFO (t -> opline , jit_extension -> offset )-> trace_flags & ZEND_JIT_TRACE_START_ENTER ) {
8094+ ((zend_op * )(t -> opline ))-> handler = (const void * )zend_jit_func_trace_counter_handler ;
8095+ } else if (ZEND_OP_TRACE_INFO (t -> opline , jit_extension -> offset )-> trace_flags & ZEND_JIT_TRACE_START_RETURN ) {
8096+ ((zend_op * )(t -> opline ))-> handler = (const void * )zend_jit_ret_trace_counter_handler ;
8097+ }
8098+ ZEND_OP_TRACE_INFO (t -> opline , jit_extension -> offset )-> trace_flags &=
8099+ ZEND_JIT_TRACE_START_LOOP |ZEND_JIT_TRACE_START_ENTER |ZEND_JIT_TRACE_START_RETURN ;
8100+
8101+ zend_jit_protect ();
8102+ SHM_PROTECT ();
8103+
8104+ return 0 ;
8105+ }
8106+
80548107 if (t -> exit_info [exit_num ].flags & ZEND_JIT_EXIT_TO_VM ) {
80558108 if (zend_jit_trace_exit_is_bad (trace_num , exit_num )) {
80568109 zend_jit_blacklist_trace_exit (trace_num , exit_num );
0 commit comments