Skip to content

Commit 8a43e97

Browse files
committed
ZJIT: Store what Ruby locals a builtin function can read/write
1 parent 9be01bc commit 8a43e97

File tree

4 files changed

+24
-5
lines changed

4 files changed

+24
-5
lines changed

builtin.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,19 @@ struct rb_builtin_function {
1111
// for load
1212
const int index;
1313
const char * const name;
14+
15+
// for JIT analysis
16+
// If every bit is set, the function may reference any local variable
17+
// (including those with an index over 63).
18+
const uint64_t locals_referenced;
1419
};
1520

16-
#define RB_BUILTIN_FUNCTION(_i, _name, _fname, _arity) {\
21+
#define RB_BUILTIN_FUNCTION(_i, _name, _fname, _arity, _locals) {\
1722
.name = _i < 0 ? NULL : #_name, \
1823
.func_ptr = (void *)(uintptr_t)_fname, \
1924
.argc = _arity, \
2025
.index = _i, \
26+
.locals_referenced = _locals, \
2127
}
2228

2329
void rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin_function *table);

tool/mk_builtin_loader.rb

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -289,13 +289,21 @@ def generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_nam
289289

290290
f.puts '{'
291291
lineno += 1
292+
locals_referenced = 0
292293
# locals is nil outside methods
293294
locals&.reverse_each&.with_index{|param, i|
294295
next unless Symbol === param
295296
param = param.to_s
296297
lvar = local_candidates.include?(param)
297298
next unless lvar or local_ptrs.include?(param)
298299
f.puts "VALUE *const #{param}__ptr = (VALUE *)&ec->cfp->ep[#{-3 - i}];"
300+
if i > 63
301+
# That's a lot of locals in a Primitive! Unlikely but possible.
302+
# In that case, set every bit.
303+
locals_referenced = ((1<<64)-1)
304+
else
305+
locals_referenced |= (1 << i)
306+
end
299307
f.puts "MAYBE_UNUSED(const VALUE) #{param} = *#{param}__ptr;" if lvar
300308
lineno += lvar ? 2 : 1
301309
}
@@ -310,7 +318,7 @@ def generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_nam
310318
f.puts
311319
lineno += 3
312320

313-
return lineno, f.string
321+
return lineno, f.string, locals_referenced
314322
end
315323

316324
def mk_builtin_header file
@@ -351,12 +359,14 @@ def mk_builtin_header file
351359
f.puts
352360
lineno = __LINE__ - lineno - 1
353361
line_file = file
362+
reads_writes_locals = {}
354363

355364
inlines.each{|cfunc_name, (body_lineno, text, locals, func_name)|
356365
if String === cfunc_name
357366
f.puts "static VALUE #{cfunc_name}(struct rb_execution_context_struct *ec, const VALUE self)"
358367
lineno += 1
359-
lineno, str = generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_name)
368+
lineno, str, locals_referenced = generate_cexpr(ofile, lineno, line_file, body_lineno, text, locals, func_name)
369+
reads_writes_locals[cfunc_name] = locals_referenced
360370
f.write str
361371
else
362372
# cinit!
@@ -384,9 +394,10 @@ def mk_builtin_header file
384394
f.puts " // table definition"
385395
f.puts " static const struct rb_builtin_function #{table}[] = {"
386396
bs.each.with_index{|(func, (argc, cfunc_name)), i|
387-
f.puts " RB_BUILTIN_FUNCTION(#{i}, #{func}, #{cfunc_name}, #{argc}),"
397+
locals_bitset = "0x"+reads_writes_locals.fetch(cfunc_name, 0).to_s(16)
398+
f.puts " RB_BUILTIN_FUNCTION(#{i}, #{func}, #{cfunc_name}, #{argc}, #{locals_bitset}),"
388399
}
389-
f.puts " RB_BUILTIN_FUNCTION(-1, NULL, NULL, 0),"
400+
f.puts " RB_BUILTIN_FUNCTION(-1, NULL, NULL, 0, 0),"
390401
f.puts " };"
391402

392403
f.puts

yjit/src/cruby_bindings.inc.rs

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

zjit/src/cruby_bindings.inc.rs

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)