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;
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;
#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;
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 */
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;
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);
}
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);
}
}
}
#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);
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();
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;
}
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();
} else {
zval retval;
ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION);
- if (IS_OBSERVER) {
+ if (ZEND_OBSERVER_ENABLED) {
ret = NULL;
}
}
}
}
- OBSERVER_FCALL_END_HANDLERS(execute_data, return_value);
+ ZEND_OBSERVER_FCALL_END(execute_data, return_value);
ZEND_VM_DISPATCH_TO_HELPER(zend_leave_helper);
}
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);
}
}
}
- 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);
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();
}
}
- 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)) {
}
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();
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();
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();
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();
}
}
- 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)) {
}
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();
}
}
}
- 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));
}
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));
}
}
}
- 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);
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();
}
}
}
- zend_observer_maybe_fcall_call_end(execute_data, return_value);
+ zend_observer_fcall_end(execute_data, return_value);
goto zend_leave_helper_SPEC_LABEL;
}
}
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);
}
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);
"/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);
#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"
}
}
-#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();
#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"
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
|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
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;
}
}
|9:
+ if (ZEND_OBSERVER_ENABLED) {
+ | LOAD_ZVAL_ADDR FCARG2a, ret_addr
+ | mov FCARG1a, FP
+ | EXT_CALL zend_observer_fcall_end, r0
+ }
return 1;
}
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)
{
}
}
-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)
+++ /dev/null
---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'>