@@ -6659,9 +6659,10 @@ static zend_type zend_compile_single_typename(zend_ast *ast);
66596659static void zend_pm_context_init (zend_pm_context * context )
66606660{
66616661 zend_stack_init (& context -> labels , sizeof (uint32_t ));
6662- /* Avoid offset 0 . */
6662+ /* Avoid offsets 0 and 1 . */
66636663 uint32_t dummy = 0 ;
66646664 zend_stack_push (& context -> labels , & dummy );
6665+ zend_stack_push (& context -> labels , & dummy );
66656666
66666667 zend_stack_init (& context -> bindings , sizeof (zend_pm_binding ));
66676668}
@@ -6700,6 +6701,7 @@ static void zend_pm_labels_replace(zend_pm_context *context, uint32_t start_opnu
67006701 }
67016702 break ;
67026703 case ZEND_JMPZ_EX :
6704+ case ZEND_JMPNZ_EX :
67036705 if (opline -> op2 .opline_num >= label_lower_bound ) {
67046706 opline -> op2 .opline_num = labels [- opline -> op2 .opline_num ];
67056707 }
@@ -6716,6 +6718,42 @@ static void zend_pm_emit_jmpz_ex(znode *result, uint32_t opnum_target)
67166718 SET_NODE (opline -> result , result );
67176719}
67186720
6721+ static void zend_pm_emit_jmpnz_ex (znode * result , uint32_t opnum_target )
6722+ {
6723+ zend_op * opline = zend_emit_op (NULL , ZEND_JMPNZ_EX , result , NULL );
6724+ opline -> op2 .opline_num = opnum_target ;
6725+ SET_NODE (opline -> result , result );
6726+ }
6727+
6728+ static void zend_pm_kill_last_op_if_jmp (zend_pm_context * context )
6729+ {
6730+ zend_op_array * op_array = CG (active_op_array );
6731+ zend_op * opline = & op_array -> opcodes [op_array -> last - 1 ];
6732+
6733+ #if ZEND_DEBUG
6734+ uint32_t * labels = zend_stack_base (& context -> labels );
6735+ uint32_t label_lower_bound = - zend_stack_count (& context -> labels );
6736+ #endif
6737+
6738+ switch (opline -> opcode ) {
6739+ case ZEND_JMP :
6740+ #if ZEND_DEBUG
6741+ ZEND_ASSERT (opline -> op1 .opline_num >= label_lower_bound && labels [- opline -> op1 .opline_num ] == op_array -> last );
6742+ #endif
6743+ MAKE_NOP (opline );
6744+ op_array -> last -- ;
6745+ break ;
6746+ case ZEND_JMPZ_EX :
6747+ case ZEND_JMPNZ_EX :
6748+ #if ZEND_DEBUG
6749+ ZEND_ASSERT (opline -> op2 .opline_num >= label_lower_bound && labels [- opline -> op2 .opline_num ] == op_array -> last );
6750+ #endif
6751+ MAKE_NOP (opline );
6752+ op_array -> last -- ;
6753+ break ;
6754+ }
6755+ }
6756+
67196757static void zend_pm_compile_expr_like (zend_ast * ast , znode * result , znode * expr_node , bool consume_expr , uint32_t false_opnum )
67206758{
67216759 znode value ;
@@ -6754,8 +6792,8 @@ static void zend_pm_compile_or(zend_ast *ast, znode *result, znode *expr_node, b
67546792 zend_pm_label_set_next (context , next_label );
67556793 }
67566794 next_label = zend_pm_label_create (context );
6757- zend_compile_pattern (ast_list -> child [i ], result , expr_node , false, next_label , context );
6758- zend_emit_jump ( true_label );
6795+ zend_compile_pattern (ast_list -> child [i ], result , expr_node , false, ( uint32_t ) -1 , context );
6796+ zend_pm_emit_jmpnz_ex ( result , true_label );
67596797 }
67606798 zend_pm_label_set_next (context , next_label );
67616799
@@ -6933,6 +6971,11 @@ static void zend_pm_compile_container(
69336971
69346972static void zend_compile_pattern (zend_ast * ast , znode * result , znode * expr_node , bool consume_expr , uint32_t false_opnum , zend_pm_context * context )
69356973{
6974+ bool create_label = false_opnum == (uint32_t )-1 ;
6975+ if (create_label ) {
6976+ false_opnum = zend_pm_label_create (context );
6977+ }
6978+
69366979 switch (ast -> kind ) {
69376980 case ZEND_AST_EXPR_LIKE_PATTERN :
69386981 zend_pm_compile_expr_like (ast , result , expr_node , consume_expr , false_opnum );
@@ -6957,6 +7000,11 @@ static void zend_compile_pattern(zend_ast *ast, znode *result, znode *expr_node,
69577000 break ;
69587001 EMPTY_SWITCH_DEFAULT_CASE ();
69597002 }
7003+
7004+ if (create_label ) {
7005+ zend_pm_label_set_next (context , false_opnum );
7006+ zend_pm_kill_last_op_if_jmp (context );
7007+ }
69607008}
69617009
69627010static void zend_pm_count_bindings (zend_ast * * ast_ptr , void * context )
@@ -7005,12 +7053,14 @@ static void zend_emit_is(znode *result, znode *expr_node, bool consume_expr, zen
70057053 }
70067054
70077055 uint32_t start_opnum = get_next_op_number ();
7008- uint32_t false_label = zend_pm_label_create (& context );
7056+ uint32_t false_label = context . num_bindings ? zend_pm_label_create (& context ) : -1 ;
70097057 zend_compile_pattern (pattern_ast , result , & expr_copy_node , consume_expr , false_label , & context );
70107058
70117059 if (context .num_bindings ) {
7012- zend_pm_binding * binding = zend_stack_base (& context .bindings );
7013- zend_pm_binding * binding_end = zend_stack_top (& context .bindings );
7060+ zend_pm_binding * binding , * binding_end ;
7061+
7062+ binding = zend_stack_base (& context .bindings );
7063+ binding_end = zend_stack_top (& context .bindings );
70147064 zend_op * binding_init_op = & CG (active_op_array )-> opcodes [first_binding_init_opnum ];
70157065 while (binding <= binding_end ) {
70167066 znode var_node ;
@@ -7030,22 +7080,17 @@ static void zend_emit_is(znode *result, znode *expr_node, bool consume_expr, zen
70307080 binding ++ ;
70317081 binding_init_op ++ ;
70327082 }
7033- }
7034-
7035- if (context .num_bindings ) {
70367083 uint32_t jmp_end = zend_emit_jump (0 );
7037- zend_pm_label_set_next (& context , false_label );
70387084
7039- zend_pm_binding * binding = zend_stack_base (& context .bindings );
7040- zend_pm_binding * binding_end = zend_stack_top (& context .bindings );
7085+ zend_pm_label_set_next (& context , false_label );
7086+ binding = zend_stack_base (& context .bindings );
7087+ binding_end = zend_stack_top (& context .bindings );
70417088 while (binding <= binding_end ) {
70427089 zend_emit_op (NULL , ZEND_FREE , & binding -> value , NULL );
70437090 binding ++ ;
70447091 }
70457092
70467093 zend_update_jump_target_to_next (jmp_end );
7047- } else {
7048- zend_pm_label_set_next (& context , false_label );
70497094 }
70507095
70517096 zend_pm_labels_replace (& context , start_opnum );
0 commit comments