@@ -655,22 +655,17 @@ static zend_result zend_generator_get_next_delegated_value(zend_generator *gener
655
655
if (iter -> index ++ > 0 ) {
656
656
iter -> funcs -> move_forward (iter );
657
657
if (UNEXPECTED (EG (exception ) != NULL )) {
658
- goto exception ;
658
+ goto failure ;
659
659
}
660
660
}
661
661
662
662
if (iter -> funcs -> valid (iter ) == FAILURE ) {
663
- if (UNEXPECTED (EG (exception ) != NULL )) {
664
- goto exception ;
665
- }
666
663
/* reached end of iteration */
667
664
goto failure ;
668
665
}
669
666
670
667
value = iter -> funcs -> get_current_data (iter );
671
- if (UNEXPECTED (EG (exception ) != NULL )) {
672
- goto exception ;
673
- } else if (UNEXPECTED (!value )) {
668
+ if (UNEXPECTED (EG (exception ) != NULL ) || UNEXPECTED (!value )) {
674
669
goto failure ;
675
670
}
676
671
@@ -682,17 +677,14 @@ static zend_result zend_generator_get_next_delegated_value(zend_generator *gener
682
677
iter -> funcs -> get_current_key (iter , & generator -> key );
683
678
if (UNEXPECTED (EG (exception ) != NULL )) {
684
679
ZVAL_UNDEF (& generator -> key );
685
- goto exception ;
680
+ goto failure ;
686
681
}
687
682
} else {
688
683
ZVAL_LONG (& generator -> key , iter -> index );
689
684
}
690
685
}
691
686
return SUCCESS ;
692
687
693
- exception :
694
- zend_generator_throw_exception (generator , NULL );
695
-
696
688
failure :
697
689
zval_ptr_dtor (& generator -> values );
698
690
ZVAL_UNDEF (& generator -> values );
@@ -724,94 +716,97 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
724
716
/* Drop the AT_FIRST_YIELD flag */
725
717
orig_generator -> flags &= ~ZEND_GENERATOR_AT_FIRST_YIELD ;
726
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
+ }
738
+
739
+ /* Ensure this is run after executor_data swap to have a proper stack trace */
727
740
if (UNEXPECTED (!Z_ISUNDEF (generator -> values ))) {
728
741
if (EXPECTED (zend_generator_get_next_delegated_value (generator ) == SUCCESS )) {
742
+ /* Restore executor globals */
743
+ EG (current_execute_data ) = original_execute_data ;
744
+ EG (jit_trace_num ) = original_jit_trace_num ;
745
+
729
746
orig_generator -> flags &= ~ZEND_GENERATOR_DO_INIT ;
730
747
return ;
731
748
}
732
749
/* If there are no more delegated values, resume the generator
733
750
* after the "yield from" expression. */
734
751
}
735
752
736
- {
737
- /* Backup executor globals */
738
- zend_execute_data * original_execute_data = EG (current_execute_data );
739
- uint32_t original_jit_trace_num = EG (jit_trace_num );
740
-
741
- /* Set executor globals */
742
- EG (current_execute_data ) = generator -> execute_data ;
743
- EG (jit_trace_num ) = 0 ;
744
-
745
- /* We want the backtrace to look as if the generator function was
746
- * called from whatever method we are current running (e.g. next()).
747
- * So we have to link generator call frame with caller call frame. */
748
- if (generator == orig_generator ) {
749
- generator -> execute_data -> prev_execute_data = original_execute_data ;
750
- } else {
751
- /* We need some execute_data placeholder in stacktrace to be replaced
752
- * by the real stack trace when needed */
753
- generator -> execute_data -> prev_execute_data = & orig_generator -> execute_fake ;
754
- orig_generator -> execute_fake .prev_execute_data = original_execute_data ;
755
- }
753
+ if (UNEXPECTED (generator -> frozen_call_stack )) {
754
+ /* Restore frozen call-stack */
755
+ zend_generator_restore_call_stack (generator );
756
+ }
756
757
757
- if (UNEXPECTED (generator -> frozen_call_stack )) {
758
- /* Restore frozen call-stack */
759
- zend_generator_restore_call_stack (generator );
758
+ /* Resume execution */
759
+ generator -> flags |= ZEND_GENERATOR_CURRENTLY_RUNNING ;
760
+ if (!ZEND_OBSERVER_ENABLED ) {
761
+ zend_execute_ex (generator -> execute_data );
762
+ } else {
763
+ zend_observer_generator_resume (generator -> execute_data );
764
+ zend_execute_ex (generator -> execute_data );
765
+ if (generator -> execute_data ) {
766
+ /* On the final return, this will be called from ZEND_GENERATOR_RETURN */
767
+ zend_observer_fcall_end (generator -> execute_data , & generator -> value );
760
768
}
769
+ }
770
+ generator -> flags &= ~ZEND_GENERATOR_CURRENTLY_RUNNING ;
761
771
762
- /* Resume execution */
763
- generator -> flags |= ZEND_GENERATOR_CURRENTLY_RUNNING ;
764
- if (!ZEND_OBSERVER_ENABLED ) {
765
- zend_execute_ex (generator -> execute_data );
766
- } else {
767
- zend_observer_generator_resume (generator -> execute_data );
768
- zend_execute_ex (generator -> execute_data );
769
- if (generator -> execute_data ) {
770
- /* On the final return, this will be called from ZEND_GENERATOR_RETURN */
771
- zend_observer_fcall_end (generator -> execute_data , & generator -> value );
772
- }
773
- }
774
- generator -> flags &= ~ZEND_GENERATOR_CURRENTLY_RUNNING ;
772
+ generator -> frozen_call_stack = NULL ;
773
+ if (EXPECTED (generator -> execute_data ) &&
774
+ UNEXPECTED (generator -> execute_data -> call )) {
775
+ /* Frize call-stack */
776
+ generator -> frozen_call_stack = zend_generator_freeze_call_stack (generator -> execute_data );
777
+ }
775
778
776
- generator -> frozen_call_stack = NULL ;
777
- if (EXPECTED (generator -> execute_data ) &&
778
- UNEXPECTED (generator -> execute_data -> call )) {
779
- /* Frize call-stack */
780
- generator -> frozen_call_stack = zend_generator_freeze_call_stack (generator -> execute_data );
781
- }
779
+ /* Restore executor globals */
780
+ EG (current_execute_data ) = original_execute_data ;
781
+ EG (jit_trace_num ) = original_jit_trace_num ;
782
782
783
- /* Restore executor globals */
784
- EG (current_execute_data ) = original_execute_data ;
785
- EG (jit_trace_num ) = original_jit_trace_num ;
786
-
787
- /* If an exception was thrown in the generator we have to internally
788
- * rethrow it in the parent scope.
789
- * In case we did yield from, the Exception must be rethrown into
790
- * its calling frame (see above in if (check_yield_from). */
791
- if (UNEXPECTED (EG (exception ) != NULL )) {
792
- if (generator == orig_generator ) {
793
- zend_generator_close (generator , 0 );
794
- if (!EG (current_execute_data )) {
795
- zend_throw_exception_internal (NULL );
796
- } else if (EG (current_execute_data )-> func &&
797
- ZEND_USER_CODE (EG (current_execute_data )-> func -> common .type )) {
798
- zend_rethrow_exception (EG (current_execute_data ));
799
- }
800
- } else {
801
- generator = zend_generator_get_current (orig_generator );
802
- zend_generator_throw_exception (generator , NULL );
803
- orig_generator -> flags &= ~ZEND_GENERATOR_DO_INIT ;
804
- goto try_again ;
783
+ /* If an exception was thrown in the generator we have to internally
784
+ * rethrow it in the parent scope.
785
+ * In case we did yield from, the Exception must be rethrown into
786
+ * its calling frame (see above in if (check_yield_from). */
787
+ if (UNEXPECTED (EG (exception ) != NULL )) {
788
+ if (generator == orig_generator ) {
789
+ zend_generator_close (generator , 0 );
790
+ if (!EG (current_execute_data )) {
791
+ zend_throw_exception_internal (NULL );
792
+ } else if (EG (current_execute_data )-> func &&
793
+ ZEND_USER_CODE (EG (current_execute_data )-> func -> common .type )) {
794
+ zend_rethrow_exception (EG (current_execute_data ));
805
795
}
806
- }
807
-
808
- /* yield from was used, try another resume. */
809
- if (UNEXPECTED ((generator != orig_generator && !Z_ISUNDEF (generator -> retval )) || (generator -> execute_data && (generator -> execute_data -> opline - 1 )-> opcode == ZEND_YIELD_FROM ))) {
796
+ } else {
810
797
generator = zend_generator_get_current (orig_generator );
798
+ zend_generator_throw_exception (generator , NULL );
799
+ orig_generator -> flags &= ~ZEND_GENERATOR_DO_INIT ;
811
800
goto try_again ;
812
801
}
813
802
}
814
803
804
+ /* yield from was used, try another resume. */
805
+ if (UNEXPECTED ((generator != orig_generator && !Z_ISUNDEF (generator -> retval )) || (generator -> execute_data && (generator -> execute_data -> opline - 1 )-> opcode == ZEND_YIELD_FROM ))) {
806
+ generator = zend_generator_get_current (orig_generator );
807
+ goto try_again ;
808
+ }
809
+
815
810
orig_generator -> flags &= ~ZEND_GENERATOR_DO_INIT ;
816
811
}
817
812
/* }}} */
0 commit comments