Transfer the responsibility for MJIT options to mjit.c

This commit is contained in:
Nobuyoshi Nakada 2022-01-10 23:38:16 +09:00
parent 670f3e6cd7
commit c1bcfeec38
No known key found for this signature in database
GPG Key ID: 7CD2805BFA3770C6
Notes: git 2022-01-15 20:10:46 +09:00
4 changed files with 135 additions and 117 deletions

View File

@ -9419,6 +9419,7 @@ mjit.$(OBJEXT): $(hdrdir)/ruby/ruby.h
mjit.$(OBJEXT): $(hdrdir)/ruby/version.h
mjit.$(OBJEXT): $(top_srcdir)/internal/array.h
mjit.$(OBJEXT): $(top_srcdir)/internal/class.h
mjit.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h
mjit.$(OBJEXT): $(top_srcdir)/internal/compile.h
mjit.$(OBJEXT): $(top_srcdir)/internal/compilers.h
mjit.$(OBJEXT): $(top_srcdir)/internal/cont.h
@ -13162,6 +13163,7 @@ ruby.$(OBJEXT): $(hdrdir)/ruby/ruby.h
ruby.$(OBJEXT): $(hdrdir)/ruby/version.h
ruby.$(OBJEXT): $(top_srcdir)/internal/array.h
ruby.$(OBJEXT): $(top_srcdir)/internal/class.h
ruby.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h
ruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h
ruby.$(OBJEXT): $(top_srcdir)/internal/error.h
ruby.$(OBJEXT): $(top_srcdir)/internal/file.h

61
internal/cmdlineopt.h Normal file
View File

@ -0,0 +1,61 @@
#ifndef INTERNAL_CMDLINEOPT_H /*-*-C-*-vi:se ft=c:*/
#define INTERNAL_CMDLINEOPT_H
#include "mjit.h"
#include "yjit.h"
typedef struct {
unsigned int mask;
unsigned int set;
} ruby_features_t;
typedef struct ruby_cmdline_options {
const char *script;
VALUE script_name;
VALUE e_script;
struct {
struct {
VALUE name;
int index;
} enc;
} src, ext, intern;
VALUE req_list;
ruby_features_t features;
ruby_features_t warn;
unsigned int dump;
#if USE_MJIT
struct mjit_options mjit;
#endif
#if YJIT_SUPPORTED_P
struct rb_yjit_options yjit;
#endif
int sflag, xflag;
unsigned int warning: 1;
unsigned int verbose: 1;
unsigned int do_loop: 1;
unsigned int do_print: 1;
unsigned int do_line: 1;
unsigned int do_split: 1;
unsigned int do_search: 1;
unsigned int setids: 2;
} ruby_cmdline_options_t;
struct ruby_opt_message {
const char *str;
unsigned short namelen, secondlen;
};
#define RUBY_OPT_MESSAGE(shortopt, longopt, desc) { \
shortopt " " longopt " " desc, \
(unsigned short)sizeof(shortopt), \
(unsigned short)sizeof(longopt), \
}
#define opt_match(s, l, name) \
((((l) > rb_strlen_lit(name)) ? (s)[rb_strlen_lit(name)] == '=' : \
(l) == rb_strlen_lit(name)) && \
memcmp((s), name, rb_strlen_lit(name)) == 0 && \
(((s) += rb_strlen_lit(name)), 1))
#endif

58
mjit.c
View File

@ -19,6 +19,7 @@
#include "id_table.h"
#include "internal.h"
#include "internal/class.h"
#include "internal/cmdlineopt.h"
#include "internal/cont.h"
#include "internal/file.h"
#include "internal/hash.h"
@ -692,6 +693,63 @@ split_flags(const char *flags)
return ret;
}
#define opt_match_noarg(s, l, name) \
opt_match(s, l, name) && (*(s) ? (rb_warn("argument to --mjit-" name " is ignored"), 1) : 1)
#define opt_match_arg(s, l, name) \
opt_match(s, l, name) && (*(s) ? 1 : (rb_raise(rb_eRuntimeError, "--mjit-" name " needs an argument"), 0))
void
mjit_setup_options(const char *s, struct mjit_options *mjit_opt)
{
const size_t l = strlen(s);
if (l == 0) {
return;
}
else if (opt_match_noarg(s, l, "warnings")) {
mjit_opt->warnings = 1;
}
else if (opt_match(s, l, "debug")) {
if (*s)
mjit_opt->debug_flags = strdup(s + 1);
else
mjit_opt->debug = 1;
}
else if (opt_match_noarg(s, l, "wait")) {
mjit_opt->wait = 1;
}
else if (opt_match_noarg(s, l, "save-temps")) {
mjit_opt->save_temps = 1;
}
else if (opt_match(s, l, "verbose")) {
mjit_opt->verbose = *s ? atoi(s + 1) : 1;
}
else if (opt_match_arg(s, l, "max-cache")) {
mjit_opt->max_cache_size = atoi(s + 1);
}
else if (opt_match_arg(s, l, "min-calls")) {
mjit_opt->min_calls = atoi(s + 1);
}
else {
rb_raise(rb_eRuntimeError,
"invalid MJIT option `%s' (--help will show valid MJIT options)", s);
}
}
#define M(shortopt, longopt, desc) RUBY_OPT_MESSAGE(shortopt, longopt, desc)
const struct ruby_opt_message mjit_option_messages[] = {
M("--mjit-warnings", "", "Enable printing JIT warnings"),
M("--mjit-debug", "", "Enable JIT debugging (very slow), or add cflags if specified"),
M("--mjit-wait", "", "Wait until JIT compilation finishes every time (for testing)"),
M("--mjit-save-temps", "", "Save JIT temporary files in $TMP or /tmp (for testing)"),
M("--mjit-verbose=num", "", "Print JIT logs of level num or less to stderr (default: 0)"),
M("--mjit-max-cache=num", "", "Max number of methods to be JIT-ed in a cache (default: "
STRINGIZE(DEFAULT_MAX_CACHE_SIZE) ")"),
M("--mjit-min-calls=num", "", "Number of calls to trigger JIT (for testing, default: "
STRINGIZE(DEFAULT_MIN_CALLS_TO_ADD) ")"),
{0}
};
#undef M
// 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.

131
ruby.c
View File

@ -47,6 +47,7 @@
#include "dln.h"
#include "eval_intern.h"
#include "internal.h"
#include "internal/cmdlineopt.h"
#include "internal/error.h"
#include "internal/file.h"
#include "internal/inits.h"
@ -58,8 +59,6 @@
#include "internal/parse.h"
#include "internal/process.h"
#include "internal/variable.h"
#include "mjit.h"
#include "yjit.h"
#include "ruby/encoding.h"
#include "ruby/thread.h"
#include "ruby/util.h"
@ -159,13 +158,6 @@ enum dump_flag_bits {
DUMP_BIT(insns) | DUMP_BIT(insns_without_opt))
};
typedef struct ruby_cmdline_options ruby_cmdline_options_t;
typedef struct {
unsigned int mask;
unsigned int set;
} ruby_features_t;
static inline void
rb_feature_set_to(ruby_features_t *feat, unsigned int bit_mask, unsigned int bit_set)
{
@ -179,38 +171,6 @@ rb_feature_set_to(ruby_features_t *feat, unsigned int bit_mask, unsigned int bit
#define FEATURE_SET_RESTORE(feat, save) FEATURE_SET_TO(feat, (save).mask, (save).set & (save).mask)
#define FEATURE_SET_P(feat, bits) ((feat).set & (bits))
struct ruby_cmdline_options {
const char *script;
VALUE script_name;
VALUE e_script;
struct {
struct {
VALUE name;
int index;
} enc;
} src, ext, intern;
VALUE req_list;
ruby_features_t features;
ruby_features_t warn;
unsigned int dump;
#if USE_MJIT
struct mjit_options mjit;
#endif
#if YJIT_SUPPORTED_P
struct rb_yjit_options yjit;
#endif
int sflag, xflag;
unsigned int warning: 1;
unsigned int verbose: 1;
unsigned int do_loop: 1;
unsigned int do_print: 1;
unsigned int do_line: 1;
unsigned int do_split: 1;
unsigned int do_search: 1;
unsigned int setids: 2;
};
static void init_ids(ruby_cmdline_options_t *);
#define src_encoding_index GET_VM()->src_encoding_index
@ -289,21 +249,14 @@ usage(const char *name, int help, int highlight, int columns)
/* This message really ought to be max 23 lines.
* Removed -h because the user already knows that option. Others? */
struct message {
const char *str;
unsigned short namelen, secondlen;
};
#define M(shortopt, longopt, desc) { \
shortopt " " longopt " " desc, \
(unsigned short)sizeof(shortopt), \
(unsigned short)sizeof(longopt), \
}
#define M(shortopt, longopt, desc) RUBY_OPT_MESSAGE(shortopt, longopt, desc)
#if YJIT_SUPPORTED_P
# define PLATFORM_JIT_OPTION "--yjit"
#else
# define PLATFORM_JIT_OPTION "--mjit"
#endif
static const struct message usage_msg[] = {
static const struct ruby_opt_message usage_msg[] = {
M("-0[octal]", "", "specify record separator (\\0, if no argument)"),
M("-a", "", "autosplit mode with -n or -p (splits $_ into $F)"),
M("-c", "", "check syntax only"),
@ -333,7 +286,7 @@ usage(const char *name, int help, int highlight, int columns)
#endif
M("-h", "", "show this message, --help for more info"),
};
static const struct message help_msg[] = {
static const struct ruby_opt_message help_msg[] = {
M("--copyright", "", "print the copyright"),
M("--dump={insns|parsetree|...}[,...]", "",
"dump debug information. see below for available dump list"),
@ -346,14 +299,14 @@ usage(const char *name, int help, int highlight, int columns)
M("--version", "", "print the version number, then exit"),
M("--help", "", "show this message, -h for short message"),
};
static const struct message dumps[] = {
static const struct ruby_opt_message dumps[] = {
M("insns", "", "instruction sequences"),
M("insns_without_opt", "", "instruction sequences compiled with no optimization"),
M("yydebug", "", "yydebug of yacc parser generator"),
M("parsetree", "", "AST"),
M("parsetree_with_comment", "", "AST with comments"),
};
static const struct message features[] = {
static const struct ruby_opt_message features[] = {
M("gems", "", "rubygems (only for debugging, default: "DEFAULT_RUBYGEMS_ENABLED")"),
M("error_highlight", "", "error_highlight (default: "DEFAULT_RUBYGEMS_ENABLED")"),
M("did_you_mean", "", "did_you_mean (default: "DEFAULT_RUBYGEMS_ENABLED")"),
@ -366,23 +319,15 @@ usage(const char *name, int help, int highlight, int columns)
M("yjit", "", "in-process JIT compiler (default: disabled)"),
#endif
};
static const struct message warn_categories[] = {
static const struct ruby_opt_message warn_categories[] = {
M("deprecated", "", "deprecated features"),
M("experimental", "", "experimental features"),
};
#if USE_MJIT
static const struct message mjit_options[] = {
M("--mjit-warnings", "", "Enable printing JIT warnings"),
M("--mjit-debug", "", "Enable JIT debugging (very slow), or add cflags if specified"),
M("--mjit-wait", "", "Wait until JIT compilation finishes every time (for testing)"),
M("--mjit-save-temps", "", "Save JIT temporary files in $TMP or /tmp (for testing)"),
M("--mjit-verbose=num", "", "Print JIT logs of level num or less to stderr (default: 0)"),
M("--mjit-max-cache=num", "", "Max number of methods to be JIT-ed in a cache (default: 10000)"),
M("--mjit-min-calls=num", "", "Number of calls to trigger JIT (for testing, default: 10000)"),
};
extern const struct ruby_opt_message mjit_option_messages[];
#endif
#if YJIT_SUPPORTED_P
static const struct message yjit_options[] = {
static const struct ruby_opt_message yjit_options[] = {
#if YJIT_STATS
M("--yjit-stats", "", "Enable collecting YJIT statistics"),
#endif
@ -420,8 +365,8 @@ usage(const char *name, int help, int highlight, int columns)
SHOW(warn_categories[i]);
#if USE_MJIT
printf("%s""MJIT options (experimental):%s\n", sb, se);
for (i = 0; i < numberof(mjit_options); ++i)
SHOW(mjit_options[i]);
for (i = 0; mjit_option_messages[i].str; ++i)
SHOW(mjit_option_messages[i]);
#endif
#if YJIT_SUPPORTED_P
printf("%s""YJIT options (experimental):%s\n", sb, se);
@ -1082,16 +1027,6 @@ set_option_encoding_once(const char *type, VALUE *name, const char *e, long elen
#define set_source_encoding_once(opt, e, elen) \
set_option_encoding_once("source", &(opt)->src.enc.name, (e), (elen))
#define opt_match(s, l, name) \
((((l) > rb_strlen_lit(name)) ? (s)[rb_strlen_lit(name)] == '=' : \
(l) == rb_strlen_lit(name)) && \
memcmp((s), name, rb_strlen_lit(name)) == 0 && \
(((s) += rb_strlen_lit(name)), 1))
#define opt_match_noarg(s, l, name) \
opt_match(s, l, name) && (*(s) ? (rb_warn("argument to --jit-" name " is ignored"), 1) : 1)
#define opt_match_arg(s, l, name) \
opt_match(s, l, name) && (*(s) ? 1 : (rb_raise(rb_eRuntimeError, "--jit-" name " needs an argument"), 0))
#define yjit_opt_match_noarg(s, l, name) \
opt_match(s, l, name) && (*(s) ? (rb_warn("argument to --yjit-" name " is ignored"), 1) : 1)
#define yjit_opt_match_arg(s, l, name) \
@ -1130,45 +1065,6 @@ setup_yjit_options(const char *s, struct rb_yjit_options *yjit_opt)
}
#endif
#if USE_MJIT
static void
setup_mjit_options(const char *s, struct mjit_options *mjit_opt)
{
const size_t l = strlen(s);
if (l == 0) {
return;
}
else if (opt_match_noarg(s, l, "warnings")) {
mjit_opt->warnings = 1;
}
else if (opt_match(s, l, "debug")) {
if (*s)
mjit_opt->debug_flags = strdup(s + 1);
else
mjit_opt->debug = 1;
}
else if (opt_match_noarg(s, l, "wait")) {
mjit_opt->wait = 1;
}
else if (opt_match_noarg(s, l, "save-temps")) {
mjit_opt->save_temps = 1;
}
else if (opt_match(s, l, "verbose")) {
mjit_opt->verbose = *s ? atoi(s + 1) : 1;
}
else if (opt_match_arg(s, l, "max-cache")) {
mjit_opt->max_cache_size = atoi(s + 1);
}
else if (opt_match_arg(s, l, "min-calls")) {
mjit_opt->min_calls = atoi(s + 1);
}
else {
rb_raise(rb_eRuntimeError,
"invalid MJIT option `%s' (--help will show valid MJIT options)", s);
}
}
#endif
static long
proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt)
{
@ -1546,8 +1442,9 @@ proc_options(long argc, char **argv, ruby_cmdline_options_t *opt, int envopt)
}
else if (is_option_with_optarg("mjit", '-', true, false, false)) {
#if USE_MJIT
extern void mjit_setup_options(const char *s, struct mjit_options *mjit_opt);
FEATURE_SET(opt->features, FEATURE_BIT(mjit));
setup_mjit_options(s, &opt->mjit);
mjit_setup_options(s, &opt->mjit);
#else
rb_warn("MJIT support is disabled.");
#endif