@@ -4981,41 +4981,63 @@ void zend_compile_if(zend_ast *ast) /* {{{ */
4981
4981
}
4982
4982
/* }}} */
4983
4983
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
+
4984
5002
static zend_uchar determine_switch_jumptable_type (zend_ast_list * cases ) {
4985
5003
uint32_t i ;
4986
5004
zend_uchar common_type = IS_UNDEF ;
4987
5005
for (i = 0 ; i < cases -> children ; i ++ ) {
4988
5006
zend_ast * case_ast = cases -> child [i ];
4989
- zend_ast * * cond_ast = & case_ast -> child [0 ];
4990
5007
zval * cond_zv ;
4991
5008
if (!case_ast -> child [0 ]) {
4992
5009
/* Skip default clause */
4993
5010
continue ;
4994
5011
}
4995
5012
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 ];
5001
5016
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
+ }
5007
5022
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
+ }
5014
5028
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
+ }
5019
5041
}
5020
5042
}
5021
5043
@@ -5083,13 +5105,14 @@ void zend_compile_switch(znode *result, zend_ast *ast) /* {{{ */
5083
5105
opnum_switch = opline - CG (active_op_array )-> opcodes ;
5084
5106
}
5085
5107
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 );
5087
5111
for (i = 0 ; i < cases -> children ; ++ i ) {
5088
5112
zend_ast * case_ast = cases -> child [i ];
5089
- zend_ast * cond_ast = case_ast -> child [0 ];
5090
5113
znode cond_node ;
5091
5114
5092
- if (! cond_ast ) {
5115
+ if (case_ast -> child [ 0 ] == NULL ) {
5093
5116
if (has_default_case ) {
5094
5117
CG (zend_lineno ) = case_ast -> lineno ;
5095
5118
zend_error_noreturn (E_COMPILE_ERROR ,
@@ -5099,50 +5122,63 @@ void zend_compile_switch(znode *result, zend_ast *ast) /* {{{ */
5099
5122
continue ;
5100
5123
}
5101
5124
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
+ }
5103
5144
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 );
5117
5146
}
5118
5147
5119
- jmpnz_opnums [ i ] = zend_emit_cond_jump ( ZEND_JMPNZ , & case_node , 0 ) ;
5148
+ case_cond_count ++ ;
5120
5149
}
5121
5150
}
5122
5151
5123
5152
opnum_default_jmp = zend_emit_jump (0 );
5124
5153
zend_bool is_first_case = 1 ;
5154
+ case_cond_count = 0 ;
5125
5155
5126
5156
for (i = 0 ; i < cases -> children ; ++ i ) {
5127
5157
zend_ast * case_ast = cases -> child [i ];
5128
- zend_ast * cond_ast = case_ast -> child [0 ];
5129
5158
zend_ast * stmt_ast = case_ast -> child [1 ];
5130
5159
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 ]);
5133
5162
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 ]);
5138
5166
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
+ }
5145
5179
}
5180
+
5181
+ case_cond_count ++ ;
5146
5182
}
5147
5183
} else {
5148
5184
zend_update_jump_target_to_next (opnum_default_jmp );
0 commit comments