mirror of
https://github.com/php/php-src.git
synced 2025-08-15 21:48:51 +02:00
Include internal functions in the observer API
There are two main motivations to this: a) The logic for handling internal and userland observation can be unified. b) Unwinding of observed functions on a bailout does notably not include observers. Even if users of observers were to ensure such handling themselves, it would be impossible to retain the relative ordering - either the user has to unwind all internal observed frames before the automatic unwinding (zend_observer_fcall_end_all) or afterwards, but not properly interleaved. Signed-off-by: Bob Weinand <bobwei9@hotmail.com>
This commit is contained in:
parent
0c225a2f57
commit
625f164963
49 changed files with 1675 additions and 1257 deletions
|
@ -51,6 +51,7 @@ PHP 8.2 INTERNALS UPGRADE NOTES
|
||||||
are deprecated (see main UPGRADING notes). To suppress the notice, e.g. to
|
are deprecated (see main UPGRADING notes). To suppress the notice, e.g. to
|
||||||
avoid duplicates when processing the same value multiple times, pass or add
|
avoid duplicates when processing the same value multiple times, pass or add
|
||||||
IS_CALLABLE_SUPPRESS_DEPRECATIONS to the check_flags parameter.
|
IS_CALLABLE_SUPPRESS_DEPRECATIONS to the check_flags parameter.
|
||||||
|
* Registered zend_observer_fcall_init handlers are now also called for internal functions.
|
||||||
|
|
||||||
========================
|
========================
|
||||||
2. Build system changes
|
2. Build system changes
|
||||||
|
|
|
@ -1226,6 +1226,7 @@ ZEND_API void zend_activate(void) /* {{{ */
|
||||||
if (CG(map_ptr_last)) {
|
if (CG(map_ptr_last)) {
|
||||||
memset(CG(map_ptr_real_base), 0, CG(map_ptr_last) * sizeof(void*));
|
memset(CG(map_ptr_real_base), 0, CG(map_ptr_last) * sizeof(void*));
|
||||||
}
|
}
|
||||||
|
zend_init_internal_run_time_cache();
|
||||||
zend_observer_activate();
|
zend_observer_activate();
|
||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
|
@ -2694,6 +2694,11 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
|
||||||
internal_function->scope = scope;
|
internal_function->scope = scope;
|
||||||
internal_function->prototype = NULL;
|
internal_function->prototype = NULL;
|
||||||
internal_function->attributes = NULL;
|
internal_function->attributes = NULL;
|
||||||
|
if (EG(active)) { // at run-time: this ought to only happen if registered with dl() or somehow temporarily at runtime
|
||||||
|
ZEND_MAP_PTR_INIT(internal_function->run_time_cache, zend_arena_alloc(&CG(arena), zend_internal_run_time_cache_reserved_size()));
|
||||||
|
} else {
|
||||||
|
ZEND_MAP_PTR_NEW(internal_function->run_time_cache);
|
||||||
|
}
|
||||||
if (ptr->flags) {
|
if (ptr->flags) {
|
||||||
if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
|
if (!(ptr->flags & ZEND_ACC_PPP_MASK)) {
|
||||||
if (ptr->flags != ZEND_ACC_DEPRECATED && scope) {
|
if (ptr->flags != ZEND_ACC_DEPRECATED && scope) {
|
||||||
|
|
|
@ -33,6 +33,7 @@
|
||||||
#include "zend_inheritance.h"
|
#include "zend_inheritance.h"
|
||||||
#include "zend_vm.h"
|
#include "zend_vm.h"
|
||||||
#include "zend_enum.h"
|
#include "zend_enum.h"
|
||||||
|
#include "zend_observer.h"
|
||||||
|
|
||||||
#define SET_NODE(target, src) do { \
|
#define SET_NODE(target, src) do { \
|
||||||
target ## _type = (src)->op_type; \
|
target ## _type = (src)->op_type; \
|
||||||
|
|
|
@ -448,6 +448,7 @@ struct _zend_op_array {
|
||||||
uint32_t required_num_args;
|
uint32_t required_num_args;
|
||||||
zend_arg_info *arg_info;
|
zend_arg_info *arg_info;
|
||||||
HashTable *attributes;
|
HashTable *attributes;
|
||||||
|
ZEND_MAP_PTR_DEF(void **, run_time_cache);
|
||||||
/* END of common elements */
|
/* END of common elements */
|
||||||
|
|
||||||
int cache_size; /* number of run_time_cache_slots * sizeof(void*) */
|
int cache_size; /* number of run_time_cache_slots * sizeof(void*) */
|
||||||
|
@ -456,7 +457,6 @@ struct _zend_op_array {
|
||||||
uint32_t last; /* number of opcodes */
|
uint32_t last; /* number of opcodes */
|
||||||
|
|
||||||
zend_op *opcodes;
|
zend_op *opcodes;
|
||||||
ZEND_MAP_PTR_DEF(void **, run_time_cache);
|
|
||||||
ZEND_MAP_PTR_DEF(HashTable *, static_variables_ptr);
|
ZEND_MAP_PTR_DEF(HashTable *, static_variables_ptr);
|
||||||
HashTable *static_variables;
|
HashTable *static_variables;
|
||||||
zend_string **vars; /* names of CV variables */
|
zend_string **vars; /* names of CV variables */
|
||||||
|
@ -503,6 +503,7 @@ typedef struct _zend_internal_function {
|
||||||
uint32_t required_num_args;
|
uint32_t required_num_args;
|
||||||
zend_internal_arg_info *arg_info;
|
zend_internal_arg_info *arg_info;
|
||||||
HashTable *attributes;
|
HashTable *attributes;
|
||||||
|
ZEND_MAP_PTR_DEF(void **, run_time_cache);
|
||||||
/* END of common elements */
|
/* END of common elements */
|
||||||
|
|
||||||
zif_handler handler;
|
zif_handler handler;
|
||||||
|
@ -527,6 +528,7 @@ union _zend_function {
|
||||||
uint32_t required_num_args;
|
uint32_t required_num_args;
|
||||||
zend_arg_info *arg_info; /* index -1 represents the return value info, if any */
|
zend_arg_info *arg_info; /* index -1 represents the return value info, if any */
|
||||||
HashTable *attributes;
|
HashTable *attributes;
|
||||||
|
ZEND_MAP_PTR_DEF(void **, run_time_cache);
|
||||||
} common;
|
} common;
|
||||||
|
|
||||||
zend_op_array op_array;
|
zend_op_array op_array;
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
#include "zend_enum_arginfo.h"
|
#include "zend_enum_arginfo.h"
|
||||||
#include "zend_interfaces.h"
|
#include "zend_interfaces.h"
|
||||||
#include "zend_enum.h"
|
#include "zend_enum.h"
|
||||||
|
#include "zend_extensions.h"
|
||||||
|
|
||||||
#define ZEND_ENUM_DISALLOW_MAGIC_METHOD(propertyName, methodName) \
|
#define ZEND_ENUM_DISALLOW_MAGIC_METHOD(propertyName, methodName) \
|
||||||
do { \
|
do { \
|
||||||
|
@ -401,59 +402,48 @@ static ZEND_NAMED_FUNCTION(zend_enum_try_from_func)
|
||||||
zend_enum_from_base(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
|
zend_enum_from_base(INTERNAL_FUNCTION_PARAM_PASSTHRU, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void zend_enum_register_func(zend_class_entry *ce, zend_known_string_id name_id, zend_internal_function *zif) {
|
||||||
|
zend_string *name = ZSTR_KNOWN(name_id);
|
||||||
|
zif->type = ZEND_INTERNAL_FUNCTION;
|
||||||
|
zif->module = EG(current_module);
|
||||||
|
zif->scope = ce;
|
||||||
|
ZEND_MAP_PTR_NEW(zif->run_time_cache);
|
||||||
|
ZEND_MAP_PTR_SET(zif->run_time_cache, zend_arena_alloc(&CG(arena), zend_internal_run_time_cache_reserved_size()));
|
||||||
|
|
||||||
|
if (!zend_hash_add_ptr(&ce->function_table, name, zif)) {
|
||||||
|
zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::%s()", ZSTR_VAL(ce->name), ZSTR_VAL(name));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void zend_enum_register_funcs(zend_class_entry *ce)
|
void zend_enum_register_funcs(zend_class_entry *ce)
|
||||||
{
|
{
|
||||||
const uint32_t fn_flags =
|
const uint32_t fn_flags =
|
||||||
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_ARENA_ALLOCATED;
|
ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_HAS_RETURN_TYPE|ZEND_ACC_ARENA_ALLOCATED;
|
||||||
zend_internal_function *cases_function =
|
zend_internal_function *cases_function = zend_arena_calloc(&CG(arena), sizeof(zend_internal_function), 1);
|
||||||
zend_arena_alloc(&CG(arena), sizeof(zend_internal_function));
|
|
||||||
memset(cases_function, 0, sizeof(zend_internal_function));
|
|
||||||
cases_function->type = ZEND_INTERNAL_FUNCTION;
|
|
||||||
cases_function->module = EG(current_module);
|
|
||||||
cases_function->handler = zend_enum_cases_func;
|
cases_function->handler = zend_enum_cases_func;
|
||||||
cases_function->function_name = ZSTR_KNOWN(ZEND_STR_CASES);
|
cases_function->function_name = ZSTR_KNOWN(ZEND_STR_CASES);
|
||||||
cases_function->scope = ce;
|
|
||||||
cases_function->fn_flags = fn_flags;
|
cases_function->fn_flags = fn_flags;
|
||||||
cases_function->arg_info = (zend_internal_arg_info *) (arginfo_class_UnitEnum_cases + 1);
|
cases_function->arg_info = (zend_internal_arg_info *) (arginfo_class_UnitEnum_cases + 1);
|
||||||
if (!zend_hash_add_ptr(&ce->function_table, ZSTR_KNOWN(ZEND_STR_CASES), cases_function)) {
|
zend_enum_register_func(ce, ZEND_STR_CASES, cases_function);
|
||||||
zend_error_noreturn(E_COMPILE_ERROR, "Cannot redeclare %s::cases()", ZSTR_VAL(ce->name));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ce->enum_backing_type != IS_UNDEF) {
|
if (ce->enum_backing_type != IS_UNDEF) {
|
||||||
zend_internal_function *from_function =
|
zend_internal_function *from_function = zend_arena_calloc(&CG(arena), sizeof(zend_internal_function), 1);
|
||||||
zend_arena_alloc(&CG(arena), sizeof(zend_internal_function));
|
|
||||||
memset(from_function, 0, sizeof(zend_internal_function));
|
|
||||||
from_function->type = ZEND_INTERNAL_FUNCTION;
|
|
||||||
from_function->module = EG(current_module);
|
|
||||||
from_function->handler = zend_enum_from_func;
|
from_function->handler = zend_enum_from_func;
|
||||||
from_function->function_name = ZSTR_KNOWN(ZEND_STR_FROM);
|
from_function->function_name = ZSTR_KNOWN(ZEND_STR_FROM);
|
||||||
from_function->scope = ce;
|
|
||||||
from_function->fn_flags = fn_flags;
|
from_function->fn_flags = fn_flags;
|
||||||
from_function->num_args = 1;
|
from_function->num_args = 1;
|
||||||
from_function->required_num_args = 1;
|
from_function->required_num_args = 1;
|
||||||
from_function->arg_info = (zend_internal_arg_info *) (arginfo_class_BackedEnum_from + 1);
|
from_function->arg_info = (zend_internal_arg_info *) (arginfo_class_BackedEnum_from + 1);
|
||||||
if (!zend_hash_add_ptr(&ce->function_table, ZSTR_KNOWN(ZEND_STR_FROM), from_function)) {
|
zend_enum_register_func(ce, ZEND_STR_FROM, from_function);
|
||||||
zend_error_noreturn(E_COMPILE_ERROR,
|
|
||||||
"Cannot redeclare %s::from()", ZSTR_VAL(ce->name));
|
|
||||||
}
|
|
||||||
|
|
||||||
zend_internal_function *try_from_function =
|
zend_internal_function *try_from_function = zend_arena_calloc(&CG(arena), sizeof(zend_internal_function), 1);
|
||||||
zend_arena_alloc(&CG(arena), sizeof(zend_internal_function));
|
|
||||||
memset(try_from_function, 0, sizeof(zend_internal_function));
|
|
||||||
try_from_function->type = ZEND_INTERNAL_FUNCTION;
|
|
||||||
try_from_function->module = EG(current_module);
|
|
||||||
try_from_function->handler = zend_enum_try_from_func;
|
try_from_function->handler = zend_enum_try_from_func;
|
||||||
try_from_function->function_name = ZSTR_KNOWN(ZEND_STR_TRYFROM);
|
try_from_function->function_name = ZSTR_KNOWN(ZEND_STR_TRYFROM);
|
||||||
try_from_function->scope = ce;
|
|
||||||
try_from_function->fn_flags = fn_flags;
|
try_from_function->fn_flags = fn_flags;
|
||||||
try_from_function->num_args = 1;
|
try_from_function->num_args = 1;
|
||||||
try_from_function->required_num_args = 1;
|
try_from_function->required_num_args = 1;
|
||||||
try_from_function->arg_info = (zend_internal_arg_info *) (arginfo_class_BackedEnum_tryFrom + 1);
|
try_from_function->arg_info = (zend_internal_arg_info *) (arginfo_class_BackedEnum_tryFrom + 1);
|
||||||
if (!zend_hash_add_ptr(
|
zend_enum_register_func(ce, ZEND_STR_TRYFROM_LOWERCASE, try_from_function);
|
||||||
&ce->function_table, ZSTR_KNOWN(ZEND_STR_TRYFROM_LOWERCASE), try_from_function)) {
|
|
||||||
zend_error_noreturn(E_COMPILE_ERROR,
|
|
||||||
"Cannot redeclare %s::tryFrom()", ZSTR_VAL(ce->name));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -144,6 +144,7 @@ ZEND_API const zend_internal_function zend_pass_function = {
|
||||||
0, /* required_num_args */
|
0, /* required_num_args */
|
||||||
(zend_internal_arg_info *) zend_pass_function_arg_info + 1, /* arg_info */
|
(zend_internal_arg_info *) zend_pass_function_arg_info + 1, /* arg_info */
|
||||||
NULL, /* attributes */
|
NULL, /* attributes */
|
||||||
|
NULL, /* run_time_cache */
|
||||||
ZEND_FN(pass), /* handler */
|
ZEND_FN(pass), /* handler */
|
||||||
NULL, /* module */
|
NULL, /* module */
|
||||||
{NULL,NULL,NULL,NULL} /* reserved */
|
{NULL,NULL,NULL,NULL} /* reserved */
|
||||||
|
|
|
@ -935,6 +935,7 @@ cleanup_args:
|
||||||
#if ZEND_DEBUG
|
#if ZEND_DEBUG
|
||||||
bool should_throw = zend_internal_call_should_throw(func, call);
|
bool should_throw = zend_internal_call_should_throw(func, call);
|
||||||
#endif
|
#endif
|
||||||
|
ZEND_OBSERVER_FCALL_BEGIN(call);
|
||||||
if (EXPECTED(zend_execute_internal == NULL)) {
|
if (EXPECTED(zend_execute_internal == NULL)) {
|
||||||
/* saves one function call if zend_execute_internal is not used */
|
/* saves one function call if zend_execute_internal is not used */
|
||||||
func->internal_function.handler(call, fci->retval);
|
func->internal_function.handler(call, fci->retval);
|
||||||
|
@ -953,6 +954,7 @@ cleanup_args:
|
||||||
? Z_ISREF_P(fci->retval) : !Z_ISREF_P(fci->retval));
|
? Z_ISREF_P(fci->retval) : !Z_ISREF_P(fci->retval));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
ZEND_OBSERVER_FCALL_END(call, fci->retval);
|
||||||
EG(current_execute_data) = call->prev_execute_data;
|
EG(current_execute_data) = call->prev_execute_data;
|
||||||
zend_vm_stack_free_args(call);
|
zend_vm_stack_free_args(call);
|
||||||
if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
|
if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_HAS_EXTRA_NAMED_PARAMS)) {
|
||||||
|
|
|
@ -280,6 +280,40 @@ ZEND_API int zend_get_op_array_extension_handles(const char *module_name, int ha
|
||||||
return handle;
|
return handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ZEND_API size_t zend_internal_run_time_cache_reserved_size() {
|
||||||
|
return zend_op_array_extension_handles * sizeof(void *);
|
||||||
|
}
|
||||||
|
|
||||||
|
ZEND_API void zend_init_internal_run_time_cache() {
|
||||||
|
size_t rt_size = zend_internal_run_time_cache_reserved_size();
|
||||||
|
if (rt_size) {
|
||||||
|
size_t functions = zend_hash_num_elements(CG(function_table));
|
||||||
|
zend_class_entry *ce;
|
||||||
|
ZEND_HASH_MAP_FOREACH_PTR(CG(class_table), ce) {
|
||||||
|
functions += zend_hash_num_elements(&ce->function_table);
|
||||||
|
} ZEND_HASH_FOREACH_END();
|
||||||
|
|
||||||
|
char *ptr = zend_arena_calloc(&CG(arena), functions, rt_size);
|
||||||
|
zend_internal_function *zif;
|
||||||
|
ZEND_HASH_MAP_FOREACH_PTR(CG(function_table), zif) {
|
||||||
|
if (!ZEND_USER_CODE(zif->type) && ZEND_MAP_PTR_GET(zif->run_time_cache) == NULL)
|
||||||
|
{
|
||||||
|
ZEND_MAP_PTR_SET(zif->run_time_cache, (void *)ptr);
|
||||||
|
ptr += rt_size;
|
||||||
|
}
|
||||||
|
} ZEND_HASH_FOREACH_END();
|
||||||
|
ZEND_HASH_MAP_FOREACH_PTR(CG(class_table), ce) {
|
||||||
|
ZEND_HASH_MAP_FOREACH_PTR(&ce->function_table, zif) {
|
||||||
|
if (!ZEND_USER_CODE(zif->type) && ZEND_MAP_PTR_GET(zif->run_time_cache) == NULL)
|
||||||
|
{
|
||||||
|
ZEND_MAP_PTR_SET(zif->run_time_cache, (void *)ptr);
|
||||||
|
ptr += rt_size;
|
||||||
|
}
|
||||||
|
} ZEND_HASH_FOREACH_END();
|
||||||
|
} ZEND_HASH_FOREACH_END();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
ZEND_API zend_extension *zend_get_extension(const char *extension_name)
|
ZEND_API zend_extension *zend_get_extension(const char *extension_name)
|
||||||
{
|
{
|
||||||
zend_llist_element *element;
|
zend_llist_element *element;
|
||||||
|
|
|
@ -145,6 +145,9 @@ void zend_startup_extensions_mechanism(void);
|
||||||
void zend_startup_extensions(void);
|
void zend_startup_extensions(void);
|
||||||
void zend_shutdown_extensions(void);
|
void zend_shutdown_extensions(void);
|
||||||
|
|
||||||
|
ZEND_API size_t zend_internal_run_time_cache_reserved_size(void);
|
||||||
|
ZEND_API void zend_init_internal_run_time_cache(void);
|
||||||
|
|
||||||
BEGIN_EXTERN_C()
|
BEGIN_EXTERN_C()
|
||||||
ZEND_API zend_result zend_load_extension(const char *path);
|
ZEND_API zend_result zend_load_extension(const char *path);
|
||||||
ZEND_API zend_result zend_load_extension_handle(DL_HANDLE handle, const char *path);
|
ZEND_API zend_result zend_load_extension_handle(DL_HANDLE handle, const char *path);
|
||||||
|
|
|
@ -23,13 +23,13 @@
|
||||||
#include "zend_llist.h"
|
#include "zend_llist.h"
|
||||||
#include "zend_vm.h"
|
#include "zend_vm.h"
|
||||||
|
|
||||||
#define ZEND_OBSERVER_DATA(op_array) \
|
#define ZEND_OBSERVER_DATA(function) \
|
||||||
ZEND_OP_ARRAY_EXTENSION(op_array, zend_observer_fcall_op_array_extension)
|
ZEND_OP_ARRAY_EXTENSION((&(function)->common), zend_observer_fcall_op_array_extension)
|
||||||
|
|
||||||
#define ZEND_OBSERVER_NOT_OBSERVED ((void *) 2)
|
#define ZEND_OBSERVER_NOT_OBSERVED ((void *) 2)
|
||||||
|
|
||||||
#define ZEND_OBSERVABLE_FN(fn_flags) \
|
#define ZEND_OBSERVABLE_FN(function) \
|
||||||
(!(fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
|
(ZEND_MAP_PTR(function->common.run_time_cache) && !(function->common.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
|
||||||
|
|
||||||
zend_llist zend_observers_fcall_list;
|
zend_llist zend_observers_fcall_list;
|
||||||
zend_llist zend_observer_error_callbacks;
|
zend_llist zend_observer_error_callbacks;
|
||||||
|
@ -100,12 +100,9 @@ static void zend_observer_fcall_install(zend_execute_data *execute_data)
|
||||||
{
|
{
|
||||||
zend_llist *list = &zend_observers_fcall_list;
|
zend_llist *list = &zend_observers_fcall_list;
|
||||||
zend_function *function = execute_data->func;
|
zend_function *function = execute_data->func;
|
||||||
zend_op_array *op_array = &function->op_array;
|
|
||||||
|
|
||||||
ZEND_ASSERT(function->type != ZEND_INTERNAL_FUNCTION);
|
ZEND_ASSERT(RUN_TIME_CACHE(&function->common));
|
||||||
|
zend_observer_fcall_begin_handler *begin_handlers = (zend_observer_fcall_begin_handler *)&ZEND_OBSERVER_DATA(function);
|
||||||
ZEND_ASSERT(RUN_TIME_CACHE(op_array));
|
|
||||||
zend_observer_fcall_begin_handler *begin_handlers = (zend_observer_fcall_begin_handler *)&ZEND_OBSERVER_DATA(op_array);
|
|
||||||
zend_observer_fcall_end_handler *end_handlers = (zend_observer_fcall_end_handler *)begin_handlers + list->count, *end_handlers_start = end_handlers;
|
zend_observer_fcall_end_handler *end_handlers = (zend_observer_fcall_end_handler *)begin_handlers + list->count, *end_handlers_start = end_handlers;
|
||||||
|
|
||||||
*begin_handlers = ZEND_OBSERVER_NOT_OBSERVED;
|
*begin_handlers = ZEND_OBSERVER_NOT_OBSERVED;
|
||||||
|
@ -152,9 +149,9 @@ static bool zend_observer_remove_handler(void **first_handler, void *old_handler
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_API void zend_observer_add_begin_handler(zend_op_array *op_array, zend_observer_fcall_begin_handler begin) {
|
ZEND_API void zend_observer_add_begin_handler(zend_function *function, zend_observer_fcall_begin_handler begin) {
|
||||||
size_t registered_observers = zend_observers_fcall_list.count;
|
size_t registered_observers = zend_observers_fcall_list.count;
|
||||||
zend_observer_fcall_begin_handler *first_handler = (void *)&ZEND_OBSERVER_DATA(op_array), *last_handler = first_handler + registered_observers - 1;
|
zend_observer_fcall_begin_handler *first_handler = (void *)&ZEND_OBSERVER_DATA(function), *last_handler = first_handler + registered_observers - 1;
|
||||||
if (*first_handler == ZEND_OBSERVER_NOT_OBSERVED) {
|
if (*first_handler == ZEND_OBSERVER_NOT_OBSERVED) {
|
||||||
*first_handler = begin;
|
*first_handler = begin;
|
||||||
} else {
|
} else {
|
||||||
|
@ -169,13 +166,13 @@ ZEND_API void zend_observer_add_begin_handler(zend_op_array *op_array, zend_obse
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_API bool zend_observer_remove_begin_handler(zend_op_array *op_array, zend_observer_fcall_begin_handler begin) {
|
ZEND_API bool zend_observer_remove_begin_handler(zend_function *function, zend_observer_fcall_begin_handler begin) {
|
||||||
return zend_observer_remove_handler((void **)&ZEND_OBSERVER_DATA(op_array), begin);
|
return zend_observer_remove_handler((void **)&ZEND_OBSERVER_DATA(function), begin);
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_API void zend_observer_add_end_handler(zend_op_array *op_array, zend_observer_fcall_end_handler end) {
|
ZEND_API void zend_observer_add_end_handler(zend_function *function, zend_observer_fcall_end_handler end) {
|
||||||
size_t registered_observers = zend_observers_fcall_list.count;
|
size_t registered_observers = zend_observers_fcall_list.count;
|
||||||
zend_observer_fcall_end_handler *end_handler = (zend_observer_fcall_end_handler *)&ZEND_OBSERVER_DATA(op_array) + registered_observers;
|
zend_observer_fcall_end_handler *end_handler = (zend_observer_fcall_end_handler *)&ZEND_OBSERVER_DATA(function) + registered_observers;
|
||||||
// to allow to preserve the invariant that end handlers are in reverse order of begin handlers, push the new end handler in front
|
// to allow to preserve the invariant that end handlers are in reverse order of begin handlers, push the new end handler in front
|
||||||
if (*end_handler != ZEND_OBSERVER_NOT_OBSERVED) {
|
if (*end_handler != ZEND_OBSERVER_NOT_OBSERVED) {
|
||||||
// there's no space for new handlers, then it's forbidden to call this function
|
// there's no space for new handlers, then it's forbidden to call this function
|
||||||
|
@ -185,9 +182,9 @@ ZEND_API void zend_observer_add_end_handler(zend_op_array *op_array, zend_observ
|
||||||
*end_handler = end;
|
*end_handler = end;
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_API bool zend_observer_remove_end_handler(zend_op_array *op_array, zend_observer_fcall_end_handler end) {
|
ZEND_API bool zend_observer_remove_end_handler(zend_function *function, zend_observer_fcall_end_handler end) {
|
||||||
size_t registered_observers = zend_observers_fcall_list.count;
|
size_t registered_observers = zend_observers_fcall_list.count;
|
||||||
return zend_observer_remove_handler((void **)&ZEND_OBSERVER_DATA(op_array) + registered_observers, end);
|
return zend_observer_remove_handler((void **)&ZEND_OBSERVER_DATA(function) + registered_observers, end);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ZEND_FASTCALL _zend_observe_fcall_begin(zend_execute_data *execute_data)
|
static void ZEND_FASTCALL _zend_observe_fcall_begin(zend_execute_data *execute_data)
|
||||||
|
@ -196,14 +193,13 @@ static void ZEND_FASTCALL _zend_observe_fcall_begin(zend_execute_data *execute_d
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_op_array *op_array = &execute_data->func->op_array;
|
zend_function *function = execute_data->func;
|
||||||
uint32_t fn_flags = op_array->fn_flags;
|
|
||||||
|
|
||||||
if (!ZEND_OBSERVABLE_FN(fn_flags)) {
|
if (!ZEND_OBSERVABLE_FN(function)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_observer_fcall_begin_handler *handler = (zend_observer_fcall_begin_handler *)&ZEND_OBSERVER_DATA(op_array);
|
zend_observer_fcall_begin_handler *handler = (zend_observer_fcall_begin_handler *)&ZEND_OBSERVER_DATA(function);
|
||||||
if (!*handler) {
|
if (!*handler) {
|
||||||
zend_observer_fcall_install(execute_data);
|
zend_observer_fcall_install(execute_data);
|
||||||
}
|
}
|
||||||
|
@ -243,11 +239,11 @@ ZEND_API void ZEND_FASTCALL zend_observer_fcall_begin(zend_execute_data *execute
|
||||||
static inline bool zend_observer_is_skipped_frame(zend_execute_data *execute_data) {
|
static inline bool zend_observer_is_skipped_frame(zend_execute_data *execute_data) {
|
||||||
zend_function *func = execute_data->func;
|
zend_function *func = execute_data->func;
|
||||||
|
|
||||||
if (!func || func->type == ZEND_INTERNAL_FUNCTION || !ZEND_OBSERVABLE_FN(func->common.fn_flags)) {
|
if (!func || !ZEND_OBSERVABLE_FN(func)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_observer_fcall_end_handler end_handler = (&ZEND_OBSERVER_DATA(&func->op_array))[zend_observers_fcall_list.count];
|
zend_observer_fcall_end_handler end_handler = (&ZEND_OBSERVER_DATA(func))[zend_observers_fcall_list.count];
|
||||||
if (end_handler == NULL || end_handler == ZEND_OBSERVER_NOT_OBSERVED) {
|
if (end_handler == NULL || end_handler == ZEND_OBSERVER_NOT_OBSERVED) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -259,11 +255,11 @@ ZEND_API void ZEND_FASTCALL zend_observer_fcall_end(zend_execute_data *execute_d
|
||||||
{
|
{
|
||||||
zend_function *func = execute_data->func;
|
zend_function *func = execute_data->func;
|
||||||
|
|
||||||
if (!ZEND_OBSERVER_ENABLED || !ZEND_OBSERVABLE_FN(func->common.fn_flags)) {
|
if (!ZEND_OBSERVER_ENABLED || !ZEND_OBSERVABLE_FN(func)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
zend_observer_fcall_end_handler *handler = (zend_observer_fcall_end_handler *)&ZEND_OBSERVER_DATA(&func->op_array) + zend_observers_fcall_list.count;
|
zend_observer_fcall_end_handler *handler = (zend_observer_fcall_end_handler *)&ZEND_OBSERVER_DATA(func) + zend_observers_fcall_list.count;
|
||||||
// TODO: Fix exceptions from generators
|
// TODO: Fix exceptions from generators
|
||||||
// ZEND_ASSERT(fcall_data);
|
// ZEND_ASSERT(fcall_data);
|
||||||
if (!*handler || *handler == ZEND_OBSERVER_NOT_OBSERVED) {
|
if (!*handler || *handler == ZEND_OBSERVER_NOT_OBSERVED) {
|
||||||
|
@ -291,7 +287,7 @@ ZEND_API void zend_observer_fcall_end_all(void)
|
||||||
{
|
{
|
||||||
zend_execute_data *ex = current_observed_frame;
|
zend_execute_data *ex = current_observed_frame;
|
||||||
while (ex != NULL) {
|
while (ex != NULL) {
|
||||||
if (ex->func && ex->func->type != ZEND_INTERNAL_FUNCTION) {
|
if (ex->func) {
|
||||||
zend_observer_fcall_end(ex, NULL);
|
zend_observer_fcall_end(ex, NULL);
|
||||||
}
|
}
|
||||||
ex = ex->prev_execute_data;
|
ex = ex->prev_execute_data;
|
||||||
|
|
|
@ -58,10 +58,10 @@ ZEND_API void zend_observer_fcall_register(zend_observer_fcall_init);
|
||||||
|
|
||||||
// Call during runtime, but only if you have used zend_observer_fcall_register.
|
// Call during runtime, but only if you have used zend_observer_fcall_register.
|
||||||
// You must not have more than one begin and one end handler active at the same time. Remove the old one first, if there is an existing one.
|
// You must not have more than one begin and one end handler active at the same time. Remove the old one first, if there is an existing one.
|
||||||
ZEND_API void zend_observer_add_begin_handler(zend_op_array *op_array, zend_observer_fcall_begin_handler begin);
|
ZEND_API void zend_observer_add_begin_handler(zend_function *function, zend_observer_fcall_begin_handler begin);
|
||||||
ZEND_API bool zend_observer_remove_begin_handler(zend_op_array *op_array, zend_observer_fcall_begin_handler begin);
|
ZEND_API bool zend_observer_remove_begin_handler(zend_function *function, zend_observer_fcall_begin_handler begin);
|
||||||
ZEND_API void zend_observer_add_end_handler(zend_op_array *op_array, zend_observer_fcall_end_handler end);
|
ZEND_API void zend_observer_add_end_handler(zend_function *function, zend_observer_fcall_end_handler end);
|
||||||
ZEND_API bool zend_observer_remove_end_handler(zend_op_array *op_array, zend_observer_fcall_end_handler end);
|
ZEND_API bool zend_observer_remove_end_handler(zend_function *function, zend_observer_fcall_end_handler end);
|
||||||
|
|
||||||
ZEND_API void zend_observer_startup(void); // Called by engine before MINITs
|
ZEND_API void zend_observer_startup(void); // Called by engine before MINITs
|
||||||
ZEND_API void zend_observer_post_startup(void); // Called by engine after MINITs
|
ZEND_API void zend_observer_post_startup(void); // Called by engine after MINITs
|
||||||
|
|
|
@ -405,7 +405,7 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV, SPEC(NO_CONST_
|
||||||
}
|
}
|
||||||
} else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV &&
|
} else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV &&
|
||||||
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
|
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
|
||||||
size_t len = ZSTR_LEN(op1_str);
|
size_t len = ZSTR_LEN(op1_str);
|
||||||
|
|
||||||
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
|
if (UNEXPECTED(len > ZSTR_MAX_LEN - ZSTR_LEN(op2_str))) {
|
||||||
zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
|
zend_error_noreturn(E_ERROR, "Integer overflow in memory allocation");
|
||||||
|
@ -1998,9 +1998,9 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, C
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
|
if (UNEXPECTED(ZEND_CALL_INFO(EX(call)) & ZEND_CALL_SEND_ARG_BY_REF)) {
|
||||||
if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) {
|
if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) {
|
||||||
ZEND_VM_DISPATCH_TO_HELPER(zend_use_tmp_in_write_context_helper);
|
ZEND_VM_DISPATCH_TO_HELPER(zend_use_tmp_in_write_context_helper);
|
||||||
}
|
}
|
||||||
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_DIM_W);
|
ZEND_VM_DISPATCH_TO_HANDLER(ZEND_FETCH_DIM_W);
|
||||||
} else {
|
} else {
|
||||||
if (OP2_TYPE == IS_UNUSED) {
|
if (OP2_TYPE == IS_UNUSED) {
|
||||||
|
@ -2036,7 +2036,7 @@ ZEND_VM_HOT_OBJ_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMPVAR|UNUSED|THIS|CV, CONST
|
||||||
|
|
||||||
if (OP1_TYPE == IS_CONST ||
|
if (OP1_TYPE == IS_CONST ||
|
||||||
(OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
|
(OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
|
||||||
do {
|
do {
|
||||||
if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
|
||||||
container = Z_REFVAL_P(container);
|
container = Z_REFVAL_P(container);
|
||||||
if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
|
||||||
|
@ -2084,9 +2084,9 @@ ZEND_VM_C_LABEL(fetch_obj_r_fast_copy):
|
||||||
Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx);
|
Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx);
|
||||||
|
|
||||||
if (EXPECTED(p->key == name) ||
|
if (EXPECTED(p->key == name) ||
|
||||||
(EXPECTED(p->h == ZSTR_H(name)) &&
|
(EXPECTED(p->h == ZSTR_H(name)) &&
|
||||||
EXPECTED(p->key != NULL) &&
|
EXPECTED(p->key != NULL) &&
|
||||||
EXPECTED(zend_string_equal_content(p->key, name)))) {
|
EXPECTED(zend_string_equal_content(p->key, name)))) {
|
||||||
retval = &p->val;
|
retval = &p->val;
|
||||||
if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) {
|
if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) {
|
||||||
ZEND_VM_C_GOTO(fetch_obj_r_copy);
|
ZEND_VM_C_GOTO(fetch_obj_r_copy);
|
||||||
|
@ -2248,9 +2248,9 @@ ZEND_VM_C_LABEL(fetch_obj_is_fast_copy):
|
||||||
Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx);
|
Bucket *p = (Bucket*)((char*)zobj->properties->arData + idx);
|
||||||
|
|
||||||
if (EXPECTED(p->key == name) ||
|
if (EXPECTED(p->key == name) ||
|
||||||
(EXPECTED(p->h == ZSTR_H(name)) &&
|
(EXPECTED(p->h == ZSTR_H(name)) &&
|
||||||
EXPECTED(p->key != NULL) &&
|
EXPECTED(p->key != NULL) &&
|
||||||
EXPECTED(zend_string_equal_content(p->key, name)))) {
|
EXPECTED(zend_string_equal_content(p->key, name)))) {
|
||||||
retval = &p->val;
|
retval = &p->val;
|
||||||
if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) {
|
if (!ZEND_VM_SPEC || (OP1_TYPE & (IS_TMP_VAR|IS_VAR)) != 0) {
|
||||||
ZEND_VM_C_GOTO(fetch_obj_is_copy);
|
ZEND_VM_C_GOTO(fetch_obj_is_copy);
|
||||||
|
@ -3161,7 +3161,7 @@ ZEND_VM_COLD_CONSTCONST_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMP
|
||||||
}
|
}
|
||||||
} else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV &&
|
} else if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV &&
|
||||||
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
|
!ZSTR_IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
|
||||||
size_t len = ZSTR_LEN(op1_str);
|
size_t len = ZSTR_LEN(op1_str);
|
||||||
|
|
||||||
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
|
str = zend_string_extend(op1_str, len + ZSTR_LEN(op2_str), 0);
|
||||||
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
|
memcpy(ZSTR_VAL(str) + len, ZSTR_VAL(op2_str), ZSTR_LEN(op2_str)+1);
|
||||||
|
@ -3503,9 +3503,9 @@ ZEND_VM_HOT_OBJ_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV,
|
||||||
|
|
||||||
if (OP2_TYPE == IS_CONST &&
|
if (OP2_TYPE == IS_CONST &&
|
||||||
EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) {
|
EXPECTED(CACHED_PTR(opline->result.num) == called_scope)) {
|
||||||
fbc = CACHED_PTR(opline->result.num + sizeof(void*));
|
fbc = CACHED_PTR(opline->result.num + sizeof(void*));
|
||||||
} else {
|
} else {
|
||||||
zend_object *orig_obj = obj;
|
zend_object *orig_obj = obj;
|
||||||
|
|
||||||
if (OP2_TYPE == IS_CONST) {
|
if (OP2_TYPE == IS_CONST) {
|
||||||
function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
|
function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
|
||||||
|
@ -3908,7 +3908,7 @@ ZEND_VM_HOT_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM|CACHE_SLOT)
|
||||||
ZEND_VM_NEXT_OPCODE();
|
ZEND_VM_NEXT_OPCODE();
|
||||||
}
|
}
|
||||||
|
|
||||||
ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL))
|
ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
|
||||||
{
|
{
|
||||||
USE_OPLINE
|
USE_OPLINE
|
||||||
zend_execute_data *call = EX(call);
|
zend_execute_data *call = EX(call);
|
||||||
|
@ -3929,6 +3929,7 @@ ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL))
|
||||||
ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
|
ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
|
||||||
ZVAL_NULL(ret);
|
ZVAL_NULL(ret);
|
||||||
|
|
||||||
|
ZEND_OBSERVER_FCALL_BEGIN(call);
|
||||||
fbc->internal_function.handler(call, ret);
|
fbc->internal_function.handler(call, ret);
|
||||||
|
|
||||||
#if ZEND_DEBUG
|
#if ZEND_DEBUG
|
||||||
|
@ -3943,6 +3944,7 @@ ZEND_VM_HOT_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL))
|
||||||
zend_verify_internal_func_info(call->func, ret);
|
zend_verify_internal_func_info(call->func, ret);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
|
||||||
|
|
||||||
EG(current_execute_data) = execute_data;
|
EG(current_execute_data) = execute_data;
|
||||||
zend_vm_stack_free_args(call);
|
zend_vm_stack_free_args(call);
|
||||||
|
@ -4048,6 +4050,7 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL,OBSERVER))
|
||||||
ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
|
ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
|
||||||
ZVAL_NULL(ret);
|
ZVAL_NULL(ret);
|
||||||
|
|
||||||
|
ZEND_OBSERVER_FCALL_BEGIN(call);
|
||||||
fbc->internal_function.handler(call, ret);
|
fbc->internal_function.handler(call, ret);
|
||||||
|
|
||||||
#if ZEND_DEBUG
|
#if ZEND_DEBUG
|
||||||
|
@ -4062,6 +4065,7 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL,OBSERVER))
|
||||||
zend_verify_internal_func_info(call->func, ret);
|
zend_verify_internal_func_info(call->func, ret);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
|
||||||
|
|
||||||
EG(current_execute_data) = execute_data;
|
EG(current_execute_data) = execute_data;
|
||||||
|
|
||||||
|
@ -4153,6 +4157,7 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
|
||||||
ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
|
ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval;
|
||||||
ZVAL_NULL(ret);
|
ZVAL_NULL(ret);
|
||||||
|
|
||||||
|
ZEND_OBSERVER_FCALL_BEGIN(call);
|
||||||
if (!zend_execute_internal) {
|
if (!zend_execute_internal) {
|
||||||
/* saves one function call if zend_execute_internal is not used */
|
/* saves one function call if zend_execute_internal is not used */
|
||||||
fbc->internal_function.handler(call, ret);
|
fbc->internal_function.handler(call, ret);
|
||||||
|
@ -4172,6 +4177,7 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER))
|
||||||
zend_verify_internal_func_info(call->func, ret);
|
zend_verify_internal_func_info(call->func, ret);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
|
||||||
|
|
||||||
EG(current_execute_data) = execute_data;
|
EG(current_execute_data) = execute_data;
|
||||||
|
|
||||||
|
@ -5782,7 +5788,7 @@ ZEND_VM_COLD_CONST_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|THIS|CV, ANY)
|
||||||
do {
|
do {
|
||||||
if (OP1_TYPE == IS_CONST ||
|
if (OP1_TYPE == IS_CONST ||
|
||||||
(OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) {
|
(OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(obj) != IS_OBJECT))) {
|
||||||
if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) {
|
if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(obj)) {
|
||||||
obj = Z_REFVAL_P(obj);
|
obj = Z_REFVAL_P(obj);
|
||||||
if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) {
|
if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) {
|
||||||
break;
|
break;
|
||||||
|
@ -6301,7 +6307,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL, SPEC(OBSER
|
||||||
new_op_array->scope = EX(func)->op_array.scope;
|
new_op_array->scope = EX(func)->op_array.scope;
|
||||||
|
|
||||||
call = zend_vm_stack_push_call_frame(
|
call = zend_vm_stack_push_call_frame(
|
||||||
(Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
|
(Z_TYPE_INFO(EX(This)) & ZEND_CALL_HAS_THIS) | ZEND_CALL_NESTED_CODE | ZEND_CALL_HAS_SYMBOL_TABLE,
|
||||||
(zend_function*)new_op_array, 0,
|
(zend_function*)new_op_array, 0,
|
||||||
Z_PTR(EX(This)));
|
Z_PTR(EX(This)));
|
||||||
|
|
||||||
|
@ -8129,7 +8135,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMPVAR|CV|UNUSED
|
||||||
}
|
}
|
||||||
} else if (OP1_TYPE == IS_TMP_VAR) {
|
} else if (OP1_TYPE == IS_TMP_VAR) {
|
||||||
ZVAL_COPY_VALUE(&generator->value, value);
|
ZVAL_COPY_VALUE(&generator->value, value);
|
||||||
} else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
|
} else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
|
||||||
ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
|
ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
|
||||||
FREE_OP1_IF_VAR();
|
FREE_OP1_IF_VAR();
|
||||||
} else {
|
} else {
|
||||||
|
@ -8364,9 +8370,9 @@ ZEND_VM_HOT_HANDLER(168, ZEND_BIND_GLOBAL, CV, CONST, CACHE_SLOT)
|
||||||
Bucket *p = (Bucket*)((char*)EG(symbol_table).arData + idx);
|
Bucket *p = (Bucket*)((char*)EG(symbol_table).arData + idx);
|
||||||
|
|
||||||
if (EXPECTED(p->key == varname) ||
|
if (EXPECTED(p->key == varname) ||
|
||||||
(EXPECTED(p->h == ZSTR_H(varname)) &&
|
(EXPECTED(p->h == ZSTR_H(varname)) &&
|
||||||
EXPECTED(p->key != NULL) &&
|
EXPECTED(p->key != NULL) &&
|
||||||
EXPECTED(zend_string_equal_content(p->key, varname)))) {
|
EXPECTED(zend_string_equal_content(p->key, varname)))) {
|
||||||
|
|
||||||
value = (zval*)p; /* value = &p->val; */
|
value = (zval*)p; /* value = &p->val; */
|
||||||
ZEND_VM_C_GOTO(check_indirect);
|
ZEND_VM_C_GOTO(check_indirect);
|
||||||
|
@ -8710,6 +8716,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER))
|
||||||
}
|
}
|
||||||
|
|
||||||
ZVAL_NULL(ret);
|
ZVAL_NULL(ret);
|
||||||
|
ZEND_OBSERVER_FCALL_BEGIN(call);
|
||||||
if (!zend_execute_internal) {
|
if (!zend_execute_internal) {
|
||||||
/* saves one function call if zend_execute_internal is not used */
|
/* saves one function call if zend_execute_internal is not used */
|
||||||
fbc->internal_function.handler(call, ret);
|
fbc->internal_function.handler(call, ret);
|
||||||
|
@ -8729,6 +8736,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER))
|
||||||
zend_verify_internal_func_info(call->func, ret);
|
zend_verify_internal_func_info(call->func, ret);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
ZEND_OBSERVER_FCALL_END(call, EG(exception) ? NULL : ret);
|
||||||
|
|
||||||
EG(current_execute_data) = call->prev_execute_data;
|
EG(current_execute_data) = call->prev_execute_data;
|
||||||
|
|
||||||
|
|
767
Zend/zend_vm_execute.h
generated
767
Zend/zend_vm_execute.h
generated
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -9527,13 +9527,19 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
| // EG(current_execute_data) = execute_data;
|
||||||
|
| MEM_STORE_64_ZTS str, RX, executor_globals, current_execute_data, REG1
|
||||||
|
|
||||||
|
if (ZEND_OBSERVER_ENABLED) {
|
||||||
|
| mov FCARG1x, RX
|
||||||
|
| EXT_CALL zend_observer_fcall_begin, REG0
|
||||||
|
| ldr REG0, EX:RX->func // reload
|
||||||
|
}
|
||||||
|
|
||||||
| // ZVAL_NULL(EX_VAR(opline->result.var));
|
| // ZVAL_NULL(EX_VAR(opline->result.var));
|
||||||
| LOAD_ZVAL_ADDR FCARG2x, res_addr
|
| LOAD_ZVAL_ADDR FCARG2x, res_addr
|
||||||
| SET_Z_TYPE_INFO FCARG2x, IS_NULL, TMP1w
|
| SET_Z_TYPE_INFO FCARG2x, IS_NULL, TMP1w
|
||||||
|
|
||||||
| // EG(current_execute_data) = execute_data;
|
|
||||||
| MEM_STORE_64_ZTS str, RX, executor_globals, current_execute_data, REG1
|
|
||||||
|
|
||||||
zend_jit_reset_last_valid_opline();
|
zend_jit_reset_last_valid_opline();
|
||||||
|
|
||||||
| // fbc->internal_function.handler(call, ret);
|
| // fbc->internal_function.handler(call, ret);
|
||||||
|
@ -9545,6 +9551,12 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
|
||||||
| blr TMP1
|
| blr TMP1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ZEND_OBSERVER_ENABLED) {
|
||||||
|
| LOAD_ZVAL_ADDR FCARG2x, res_addr
|
||||||
|
| mov FCARG1x, RX
|
||||||
|
| EXT_CALL zend_observer_fcall_end, REG0
|
||||||
|
}
|
||||||
|
|
||||||
| // EG(current_execute_data) = execute_data;
|
| // EG(current_execute_data) = execute_data;
|
||||||
| MEM_STORE_64_ZTS str, FP, executor_globals, current_execute_data, REG0
|
| MEM_STORE_64_ZTS str, FP, executor_globals, current_execute_data, REG0
|
||||||
|
|
||||||
|
|
|
@ -10231,13 +10231,19 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
| // EG(current_execute_data) = execute_data;
|
||||||
|
| MEM_STORE_ZTS aword, executor_globals, current_execute_data, RX, r1
|
||||||
|
|
||||||
|
if (ZEND_OBSERVER_ENABLED) {
|
||||||
|
| mov FCARG1a, RX
|
||||||
|
| EXT_CALL zend_observer_fcall_begin, r0
|
||||||
|
| mov r0, EX:RX->func // reload
|
||||||
|
}
|
||||||
|
|
||||||
| // ZVAL_NULL(EX_VAR(opline->result.var));
|
| // ZVAL_NULL(EX_VAR(opline->result.var));
|
||||||
| LOAD_ZVAL_ADDR FCARG2a, res_addr
|
| LOAD_ZVAL_ADDR FCARG2a, res_addr
|
||||||
| SET_Z_TYPE_INFO FCARG2a, IS_NULL
|
| SET_Z_TYPE_INFO FCARG2a, IS_NULL
|
||||||
|
|
||||||
| // EG(current_execute_data) = execute_data;
|
|
||||||
| MEM_STORE_ZTS aword, executor_globals, current_execute_data, RX, r1
|
|
||||||
|
|
||||||
zend_jit_reset_last_valid_opline();
|
zend_jit_reset_last_valid_opline();
|
||||||
|
|
||||||
| // fbc->internal_function.handler(call, ret);
|
| // fbc->internal_function.handler(call, ret);
|
||||||
|
@ -10248,6 +10254,12 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend
|
||||||
| call aword [r0 + offsetof(zend_internal_function, handler)]
|
| call aword [r0 + offsetof(zend_internal_function, handler)]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ZEND_OBSERVER_ENABLED) {
|
||||||
|
| LOAD_ZVAL_ADDR FCARG2a, res_addr
|
||||||
|
| mov FCARG1a, RX
|
||||||
|
| EXT_CALL zend_observer_fcall_end, r0
|
||||||
|
}
|
||||||
|
|
||||||
| // EG(current_execute_data) = execute_data;
|
| // EG(current_execute_data) = execute_data;
|
||||||
| MEM_STORE_ZTS aword, executor_globals, current_execute_data, FP, r0
|
| MEM_STORE_ZTS aword, executor_globals, current_execute_data, FP, r0
|
||||||
|
|
||||||
|
|
|
@ -1245,6 +1245,7 @@ bool pdo_hash_methods(pdo_dbh_object_t *dbh_obj, int kind)
|
||||||
func.function_name = zend_string_init(funcs->fname, strlen(funcs->fname), dbh->is_persistent);
|
func.function_name = zend_string_init(funcs->fname, strlen(funcs->fname), dbh->is_persistent);
|
||||||
func.scope = dbh_obj->std.ce;
|
func.scope = dbh_obj->std.ce;
|
||||||
func.prototype = NULL;
|
func.prototype = NULL;
|
||||||
|
ZEND_MAP_PTR(func.run_time_cache) = NULL;
|
||||||
if (funcs->flags) {
|
if (funcs->flags) {
|
||||||
func.fn_flags = funcs->flags | ZEND_ACC_NEVER_CACHE;
|
func.fn_flags = funcs->flags | ZEND_ACC_NEVER_CACHE;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -264,8 +264,8 @@ static ZEND_INI_MH(zend_test_observer_OnUpdateCommaList)
|
||||||
if (stage != PHP_INI_STAGE_STARTUP && stage != PHP_INI_STAGE_ACTIVATE && stage != PHP_INI_STAGE_DEACTIVATE && stage != PHP_INI_STAGE_SHUTDOWN) {
|
if (stage != PHP_INI_STAGE_STARTUP && stage != PHP_INI_STAGE_ACTIVATE && stage != PHP_INI_STAGE_DEACTIVATE && stage != PHP_INI_STAGE_SHUTDOWN) {
|
||||||
ZEND_HASH_FOREACH_STR_KEY(*p, funcname) {
|
ZEND_HASH_FOREACH_STR_KEY(*p, funcname) {
|
||||||
if ((func = zend_hash_find_ptr(EG(function_table), funcname))) {
|
if ((func = zend_hash_find_ptr(EG(function_table), funcname))) {
|
||||||
zend_observer_remove_begin_handler(&func->op_array, observer_begin);
|
zend_observer_remove_begin_handler(func, observer_begin);
|
||||||
zend_observer_remove_end_handler(&func->op_array, observer_end);
|
zend_observer_remove_end_handler(func, observer_end);
|
||||||
}
|
}
|
||||||
} ZEND_HASH_FOREACH_END();
|
} ZEND_HASH_FOREACH_END();
|
||||||
}
|
}
|
||||||
|
@ -280,8 +280,8 @@ static ZEND_INI_MH(zend_test_observer_OnUpdateCommaList)
|
||||||
if (stage != PHP_INI_STAGE_STARTUP && stage != PHP_INI_STAGE_ACTIVATE && stage != PHP_INI_STAGE_DEACTIVATE && stage != PHP_INI_STAGE_SHUTDOWN) {
|
if (stage != PHP_INI_STAGE_STARTUP && stage != PHP_INI_STAGE_ACTIVATE && stage != PHP_INI_STAGE_DEACTIVATE && stage != PHP_INI_STAGE_SHUTDOWN) {
|
||||||
ZEND_HASH_FOREACH_STR_KEY(*p, funcname) {
|
ZEND_HASH_FOREACH_STR_KEY(*p, funcname) {
|
||||||
if ((func = zend_hash_find_ptr(EG(function_table), funcname))) {
|
if ((func = zend_hash_find_ptr(EG(function_table), funcname))) {
|
||||||
zend_observer_add_begin_handler(&func->op_array, observer_begin);
|
zend_observer_add_begin_handler(func, observer_begin);
|
||||||
zend_observer_add_end_handler(&func->op_array, observer_end);
|
zend_observer_add_end_handler(func, observer_end);
|
||||||
}
|
}
|
||||||
} ZEND_HASH_FOREACH_END();
|
} ZEND_HASH_FOREACH_END();
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,38 +48,32 @@ var_dump(foo());
|
||||||
{main} %s%eobserver_backtrace_%d.php
|
{main} %s%eobserver_backtrace_%d.php
|
||||||
-->
|
-->
|
||||||
<foo>
|
<foo>
|
||||||
<!-- init gen() -->
|
<!-- init Generator::current() -->
|
||||||
<!--
|
<!--
|
||||||
gen()
|
|
||||||
Generator::current()
|
Generator::current()
|
||||||
foo()
|
foo()
|
||||||
{main} %s%eobserver_backtrace_%d.php
|
{main} %s%eobserver_backtrace_%d.php
|
||||||
-->
|
-->
|
||||||
<gen>
|
<Generator::current>
|
||||||
<!-- init TestClass::foo() -->
|
<!-- init gen() -->
|
||||||
<!--
|
<!--
|
||||||
TestClass::foo()
|
|
||||||
gen()
|
gen()
|
||||||
Generator::current()
|
Generator::current()
|
||||||
foo()
|
foo()
|
||||||
{main} %s%eobserver_backtrace_%d.php
|
{main} %s%eobserver_backtrace_%d.php
|
||||||
-->
|
-->
|
||||||
<TestClass::foo>
|
<gen>
|
||||||
<!-- init TestClass::{closure}() -->
|
<!-- init TestClass::foo() -->
|
||||||
<!--
|
<!--
|
||||||
TestClass::{closure}()
|
|
||||||
array_map()
|
|
||||||
TestClass::foo()
|
TestClass::foo()
|
||||||
gen()
|
gen()
|
||||||
Generator::current()
|
Generator::current()
|
||||||
foo()
|
foo()
|
||||||
{main} %s%eobserver_backtrace_%d.php
|
{main} %s%eobserver_backtrace_%d.php
|
||||||
-->
|
-->
|
||||||
<TestClass::{closure}>
|
<TestClass::foo>
|
||||||
<!-- init TestClass::bar() -->
|
<!-- init array_map() -->
|
||||||
<!--
|
<!--
|
||||||
TestClass::bar()
|
|
||||||
TestClass::{closure}()
|
|
||||||
array_map()
|
array_map()
|
||||||
TestClass::foo()
|
TestClass::foo()
|
||||||
gen()
|
gen()
|
||||||
|
@ -87,20 +81,52 @@ var_dump(foo());
|
||||||
foo()
|
foo()
|
||||||
{main} %s%eobserver_backtrace_%d.php
|
{main} %s%eobserver_backtrace_%d.php
|
||||||
-->
|
-->
|
||||||
<TestClass::bar>
|
<array_map>
|
||||||
</TestClass::bar>
|
<!-- init TestClass::{closure}() -->
|
||||||
</TestClass::{closure}>
|
<!--
|
||||||
<TestClass::{closure}>
|
TestClass::{closure}()
|
||||||
<TestClass::bar>
|
array_map()
|
||||||
</TestClass::bar>
|
TestClass::foo()
|
||||||
</TestClass::{closure}>
|
gen()
|
||||||
</TestClass::foo>
|
Generator::current()
|
||||||
</gen>
|
foo()
|
||||||
|
{main} %s%eobserver_backtrace_%d.php
|
||||||
|
-->
|
||||||
|
<TestClass::{closure}>
|
||||||
|
<!-- init TestClass::bar() -->
|
||||||
|
<!--
|
||||||
|
TestClass::bar()
|
||||||
|
TestClass::{closure}()
|
||||||
|
array_map()
|
||||||
|
TestClass::foo()
|
||||||
|
gen()
|
||||||
|
Generator::current()
|
||||||
|
foo()
|
||||||
|
{main} %s%eobserver_backtrace_%d.php
|
||||||
|
-->
|
||||||
|
<TestClass::bar>
|
||||||
|
</TestClass::bar>
|
||||||
|
</TestClass::{closure}>
|
||||||
|
<TestClass::{closure}>
|
||||||
|
<TestClass::bar>
|
||||||
|
</TestClass::bar>
|
||||||
|
</TestClass::{closure}>
|
||||||
|
</array_map>
|
||||||
|
</TestClass::foo>
|
||||||
|
</gen>
|
||||||
|
</Generator::current>
|
||||||
</foo>
|
</foo>
|
||||||
|
<!-- init var_dump() -->
|
||||||
|
<!--
|
||||||
|
var_dump()
|
||||||
|
{main} %s%eobserver_backtrace_%d.php
|
||||||
|
-->
|
||||||
|
<var_dump>
|
||||||
array(2) {
|
array(2) {
|
||||||
[0]=>
|
[0]=>
|
||||||
int(42)
|
int(42)
|
||||||
[1]=>
|
[1]=>
|
||||||
int(1337)
|
int(1337)
|
||||||
}
|
}
|
||||||
|
</var_dump>
|
||||||
</file '%s%eobserver_backtrace_%d.php'>
|
</file '%s%eobserver_backtrace_%d.php'>
|
||||||
|
|
|
@ -26,30 +26,44 @@ foo();
|
||||||
echo 'DONE' . PHP_EOL;
|
echo 'DONE' . PHP_EOL;
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_basic_01.php' -->
|
<!-- init '%s%eobserver_basic_%d.php' -->
|
||||||
<file '%s%eobserver_basic_01.php'>
|
<file '%s%eobserver_basic_%d.php'>
|
||||||
<!-- init foo() -->
|
<!-- init foo() -->
|
||||||
<foo>
|
<foo>
|
||||||
Foo
|
Foo
|
||||||
<!-- init bar() -->
|
<!-- init bar() -->
|
||||||
<bar>
|
<bar>
|
||||||
Bar
|
Bar
|
||||||
|
<!-- init array_sum() -->
|
||||||
|
<array_sum>
|
||||||
|
</array_sum>
|
||||||
|
<!-- init var_dump() -->
|
||||||
|
<var_dump>
|
||||||
int(6)
|
int(6)
|
||||||
|
</var_dump>
|
||||||
</bar>
|
</bar>
|
||||||
</foo>
|
</foo>
|
||||||
<foo>
|
<foo>
|
||||||
Foo
|
Foo
|
||||||
<bar>
|
<bar>
|
||||||
Bar
|
Bar
|
||||||
|
<array_sum>
|
||||||
|
</array_sum>
|
||||||
|
<var_dump>
|
||||||
int(6)
|
int(6)
|
||||||
|
</var_dump>
|
||||||
</bar>
|
</bar>
|
||||||
</foo>
|
</foo>
|
||||||
<foo>
|
<foo>
|
||||||
Foo
|
Foo
|
||||||
<bar>
|
<bar>
|
||||||
Bar
|
Bar
|
||||||
|
<array_sum>
|
||||||
|
</array_sum>
|
||||||
|
<var_dump>
|
||||||
int(6)
|
int(6)
|
||||||
|
</var_dump>
|
||||||
</bar>
|
</bar>
|
||||||
</foo>
|
</foo>
|
||||||
DONE
|
DONE
|
||||||
</file '%s%eobserver_basic_01.php'>
|
</file '%s%eobserver_basic_%d.php'>
|
||||||
|
|
|
@ -30,30 +30,44 @@ $test->foo();
|
||||||
echo 'DONE' . PHP_EOL;
|
echo 'DONE' . PHP_EOL;
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_basic_02.php' -->
|
<!-- init '%s%eobserver_basic_%d.php' -->
|
||||||
<file '%s%eobserver_basic_02.php'>
|
<file '%s%eobserver_basic_%d.php'>
|
||||||
<!-- init TestClass::foo() -->
|
<!-- init TestClass::foo() -->
|
||||||
<TestClass::foo>
|
<TestClass::foo>
|
||||||
Foo
|
Foo
|
||||||
<!-- init TestClass::bar() -->
|
<!-- init TestClass::bar() -->
|
||||||
<TestClass::bar>
|
<TestClass::bar>
|
||||||
Bar
|
Bar
|
||||||
|
<!-- init array_sum() -->
|
||||||
|
<array_sum>
|
||||||
|
</array_sum>
|
||||||
|
<!-- init var_dump() -->
|
||||||
|
<var_dump>
|
||||||
int(6)
|
int(6)
|
||||||
|
</var_dump>
|
||||||
</TestClass::bar>
|
</TestClass::bar>
|
||||||
</TestClass::foo>
|
</TestClass::foo>
|
||||||
<TestClass::foo>
|
<TestClass::foo>
|
||||||
Foo
|
Foo
|
||||||
<TestClass::bar>
|
<TestClass::bar>
|
||||||
Bar
|
Bar
|
||||||
|
<array_sum>
|
||||||
|
</array_sum>
|
||||||
|
<var_dump>
|
||||||
int(6)
|
int(6)
|
||||||
|
</var_dump>
|
||||||
</TestClass::bar>
|
</TestClass::bar>
|
||||||
</TestClass::foo>
|
</TestClass::foo>
|
||||||
<TestClass::foo>
|
<TestClass::foo>
|
||||||
Foo
|
Foo
|
||||||
<TestClass::bar>
|
<TestClass::bar>
|
||||||
Bar
|
Bar
|
||||||
|
<array_sum>
|
||||||
|
</array_sum>
|
||||||
|
<var_dump>
|
||||||
int(6)
|
int(6)
|
||||||
|
</var_dump>
|
||||||
</TestClass::bar>
|
</TestClass::bar>
|
||||||
</TestClass::foo>
|
</TestClass::foo>
|
||||||
DONE
|
DONE
|
||||||
</file '%s%eobserver_basic_02.php'>
|
</file '%s%eobserver_basic_%d.php'>
|
||||||
|
|
|
@ -34,6 +34,7 @@ Foo
|
||||||
</foo>
|
</foo>
|
||||||
<!-- init bar() -->
|
<!-- init bar() -->
|
||||||
Bar
|
Bar
|
||||||
|
<!-- init ini_set() -->
|
||||||
Foo
|
Foo
|
||||||
<bar>
|
<bar>
|
||||||
Bar
|
Bar
|
||||||
|
|
|
@ -25,7 +25,16 @@ call_user_func([$r->getAttributes(A::class)[0], 'newInstance']);
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s' -->
|
<!-- init '%s' -->
|
||||||
<file '%s'>
|
<file '%s'>
|
||||||
<!-- init A::__construct() -->
|
<!-- init ReflectionFunction::__construct() -->
|
||||||
<A::__construct>
|
<ReflectionFunction::__construct>
|
||||||
</A::__construct>
|
</ReflectionFunction::__construct>
|
||||||
|
<!-- init ReflectionFunctionAbstract::getAttributes() -->
|
||||||
|
<ReflectionFunctionAbstract::getAttributes>
|
||||||
|
</ReflectionFunctionAbstract::getAttributes>
|
||||||
|
<!-- init ReflectionAttribute::newInstance() -->
|
||||||
|
<ReflectionAttribute::newInstance>
|
||||||
|
<!-- init A::__construct() -->
|
||||||
|
<A::__construct>
|
||||||
|
</A::__construct>
|
||||||
|
</ReflectionAttribute::newInstance>
|
||||||
</file '%s'>
|
</file '%s'>
|
|
@ -25,9 +25,24 @@ call_user_func([$r->getAttributes(A::class)[0], 'newInstance']);
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s' -->
|
<!-- init '%s' -->
|
||||||
<file '%s'>
|
<file '%s'>
|
||||||
<!-- init A::__construct() -->
|
<!-- init ReflectionFunction::__construct() -->
|
||||||
<A::__construct>
|
<ReflectionFunction::__construct>
|
||||||
|
</ReflectionFunction::__construct>
|
||||||
|
<!-- init ReflectionFunctionAbstract::getAttributes() -->
|
||||||
|
<ReflectionFunctionAbstract::getAttributes>
|
||||||
|
</ReflectionFunctionAbstract::getAttributes>
|
||||||
|
<!-- init ReflectionAttribute::newInstance() -->
|
||||||
|
<ReflectionAttribute::newInstance>
|
||||||
|
<!-- init A::__construct() -->
|
||||||
|
<A::__construct>
|
||||||
|
<!-- init array_map() -->
|
||||||
|
<array_map>
|
||||||
|
<!-- init str_repeat() -->
|
||||||
|
<str_repeat>
|
||||||
|
|
||||||
Fatal error: Allowed memory size of %d bytes exhausted %s in %s on line %d
|
Fatal error: Allowed memory size of %d bytes exhausted %s in %s on line %d
|
||||||
</A::__construct>
|
</str_repeat>
|
||||||
|
</array_map>
|
||||||
|
</A::__construct>
|
||||||
|
</ReflectionAttribute::newInstance>
|
||||||
</file '%s'>
|
</file '%s'>
|
||||||
|
|
|
@ -42,6 +42,8 @@ a();
|
||||||
<d>
|
<d>
|
||||||
</d>
|
</d>
|
||||||
<!-- init bailout() -->
|
<!-- init bailout() -->
|
||||||
|
<!-- init array_map() -->
|
||||||
|
<!-- init str_repeat() -->
|
||||||
|
|
||||||
Fatal error: Allowed memory size of 20971520 bytes exhausted %s in %s on line %d
|
Fatal error: Allowed memory size of 20971520 bytes exhausted %s in %s on line %d
|
||||||
</a>
|
</a>
|
||||||
|
|
|
@ -26,14 +26,19 @@ namespace Test {
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_call_user_func_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<file '%s%eobserver_call_user_func_%d.php'>
|
<file '%s'>
|
||||||
<!-- init Test\MyClass::myMethod() -->
|
<!-- init call_user_func() -->
|
||||||
<Test\MyClass::myMethod>
|
<call_user_func>
|
||||||
|
<!-- init Test\MyClass::myMethod() -->
|
||||||
|
<Test\MyClass::myMethod>
|
||||||
MyClass::myMethod called
|
MyClass::myMethod called
|
||||||
</Test\MyClass::myMethod>
|
</Test\MyClass::myMethod>
|
||||||
<!-- init Test\my_function() -->
|
</call_user_func>
|
||||||
<Test\my_function>
|
<call_user_func>
|
||||||
|
<!-- init Test\my_function() -->
|
||||||
|
<Test\my_function>
|
||||||
my_function called
|
my_function called
|
||||||
</Test\my_function>
|
</Test\my_function>
|
||||||
</file '%s%eobserver_call_user_func_%d.php'>
|
</call_user_func>
|
||||||
|
</file '%s'>
|
||||||
|
|
|
@ -26,14 +26,19 @@ namespace Test {
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_call_user_func_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<file '%s%eobserver_call_user_func_%d.php'>
|
<file '%s'>
|
||||||
<!-- init Test\MyClass::myMethod() -->
|
<!-- init call_user_func_array() -->
|
||||||
<Test\MyClass::myMethod>
|
<call_user_func_array>
|
||||||
|
<!-- init Test\MyClass::myMethod() -->
|
||||||
|
<Test\MyClass::myMethod>
|
||||||
MyClass::myMethod called
|
MyClass::myMethod called
|
||||||
</Test\MyClass::myMethod>
|
</Test\MyClass::myMethod>
|
||||||
<!-- init Test\my_function() -->
|
</call_user_func_array>
|
||||||
<Test\my_function>
|
<call_user_func_array>
|
||||||
|
<!-- init Test\my_function() -->
|
||||||
|
<Test\my_function>
|
||||||
my_function called
|
my_function called
|
||||||
</Test\my_function>
|
</Test\my_function>
|
||||||
</file '%s%eobserver_call_user_func_%d.php'>
|
</call_user_func_array>
|
||||||
|
</file '%s'>
|
||||||
|
|
|
@ -23,27 +23,41 @@ $foo($bar);
|
||||||
echo 'DONE' . PHP_EOL;
|
echo 'DONE' . PHP_EOL;
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_closure_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<file '%s%eobserver_closure_%d.php'>
|
<file '%s'>
|
||||||
<!-- init {closure}() -->
|
<!-- init {closure}() -->
|
||||||
<{closure}>
|
<{closure}>
|
||||||
Answer
|
Answer
|
||||||
<!-- init {closure}() -->
|
<!-- init {closure}() -->
|
||||||
<{closure}>
|
<{closure}>
|
||||||
|
<!-- init array_sum() -->
|
||||||
|
<array_sum>
|
||||||
|
</array_sum>
|
||||||
|
<!-- init var_dump() -->
|
||||||
|
<var_dump>
|
||||||
int(42)
|
int(42)
|
||||||
|
</var_dump>
|
||||||
</{closure}>
|
</{closure}>
|
||||||
</{closure}>
|
</{closure}>
|
||||||
<{closure}>
|
<{closure}>
|
||||||
Answer
|
Answer
|
||||||
<{closure}>
|
<{closure}>
|
||||||
|
<array_sum>
|
||||||
|
</array_sum>
|
||||||
|
<var_dump>
|
||||||
int(42)
|
int(42)
|
||||||
|
</var_dump>
|
||||||
</{closure}>
|
</{closure}>
|
||||||
</{closure}>
|
</{closure}>
|
||||||
<{closure}>
|
<{closure}>
|
||||||
Answer
|
Answer
|
||||||
<{closure}>
|
<{closure}>
|
||||||
|
<array_sum>
|
||||||
|
</array_sum>
|
||||||
|
<var_dump>
|
||||||
int(42)
|
int(42)
|
||||||
|
</var_dump>
|
||||||
</{closure}>
|
</{closure}>
|
||||||
</{closure}>
|
</{closure}>
|
||||||
DONE
|
DONE
|
||||||
</file '%s%eobserver_closure_%d.php'>
|
</file '%s'>
|
||||||
|
|
|
@ -22,11 +22,14 @@ $closure();
|
||||||
echo 'DONE' . PHP_EOL;
|
echo 'DONE' . PHP_EOL;
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_closure_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<file '%s%eobserver_closure_%d.php'>
|
<file '%s'>
|
||||||
|
<!-- init Closure::fromCallable() -->
|
||||||
|
<Closure::fromCallable>
|
||||||
|
</Closure::fromCallable>
|
||||||
<!-- init Foo::bar() -->
|
<!-- init Foo::bar() -->
|
||||||
<Foo::bar>
|
<Foo::bar>
|
||||||
Called as fake closure.
|
Called as fake closure.
|
||||||
</Foo::bar>
|
</Foo::bar>
|
||||||
DONE
|
DONE
|
||||||
</file '%s%eobserver_closure_%d.php'>
|
</file '%s'>
|
||||||
|
|
|
@ -19,11 +19,14 @@ foo();
|
||||||
echo 'You should not see this.';
|
echo 'You should not see this.';
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_error_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<file '%s%eobserver_error_%d.php'>
|
<file '%s'>
|
||||||
<!-- init foo() -->
|
<!-- init foo() -->
|
||||||
<foo>
|
<foo>
|
||||||
|
<!-- init str_repeat() -->
|
||||||
|
<str_repeat>
|
||||||
|
|
||||||
Fatal error: Allowed memory size of 2097152 bytes exhausted%s(tried to allocate %d bytes) in %s on line %d
|
Fatal error: Allowed memory size of 2097152 bytes exhausted%s(tried to allocate %d bytes) in %s on line %d
|
||||||
|
</str_repeat:NULL>
|
||||||
</foo:NULL>
|
</foo:NULL>
|
||||||
</file '%s%eobserver_error_%d.php'>
|
</file '%s%eobserver_error_%d.php'>
|
||||||
|
|
|
@ -18,11 +18,14 @@ foo();
|
||||||
echo 'You should not see this.';
|
echo 'You should not see this.';
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_error_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<file '%s%eobserver_error_%d.php'>
|
<file '%s'>
|
||||||
<!-- init foo() -->
|
<!-- init foo() -->
|
||||||
<foo>
|
<foo>
|
||||||
|
<!-- init trigger_error() -->
|
||||||
|
<trigger_error>
|
||||||
|
|
||||||
Fatal error: Foo error in %s on line %d
|
Fatal error: Foo error in %s on line %d
|
||||||
|
</trigger_error:NULL>
|
||||||
</foo:NULL>
|
</foo:NULL>
|
||||||
</file '%s%eobserver_error_%d.php'>
|
</file '%s'>
|
||||||
|
|
|
@ -36,10 +36,18 @@ echo 'Done.' . PHP_EOL;
|
||||||
<main>
|
<main>
|
||||||
<!-- init foo() -->
|
<!-- init foo() -->
|
||||||
<foo>
|
<foo>
|
||||||
|
<!-- init SoapClient::__construct() -->
|
||||||
|
<SoapClient::__construct>
|
||||||
|
<!-- Exception: SoapFault -->
|
||||||
|
</SoapClient::__construct:NULL>
|
||||||
<!-- Exception: SoapFault -->
|
<!-- Exception: SoapFault -->
|
||||||
</foo:NULL>
|
</foo:NULL>
|
||||||
<!-- Exception: SoapFault -->
|
<!-- Exception: SoapFault -->
|
||||||
</main:NULL>
|
</main:NULL>
|
||||||
|
<!-- init Exception::getMessage() -->
|
||||||
|
<Exception::getMessage>
|
||||||
|
</Exception::getMessage:'SOAP-ERROR: Parsing WSDL: Couldn\'t load from \'foo\' : failed to load external entity "foo"
|
||||||
|
'>
|
||||||
SOAP-ERROR: Parsing WSDL: Couldn't load from 'foo' : failed to load external entity "foo"
|
SOAP-ERROR: Parsing WSDL: Couldn't load from 'foo' : failed to load external entity "foo"
|
||||||
|
|
||||||
Done.
|
Done.
|
||||||
|
|
|
@ -22,14 +22,20 @@ foo();
|
||||||
echo 'You should not see this.';
|
echo 'You should not see this.';
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_error_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<file '%s%eobserver_error_%d.php'>
|
<file '%s'>
|
||||||
|
<!-- init set_error_handler() -->
|
||||||
|
<set_error_handler>
|
||||||
|
</set_error_handler:NULL>
|
||||||
<!-- init foo() -->
|
<!-- init foo() -->
|
||||||
<foo>
|
<foo>
|
||||||
<!-- init {closure}() -->
|
<!-- init {closure}() -->
|
||||||
<{closure}>
|
<{closure}>
|
||||||
|
<!-- init trigger_error() -->
|
||||||
|
<trigger_error>
|
||||||
|
|
||||||
Fatal error: Foo error in %s on line %d
|
Fatal error: Foo error in %s on line %d
|
||||||
|
</trigger_error:NULL>
|
||||||
</{closure}:NULL>
|
</{closure}:NULL>
|
||||||
</foo:NULL>
|
</foo:NULL>
|
||||||
</file '%s%eobserver_error_%d.php'>
|
</file '%s'>
|
||||||
|
|
|
@ -23,8 +23,8 @@ foo();
|
||||||
echo 'You should not see this' . PHP_EOL;
|
echo 'You should not see this' . PHP_EOL;
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_exception_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<file '%s%eobserver_exception_%d.php'>
|
<file '%s'>
|
||||||
<!-- init foo() -->
|
<!-- init foo() -->
|
||||||
<foo>
|
<foo>
|
||||||
Call #0
|
Call #0
|
||||||
|
@ -34,10 +34,19 @@ Call #1
|
||||||
</foo>
|
</foo>
|
||||||
<foo>
|
<foo>
|
||||||
Call #2
|
Call #2
|
||||||
|
<!-- init Exception::__construct() -->
|
||||||
|
<Exception::__construct>
|
||||||
|
</Exception::__construct>
|
||||||
<!-- Exception: RuntimeException -->
|
<!-- Exception: RuntimeException -->
|
||||||
</foo>
|
</foo>
|
||||||
<!-- Exception: RuntimeException -->
|
<!-- Exception: RuntimeException -->
|
||||||
</file '%s%eobserver_exception_%d.php'>
|
</file '%s'>
|
||||||
|
<!-- init Exception::__toString() -->
|
||||||
|
<Exception::__toString>
|
||||||
|
<!-- init Exception::getTraceAsString() -->
|
||||||
|
<Exception::getTraceAsString>
|
||||||
|
</Exception::getTraceAsString>
|
||||||
|
</Exception::__toString>
|
||||||
|
|
||||||
Fatal error: Uncaught RuntimeException: Third time is a charm in %s%eobserver_exception_%d.php:%d
|
Fatal error: Uncaught RuntimeException: Third time is a charm in %s%eobserver_exception_%d.php:%d
|
||||||
Stack trace:
|
Stack trace:
|
||||||
|
|
|
@ -19,13 +19,17 @@ $fiber->resume();
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%sobserver_fiber_01.php' -->
|
<!-- init '%s' -->
|
||||||
|
<!-- init Fiber::__construct() -->
|
||||||
|
<!-- init Fiber::start() -->
|
||||||
<!-- alloc: %s -->
|
<!-- alloc: %s -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<init '%s'>
|
<init '%s'>
|
||||||
<!-- init {closure}() -->
|
<!-- init {closure}() -->
|
||||||
|
<!-- init Fiber::suspend() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<suspend '%s'>
|
<suspend '%s'>
|
||||||
|
<!-- init Fiber::resume() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<resume '%s'>
|
<resume '%s'>
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
|
|
|
@ -16,10 +16,13 @@ $fiber->start();
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%sobserver_fiber_02.php' -->
|
<!-- init '%s' -->
|
||||||
|
<!-- init Fiber::__construct() -->
|
||||||
|
<!-- init Fiber::start() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<init '%s'>
|
<init '%s'>
|
||||||
<!-- init {closure}() -->
|
<!-- init {closure}() -->
|
||||||
|
<!-- init Fiber::suspend() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<suspend '%s'>
|
<suspend '%s'>
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
|
|
|
@ -39,14 +39,19 @@ $fiber->resume();
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%sobserver_fiber_03.php' -->
|
<!-- init '%s' -->
|
||||||
|
<!-- init Fiber::__construct() -->
|
||||||
|
<!-- init Fiber::start() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<init '%s'>
|
<init '%s'>
|
||||||
<!-- init {closure}() -->
|
<!-- init {closure}() -->
|
||||||
|
<!-- init Fiber::suspend() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<suspend '%s'>
|
<suspend '%s'>
|
||||||
|
<!-- init Fiber::resume() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<resume '%s'>
|
<resume '%s'>
|
||||||
|
<!-- init var_dump() -->
|
||||||
int(1)
|
int(1)
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<init '%s'>
|
<init '%s'>
|
||||||
|
|
|
@ -26,12 +26,16 @@ $fiber->resume();
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%sobserver_fiber_04.php' -->
|
<!-- init '%s' -->
|
||||||
|
<!-- init Fiber::__construct() -->
|
||||||
|
<!-- init Fiber::start() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<init '%s'>
|
<init '%s'>
|
||||||
<!-- init {closure}() -->
|
<!-- init {closure}() -->
|
||||||
|
<!-- init Fiber::suspend() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<suspend '%s'>
|
<suspend '%s'>
|
||||||
|
<!-- init Fiber::resume() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<resume '%s'>
|
<resume '%s'>
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
|
|
|
@ -25,12 +25,16 @@ $fiber->resume();
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%sobserver_fiber_05.php' -->
|
<!-- init '%s' -->
|
||||||
|
<!-- init Fiber::__construct() -->
|
||||||
|
<!-- init Fiber::start() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<init '%s'>
|
<init '%s'>
|
||||||
<!-- init {closure}() -->
|
<!-- init {closure}() -->
|
||||||
|
<!-- init Fiber::suspend() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<suspend '%s'>
|
<suspend '%s'>
|
||||||
|
<!-- init Fiber::resume() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<resume '%s'>
|
<resume '%s'>
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
|
|
|
@ -22,12 +22,17 @@ try {
|
||||||
|
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%sobserver_fiber_06.php' -->
|
<!-- init '%s' -->
|
||||||
|
<!-- init Fiber::__construct() -->
|
||||||
|
<!-- init Fiber::start() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<init '%s'>
|
<init '%s'>
|
||||||
<!-- init {closure}() -->
|
<!-- init {closure}() -->
|
||||||
|
<!-- init Fiber::suspend() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<suspend '%s'>
|
<suspend '%s'>
|
||||||
|
<!-- init Exception::__construct() -->
|
||||||
|
<!-- init Fiber::throw() -->
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
<resume '%s'>
|
<resume '%s'>
|
||||||
<!-- switching from fiber %s to %s -->
|
<!-- switching from fiber %s to %s -->
|
||||||
|
|
|
@ -28,8 +28,8 @@ function doSomething() {
|
||||||
echo doSomething() . PHP_EOL;
|
echo doSomething() . PHP_EOL;
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_generator_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<file '%s%eobserver_generator_%d.php'>
|
<file '%s'>
|
||||||
<!-- init doSomething() -->
|
<!-- init doSomething() -->
|
||||||
<doSomething>
|
<doSomething>
|
||||||
<!-- init getResults() -->
|
<!-- init getResults() -->
|
||||||
|
@ -44,7 +44,10 @@ echo doSomething() . PHP_EOL;
|
||||||
12
|
12
|
||||||
<getResults>
|
<getResults>
|
||||||
</getResults:1337>
|
</getResults:1337>
|
||||||
|
<!-- init Generator::getReturn() -->
|
||||||
|
<Generator::getReturn>
|
||||||
|
</Generator::getReturn:1337>
|
||||||
1337
|
1337
|
||||||
</doSomething:'Done'>
|
</doSomething:'Done'>
|
||||||
Done
|
Done
|
||||||
</file '%s%eobserver_generator_%d.php'>
|
</file '%s'>
|
||||||
|
|
|
@ -33,32 +33,87 @@ function doSomething() {
|
||||||
echo doSomething() . PHP_EOL;
|
echo doSomething() . PHP_EOL;
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_generator_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<file '%s%eobserver_generator_%d.php'>
|
<file '%s'>
|
||||||
<!-- init doSomething() -->
|
<!-- init doSomething() -->
|
||||||
<doSomething>
|
<doSomething>
|
||||||
<!-- init fooResults() -->
|
<!-- init Generator::current() -->
|
||||||
<fooResults>
|
<Generator::current>
|
||||||
|
<!-- init fooResults() -->
|
||||||
|
<fooResults>
|
||||||
Starting generator
|
Starting generator
|
||||||
</fooResults:0>
|
</fooResults:0>
|
||||||
|
</Generator::current:0>
|
||||||
|
<Generator::current>
|
||||||
|
</Generator::current:0>
|
||||||
0
|
0
|
||||||
<fooResults>
|
<Generator::current>
|
||||||
</fooResults:1>
|
</Generator::current:0>
|
||||||
|
<!-- init Generator::next() -->
|
||||||
|
<Generator::next>
|
||||||
|
<fooResults>
|
||||||
|
</fooResults:1>
|
||||||
|
</Generator::next:NULL>
|
||||||
|
<Generator::current>
|
||||||
|
</Generator::current:1>
|
||||||
|
<Generator::current>
|
||||||
|
</Generator::current:1>
|
||||||
1
|
1
|
||||||
<fooResults>
|
<Generator::current>
|
||||||
</fooResults:2>
|
</Generator::current:1>
|
||||||
|
<Generator::next>
|
||||||
|
<fooResults>
|
||||||
|
</fooResults:2>
|
||||||
|
</Generator::next:NULL>
|
||||||
|
<Generator::current>
|
||||||
|
</Generator::current:2>
|
||||||
|
<Generator::current>
|
||||||
|
</Generator::current:2>
|
||||||
2
|
2
|
||||||
<fooResults>
|
<Generator::current>
|
||||||
</fooResults:3>
|
</Generator::current:2>
|
||||||
|
<Generator::next>
|
||||||
|
<fooResults>
|
||||||
|
</fooResults:3>
|
||||||
|
</Generator::next:NULL>
|
||||||
|
<Generator::current>
|
||||||
|
</Generator::current:3>
|
||||||
|
<Generator::current>
|
||||||
|
</Generator::current:3>
|
||||||
3
|
3
|
||||||
<fooResults>
|
<Generator::current>
|
||||||
</fooResults:4>
|
</Generator::current:3>
|
||||||
|
<Generator::next>
|
||||||
|
<fooResults>
|
||||||
|
</fooResults:4>
|
||||||
|
</Generator::next:NULL>
|
||||||
|
<Generator::current>
|
||||||
|
</Generator::current:4>
|
||||||
|
<Generator::current>
|
||||||
|
</Generator::current:4>
|
||||||
4
|
4
|
||||||
<fooResults>
|
<Generator::current>
|
||||||
</fooResults:5>
|
</Generator::current:4>
|
||||||
|
<Generator::next>
|
||||||
|
<fooResults>
|
||||||
|
</fooResults:5>
|
||||||
|
</Generator::next:NULL>
|
||||||
|
<Generator::current>
|
||||||
|
</Generator::current:5>
|
||||||
|
<Generator::current>
|
||||||
|
</Generator::current:5>
|
||||||
5
|
5
|
||||||
<fooResults>
|
<Generator::current>
|
||||||
</fooResults:NULL>
|
</Generator::current:5>
|
||||||
|
<!-- init Generator::send() -->
|
||||||
|
<Generator::send>
|
||||||
|
<fooResults>
|
||||||
|
</fooResults:NULL>
|
||||||
|
</Generator::send:NULL>
|
||||||
|
<Generator::next>
|
||||||
|
</Generator::next:NULL>
|
||||||
|
<Generator::current>
|
||||||
|
</Generator::current:NULL>
|
||||||
</doSomething:'Done'>
|
</doSomething:'Done'>
|
||||||
Done
|
Done
|
||||||
</file '%s%eobserver_generator_%d.php'>
|
</file '%s'>
|
||||||
|
|
|
@ -26,8 +26,8 @@ function doSomething() {
|
||||||
echo doSomething() . PHP_EOL;
|
echo doSomething() . PHP_EOL;
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_generator_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<file '%s%eobserver_generator_%d.php'>
|
<file '%s'>
|
||||||
<!-- init doSomething() -->
|
<!-- init doSomething() -->
|
||||||
<doSomething>
|
<doSomething>
|
||||||
<!-- init fooResults() -->
|
<!-- init fooResults() -->
|
||||||
|
@ -38,12 +38,27 @@ echo doSomething() . PHP_EOL;
|
||||||
</fooResults:1>
|
</fooResults:1>
|
||||||
1
|
1
|
||||||
<fooResults>
|
<fooResults>
|
||||||
|
<!-- init Exception::__construct() -->
|
||||||
|
<Exception::__construct>
|
||||||
|
</Exception::__construct:NULL>
|
||||||
<!-- Exception: RuntimeException -->
|
<!-- Exception: RuntimeException -->
|
||||||
</fooResults:NULL>
|
</fooResults:NULL>
|
||||||
<!-- Exception: RuntimeException -->
|
<!-- Exception: RuntimeException -->
|
||||||
</doSomething:NULL>
|
</doSomething:NULL>
|
||||||
<!-- Exception: RuntimeException -->
|
<!-- Exception: RuntimeException -->
|
||||||
</file '%s%eobserver_generator_%d.php'>
|
</file '%s'>
|
||||||
|
<!-- init Exception::__toString() -->
|
||||||
|
<Exception::__toString>
|
||||||
|
<!-- init Exception::getTraceAsString() -->
|
||||||
|
<Exception::getTraceAsString>
|
||||||
|
</Exception::getTraceAsString:'#0 %s(%d): fooResults()
|
||||||
|
#1 %s(%d): doSomething()
|
||||||
|
#2 {main}'>
|
||||||
|
</Exception::__toString:'RuntimeException: Oops! in %s%eobserver_generator_%d.php:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 %s%eobserver_generator_%d.php(%d): fooResults()
|
||||||
|
#1 %s%eobserver_generator_%d.php(%d): doSomething()
|
||||||
|
#2 {main}'>
|
||||||
|
|
||||||
Fatal error: Uncaught RuntimeException: Oops! in %s%eobserver_generator_%d.php:%d
|
Fatal error: Uncaught RuntimeException: Oops! in %s%eobserver_generator_%d.php:%d
|
||||||
Stack trace:
|
Stack trace:
|
||||||
|
|
|
@ -20,9 +20,9 @@ echo array_sum([1,2,3]) . PHP_EOL;
|
||||||
foo();
|
foo();
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_opline_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<!-- opcode: 'ZEND_INIT_FCALL' -->
|
<!-- opcode: 'ZEND_INIT_FCALL' -->
|
||||||
<file '%s%eobserver_opline_%d.php'>
|
<file '%s'>
|
||||||
<!-- opcode: 'ZEND_INIT_FCALL' -->
|
<!-- opcode: 'ZEND_INIT_FCALL' -->
|
||||||
<!-- init foo() -->
|
<!-- init foo() -->
|
||||||
<!-- opcode: 'ZEND_ECHO' -->
|
<!-- opcode: 'ZEND_ECHO' -->
|
||||||
|
@ -31,9 +31,9 @@ foo();
|
||||||
Foo
|
Foo
|
||||||
<!-- opcode: 'ZEND_RETURN' -->
|
<!-- opcode: 'ZEND_RETURN' -->
|
||||||
</foo>
|
</foo>
|
||||||
<!-- init '%s%eobserver.inc' -->
|
<!-- init '%s' -->
|
||||||
<!-- opcode: 'ZEND_INIT_FCALL' -->
|
<!-- opcode: 'ZEND_INIT_FCALL' -->
|
||||||
<file '%s%eobserver.inc'>
|
<file '%s'>
|
||||||
<!-- opcode: 'ZEND_INIT_FCALL' -->
|
<!-- opcode: 'ZEND_INIT_FCALL' -->
|
||||||
<!-- init foo_observer_test() -->
|
<!-- init foo_observer_test() -->
|
||||||
<!-- opcode: 'ZEND_ECHO' -->
|
<!-- opcode: 'ZEND_ECHO' -->
|
||||||
|
@ -43,7 +43,13 @@ foo_observer_test
|
||||||
<!-- opcode: 'ZEND_RETURN' -->
|
<!-- opcode: 'ZEND_RETURN' -->
|
||||||
</foo_observer_test>
|
</foo_observer_test>
|
||||||
<!-- opcode: 'ZEND_RETURN' -->
|
<!-- opcode: 'ZEND_RETURN' -->
|
||||||
</file '%s%eobserver.inc'>
|
</file '%s'>
|
||||||
|
<!-- init array_sum() -->
|
||||||
|
<!-- opcode: 'ZEND_RETURN' -->
|
||||||
|
<array_sum>
|
||||||
|
<!-- opcode: 'ZEND_RETURN' -->
|
||||||
|
<!-- opcode: 'ZEND_RETURN' -->
|
||||||
|
</array_sum>
|
||||||
6
|
6
|
||||||
<foo>
|
<foo>
|
||||||
<!-- opcode: 'ZEND_ECHO' -->
|
<!-- opcode: 'ZEND_ECHO' -->
|
||||||
|
@ -51,4 +57,4 @@ Foo
|
||||||
<!-- opcode: 'ZEND_RETURN' -->
|
<!-- opcode: 'ZEND_RETURN' -->
|
||||||
</foo>
|
</foo>
|
||||||
<!-- opcode: 'ZEND_RETURN' -->
|
<!-- opcode: 'ZEND_RETURN' -->
|
||||||
</file '%s%eobserver_opline_%d.php'>
|
</file '%s'>
|
||||||
|
|
|
@ -21,12 +21,20 @@ $gen->current();
|
||||||
echo 'Done' . PHP_EOL;
|
echo 'Done' . PHP_EOL;
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_retval_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<file '%s%eobserver_retval_%d.php'>
|
<file '%s'>
|
||||||
<!-- init foo() -->
|
<!-- init Generator::current() -->
|
||||||
<foo>
|
<Generator::current>
|
||||||
</foo:'I should be observable'>
|
<!-- init foo() -->
|
||||||
<foo>
|
<foo>
|
||||||
</foo:'Me too!'>
|
</foo:'I should be observable'>
|
||||||
|
</Generator::current:'I should be observable'>
|
||||||
|
<!-- init Generator::next() -->
|
||||||
|
<Generator::next>
|
||||||
|
<foo>
|
||||||
|
</foo:'Me too!'>
|
||||||
|
</Generator::next:NULL>
|
||||||
|
<Generator::current>
|
||||||
|
</Generator::current:'Me too!'>
|
||||||
Done
|
Done
|
||||||
</file '%s%eobserver_retval_%d.php'>
|
</file '%s'>
|
||||||
|
|
|
@ -24,13 +24,16 @@ function foo() {
|
||||||
echo 'Done: ' . bar(40) . PHP_EOL;
|
echo 'Done: ' . bar(40) . PHP_EOL;
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_shutdown_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<file '%s%eobserver_shutdown_%d.php'>
|
<file '%s'>
|
||||||
|
<!-- init register_shutdown_function() -->
|
||||||
|
<register_shutdown_function>
|
||||||
|
</register_shutdown_function:NULL>
|
||||||
<!-- init bar() -->
|
<!-- init bar() -->
|
||||||
<bar>
|
<bar>
|
||||||
</bar:40>
|
</bar:40>
|
||||||
Done: 40
|
Done: 40
|
||||||
</file '%s%eobserver_shutdown_%d.php'>
|
</file '%s'>
|
||||||
<!-- init {closure}() -->
|
<!-- init {closure}() -->
|
||||||
<{closure}>
|
<{closure}>
|
||||||
<!-- init foo() -->
|
<!-- init foo() -->
|
||||||
|
|
|
@ -12,14 +12,24 @@ function foo(array $a) { return 1; }
|
||||||
foo(42);
|
foo(42);
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_types_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<file '%s%eobserver_types_%d.php'>
|
<file '%s'>
|
||||||
<!-- init foo() -->
|
<!-- init foo() -->
|
||||||
<foo>
|
<foo>
|
||||||
<!-- Exception: TypeError -->
|
<!-- Exception: TypeError -->
|
||||||
</foo:NULL>
|
</foo:NULL>
|
||||||
<!-- Exception: TypeError -->
|
<!-- Exception: TypeError -->
|
||||||
</file '%s%eobserver_types_%d.php'>
|
</file '%s'>
|
||||||
|
<!-- init Error::__toString() -->
|
||||||
|
<Error::__toString>
|
||||||
|
<!-- init Error::getTraceAsString() -->
|
||||||
|
<Error::getTraceAsString>
|
||||||
|
</Error::getTraceAsString:'#0 %s(%d): foo(42)
|
||||||
|
#1 {main}'>
|
||||||
|
</Error::__toString:'TypeError: foo(): Argument #1 ($a) must be of type array, int given, called in %s:%d
|
||||||
|
Stack trace:
|
||||||
|
#0 %s%eobserver_types_%d.php(%d): foo(42)
|
||||||
|
#1 {main}'>
|
||||||
|
|
||||||
Fatal error: Uncaught TypeError: foo(): Argument #1 ($a) must be of type array, int given, called in %s:%d
|
Fatal error: Uncaught TypeError: foo(): Argument #1 ($a) must be of type array, int given, called in %s:%d
|
||||||
Stack trace:
|
Stack trace:
|
||||||
|
|
|
@ -18,19 +18,25 @@ var_dump(array_reduce($a, 'sum'));
|
||||||
echo 'Done' . PHP_EOL;
|
echo 'Done' . PHP_EOL;
|
||||||
?>
|
?>
|
||||||
--EXPECTF--
|
--EXPECTF--
|
||||||
<!-- init '%s%eobserver_zend_call_function_%d.php' -->
|
<!-- init '%s' -->
|
||||||
<file '%s%eobserver_zend_call_function_%d.php'>
|
<file '%s'>
|
||||||
<!-- init sum() -->
|
<!-- init array_reduce() -->
|
||||||
<sum>
|
<array_reduce>
|
||||||
</sum>
|
<!-- init sum() -->
|
||||||
<sum>
|
<sum>
|
||||||
</sum>
|
</sum>
|
||||||
<sum>
|
<sum>
|
||||||
</sum>
|
</sum>
|
||||||
<sum>
|
<sum>
|
||||||
</sum>
|
</sum>
|
||||||
<sum>
|
<sum>
|
||||||
</sum>
|
</sum>
|
||||||
|
<sum>
|
||||||
|
</sum>
|
||||||
|
</array_reduce>
|
||||||
|
<!-- init var_dump() -->
|
||||||
|
<var_dump>
|
||||||
int(15)
|
int(15)
|
||||||
|
</var_dump>
|
||||||
Done
|
Done
|
||||||
</file '%s%eobserver_zend_call_function_%d.php'>
|
</file '%s'>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue