mirror of
https://github.com/php/php-src.git
synced 2025-08-16 05:58:45 +02:00
Alternative Fiber Internals Refactoring (#7101)
This commit is contained in:
parent
0dbbf9ec47
commit
a65989b127
14 changed files with 205 additions and 197 deletions
|
@ -380,6 +380,7 @@ void shutdown_executor(void) /* {{{ */
|
|||
zend_objects_store_free_object_storage(&EG(objects_store), fast_shutdown);
|
||||
|
||||
zend_weakrefs_shutdown();
|
||||
zend_fiber_shutdown();
|
||||
|
||||
zend_try {
|
||||
zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_deactivator);
|
||||
|
|
|
@ -78,28 +78,6 @@ extern transfer_t jump_fcontext(fcontext_t to, void *vp);
|
|||
|
||||
#define ZEND_FIBER_DEFAULT_PAGE_SIZE 4096
|
||||
|
||||
#define ZEND_FIBER_BACKUP_EG(stack, stack_page_size, execute_data, error_reporting, trace_num, bailout) do { \
|
||||
stack = EG(vm_stack); \
|
||||
stack->top = EG(vm_stack_top); \
|
||||
stack->end = EG(vm_stack_end); \
|
||||
stack_page_size = EG(vm_stack_page_size); \
|
||||
execute_data = EG(current_execute_data); \
|
||||
error_reporting = EG(error_reporting); \
|
||||
trace_num = EG(jit_trace_num); \
|
||||
bailout = EG(bailout); \
|
||||
} while (0)
|
||||
|
||||
#define ZEND_FIBER_RESTORE_EG(stack, stack_page_size, execute_data, error_reporting, trace_num, bailout) do { \
|
||||
EG(vm_stack) = stack; \
|
||||
EG(vm_stack_top) = stack->top; \
|
||||
EG(vm_stack_end) = stack->end; \
|
||||
EG(vm_stack_page_size) = stack_page_size; \
|
||||
EG(current_execute_data) = execute_data; \
|
||||
EG(error_reporting) = error_reporting; \
|
||||
EG(jit_trace_num) = trace_num; \
|
||||
EG(bailout) = bailout; \
|
||||
} while (0)
|
||||
|
||||
static size_t zend_fiber_get_page_size(void)
|
||||
{
|
||||
static size_t page_size = 0;
|
||||
|
@ -172,6 +150,11 @@ static bool zend_fiber_stack_allocate(zend_fiber_stack *stack, size_t size)
|
|||
stack->valgrind = VALGRIND_STACK_REGISTER(base, base + stack->size);
|
||||
#endif
|
||||
|
||||
#ifdef __SANITIZE_ADDRESS__
|
||||
stack->prior_pointer = stack->pointer;
|
||||
stack->prior_size = stack->size;
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -200,24 +183,19 @@ static void zend_fiber_stack_free(zend_fiber_stack *stack)
|
|||
|
||||
static ZEND_NORETURN void zend_fiber_trampoline(transfer_t transfer)
|
||||
{
|
||||
zend_fiber_context *context = transfer.data;
|
||||
zend_fiber_context *context = EG(current_fiber);
|
||||
zend_fiber_context *from = transfer.data;
|
||||
|
||||
from->handle = transfer.context;
|
||||
|
||||
#ifdef __SANITIZE_ADDRESS__
|
||||
__sanitizer_finish_switch_fiber(NULL, &context->stack.prior_pointer, &context->stack.prior_size);
|
||||
__sanitizer_finish_switch_fiber(NULL, &from->stack.prior_pointer, &from->stack.prior_size);
|
||||
#endif
|
||||
|
||||
context->caller = transfer.context;
|
||||
|
||||
context->function(context);
|
||||
|
||||
context->self = NULL;
|
||||
|
||||
#ifdef __SANITIZE_ADDRESS__
|
||||
__sanitizer_start_switch_fiber(NULL, context->stack.prior_pointer, context->stack.prior_size);
|
||||
#endif
|
||||
|
||||
jump_fcontext(context->caller, NULL);
|
||||
/* Final context switch, the fiber must not be resumed afterwards! */
|
||||
zend_fiber_switch_context(context->function(context));
|
||||
|
||||
/* Abort here because we are in an inconsistent program state. */
|
||||
abort();
|
||||
}
|
||||
|
||||
|
@ -230,10 +208,10 @@ ZEND_API bool zend_fiber_init_context(zend_fiber_context *context, zend_fiber_co
|
|||
// Stack grows down, calculate the top of the stack. make_fcontext then shifts pointer to lower 16-byte boundary.
|
||||
void *stack = (void *) ((uintptr_t) context->stack.pointer + context->stack.size);
|
||||
|
||||
context->self = make_fcontext(stack, context->stack.size, zend_fiber_trampoline);
|
||||
ZEND_ASSERT(context->self != NULL && "make_fcontext() never returns NULL");
|
||||
context->handle = make_fcontext(stack, context->stack.size, zend_fiber_trampoline);
|
||||
ZEND_ASSERT(context->handle != NULL && "make_fcontext() never returns NULL");
|
||||
|
||||
context->function = coroutine;
|
||||
context->caller = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -245,81 +223,59 @@ ZEND_API void zend_fiber_destroy_context(zend_fiber_context *context)
|
|||
|
||||
ZEND_API void zend_fiber_switch_context(zend_fiber_context *to)
|
||||
{
|
||||
ZEND_ASSERT(to && to->self && to->stack.pointer && "Invalid fiber context");
|
||||
zend_fiber_context *from = EG(current_fiber);
|
||||
|
||||
ZEND_ASSERT(to && to->handle && "Invalid fiber context");
|
||||
ZEND_ASSERT(from && "From fiber context must be present");
|
||||
ZEND_ASSERT(to != from && "Cannot switch into the running fiber context");
|
||||
|
||||
#ifdef __SANITIZE_ADDRESS__
|
||||
void *fake_stack;
|
||||
__sanitizer_start_switch_fiber(&fake_stack, to->stack.pointer, to->stack.size);
|
||||
void *fake_stack = NULL;
|
||||
__sanitizer_start_switch_fiber(
|
||||
from->status != ZEND_FIBER_STATUS_DEAD ? &fake_stack : NULL,
|
||||
to->stack.prior_pointer,
|
||||
to->stack.prior_size);
|
||||
#endif
|
||||
|
||||
transfer_t transfer = jump_fcontext(to->self, to);
|
||||
EG(current_fiber) = to;
|
||||
|
||||
transfer_t transfer = jump_fcontext(to->handle, from);
|
||||
((zend_fiber_context *) transfer.data)->handle = transfer.context;
|
||||
|
||||
EG(current_fiber) = from;
|
||||
|
||||
#ifdef __SANITIZE_ADDRESS__
|
||||
__sanitizer_finish_switch_fiber(fake_stack, &to->stack.prior_pointer, &to->stack.prior_size);
|
||||
#endif
|
||||
|
||||
to->self = transfer.context;
|
||||
}
|
||||
|
||||
ZEND_API void zend_fiber_suspend_context(zend_fiber_context *current)
|
||||
{
|
||||
ZEND_ASSERT(current && current->caller && current->stack.pointer && "Invalid fiber context");
|
||||
|
||||
#ifdef __SANITIZE_ADDRESS__
|
||||
void *fake_stack;
|
||||
__sanitizer_start_switch_fiber(&fake_stack, current->stack.prior_pointer, current->stack.prior_size);
|
||||
#endif
|
||||
|
||||
transfer_t transfer = jump_fcontext(current->caller, NULL);
|
||||
|
||||
#ifdef __SANITIZE_ADDRESS__
|
||||
__sanitizer_finish_switch_fiber(fake_stack, ¤t->stack.prior_pointer, ¤t->stack.prior_size);
|
||||
#endif
|
||||
|
||||
current->caller = transfer.context;
|
||||
}
|
||||
|
||||
static void zend_fiber_suspend_from(zend_fiber *fiber)
|
||||
{
|
||||
zend_vm_stack stack;
|
||||
size_t stack_page_size;
|
||||
zend_execute_data *execute_data;
|
||||
int error_reporting;
|
||||
uint32_t jit_trace_num;
|
||||
JMP_BUF *bailout;
|
||||
zend_fiber_vm_state state;
|
||||
|
||||
ZEND_FIBER_BACKUP_EG(stack, stack_page_size, execute_data, error_reporting, jit_trace_num, bailout);
|
||||
ZEND_ASSERT(fiber->caller && "Fiber has no caller");
|
||||
|
||||
zend_fiber_suspend_context(&fiber->context);
|
||||
|
||||
ZEND_FIBER_RESTORE_EG(stack, stack_page_size, execute_data, error_reporting, jit_trace_num, bailout);
|
||||
zend_fiber_capture_vm_state(&state);
|
||||
zend_fiber_switch_context(zend_fiber_get_context(fiber->caller));
|
||||
zend_fiber_restore_vm_state(&state);
|
||||
}
|
||||
|
||||
static void zend_fiber_switch_to(zend_fiber *fiber)
|
||||
{
|
||||
zend_fiber *previous;
|
||||
zend_vm_stack stack;
|
||||
size_t stack_page_size;
|
||||
zend_execute_data *execute_data;
|
||||
int error_reporting;
|
||||
uint32_t jit_trace_num;
|
||||
JMP_BUF *bailout;
|
||||
zend_fiber_context *context = zend_fiber_get_context(fiber);
|
||||
zend_fiber_vm_state state;
|
||||
|
||||
previous = EG(current_fiber);
|
||||
zend_observer_fiber_switch_notify(EG(current_fiber), context);
|
||||
|
||||
zend_observer_fiber_switch_notify(previous, fiber);
|
||||
fiber->caller = zend_fiber_from_context(EG(current_fiber));
|
||||
|
||||
ZEND_FIBER_BACKUP_EG(stack, stack_page_size, execute_data, error_reporting, jit_trace_num, bailout);
|
||||
zend_fiber_capture_vm_state(&state);
|
||||
zend_fiber_switch_context(context);
|
||||
zend_fiber_restore_vm_state(&state);
|
||||
|
||||
EG(current_fiber) = fiber;
|
||||
fiber->caller = NULL;
|
||||
|
||||
zend_fiber_switch_context(&fiber->context);
|
||||
|
||||
EG(current_fiber) = previous;
|
||||
|
||||
ZEND_FIBER_RESTORE_EG(stack, stack_page_size, execute_data, error_reporting, jit_trace_num, bailout);
|
||||
|
||||
zend_observer_fiber_switch_notify(fiber, previous);
|
||||
zend_observer_fiber_switch_notify(context, EG(current_fiber));
|
||||
|
||||
if (UNEXPECTED(fiber->flags & ZEND_FIBER_FLAG_BAILOUT)) {
|
||||
// zend_bailout() was called in the fiber, so call it again in the previous fiber or {main}.
|
||||
|
@ -339,10 +295,9 @@ static zend_always_inline zend_vm_stack zend_fiber_vm_stack_alloc(size_t size)
|
|||
return page;
|
||||
}
|
||||
|
||||
static void ZEND_STACK_ALIGNED zend_fiber_execute(zend_fiber_context *context)
|
||||
static ZEND_STACK_ALIGNED zend_fiber_context *zend_fiber_execute(zend_fiber_context *context)
|
||||
{
|
||||
zend_fiber *fiber = EG(current_fiber);
|
||||
ZEND_ASSERT(fiber);
|
||||
zend_fiber *fiber = zend_fiber_from_context(context);
|
||||
|
||||
zend_long error_reporting = INI_INT("error_reporting");
|
||||
if (!error_reporting && !INI_STR("error_reporting")) {
|
||||
|
@ -396,6 +351,8 @@ static void ZEND_STACK_ALIGNED zend_fiber_execute(zend_fiber_context *context)
|
|||
zend_vm_stack_destroy();
|
||||
fiber->execute_data = NULL;
|
||||
fiber->stack_bottom = NULL;
|
||||
|
||||
return zend_fiber_get_context(fiber->caller);
|
||||
}
|
||||
|
||||
static zend_object *zend_fiber_object_create(zend_class_entry *ce)
|
||||
|
@ -454,7 +411,7 @@ static void zend_fiber_object_free(zend_object *object)
|
|||
|
||||
zval_ptr_dtor(&fiber->value);
|
||||
|
||||
zend_fiber_destroy_context(&fiber->context);
|
||||
zend_fiber_destroy_context(zend_fiber_get_context(fiber));
|
||||
|
||||
zend_object_std_dtor(&fiber->std);
|
||||
}
|
||||
|
@ -494,7 +451,7 @@ ZEND_API void zend_fiber_start(zend_fiber *fiber, zval *params, uint32_t param_c
|
|||
fiber->fci.param_count = param_count;
|
||||
fiber->fci.named_params = named_params;
|
||||
|
||||
if (!zend_fiber_init_context(&fiber->context, zend_fiber_execute, EG(fiber_stack_size))) {
|
||||
if (!zend_fiber_init_context(zend_fiber_get_context(fiber), zend_fiber_execute, EG(fiber_stack_size))) {
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
|
@ -524,13 +481,13 @@ ZEND_METHOD(Fiber, start)
|
|||
|
||||
ZEND_API void zend_fiber_suspend(zval *value, zval *return_value)
|
||||
{
|
||||
zend_fiber *fiber = EG(current_fiber);
|
||||
|
||||
if (UNEXPECTED(!fiber)) {
|
||||
if (UNEXPECTED(EG(current_fiber) == EG(main_fiber))) {
|
||||
zend_throw_error(zend_ce_fiber_error, "Cannot suspend outside of a fiber");
|
||||
RETURN_THROWS();
|
||||
}
|
||||
|
||||
zend_fiber *fiber = zend_fiber_from_context(EG(current_fiber));
|
||||
|
||||
if (UNEXPECTED(fiber->flags & ZEND_FIBER_FLAG_DESTROYED)) {
|
||||
zend_throw_error(zend_ce_fiber_error, "Cannot suspend in a force-closed fiber");
|
||||
RETURN_THROWS();
|
||||
|
@ -734,17 +691,13 @@ ZEND_METHOD(Fiber, getReturn)
|
|||
|
||||
ZEND_METHOD(Fiber, this)
|
||||
{
|
||||
zend_fiber *fiber;
|
||||
|
||||
ZEND_PARSE_PARAMETERS_NONE();
|
||||
|
||||
fiber = EG(current_fiber);
|
||||
|
||||
if (!fiber) {
|
||||
if (EG(current_fiber) == EG(main_fiber)) {
|
||||
RETURN_NULL();
|
||||
}
|
||||
|
||||
RETURN_OBJ_COPY(&fiber->std);
|
||||
RETURN_OBJ_COPY(&zend_fiber_from_context(EG(current_fiber))->std);
|
||||
}
|
||||
|
||||
ZEND_METHOD(FiberError, __construct)
|
||||
|
@ -775,5 +728,15 @@ void zend_register_fiber_ce(void)
|
|||
|
||||
void zend_fiber_init(void)
|
||||
{
|
||||
EG(current_fiber) = NULL;
|
||||
zend_fiber_context *context = ecalloc(1, sizeof(zend_fiber_context));
|
||||
|
||||
context->status = ZEND_FIBER_STATUS_RUNNING;
|
||||
|
||||
EG(main_fiber) = context;
|
||||
EG(current_fiber) = context;
|
||||
}
|
||||
|
||||
void zend_fiber_shutdown(void)
|
||||
{
|
||||
efree(EG(main_fiber));
|
||||
}
|
||||
|
|
|
@ -23,6 +23,11 @@
|
|||
#include "zend_API.h"
|
||||
#include "zend_types.h"
|
||||
|
||||
#define ZEND_FIBER_GUARD_PAGES 1
|
||||
|
||||
#define ZEND_FIBER_DEFAULT_C_STACK_SIZE (4096 * (((sizeof(void *)) < 8) ? 256 : 512))
|
||||
#define ZEND_FIBER_VM_STACK_SIZE (1024 * sizeof(zval))
|
||||
|
||||
BEGIN_EXTERN_C()
|
||||
|
||||
typedef enum {
|
||||
|
@ -40,13 +45,11 @@ typedef enum {
|
|||
|
||||
void zend_register_fiber_ce(void);
|
||||
void zend_fiber_init(void);
|
||||
void zend_fiber_shutdown(void);
|
||||
|
||||
extern ZEND_API zend_class_entry *zend_ce_fiber;
|
||||
|
||||
typedef struct _zend_fiber_context zend_fiber_context;
|
||||
|
||||
typedef void (*zend_fiber_coroutine)(zend_fiber_context *context);
|
||||
|
||||
/* Encapsulates the fiber C stack with extension for debugging tools. */
|
||||
typedef struct _zend_fiber_stack {
|
||||
void *pointer;
|
||||
size_t size;
|
||||
|
@ -61,30 +64,49 @@ typedef struct _zend_fiber_stack {
|
|||
#endif
|
||||
} zend_fiber_stack;
|
||||
|
||||
typedef struct _zend_fiber_context {
|
||||
void *self;
|
||||
void *caller;
|
||||
zend_fiber_coroutine function;
|
||||
zend_fiber_stack stack;
|
||||
} zend_fiber_context;
|
||||
typedef struct _zend_fiber zend_fiber;
|
||||
typedef struct _zend_fiber_context zend_fiber_context;
|
||||
|
||||
typedef struct _zend_fiber {
|
||||
/* Fiber PHP object handle. */
|
||||
/* Coroutine functions must return a fiber context to switch to after they are finished. */
|
||||
typedef zend_fiber_context *(*zend_fiber_coroutine)(zend_fiber_context *context);
|
||||
|
||||
/* Defined as a macro to allow anonymous embedding. */
|
||||
#define ZEND_FIBER_CONTEXT_FIELDS \
|
||||
void *handle; \
|
||||
zend_fiber_coroutine function; \
|
||||
zend_fiber_stack stack; \
|
||||
zend_fiber_status status; \
|
||||
zend_uchar flags
|
||||
|
||||
/* Standalone context (used primarily as pointer type). */
|
||||
struct _zend_fiber_context {
|
||||
ZEND_FIBER_CONTEXT_FIELDS;
|
||||
};
|
||||
|
||||
/* Zend VM state that needs to be captured / restored during fiber context switch. */
|
||||
typedef struct _zend_fiber_vm_state {
|
||||
zend_vm_stack vm_stack;
|
||||
size_t vm_stack_page_size;
|
||||
zend_execute_data *current_execute_data;
|
||||
int error_reporting;
|
||||
uint32_t jit_trace_num;
|
||||
JMP_BUF *bailout;
|
||||
} zend_fiber_vm_state;
|
||||
|
||||
struct _zend_fiber {
|
||||
/* PHP object handle. */
|
||||
zend_object std;
|
||||
|
||||
/* Status of the fiber, one of the zend_fiber_status values. */
|
||||
zend_fiber_status status;
|
||||
/* Fiber that resumed us. */
|
||||
zend_fiber *caller;
|
||||
|
||||
/* Flags of the fiber, bit field of the zend_fiber_flag values. */
|
||||
zend_uchar flags;
|
||||
/* Fiber context fields (embedded to avoid memory allocation). */
|
||||
ZEND_FIBER_CONTEXT_FIELDS;
|
||||
|
||||
/* Callback and info / cache to be used when fiber is started. */
|
||||
zend_fcall_info fci;
|
||||
zend_fcall_info_cache fci_cache;
|
||||
|
||||
/* Context of this fiber, will be initialized during call to Fiber::start(). */
|
||||
zend_fiber_context context;
|
||||
|
||||
/* Current Zend VM execute data being run by the fiber. */
|
||||
zend_execute_data *execute_data;
|
||||
|
||||
|
@ -96,7 +118,7 @@ typedef struct _zend_fiber {
|
|||
|
||||
/* Storage for temporaries and fiber return value. */
|
||||
zval value;
|
||||
} zend_fiber;
|
||||
};
|
||||
|
||||
/* These functions create and manipulate a Fiber object, allowing any internal function to start, resume, or suspend a fiber. */
|
||||
ZEND_API zend_fiber *zend_fiber_create(const zend_fcall_info *fci, const zend_fcall_info_cache *fci_cache);
|
||||
|
@ -109,14 +131,41 @@ ZEND_API void zend_fiber_throw(zend_fiber *fiber, zval *exception, zval *return_
|
|||
ZEND_API zend_bool zend_fiber_init_context(zend_fiber_context *context, zend_fiber_coroutine coroutine, size_t stack_size);
|
||||
ZEND_API void zend_fiber_destroy_context(zend_fiber_context *context);
|
||||
ZEND_API void zend_fiber_switch_context(zend_fiber_context *to);
|
||||
ZEND_API void zend_fiber_suspend_context(zend_fiber_context *current);
|
||||
|
||||
#define ZEND_FIBER_GUARD_PAGES 1
|
||||
|
||||
#define ZEND_FIBER_DEFAULT_C_STACK_SIZE (4096 * (((sizeof(void *)) < 8) ? 256 : 512))
|
||||
|
||||
#define ZEND_FIBER_VM_STACK_SIZE (1024 * sizeof(zval))
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
static zend_always_inline zend_fiber *zend_fiber_from_context(zend_fiber_context *context)
|
||||
{
|
||||
return (zend_fiber *)(((char *) context) - XtOffsetOf(zend_fiber, handle));
|
||||
}
|
||||
|
||||
static zend_always_inline zend_fiber_context *zend_fiber_get_context(zend_fiber *fiber)
|
||||
{
|
||||
return (zend_fiber_context *) &fiber->handle;
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_fiber_capture_vm_state(zend_fiber_vm_state *state)
|
||||
{
|
||||
state->vm_stack = EG(vm_stack);
|
||||
state->vm_stack->top = EG(vm_stack_top);
|
||||
state->vm_stack->end = EG(vm_stack_end);
|
||||
state->vm_stack_page_size = EG(vm_stack_page_size);
|
||||
state->current_execute_data = EG(current_execute_data);
|
||||
state->error_reporting = EG(error_reporting);
|
||||
state->jit_trace_num = EG(jit_trace_num);
|
||||
state->bailout = EG(bailout);
|
||||
}
|
||||
|
||||
static zend_always_inline void zend_fiber_restore_vm_state(zend_fiber_vm_state *state)
|
||||
{
|
||||
EG(vm_stack) = state->vm_stack;
|
||||
EG(vm_stack_top) = state->vm_stack->top;
|
||||
EG(vm_stack_end) = state->vm_stack->end;
|
||||
EG(vm_stack_page_size) = state->vm_stack_page_size;
|
||||
EG(current_execute_data) = state->current_execute_data;
|
||||
EG(error_reporting) = state->error_reporting;
|
||||
EG(jit_trace_num) = state->jit_trace_num;
|
||||
EG(bailout) = state->bailout;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -61,8 +61,7 @@ END_EXTERN_C()
|
|||
|
||||
typedef struct _zend_vm_stack *zend_vm_stack;
|
||||
typedef struct _zend_ini_entry zend_ini_entry;
|
||||
typedef struct _zend_fiber zend_fiber;
|
||||
|
||||
typedef struct _zend_fiber_context zend_fiber_context;
|
||||
|
||||
struct _zend_compiler_globals {
|
||||
zend_stack loop_var_stack;
|
||||
|
@ -250,8 +249,8 @@ struct _zend_executor_globals {
|
|||
|
||||
zend_get_gc_buffer get_gc_buffer;
|
||||
|
||||
/* Active fiber, NULL when in main thread. */
|
||||
zend_fiber *current_fiber;
|
||||
zend_fiber_context *main_fiber;
|
||||
zend_fiber_context *current_fiber;
|
||||
|
||||
/* Default fiber C stack size. */
|
||||
zend_long fiber_stack_size;
|
||||
|
|
|
@ -264,7 +264,7 @@ ZEND_API void zend_observer_fiber_switch_register(zend_observer_fiber_switch_han
|
|||
zend_llist_add_element(&zend_observer_fiber_switch, &handler);
|
||||
}
|
||||
|
||||
void zend_observer_fiber_switch_notify(zend_fiber *from, zend_fiber *to)
|
||||
ZEND_API void ZEND_FASTCALL zend_observer_fiber_switch_notify(zend_fiber_context *from, zend_fiber_context *to)
|
||||
{
|
||||
zend_llist_element *element;
|
||||
zend_observer_fiber_switch_handler callback;
|
||||
|
|
|
@ -78,10 +78,10 @@ typedef void (*zend_observer_error_cb)(int type, zend_string *error_filename, ui
|
|||
ZEND_API void zend_observer_error_register(zend_observer_error_cb callback);
|
||||
void zend_observer_error_notify(int type, zend_string *error_filename, uint32_t error_lineno, zend_string *message);
|
||||
|
||||
typedef void (*zend_observer_fiber_switch_handler)(zend_fiber *from, zend_fiber *to);
|
||||
typedef void (*zend_observer_fiber_switch_handler)(zend_fiber_context *from, zend_fiber_context *to);
|
||||
|
||||
ZEND_API void zend_observer_fiber_switch_register(zend_observer_fiber_switch_handler handler);
|
||||
void zend_observer_fiber_switch_notify(zend_fiber *from, zend_fiber *to);
|
||||
ZEND_API void ZEND_FASTCALL zend_observer_fiber_switch_notify(zend_fiber_context *from, zend_fiber_context *to);
|
||||
|
||||
END_EXTERN_C()
|
||||
|
||||
|
|
|
@ -6895,7 +6895,7 @@ ZEND_METHOD(ReflectionFiber, getTrace)
|
|||
prev_execute_data = fiber->stack_bottom->prev_execute_data;
|
||||
fiber->stack_bottom->prev_execute_data = NULL;
|
||||
|
||||
if (EG(current_fiber) != fiber) {
|
||||
if (EG(current_fiber) != zend_fiber_get_context(fiber)) {
|
||||
// No need to replace current execute data if within the current fiber.
|
||||
EG(current_execute_data) = fiber->execute_data;
|
||||
}
|
||||
|
@ -6915,7 +6915,7 @@ ZEND_METHOD(ReflectionFiber, getExecutingLine)
|
|||
|
||||
REFLECTION_CHECK_VALID_FIBER(fiber);
|
||||
|
||||
if (EG(current_fiber) == fiber) {
|
||||
if (EG(current_fiber) == zend_fiber_get_context(fiber)) {
|
||||
prev_execute_data = execute_data->prev_execute_data;
|
||||
} else {
|
||||
prev_execute_data = fiber->execute_data->prev_execute_data;
|
||||
|
@ -6933,7 +6933,7 @@ ZEND_METHOD(ReflectionFiber, getExecutingFile)
|
|||
|
||||
REFLECTION_CHECK_VALID_FIBER(fiber);
|
||||
|
||||
if (EG(current_fiber) == fiber) {
|
||||
if (EG(current_fiber) == zend_fiber_get_context(fiber)) {
|
||||
prev_execute_data = execute_data->prev_execute_data;
|
||||
} else {
|
||||
prev_execute_data = fiber->execute_data->prev_execute_data;
|
||||
|
|
|
@ -411,20 +411,19 @@ static void observer_set_user_opcode_handler(const char *opcode_names, user_opco
|
|||
}
|
||||
}
|
||||
|
||||
static void fiber_address_observer(zend_fiber *from, zend_fiber *to)
|
||||
static void fiber_address_observer(zend_fiber_context *from, zend_fiber_context *to)
|
||||
{
|
||||
if (ZT_G(observer_fiber_switch)) {
|
||||
php_printf("<!-- switching from fiber %p to %p -->\n", from, to);
|
||||
}
|
||||
}
|
||||
|
||||
static void fiber_enter_observer(zend_fiber *from, zend_fiber *to)
|
||||
static void fiber_enter_observer(zend_fiber_context *from, zend_fiber_context *to)
|
||||
{
|
||||
if (ZT_G(observer_fiber_switch)) {
|
||||
if (to) {
|
||||
if (to->status == ZEND_FIBER_STATUS_INIT) {
|
||||
php_printf("<init '%p'>\n", to);
|
||||
} else if (to->status == ZEND_FIBER_STATUS_RUNNING && (!from || from->status == ZEND_FIBER_STATUS_RUNNING)) {
|
||||
} else if (to->status == ZEND_FIBER_STATUS_RUNNING && from->status == ZEND_FIBER_STATUS_RUNNING) {
|
||||
if (to->flags & ZEND_FIBER_FLAG_DESTROYED) {
|
||||
php_printf("<destroying '%p'>\n", to);
|
||||
} else if (to->status != ZEND_FIBER_STATUS_DEAD) {
|
||||
|
@ -433,12 +432,10 @@ static void fiber_enter_observer(zend_fiber *from, zend_fiber *to)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void fiber_suspend_observer(zend_fiber *from, zend_fiber *to)
|
||||
static void fiber_suspend_observer(zend_fiber_context *from, zend_fiber_context *to)
|
||||
{
|
||||
if (ZT_G(observer_fiber_switch)) {
|
||||
if (from) {
|
||||
if (from->status == ZEND_FIBER_STATUS_SUSPENDED) {
|
||||
php_printf("<suspend '%p'>\n", from);
|
||||
} else if (from->status == ZEND_FIBER_STATUS_DEAD) {
|
||||
|
@ -452,7 +449,6 @@ static void fiber_suspend_observer(zend_fiber *from, zend_fiber *to)
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PHP_MINIT_FUNCTION(zend_test)
|
||||
{
|
||||
|
|
|
@ -18,12 +18,12 @@ $fiber->resume();
|
|||
?>
|
||||
--EXPECTF--
|
||||
<!-- init '%sobserver_fiber_01.php' -->
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<init '%s'>
|
||||
<!-- init {closure}() -->
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<suspend '%s'>
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<resume '%s'>
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<returned '%s'>
|
||||
|
|
|
@ -17,12 +17,12 @@ $fiber->start();
|
|||
?>
|
||||
--EXPECTF--
|
||||
<!-- init '%sobserver_fiber_02.php' -->
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<init '%s'>
|
||||
<!-- init {closure}() -->
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<suspend '%s'>
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<destroying '%s'>
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<destroyed '%s'>
|
||||
|
|
|
@ -40,12 +40,12 @@ $fiber->resume();
|
|||
?>
|
||||
--EXPECTF--
|
||||
<!-- init '%sobserver_fiber_03.php' -->
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<init '%s'>
|
||||
<!-- init {closure}() -->
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<suspend '%s'>
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<resume '%s'>
|
||||
int(1)
|
||||
<!-- switching from fiber %s to %s -->
|
||||
|
@ -53,9 +53,9 @@ int(1)
|
|||
<!-- init {closure}() -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<suspend '%s'>
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<suspend '%s'>
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<resume '%s'>
|
||||
int(2)
|
||||
<!-- switching from fiber %s to %s -->
|
||||
|
@ -63,9 +63,9 @@ int(2)
|
|||
int(3)
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<suspend '%s'>
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<suspend '%s'>
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<resume '%s'>
|
||||
int(4)
|
||||
<!-- switching from fiber %s to %s -->
|
||||
|
@ -73,5 +73,5 @@ int(4)
|
|||
int(5)
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<returned '%s'>
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<returned '%s'>
|
||||
|
|
|
@ -27,25 +27,25 @@ $fiber->resume();
|
|||
?>
|
||||
--EXPECTF--
|
||||
<!-- init '%sobserver_fiber_04.php' -->
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<init '%s'>
|
||||
<!-- init {closure}() -->
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<suspend '%s'>
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<resume '%s'>
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<init '%s'>
|
||||
<!-- init {closure}() -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<suspend '%s'>
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<suspend '%s'>
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<resume '%s'>
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<destroying '%s'>
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<destroyed '%s'>
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<returned '%s'>
|
||||
|
|
|
@ -26,25 +26,25 @@ $fiber->resume();
|
|||
?>
|
||||
--EXPECTF--
|
||||
<!-- init '%sobserver_fiber_05.php' -->
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<init '%s'>
|
||||
<!-- init {closure}() -->
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<suspend '%s'>
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<resume '%s'>
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<init '%s'>
|
||||
<!-- init {closure}() -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<suspend '%s'>
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<suspend '%s'>
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<destroying '%s'>
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<destroying '%s'>
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<destroyed '%s'>
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<destroyed '%s'>
|
||||
|
|
|
@ -23,12 +23,12 @@ try {
|
|||
?>
|
||||
--EXPECTF--
|
||||
<!-- init '%sobserver_fiber_06.php' -->
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<init '%s'>
|
||||
<!-- init {closure}() -->
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<suspend '%s'>
|
||||
<!-- switching from fiber 0 to %s -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<resume '%s'>
|
||||
<!-- switching from fiber %s to 0 -->
|
||||
<!-- switching from fiber %s to %s -->
|
||||
<threw '%s'>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue