From f5149a7c647112d2eba69f55483cf41aae88dac6 Mon Sep 17 00:00:00 2001 From: longxinhui Date: Wed, 31 Mar 2021 17:18:38 +0800 Subject: [PATCH] JIT support #51 Use PHP 8.0 Observer API --- extension/php_xhprof.h | 80 +++------- extension/trace.h | 190 ++++++++++++++++++++++++ extension/xhprof.c | 330 ++++++++++++----------------------------- 3 files changed, 304 insertions(+), 296 deletions(-) create mode 100644 extension/trace.h diff --git a/extension/php_xhprof.h b/extension/php_xhprof.h index e7d42b5c..ccf66ddd 100755 --- a/extension/php_xhprof.h +++ b/extension/php_xhprof.h @@ -31,6 +31,10 @@ extern zend_module_entry xhprof_module_entry; #include "TSRM.h" #endif +#if PHP_VERSION_ID >= 80000 +#include "zend_observer.h" +#endif + /** * ********************** @@ -39,7 +43,7 @@ extern zend_module_entry xhprof_module_entry; */ /* XHProf version */ -#define XHPROF_VERSION "2.2.3" +#define XHPROF_VERSION "2.3.0-dev" #define XHPROF_FUNC_HASH_COUNTERS_SIZE 1024 @@ -80,60 +84,6 @@ extern zend_module_entry xhprof_module_entry; typedef unsigned char uint8; #endif -/* - * Start profiling - called just before calling the actual function - * NOTE: PLEASE MAKE SURE TSRMLS_CC IS AVAILABLE IN THE CONTEXT - * OF THE FUNCTION WHERE THIS MACRO IS CALLED. - * TSRMLS_CC CAN BE MADE AVAILABLE VIA TSRMLS_DC IN THE - * CALLING FUNCTION OR BY CALLING TSRMLS_FETCH() - * TSRMLS_FETCH() IS RELATIVELY EXPENSIVE. - */ -#define BEGIN_PROFILING(entries, symbol, profile_curr, execute_data) \ -do { \ - /* Use a hash code for zend_string. */ \ - zend_ulong hash_code = ZSTR_HASH(symbol); \ - profile_curr = !hp_ignore_entry_work(hash_code, symbol); \ - if (profile_curr) { \ - if (execute_data != NULL) { \ - symbol = hp_get_trace_callback(symbol, execute_data); \ - } \ - hp_entry_t *cur_entry = hp_fast_alloc_hprof_entry(); \ - (cur_entry)->hash_code = hash_code % XHPROF_FUNC_HASH_COUNTERS_SIZE; \ - (cur_entry)->name_hprof = symbol; \ - (cur_entry)->prev_hprof = (*(entries)); \ - /* Call the universal callback */ \ - hp_mode_common_beginfn((entries), (cur_entry)); \ - /* Call the mode's beginfn callback */ \ - XHPROF_G(mode_cb).begin_fn_cb((entries), (cur_entry)); \ - /* Update entries linked list */ \ - (*(entries)) = (cur_entry); \ - } \ -} while (0) - -/* - * Stop profiling - called just after calling the actual function - * NOTE: PLEASE MAKE SURE TSRMLS_CC IS AVAILABLE IN THE CONTEXT - * OF THE FUNCTION WHERE THIS MACRO IS CALLED. - * TSRMLS_CC CAN BE MADE AVAILABLE VIA TSRMLS_DC IN THE - * CALLING FUNCTION OR BY CALLING TSRMLS_FETCH() - * TSRMLS_FETCH() IS RELATIVELY EXPENSIVE. - */ -#define END_PROFILING(entries, profile_curr) \ -do { \ - if (profile_curr) { \ - hp_entry_t *cur_entry; \ - /* Call the mode's endfn callback. */ \ - /* NOTE(cjiang): we want to call this 'end_fn_cb' before */ \ - /* 'hp_mode_common_endfn' to avoid including the time in */ \ - /* 'hp_mode_common_endfn' in the profiling results. */ \ - XHPROF_G(mode_cb).end_fn_cb((entries)); \ - cur_entry = (*(entries)); \ - /* Free top entry and update entries linked list */ \ - (*(entries)) = (*(entries))->prev_hprof; \ - hp_fast_free_hprof_entry(cur_entry); \ - } \ -} while (0) - /* Bloom filter for function names to be ignored */ #define INDEX_2_BYTE(index) (index >> 3) #define INDEX_2_BIT(index) (1 << (index & 0x7)); @@ -156,6 +106,9 @@ typedef struct hp_entry_t { zend_ulong tsc_start; /* start value for TSC counter */ zend_ulong cpu_start; zend_ulong hash_code; /* hash_code for the function name */ +#if PHP_VERSION_ID >= 80000 + int is_trace; +#endif } hp_entry_t; typedef struct hp_ignored_functions { @@ -176,9 +129,6 @@ typedef void (*hp_end_function_cb) (hp_entry_t **entries); * GLOBAL STATIC VARIABLES * *********************** */ -/* Pointer to the original execute function */ -static void (*_zend_execute_ex) (zend_execute_data *execute_data); -ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data); /* Pointer to the origianl execute_internal function */ static void (*_zend_execute_internal) (zend_execute_data *data, zval *return_value); @@ -188,13 +138,22 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval *re static zend_op_array * (*_zend_compile_file) (zend_file_handle *file_handle, int type); ZEND_DLEXPORT zend_op_array* hp_compile_file(zend_file_handle *file_handle, int type); -/* Pointer to the original compile string function (used by eval) */ #if PHP_VERSION_ID < 80000 +/* Pointer to the original compile string function (used by eval) */ static zend_op_array * (*_zend_compile_string) (zval *source_string, char *filename); ZEND_DLEXPORT zend_op_array* hp_compile_string(zval *source_string, char *filename); + +/* Pointer to the original execute function */ +static void (*_zend_execute_ex) (zend_execute_data *execute_data); +ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data); #else +/* Pointer to the original compile string function (used by eval) */ static zend_op_array * (*_zend_compile_string) (zend_string *source_string, const char *filename); ZEND_DLEXPORT zend_op_array* hp_compile_string(zend_string *source_string, const char *filename); + +static zend_observer_fcall_handlers tracer_observer(zend_execute_data *execute_data); +static void tracer_observer_begin(zend_execute_data *ex); +static void tracer_observer_end(zend_execute_data *ex, zval *return_value); #endif /** @@ -211,7 +170,6 @@ static void hp_end(); static inline zend_ulong cycle_timer(); static void hp_free_the_free_list(); -static hp_entry_t *hp_fast_alloc_hprof_entry(); static void hp_fast_free_hprof_entry(hp_entry_t *p); static void incr_us_interval(struct timeval *start, zend_ulong incr); @@ -220,7 +178,6 @@ static void hp_get_ignored_functions_from_arg(zval *args); static inline void hp_array_del(zend_string **names); -zend_string *hp_get_trace_callback(zend_string *symbol, zend_execute_data *data); void hp_init_trace_callbacks(); double get_timebase_conversion(); @@ -311,5 +268,4 @@ PHP_FUNCTION(xhprof_sample_disable); #endif extern ZEND_DECLARE_MODULE_GLOBALS(xhprof); - #endif /* PHP_XHPROF_H */ diff --git a/extension/trace.h b/extension/trace.h new file mode 100644 index 00000000..1447906b --- /dev/null +++ b/extension/trace.h @@ -0,0 +1,190 @@ +#ifndef XHPROF_TRACE_H +#define XHPROF_TRACE_H + +static zend_always_inline void hp_mode_common_beginfn(hp_entry_t **entries, hp_entry_t *current) +{ + hp_entry_t *p; + + /* This symbol's recursive level */ + int recurse_level = 0; + + if (XHPROF_G(func_hash_counters[current->hash_code]) > 0) { + /* Find this symbols recurse level */ + for (p = (*entries); p; p = p->prev_hprof) { + if (zend_string_equals(current->name_hprof, p->name_hprof)) { + recurse_level = (p->rlvl_hprof) + 1; + break; + } + } + } + + XHPROF_G(func_hash_counters[current->hash_code])++; + + /* Init current function's recurse level */ + current->rlvl_hprof = recurse_level; +} + +static zend_always_inline int hp_ignored_functions_filter_collision(hp_ignored_functions *functions, zend_ulong hash) +{ + zend_ulong idx = hash % XHPROF_MAX_IGNORED_FUNCTIONS; + return functions->filter[idx]; +} + +static zend_always_inline int hp_ignore_entry_work(zend_ulong hash_code, zend_string *curr_func) +{ + if (XHPROF_G(ignored_functions) == NULL) { + return 0; + } + + hp_ignored_functions *functions = XHPROF_G(ignored_functions); + + if (hp_ignored_functions_filter_collision(functions, hash_code)) { + int i = 0; + for (; functions->names[i] != NULL; i++) { + zend_string *name = functions->names[i]; + if (zend_string_equals(curr_func, name)) { + return 1; + } + } + } + + return 0; +} + +static zend_always_inline zend_string *hp_get_function_name(zend_execute_data *execute_data) +{ + zend_function *curr_func; + zend_string *real_function_name; + + if (!execute_data) { + return NULL; + } + + curr_func = execute_data->func; + + if (!curr_func->common.function_name) { + return NULL; + } + + if (curr_func->common.scope != NULL) { + real_function_name = strpprintf(0, "%s::%s", curr_func->common.scope->name->val, ZSTR_VAL(curr_func->common.function_name)); + } else { + real_function_name = zend_string_copy(curr_func->common.function_name); + } + + return real_function_name; +} + +static zend_always_inline zend_string *hp_get_trace_callback(zend_string *function_name, zend_execute_data *data) +{ + zend_string *trace_name; + hp_trace_callback *callback; + + if (XHPROF_G(trace_callbacks)) { + callback = (hp_trace_callback*)zend_hash_find_ptr(XHPROF_G(trace_callbacks), function_name); + if (callback) { + trace_name = (*callback)(function_name, data); + } else { + return function_name; + } + } else { + return function_name; + } + + zend_string_release(function_name); + + return trace_name; +} + +static zend_always_inline hp_entry_t *hp_fast_alloc_hprof_entry() +{ + hp_entry_t *p; + + p = XHPROF_G(entry_free_list); + + if (p) { + XHPROF_G(entry_free_list) = p->prev_hprof; + return p; + } else { + return (hp_entry_t *)malloc(sizeof(hp_entry_t)); + } +} + +static zend_always_inline void hp_fast_free_hprof_entry(hp_entry_t *p) +{ + if (p->name_hprof != NULL) { + zend_string_release(p->name_hprof); + } + + /* we use/overload the prev_hprof field in the structure to link entries in + * the free list. + * */ + p->prev_hprof = XHPROF_G(entry_free_list); + XHPROF_G(entry_free_list) = p; +} + +static zend_always_inline int begin_profiling(zend_string *root_symbol, zend_execute_data *execute_data) +{ + zend_string *function_name; + hp_entry_t **entries = &XHPROF_G(entries); + + if (root_symbol == NULL) { + function_name = hp_get_function_name(execute_data); + } else { + function_name = zend_string_copy(root_symbol); + } + + if (function_name == NULL) { + return 0; + } + + zend_ulong hash_code = ZSTR_HASH(function_name); + int profile_curr = !hp_ignore_entry_work(hash_code, function_name); + if (profile_curr) { + if (execute_data != NULL) { + function_name = hp_get_trace_callback(function_name, execute_data); + } + + hp_entry_t *cur_entry = hp_fast_alloc_hprof_entry(); + (cur_entry)->hash_code = hash_code % XHPROF_FUNC_HASH_COUNTERS_SIZE; + (cur_entry)->name_hprof = function_name; + (cur_entry)->prev_hprof = (*(entries)); +#if PHP_VERSION_ID >= 80000 + (cur_entry)->is_trace = 1; +#endif + /* Call the universal callback */ + hp_mode_common_beginfn((entries), (cur_entry)); + /* Call the mode's beginfn callback */ + XHPROF_G(mode_cb).begin_fn_cb((entries), (cur_entry)); + /* Update entries linked list */ + (*(entries)) = (cur_entry); + } else { +#if PHP_VERSION_ID >= 80000 + hp_entry_t *cur_entry = hp_fast_alloc_hprof_entry(); + (cur_entry)->name_hprof = (*(entries))->name_hprof; + (cur_entry)->prev_hprof = (*(entries)); + (cur_entry)->is_trace = 0; + (*(entries)) = (cur_entry); +#endif + zend_string_release(function_name); + } + + return profile_curr; +} + +static zend_always_inline void end_profiling() +{ + hp_entry_t *cur_entry; + hp_entry_t **entries = &XHPROF_G(entries); + + /* Call the mode's endfn callback. */ + /* NOTE(cjiang): we want to call this 'end_fn_cb' before */ + /* 'hp_mode_common_endfn' to avoid including the time in */ + /* 'hp_mode_common_endfn' in the profiling results. */ + XHPROF_G(mode_cb).end_fn_cb(entries); + cur_entry = (*(entries)); + /* Free top entry and update entries linked list */ + (*(entries)) = (*(entries))->prev_hprof; + hp_fast_free_hprof_entry(cur_entry); +} +#endif \ No newline at end of file diff --git a/extension/xhprof.c b/extension/xhprof.c index d3eea0f6..522b0116 100755 --- a/extension/xhprof.c +++ b/extension/xhprof.c @@ -24,6 +24,8 @@ #include "ext/standard/info.h" #include "php_xhprof.h" #include "zend_extensions.h" +#include "trace.h" + #ifndef ZEND_WIN32 # include # include @@ -266,9 +268,13 @@ PHP_MINIT_FUNCTION(xhprof) _zend_compile_string = zend_compile_string; zend_compile_string = hp_compile_string; +#if PHP_VERSION_ID >= 80000 + zend_observer_fcall_register(tracer_observer); +#else /* Replace zend_execute with our proxy */ _zend_execute_ex = zend_execute_ex; zend_execute_ex = hp_execute_ex; +#endif /* Replace zend_execute_internal with our proxy */ _zend_execute_internal = zend_execute_internal; @@ -293,8 +299,10 @@ PHP_MSHUTDOWN_FUNCTION(xhprof) /* free any remaining items in the free list */ hp_free_the_free_list(); +#if PHP_VERSION_ID < 80000 /* Remove proxies, restore the originals */ zend_execute_ex = _zend_execute_ex; +#endif zend_execute_internal = _zend_execute_internal; zend_compile_file = _zend_compile_file; zend_compile_string = _zend_compile_string; @@ -461,17 +469,6 @@ hp_ignored_functions *hp_ignored_functions_init(zval *values) return functions; } -/** - * Check if function collides in filter of functions to be ignored. - * - * @author mpal - */ -int hp_ignored_functions_filter_collision(hp_ignored_functions *functions, zend_ulong hash) -{ - zend_ulong idx = hash % XHPROF_MAX_IGNORED_FUNCTIONS; - return functions->filter[idx]; -} - /** * Initialize profiler state * @@ -492,6 +489,10 @@ void hp_init_profiler_state(int level) zval_ptr_dtor(&XHPROF_G(stats_count)); } + if (XHPROF_G(root)) { + zend_string_release(XHPROF_G(root)); + } + array_init(&XHPROF_G(stats_count)); hp_init_trace_callbacks(); @@ -527,6 +528,10 @@ void hp_clean_profiler_state() XHPROF_G(trace_callbacks) = NULL; } + if (XHPROF_G(root)) { + zend_string_release(XHPROF_G(root)); + } + /* Delete the array storing ignored function names */ hp_ignored_functions_clear(XHPROF_G(ignored_functions)); XHPROF_G(ignored_functions) = NULL; @@ -553,32 +558,6 @@ size_t hp_get_entry_name(hp_entry_t *entry, char *result_buf, size_t result_len) return len; } -/** - * Check if this entry should be ignored, first with a conservative Bloomish - * filter then with an exact check against the function names. - * - * @author mpal - */ -int hp_ignore_entry_work(zend_ulong hash_code, zend_string *curr_func) -{ - if (XHPROF_G(ignored_functions) == NULL) { - return 0; - } - - hp_ignored_functions *functions = XHPROF_G(ignored_functions); - - if (hp_ignored_functions_filter_collision(functions, hash_code)) { - int i = 0; - for (; functions->names[i] != NULL; i++) { - zend_string *name = functions->names[i]; - if (zend_string_equals(curr_func, name)) { - return 1; - } - } - } - - return 0; -} /** * Build a caller qualified name for a callee. @@ -657,40 +636,6 @@ static const char *hp_get_base_filename(const char *filename) return filename; } -/** - * Get the name of the current function. The name is qualified with - * the class name if the function is in a class. - * - * @author kannan, hzhao - */ -static zend_string *hp_get_function_name(zend_execute_data *execute_data) -{ - zend_string *ret; - zend_function *curr_func; - zend_string *func = NULL; - - if (!execute_data) { - return NULL; - } - - /* shared meta data for function on the call stack */ - curr_func = execute_data->func; - /* extract function name from the meta info */ - func = curr_func->common.function_name; - - if (!func) { - return NULL; - } - - if (curr_func->common.scope != NULL) { - ret = strpprintf(0, "%s::%s", curr_func->common.scope->name->val, ZSTR_VAL(func)); - } else { - ret = zend_string_init(ZSTR_VAL(func), ZSTR_LEN(func), 0); - } - - return ret; -} - /** * Free any items in the free list. */ @@ -706,44 +651,6 @@ static void hp_free_the_free_list() } } -/** - * Fast allocate a hp_entry_t structure. Picks one from the - * free list if available, else does an actual allocate. - * - * Doesn't bother initializing allocated memory. - * - * @author kannan - */ -static hp_entry_t *hp_fast_alloc_hprof_entry() -{ - hp_entry_t *p; - - p = XHPROF_G(entry_free_list); - - if (p) { - XHPROF_G(entry_free_list) = p->prev_hprof; - return p; - } else { - return (hp_entry_t *)malloc(sizeof(hp_entry_t)); - } -} - -/** - * Fast free a hp_entry_t structure. Simply returns back - * the hp_entry_t to a free list and doesn't actually - * perform the free. - * - * @author kannan - */ -static void hp_fast_free_hprof_entry(hp_entry_t *p) -{ - /* we use/overload the prev_hprof field in the structure to link entries in - * the free list. - * */ - p->prev_hprof = XHPROF_G(entry_free_list); - XHPROF_G(entry_free_list) = p; -} - /** * Increment the count of the given stat with the given count * If the stat was not set before, inits the stat to the given count @@ -934,46 +841,6 @@ void hp_mode_dummy_endfn_cb(hp_entry_t **entries) } - -/** - * **************************** - * XHPROF COMMON CALLBACKS - * **************************** - */ -/** - * XHPROF universal begin function. - * This function is called for all modes before the - * mode's specific begin_function callback is called. - * - * @param hp_entry_t **entries linked list (stack) - * of hprof entries - * @param hp_entry_t *current hprof entry for the current fn - * @return void - * @author kannan, veeve - */ -void hp_mode_common_beginfn(hp_entry_t **entries, hp_entry_t *current) -{ - hp_entry_t *p; - - /* This symbol's recursive level */ - int recurse_level = 0; - - if (XHPROF_G(func_hash_counters[current->hash_code]) > 0) { - /* Find this symbols recurse level */ - for (p = (*entries); p; p = p->prev_hprof) { - if (zend_string_equals(current->name_hprof, p->name_hprof)) { - recurse_level = (p->rlvl_hprof) + 1; - break; - } - } - } - - XHPROF_G(func_hash_counters[current->hash_code])++; - - /* Init current function's recurse level */ - current->rlvl_hprof = recurse_level; -} - /** * ********************************* * XHPROF INIT MODULE CALLBACKS @@ -1059,6 +926,13 @@ void hp_mode_hier_endfn_cb(hp_entry_t **entries) long int pmu_end; double wt, cpu; +#if PHP_VERSION_ID >= 80000 + if (top->is_trace == 0) { + XHPROF_G(func_hash_counters[top->hash_code])--; + return; + } +#endif + /* Get end tsc counter */ wt = cycle_timer() - top->tsc_start; @@ -1123,35 +997,56 @@ void hp_mode_sampled_endfn_cb(hp_entry_t **entries) * @author hzhao, kannan */ -ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data) -{ +#if PHP_VERSION_ID >= 80000 +static void tracer_observer_begin(zend_execute_data *execute_data) { if (!XHPROF_G(enabled)) { - _zend_execute_ex(execute_data); return; } - zend_string *func; - int hp_profile_flag = 1; + begin_profiling(NULL, execute_data); +} - func = hp_get_function_name(execute_data); +static void tracer_observer_end(zend_execute_data *ex, zval *return_value) { + if (!XHPROF_G(enabled)) { + return; + } - if (!func) { + if (XHPROF_G(entries)) { + end_profiling(); + } +} + + +static zend_observer_fcall_handlers tracer_observer(zend_execute_data *execute_data) { + zend_function *func = execute_data->func; + + if (!func->common.function_name) { + return (zend_observer_fcall_handlers){NULL, NULL}; + } + + return (zend_observer_fcall_handlers){tracer_observer_begin, tracer_observer_end}; +} +#else +ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data) +{ + int is_profiling = 1; + + if (!XHPROF_G(enabled)) { _zend_execute_ex(execute_data); return; } - zend_execute_data *real_execute_data = execute_data->prev_execute_data; + //zend_execute_data *real_execute_data = execute_data->prev_execute_data; - BEGIN_PROFILING(&XHPROF_G(entries), func, hp_profile_flag, real_execute_data); + is_profiling = begin_profiling(NULL, execute_data); _zend_execute_ex(execute_data); - if (XHPROF_G(entries)) { - END_PROFILING(&XHPROF_G(entries), hp_profile_flag); + if (is_profiling == 1 && XHPROF_G(entries)) { + end_profiling(); } - - zend_string_release(func); } +#endif /** * Very similar to hp_execute. Proxy for zend_execute_internal(). @@ -1162,19 +1057,14 @@ ZEND_DLEXPORT void hp_execute_ex (zend_execute_data *execute_data) ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval *return_value) { - if (!XHPROF_G(enabled) || (XHPROF_G(xhprof_flags) & XHPROF_FLAGS_NO_BUILTINS)) { + int is_profiling = 1; + + if (!XHPROF_G(enabled) || (XHPROF_G(xhprof_flags) & XHPROF_FLAGS_NO_BUILTINS) > 0) { execute_internal(execute_data, return_value); return; } - zend_string *func; - int hp_profile_flag = 1; - - func = hp_get_function_name(execute_data); - - if (func) { - BEGIN_PROFILING(&XHPROF_G(entries), func, hp_profile_flag, execute_data); - } + is_profiling = begin_profiling(NULL, execute_data); if (!_zend_execute_internal) { /* no old override to begin with. so invoke the builtin's implementation */ @@ -1184,11 +1074,8 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval *re _zend_execute_internal(execute_data, return_value); } - if (func) { - if (XHPROF_G(entries)) { - END_PROFILING(&XHPROF_G(entries), hp_profile_flag); - } - zend_string_release(func); + if (is_profiling == 1 && XHPROF_G(entries)) { + end_profiling(); } } @@ -1200,27 +1087,29 @@ ZEND_DLEXPORT void hp_execute_internal(zend_execute_data *execute_data, zval *re */ ZEND_DLEXPORT zend_op_array* hp_compile_file(zend_file_handle *file_handle, int type) { + int is_profiling = 1; + if (!XHPROF_G(enabled)) { return _zend_compile_file(file_handle, type); } const char *filename; - zend_string *func; - zend_op_array *ret; - int hp_profile_flag = 1; + zend_string *function_name; + zend_op_array *op_array; filename = hp_get_base_filename(file_handle->filename); - func = strpprintf(0, "load::%s", filename); + function_name = strpprintf(0, "load::%s", filename); - BEGIN_PROFILING(&XHPROF_G(entries), func, hp_profile_flag, NULL); - ret = _zend_compile_file(file_handle, type); + is_profiling = begin_profiling(function_name, NULL); + op_array = _zend_compile_file(file_handle, type); - if (XHPROF_G(entries)) { - END_PROFILING(&XHPROF_G(entries), hp_profile_flag); + if (is_profiling == 1 && XHPROF_G(entries)) { + end_profiling(); } - zend_string_release(func); - return ret; + zend_string_release(function_name); + + return op_array; } /** @@ -1232,25 +1121,27 @@ ZEND_DLEXPORT zend_op_array* hp_compile_string(zval *source_string, char *filena ZEND_DLEXPORT zend_op_array* hp_compile_string(zend_string *source_string, const char *filename) #endif { + int is_profiling = 1; + if (!XHPROF_G(enabled)) { return _zend_compile_string(source_string, filename); } - zend_string *func; - zend_op_array *ret; - int hp_profile_flag = 1; + zend_string *function_name; + zend_op_array *op_array; - func = strpprintf(0, "eval::%s", filename); + function_name = strpprintf(0, "eval::%s", filename); - BEGIN_PROFILING(&XHPROF_G(entries), func, hp_profile_flag, NULL); - ret = _zend_compile_string(source_string, filename); + is_profiling = begin_profiling(function_name, NULL); + op_array = _zend_compile_string(source_string, filename); - if (XHPROF_G(entries)) { - END_PROFILING(&XHPROF_G(entries), hp_profile_flag); + if (is_profiling == 1 && XHPROF_G(entries)) { + end_profiling(); } - zend_string_release(func); - return ret; + zend_string_release(function_name); + + return op_array; } /** @@ -1267,8 +1158,6 @@ ZEND_DLEXPORT zend_op_array* hp_compile_string(zend_string *source_string, const static void hp_begin(zend_long level, zend_long xhprof_flags) { if (!XHPROF_G(enabled)) { - int hp_profile_flag = 1; - XHPROF_G(enabled) = 1; XHPROF_G(xhprof_flags) = (uint32)xhprof_flags; @@ -1300,7 +1189,7 @@ static void hp_begin(zend_long level, zend_long xhprof_flags) XHPROF_G(root) = zend_string_init(ROOT_SYMBOL, sizeof(ROOT_SYMBOL) - 1, 0); /* start profiling from fictitious main() */ - BEGIN_PROFILING(&XHPROF_G(entries), XHPROF_G(root), hp_profile_flag, NULL); + begin_profiling(XHPROF_G(root), NULL); } } @@ -1329,15 +1218,9 @@ static void hp_end() */ static void hp_stop() { - int hp_profile_flag = 1; - /* End any unfinished calls */ while (XHPROF_G(entries)) { - END_PROFILING(&XHPROF_G(entries), hp_profile_flag); - } - - if (XHPROF_G(root)) { - zend_string_release(XHPROF_G(root)); + end_profiling(); } /* Stop profiling */ @@ -1421,19 +1304,19 @@ zend_string *hp_pcre_replace(zend_string *pattern, zend_string *repl, zval *data return replace; } -zend_string *hp_trace_callback_sql_query(zend_string *symbol, zend_execute_data *data) +zend_string *hp_trace_callback_sql_query(zend_string *function_name, zend_execute_data *data) { - zend_string *result; + zend_string *trace_name; - if (strcmp(ZSTR_VAL(symbol), "mysqli_query") == 0) { + if (strcmp(ZSTR_VAL(function_name), "mysqli_query") == 0) { zval *arg = ZEND_CALL_ARG(data, 2); - result = strpprintf(0, "%s#%s", ZSTR_VAL(symbol), Z_STRVAL_P(arg)); + trace_name = strpprintf(0, "%s#%s", ZSTR_VAL(function_name), Z_STRVAL_P(arg)); } else { zval *arg = ZEND_CALL_ARG(data, 1); - result = strpprintf(0, "%s#%s", ZSTR_VAL(symbol), Z_STRVAL_P(arg)); + trace_name = strpprintf(0, "%s#%s", ZSTR_VAL(function_name), Z_STRVAL_P(arg)); } - return result; + return trace_name; } zend_string *hp_trace_callback_pdo_statement_execute(zend_string *symbol, zend_execute_data *data) @@ -1565,27 +1448,6 @@ zend_string *hp_trace_callback_curl_exec(zend_string *symbol, zend_execute_data return result; } -zend_string *hp_get_trace_callback(zend_string *symbol, zend_execute_data *data) -{ - zend_string *result; - hp_trace_callback *callback; - - if (XHPROF_G(trace_callbacks)) { - callback = (hp_trace_callback*)zend_hash_find_ptr(XHPROF_G(trace_callbacks), symbol); - if (callback) { - result = (*callback)(symbol, data); - } else { - return symbol; - } - } else { - return symbol; - } - - zend_string_release(symbol); - - return result; -} - static inline void hp_free_trace_callbacks(zval *val) { efree(Z_PTR_P(val)); } @@ -1623,4 +1485,4 @@ void hp_init_trace_callbacks() callback = hp_trace_callback_curl_exec; register_trace_callback("curl_exec", callback); -} +} \ No newline at end of file