@@ -204,7 +204,7 @@ static ZEND_NORETURN void zend_fiber_trampoline(boost_context_data data)
204204 /* Initialize transfer struct with a copy of passed data. */
205205 zend_fiber_transfer transfer = * data .transfer ;
206206
207- zend_fiber_context * context = EG (current_fiber );
207+ zend_fiber_context * context = EG (current_fiber_context );
208208
209209 context -> function (& transfer );
210210 context -> status = ZEND_FIBER_STATUS_DEAD ;
@@ -241,7 +241,7 @@ ZEND_API void zend_fiber_destroy_context(zend_fiber_context *context)
241241
242242ZEND_API void zend_fiber_switch_context (zend_fiber_transfer * transfer )
243243{
244- zend_fiber_context * from = EG (current_fiber );
244+ zend_fiber_context * from = EG (current_fiber_context );
245245 zend_fiber_context * to = transfer -> context ;
246246 zend_fiber_vm_state state ;
247247
@@ -272,7 +272,7 @@ ZEND_API void zend_fiber_switch_context(zend_fiber_transfer *transfer)
272272 /* Update transfer context with the current fiber before switching. */
273273 transfer -> context = from ;
274274
275- EG (current_fiber ) = to ;
275+ EG (current_fiber_context ) = to ;
276276
277277#ifdef __SANITIZE_ADDRESS__
278278 void * fake_stack = NULL ;
@@ -295,7 +295,7 @@ ZEND_API void zend_fiber_switch_context(zend_fiber_transfer *transfer)
295295 __sanitizer_finish_switch_fiber (fake_stack , & to -> stack .prior_pointer , & to -> stack .prior_size );
296296#endif
297297
298- EG (current_fiber ) = from ;
298+ EG (current_fiber_context ) = from ;
299299
300300 zend_fiber_restore_vm_state (& state );
301301
@@ -312,11 +312,11 @@ ZEND_API void zend_fiber_switch_context(zend_fiber_transfer *transfer)
312312
313313static ZEND_STACK_ALIGNED void zend_fiber_execute (zend_fiber_transfer * transfer )
314314{
315- ZEND_ASSERT (Z_TYPE (transfer -> value ) == IS_UNDEF && "First context switch into a fiber must not transmit data" );
316-
317- zend_fiber * fiber = zend_fiber_from_context (EG (current_fiber ));
315+ zend_fiber * fiber = EG (active_fiber );
318316
317+ /* Determine the current error_reporting ini setting. */
319318 zend_long error_reporting = INI_INT ("error_reporting" );
319+ /* If error_reporting is 0 and not explicitly set to 0, INI_STR returns a null pointer. */
320320 if (!error_reporting && !INI_STR ("error_reporting" )) {
321321 error_reporting = E_ALL ;
322322 }
@@ -392,6 +392,50 @@ static zend_always_inline void delegate_transfer_result(
392392 RETURN_COPY_VALUE (& transfer -> value );
393393}
394394
395+ static zend_always_inline zend_fiber_transfer zend_fiber_switch_to (
396+ zend_fiber_context * context , zval * value , bool exception
397+ ) {
398+ zend_fiber_transfer transfer = {
399+ .context = context ,
400+ .flags = exception ? ZEND_FIBER_TRANSFER_FLAG_ERROR : 0 ,
401+ };
402+
403+ if (value ) {
404+ ZVAL_COPY (& transfer .value , value );
405+ } else {
406+ ZVAL_NULL (& transfer .value );
407+ }
408+
409+ zend_fiber_switch_context (& transfer );
410+
411+ return transfer ;
412+ }
413+
414+ static zend_always_inline zend_fiber_transfer zend_fiber_resume (zend_fiber * fiber , zval * value , bool exception )
415+ {
416+ zend_fiber * previous = EG (active_fiber );
417+
418+ fiber -> caller = EG (current_fiber_context );
419+ EG (active_fiber ) = fiber ;
420+
421+ zend_fiber_transfer transfer = zend_fiber_switch_to (fiber -> previous , value , exception );
422+
423+ EG (active_fiber ) = previous ;
424+
425+ return transfer ;
426+ }
427+
428+ static zend_always_inline zend_fiber_transfer zend_fiber_suspend (zend_fiber * fiber , zval * value )
429+ {
430+ ZEND_ASSERT (fiber -> caller != NULL );
431+
432+ zend_fiber_context * caller = fiber -> caller ;
433+ fiber -> previous = EG (current_fiber_context );
434+ fiber -> caller = NULL ;
435+
436+ return zend_fiber_switch_to (caller , value , false);
437+ }
438+
395439static zend_object * zend_fiber_object_create (zend_class_entry * ce )
396440{
397441 zend_fiber * fiber ;
@@ -416,14 +460,9 @@ static void zend_fiber_object_destroy(zend_object *object)
416460 zend_object * exception = EG (exception );
417461 EG (exception ) = NULL ;
418462
419- fiber -> caller = EG (current_fiber );
420463 fiber -> flags |= ZEND_FIBER_FLAG_DESTROYED ;
421464
422- zend_fiber_transfer transfer = {
423- .context = zend_fiber_get_context (fiber )
424- };
425-
426- zend_fiber_switch_context (& transfer );
465+ zend_fiber_transfer transfer = zend_fiber_resume (fiber , NULL , false);
427466
428467 if (transfer .flags & ZEND_FIBER_TRANSFER_FLAG_ERROR ) {
429468 EG (exception ) = Z_OBJ (transfer .value );
@@ -496,13 +535,9 @@ ZEND_METHOD(Fiber, start)
496535 RETURN_THROWS ();
497536 }
498537
499- fiber -> caller = EG (current_fiber );
500-
501- zend_fiber_transfer transfer = {
502- .context = context
503- };
538+ fiber -> previous = context ;
504539
505- zend_fiber_switch_context ( & transfer );
540+ zend_fiber_transfer transfer = zend_fiber_resume ( fiber , NULL , false );
506541
507542 delegate_transfer_result (fiber , & transfer , INTERNAL_FUNCTION_PARAM_PASSTHRU );
508543}
@@ -516,38 +551,24 @@ ZEND_METHOD(Fiber, suspend)
516551 Z_PARAM_ZVAL (value );
517552 ZEND_PARSE_PARAMETERS_END ();
518553
519- if (UNEXPECTED (EG (current_fiber )-> kind != zend_ce_fiber )) {
554+ zend_fiber * fiber = EG (active_fiber );
555+
556+ if (UNEXPECTED (!fiber )) {
520557 zend_throw_error (zend_ce_fiber_error , "Cannot suspend outside of a fiber" );
521558 RETURN_THROWS ();
522559 }
523560
524- zend_fiber * fiber = zend_fiber_from_context (EG (current_fiber ));
525- zend_fiber_context * caller = fiber -> caller ;
526-
527561 if (UNEXPECTED (fiber -> flags & ZEND_FIBER_FLAG_DESTROYED )) {
528562 zend_throw_error (zend_ce_fiber_error , "Cannot suspend in a force-closed fiber" );
529563 RETURN_THROWS ();
530564 }
531565
532- ZEND_ASSERT (fiber -> status == ZEND_FIBER_STATUS_RUNNING );
533- ZEND_ASSERT (caller != NULL );
534-
535- fiber -> caller = NULL ;
566+ ZEND_ASSERT (fiber -> status == ZEND_FIBER_STATUS_RUNNING || fiber -> status == ZEND_FIBER_STATUS_SUSPENDED );
536567
537568 fiber -> execute_data = EG (current_execute_data );
538569 fiber -> stack_bottom -> prev_execute_data = NULL ;
539570
540- zend_fiber_transfer transfer = {
541- .context = caller
542- };
543-
544- if (value ) {
545- ZVAL_COPY (& transfer .value , value );
546- } else {
547- ZVAL_NULL (& transfer .value );
548- }
549-
550- zend_fiber_switch_context (& transfer );
571+ zend_fiber_transfer transfer = zend_fiber_suspend (fiber , value );
551572
552573 if (fiber -> flags & ZEND_FIBER_FLAG_DESTROYED ) {
553574 // This occurs when the fiber is GC'ed while suspended.
@@ -576,21 +597,9 @@ ZEND_METHOD(Fiber, resume)
576597 RETURN_THROWS ();
577598 }
578599
579- fiber -> caller = EG (current_fiber );
580-
581600 fiber -> stack_bottom -> prev_execute_data = EG (current_execute_data );
582601
583- zend_fiber_transfer transfer = {
584- .context = zend_fiber_get_context (fiber )
585- };
586-
587- if (value ) {
588- ZVAL_COPY (& transfer .value , value );
589- } else {
590- ZVAL_NULL (& transfer .value );
591- }
592-
593- zend_fiber_switch_context (& transfer );
602+ zend_fiber_transfer transfer = zend_fiber_resume (fiber , value , false);
594603
595604 delegate_transfer_result (fiber , & transfer , INTERNAL_FUNCTION_PARAM_PASSTHRU );
596605}
@@ -611,18 +620,9 @@ ZEND_METHOD(Fiber, throw)
611620 RETURN_THROWS ();
612621 }
613622
614- fiber -> caller = EG (current_fiber );
615-
616623 fiber -> stack_bottom -> prev_execute_data = EG (current_execute_data );
617624
618- zend_fiber_transfer transfer = {
619- .context = zend_fiber_get_context (fiber ),
620- .flags = ZEND_FIBER_TRANSFER_FLAG_ERROR
621- };
622-
623- ZVAL_COPY (& transfer .value , exception );
624-
625- zend_fiber_switch_context (& transfer );
625+ zend_fiber_transfer transfer = zend_fiber_resume (fiber , exception , true);
626626
627627 delegate_transfer_result (fiber , & transfer , INTERNAL_FUNCTION_PARAM_PASSTHRU );
628628}
@@ -702,11 +702,13 @@ ZEND_METHOD(Fiber, this)
702702{
703703 ZEND_PARSE_PARAMETERS_NONE ();
704704
705- if (EG (current_fiber )-> kind != zend_ce_fiber ) {
705+ zend_fiber * fiber = EG (active_fiber );
706+
707+ if (!fiber ) {
706708 RETURN_NULL ();
707709 }
708710
709- RETURN_OBJ_COPY (& zend_fiber_from_context ( EG ( current_fiber )) -> std );
711+ RETURN_OBJ_COPY (& fiber -> std );
710712}
711713
712714ZEND_METHOD (FiberError , __construct )
@@ -741,11 +743,12 @@ void zend_fiber_init(void)
741743
742744 context -> status = ZEND_FIBER_STATUS_RUNNING ;
743745
744- EG (main_fiber ) = context ;
745- EG (current_fiber ) = context ;
746+ EG (main_fiber_context ) = context ;
747+ EG (current_fiber_context ) = context ;
748+ EG (active_fiber ) = NULL ;
746749}
747750
748751void zend_fiber_shutdown (void )
749752{
750- efree (EG (main_fiber ));
753+ efree (EG (main_fiber_context ));
751754}
0 commit comments