Skip to content

Commit 859524c

Browse files
committed
Remove fiber context embedding
1 parent fdc2274 commit 859524c

File tree

5 files changed

+51
-66
lines changed

5 files changed

+51
-66
lines changed

Zend/zend_fibers.c

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -392,10 +392,10 @@ static ZEND_STACK_ALIGNED void zend_fiber_execute(zend_fiber_transfer *transfer)
392392
zval_ptr_dtor(&fiber->fci.function_name);
393393

394394
if (EG(exception)) {
395-
if (!(fiber->flags & ZEND_FIBER_FLAG_DESTROYED)
395+
if (!(fiber->context.flags & ZEND_FIBER_FLAG_DESTROYED)
396396
|| !(zend_is_graceful_exit(EG(exception)) || zend_is_unwind_exit(EG(exception)))
397397
) {
398-
fiber->flags |= ZEND_FIBER_FLAG_THREW;
398+
fiber->context.flags |= ZEND_FIBER_FLAG_THREW;
399399
transfer->flags = ZEND_FIBER_TRANSFER_FLAG_ERROR;
400400

401401
ZVAL_OBJ_COPY(&transfer->value, EG(exception));
@@ -406,7 +406,7 @@ static ZEND_STACK_ALIGNED void zend_fiber_execute(zend_fiber_transfer *transfer)
406406
ZVAL_COPY(&transfer->value, &fiber->result);
407407
}
408408
} zend_catch {
409-
fiber->flags |= ZEND_FIBER_FLAG_BAILOUT;
409+
fiber->context.flags |= ZEND_FIBER_FLAG_BAILOUT;
410410
} zend_end_try();
411411

412412
transfer->context = fiber->caller;
@@ -427,7 +427,7 @@ static zend_always_inline void delegate_transfer_result(
427427
RETURN_THROWS();
428428
}
429429

430-
if (fiber->status == ZEND_FIBER_STATUS_DEAD) {
430+
if (fiber->context.status == ZEND_FIBER_STATUS_DEAD) {
431431
zval_ptr_dtor(&transfer->value);
432432
RETURN_NULL();
433433
}
@@ -496,14 +496,14 @@ static void zend_fiber_object_destroy(zend_object *object)
496496
{
497497
zend_fiber *fiber = (zend_fiber *) object;
498498

499-
if (fiber->status != ZEND_FIBER_STATUS_SUSPENDED) {
499+
if (fiber->context.status != ZEND_FIBER_STATUS_SUSPENDED) {
500500
return;
501501
}
502502

503503
zend_object *exception = EG(exception);
504504
EG(exception) = NULL;
505505

506-
fiber->flags |= ZEND_FIBER_FLAG_DESTROYED;
506+
fiber->context.flags |= ZEND_FIBER_FLAG_DESTROYED;
507507

508508
zend_fiber_transfer transfer = zend_fiber_resume(fiber, NULL, false);
509509

@@ -530,7 +530,7 @@ static void zend_fiber_object_free(zend_object *object)
530530
{
531531
zend_fiber *fiber = (zend_fiber *) object;
532532

533-
if (fiber->status == ZEND_FIBER_STATUS_INIT) {
533+
if (fiber->context.status == ZEND_FIBER_STATUS_INIT) {
534534
// Fiber was never started, so we need to release the reference to the callback.
535535
zval_ptr_dtor(&fiber->fci.function_name);
536536
}
@@ -568,7 +568,7 @@ ZEND_METHOD(Fiber, start)
568568
RETURN_THROWS();
569569
}
570570

571-
if (fiber->status != ZEND_FIBER_STATUS_INIT) {
571+
if (fiber->context.status != ZEND_FIBER_STATUS_INIT) {
572572
zend_throw_error(zend_ce_fiber_error, "Cannot start a fiber that has already been started");
573573
RETURN_THROWS();
574574
}
@@ -577,13 +577,11 @@ ZEND_METHOD(Fiber, start)
577577
fiber->fci.param_count = param_count;
578578
fiber->fci.named_params = named_params;
579579

580-
zend_fiber_context *context = zend_fiber_get_context(fiber);
581-
582-
if (!zend_fiber_init_context(context, zend_ce_fiber, zend_fiber_execute, EG(fiber_stack_size))) {
580+
if (!zend_fiber_init_context(&fiber->context, zend_ce_fiber, zend_fiber_execute, EG(fiber_stack_size))) {
583581
RETURN_THROWS();
584582
}
585583

586-
fiber->previous = context;
584+
fiber->previous = &fiber->context;
587585

588586
zend_fiber_transfer transfer = zend_fiber_resume(fiber, NULL, false);
589587

@@ -606,7 +604,7 @@ ZEND_METHOD(Fiber, suspend)
606604
RETURN_THROWS();
607605
}
608606

609-
if (UNEXPECTED(fiber->flags & ZEND_FIBER_FLAG_DESTROYED)) {
607+
if (UNEXPECTED(fiber->context.flags & ZEND_FIBER_FLAG_DESTROYED)) {
610608
zend_throw_error(zend_ce_fiber_error, "Cannot suspend in a force-closed fiber");
611609
RETURN_THROWS();
612610
}
@@ -616,14 +614,14 @@ ZEND_METHOD(Fiber, suspend)
616614
RETURN_THROWS();
617615
}
618616

619-
ZEND_ASSERT(fiber->status == ZEND_FIBER_STATUS_RUNNING || fiber->status == ZEND_FIBER_STATUS_SUSPENDED);
617+
ZEND_ASSERT(fiber->context.status == ZEND_FIBER_STATUS_RUNNING || fiber->context.status == ZEND_FIBER_STATUS_SUSPENDED);
620618

621619
fiber->execute_data = EG(current_execute_data);
622620
fiber->stack_bottom->prev_execute_data = NULL;
623621

624622
zend_fiber_transfer transfer = zend_fiber_suspend(fiber, value);
625623

626-
if (fiber->flags & ZEND_FIBER_FLAG_DESTROYED) {
624+
if (fiber->context.flags & ZEND_FIBER_FLAG_DESTROYED) {
627625
// This occurs when the fiber is GC'ed while suspended.
628626
zval_ptr_dtor(&transfer.value);
629627
zend_throw_graceful_exit();
@@ -650,7 +648,7 @@ ZEND_METHOD(Fiber, resume)
650648

651649
fiber = (zend_fiber *) Z_OBJ_P(getThis());
652650

653-
if (UNEXPECTED(fiber->status != ZEND_FIBER_STATUS_SUSPENDED || fiber->caller != NULL)) {
651+
if (UNEXPECTED(fiber->context.status != ZEND_FIBER_STATUS_SUSPENDED || fiber->caller != NULL)) {
654652
zend_throw_error(zend_ce_fiber_error, "Cannot resume a fiber that is not suspended");
655653
RETURN_THROWS();
656654
}
@@ -678,7 +676,7 @@ ZEND_METHOD(Fiber, throw)
678676

679677
fiber = (zend_fiber *) Z_OBJ_P(getThis());
680678

681-
if (UNEXPECTED(fiber->status != ZEND_FIBER_STATUS_SUSPENDED || fiber->caller != NULL)) {
679+
if (UNEXPECTED(fiber->context.status != ZEND_FIBER_STATUS_SUSPENDED || fiber->caller != NULL)) {
682680
zend_throw_error(zend_ce_fiber_error, "Cannot resume a fiber that is not suspended");
683681
RETURN_THROWS();
684682
}
@@ -698,7 +696,7 @@ ZEND_METHOD(Fiber, isStarted)
698696

699697
fiber = (zend_fiber *) Z_OBJ_P(getThis());
700698

701-
RETURN_BOOL(fiber->status != ZEND_FIBER_STATUS_INIT);
699+
RETURN_BOOL(fiber->context.status != ZEND_FIBER_STATUS_INIT);
702700
}
703701

704702
ZEND_METHOD(Fiber, isSuspended)
@@ -709,7 +707,7 @@ ZEND_METHOD(Fiber, isSuspended)
709707

710708
fiber = (zend_fiber *) Z_OBJ_P(getThis());
711709

712-
RETURN_BOOL(fiber->status == ZEND_FIBER_STATUS_SUSPENDED && fiber->caller == NULL);
710+
RETURN_BOOL(fiber->context.status == ZEND_FIBER_STATUS_SUSPENDED && fiber->caller == NULL);
713711
}
714712

715713
ZEND_METHOD(Fiber, isRunning)
@@ -720,7 +718,7 @@ ZEND_METHOD(Fiber, isRunning)
720718

721719
fiber = (zend_fiber *) Z_OBJ_P(getThis());
722720

723-
RETURN_BOOL(fiber->status == ZEND_FIBER_STATUS_RUNNING || fiber->caller != NULL);
721+
RETURN_BOOL(fiber->context.status == ZEND_FIBER_STATUS_RUNNING || fiber->caller != NULL);
724722
}
725723

726724
ZEND_METHOD(Fiber, isTerminated)
@@ -731,7 +729,7 @@ ZEND_METHOD(Fiber, isTerminated)
731729

732730
fiber = (zend_fiber *) Z_OBJ_P(getThis());
733731

734-
RETURN_BOOL(fiber->status == ZEND_FIBER_STATUS_DEAD);
732+
RETURN_BOOL(fiber->context.status == ZEND_FIBER_STATUS_DEAD);
735733
}
736734

737735
ZEND_METHOD(Fiber, getReturn)
@@ -743,15 +741,15 @@ ZEND_METHOD(Fiber, getReturn)
743741

744742
fiber = (zend_fiber *) Z_OBJ_P(getThis());
745743

746-
if (fiber->status == ZEND_FIBER_STATUS_DEAD) {
747-
if (fiber->flags & ZEND_FIBER_FLAG_THREW) {
744+
if (fiber->context.status == ZEND_FIBER_STATUS_DEAD) {
745+
if (fiber->context.flags & ZEND_FIBER_FLAG_THREW) {
748746
message = "The fiber threw an exception";
749-
} else if (fiber->flags & ZEND_FIBER_FLAG_BAILOUT) {
747+
} else if (fiber->context.flags & ZEND_FIBER_FLAG_BAILOUT) {
750748
message = "The fiber exited with a fatal error";
751749
} else {
752750
RETURN_COPY(&fiber->result);
753751
}
754-
} else if (fiber->status == ZEND_FIBER_STATUS_INIT) {
752+
} else if (fiber->context.status == ZEND_FIBER_STATUS_INIT) {
755753
message = "The fiber has not been started";
756754
} else {
757755
message = "The fiber has not returned";

Zend/zend_fibers.h

Lines changed: 11 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -74,20 +74,15 @@ typedef struct _zend_fiber_transfer {
7474
* and (optional) data before they return. */
7575
typedef void (*zend_fiber_coroutine)(zend_fiber_transfer *transfer);
7676

77-
/* Defined as a macro to allow anonymous embedding. */
78-
#define ZEND_FIBER_CONTEXT_FIELDS \
79-
/* Handle to fiber state as needed by boost.context */ \
80-
void *handle; \
81-
/* Pointer that identifies the fiber type. */ \
82-
void *kind; \
83-
zend_fiber_coroutine function; \
84-
zend_fiber_stack *stack; \
85-
zend_fiber_status status; \
86-
uint8_t flags
87-
88-
/* Standalone context (used primarily as pointer type). */
8977
struct _zend_fiber_context {
90-
ZEND_FIBER_CONTEXT_FIELDS;
78+
/* Handle to fiber state as needed by boost.context */
79+
void *handle;
80+
/* Pointer that identifies the fiber type. */
81+
void *kind;
82+
zend_fiber_coroutine function;
83+
zend_fiber_stack *stack;
84+
zend_fiber_status status;
85+
uint8_t flags;
9186
};
9287

9388
/* Zend VM state that needs to be captured / restored during fiber context switch. */
@@ -107,8 +102,7 @@ struct _zend_fiber {
107102
/* PHP object handle. */
108103
zend_object std;
109104

110-
/* Fiber context fields (embedded to avoid memory allocation). */
111-
ZEND_FIBER_CONTEXT_FIELDS;
105+
zend_fiber_context context;
112106

113107
/* Fiber that resumed us. */
114108
zend_fiber_context *caller;
@@ -141,12 +135,12 @@ static zend_always_inline zend_fiber *zend_fiber_from_context(zend_fiber_context
141135
{
142136
ZEND_ASSERT(context->kind == zend_ce_fiber && "Fiber context does not belong to a Zend fiber");
143137

144-
return (zend_fiber *)(((char *) context) - XtOffsetOf(zend_fiber, handle));
138+
return (zend_fiber *)(((char *) context) - XtOffsetOf(zend_fiber, context));
145139
}
146140

147141
static zend_always_inline zend_fiber_context *zend_fiber_get_context(zend_fiber *fiber)
148142
{
149-
return (zend_fiber_context *) &fiber->handle;
143+
return &fiber->context;
150144
}
151145

152146
static zend_always_inline void zend_fiber_capture_vm_state(zend_fiber_vm_state *state)

ext/reflection/php_reflection.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6873,7 +6873,7 @@ ZEND_METHOD(ReflectionFiber, getFiber)
68736873
}
68746874

68756875
#define REFLECTION_CHECK_VALID_FIBER(fiber) do { \
6876-
if (fiber == NULL || fiber->status == ZEND_FIBER_STATUS_INIT || fiber->status == ZEND_FIBER_STATUS_DEAD) { \
6876+
if (fiber == NULL || fiber->context.status == ZEND_FIBER_STATUS_INIT || fiber->context.status == ZEND_FIBER_STATUS_DEAD) { \
68776877
zend_throw_error(NULL, "Cannot fetch information from a fiber that has not been started or is terminated"); \
68786878
RETURN_THROWS(); \
68796879
} \
@@ -6948,7 +6948,7 @@ ZEND_METHOD(ReflectionFiber, getCallable)
69486948

69496949
ZEND_PARSE_PARAMETERS_NONE();
69506950

6951-
if (fiber == NULL || fiber->status == ZEND_FIBER_STATUS_DEAD) {
6951+
if (fiber == NULL || fiber->context.status == ZEND_FIBER_STATUS_DEAD) {
69526952
zend_throw_error(NULL, "Cannot fetch the callable from a fiber that has terminated"); \
69536953
RETURN_THROWS();
69546954
}

ext/zend_test/fiber.c

Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,6 @@
2323
static zend_class_entry *zend_test_fiber_class;
2424
static zend_object_handlers zend_test_fiber_handlers;
2525

26-
static zend_always_inline zend_fiber_context *zend_test_fiber_get_context(zend_test_fiber *fiber)
27-
{
28-
return (zend_fiber_context *) &fiber->handle;
29-
}
30-
3126
static zend_fiber_transfer zend_test_fiber_switch_to(zend_fiber_context *context, zval *value, bool exception)
3227
{
3328
zend_fiber_transfer transfer = {
@@ -102,10 +97,10 @@ static ZEND_STACK_ALIGNED void zend_test_fiber_execute(zend_fiber_transfer *tran
10297
zval_ptr_dtor(&fiber->fci.function_name);
10398

10499
if (EG(exception)) {
105-
if (!(fiber->flags & ZEND_FIBER_FLAG_DESTROYED)
100+
if (!(fiber->context.flags & ZEND_FIBER_FLAG_DESTROYED)
106101
|| !(zend_is_graceful_exit(EG(exception)) || zend_is_unwind_exit(EG(exception)))
107102
) {
108-
fiber->flags |= ZEND_FIBER_FLAG_THREW;
103+
fiber->context.flags |= ZEND_FIBER_FLAG_THREW;
109104
transfer->flags = ZEND_FIBER_TRANSFER_FLAG_ERROR;
110105

111106
ZVAL_OBJ_COPY(&transfer->value, EG(exception));
@@ -117,13 +112,13 @@ static ZEND_STACK_ALIGNED void zend_test_fiber_execute(zend_fiber_transfer *tran
117112
ZVAL_COPY(&transfer->value, &fiber->result);
118113
}
119114
} zend_catch {
120-
fiber->flags |= ZEND_FIBER_FLAG_BAILOUT;
115+
fiber->context.flags |= ZEND_FIBER_FLAG_BAILOUT;
121116
} zend_end_try();
122117

123118
zend_vm_stack_destroy();
124119

125120
if (fiber->target) {
126-
zend_fiber_context *target = zend_test_fiber_get_context(fiber->target);
121+
zend_fiber_context *target = &fiber->target->context;
127122
zend_fiber_init_context(target, zend_test_fiber_class, zend_test_fiber_execute, EG(fiber_stack_size));
128123
transfer->context = target;
129124

@@ -157,14 +152,14 @@ static void zend_test_fiber_object_destroy(zend_object *object)
157152
{
158153
zend_test_fiber *fiber = (zend_test_fiber *) object;
159154

160-
if (fiber->status != ZEND_FIBER_STATUS_SUSPENDED) {
155+
if (fiber->context.status != ZEND_FIBER_STATUS_SUSPENDED) {
161156
return;
162157
}
163158

164159
zend_object *exception = EG(exception);
165160
EG(exception) = NULL;
166161

167-
fiber->flags |= ZEND_FIBER_FLAG_DESTROYED;
162+
fiber->context.flags |= ZEND_FIBER_FLAG_DESTROYED;
168163

169164
zend_fiber_transfer transfer = zend_test_fiber_resume(fiber, NULL, false);
170165

@@ -191,7 +186,7 @@ static void zend_test_fiber_object_free(zend_object *object)
191186
{
192187
zend_test_fiber *fiber = (zend_test_fiber *) object;
193188

194-
if (fiber->status == ZEND_FIBER_STATUS_INIT) {
189+
if (fiber->context.status == ZEND_FIBER_STATUS_INIT) {
195190
// Fiber was never started, so we need to release the reference to the callback.
196191
zval_ptr_dtor(&fiber->fci.function_name);
197192
}
@@ -213,7 +208,7 @@ static zend_always_inline void delegate_transfer_result(
213208
RETURN_THROWS();
214209
}
215210

216-
if (fiber->status == ZEND_FIBER_STATUS_DEAD) {
211+
if (fiber->context.status == ZEND_FIBER_STATUS_DEAD) {
217212
zval_ptr_dtor(&transfer->value);
218213
RETURN_NULL();
219214
}
@@ -244,7 +239,7 @@ static ZEND_METHOD(_ZendTestFiber, start)
244239
Z_PARAM_VARIADIC_WITH_NAMED(params, param_count, named_params);
245240
ZEND_PARSE_PARAMETERS_END();
246241

247-
ZEND_ASSERT(fiber->status == ZEND_FIBER_STATUS_INIT);
242+
ZEND_ASSERT(fiber->context.status == ZEND_FIBER_STATUS_INIT);
248243

249244
if (fiber->previous != NULL) {
250245
zend_throw_error(NULL, "Cannot start a fiber that is the target of another fiber");
@@ -255,11 +250,9 @@ static ZEND_METHOD(_ZendTestFiber, start)
255250
fiber->fci.param_count = param_count;
256251
fiber->fci.named_params = named_params;
257252

258-
zend_fiber_context *context = zend_test_fiber_get_context(fiber);
259-
260-
zend_fiber_init_context(context, zend_test_fiber_class, zend_test_fiber_execute, EG(fiber_stack_size));
253+
zend_fiber_init_context(&fiber->context, zend_test_fiber_class, zend_test_fiber_execute, EG(fiber_stack_size));
261254

262-
fiber->previous = context;
255+
fiber->previous = &fiber->context;
263256

264257
zend_fiber_transfer transfer = zend_test_fiber_resume(fiber, NULL, false);
265258

@@ -281,7 +274,7 @@ static ZEND_METHOD(_ZendTestFiber, suspend)
281274

282275
zend_fiber_transfer transfer = zend_test_fiber_suspend(fiber, value);
283276

284-
if (fiber->flags & ZEND_FIBER_FLAG_DESTROYED) {
277+
if (fiber->context.flags & ZEND_FIBER_FLAG_DESTROYED) {
285278
// This occurs when the test fiber is GC'ed while suspended.
286279
zval_ptr_dtor(&transfer.value);
287280
zend_throw_graceful_exit();
@@ -303,7 +296,7 @@ static ZEND_METHOD(_ZendTestFiber, resume)
303296

304297
fiber = (zend_test_fiber *) Z_OBJ_P(getThis());
305298

306-
if (UNEXPECTED(fiber->status != ZEND_FIBER_STATUS_SUSPENDED || fiber->caller != NULL)) {
299+
if (UNEXPECTED(fiber->context.status != ZEND_FIBER_STATUS_SUSPENDED || fiber->caller != NULL)) {
307300
zend_throw_error(NULL, "Cannot resume a fiber that is not suspended");
308301
RETURN_THROWS();
309302
}
@@ -329,7 +322,7 @@ static ZEND_METHOD(_ZendTestFiber, pipeTo)
329322
target->fci_cache = fci_cache;
330323
Z_TRY_ADDREF(target->fci.function_name);
331324

332-
target->previous = zend_test_fiber_get_context(fiber);
325+
target->previous = &fiber->context;
333326

334327
if (fiber->target) {
335328
OBJ_RELEASE(&fiber->target->std);

ext/zend_test/fiber.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ typedef struct _zend_test_fiber zend_test_fiber;
2323

2424
struct _zend_test_fiber {
2525
zend_object std;
26-
ZEND_FIBER_CONTEXT_FIELDS;
26+
zend_fiber_context context;
2727
zend_fiber_context *caller;
2828
zend_fiber_context *previous;
2929
zend_test_fiber *target;

0 commit comments

Comments
 (0)