mirror of
https://github.com/php/php-src.git
synced 2024-09-21 18:07:23 +00:00
Remove fiber context embedding
This commit is contained in:
parent
fdc22744a8
commit
859524c246
@ -392,10 +392,10 @@ static ZEND_STACK_ALIGNED void zend_fiber_execute(zend_fiber_transfer *transfer)
|
||||
zval_ptr_dtor(&fiber->fci.function_name);
|
||||
|
||||
if (EG(exception)) {
|
||||
if (!(fiber->flags & ZEND_FIBER_FLAG_DESTROYED)
|
||||
if (!(fiber->context.flags & ZEND_FIBER_FLAG_DESTROYED)
|
||||
|| !(zend_is_graceful_exit(EG(exception)) || zend_is_unwind_exit(EG(exception)))
|
||||
) {
|
||||
fiber->flags |= ZEND_FIBER_FLAG_THREW;
|
||||
fiber->context.flags |= ZEND_FIBER_FLAG_THREW;
|
||||
transfer->flags = ZEND_FIBER_TRANSFER_FLAG_ERROR;
|
||||
|
||||
ZVAL_OBJ_COPY(&transfer->value, EG(exception));
|
||||
@ -406,7 +406,7 @@ static ZEND_STACK_ALIGNED void zend_fiber_execute(zend_fiber_transfer *transfer)
|
||||
ZVAL_COPY(&transfer->value, &fiber->result);
|
||||
}
|
||||
} zend_catch {
|
||||
fiber->flags |= ZEND_FIBER_FLAG_BAILOUT;
|
||||
fiber->context.flags |= ZEND_FIBER_FLAG_BAILOUT;
|
||||
} zend_end_try();
|
||||
|
||||
transfer->context = fiber->caller;
|
||||
@ -427,7 +427,7 @@ static zend_always_inline void delegate_transfer_result(
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (fiber->status == ZEND_FIBER_STATUS_DEAD) {
|
||||
if (fiber->context.status == ZEND_FIBER_STATUS_DEAD) {
|
||||
zval_ptr_dtor(&transfer->value);
|
||||
RETURN_NULL();
|
||||
}
|
||||
@ -496,14 +496,14 @@ static void zend_fiber_object_destroy(zend_object *object)
|
||||
{
|
||||
zend_fiber *fiber = (zend_fiber *) object;
|
||||
|
||||
if (fiber->status != ZEND_FIBER_STATUS_SUSPENDED) {
|
||||
if (fiber->context.status != ZEND_FIBER_STATUS_SUSPENDED) {
|
||||
return;
|
||||
}
|
||||
|
||||
zend_object *exception = EG(exception);
|
||||
EG(exception) = NULL;
|
||||
|
||||
fiber->flags |= ZEND_FIBER_FLAG_DESTROYED;
|
||||
fiber->context.flags |= ZEND_FIBER_FLAG_DESTROYED;
|
||||
|
||||
zend_fiber_transfer transfer = zend_fiber_resume(fiber, NULL, false);
|
||||
|
||||
@ -530,7 +530,7 @@ static void zend_fiber_object_free(zend_object *object)
|
||||
{
|
||||
zend_fiber *fiber = (zend_fiber *) object;
|
||||
|
||||
if (fiber->status == ZEND_FIBER_STATUS_INIT) {
|
||||
if (fiber->context.status == ZEND_FIBER_STATUS_INIT) {
|
||||
// Fiber was never started, so we need to release the reference to the callback.
|
||||
zval_ptr_dtor(&fiber->fci.function_name);
|
||||
}
|
||||
@ -568,7 +568,7 @@ ZEND_METHOD(Fiber, start)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (fiber->status != ZEND_FIBER_STATUS_INIT) {
|
||||
if (fiber->context.status != ZEND_FIBER_STATUS_INIT) {
|
||||
zend_throw_error(zend_ce_fiber_error, "Cannot start a fiber that has already been started");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
@ -577,13 +577,11 @@ ZEND_METHOD(Fiber, start)
|
||||
fiber->fci.param_count = param_count;
|
||||
fiber->fci.named_params = named_params;
|
||||
|
||||
zend_fiber_context *context = zend_fiber_get_context(fiber);
|
||||
|
||||
if (!zend_fiber_init_context(context, zend_ce_fiber, zend_fiber_execute, EG(fiber_stack_size))) {
|
||||
if (!zend_fiber_init_context(&fiber->context, zend_ce_fiber, zend_fiber_execute, EG(fiber_stack_size))) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
fiber->previous = context;
|
||||
fiber->previous = &fiber->context;
|
||||
|
||||
zend_fiber_transfer transfer = zend_fiber_resume(fiber, NULL, false);
|
||||
|
||||
@ -606,7 +604,7 @@ ZEND_METHOD(Fiber, suspend)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (UNEXPECTED(fiber->flags & ZEND_FIBER_FLAG_DESTROYED)) {
|
||||
if (UNEXPECTED(fiber->context.flags & ZEND_FIBER_FLAG_DESTROYED)) {
|
||||
zend_throw_error(zend_ce_fiber_error, "Cannot suspend in a force-closed fiber");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
@ -616,14 +614,14 @@ ZEND_METHOD(Fiber, suspend)
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
ZEND_ASSERT(fiber->status == ZEND_FIBER_STATUS_RUNNING || fiber->status == ZEND_FIBER_STATUS_SUSPENDED);
|
||||
ZEND_ASSERT(fiber->context.status == ZEND_FIBER_STATUS_RUNNING || fiber->context.status == ZEND_FIBER_STATUS_SUSPENDED);
|
||||
|
||||
fiber->execute_data = EG(current_execute_data);
|
||||
fiber->stack_bottom->prev_execute_data = NULL;
|
||||
|
||||
zend_fiber_transfer transfer = zend_fiber_suspend(fiber, value);
|
||||
|
||||
if (fiber->flags & ZEND_FIBER_FLAG_DESTROYED) {
|
||||
if (fiber->context.flags & ZEND_FIBER_FLAG_DESTROYED) {
|
||||
// This occurs when the fiber is GC'ed while suspended.
|
||||
zval_ptr_dtor(&transfer.value);
|
||||
zend_throw_graceful_exit();
|
||||
@ -650,7 +648,7 @@ ZEND_METHOD(Fiber, resume)
|
||||
|
||||
fiber = (zend_fiber *) Z_OBJ_P(getThis());
|
||||
|
||||
if (UNEXPECTED(fiber->status != ZEND_FIBER_STATUS_SUSPENDED || fiber->caller != NULL)) {
|
||||
if (UNEXPECTED(fiber->context.status != ZEND_FIBER_STATUS_SUSPENDED || fiber->caller != NULL)) {
|
||||
zend_throw_error(zend_ce_fiber_error, "Cannot resume a fiber that is not suspended");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
@ -678,7 +676,7 @@ ZEND_METHOD(Fiber, throw)
|
||||
|
||||
fiber = (zend_fiber *) Z_OBJ_P(getThis());
|
||||
|
||||
if (UNEXPECTED(fiber->status != ZEND_FIBER_STATUS_SUSPENDED || fiber->caller != NULL)) {
|
||||
if (UNEXPECTED(fiber->context.status != ZEND_FIBER_STATUS_SUSPENDED || fiber->caller != NULL)) {
|
||||
zend_throw_error(zend_ce_fiber_error, "Cannot resume a fiber that is not suspended");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
@ -698,7 +696,7 @@ ZEND_METHOD(Fiber, isStarted)
|
||||
|
||||
fiber = (zend_fiber *) Z_OBJ_P(getThis());
|
||||
|
||||
RETURN_BOOL(fiber->status != ZEND_FIBER_STATUS_INIT);
|
||||
RETURN_BOOL(fiber->context.status != ZEND_FIBER_STATUS_INIT);
|
||||
}
|
||||
|
||||
ZEND_METHOD(Fiber, isSuspended)
|
||||
@ -709,7 +707,7 @@ ZEND_METHOD(Fiber, isSuspended)
|
||||
|
||||
fiber = (zend_fiber *) Z_OBJ_P(getThis());
|
||||
|
||||
RETURN_BOOL(fiber->status == ZEND_FIBER_STATUS_SUSPENDED && fiber->caller == NULL);
|
||||
RETURN_BOOL(fiber->context.status == ZEND_FIBER_STATUS_SUSPENDED && fiber->caller == NULL);
|
||||
}
|
||||
|
||||
ZEND_METHOD(Fiber, isRunning)
|
||||
@ -720,7 +718,7 @@ ZEND_METHOD(Fiber, isRunning)
|
||||
|
||||
fiber = (zend_fiber *) Z_OBJ_P(getThis());
|
||||
|
||||
RETURN_BOOL(fiber->status == ZEND_FIBER_STATUS_RUNNING || fiber->caller != NULL);
|
||||
RETURN_BOOL(fiber->context.status == ZEND_FIBER_STATUS_RUNNING || fiber->caller != NULL);
|
||||
}
|
||||
|
||||
ZEND_METHOD(Fiber, isTerminated)
|
||||
@ -731,7 +729,7 @@ ZEND_METHOD(Fiber, isTerminated)
|
||||
|
||||
fiber = (zend_fiber *) Z_OBJ_P(getThis());
|
||||
|
||||
RETURN_BOOL(fiber->status == ZEND_FIBER_STATUS_DEAD);
|
||||
RETURN_BOOL(fiber->context.status == ZEND_FIBER_STATUS_DEAD);
|
||||
}
|
||||
|
||||
ZEND_METHOD(Fiber, getReturn)
|
||||
@ -743,15 +741,15 @@ ZEND_METHOD(Fiber, getReturn)
|
||||
|
||||
fiber = (zend_fiber *) Z_OBJ_P(getThis());
|
||||
|
||||
if (fiber->status == ZEND_FIBER_STATUS_DEAD) {
|
||||
if (fiber->flags & ZEND_FIBER_FLAG_THREW) {
|
||||
if (fiber->context.status == ZEND_FIBER_STATUS_DEAD) {
|
||||
if (fiber->context.flags & ZEND_FIBER_FLAG_THREW) {
|
||||
message = "The fiber threw an exception";
|
||||
} else if (fiber->flags & ZEND_FIBER_FLAG_BAILOUT) {
|
||||
} else if (fiber->context.flags & ZEND_FIBER_FLAG_BAILOUT) {
|
||||
message = "The fiber exited with a fatal error";
|
||||
} else {
|
||||
RETURN_COPY(&fiber->result);
|
||||
}
|
||||
} else if (fiber->status == ZEND_FIBER_STATUS_INIT) {
|
||||
} else if (fiber->context.status == ZEND_FIBER_STATUS_INIT) {
|
||||
message = "The fiber has not been started";
|
||||
} else {
|
||||
message = "The fiber has not returned";
|
||||
|
@ -74,20 +74,15 @@ typedef struct _zend_fiber_transfer {
|
||||
* and (optional) data before they return. */
|
||||
typedef void (*zend_fiber_coroutine)(zend_fiber_transfer *transfer);
|
||||
|
||||
/* Defined as a macro to allow anonymous embedding. */
|
||||
#define ZEND_FIBER_CONTEXT_FIELDS \
|
||||
/* Handle to fiber state as needed by boost.context */ \
|
||||
void *handle; \
|
||||
/* Pointer that identifies the fiber type. */ \
|
||||
void *kind; \
|
||||
zend_fiber_coroutine function; \
|
||||
zend_fiber_stack *stack; \
|
||||
zend_fiber_status status; \
|
||||
uint8_t flags
|
||||
|
||||
/* Standalone context (used primarily as pointer type). */
|
||||
struct _zend_fiber_context {
|
||||
ZEND_FIBER_CONTEXT_FIELDS;
|
||||
/* Handle to fiber state as needed by boost.context */
|
||||
void *handle;
|
||||
/* Pointer that identifies the fiber type. */
|
||||
void *kind;
|
||||
zend_fiber_coroutine function;
|
||||
zend_fiber_stack *stack;
|
||||
zend_fiber_status status;
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
/* Zend VM state that needs to be captured / restored during fiber context switch. */
|
||||
@ -107,8 +102,7 @@ struct _zend_fiber {
|
||||
/* PHP object handle. */
|
||||
zend_object std;
|
||||
|
||||
/* Fiber context fields (embedded to avoid memory allocation). */
|
||||
ZEND_FIBER_CONTEXT_FIELDS;
|
||||
zend_fiber_context context;
|
||||
|
||||
/* Fiber that resumed us. */
|
||||
zend_fiber_context *caller;
|
||||
@ -141,12 +135,12 @@ static zend_always_inline zend_fiber *zend_fiber_from_context(zend_fiber_context
|
||||
{
|
||||
ZEND_ASSERT(context->kind == zend_ce_fiber && "Fiber context does not belong to a Zend fiber");
|
||||
|
||||
return (zend_fiber *)(((char *) context) - XtOffsetOf(zend_fiber, handle));
|
||||
return (zend_fiber *)(((char *) context) - XtOffsetOf(zend_fiber, context));
|
||||
}
|
||||
|
||||
static zend_always_inline zend_fiber_context *zend_fiber_get_context(zend_fiber *fiber)
|
||||
{
|
||||
return (zend_fiber_context *) &fiber->handle;
|
||||
return &fiber->context;
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_fiber_capture_vm_state(zend_fiber_vm_state *state)
|
||||
|
@ -6873,7 +6873,7 @@ ZEND_METHOD(ReflectionFiber, getFiber)
|
||||
}
|
||||
|
||||
#define REFLECTION_CHECK_VALID_FIBER(fiber) do { \
|
||||
if (fiber == NULL || fiber->status == ZEND_FIBER_STATUS_INIT || fiber->status == ZEND_FIBER_STATUS_DEAD) { \
|
||||
if (fiber == NULL || fiber->context.status == ZEND_FIBER_STATUS_INIT || fiber->context.status == ZEND_FIBER_STATUS_DEAD) { \
|
||||
zend_throw_error(NULL, "Cannot fetch information from a fiber that has not been started or is terminated"); \
|
||||
RETURN_THROWS(); \
|
||||
} \
|
||||
@ -6948,7 +6948,7 @@ ZEND_METHOD(ReflectionFiber, getCallable)
|
||||
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
|
||||
if (fiber == NULL || fiber->status == ZEND_FIBER_STATUS_DEAD) {
|
||||
if (fiber == NULL || fiber->context.status == ZEND_FIBER_STATUS_DEAD) {
|
||||
zend_throw_error(NULL, "Cannot fetch the callable from a fiber that has terminated"); \
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
@ -23,11 +23,6 @@
|
||||
static zend_class_entry *zend_test_fiber_class;
|
||||
static zend_object_handlers zend_test_fiber_handlers;
|
||||
|
||||
static zend_always_inline zend_fiber_context *zend_test_fiber_get_context(zend_test_fiber *fiber)
|
||||
{
|
||||
return (zend_fiber_context *) &fiber->handle;
|
||||
}
|
||||
|
||||
static zend_fiber_transfer zend_test_fiber_switch_to(zend_fiber_context *context, zval *value, bool exception)
|
||||
{
|
||||
zend_fiber_transfer transfer = {
|
||||
@ -102,10 +97,10 @@ static ZEND_STACK_ALIGNED void zend_test_fiber_execute(zend_fiber_transfer *tran
|
||||
zval_ptr_dtor(&fiber->fci.function_name);
|
||||
|
||||
if (EG(exception)) {
|
||||
if (!(fiber->flags & ZEND_FIBER_FLAG_DESTROYED)
|
||||
if (!(fiber->context.flags & ZEND_FIBER_FLAG_DESTROYED)
|
||||
|| !(zend_is_graceful_exit(EG(exception)) || zend_is_unwind_exit(EG(exception)))
|
||||
) {
|
||||
fiber->flags |= ZEND_FIBER_FLAG_THREW;
|
||||
fiber->context.flags |= ZEND_FIBER_FLAG_THREW;
|
||||
transfer->flags = ZEND_FIBER_TRANSFER_FLAG_ERROR;
|
||||
|
||||
ZVAL_OBJ_COPY(&transfer->value, EG(exception));
|
||||
@ -117,13 +112,13 @@ static ZEND_STACK_ALIGNED void zend_test_fiber_execute(zend_fiber_transfer *tran
|
||||
ZVAL_COPY(&transfer->value, &fiber->result);
|
||||
}
|
||||
} zend_catch {
|
||||
fiber->flags |= ZEND_FIBER_FLAG_BAILOUT;
|
||||
fiber->context.flags |= ZEND_FIBER_FLAG_BAILOUT;
|
||||
} zend_end_try();
|
||||
|
||||
zend_vm_stack_destroy();
|
||||
|
||||
if (fiber->target) {
|
||||
zend_fiber_context *target = zend_test_fiber_get_context(fiber->target);
|
||||
zend_fiber_context *target = &fiber->target->context;
|
||||
zend_fiber_init_context(target, zend_test_fiber_class, zend_test_fiber_execute, EG(fiber_stack_size));
|
||||
transfer->context = target;
|
||||
|
||||
@ -157,14 +152,14 @@ static void zend_test_fiber_object_destroy(zend_object *object)
|
||||
{
|
||||
zend_test_fiber *fiber = (zend_test_fiber *) object;
|
||||
|
||||
if (fiber->status != ZEND_FIBER_STATUS_SUSPENDED) {
|
||||
if (fiber->context.status != ZEND_FIBER_STATUS_SUSPENDED) {
|
||||
return;
|
||||
}
|
||||
|
||||
zend_object *exception = EG(exception);
|
||||
EG(exception) = NULL;
|
||||
|
||||
fiber->flags |= ZEND_FIBER_FLAG_DESTROYED;
|
||||
fiber->context.flags |= ZEND_FIBER_FLAG_DESTROYED;
|
||||
|
||||
zend_fiber_transfer transfer = zend_test_fiber_resume(fiber, NULL, false);
|
||||
|
||||
@ -191,7 +186,7 @@ static void zend_test_fiber_object_free(zend_object *object)
|
||||
{
|
||||
zend_test_fiber *fiber = (zend_test_fiber *) object;
|
||||
|
||||
if (fiber->status == ZEND_FIBER_STATUS_INIT) {
|
||||
if (fiber->context.status == ZEND_FIBER_STATUS_INIT) {
|
||||
// Fiber was never started, so we need to release the reference to the callback.
|
||||
zval_ptr_dtor(&fiber->fci.function_name);
|
||||
}
|
||||
@ -213,7 +208,7 @@ static zend_always_inline void delegate_transfer_result(
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
if (fiber->status == ZEND_FIBER_STATUS_DEAD) {
|
||||
if (fiber->context.status == ZEND_FIBER_STATUS_DEAD) {
|
||||
zval_ptr_dtor(&transfer->value);
|
||||
RETURN_NULL();
|
||||
}
|
||||
@ -244,7 +239,7 @@ static ZEND_METHOD(_ZendTestFiber, start)
|
||||
Z_PARAM_VARIADIC_WITH_NAMED(params, param_count, named_params);
|
||||
ZEND_PARSE_PARAMETERS_END();
|
||||
|
||||
ZEND_ASSERT(fiber->status == ZEND_FIBER_STATUS_INIT);
|
||||
ZEND_ASSERT(fiber->context.status == ZEND_FIBER_STATUS_INIT);
|
||||
|
||||
if (fiber->previous != NULL) {
|
||||
zend_throw_error(NULL, "Cannot start a fiber that is the target of another fiber");
|
||||
@ -255,11 +250,9 @@ static ZEND_METHOD(_ZendTestFiber, start)
|
||||
fiber->fci.param_count = param_count;
|
||||
fiber->fci.named_params = named_params;
|
||||
|
||||
zend_fiber_context *context = zend_test_fiber_get_context(fiber);
|
||||
zend_fiber_init_context(&fiber->context, zend_test_fiber_class, zend_test_fiber_execute, EG(fiber_stack_size));
|
||||
|
||||
zend_fiber_init_context(context, zend_test_fiber_class, zend_test_fiber_execute, EG(fiber_stack_size));
|
||||
|
||||
fiber->previous = context;
|
||||
fiber->previous = &fiber->context;
|
||||
|
||||
zend_fiber_transfer transfer = zend_test_fiber_resume(fiber, NULL, false);
|
||||
|
||||
@ -281,7 +274,7 @@ static ZEND_METHOD(_ZendTestFiber, suspend)
|
||||
|
||||
zend_fiber_transfer transfer = zend_test_fiber_suspend(fiber, value);
|
||||
|
||||
if (fiber->flags & ZEND_FIBER_FLAG_DESTROYED) {
|
||||
if (fiber->context.flags & ZEND_FIBER_FLAG_DESTROYED) {
|
||||
// This occurs when the test fiber is GC'ed while suspended.
|
||||
zval_ptr_dtor(&transfer.value);
|
||||
zend_throw_graceful_exit();
|
||||
@ -303,7 +296,7 @@ static ZEND_METHOD(_ZendTestFiber, resume)
|
||||
|
||||
fiber = (zend_test_fiber *) Z_OBJ_P(getThis());
|
||||
|
||||
if (UNEXPECTED(fiber->status != ZEND_FIBER_STATUS_SUSPENDED || fiber->caller != NULL)) {
|
||||
if (UNEXPECTED(fiber->context.status != ZEND_FIBER_STATUS_SUSPENDED || fiber->caller != NULL)) {
|
||||
zend_throw_error(NULL, "Cannot resume a fiber that is not suspended");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
@ -329,7 +322,7 @@ static ZEND_METHOD(_ZendTestFiber, pipeTo)
|
||||
target->fci_cache = fci_cache;
|
||||
Z_TRY_ADDREF(target->fci.function_name);
|
||||
|
||||
target->previous = zend_test_fiber_get_context(fiber);
|
||||
target->previous = &fiber->context;
|
||||
|
||||
if (fiber->target) {
|
||||
OBJ_RELEASE(&fiber->target->std);
|
||||
|
@ -23,7 +23,7 @@ typedef struct _zend_test_fiber zend_test_fiber;
|
||||
|
||||
struct _zend_test_fiber {
|
||||
zend_object std;
|
||||
ZEND_FIBER_CONTEXT_FIELDS;
|
||||
zend_fiber_context context;
|
||||
zend_fiber_context *caller;
|
||||
zend_fiber_context *previous;
|
||||
zend_test_fiber *target;
|
||||
|
Loading…
Reference in New Issue
Block a user