diff options
author | Takashi Kokubun <[email protected]> | 2019-12-01 00:56:27 -0800 |
---|---|---|
committer | Takashi Kokubun <[email protected]> | 2019-12-01 00:58:47 -0800 |
commit | a19d625e667024fe27dcee04dd748e914bc24762 (patch) | |
tree | 5ca8c6cec0d19cb54e8c2643d8736216bb6fd2e2 | |
parent | bdc62dfc8ecffd27dd5ad6756cce88eac5c993f5 (diff) |
Allow specifying arbitrary MJIT flags by --jit-debug
This is a secret feature for me. It's only for testing and any behavior
with this flag override is unsupported.
I needed this because I sometimes want to add debug options but do not
want to disable optimizations, for using Linux perf.
-rw-r--r-- | mjit.c | 32 | ||||
-rw-r--r-- | mjit.h | 2 | ||||
-rw-r--r-- | mjit_worker.c | 6 | ||||
-rw-r--r-- | ruby.c | 5 | ||||
-rw-r--r-- | test/ruby/test_rubyoptions.rb | 6 |
5 files changed, 48 insertions, 3 deletions
@@ -700,6 +700,33 @@ start_worker(void) return true; } +// Convert "foo bar" to {"foo", "bar", NULL} array. Caller is responsible for +// freeing a returned buffer and its elements. +static char ** +split_flags(char *flags) +{ + char *buf[MAXPATHLEN]; + int i = 0; + char *next; + for (; flags != NULL; flags = next) { + next = strchr(flags, ' '); + if (next == NULL) { + if (strlen(flags) > 0) + buf[i++] = strdup(flags); + } + else { + if (next > flags) + buf[i++] = strndup(flags, next - flags); + next++; // skip space + } + } + buf[i] = NULL; + + char **ret = xmalloc(sizeof(char **) * i); + memcpy((void *)ret, buf, sizeof(char **) * i); + return ret; +} + // Initialize MJIT. Start a thread creating the precompiled header and // processing ISeqs. The function should be called first for using MJIT. // If everything is successful, MJIT_INIT_P will be TRUE. @@ -728,6 +755,8 @@ mjit_init(struct mjit_options *opts) verbose(2, "MJIT: CC defaults to %s", cc_path); cc_common_args = xmalloc(sizeof(CC_COMMON_ARGS)); memcpy((void *)cc_common_args, CC_COMMON_ARGS, sizeof(CC_COMMON_ARGS)); + cc_added_args = split_flags(opts->debug_flags); + xfree(opts->debug_flags); #if MJIT_CFLAGS_PIPE { // eliminate a flag incompatible with `-pipe` size_t i, j; @@ -921,6 +950,9 @@ mjit_finish(bool close_handle_p) xfree(header_file); header_file = NULL; #endif xfree((void *)cc_common_args); cc_common_args = NULL; + for (char **flag = cc_added_args; *flag != NULL; flag++) + xfree(*flag); + xfree((void *)cc_added_args); cc_added_args = NULL; xfree(tmp_dir); tmp_dir = NULL; xfree(pch_file); pch_file = NULL; @@ -43,6 +43,8 @@ struct mjit_options { // Disable compiler optimization and add debug symbols. It can be // very slow. char debug; + // Add arbitrary cflags. + char* debug_flags; // If not 0, all ISeqs are synchronously compiled. For testing. unsigned int wait; // Number of calls to trigger JIT compilation. For testing. diff --git a/mjit_worker.c b/mjit_worker.c index b23baf656d..ce8133ac7d 100644 --- a/mjit_worker.c +++ b/mjit_worker.c @@ -221,6 +221,8 @@ static VALUE valid_class_serials; static const char *cc_path; // Used C compiler flags. static const char **cc_common_args; +// Used C compiler flags added by --jit-debug=... +static char **cc_added_args; // Name of the precompiled header file. static char *pch_file; // The process id which should delete the pch_file on mjit_finish. @@ -759,7 +761,7 @@ make_pch(void) }; verbose(2, "Creating precompiled header"); - char **args = form_args(3, cc_common_args, CC_CODEFLAG_ARGS, rest_args); + char **args = form_args(4, cc_common_args, CC_CODEFLAG_ARGS, cc_added_args, rest_args); if (args == NULL) { mjit_warning("making precompiled header failed on forming args"); CRITICAL_SECTION_START(3, "in make_pch"); @@ -796,7 +798,7 @@ compile_c_to_o(const char *c_file, const char *o_file) "-c", NULL }; - char **args = form_args(4, cc_common_args, CC_CODEFLAG_ARGS, files, CC_LINKER_ARGS); + char **args = form_args(5, cc_common_args, CC_CODEFLAG_ARGS, cc_added_args, files, CC_LINKER_ARGS); if (args == NULL) return false; @@ -298,7 +298,7 @@ usage(const char *name, int help) }; static const struct message mjit_options[] = { M("--jit-warnings", "", "Enable printing JIT warnings"), - M("--jit-debug", "", "Enable JIT debugging (very slow)"), + M("--jit-debug", "", "Enable JIT debugging (very slow), or add cflags if specified"), M("--jit-wait", "", "Wait until JIT compilation is finished everytime (for testing)"), M("--jit-save-temps", "", "Save JIT temporary files in $TMP or /tmp (for testing)"), M("--jit-verbose=num", "", "Print JIT logs of level num or less to stderr (default: 0)"), @@ -969,6 +969,9 @@ setup_mjit_options(const char *s, struct mjit_options *mjit_opt) else if (strcmp(s, "-warnings") == 0) { mjit_opt->warnings = 1; } + else if (strncmp(s, "-debug=", 7) == 0) { + mjit_opt->debug_flags = strdup(s + 7); + } else if (strcmp(s, "-debug") == 0) { mjit_opt->debug = 1; } diff --git a/test/ruby/test_rubyoptions.rb b/test/ruby/test_rubyoptions.rb index 10d54550c1..abdacc508e 100644 --- a/test/ruby/test_rubyoptions.rb +++ b/test/ruby/test_rubyoptions.rb @@ -1043,6 +1043,12 @@ class TestRubyOptions < Test::Unit::TestCase assert_in_out_err([IO::NULL], success: true) end + def test_jit_debug + if JITSupport.supported? + assert_in_out_err(["--jit-debug=-O0 -O1", "--jit-verbose=2", ""], "", [], /-O0 -O1/) + end + end + private def mjit_force_enabled? |