summaryrefslogtreecommitdiff
path: root/yjit.c
diff options
context:
space:
mode:
authorAlan Wu <[email protected]>2024-01-23 12:35:34 -0500
committerAlan Wu <[email protected]>2024-01-23 19:22:57 -0500
commitac1e9e443a0d6a4d4c0801c26d1d8bd33d9eb431 (patch)
treee93ed953f8b4ed28850c8b6c18f6011988cfadd2 /yjit.c
parentc0cabc0a699b2c8b0fded6d0ed85aff4bf102c03 (diff)
YJIT: Fix ruby2_keywords splat+rest and drop bogus checks
YJIT didn't guard for ruby2_keywords hash in case of splat calls that land in methods with a rest parameter, creating incorrect results. The compile-time checks didn't correspond to any actual effects of ruby2_keywords, so it was masking this bug and YJIT was needlessly refusing to compile some code. About 16% of fallback reasons in `lobsters` was due to the ISeq check. We already handle the tagging part with exit_if_supplying_kw_and_has_no_kw() and should now have a dynamic guard for all splat cases. Note for backporting: You also need 7f51959ff1. [Bug #20195]
Diffstat (limited to 'yjit.c')
-rw-r--r--yjit.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/yjit.c b/yjit.c
index d5071cb952..cf6d81092f 100644
--- a/yjit.c
+++ b/yjit.c
@@ -871,6 +871,19 @@ rb_yjit_fix_mod_fix(VALUE recv, VALUE obj)
return rb_fix_mod_fix(recv, obj);
}
+// Return non-zero when `obj` is an array and its last item is a
+// `ruby2_keywords` hash. We don't support this kind of splat.
+size_t
+rb_yjit_ruby2_keywords_splat_p(VALUE obj)
+{
+ if (!RB_TYPE_P(obj, T_ARRAY)) return 0;
+ long len = RARRAY_LEN(obj);
+ if (len == 0) return 0;
+ VALUE last = RARRAY_AREF(obj, len - 1);
+ if (!RB_TYPE_P(last, T_HASH)) return 0;
+ return FL_TEST_RAW(last, RHASH_PASS_AS_KEYWORDS);
+}
+
// Print the Ruby source location of some ISEQ for debugging purposes
void
rb_yjit_dump_iseq_loc(const rb_iseq_t *iseq, uint32_t insn_idx)