diff options
Diffstat (limited to 'vm_debug.h')
| -rw-r--r-- | vm_debug.h | 107 |
1 files changed, 95 insertions, 12 deletions
diff --git a/vm_debug.h b/vm_debug.h index 424390fade..cf80232f3a 100644 --- a/vm_debug.h +++ b/vm_debug.h @@ -1,3 +1,5 @@ +#ifndef RUBY_DEBUG_H +#define RUBY_DEBUG_H /********************************************************************** vm_debug.h - YARV Debug function interface @@ -9,33 +11,114 @@ **********************************************************************/ -#ifndef RUBY_DEBUG_H -#define RUBY_DEBUG_H - #include "ruby/ruby.h" -#include "node.h" -#if defined __GNUC__ && __GNUC__ >= 4 -#pragma GCC visibility push(default) -#endif +RUBY_SYMBOL_EXPORT_BEGIN #define dpv(h,v) ruby_debug_print_value(-1, 0, (h), (v)) #define dp(v) ruby_debug_print_value(-1, 0, "", (v)) #define dpi(i) ruby_debug_print_id(-1, 0, "", (i)) #define dpn(n) ruby_debug_print_node(-1, 0, "", (n)) -#define bp() ruby_debug_breakpoint() +struct RNode; VALUE ruby_debug_print_value(int level, int debug_level, const char *header, VALUE v); +void ruby_debug_print_v(VALUE v); ID ruby_debug_print_id(int level, int debug_level, const char *header, ID id); -NODE *ruby_debug_print_node(int level, int debug_level, const char *header, const NODE *node); +struct RNode *ruby_debug_print_node(int level, int debug_level, const char *header, const struct RNode *node); +void ruby_debug_print_n(const struct RNode *node); int ruby_debug_print_indent(int level, int debug_level, int indent_level); -void ruby_debug_breakpoint(void); void ruby_debug_gc_check_func(void); void ruby_set_debug_option(const char *str); -#if defined __GNUC__ && __GNUC__ >= 4 -#pragma GCC visibility pop +RUBY_SYMBOL_EXPORT_END + +#ifndef USE_RUBY_DEBUG_LOG +#define USE_RUBY_DEBUG_LOG 0 #endif +/* RUBY_DEBUG_LOG: Logging debug information mechanism + * + * This feature provides a mechanism to store logging information + * to a file, stderr or memory space with simple macros. + * + * The following information will be stored. + * * (1) __FILE__, __LINE__ in C + * * (2) __FILE__, __LINE__ in Ruby + * * (3) __func__ in C (message title) + * * (4) given string with sprintf format + * * (5) Thread number (if multiple threads are running) + * + * This feature is enabled only USE_RUBY_DEBUG_LOG is enabled. + * Release version should not enable it. + * + * Running with the `RUBY_DEBUG_LOG` environment variable enables + * this feature. + * + * # logging into a file + * RUBY_DEBUG_LOG=/path/to/file STDERR + * + * # logging into STDERR + * RUBY_DEBUG_LOG=stderr + * + * # logging into memory space (check with a debugger) + * # It will help if the timing is important. + * RUBY_DEBUG_LOG=mem + * + * RUBY_DEBUG_LOG_FILTER environment variable can specify the filter string. + * If "(3) __func__ in C (message title)" contains the specified string, the + * information will be stored (example: RUBY_DEBUG_LOG_FILTER=str will enable + * only on str related information). + * + * In a MRI source code, you can use the following macros: + * * RUBY_DEBUG_LOG(fmt, ...): Above (1) to (4) will be logged. + * * RUBY_DEBUG_LOG2(file, line, fmt, ...): + * Same as RUBY_DEBUG_LOG(), but (1) will be replaced with given file, line. + */ + +extern enum ruby_debug_log_mode { + ruby_debug_log_disabled = 0x00, + ruby_debug_log_memory = 0x01, + ruby_debug_log_stderr = 0x02, + ruby_debug_log_file = 0x04, +} ruby_debug_log_mode; + +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 4, 5) +void ruby_debug_log(const char *file, int line, const char *func_name, const char *fmt, ...); +void ruby_debug_log_print(unsigned int n); +bool ruby_debug_log_filter(const char *func_name, const char *file_name); + +// convenient macro to log even if the USE_RUBY_DEBUG_LOG macro is not specified. +// You can use this macro for temporary usage (you should not commit it). +#define _RUBY_DEBUG_LOG(...) ruby_debug_log(__FILE__, __LINE__, RUBY_FUNCTION_NAME_STRING, "" __VA_ARGS__) + +#if RBIMPL_COMPILER_IS(GCC) && defined(__OPTIMIZE__) +# define ruby_debug_log(...) \ + RB_GNUC_EXTENSION_BLOCK( \ + RBIMPL_WARNING_PUSH(); \ + RBIMPL_WARNING_IGNORED(-Wformat-zero-length); \ + ruby_debug_log(__VA_ARGS__); \ + RBIMPL_WARNING_POP()) +#endif + +#if USE_RUBY_DEBUG_LOG +# define RUBY_DEBUG_LOG_ENABLED(func_name, file_name) \ + (ruby_debug_log_mode && ruby_debug_log_filter(func_name, file_name)) + +#define RUBY_DEBUG_LOG(...) do { \ + if (RUBY_DEBUG_LOG_ENABLED(RUBY_FUNCTION_NAME_STRING, __FILE__)) \ + ruby_debug_log(__FILE__, __LINE__, RUBY_FUNCTION_NAME_STRING, "" __VA_ARGS__); \ +} while (0) + +#define RUBY_DEBUG_LOG2(file, line, ...) do { \ + if (RUBY_DEBUG_LOG_ENABLED(RUBY_FUNCTION_NAME_STRING, file)) \ + ruby_debug_log(file, line, RUBY_FUNCTION_NAME_STRING, "" __VA_ARGS__); \ +} while (0) + +#else // USE_RUBY_DEBUG_LOG +// do nothing +#define RUBY_DEBUG_LOG(...) +#define RUBY_DEBUG_LOG2(file, line, ...) +#endif // USE_RUBY_DEBUG_LOG + #endif /* RUBY_DEBUG_H */ |
