summaryrefslogtreecommitdiff
path: root/vm_debug.h
diff options
context:
space:
mode:
Diffstat (limited to 'vm_debug.h')
-rw-r--r--vm_debug.h107
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 */