@@ -4981,41 +4981,63 @@ void zend_compile_if(zend_ast *ast) /* {{{ */
49814981}
49824982/* }}} */
49834983
4984+ static uint32_t count_switch_conds (zend_ast_list * cases ) /* {{{ */
4985+ {
4986+ uint32_t num_conds = 0 ;
4987+
4988+ for (uint32_t i = 0 ; i < cases -> children ; i ++ ) {
4989+ zend_ast * case_ast = cases -> child [i ];
4990+ if (case_ast -> child [0 ] == NULL ) {
4991+ continue ;
4992+ }
4993+
4994+ zend_ast_list * conds = zend_ast_get_list (case_ast -> child [0 ]);
4995+ num_conds += conds -> children ;
4996+ }
4997+
4998+ return num_conds ;
4999+ }
5000+ /* }}} */
5001+
49845002static zend_uchar determine_switch_jumptable_type (zend_ast_list * cases ) {
49855003 uint32_t i ;
49865004 zend_uchar common_type = IS_UNDEF ;
49875005 for (i = 0 ; i < cases -> children ; i ++ ) {
49885006 zend_ast * case_ast = cases -> child [i ];
4989- zend_ast * * cond_ast = & case_ast -> child [0 ];
49905007 zval * cond_zv ;
49915008 if (!case_ast -> child [0 ]) {
49925009 /* Skip default clause */
49935010 continue ;
49945011 }
49955012
4996- zend_eval_const_expr (cond_ast );
4997- if ((* cond_ast )-> kind != ZEND_AST_ZVAL ) {
4998- /* Non-constant case */
4999- return IS_UNDEF ;
5000- }
5013+ zend_ast_list * conds = zend_ast_get_list (case_ast -> child [0 ]);
5014+ for (uint32_t j = 0 ; j < conds -> children ; j ++ ) {
5015+ zend_ast * * cond_ast = & conds -> child [j ];
50015016
5002- cond_zv = zend_ast_get_zval ( case_ast -> child [ 0 ] );
5003- if (Z_TYPE_P ( cond_zv ) != IS_LONG && Z_TYPE_P ( cond_zv ) != IS_STRING ) {
5004- /* We only optimize switched on integers and strings */
5005- return IS_UNDEF ;
5006- }
5017+ zend_eval_const_expr ( cond_ast );
5018+ if (( * cond_ast ) -> kind != ZEND_AST_ZVAL ) {
5019+ /* Non-constant case */
5020+ return IS_UNDEF ;
5021+ }
50075022
5008- if (common_type == IS_UNDEF ) {
5009- common_type = Z_TYPE_P (cond_zv );
5010- } else if (common_type != Z_TYPE_P (cond_zv )) {
5011- /* Non-uniform case types */
5012- return IS_UNDEF ;
5013- }
5023+ cond_zv = zend_ast_get_zval (* cond_ast );
5024+ if (Z_TYPE_P (cond_zv ) != IS_LONG && Z_TYPE_P (cond_zv ) != IS_STRING ) {
5025+ /* We only optimize switched on integers and strings */
5026+ return IS_UNDEF ;
5027+ }
50145028
5015- if (Z_TYPE_P (cond_zv ) == IS_STRING
5016- && is_numeric_string (Z_STRVAL_P (cond_zv ), Z_STRLEN_P (cond_zv ), NULL , NULL , 0 )) {
5017- /* Numeric strings cannot be compared with a simple hash lookup */
5018- return IS_UNDEF ;
5029+ if (common_type == IS_UNDEF ) {
5030+ common_type = Z_TYPE_P (cond_zv );
5031+ } else if (common_type != Z_TYPE_P (cond_zv )) {
5032+ /* Non-uniform case types */
5033+ return IS_UNDEF ;
5034+ }
5035+
5036+ if (Z_TYPE_P (cond_zv ) == IS_STRING
5037+ && is_numeric_string (Z_STRVAL_P (cond_zv ), Z_STRLEN_P (cond_zv ), NULL , NULL , 0 )) {
5038+ /* Numeric strings cannot be compared with a simple hash lookup */
5039+ return IS_UNDEF ;
5040+ }
50195041 }
50205042 }
50215043
@@ -5083,13 +5105,14 @@ void zend_compile_switch(znode *result, zend_ast *ast) /* {{{ */
50835105 opnum_switch = opline - CG (active_op_array )-> opcodes ;
50845106 }
50855107
5086- jmpnz_opnums = safe_emalloc (sizeof (uint32_t ), cases -> children , 0 );
5108+ uint32_t num_conds = count_switch_conds (cases );
5109+ uint32_t case_cond_count = 0 ;
5110+ jmpnz_opnums = safe_emalloc (sizeof (uint32_t ), num_conds , 0 );
50875111 for (i = 0 ; i < cases -> children ; ++ i ) {
50885112 zend_ast * case_ast = cases -> child [i ];
5089- zend_ast * cond_ast = case_ast -> child [0 ];
50905113 znode cond_node ;
50915114
5092- if (! cond_ast ) {
5115+ if (case_ast -> child [ 0 ] == NULL ) {
50935116 if (has_default_case ) {
50945117 CG (zend_lineno ) = case_ast -> lineno ;
50955118 zend_error_noreturn (E_COMPILE_ERROR ,
@@ -5099,50 +5122,63 @@ void zend_compile_switch(znode *result, zend_ast *ast) /* {{{ */
50995122 continue ;
51005123 }
51015124
5102- zend_compile_expr (& cond_node , cond_ast );
5125+ zend_ast_list * conds = zend_ast_get_list (case_ast -> child [0 ]);
5126+ for (uint32_t j = 0 ; j < conds -> children ; j ++ ) {
5127+ zend_ast * cond_ast = conds -> child [j ];
5128+ zend_compile_expr (& cond_node , cond_ast );
5129+
5130+ if (expr_node .op_type == IS_CONST
5131+ && Z_TYPE (expr_node .u .constant ) == IS_FALSE ) {
5132+ jmpnz_opnums [case_cond_count ] = zend_emit_cond_jump (ZEND_JMPZ , & cond_node , 0 );
5133+ } else if (expr_node .op_type == IS_CONST
5134+ && Z_TYPE (expr_node .u .constant ) == IS_TRUE ) {
5135+ jmpnz_opnums [case_cond_count ] = zend_emit_cond_jump (ZEND_JMPNZ , & cond_node , 0 );
5136+ } else {
5137+ opline = zend_emit_op (NULL ,
5138+ (expr_node .op_type & (IS_VAR |IS_TMP_VAR )) ? ZEND_CASE : ZEND_IS_EQUAL ,
5139+ & expr_node , & cond_node );
5140+ SET_NODE (opline -> result , & case_node );
5141+ if (opline -> op1_type == IS_CONST ) {
5142+ Z_TRY_ADDREF_P (CT_CONSTANT (opline -> op1 ));
5143+ }
51035144
5104- if (expr_node .op_type == IS_CONST
5105- && Z_TYPE (expr_node .u .constant ) == IS_FALSE ) {
5106- jmpnz_opnums [i ] = zend_emit_cond_jump (ZEND_JMPZ , & cond_node , 0 );
5107- } else if (expr_node .op_type == IS_CONST
5108- && Z_TYPE (expr_node .u .constant ) == IS_TRUE ) {
5109- jmpnz_opnums [i ] = zend_emit_cond_jump (ZEND_JMPNZ , & cond_node , 0 );
5110- } else {
5111- opline = zend_emit_op (NULL ,
5112- (expr_node .op_type & (IS_VAR |IS_TMP_VAR )) ? ZEND_CASE : ZEND_IS_EQUAL ,
5113- & expr_node , & cond_node );
5114- SET_NODE (opline -> result , & case_node );
5115- if (opline -> op1_type == IS_CONST ) {
5116- Z_TRY_ADDREF_P (CT_CONSTANT (opline -> op1 ));
5145+ jmpnz_opnums [case_cond_count ] = zend_emit_cond_jump (ZEND_JMPNZ , & case_node , 0 );
51175146 }
51185147
5119- jmpnz_opnums [ i ] = zend_emit_cond_jump ( ZEND_JMPNZ , & case_node , 0 ) ;
5148+ case_cond_count ++ ;
51205149 }
51215150 }
51225151
51235152 opnum_default_jmp = zend_emit_jump (0 );
51245153 zend_bool is_first_case = 1 ;
5154+ case_cond_count = 0 ;
51255155
51265156 for (i = 0 ; i < cases -> children ; ++ i ) {
51275157 zend_ast * case_ast = cases -> child [i ];
5128- zend_ast * cond_ast = case_ast -> child [0 ];
51295158 zend_ast * stmt_ast = case_ast -> child [1 ];
51305159
5131- if (cond_ast ) {
5132- zend_update_jump_target_to_next ( jmpnz_opnums [ i ]);
5160+ if (case_ast -> child [ 0 ] != NULL ) {
5161+ zend_ast_list * conds = zend_ast_get_list ( case_ast -> child [ 0 ]);
51335162
5134- if (jumptable ) {
5135- zval * cond_zv = zend_ast_get_zval (cond_ast );
5136- zval jmp_target ;
5137- ZVAL_LONG (& jmp_target , get_next_op_number ());
5163+ for (uint32_t j = 0 ; j < conds -> children ; j ++ ) {
5164+ zend_ast * cond_ast = conds -> child [j ];
5165+ zend_update_jump_target_to_next (jmpnz_opnums [case_cond_count ]);
51385166
5139- ZEND_ASSERT (Z_TYPE_P (cond_zv ) == jumptable_type );
5140- if (Z_TYPE_P (cond_zv ) == IS_LONG ) {
5141- zend_hash_index_add (jumptable , Z_LVAL_P (cond_zv ), & jmp_target );
5142- } else {
5143- ZEND_ASSERT (Z_TYPE_P (cond_zv ) == IS_STRING );
5144- zend_hash_add (jumptable , Z_STR_P (cond_zv ), & jmp_target );
5167+ if (jumptable ) {
5168+ zval * cond_zv = zend_ast_get_zval (cond_ast );
5169+ zval jmp_target ;
5170+ ZVAL_LONG (& jmp_target , get_next_op_number ());
5171+
5172+ ZEND_ASSERT (Z_TYPE_P (cond_zv ) == jumptable_type );
5173+ if (Z_TYPE_P (cond_zv ) == IS_LONG ) {
5174+ zend_hash_index_add (jumptable , Z_LVAL_P (cond_zv ), & jmp_target );
5175+ } else {
5176+ ZEND_ASSERT (Z_TYPE_P (cond_zv ) == IS_STRING );
5177+ zend_hash_add (jumptable , Z_STR_P (cond_zv ), & jmp_target );
5178+ }
51455179 }
5180+
5181+ case_cond_count ++ ;
51465182 }
51475183 } else {
51485184 zend_update_jump_target_to_next (opnum_default_jmp );
0 commit comments