diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS index 00180b15f2..15abc79af6 100644 --- a/.github/CODEOWNERS +++ b/.github/CODEOWNERS @@ -7,3 +7,4 @@ yjit* @maximecb @xrxr @tenderlove doc/yjit/* @maximecb @xrxr @tenderlove bootstraptest/test_yjit* @maximecb @xrxr @tenderlove test/ruby/test_yjit* @maximecb @xrxr @tenderlove +.github/workflows/yjit* @maximecb @xrxr @tenderlove diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml index a14169b6f9..826186585d 100644 --- a/.github/workflows/yjit-ubuntu.yml +++ b/.github/workflows/yjit-ubuntu.yml @@ -25,9 +25,7 @@ jobs: # - ubuntu-18.04 yjit_opts: [ "--yjit", - "--yjit --yjit-call-threshold=1 --yjit-max-versions=1", - # "--yjit --yjit-call-threshold=1", - # "--yjit --yjit-call-threshold=2" + "--yjit --yjit-call-threshold=1", ] configure: ["", "cppflags=-DRUBY_DEBUG"] include: diff --git a/doc/yjit/yjit.md b/doc/yjit/yjit.md index f84b989f6d..0da6c15911 100644 --- a/doc/yjit/yjit.md +++ b/doc/yjit/yjit.md @@ -78,6 +78,14 @@ To support disassembly of the generated code, `libcapstone` is also required (`b make -j16 install ``` +On macOS, you may need to specify where to find openssl, libyaml and gdbm: + +``` +# Configure with debugging/stats options for development, build and install +./configure cppflags="-DRUBY_DEBUG -DYJIT_STATS" --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc --disable--install-rdoc --with-opt-dir=$(brew --prefix openssl):$(brew --prefix readline):$(brew --prefix libyaml):$(brew --prefix gdbm) +make -j16 install +``` + Typically configure will choose default C compiler. To specify the C compiler, use ``` # Choosing a specific c compiler diff --git a/ruby.c b/ruby.c index 0c64d4e1ce..c04810acf3 100644 --- a/ruby.c +++ b/ruby.c @@ -1091,6 +1091,9 @@ setup_yjit_options(const char *s, struct rb_yjit_options *yjit_opt) else if (yjit_opt_match_noarg(s, l, "greedy-versioning")) { yjit_opt->greedy_versioning = true; } + else if (yjit_opt_match_noarg(s, l, "no-type-prop")) { + yjit_opt->no_type_prop = true; + } else if (yjit_opt_match_noarg(s, l, "stats")) { yjit_opt->gen_stats = true; } diff --git a/yjit.h b/yjit.h index a3d8594a5d..c254c02cd8 100644 --- a/yjit.h +++ b/yjit.h @@ -29,6 +29,9 @@ struct rb_yjit_options { // Generate versions greedily until the limit is hit bool greedy_versioning; + // Disable the propagation of type information + bool no_type_prop; + // Maximum number of versions per block // 1 means always create generic versions unsigned max_versions; diff --git a/yjit_core.c b/yjit_core.c index 8d9c267908..a395285e1c 100644 --- a/yjit_core.c +++ b/yjit_core.c @@ -26,6 +26,11 @@ Return a pointer to the new stack top static x86opnd_t ctx_stack_push_mapping(ctx_t *ctx, temp_type_mapping_t mapping) { + // If type propagation is disabled, store no types + if (rb_yjit_opts.no_type_prop) { + mapping.type = TYPE_UNKNOWN; + } + // Keep track of the type and mapping of the value if (ctx->stack_size < MAX_TEMP_TYPES) { ctx->temp_mapping[ctx->stack_size] = mapping.mapping; @@ -80,6 +85,7 @@ ctx_stack_push_local(ctx_t *ctx, size_t local_idx) (temp_mapping_t){ .kind = TEMP_LOCAL, .idx = local_idx }, TYPE_UNKNOWN }; + return ctx_stack_push_mapping(ctx, mapping); } @@ -165,7 +171,6 @@ static int type_diff(val_type_t src, val_type_t dst); (dest) = (src); \ } while (false) - /** Upgrade (or "learn") the type of an instruction operand This value must be compatible and at least as specific as the previously known type. @@ -175,6 +180,10 @@ propagated back to its source. static void ctx_upgrade_opnd_type(ctx_t *ctx, insn_opnd_t opnd, val_type_t type) { + // If type propagation is disabled, store no types + if (rb_yjit_opts.no_type_prop) + return; + if (opnd.is_self) { UPGRADE_TYPE(ctx->self_type, type); return; @@ -249,6 +258,10 @@ ctx_set_opnd_mapping(ctx_t *ctx, insn_opnd_t opnd, temp_type_mapping_t type_mapp RUBY_ASSERT(opnd.idx < ctx->stack_size); int stack_idx = ctx->stack_size - 1 - opnd.idx; + // If type propagation is disabled, store no types + if (rb_yjit_opts.no_type_prop) + return; + // If outside of tracked range, do nothing if (stack_idx >= MAX_TEMP_TYPES) return; @@ -265,6 +278,10 @@ Set the type of a local variable static void ctx_set_local_type(ctx_t *ctx, size_t idx, val_type_t type) { + // If type propagation is disabled, store no types + if (rb_yjit_opts.no_type_prop) + return; + if (idx >= MAX_LOCAL_TYPES) return; diff --git a/yjit_iface.c b/yjit_iface.c index 5c9dc891ba..a880a870ed 100644 --- a/yjit_iface.c +++ b/yjit_iface.c @@ -1210,6 +1210,12 @@ rb_yjit_init(struct rb_yjit_options *options) rb_yjit_opts.max_versions = 4; } + // If type propagation is disabled, max 1 version per block + if (rb_yjit_opts.no_type_prop) + { + rb_yjit_opts.max_versions = 1; + } + blocks_assuming_stable_global_constant_state = st_init_numtable(); blocks_assuming_single_ractor_mode = st_init_numtable(); blocks_assuming_bops = st_init_numtable();