@@ -366,6 +366,26 @@ static int zend_jit_trace_may_exit(const zend_op_array *op_array, const zend_op
366
366
return 0 ;
367
367
}
368
368
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
+
369
389
static zend_always_inline uint32_t zend_jit_trace_type_to_info_ex (zend_uchar type , uint32_t info )
370
390
{
371
391
if (type == IS_UNKNOWN ) {
@@ -6081,10 +6101,11 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
6081
6101
if (!zend_jit_trace_handler (& dasm_state , op_array , opline , zend_may_throw (opline , ssa_op , op_array , ssa ), p + 1 )) {
6082
6102
goto jit_failure ;
6083
6103
}
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
6085
6106
|| 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 )) ) {
6088
6109
if (!zend_jit_init_fcall_guard (& dasm_state , 0 , (p + 1 )-> func , opline + 1 )) {
6089
6110
goto jit_failure ;
6090
6111
}
@@ -6094,8 +6115,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
6094
6115
if (!zend_jit_trace_handler (& dasm_state , op_array , opline , zend_may_throw (opline , ssa_op , op_array , ssa ), p + 1 )) {
6095
6116
goto jit_failure ;
6096
6117
}
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 ))) {
6099
6121
if (!zend_jit_init_fcall_guard (& dasm_state , 0 , (p + 1 )-> func , opline + 1 )) {
6100
6122
goto jit_failure ;
6101
6123
}
@@ -6105,8 +6127,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
6105
6127
if (!zend_jit_trace_handler (& dasm_state , op_array , opline , zend_may_throw (opline , ssa_op , op_array , ssa ), p + 1 )) {
6106
6128
goto jit_failure ;
6107
6129
}
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 ))) {
6110
6133
SET_STACK_TYPE (stack , EX_VAR_TO_NUM (opline -> result .var ), IS_OBJECT , 1 );
6111
6134
if (!zend_jit_init_fcall_guard (& dasm_state , 0 , (p + 1 )-> func , opline + 1 )) {
6112
6135
goto jit_failure ;
@@ -6672,8 +6695,8 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
6672
6695
call_info = call_info -> next_callee ;
6673
6696
}
6674
6697
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 )) {
6677
6700
skip_guard = 1 ;
6678
6701
}
6679
6702
}
@@ -7006,6 +7029,7 @@ static zend_jit_trace_stop zend_jit_compile_root_trace(zend_jit_trace_rec *trace
7006
7029
t -> flags = 0 ;
7007
7030
t -> polymorphism = 0 ;
7008
7031
t -> jmp_table_size = 0 ;
7032
+ t -> op_array = trace_buffer [0 ].op_array ;
7009
7033
t -> opline = trace_buffer [1 ].opline ;
7010
7034
t -> exit_info = exit_info ;
7011
7035
t -> stack_map = NULL ;
@@ -8034,6 +8058,35 @@ int ZEND_FASTCALL zend_jit_trace_exit(uint32_t exit_num, zend_jit_registers_buf
8034
8058
EX (opline )-> lineno );
8035
8059
}
8036
8060
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
+
8037
8090
if (t -> exit_info [exit_num ].flags & ZEND_JIT_EXIT_TO_VM ) {
8038
8091
if (zend_jit_trace_exit_is_bad (trace_num , exit_num )) {
8039
8092
zend_jit_blacklist_trace_exit (trace_num , exit_num );
0 commit comments