summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--vm_core.h5
-rw-r--r--yjit.c6
-rw-r--r--yjit/bindgen/src/main.rs1
-rw-r--r--yjit/src/codegen.rs11
-rw-r--r--yjit/src/cruby.rs6
-rw-r--r--yjit/src/cruby_bindings.inc.rs1
6 files changed, 23 insertions, 7 deletions
diff --git a/vm_core.h b/vm_core.h
index 999f06d403..68adc5eac1 100644
--- a/vm_core.h
+++ b/vm_core.h
@@ -2074,8 +2074,9 @@ rb_ec_ractor_ptr(const rb_execution_context_t *ec)
static inline rb_serial_t
rb_ec_ractor_id(const rb_execution_context_t *ec)
{
- VM_ASSERT(ec->ractor_id == rb_ractor_id(rb_ec_ractor_ptr(ec)));
- return ec->ractor_id;
+ rb_serial_t ractor_id = ec->ractor_id;
+ RUBY_ASSERT(ractor_id);
+ return ractor_id;
}
static inline rb_vm_t *
diff --git a/yjit.c b/yjit.c
index 6c3c9cd001..1cd934c42e 100644
--- a/yjit.c
+++ b/yjit.c
@@ -473,6 +473,12 @@ rb_yjit_invokeblock_sp_pops(const struct rb_callinfo *ci)
return 1 - sp_inc_of_invokeblock(ci); // + 1 to ignore return value push
}
+rb_serial_t
+rb_yjit_cme_ractor_serial(const rb_callable_method_entry_t *cme)
+{
+ return cme->def->body.bmethod.defined_ractor_id;
+}
+
// Setup jit_return to avoid returning a non-Qundef value on a non-FINISH frame.
// See [jit_compile_exception] for details.
void
diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs
index 06c475f3c8..fd99d52904 100644
--- a/yjit/bindgen/src/main.rs
+++ b/yjit/bindgen/src/main.rs
@@ -272,6 +272,7 @@ fn main() {
.allowlist_function("rb_optimized_call")
.allowlist_function("rb_yjit_sendish_sp_pops")
.allowlist_function("rb_yjit_invokeblock_sp_pops")
+ .allowlist_function("rb_yjit_cme_ractor_serial")
.allowlist_function("rb_yjit_set_exception_return")
.allowlist_function("rb_jit_str_concat_codepoint")
.allowlist_type("rstring_offsets")
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index 620bdb8280..606fe6ed70 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -7396,11 +7396,12 @@ fn gen_send_bmethod(
let capture = unsafe { proc_block.as_.captured.as_ref() };
let iseq = unsafe { *capture.code.iseq.as_ref() };
- // Optimize for single ractor mode and avoid runtime check for
- // "defined with an un-shareable Proc in a different Ractor"
- if !assume_single_ractor_mode(jit, asm) {
- gen_counter_incr(jit, asm, Counter::send_bmethod_ractor);
- return None;
+ if !procv.shareable_p() {
+ let ractor_serial = unsafe { rb_yjit_cme_ractor_serial(cme) };
+ asm_comment!(asm, "guard current ractor == {}", ractor_serial);
+ let current_ractor_serial = asm.load(Opnd::mem(64, EC, RUBY_OFFSET_EC_RACTOR_ID));
+ asm.cmp(current_ractor_serial, Opnd::UImm(ractor_serial));
+ asm.jne(Target::side_exit(Counter::send_bmethod_ractor));
}
// Passing a block to a block needs logic different from passing
diff --git a/yjit/src/cruby.rs b/yjit/src/cruby.rs
index 6e6a1810c6..d8497e41e3 100644
--- a/yjit/src/cruby.rs
+++ b/yjit/src/cruby.rs
@@ -361,6 +361,11 @@ impl VALUE {
!self.special_const_p()
}
+ /// Shareability between ractors. `RB_OBJ_SHAREABLE_P()`.
+ pub fn shareable_p(self) -> bool {
+ (self.builtin_flags() & RUBY_FL_SHAREABLE as usize) != 0
+ }
+
/// Return true if the value is a Ruby Fixnum (immediate-size integer)
pub fn fixnum_p(self) -> bool {
let VALUE(cval) = self;
@@ -772,6 +777,7 @@ mod manual_defs {
pub const RUBY_OFFSET_EC_INTERRUPT_FLAG: i32 = 32; // rb_atomic_t (u32)
pub const RUBY_OFFSET_EC_INTERRUPT_MASK: i32 = 36; // rb_atomic_t (u32)
pub const RUBY_OFFSET_EC_THREAD_PTR: i32 = 48;
+ pub const RUBY_OFFSET_EC_RACTOR_ID: i32 = 64;
// Constants from rb_thread_t in vm_core.h
pub const RUBY_OFFSET_THREAD_SELF: i32 = 16;
diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs
index d2347671bb..0cab97ebf4 100644
--- a/yjit/src/cruby_bindings.inc.rs
+++ b/yjit/src/cruby_bindings.inc.rs
@@ -1198,6 +1198,7 @@ extern "C" {
pub fn rb_yjit_shape_index(shape_id: shape_id_t) -> attr_index_t;
pub fn rb_yjit_sendish_sp_pops(ci: *const rb_callinfo) -> usize;
pub fn rb_yjit_invokeblock_sp_pops(ci: *const rb_callinfo) -> usize;
+ pub fn rb_yjit_cme_ractor_serial(cme: *const rb_callable_method_entry_t) -> rb_serial_t;
pub fn rb_yjit_set_exception_return(
cfp: *mut rb_control_frame_t,
leave_exit: *mut ::std::os::raw::c_void,