@@ -4981,41 +4981,62 @@ 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
+
4984
5001
static zend_uchar determine_switch_jumptable_type (zend_ast_list * cases ) {
4985
5002
uint32_t i ;
4986
5003
zend_uchar common_type = IS_UNDEF ;
4987
5004
for (i = 0 ; i < cases -> children ; i ++ ) {
4988
5005
zend_ast * case_ast = cases -> child [i ];
4989
- zend_ast * * cond_ast = & case_ast -> child [0 ];
4990
5006
zval * cond_zv ;
4991
5007
if (!case_ast -> child [0 ]) {
4992
5008
/* Skip default clause */
4993
5009
continue ;
4994
5010
}
4995
5011
4996
- zend_eval_const_expr (cond_ast );
4997
- if ((* cond_ast )-> kind != ZEND_AST_ZVAL ) {
4998
- /* Non-constant case */
4999
- return IS_UNDEF ;
5000
- }
5012
+ zend_ast_list * conds = zend_ast_get_list (case_ast -> child [0 ]);
5013
+ for (uint32_t j = 0 ; j < conds -> children ; j ++ ) {
5014
+ zend_ast * * cond_ast = & conds -> child [j ];
5001
5015
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
- }
5016
+ zend_eval_const_expr ( cond_ast );
5017
+ if (( * cond_ast ) -> kind != ZEND_AST_ZVAL ) {
5018
+ /* Non-constant case */
5019
+ return IS_UNDEF ;
5020
+ }
5007
5021
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
- }
5022
+ cond_zv = zend_ast_get_zval (* cond_ast );
5023
+ if (Z_TYPE_P (cond_zv ) != IS_LONG && Z_TYPE_P (cond_zv ) != IS_STRING ) {
5024
+ /* We only optimize switched on integers and strings */
5025
+ return IS_UNDEF ;
5026
+ }
5014
5027
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 ;
5028
+ if (common_type == IS_UNDEF ) {
5029
+ common_type = Z_TYPE_P (cond_zv );
5030
+ } else if (common_type != Z_TYPE_P (cond_zv )) {
5031
+ /* Non-uniform case types */
5032
+ return IS_UNDEF ;
5033
+ }
5034
+
5035
+ if (Z_TYPE_P (cond_zv ) == IS_STRING
5036
+ && is_numeric_string (Z_STRVAL_P (cond_zv ), Z_STRLEN_P (cond_zv ), NULL , NULL , 0 )) {
5037
+ /* Numeric strings cannot be compared with a simple hash lookup */
5038
+ return IS_UNDEF ;
5039
+ }
5019
5040
}
5020
5041
}
5021
5042
@@ -5083,13 +5104,14 @@ void zend_compile_switch(znode *result, zend_ast *ast) /* {{{ */
5083
5104
opnum_switch = opline - CG (active_op_array )-> opcodes ;
5084
5105
}
5085
5106
5086
- jmpnz_opnums = safe_emalloc (sizeof (uint32_t ), cases -> children , 0 );
5107
+ uint32_t num_conds = count_switch_conds (cases );
5108
+ uint32_t cond_count = 0 ;
5109
+ jmpnz_opnums = safe_emalloc (sizeof (uint32_t ), num_conds , 0 );
5087
5110
for (i = 0 ; i < cases -> children ; ++ i ) {
5088
5111
zend_ast * case_ast = cases -> child [i ];
5089
- zend_ast * cond_ast = case_ast -> child [0 ];
5090
5112
znode cond_node ;
5091
5113
5092
- if (! cond_ast ) {
5114
+ if (case_ast -> child [ 0 ] == NULL ) {
5093
5115
if (has_default_case ) {
5094
5116
CG (zend_lineno ) = case_ast -> lineno ;
5095
5117
zend_error_noreturn (E_COMPILE_ERROR ,
@@ -5099,50 +5121,63 @@ void zend_compile_switch(znode *result, zend_ast *ast) /* {{{ */
5099
5121
continue ;
5100
5122
}
5101
5123
5102
- zend_compile_expr (& cond_node , cond_ast );
5124
+ zend_ast_list * conds = zend_ast_get_list (case_ast -> child [0 ]);
5125
+ for (uint32_t j = 0 ; j < conds -> children ; j ++ ) {
5126
+ zend_ast * cond_ast = conds -> child [j ];
5127
+ zend_compile_expr (& cond_node , cond_ast );
5128
+
5129
+ if (expr_node .op_type == IS_CONST
5130
+ && Z_TYPE (expr_node .u .constant ) == IS_FALSE ) {
5131
+ jmpnz_opnums [cond_count ] = zend_emit_cond_jump (ZEND_JMPZ , & cond_node , 0 );
5132
+ } else if (expr_node .op_type == IS_CONST
5133
+ && Z_TYPE (expr_node .u .constant ) == IS_TRUE ) {
5134
+ jmpnz_opnums [cond_count ] = zend_emit_cond_jump (ZEND_JMPNZ , & cond_node , 0 );
5135
+ } else {
5136
+ opline = zend_emit_op (NULL ,
5137
+ (expr_node .op_type & (IS_VAR |IS_TMP_VAR )) ? ZEND_CASE : ZEND_IS_EQUAL ,
5138
+ & expr_node , & cond_node );
5139
+ SET_NODE (opline -> result , & case_node );
5140
+ if (opline -> op1_type == IS_CONST ) {
5141
+ Z_TRY_ADDREF_P (CT_CONSTANT (opline -> op1 ));
5142
+ }
5103
5143
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 ));
5144
+ jmpnz_opnums [cond_count ] = zend_emit_cond_jump (ZEND_JMPNZ , & case_node , 0 );
5117
5145
}
5118
5146
5119
- jmpnz_opnums [ i ] = zend_emit_cond_jump ( ZEND_JMPNZ , & case_node , 0 ) ;
5147
+ cond_count ++ ;
5120
5148
}
5121
5149
}
5122
5150
5123
5151
opnum_default_jmp = zend_emit_jump (0 );
5124
5152
zend_bool is_first_case = 1 ;
5153
+ cond_count = 0 ;
5125
5154
5126
5155
for (i = 0 ; i < cases -> children ; ++ i ) {
5127
5156
zend_ast * case_ast = cases -> child [i ];
5128
- zend_ast * cond_ast = case_ast -> child [0 ];
5129
5157
zend_ast * stmt_ast = case_ast -> child [1 ];
5130
5158
5131
- if (cond_ast ) {
5132
- zend_update_jump_target_to_next ( jmpnz_opnums [ i ]);
5159
+ if (case_ast -> child [ 0 ] != NULL ) {
5160
+ zend_ast_list * conds = zend_ast_get_list ( case_ast -> child [ 0 ]);
5133
5161
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 ());
5162
+ for (uint32_t j = 0 ; j < conds -> children ; j ++ ) {
5163
+ zend_ast * cond_ast = conds -> child [j ];
5164
+ zend_update_jump_target_to_next (jmpnz_opnums [cond_count ]);
5138
5165
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 );
5166
+ if (jumptable ) {
5167
+ zval * cond_zv = zend_ast_get_zval (cond_ast );
5168
+ zval jmp_target ;
5169
+ ZVAL_LONG (& jmp_target , get_next_op_number ());
5170
+
5171
+ ZEND_ASSERT (Z_TYPE_P (cond_zv ) == jumptable_type );
5172
+ if (Z_TYPE_P (cond_zv ) == IS_LONG ) {
5173
+ zend_hash_index_add (jumptable , Z_LVAL_P (cond_zv ), & jmp_target );
5174
+ } else {
5175
+ ZEND_ASSERT (Z_TYPE_P (cond_zv ) == IS_STRING );
5176
+ zend_hash_add (jumptable , Z_STR_P (cond_zv ), & jmp_target );
5177
+ }
5145
5178
}
5179
+
5180
+ cond_count ++ ;
5146
5181
}
5147
5182
} else {
5148
5183
zend_update_jump_target_to_next (opnum_default_jmp );
0 commit comments