From d5d31ea3b32a75697bb2c2ee95acedd29ef69708 Mon Sep 17 00:00:00 2001 From: Dmitry Stogov Date: Fri, 18 Sep 2020 12:55:58 +0300 Subject: [PATCH] Cleanup observer API and add JIT support --- Zend/zend_execute_API.c | 4 +- Zend/zend_generators.c | 13 +-- Zend/zend_observer.c | 128 ++++++++++++++++------- Zend/zend_observer.h | 90 +++++----------- Zend/zend_vm_def.h | 22 ++-- Zend/zend_vm_execute.h | 24 ++--- Zend/zend_vm_execute.skl | 4 +- Zend/zend_vm_gen.php | 10 +- ext/opcache/ZendAccelerator.c | 10 -- ext/opcache/jit/zend_jit.c | 1 + ext/opcache/jit/zend_jit_x86.dasc | 19 ++++ ext/zend_test/test.c | 12 +-- ext/zend_test/tests/observer_jit_01.phpt | 25 ----- 13 files changed, 170 insertions(+), 192 deletions(-) delete mode 100644 ext/zend_test/tests/observer_jit_01.phpt diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 030455a94e..7572a0d890 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -891,9 +891,7 @@ cleanup_args: uint32_t orig_jit_trace_num = EG(jit_trace_num); zend_init_func_execute_data(call, &func->op_array, fci->retval); - if (ZEND_OBSERVER_ENABLED) { - zend_observer_maybe_fcall_call_begin(call); - } + ZEND_OBSERVER_FCALL_BEGIN(call); zend_execute_ex(call); EG(jit_trace_num) = orig_jit_trace_num; EG(opline_before_exception) = current_opline_before_exception; diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index baca12f66b..4e2351869d 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -859,20 +859,11 @@ try_again: if (!ZEND_OBSERVER_ENABLED) { zend_execute_ex(generator->execute_data); } else { - zend_op_array *op_array = &generator->execute_data->func->op_array; - void *observer_handlers = ZEND_OBSERVER_HANDLERS(op_array); - if (!observer_handlers) { - zend_observer_fcall_install((zend_function *)op_array); - observer_handlers = ZEND_OBSERVER_HANDLERS(op_array); - } - ZEND_ASSERT(observer_handlers); - if (observer_handlers != ZEND_OBSERVER_NOT_OBSERVED) { - zend_observe_fcall_begin(observer_handlers, generator->execute_data); - } + zend_observer_generator_resume(generator->execute_data); zend_execute_ex(generator->execute_data); if (generator->execute_data) { /* On the final return, this will be called from ZEND_GENERATOR_RETURN */ - zend_observer_maybe_fcall_call_end(generator->execute_data, &generator->value); + zend_observer_fcall_end(generator->execute_data, &generator->value); } } generator->flags &= ~ZEND_GENERATOR_CURRENTLY_RUNNING; diff --git a/Zend/zend_observer.c b/Zend/zend_observer.c index b124de5cc3..5544039c3e 100644 --- a/Zend/zend_observer.c +++ b/Zend/zend_observer.c @@ -23,6 +23,21 @@ #include "zend_llist.h" #include "zend_vm.h" +#define ZEND_OBSERVER_DATA(op_array) \ + ZEND_OP_ARRAY_EXTENSION(op_array, zend_observer_fcall_op_array_extension) + +#define ZEND_OBSERVER_NOT_OBSERVED ((void *) 2) + +#define ZEND_OBSERVABLE_FN(fn_flags) \ + (!(fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_FAKE_CLOSURE))) + +typedef struct _zend_observer_fcall_data { + // points after the last handler + zend_observer_fcall_handlers *end; + // a variadic array using "struct hack" + zend_observer_fcall_handlers handlers[1]; +} zend_observer_fcall_data; + zend_llist zend_observers_fcall_list; zend_llist zend_observer_error_callbacks; @@ -30,12 +45,6 @@ int zend_observer_fcall_op_array_extension = -1; ZEND_TLS zend_arena *fcall_handlers_arena = NULL; -ZEND_API extern inline void zend_observer_maybe_fcall_call_begin( - zend_execute_data *execute_data); -ZEND_API extern inline void zend_observer_maybe_fcall_call_end( - zend_execute_data *execute_data, - zval *return_value); - // Call during minit/startup ONLY ZEND_API void zend_observer_fcall_register(zend_observer_fcall_init init) { /* We don't want to get an extension handle unless an ext installs an observer */ @@ -80,7 +89,7 @@ ZEND_API void zend_observer_shutdown(void) { zend_llist_destroy(&zend_observer_error_callbacks); } -ZEND_API void zend_observer_fcall_install(zend_function *function) { +static void zend_observer_fcall_install(zend_function *function) { zend_llist_element *element; zend_llist *list = &zend_observers_fcall_list; zend_op_array *op_array = &function->op_array; @@ -92,11 +101,11 @@ ZEND_API void zend_observer_fcall_install(zend_function *function) { ZEND_ASSERT(function->type != ZEND_INTERNAL_FUNCTION); zend_llist handlers_list; - zend_llist_init(&handlers_list, sizeof(zend_observer_fcall), NULL, 0); + zend_llist_init(&handlers_list, sizeof(zend_observer_fcall_handlers), NULL, 0); for (element = list->head; element; element = element->next) { zend_observer_fcall_init init; memcpy(&init, element->data, sizeof init); - zend_observer_fcall handlers = init(function); + zend_observer_fcall_handlers handlers = init(function); if (handlers.begin || handlers.end) { zend_llist_add_element(&handlers_list, &handlers); } @@ -105,58 +114,97 @@ ZEND_API void zend_observer_fcall_install(zend_function *function) { ZEND_ASSERT(RUN_TIME_CACHE(op_array)); void *ext; if (handlers_list.count) { - size_t size = sizeof(zend_observer_fcall_cache) + (handlers_list.count - 1) * sizeof(zend_observer_fcall); - zend_observer_fcall_cache *cache = zend_arena_alloc(&fcall_handlers_arena, size); - zend_observer_fcall *handler = cache->handlers; + size_t size = sizeof(zend_observer_fcall_data) + (handlers_list.count - 1) * sizeof(zend_observer_fcall_handlers); + zend_observer_fcall_data *fcall_data = zend_arena_alloc(&fcall_handlers_arena, size); + zend_observer_fcall_handlers *handlers = fcall_data->handlers; for (element = handlers_list.head; element; element = element->next) { - memcpy(handler++, element->data, sizeof *handler); + memcpy(handlers++, element->data, sizeof *handlers); } - cache->end = handler; - ext = cache; + fcall_data->end = handlers; + ext = fcall_data; } else { ext = ZEND_OBSERVER_NOT_OBSERVED; } - ZEND_OBSERVER_HANDLERS(op_array) = ext; + ZEND_OBSERVER_DATA(op_array) = ext; zend_llist_destroy(&handlers_list); } -ZEND_API void zend_observe_fcall_begin( - zend_observer_fcall_cache *cache, - zend_execute_data *execute_data) +static void ZEND_FASTCALL _zend_observe_fcall_begin(zend_execute_data *execute_data) { - zend_observer_fcall *handler, *end = cache->end; - for (handler = cache->handlers; handler != end; ++handler) { - if (handler->begin) { - handler->begin(execute_data); + zend_op_array *op_array; + uint32_t fn_flags; + zend_observer_fcall_data *fcall_data; + zend_observer_fcall_handlers *handlers, *end; + + if (!ZEND_OBSERVER_ENABLED) { + return; + } + + op_array = &execute_data->func->op_array; + fn_flags = op_array->fn_flags; + + if (!ZEND_OBSERVABLE_FN(fn_flags)) { + return; + } + + fcall_data = ZEND_OBSERVER_DATA(op_array); + if (!fcall_data) { + zend_observer_fcall_install((zend_function *)op_array); + fcall_data = ZEND_OBSERVER_DATA(op_array); + } + + ZEND_ASSERT(fcall_data); + if (fcall_data == ZEND_OBSERVER_NOT_OBSERVED) { + return; + } + + end = fcall_data->end; + for (handlers = fcall_data->handlers; handlers != end; ++handlers) { + if (handlers->begin) { + handlers->begin(execute_data); } } } -ZEND_API void zend_observer_fcall_call_end_helper( - zend_execute_data *execute_data, - zval *return_value) +ZEND_API void ZEND_FASTCALL zend_observer_generator_resume(zend_execute_data *execute_data) { - zend_function *func = execute_data->func; - ZEND_ASSUME(ZEND_OBSERVABLE_FN(func->common.fn_flags)); - void *observer_handlers = ZEND_OBSERVER_HANDLERS(&func->op_array); - // TODO: Fix exceptions from generators - // ZEND_ASSERT(observer_handlers); - if (observer_handlers && observer_handlers != ZEND_OBSERVER_NOT_OBSERVED) { - zend_observer_fcall_cache *cache = observer_handlers; - zend_observe_fcall_end(cache, execute_data, return_value); + _zend_observe_fcall_begin(execute_data); +} + +ZEND_API void ZEND_FASTCALL zend_observer_fcall_begin(zend_execute_data *execute_data) +{ + ZEND_ASSUME(execute_data->func); + if (!(execute_data->func->common.fn_flags & ZEND_ACC_GENERATOR)) { + _zend_observe_fcall_begin(execute_data); } } -ZEND_API void zend_observe_fcall_end( - zend_observer_fcall_cache *cache, +ZEND_API void ZEND_FASTCALL zend_observer_fcall_end( zend_execute_data *execute_data, zval *return_value) { - zend_observer_fcall *handler = cache->end, *end = cache->handlers; - while (handler-- != end) { - if (handler->end) { - handler->end(execute_data, return_value); + zend_function *func = execute_data->func; + zend_observer_fcall_data *fcall_data; + zend_observer_fcall_handlers *handlers, *end; + + if (!ZEND_OBSERVER_ENABLED + || !ZEND_OBSERVABLE_FN(func->common.fn_flags)) { + return; + } + + fcall_data = (zend_observer_fcall_data*)ZEND_OBSERVER_DATA(&func->op_array); + // TODO: Fix exceptions from generators + // ZEND_ASSERT(fcall_data); + if (!fcall_data || fcall_data == ZEND_OBSERVER_NOT_OBSERVED) { + return; + } + + handlers = fcall_data->end; + end = fcall_data->handlers; + while (handlers-- != end) { + if (handlers->end) { + handlers->end(execute_data, return_value); } } } diff --git a/Zend/zend_observer.h b/Zend/zend_observer.h index 0603591c53..246a3a61be 100644 --- a/Zend/zend_observer.h +++ b/Zend/zend_observer.h @@ -29,87 +29,47 @@ extern ZEND_API int zend_observer_fcall_op_array_extension; #define ZEND_OBSERVER_ENABLED (zend_observer_fcall_op_array_extension != -1) -#define ZEND_OBSERVER_HANDLERS(op_array) \ - ZEND_OP_ARRAY_EXTENSION(op_array, zend_observer_fcall_op_array_extension) - -#define ZEND_OBSERVER_NOT_OBSERVED ((void *) 2) - -#define ZEND_OBSERVABLE_FN(fn_flags) \ - (ZEND_OBSERVER_ENABLED && \ - !(fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_FAKE_CLOSURE))) - -struct zend_observer_fcall { - void (*begin)(zend_execute_data *execute_data); - void (*end)(zend_execute_data *execute_data, zval *retval); -}; -typedef struct zend_observer_fcall zend_observer_fcall; - -struct zend_observer_fcall_cache { - // points after the last handler - zend_observer_fcall *end; - // a variadic array using "struct hack" - zend_observer_fcall handlers[1]; -}; -typedef struct zend_observer_fcall_cache zend_observer_fcall_cache; +#define ZEND_OBSERVER_FCALL_BEGIN(execute_data) do { \ + if (ZEND_OBSERVER_ENABLED) { \ + zend_observer_fcall_begin(execute_data); \ + } \ + } while (0) + +#define ZEND_OBSERVER_FCALL_END(execute_data, return_value) do { \ + if (ZEND_OBSERVER_ENABLED) { \ + zend_observer_fcall_end(execute_data, return_value); \ + } \ + } while (0) + +typedef void (*zend_observer_fcall_begin_handler)(zend_execute_data *execute_data); +typedef void (*zend_observer_fcall_end_handler)(zend_execute_data *execute_data, zval *retval); + +typedef struct _zend_observer_fcall_handlers { + zend_observer_fcall_begin_handler begin; + zend_observer_fcall_end_handler end; +} zend_observer_fcall_handlers; /* If the fn should not be observed then return {NULL, NULL} */ -typedef zend_observer_fcall(*zend_observer_fcall_init)(zend_function *func); +typedef zend_observer_fcall_handlers (*zend_observer_fcall_init)(zend_function *func); // Call during minit/startup ONLY -ZEND_API void zend_observer_fcall_register(zend_observer_fcall_init init); +ZEND_API void zend_observer_fcall_register(zend_observer_fcall_init); ZEND_API void zend_observer_startup(void); // Called by engine before MINITs ZEND_API void zend_observer_activate(void); ZEND_API void zend_observer_deactivate(void); ZEND_API void zend_observer_shutdown(void); -ZEND_API void zend_observer_fcall_install(zend_function *function); - -ZEND_API void zend_observe_fcall_begin( - zend_observer_fcall_cache *cache, +ZEND_API void ZEND_FASTCALL zend_observer_fcall_begin( zend_execute_data *execute_data); -ZEND_API void zend_observe_fcall_end( - zend_observer_fcall_cache *cache, - zend_execute_data *execute_data, - zval *return_value); +ZEND_API void ZEND_FASTCALL zend_observer_generator_resume( + zend_execute_data *execute_data); -ZEND_API void zend_observer_fcall_call_end_helper( +ZEND_API void ZEND_FASTCALL zend_observer_fcall_end( zend_execute_data *execute_data, zval *return_value); -ZEND_API zend_always_inline void zend_observer_maybe_fcall_call_begin( - zend_execute_data *execute_data) -{ - ZEND_ASSUME(execute_data->func); - zend_op_array *op_array = &execute_data->func->op_array; - uint32_t fn_flags = op_array->fn_flags; - if (ZEND_OBSERVABLE_FN(fn_flags) && !(fn_flags & ZEND_ACC_GENERATOR)) { - void *observer_handlers = ZEND_OBSERVER_HANDLERS(op_array); - if (!observer_handlers) { - zend_observer_fcall_install((zend_function *)op_array); - observer_handlers = ZEND_OBSERVER_HANDLERS(op_array); - } - - ZEND_ASSERT(observer_handlers); - if (observer_handlers != ZEND_OBSERVER_NOT_OBSERVED) { - zend_observe_fcall_begin( - (zend_observer_fcall_cache *)observer_handlers, - execute_data); - } - } -} - -ZEND_API zend_always_inline void zend_observer_maybe_fcall_call_end( - zend_execute_data *execute_data, - zval *return_value) -{ - zend_function *func = execute_data->func; - if (ZEND_OBSERVABLE_FN(func->common.fn_flags)) { - zend_observer_fcall_call_end_helper(execute_data, return_value); - } -} - typedef void (*zend_observer_error_cb)(int type, const char *error_filename, uint32_t error_lineno, zend_string *message); ZEND_API void zend_observer_error_register(zend_observer_error_cb callback); diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 6af78eb3ae..510595b7c8 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -3956,7 +3956,7 @@ ZEND_VM_HOT_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL,OBSERVER)) call->prev_execute_data = execute_data; execute_data = call; i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); - OBSERVER_FCALL_BEGIN_HANDLERS(execute_data); + ZEND_OBSERVER_FCALL_BEGIN(execute_data); LOAD_OPLINE_EX(); ZEND_VM_ENTER_EX(); @@ -3981,14 +3981,14 @@ ZEND_VM_HOT_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL,OBSERVER)) call->prev_execute_data = execute_data; execute_data = call; i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); - OBSERVER_FCALL_BEGIN_HANDLERS(execute_data); + ZEND_OBSERVER_FCALL_BEGIN(execute_data); LOAD_OPLINE_EX(); ZEND_VM_ENTER_EX(); } else { zval retval; ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); - if (IS_OBSERVER) { + if (ZEND_OBSERVER_ENABLED) { ret = NULL; } @@ -4075,7 +4075,7 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER)) call->prev_execute_data = execute_data; execute_data = call; i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC); - OBSERVER_FCALL_BEGIN_HANDLERS(execute_data); + ZEND_OBSERVER_FCALL_BEGIN(execute_data); if (EXPECTED(zend_execute_ex == execute_ex)) { LOAD_OPLINE_EX(); @@ -4090,7 +4090,7 @@ ZEND_VM_HOT_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL,OBSERVER)) } else { zval retval; ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); - if (IS_OBSERVER) { + if (ZEND_OBSERVER_ENABLED) { ret = NULL; } @@ -4296,7 +4296,7 @@ ZEND_VM_INLINE_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER)) } } } - OBSERVER_FCALL_END_HANDLERS(execute_data, return_value); + ZEND_OBSERVER_FCALL_END(execute_data, return_value); ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); } @@ -4357,7 +4357,7 @@ ZEND_VM_COLD_CONST_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC, FREE_OP1_VAR_PTR(); } while (0); - OBSERVER_FCALL_END_HANDLERS(execute_data, EX(return_value)); + ZEND_OBSERVER_FCALL_END(execute_data, EX(return_value)); ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper); } @@ -4473,7 +4473,7 @@ ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, CONST|TMP|VAR|CV, ANY, SPEC(OBSERVER } } - OBSERVER_FCALL_END_HANDLERS(generator->execute_data, &generator->retval); + ZEND_OBSERVER_FCALL_END(generator->execute_data, &generator->retval); /* Close the generator to free up resources */ zend_generator_close(generator, 1); @@ -6191,7 +6191,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL, SPEC(OBSER call->prev_execute_data = execute_data; i_init_code_execute_data(call, new_op_array, return_value); - OBSERVER_FCALL_BEGIN_HANDLERS(call); + ZEND_OBSERVER_FCALL_BEGIN(call); if (EXPECTED(zend_execute_ex == execute_ex)) { FREE_OP1(); ZEND_VM_ENTER(); @@ -7731,7 +7731,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY, SPEC(OBSERVER)) } } - OBSERVER_FCALL_END_HANDLERS(execute_data, EX(return_value)); + ZEND_OBSERVER_FCALL_END(execute_data, EX(return_value)); cleanup_unfinished_calls(execute_data, throw_op_num); if (throw_op->result_type & (IS_VAR | IS_TMP_VAR)) { @@ -8493,7 +8493,7 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY, SPEC(OBSERVER)) } execute_data = call; i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); - OBSERVER_FCALL_BEGIN_HANDLERS(execute_data); + ZEND_OBSERVER_FCALL_BEGIN(execute_data); if (EXPECTED(zend_execute_ex == execute_ex)) { LOAD_OPLINE_EX(); ZEND_VM_ENTER_EX(); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index a6feaf02e0..f59c923bd1 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -1398,7 +1398,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_OBS call->prev_execute_data = execute_data; execute_data = call; i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); - zend_observer_maybe_fcall_call_begin(execute_data); + zend_observer_fcall_begin(execute_data); LOAD_OPLINE_EX(); ZEND_VM_ENTER_EX(); @@ -1611,7 +1611,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_ call->prev_execute_data = execute_data; execute_data = call; i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); - zend_observer_maybe_fcall_call_begin(execute_data); + zend_observer_fcall_begin(execute_data); LOAD_OPLINE_EX(); ZEND_VM_ENTER_EX(); @@ -1915,7 +1915,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_OBS call->prev_execute_data = execute_data; execute_data = call; i_init_func_execute_data(&fbc->op_array, ret, 1 EXECUTE_DATA_CC); - zend_observer_maybe_fcall_call_begin(execute_data); + zend_observer_fcall_begin(execute_data); if (EXPECTED(zend_execute_ex == execute_ex)) { LOAD_OPLINE_EX(); @@ -2991,7 +2991,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_OBSERVER } } - zend_observer_maybe_fcall_call_end(execute_data, EX(return_value)); + zend_observer_fcall_end(execute_data, EX(return_value)); cleanup_unfinished_calls(execute_data, throw_op_num); if (throw_op->result_type & (IS_VAR | IS_TMP_VAR)) { @@ -3322,7 +3322,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_OBSERVER_ } execute_data = call; i_init_func_execute_data(&fbc->op_array, ret, 0 EXECUTE_DATA_CC); - zend_observer_maybe_fcall_call_begin(execute_data); + zend_observer_fcall_begin(execute_data); if (EXPECTED(zend_execute_ex == execute_ex)) { LOAD_OPLINE_EX(); ZEND_VM_ENTER_EX(); @@ -4193,7 +4193,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_OBSER } } } - zend_observer_maybe_fcall_call_end(execute_data, return_value); + zend_observer_fcall_end(execute_data, return_value); ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -4313,7 +4313,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPE if (opline->op1_type == IS_VAR) {zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));}; } while (0); - zend_observer_maybe_fcall_call_end(execute_data, EX(return_value)); + zend_observer_fcall_end(execute_data, EX(return_value)); ZEND_VM_TAIL_CALL(zend_leave_helper_SPEC(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); } @@ -4396,7 +4396,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_OBSERVER } } - zend_observer_maybe_fcall_call_end(generator->execute_data, &generator->retval); + zend_observer_fcall_end(generator->execute_data, &generator->retval); /* Close the generator to free up resources */ zend_generator_close(generator, 1); @@ -4800,7 +4800,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_OBSERVER_ call->prev_execute_data = execute_data; i_init_code_execute_data(call, new_op_array, return_value); - zend_observer_maybe_fcall_call_begin(call); + zend_observer_fcall_begin(call); if (EXPECTED(zend_execute_ex == execute_ex)) { FREE_OP(opline->op1_type, opline->op1.var); ZEND_VM_ENTER(); @@ -54806,7 +54806,7 @@ zend_leave_helper_SPEC_LABEL: } } } - zend_observer_maybe_fcall_call_end(execute_data, return_value); + zend_observer_fcall_end(execute_data, return_value); goto zend_leave_helper_SPEC_LABEL; } @@ -58782,9 +58782,7 @@ ZEND_API void zend_execute(zend_op_array *op_array, zval *return_value) } EX(prev_execute_data) = EG(current_execute_data); i_init_code_execute_data(execute_data, op_array, return_value); - if (ZEND_OBSERVER_ENABLED) { - zend_observer_maybe_fcall_call_begin(execute_data); - } + ZEND_OBSERVER_FCALL_BEGIN(execute_data); zend_execute_ex(execute_data); /* Observer end handlers are called from ZEND_RETURN */ zend_vm_stack_free_call_frame(execute_data); diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 22911760e4..582ec490e2 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -55,9 +55,7 @@ ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value } EX(prev_execute_data) = EG(current_execute_data); i_init_code_execute_data(execute_data, op_array, return_value); - if (ZEND_OBSERVER_ENABLED) { - zend_observer_maybe_fcall_call_begin(execute_data); - } + ZEND_OBSERVER_FCALL_BEGIN(execute_data); zend_{%EXECUTOR_NAME%}_ex(execute_data); /* Observer end handlers are called from ZEND_RETURN */ zend_vm_stack_free_call_frame(execute_data); diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index e3dceaa829..3346a59cfa 100755 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -793,12 +793,12 @@ function gen_code($f, $spec, $kind, $code, $op1, $op2, $name, $extra_spec=null) "/opline->extended_value\s*&\s*~\s*ZEND_ISEMPTY/" => isset($extra_spec['ISSET']) ? ($extra_spec['ISSET'] == 0 ? "\\0" : "opline->extended_value") : "\\0", - "/IS_OBSERVER/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "1" : "0", - "/OBSERVER_FCALL_BEGIN_HANDLERS\(\s*(.*)\s*\)/" => isset($extra_spec['OBSERVER']) ? - ($extra_spec['OBSERVER'] == 0 ? "" : "zend_observer_maybe_fcall_call_begin(\\1)") + "/ZEND_OBSERVER_ENABLED/" => isset($extra_spec['OBSERVER']) && $extra_spec['OBSERVER'] == 1 ? "1" : "0", + "/ZEND_OBSERVER_FCALL_BEGIN\(\s*(.*)\s*\)/" => isset($extra_spec['OBSERVER']) ? + ($extra_spec['OBSERVER'] == 0 ? "" : "zend_observer_fcall_begin(\\1)") : "", - "/OBSERVER_FCALL_END_HANDLERS\(\s*([^,]*)\s*,\s*(.*)\s*\)/" => isset($extra_spec['OBSERVER']) ? - ($extra_spec['OBSERVER'] == 0 ? "" : "zend_observer_maybe_fcall_call_end(\\1, \\2)") + "/ZEND_OBSERVER_FCALL_END\(\s*([^,]*)\s*,\s*(.*)\s*\)/" => isset($extra_spec['OBSERVER']) ? + ($extra_spec['OBSERVER'] == 0 ? "" : "zend_observer_fcall_end(\\1, \\2)") : "", ); $code = preg_replace(array_keys($specialized_replacements), array_values($specialized_replacements), $code); diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index 46363acb7b..71af3203dc 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -44,7 +44,6 @@ #include "zend_accelerator_util_funcs.h" #include "zend_accelerator_hash.h" #include "zend_file_cache.h" -#include "zend_observer.h" #include "ext/pcre/php_pcre.h" #include "ext/standard/md5.h" #include "ext/hash/php_hash.h" @@ -2998,15 +2997,6 @@ static zend_result accel_post_startup(void) } } -#ifdef HAVE_JIT - /* TODO Observer support for JIT */ - if (ZEND_OBSERVER_ENABLED) { - JIT_G(enabled) = 0; - JIT_G(on) = 0; - zend_accel_error(ACCEL_LOG_INFO, "Observer extension present. Disabling JIT."); - } -#endif - /* Initialize zend_func_info_rid */ zend_optimizer_startup(); diff --git a/ext/opcache/jit/zend_jit.c b/ext/opcache/jit/zend_jit.c index 3dad8e4f91..094f4d56d6 100644 --- a/ext/opcache/jit/zend_jit.c +++ b/ext/opcache/jit/zend_jit.c @@ -24,6 +24,7 @@ #include "Zend/zend_constants.h" #include "Zend/zend_closures.h" #include "Zend/zend_ini.h" +#include "Zend/zend_observer.h" #include "zend_smart_str.h" #include "jit/zend_jit.h" diff --git a/ext/opcache/jit/zend_jit_x86.dasc b/ext/opcache/jit/zend_jit_x86.dasc index daff6fb641..c689359272 100644 --- a/ext/opcache/jit/zend_jit_x86.dasc +++ b/ext/opcache/jit/zend_jit_x86.dasc @@ -9689,6 +9689,10 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend if (!trace && op_array == &func->op_array) { /* recursive call */ + if (ZEND_OBSERVER_ENABLED) { + | mov FCARG1a, FP + | EXT_CALL zend_observer_fcall_begin, r0 + } #ifdef CONTEXT_THREADED_JIT | call >1 |.cold_code @@ -9793,6 +9797,11 @@ static int zend_jit_do_fcall(dasm_State **Dst, const zend_op *opline, const zend |3: } + if (ZEND_OBSERVER_ENABLED) { + | mov FCARG1a, FP + | EXT_CALL zend_observer_fcall_begin, r0 + } + if (trace) { if (!func && (opline->opcode != ZEND_DO_UCALL)) { | jmp >9 @@ -11170,6 +11179,11 @@ static int zend_jit_return(dasm_State **Dst, const zend_op *opline, const zend_o if (return_value_used == 0) { |9: + if (ZEND_OBSERVER_ENABLED) { + | xor FCARG2a, FCARG2a + | mov FCARG1a, FP + | EXT_CALL zend_observer_fcall_end, r0 + } return 1; } @@ -11232,6 +11246,11 @@ static int zend_jit_return(dasm_State **Dst, const zend_op *opline, const zend_o } |9: + if (ZEND_OBSERVER_ENABLED) { + | LOAD_ZVAL_ADDR FCARG2a, ret_addr + | mov FCARG1a, FP + | EXT_CALL zend_observer_fcall_end, r0 + } return 1; } diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 0e4040d1bd..4ca98a3c08 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -317,7 +317,7 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("zend_test.observer.show_return_value", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_return_value, zend_zend_test_globals, zend_test_globals) PHP_INI_END() -static zend_observer_fcall observer_fcall_init(zend_function *fbc); +static zend_observer_fcall_handlers observer_fcall_init(zend_function *fbc); PHP_MINIT_FUNCTION(zend_test) { @@ -498,20 +498,20 @@ static void observer_show_init(zend_function *fbc) } } -static zend_observer_fcall observer_fcall_init(zend_function *fbc) +static zend_observer_fcall_handlers observer_fcall_init(zend_function *fbc) { if (ZT_G(observer_show_output)) { observer_show_init(fbc); } if (ZT_G(observer_observe_all)) { - return (zend_observer_fcall){observer_begin, observer_end}; + return (zend_observer_fcall_handlers){observer_begin, observer_end}; } else if (ZT_G(observer_observe_includes) && !fbc->common.function_name) { - return (zend_observer_fcall){observer_begin, observer_end}; + return (zend_observer_fcall_handlers){observer_begin, observer_end}; } else if (ZT_G(observer_observe_functions) && fbc->common.function_name) { - return (zend_observer_fcall){observer_begin, observer_end}; + return (zend_observer_fcall_handlers){observer_begin, observer_end}; } - return (zend_observer_fcall){NULL, NULL}; + return (zend_observer_fcall_handlers){NULL, NULL}; } PHP_RINIT_FUNCTION(zend_test) diff --git a/ext/zend_test/tests/observer_jit_01.phpt b/ext/zend_test/tests/observer_jit_01.phpt deleted file mode 100644 index f489986b6e..0000000000 --- a/ext/zend_test/tests/observer_jit_01.phpt +++ /dev/null @@ -1,25 +0,0 @@ ---TEST-- -Observer: JIT is disabled when observer extension is present ---SKIPIF-- - - - ---INI-- -zend_test.observer.enabled=1 -zend_test.observer.observe_all=1 -opcache.enable=1 -opcache.enable_cli=1 -opcache.jit=1 -opcache.jit_buffer_size=1M ---FILE-- - ---EXPECTF-- - - -JIT enabled: no -JIT on: no - -- 2.40.0