]> granicus.if.org Git - php/commitdiff
Cleanup observer API and add JIT support
authorDmitry Stogov <dmitry@zend.com>
Fri, 18 Sep 2020 09:55:58 +0000 (12:55 +0300)
committerDmitry Stogov <dmitry@zend.com>
Fri, 18 Sep 2020 09:55:58 +0000 (12:55 +0300)
13 files changed:
Zend/zend_execute_API.c
Zend/zend_generators.c
Zend/zend_observer.c
Zend/zend_observer.h
Zend/zend_vm_def.h
Zend/zend_vm_execute.h
Zend/zend_vm_execute.skl
Zend/zend_vm_gen.php
ext/opcache/ZendAccelerator.c
ext/opcache/jit/zend_jit.c
ext/opcache/jit/zend_jit_x86.dasc
ext/zend_test/test.c
ext/zend_test/tests/observer_jit_01.phpt [deleted file]

index 030455a94e3a1c0058fabb888963a7f6212487d3..7572a0d8900c6173a338d66375a1258467f98111 100644 (file)
@@ -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;
index baca12f66b56d056aeab10c271dd84df970f6e23..4e2351869d3104e54cbe2d64b94ddd7db3fbc7a3 100644 (file)
@@ -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;
index b124de5cc36997695bf5d7b8c15f8562fb5bb845..5544039c3e87fc97bd89d16b0f58f399353181f0 100644 (file)
 #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);
                }
        }
 }
index 0603591c53957aada56faf164a774171557d8990..246a3a61be3794507fe33b242a3132e8efaf1433 100644 (file)
@@ -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);
index 6af78eb3ae17829ea5d8a426819289059487cda6..510595b7c8668224417c8720f57b2eabe1441d81 100644 (file)
@@ -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();
index a6feaf02e0caa6e3b54f3a47c3deb97a4c8295ec..f59c923bd1613019e74cbf7acf33f662a5d77182 100644 (file)
@@ -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);
index 22911760e43e1c14e849ae8cf85aae5cc98971c0..582ec490e2d77bf9fae6d8c06a0e05b4803ef617 100644 (file)
@@ -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);
index e3dceaa829a1e7f7da312fb5d69d0655f5e5622a..3346a59cfa620c384cf83dbdb925b10e7af19fa2 100755 (executable)
@@ -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);
index 46363acb7b2e1f642cfd8458f0d9438f9b6a8b20..71af3203dca383f3081f24473c02ef077def6520 100644 (file)
@@ -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();
 
index 3dad8e4f911151386936729d2fc1f332ec04bb24..094f4d56d6d34d9e04913aa49832d4ca21db543f 100644 (file)
@@ -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"
 
index daff6fb641dff347d6999be79126150f3484b0b5..c689359272ede28f5e317b462f22d638339bb2a7 100644 (file)
@@ -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;
 }
 
index 0e4040d1bd84519891de9b84b05d89c4da664d8d..4ca98a3c0831b19eb0797f8b83b602bc3cde5f49 100644 (file)
@@ -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 (file)
index f489986..0000000
+++ /dev/null
@@ -1,25 +0,0 @@
---TEST--
-Observer: JIT is disabled when observer extension is present
---SKIPIF--
-<?php if (!extension_loaded('zend-test')) die('skip: zend-test extension required'); ?>
-<?php if (!extension_loaded('Zend OPcache')) die('skip: OPcache extension required'); ?>
-<?php if (!isset(opcache_get_status()['jit'])) die('skip: Build with JIT required'); ?>
---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--
-<?php
-$status = opcache_get_status();
-echo 'JIT enabled: ' . ($status['jit']['enabled'] ? 'yes' : 'no') . PHP_EOL;
-echo 'JIT on: ' . ($status['jit']['on'] ? 'yes' : 'no') . PHP_EOL;
-?>
---EXPECTF--
-<!-- init '%s/observer_jit_%d.php' -->
-<file '%s/observer_jit_%d.php'>
-JIT enabled: no
-JIT on: no
-</file '%s/observer_jit_%d.php'>