Skip to content

Commit fde88b5

Browse files
committed
Pack booleans in to an integer
YJIT can only handle built-ins with 4 parameters, so we'll pack the booleans in to an integer to get the params low enough
1 parent 12c0445 commit fde88b5

3 files changed

Lines changed: 21 additions & 8 deletions

File tree

insns.def

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -968,7 +968,7 @@ opt_string_new
968968
vm_cstr_initialize_basic_p(recv)) {
969969

970970
if (argc == 0) {
971-
str = rb_str_new(0, 0);
971+
str = rb_str_buf_new(0);
972972
}
973973
else {
974974
VALUE rbcapa = TOPN(capa_loc);

string.c

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2079,17 +2079,26 @@ rb_str_with_debug_created_info(VALUE str, VALUE path, int line)
20792079
*/
20802080

20812081
static VALUE
2082-
rb_str_init(rb_execution_context_t *ec, VALUE str, VALUE orig, VALUE no_str, VALUE encoding, VALUE no_encoding, VALUE capacity, VALUE no_capacity)
2082+
rb_str_init(rb_execution_context_t *ec, VALUE str, VALUE orig, VALUE encoding, VALUE capacity, VALUE omitted)
20832083
{
20842084
rb_encoding *enc = 0;
2085-
int n = RTEST(no_str) ? 0 : 1;
20862085

2087-
/* A keyword was supplied iff its sentinel is false. Mirror the old
2086+
/* omitted packs the "argument was not supplied" sentinels: bit 0 = orig,
2087+
* bit 1 = encoding, bit 2 = capacity. They arrive in one integer so the
2088+
* builtin call stays within YJIT's invokebuiltin argument limit. */
2089+
const long om = FIX2LONG(omitted);
2090+
const int no_str = om & 1;
2091+
const int no_encoding = om & 2;
2092+
const int no_capacity = om & 4;
2093+
2094+
int n = no_str ? 0 : 1;
2095+
2096+
/* A keyword was supplied iff its sentinel is clear. Mirror the old
20882097
* rb_scan_args/rb_get_kwargs behavior: only touch encoding/capacity
20892098
* when the corresponding keyword was actually passed. */
2090-
if (!RTEST(no_encoding) || !RTEST(no_capacity)) {
2091-
VALUE venc = RTEST(no_encoding) ? Qundef : encoding;
2092-
VALUE vcapa = RTEST(no_capacity) ? Qundef : capacity;
2099+
if (!no_encoding || !no_capacity) {
2100+
VALUE venc = no_encoding ? Qundef : encoding;
2101+
VALUE vcapa = no_capacity ? Qundef : capacity;
20932102
if (!UNDEF_P(venc) && !NIL_P(venc)) {
20942103
enc = rb_to_encoding(venc);
20952104
}

string.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ def initialize(orig = (no_str = true; nil),
3333
capacity: (no_capacity = true; nil))
3434
return self if no_str && no_encoding && no_capacity
3535

36-
Primitive.rb_str_init(orig, no_str, encoding, no_encoding, capacity, no_capacity)
36+
# Pack the "argument was omitted" sentinels into one integer. This keeps the
37+
# builtin call at four arguments, within YJIT's limit for invokebuiltin.
38+
omitted = (no_str ? 1 : 0) | (no_encoding ? 2 : 0) | (no_capacity ? 4 : 0)
39+
40+
Primitive.rb_str_init(orig, encoding, capacity, omitted)
3741
end
3842
end

0 commit comments

Comments
 (0)