@@ -3842,6 +3842,126 @@ static bool zend_jit_trace_next_is_send_result(const zend_op *oplin
3842
3842
return 0 ;
3843
3843
}
3844
3844
3845
+ static int zend_jit_find_ssa_var (const zend_op_array * op_array ,
3846
+ const zend_ssa * ssa ,
3847
+ uint32_t opline_num ,
3848
+ uint32_t var_num )
3849
+ {
3850
+ int ssa_var , j , b = ssa -> cfg .map [opline_num ];
3851
+ const zend_basic_block * bb = ssa -> cfg .blocks + b ;
3852
+ const zend_ssa_phi * phi ;
3853
+ const zend_ssa_op * ssa_op ;
3854
+ zend_worklist worklist ;
3855
+ ALLOCA_FLAG (use_heap )
3856
+
3857
+ while (1 ) {
3858
+ ssa_op = ssa -> ops + opline_num ;
3859
+ ssa_var = ssa_op -> result_def ;
3860
+ if (ssa_var >= 0 && ssa -> vars [ssa_var ].var == var_num ) {
3861
+ return ssa_var ;
3862
+ }
3863
+ ssa_var = ssa_op -> op2_def ;
3864
+ if (ssa_var >= 0 && ssa -> vars [ssa_var ].var == var_num ) {
3865
+ return ssa_var ;
3866
+ }
3867
+ ssa_var = ssa_op -> op1_def ;
3868
+ if (ssa_var >= 0 && ssa -> vars [ssa_var ].var == var_num ) {
3869
+ return ssa_var ;
3870
+ }
3871
+ if (opline_num == bb -> start ) {
3872
+ break ;
3873
+ }
3874
+ opline_num -- ;
3875
+ }
3876
+ phi = ssa -> blocks [b ].phis ;
3877
+ ssa_var = -1 ;
3878
+ while (phi ) {
3879
+ if (phi -> var == var_num ) {
3880
+ ssa_var = phi -> ssa_var ;
3881
+ }
3882
+ phi = phi -> next ;
3883
+ }
3884
+ if (ssa_var >= 0 ) {
3885
+ return ssa_var ;
3886
+ }
3887
+
3888
+ if (!bb -> predecessors_count ) {
3889
+ return -1 ;
3890
+ }
3891
+
3892
+ ZEND_WORKLIST_ALLOCA (& worklist , ssa -> cfg .blocks_count , use_heap );
3893
+
3894
+ for (j = 0 ; j < bb -> predecessors_count ; j ++ ) {
3895
+ b = ssa -> cfg .predecessors [bb -> predecessor_offset + j ];
3896
+ zend_worklist_push (& worklist , b );
3897
+ }
3898
+
3899
+ while (zend_worklist_len (& worklist ) != 0 ) {
3900
+ b = zend_worklist_pop (& worklist );
3901
+ bb = & ssa -> cfg .blocks [b ];
3902
+ if (bb -> len ) {
3903
+ opline_num = bb -> start + bb -> len - 1 ;
3904
+ while (1 ) {
3905
+ ssa_op = ssa -> ops + opline_num ;
3906
+ ssa_var = ssa_op -> result_def ;
3907
+ if (ssa_var >= 0 && ssa -> vars [ssa_var ].var == var_num ) {
3908
+ goto found ;
3909
+ }
3910
+ ssa_var = ssa_op -> op2_def ;
3911
+ if (ssa_var >= 0 && ssa -> vars [ssa_var ].var == var_num ) {
3912
+ goto found ;
3913
+ }
3914
+ ssa_var = ssa_op -> op1_def ;
3915
+ if (ssa_var >= 0 && ssa -> vars [ssa_var ].var == var_num ) {
3916
+ goto found ;
3917
+ }
3918
+ if (opline_num == bb -> start ) {
3919
+ break ;
3920
+ }
3921
+ opline_num -- ;
3922
+ }
3923
+ }
3924
+ phi = ssa -> blocks [b ].phis ;
3925
+ ssa_var = -1 ;
3926
+ while (phi ) {
3927
+ if (phi -> var == var_num ) {
3928
+ ssa_var = phi -> ssa_var ;
3929
+ }
3930
+ phi = phi -> next ;
3931
+ }
3932
+ if (ssa_var >= 0 ) {
3933
+ goto found ;
3934
+ }
3935
+ for (j = 0 ; j < bb -> predecessors_count ; j ++ ) {
3936
+ b = ssa -> cfg .predecessors [bb -> predecessor_offset + j ];
3937
+ zend_worklist_push (& worklist , b );
3938
+ }
3939
+ }
3940
+ return -1 ;
3941
+
3942
+ found :
3943
+ ZEND_WORKLIST_FREE_ALLOCA (& worklist , use_heap );
3944
+ return ssa_var ;
3945
+ }
3946
+
3947
+ static bool zend_jit_trace_must_store_type (const zend_op_array * op_array ,
3948
+ const zend_ssa * ssa ,
3949
+ uint32_t opline_num ,
3950
+ uint32_t var_num ,
3951
+ uint8_t type )
3952
+ {
3953
+ if (ssa -> var_info ) {
3954
+ int ssa_var = zend_jit_find_ssa_var (op_array , ssa , opline_num , var_num );
3955
+
3956
+ if (ssa_var >= 0 ) {
3957
+ if ((ssa -> var_info [ssa_var ].type & (MAY_BE_ANY |MAY_BE_UNDEF )) != (1U << type )) {
3958
+ return 0 ;
3959
+ }
3960
+ }
3961
+ }
3962
+ return 1 ;
3963
+ }
3964
+
3845
3965
static const void * zend_jit_trace (zend_jit_trace_rec * trace_buffer , uint32_t parent_trace , uint32_t exit_num )
3846
3966
{
3847
3967
const void * handler = NULL ;
@@ -6861,12 +6981,15 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
6861
6981
int32_t ref = STACK_REF (stack , i );
6862
6982
uint8_t type = STACK_TYPE (stack , i );
6863
6983
6864
- if (ref && ( !(STACK_FLAGS (stack , i ) & (ZREG_LOAD |ZREG_STORE ) ))) {
6984
+ if (ref && !(STACK_FLAGS (stack , i ) & (ZREG_LOAD |ZREG_STORE ))) {
6865
6985
if (!zend_jit_store_ref (jit , 1 << type , i , ref , STACK_MEM_TYPE (stack , i ) != type )) {
6866
6986
goto jit_failure ;
6867
6987
}
6868
6988
SET_STACK_TYPE (stack , i , type , 1 );
6869
- } else if (type != IS_UNKNOWN && type != STACK_MEM_TYPE (stack , i )) {
6989
+ } else if (i < op_array -> last_var
6990
+ && type != IS_UNKNOWN
6991
+ && type != STACK_MEM_TYPE (stack , i )
6992
+ && zend_jit_trace_must_store_type (op_array , op_array_ssa , opline - op_array -> opcodes , i , type )) {
6870
6993
if (!zend_jit_store_type (jit , i , type )) {
6871
6994
return 0 ;
6872
6995
}
0 commit comments