@@ -116,8 +116,7 @@ static void zend_generator_cleanup_unfinished_execution(
116
116
{
117
117
zend_op_array * op_array = & execute_data -> func -> op_array ;
118
118
if (execute_data -> opline != op_array -> opcodes ) {
119
- /* -1 required because we want the last run opcode, not the next to-be-run one. */
120
- uint32_t op_num = execute_data -> opline - op_array -> opcodes - 1 ;
119
+ uint32_t op_num = execute_data -> opline - op_array -> opcodes ;
121
120
122
121
if (UNEXPECTED (generator -> frozen_call_stack )) {
123
122
/* Temporarily restore generator->execute_data if it has been NULLed out already. */
@@ -299,9 +298,7 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
299
298
return ;
300
299
}
301
300
302
- /* -1 required because we want the last run opcode, not the
303
- * next to-be-run one. */
304
- op_num = ex -> opline - ex -> func -> op_array .opcodes - 1 ;
301
+ op_num = ex -> opline - ex -> func -> op_array .opcodes ;
305
302
try_catch_offset = -1 ;
306
303
307
304
/* Find the innermost try/catch that we are inside of. */
@@ -331,7 +328,8 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
331
328
Z_OBJ_P (fast_call ) = NULL ;
332
329
Z_OPLINE_NUM_P (fast_call ) = (uint32_t )-1 ;
333
330
334
- ex -> opline = & ex -> func -> op_array .opcodes [try_catch -> finally_op ];
331
+ /* -1 because zend_generator_resume() will increment it */
332
+ ex -> opline = & ex -> func -> op_array .opcodes [try_catch -> finally_op ] - 1 ;
335
333
generator -> flags |= ZEND_GENERATOR_FORCED_CLOSE ;
336
334
zend_generator_resume (generator );
337
335
@@ -516,9 +514,6 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
516
514
/* Throw the exception in the context of the generator. Decrementing the opline
517
515
* to pretend the exception happened during the YIELD opcode. */
518
516
EG (current_execute_data ) = generator -> execute_data ;
519
- generator -> execute_data -> opline -- ;
520
- ZEND_ASSERT (generator -> execute_data -> opline -> opcode == ZEND_YIELD
521
- || generator -> execute_data -> opline -> opcode == ZEND_YIELD_FROM );
522
517
generator -> execute_data -> prev_execute_data = original_execute_data ;
523
518
524
519
if (exception ) {
@@ -527,8 +522,6 @@ static void zend_generator_throw_exception(zend_generator *generator, zval *exce
527
522
zend_rethrow_exception (EG (current_execute_data ));
528
523
}
529
524
530
- generator -> execute_data -> opline ++ ;
531
-
532
525
/* if we don't stop an array/iterator yield from, the exception will only reach the generator after the values were all iterated over */
533
526
if (UNEXPECTED (Z_TYPE (generator -> values ) != IS_UNDEF )) {
534
527
zval_ptr_dtor (& generator -> values );
@@ -621,7 +614,7 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator
621
614
zend_generator_remove_child (& new_root_parent -> node , new_root );
622
615
623
616
if (EXPECTED (EG (exception ) == NULL ) && EXPECTED ((OBJ_FLAGS (& generator -> std ) & IS_OBJ_DESTRUCTOR_CALLED ) == 0 )) {
624
- zend_op * yield_from = (zend_op * ) new_root -> execute_data -> opline - 1 ;
617
+ zend_op * yield_from = (zend_op * ) new_root -> execute_data -> opline ;
625
618
626
619
if (yield_from -> opcode == ZEND_YIELD_FROM ) {
627
620
if (Z_ISUNDEF (new_root_parent -> retval )) {
@@ -636,8 +629,6 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator
636
629
generator -> execute_fake .prev_execute_data = original_execute_data ;
637
630
}
638
631
639
- /* ZEND_YIELD(_FROM) already advance, so decrement opline to throw from correct place */
640
- new_root -> execute_data -> opline -- ;
641
632
zend_throw_exception (zend_ce_ClosedGeneratorException , "Generator yielded from aborted, no return value available" , 0 );
642
633
643
634
EG (current_execute_data ) = original_execute_data ;
@@ -815,15 +806,6 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
815
806
generator -> flags &= ~ZEND_GENERATOR_IN_FIBER ;
816
807
return ;
817
808
}
818
- if (UNEXPECTED (EG (exception ))) {
819
- /* Decrementing opline_before_exception to pretend the exception
820
- * happened during the YIELD_FROM opcode. */
821
- if (generator -> execute_data ) {
822
- ZEND_ASSERT (generator -> execute_data -> opline == EG (exception_op ));
823
- ZEND_ASSERT ((EG (opline_before_exception )- 1 )-> opcode == ZEND_YIELD_FROM );
824
- EG (opline_before_exception )-- ;
825
- }
826
- }
827
809
/* If there are no more delegated values, resume the generator
828
810
* after the "yield from" expression. */
829
811
}
@@ -834,6 +816,16 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
834
816
}
835
817
836
818
/* Resume execution */
819
+ ZEND_ASSERT (generator -> execute_data -> opline -> opcode == ZEND_GENERATOR_CREATE
820
+ || generator -> execute_data -> opline -> opcode == ZEND_YIELD
821
+ || generator -> execute_data -> opline -> opcode == ZEND_YIELD_FROM
822
+ /* opline points to EG(exception_op), which is a sequence of
823
+ * ZEND_HANDLE_EXCEPTION ops, so the following increment is safe */
824
+ || generator -> execute_data -> opline -> opcode == ZEND_HANDLE_EXCEPTION
825
+ /* opline points to the start of a finally block minus one op to
826
+ * account for the following increment */
827
+ || (generator -> flags & ZEND_GENERATOR_FORCED_CLOSE ));
828
+ generator -> execute_data -> opline ++ ;
837
829
generator -> flags |= ZEND_GENERATOR_CURRENTLY_RUNNING ;
838
830
if (!ZEND_OBSERVER_ENABLED ) {
839
831
zend_execute_ex (generator -> execute_data );
@@ -880,7 +872,7 @@ ZEND_API void zend_generator_resume(zend_generator *orig_generator) /* {{{ */
880
872
}
881
873
882
874
/* yield from was used, try another resume. */
883
- if (UNEXPECTED ((generator != orig_generator && !Z_ISUNDEF (generator -> retval )) || (generator -> execute_data && ( generator -> execute_data -> opline - 1 ) -> opcode == ZEND_YIELD_FROM ))) {
875
+ if (UNEXPECTED ((generator != orig_generator && !Z_ISUNDEF (generator -> retval )) || (generator -> execute_data && generator -> execute_data -> opline -> opcode == ZEND_YIELD_FROM ))) {
884
876
generator = zend_generator_get_current (orig_generator );
885
877
goto try_again ;
886
878
}
0 commit comments