summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTakashi Kokubun <[email protected]>2023-07-24 13:51:46 -0700
committer<[email protected]>2023-07-24 13:51:46 -0700
commitcef60e93e6db859b47c818f745be809feb04ae48 ()
tree60ac5fe6f0c41aa72b152656d6ce426b1c708d70
parentc4e893ceb5811f3436f1e16cab769a16469b56b0 (diff)
YJIT: Fallback send instructions to vm_sendish (#8106)
Notes: Merged-By: k0kubun <[email protected]>
-rw-r--r--test/ruby/test_yjit.rb6
-rw-r--r--vm_exec.h10
-rw-r--r--vm_insnhelper.c36
-rw-r--r--yjit.c14
-rw-r--r--yjit/bindgen/src/main.rs2
-rw-r--r--yjit/src/codegen.rs115
-rw-r--r--yjit/src/cruby_bindings.inc.rs2
7 files changed, 178 insertions, 7 deletions
@@ -548,7 +548,7 @@ class TestYJIT < Test::Unit::TestCase
def test_getblockparamproxy
# Currently two side exits as OPTIMIZED_METHOD_TYPE_CALL is unimplemented
- assert_compiles(<<~'RUBY', insns: [:getblockparamproxy], exits: { opt_send_without_block: 2 })
def foo &blk
p blk.call
p blk.call
@@ -607,7 +607,7 @@ class TestYJIT < Test::Unit::TestCase
def test_send_kwargs
# For now, this side-exits when calls include keyword args
- assert_compiles(<<~'RUBY', result: "2#a:1,b:2/A", exits: {opt_send_without_block: 1})
def internal_method(**kw)
"#{kw.size}##{kw.keys.map { |k| "#{k}:#{kw[k]}" }.join(",")}"
end
@@ -647,7 +647,7 @@ class TestYJIT < Test::Unit::TestCase
def test_send_kwargs_splat
# For now, this side-exits when calling with a splat
- assert_compiles(<<~'RUBY', result: "2#a:1,b:2/B", exits: {opt_send_without_block: 1})
def internal_method(**kw)
"#{kw.size}##{kw.keys.map { |k| "#{k}:#{kw[k]}" }.join(",")}"
end
@@ -169,10 +169,20 @@ default: \
#define THROW_EXCEPTION(exc) return (VALUE)(exc)
#endif
#define JIT_EXEC(ec, val) do { \
rb_jit_func_t func; \
if (val == Qundef && (func = jit_compile(ec))) { \
val = func(ec, ec->cfp); \
if (ec->tag->state) THROW_EXCEPTION(val); \
} \
} while (0)
@@ -5528,6 +5528,42 @@ vm_sendish(
return val;
}
/* object.c */
VALUE rb_nil_to_s(VALUE);
VALUE rb_true_to_s(VALUE);
@@ -1122,6 +1122,20 @@ rb_yjit_assert_holding_vm_lock(void)
ASSERT_vm_locking();
}
// Primitives used by yjit.rb
VALUE rb_yjit_stats_enabled_p(rb_execution_context_t *ec, VALUE self);
VALUE rb_yjit_trace_exit_locations_enabled_p(rb_execution_context_t *ec, VALUE self);
@@ -325,6 +325,8 @@ fn main() {
.allowlist_function("rb_yjit_icache_invalidate")
.allowlist_function("rb_optimized_call")
.allowlist_function("rb_yjit_assert_holding_vm_lock")
// from vm_sync.h
.allowlist_function("rb_vm_barrier")
@@ -6428,6 +6428,38 @@ fn gen_struct_aset(
Some(EndBlock)
}
fn gen_send_general(
jit: &mut JITState,
asm: &mut Assembler,
@@ -6909,9 +6941,22 @@ fn gen_opt_send_without_block(
asm: &mut Assembler,
ocb: &mut OutlinedCb,
) -> Option<CodegenStatus> {
let cd = jit.get_arg(0).as_ptr();
- gen_send_general(jit, asm, ocb, cd, None)
}
fn gen_send(
@@ -6919,9 +6964,24 @@ fn gen_send(
asm: &mut Assembler,
ocb: &mut OutlinedCb,
) -> Option<CodegenStatus> {
let cd = jit.get_arg(0).as_ptr();
let block = jit.get_arg(1).as_optional_ptr();
- return gen_send_general(jit, asm, ocb, cd, block);
}
fn gen_invokeblock(
@@ -6929,13 +6989,36 @@ fn gen_invokeblock(
asm: &mut Assembler,
ocb: &mut OutlinedCb,
) -> Option<CodegenStatus> {
if !jit.at_current_insn() {
defer_compilation(jit, asm, ocb);
return Some(EndBlock);
}
// Get call info
- let cd = jit.get_arg(0).as_ptr();
let ci = unsafe { get_call_data_ci(cd) };
let argc: i32 = unsafe { vm_ci_argc(ci) }.try_into().unwrap();
let flags = unsafe { vm_ci_flag(ci) };
@@ -7065,7 +7148,31 @@ fn gen_invokesuper(
asm: &mut Assembler,
ocb: &mut OutlinedCb,
) -> Option<CodegenStatus> {
- let cd: *const rb_call_data = jit.get_arg(0).as_ptr();
let block: Option<IseqPtr> = jit.get_arg(1).as_optional_ptr();
// Defer compilation so we can specialize on class of receiver
@@ -1336,4 +1336,6 @@ extern "C" {
line: ::std::os::raw::c_int,
);
pub fn rb_yjit_assert_holding_vm_lock();
}