@@ -490,6 +490,19 @@ static zend_always_inline void take_successor_1(zend_ssa *ssa, int block_num, ze
490
490
}
491
491
}
492
492
493
+ static zend_always_inline void take_successor_ex (zend_ssa * ssa , int block_num , zend_basic_block * block , int target_block )
494
+ {
495
+ int i ;
496
+
497
+ for (i = 0 ; i < block -> successors_count ; i ++ ) {
498
+ if (block -> successors [i ] != target_block ) {
499
+ zend_ssa_remove_predecessor (ssa , block_num , block -> successors [i ]);
500
+ }
501
+ }
502
+ block -> successors [0 ] = target_block ;
503
+ block -> successors_count = 1 ;
504
+ }
505
+
493
506
static void compress_block (zend_op_array * op_array , zend_basic_block * block )
494
507
{
495
508
while (block -> len > 0 ) {
@@ -857,6 +870,64 @@ static int zend_dfa_optimize_jmps(zend_op_array *op_array, zend_ssa *ssa)
857
870
}
858
871
break ;
859
872
}
873
+ case ZEND_SWITCH_LONG :
874
+ if (opline -> op1_type == IS_CONST ) {
875
+ zval * zv = CT_CONSTANT_EX (op_array , opline -> op1 .constant );
876
+ if (Z_TYPE_P (zv ) != IS_LONG ) {
877
+ removed_ops ++ ;
878
+ MAKE_NOP (opline );
879
+ opline -> extended_value = 0 ;
880
+ take_successor_ex (ssa , block_num , block , block -> successors [0 ]);
881
+ goto optimize_nop ;
882
+ } else {
883
+ HashTable * jmptable = Z_ARRVAL_P (CT_CONSTANT_EX (op_array , opline -> op2 .constant ));
884
+ zval * jmp_zv = zend_hash_index_find (jmptable , Z_LVAL_P (zv ));
885
+ uint32_t target ;
886
+
887
+ if (jmp_zv ) {
888
+ target = ZEND_OFFSET_TO_OPLINE_NUM (op_array , opline , Z_LVAL_P (jmp_zv ));
889
+ } else {
890
+ target = ZEND_OFFSET_TO_OPLINE_NUM (op_array , opline , opline -> extended_value );
891
+ }
892
+ opline -> opcode = ZEND_JMP ;
893
+ opline -> extended_value = 0 ;
894
+ SET_UNUSED (opline -> op1 );
895
+ ZEND_SET_OP_JMP_ADDR (opline , opline -> op1 , op_array -> opcodes + target );
896
+ SET_UNUSED (opline -> op2 );
897
+ take_successor_ex (ssa , block_num , block , ssa -> cfg .map [target ]);
898
+ goto optimize_jmp ;
899
+ }
900
+ }
901
+ break ;
902
+ case ZEND_SWITCH_STRING :
903
+ if (opline -> op1_type == IS_CONST ) {
904
+ zval * zv = CT_CONSTANT_EX (op_array , opline -> op1 .constant );
905
+ if (Z_TYPE_P (zv ) != IS_STRING ) {
906
+ removed_ops ++ ;
907
+ MAKE_NOP (opline );
908
+ opline -> extended_value = 0 ;
909
+ take_successor_ex (ssa , block_num , block , block -> successors [0 ]);
910
+ goto optimize_nop ;
911
+ } else {
912
+ HashTable * jmptable = Z_ARRVAL_P (CT_CONSTANT_EX (op_array , opline -> op2 .constant ));
913
+ zval * jmp_zv = zend_hash_find (jmptable , Z_STR_P (zv ));
914
+ uint32_t target ;
915
+
916
+ if (jmp_zv ) {
917
+ target = ZEND_OFFSET_TO_OPLINE_NUM (op_array , opline , Z_LVAL_P (jmp_zv ));
918
+ } else {
919
+ target = ZEND_OFFSET_TO_OPLINE_NUM (op_array , opline , opline -> extended_value );
920
+ }
921
+ opline -> opcode = ZEND_JMP ;
922
+ opline -> extended_value = 0 ;
923
+ SET_UNUSED (opline -> op1 );
924
+ ZEND_SET_OP_JMP_ADDR (opline , opline -> op1 , op_array -> opcodes + target );
925
+ SET_UNUSED (opline -> op2 );
926
+ take_successor_ex (ssa , block_num , block , ssa -> cfg .map [target ]);
927
+ goto optimize_jmp ;
928
+ }
929
+ }
930
+ break ;
860
931
case ZEND_NOP :
861
932
optimize_nop :
862
933
compress_block (op_array , block );
0 commit comments