@@ -637,22 +637,17 @@ static zend_result zend_generator_get_next_delegated_value(zend_generator *gener
637
637
if (iter -> index ++ > 0 ) {
638
638
iter -> funcs -> move_forward (iter );
639
639
if (UNEXPECTED (EG (exception ) != NULL )) {
640
- goto exception ;
640
+ goto failure ;
641
641
}
642
642
}
643
643
644
644
if (iter -> funcs -> valid (iter ) == FAILURE ) {
645
- if (UNEXPECTED (EG (exception ) != NULL )) {
646
- goto exception ;
647
- }
648
645
/* reached end of iteration */
649
646
goto failure ;
650
647
}
651
648
652
649
value = iter -> funcs -> get_current_data (iter );
653
- if (UNEXPECTED (EG (exception ) != NULL )) {
654
- goto exception ;
655
- } else if (UNEXPECTED (!value )) {
650
+ if (UNEXPECTED (EG (exception ) != NULL ) || UNEXPECTED (!value )) {
656
651
goto failure ;
657
652
}
658
653
@@ -664,17 +659,14 @@ static zend_result zend_generator_get_next_delegated_value(zend_generator *gener
664
659
iter -> funcs -> get_current_key (iter , & generator -> key );
665
660
if (UNEXPECTED (EG (exception ) != NULL )) {
666
661
ZVAL_UNDEF (& generator -> key );
667
- goto exception ;
662
+ goto failure ;
668
663
}
669
664
} else {
670
665
ZVAL_LONG (& generator -> key , iter -> index );
671
666
}
672
667
}
673
668
return SUCCESS ;
674
669
675
- exception :
676
- zend_generator_throw_exception (generator , NULL );
677
-
678
670
failure :
679
671
zval_ptr_dtor (& generator -> values );
680
672
ZVAL_UNDEF (& generator -> values );
@@ -706,94 +698,97 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
706
698
/* Drop the AT_FIRST_YIELD flag */
707
699
orig_generator -> flags &= ~ZEND_GENERATOR_AT_FIRST_YIELD ;
708
700
701
+ /* Backup executor globals */
702
+ zend_execute_data * original_execute_data = EG (current_execute_data );
703
+ uint32_t original_jit_trace_num = EG (jit_trace_num );
704
+
705
+ /* Set executor globals */
706
+ EG (current_execute_data ) = generator -> execute_data ;
707
+ EG (jit_trace_num ) = 0 ;
708
+
709
+ /* We want the backtrace to look as if the generator function was
710
+ * called from whatever method we are current running (e.g. next()).
711
+ * So we have to link generator call frame with caller call frame. */
712
+ if (generator == orig_generator ) {
713
+ generator -> execute_data -> prev_execute_data = original_execute_data ;
714
+ } else {
715
+ /* We need some execute_data placeholder in stacktrace to be replaced
716
+ * by the real stack trace when needed */
717
+ generator -> execute_data -> prev_execute_data = & orig_generator -> execute_fake ;
718
+ orig_generator -> execute_fake .prev_execute_data = original_execute_data ;
719
+ }
720
+
721
+ /* Ensure this is run after executor_data swap to have a proper stack trace */
709
722
if (UNEXPECTED (!Z_ISUNDEF (generator -> values ))) {
710
723
if (EXPECTED (zend_generator_get_next_delegated_value (generator ) == SUCCESS )) {
724
+ /* Restore executor globals */
725
+ EG (current_execute_data ) = original_execute_data ;
726
+ EG (jit_trace_num ) = original_jit_trace_num ;
727
+
711
728
orig_generator -> flags &= ~ZEND_GENERATOR_DO_INIT ;
712
729
return ;
713
730
}
714
731
/* If there are no more delegated values, resume the generator
715
732
* after the "yield from" expression. */
716
733
}
717
734
718
- {
719
- /* Backup executor globals */
720
- zend_execute_data * original_execute_data = EG (current_execute_data );
721
- uint32_t original_jit_trace_num = EG (jit_trace_num );
722
-
723
- /* Set executor globals */
724
- EG (current_execute_data ) = generator -> execute_data ;
725
- EG (jit_trace_num ) = 0 ;
726
-
727
- /* We want the backtrace to look as if the generator function was
728
- * called from whatever method we are current running (e.g. next()).
729
- * So we have to link generator call frame with caller call frame. */
730
- if (generator == orig_generator ) {
731
- generator -> execute_data -> prev_execute_data = original_execute_data ;
732
- } else {
733
- /* We need some execute_data placeholder in stacktrace to be replaced
734
- * by the real stack trace when needed */
735
- generator -> execute_data -> prev_execute_data = & orig_generator -> execute_fake ;
736
- orig_generator -> execute_fake .prev_execute_data = original_execute_data ;
737
- }
735
+ if (UNEXPECTED (generator -> frozen_call_stack )) {
736
+ /* Restore frozen call-stack */
737
+ zend_generator_restore_call_stack (generator );
738
+ }
738
739
739
- if (UNEXPECTED (generator -> frozen_call_stack )) {
740
- /* Restore frozen call-stack */
741
- zend_generator_restore_call_stack (generator );
740
+ /* Resume execution */
741
+ generator -> flags |= ZEND_GENERATOR_CURRENTLY_RUNNING ;
742
+ if (!ZEND_OBSERVER_ENABLED ) {
743
+ zend_execute_ex (generator -> execute_data );
744
+ } else {
745
+ zend_observer_generator_resume (generator -> execute_data );
746
+ zend_execute_ex (generator -> execute_data );
747
+ if (generator -> execute_data ) {
748
+ /* On the final return, this will be called from ZEND_GENERATOR_RETURN */
749
+ zend_observer_fcall_end (generator -> execute_data , & generator -> value );
742
750
}
751
+ }
752
+ generator -> flags &= ~ZEND_GENERATOR_CURRENTLY_RUNNING ;
743
753
744
- /* Resume execution */
745
- generator -> flags |= ZEND_GENERATOR_CURRENTLY_RUNNING ;
746
- if (!ZEND_OBSERVER_ENABLED ) {
747
- zend_execute_ex (generator -> execute_data );
748
- } else {
749
- zend_observer_generator_resume (generator -> execute_data );
750
- zend_execute_ex (generator -> execute_data );
751
- if (generator -> execute_data ) {
752
- /* On the final return, this will be called from ZEND_GENERATOR_RETURN */
753
- zend_observer_fcall_end (generator -> execute_data , & generator -> value );
754
- }
755
- }
756
- generator -> flags &= ~ZEND_GENERATOR_CURRENTLY_RUNNING ;
754
+ generator -> frozen_call_stack = NULL ;
755
+ if (EXPECTED (generator -> execute_data ) &&
756
+ UNEXPECTED (generator -> execute_data -> call )) {
757
+ /* Frize call-stack */
758
+ generator -> frozen_call_stack = zend_generator_freeze_call_stack (generator -> execute_data );
759
+ }
757
760
758
- generator -> frozen_call_stack = NULL ;
759
- if (EXPECTED (generator -> execute_data ) &&
760
- UNEXPECTED (generator -> execute_data -> call )) {
761
- /* Frize call-stack */
762
- generator -> frozen_call_stack = zend_generator_freeze_call_stack (generator -> execute_data );
763
- }
761
+ /* Restore executor globals */
762
+ EG (current_execute_data ) = original_execute_data ;
763
+ EG (jit_trace_num ) = original_jit_trace_num ;
764
764
765
- /* Restore executor globals */
766
- EG (current_execute_data ) = original_execute_data ;
767
- EG (jit_trace_num ) = original_jit_trace_num ;
768
-
769
- /* If an exception was thrown in the generator we have to internally
770
- * rethrow it in the parent scope.
771
- * In case we did yield from, the Exception must be rethrown into
772
- * its calling frame (see above in if (check_yield_from). */
773
- if (UNEXPECTED (EG (exception ) != NULL )) {
774
- if (generator == orig_generator ) {
775
- zend_generator_close (generator , 0 );
776
- if (!EG (current_execute_data )) {
777
- zend_throw_exception_internal (NULL );
778
- } else if (EG (current_execute_data )-> func &&
779
- ZEND_USER_CODE (EG (current_execute_data )-> func -> common .type )) {
780
- zend_rethrow_exception (EG (current_execute_data ));
781
- }
782
- } else {
783
- generator = zend_generator_get_current (orig_generator );
784
- zend_generator_throw_exception (generator , NULL );
785
- orig_generator -> flags &= ~ZEND_GENERATOR_DO_INIT ;
786
- goto try_again ;
765
+ /* If an exception was thrown in the generator we have to internally
766
+ * rethrow it in the parent scope.
767
+ * In case we did yield from, the Exception must be rethrown into
768
+ * its calling frame (see above in if (check_yield_from). */
769
+ if (UNEXPECTED (EG (exception ) != NULL )) {
770
+ if (generator == orig_generator ) {
771
+ zend_generator_close (generator , 0 );
57AE
772
+ if (!EG (current_execute_data )) {
773
+ zend_throw_exception_internal (NULL );
774
+ } else if (EG (current_execute_data )-> func &&
775
+ ZEND_USER_CODE (EG (current_execute_data )-> func -> common .type )) {
776
+ zend_rethrow_exception (EG (current_execute_data ));
787
777
}
788
- }
789
-
790
- /* yield from was used, try another resume. */
791
- if (UNEXPECTED ((generator != orig_generator && !Z_ISUNDEF (generator -> retval )) || (generator -> execute_data && (generator -> execute_data -> opline - 1 )-> opcode == ZEND_YIELD_FROM ))) {
778
+ } else {
792
779
generator = zend_generator_get_current (orig_generator );
780
+ zend_generator_throw_exception (generator , NULL );
781
+ orig_generator -> flags &= ~ZEND_GENERATOR_DO_INIT ;
793
782
goto try_again ;
794
783
}
795
784
}
796
785
786
+ /* yield from was used, try another resume. */
787
+ if (UNEXPECTED ((generator != orig_generator && !Z_ISUNDEF (generator -> retval )) || (generator -> execute_data && (generator -> execute_data -> opline - 1 )-> opcode == ZEND_YIELD_FROM ))) {
788
+ generator = zend_generator_get_current (orig_generator );
789
+ goto try_again ;
790
+ }
791
+
797
792
orig_generator -> flags &= ~ZEND_GENERATOR_DO_INIT ;
798
793
}
799
794
/* }}} */
0 commit comments