@@ -1587,6 +1587,20 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
15871587 }
15881588 ADD_OP2_TRACE_GUARD ();
15891589 }
1590+ if (op1_type == IS_ARRAY
1591+ && !(orig_op1_type & IS_TRACE_PACKED )
1592+ && ((opline -> op2_type == IS_CONST
1593+ && Z_TYPE_P (RT_CONSTANT (opline , opline -> op2 )) == IS_LONG )
1594+ || (opline -> op2_type != IS_CONST
1595+ && op2_type == IS_LONG ))) {
1596+
1597+ zend_ssa_var_info * info = & tssa -> var_info [tssa -> ops [idx ].op1_use ];
1598+
1599+ if (MAY_BE_PACKED (info -> type ) && MAY_BE_HASH (info -> type )) {
1600+ info -> type |= MAY_BE_PACKED_GUARD ;
1601+ info -> type &= ~MAY_BE_ARRAY_PACKED ;
1602+ }
1603+ }
15901604 break ;
15911605 case ZEND_ASSIGN_OBJ_OP :
15921606 if (opline -> extended_value == ZEND_POW
@@ -1734,22 +1748,19 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
17341748 ADD_OP1_TRACE_GUARD ();
17351749 ADD_OP2_TRACE_GUARD ();
17361750
1737- if (opline -> op1_type != IS_CONST
1738- && op1_type == IS_ARRAY
1751+ if (op1_type == IS_ARRAY
1752+ && opline -> op1_type != IS_CONST
17391753 && ((opline -> op2_type == IS_CONST
17401754 && Z_TYPE_P (RT_CONSTANT (opline , opline -> op2 )) == IS_LONG )
17411755 || (opline -> op2_type != IS_CONST
17421756 && op2_type == IS_LONG ))) {
17431757
17441758 zend_ssa_var_info * info = & tssa -> var_info [tssa -> ops [idx ].op1_use ];
17451759
1746- if ((info -> type & MAY_BE_ARRAY_PACKED )
1747- && (info -> type & MAY_BE_ARRAY_HASH )
1748- && orig_op1_type != IS_UNKNOWN
1749- && !(orig_op1_type & IS_TRACE_REFERENCE )) {
1760+ if (MAY_BE_PACKED (info -> type ) && MAY_BE_HASH (info -> type )) {
17501761 info -> type |= MAY_BE_PACKED_GUARD ;
17511762 if (orig_op1_type & IS_TRACE_PACKED ) {
1752- info -> type &= ~MAY_BE_ARRAY_HASH ;
1763+ info -> type &= ~( MAY_BE_ARRAY_NUMERIC_HASH | MAY_BE_ARRAY_STRING_HASH ) ;
17531764 } else {
17541765 info -> type &= ~MAY_BE_ARRAY_PACKED ;
17551766 }
@@ -1767,6 +1778,20 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
17671778 }
17681779 ADD_OP1_TRACE_GUARD ();
17691780 ADD_OP2_TRACE_GUARD ();
1781+ if (op1_type == IS_ARRAY
1782+ && !(orig_op1_type & IS_TRACE_PACKED )
1783+ && ((opline -> op2_type == IS_CONST
1784+ && Z_TYPE_P (RT_CONSTANT (opline , opline -> op2 )) == IS_LONG )
1785+ || (opline -> op2_type != IS_CONST
1786+ && op2_type == IS_LONG ))) {
1787+
1788+ zend_ssa_var_info * info = & tssa -> var_info [tssa -> ops [idx ].op1_use ];
1789+
1790+ if (MAY_BE_PACKED (info -> type ) && MAY_BE_HASH (info -> type )) {
1791+ info -> type |= MAY_BE_PACKED_GUARD ;
1792+ info -> type &= ~MAY_BE_ARRAY_PACKED ;
1793+ }
1794+ }
17701795 break ;
17711796 case ZEND_SEND_VAL_EX :
17721797 case ZEND_SEND_VAR_EX :
@@ -2293,35 +2318,80 @@ static zend_ssa *zend_jit_trace_build_tssa(zend_jit_trace_rec *trace_buffer, uin
22932318 ssa = & jit_extension -> func_info .ssa ;
22942319
22952320 while (phi ) {
2296- uint32_t t = ssa_var_info [phi -> ssa_var ].type ;
2297- uint32_t t0 = ssa_var_info [phi -> sources [0 ]].type ;
2298- uint32_t t1 = ssa_var_info [phi -> sources [1 ]].type ;
2321+ uint32_t t = ssa_var_info [phi -> ssa_var ].type ;
22992322
2300- if (t & MAY_BE_GUARD ) {
2301- if (tssa -> vars [phi -> ssa_var ].alias != NO_ALIAS ) {
2302- /* pass */
2303- } else if (((t0 | t1 ) & (MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF )) == (t & (MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF ))) {
2323+ if ((t & MAY_BE_GUARD ) && tssa -> vars [phi -> ssa_var ].alias == NO_ALIAS ) {
2324+ uint32_t t0 = ssa_var_info [phi -> sources [0 ]].type ;
2325+ uint32_t t1 = ssa_var_info [phi -> sources [1 ]].type ;
2326+
2327+ if (((t0 | t1 ) & (MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF )) == (t & (MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF ))) {
23042328 if (!((t0 | t1 ) & MAY_BE_GUARD )) {
23052329 ssa_var_info [phi -> ssa_var ].type = t & ~MAY_BE_GUARD ;
23062330 }
23072331 } else if ((t1 & (MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF )) == (t & (MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF ))) {
23082332 if (!(t1 & MAY_BE_GUARD )
23092333 || is_checked_guard (tssa , ssa_opcodes , phi -> sources [1 ], phi -> ssa_var )) {
23102334 ssa_var_info [phi -> ssa_var ].type = t & ~MAY_BE_GUARD ;
2311- ssa_var_info [phi -> sources [0 ]].type = t | MAY_BE_GUARD ;
2335+ t0 = (t & (MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF )) |
2336+ (t0 & ~(MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF )) |
2337+ MAY_BE_GUARD ;
2338+ if (!(t0 & MAY_BE_ARRAY )) {
2339+ t0 &= ~(MAY_BE_ARRAY_OF_ANY |MAY_BE_ARRAY_OF_REF |MAY_BE_ARRAY_KEY_ANY );
2340+ }
2341+ if (!(t0 & (MAY_BE_STRING |MAY_BE_ARRAY |MAY_BE_OBJECT |MAY_BE_RESOURCE ))) {
2342+ t0 &= ~(MAY_BE_RC1 |MAY_BE_RCN );
2343+ }
2344+ ssa_var_info [phi -> sources [0 ]].type = t0 ;
2345+ ssa_var_info [phi -> sources [0 ]].type = t0 ;
23122346 }
23132347 } else {
23142348 if ((t0 & (MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF )) != (t & (MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF ))) {
2315- ssa_var_info [phi -> sources [0 ]].type = MAY_BE_GUARD | (t & t0 );
2349+ t0 = (t & t0 & (MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF )) |
2350+ (t0 & ~(MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF )) |
2351+ MAY_BE_GUARD ;
2352+ if (!(t0 & MAY_BE_ARRAY )) {
2353+ t0 &= ~(MAY_BE_ARRAY_OF_ANY |MAY_BE_ARRAY_OF_REF |MAY_BE_ARRAY_KEY_ANY );
2354+ }
2355+ if (!(t0 & (MAY_BE_STRING |MAY_BE_ARRAY |MAY_BE_OBJECT |MAY_BE_RESOURCE ))) {
2356+ t0 &= ~(MAY_BE_RC1 |MAY_BE_RCN );
2357+ }
2358+ ssa_var_info [phi -> sources [0 ]].type = t0 ;
23162359 }
23172360 if ((t1 & (MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF )) != (t & (MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF ))) {
23182361 if (((t & t1 ) & (MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF )) != 0
23192362 && is_checked_guard (tssa , ssa_opcodes , phi -> sources [1 ], phi -> ssa_var )) {
2320- ssa_var_info [phi -> sources [1 ]].type = MAY_BE_GUARD | (t & t1 );
2363+ t1 = (t & t1 & (MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF )) |
2364+ (t1 & ~(MAY_BE_ANY |MAY_BE_UNDEF |MAY_BE_REF )) |
2365+ MAY_BE_GUARD ;
2366+ if (!(t1 & MAY_BE_ARRAY )) {
2367+ t1 &= ~(MAY_BE_ARRAY_OF_ANY |MAY_BE_ARRAY_OF_REF |MAY_BE_ARRAY_KEY_ANY );
2368+ }
2369+ if (!(t1 & (MAY_BE_STRING |MAY_BE_ARRAY |MAY_BE_OBJECT |MAY_BE_RESOURCE ))) {
2370+ t1 &= ~(MAY_BE_RC1 |MAY_BE_RCN );
2371+ }
2372+ ssa_var_info [phi -> sources [1 ]].type = t1 ;
23212373 ssa_var_info [phi -> ssa_var ].type = t & ~MAY_BE_GUARD ;
23222374 }
23232375 }
23242376 }
2377+ t = ssa_var_info [phi -> ssa_var ].type ;
2378+ }
2379+
2380+ if ((t & MAY_BE_PACKED_GUARD ) && tssa -> vars [phi -> ssa_var ].alias == NO_ALIAS ) {
2381+ uint32_t t0 = ssa_var_info [phi -> sources [0 ]].type ;
2382+ uint32_t t1 = ssa_var_info [phi -> sources [1 ]].type ;
2383+
2384+ if (((t0 | t1 ) & MAY_BE_ARRAY_KEY_ANY ) == (t & MAY_BE_ARRAY_KEY_ANY )) {
2385+ if (!((t0 | t1 ) & MAY_BE_PACKED_GUARD )) {
2386+ ssa_var_info [phi -> ssa_var ].type = t & ~MAY_BE_PACKED_GUARD ;
2387+ }
2388+ } else if ((t1 & MAY_BE_ARRAY_KEY_ANY ) == (t & MAY_BE_ARRAY_KEY_ANY )) {
2389+ if (!(t1 & MAY_BE_PACKED_GUARD )) {
2390+ ssa_var_info [phi -> ssa_var ].type = t & ~MAY_BE_PACKED_GUARD ;
2391+ ssa_var_info [phi -> sources [0 ]].type =
2392+ (t0 & ~MAY_BE_ARRAY_KEY_ANY ) | (t & MAY_BE_ARRAY_KEY_ANY ) | MAY_BE_PACKED_GUARD ;
2393+ }
2394+ }
23252395 }
23262396 phi = phi -> next ;
23272397 }
@@ -3825,7 +3895,9 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
38253895 && (trace_buffer -> stop == ZEND_JIT_TRACE_STOP_LOOP
38263896 || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_CALL
38273897 || trace_buffer -> stop == ZEND_JIT_TRACE_STOP_RECURSIVE_RET )
3828- && ssa -> vars [i ].use_chain != -1 ) {
3898+ && (ssa -> vars [i ].use_chain != -1
3899+ || (ssa -> vars [i ].phi_use_chain
3900+ && !(ssa -> var_info [ssa -> vars [i ].phi_use_chain -> ssa_var ].type & MAY_BE_PACKED_GUARD )))) {
38293901 if (!zend_jit_packed_guard (& dasm_state , opline , EX_NUM_TO_VAR (i ), info )) {
38303902 goto jit_failure ;
38313903 }
@@ -5170,12 +5242,12 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
51705242 ssa -> var_info [ssa_op -> op1_use ].type &= ~MAY_BE_PACKED_GUARD ;
51715243 } else if ((op2_info & (MAY_BE_ANY |MAY_BE_UNDEF )) == MAY_BE_LONG
51725244 && (op1_info & (MAY_BE_ANY |MAY_BE_UNDEF )) == MAY_BE_ARRAY
5173- && (op1_info & MAY_BE_ARRAY_PACKED )
5174- && (op1_info & MAY_BE_ARRAY_HASH )
5245+ && MAY_BE_PACKED (op1_info )
5246+ && MAY_BE_HASH (op1_info )
51755247 && orig_op1_type != IS_UNKNOWN ) {
51765248 op1_info |= MAY_BE_PACKED_GUARD ;
51775249 if (orig_op1_type & IS_TRACE_PACKED ) {
5178- op1_info &= ~MAY_BE_ARRAY_HASH ;
5250+ op1_info &= ~( MAY_BE_ARRAY_NUMERIC_HASH | MAY_BE_ARRAY_STRING_HASH ) ;
51795251 } else {
51805252 op1_info &= ~MAY_BE_ARRAY_PACKED ;
51815253 }
@@ -5313,12 +5385,12 @@ static const void *zend_jit_trace(zend_jit_trace_rec *trace_buffer, uint32_t par
53135385 ssa -> var_info [ssa_op -> op1_use ].type &= ~MAY_BE_PACKED_GUARD ;
53145386 } else if ((op2_info & (MAY_BE_ANY |MAY_BE_UNDEF )) == MAY_BE_LONG
53155387 && (op1_info & (MAY_BE_ANY |MAY_BE_UNDEF )) == MAY_BE_ARRAY
5316- && (op1_info & MAY_BE_ARRAY_PACKED )
5317- && (op1_info & MAY_BE_ARRAY_HASH )
5388+ && MAY_BE_PACKED (op1_info )
5389+ && MAY_BE_HASH (op1_info )
53185390 && orig_op1_type != IS_UNKNOWN ) {
53195391 op1_info |= MAY_BE_PACKED_GUARD ;
53205392 if (orig_op1_type & IS_TRACE_PACKED ) {
5321- op1_info &= ~MAY_BE_ARRAY_HASH ;
5393+ op1_info &= ~( MAY_BE_ARRAY_NUMERIC_HASH | MAY_BE_ARRAY_STRING_HASH ) ;
53225394 } else {
53235395 op1_info &= ~MAY_BE_ARRAY_PACKED ;
53245396 }
0 commit comments