@@ -204,7 +204,7 @@ static ZEND_NORETURN void zend_fiber_trampoline(boost_context_data data)
204
204
/* Initialize transfer struct with a copy of passed data. */
205
205
zend_fiber_transfer transfer = * data .transfer ;
206
206
207
- zend_fiber_context * context = EG (current_fiber );
207
+ zend_fiber_context * context = EG (current_fiber_context );
208
208
209
209
context -> function (& transfer );
210
210
context -> status = ZEND_FIBER_STATUS_DEAD ;
@@ -241,7 +241,7 @@ ZEND_API void zend_fiber_destroy_context(zend_fiber_context *context)
241
241
242
242
ZEND_API void zend_fiber_switch_context (zend_fiber_transfer * transfer )
243
243
{
244
- zend_fiber_context * from = EG (current_fiber );
244
+ zend_fiber_context * from = EG (current_fiber_context );
245
245
zend_fiber_context * to = transfer -> context ;
246
246
zend_fiber_vm_state state ;
247
247
@@ -272,7 +272,7 @@ ZEND_API void zend_fiber_switch_context(zend_fiber_transfer *transfer)
272
272
/* Update transfer context with the current fiber before switching. */
273
273
transfer -> context = from ;
274
274
275
- EG (current_fiber ) = to ;
275
+ EG (current_fiber_context ) = to ;
276
276
277
277
#ifdef __SANITIZE_ADDRESS__
278
278
void * fake_stack = NULL ;
@@ -295,7 +295,7 @@ ZEND_API void zend_fiber_switch_context(zend_fiber_transfer *transfer)
295
295
__sanitizer_finish_switch_fiber (fake_stack , & to -> stack .prior_pointer , & to -> stack .prior_size );
296
296
#endif
297
297
298
- EG (current_fiber ) = from ;
298
+ EG (current_fiber_context ) = from ;
299
299
300
300
zend_fiber_restore_vm_state (& state );
301
301
@@ -312,11 +312,11 @@ ZEND_API void zend_fiber_switch_context(zend_fiber_transfer *transfer)
312
312
313
313
static ZEND_STACK_ALIGNED void zend_fiber_execute (zend_fiber_transfer * transfer )
314
314
{
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 );
318
316
317
+ /* Determine the current error_reporting ini setting. */
319
318
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. */
320
320
if (!error_reporting && !INI_STR ("error_reporting" )) {
321
321
error_reporting = E_ALL ;
322
322
}
@@ -392,6 +392,50 @@ static zend_always_inline void delegate_transfer_result(
392
392
RETURN_COPY_VALUE (& transfer -> value );
393
393
}
394
394
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
+
395
439
static zend_object * zend_fiber_object_create (zend_class_entry * ce )
396
440
{
397
441
zend_fiber * fiber ;
@@ -416,14 +460,9 @@ static void zend_fiber_object_destroy(zend_object *object)
416
460
zend_object * exception = EG (exception );
417
461
EG (exception ) = NULL ;
418
462
419
- fiber -> caller = EG (current_fiber );
420
463
fiber -> flags |= ZEND_FIBER_FLAG_DESTROYED ;
421
464
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);
427
466
428
467
if (transfer .flags & ZEND_FIBER_TRANSFER_FLAG_ERROR ) {
429
468
EG (exception ) = Z_OBJ (transfer .value );
@@ -496,13 +535,9 @@ ZEND_METHOD(Fiber, start)
496
535
RETURN_THROWS ();
497
536
}
498
537
499
- fiber -> caller = EG (current_fiber );
500
-
501
- zend_fiber_transfer transfer = {
502
- .context = context
503
- };
538
+ fiber -> previous = context ;
504
539
505
- zend_fiber_switch_context ( & transfer );
540
+ zend_fiber_transfer transfer = zend_fiber_resume ( fiber , NULL , false );
506
541
507
542
delegate_transfer_result (fiber , & transfer , INTERNAL_FUNCTION_PARAM_PASSTHRU );
508
543
}
@@ -516,38 +551,24 @@ ZEND_METHOD(Fiber, suspend)
516
551
Z_PARAM_ZVAL (value );
517
552
ZEND_PARSE_PARAMETERS_END ();
518
553
519
- if (UNEXPECTED (EG (current_fiber )-> kind != zend_ce_fiber )) {
554
+ zend_fiber * fiber = EG (active_fiber );
555
+
556
+ if (UNEXPECTED (!fiber )) {
520
557
zend_throw_error (zend_ce_fiber_error , "Cannot suspend outside of a fiber" );
521
558
RETURN_THROWS ();
522
559
}
523
560
524
- zend_fiber * fiber = zend_fiber_from_context (EG (current_fiber ));
525
- zend_fiber_context * caller = fiber -> caller ;
526
-
527
561
if (UNEXPECTED (fiber -> flags & ZEND_FIBER_FLAG_DESTROYED )) {
528
562
zend_throw_error (zend_ce_fiber_error , "Cannot suspend in a force-closed fiber" );
529
563
RETURN_THROWS ();
530
564
}
531
565
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 );
536
567
537
568
fiber -> execute_data = EG (current_execute_data );
538
569
fiber -> stack_bottom -> prev_execute_data = NULL ;
539
570
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 );
551
572
552
573
if (fiber -> flags & ZEND_FIBER_FLAG_DESTROYED ) {
553
574
// This occurs when the fiber is GC'ed while suspended.
@@ -576,21 +597,9 @@ ZEND_METHOD(Fiber, resume)
576
597
RETURN_THROWS ();
577
598
}
578
599
579
- fiber -> caller = EG (current_fiber );
580
-
581
600
fiber -> stack_bottom -> prev_execute_data = EG (current_execute_data );
582
601
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);
594
603
595
604
delegate_transfer_result (fiber , & transfer , INTERNAL_FUNCTION_PARAM_PASSTHRU );
596
605
}
@@ -611,18 +620,9 @@ ZEND_METHOD(Fiber, throw)
611
620
RETURN_THROWS ();
612
621
}
613
622
614
- fiber -> caller = EG (current_fiber );
615
-
616
623
fiber -> stack_bottom -> prev_execute_data = EG (current_execute_data );
617
624
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);
626
626
627
627
delegate_transfer_result (fiber , & transfer , INTERNAL_FUNCTION_PARAM_PASSTHRU );
628
628
}
@@ -702,11 +702,13 @@ ZEND_METHOD(Fiber, this)
702
702
{
703
703
ZEND_PARSE_PARAMETERS_NONE ();
704
704
705
- if (EG (current_fiber )-> kind != zend_ce_fiber ) {
705
+ zend_fiber * fiber = EG (active_fiber );
706
+
707
+ if (!fiber ) {
706
708
RETURN_NULL ();
707
709
}
708
710
709
- RETURN_OBJ_COPY (& zend_fiber_from_context ( EG ( current_fiber )) -> std );
711
+ RETURN_OBJ_COPY (& fiber -> std );
710
712
}
711
713
712
714
ZEND_METHOD (FiberError , __construct )
@@ -741,11 +743,12 @@ void zend_fiber_init(void)
741
743
742
744
context -> status = ZEND_FIBER_STATUS_RUNNING ;
743
745
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 ;
746
749
}
747
750
748
751
void zend_fiber_shutdown (void )
749
752
{
750
- efree (EG (main_fiber ));
753
+ efree (EG (main_fiber_context ));
751
754
}
0 commit comments