diff --git a/Cargo.toml b/Cargo.toml index 6f61e5f95c..3f373fdace 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,8 +22,7 @@ path = "jit.rs" [features] disasm = ["yjit?/disasm", "zjit?/disasm"] -# TODO(GH-642) Turning this on trips a btest failure. -runtime_checks = [] # ["yjit?/runtime_checks", "zjit?/runtime_checks"] +runtime_checks = ["yjit?/runtime_checks", "zjit?/runtime_checks"] yjit = [ "dep:yjit" ] zjit = [ "dep:zjit" ] diff --git a/shape.h b/shape.h index 63d5534d46..a418dc7821 100644 --- a/shape.h +++ b/shape.h @@ -48,7 +48,9 @@ enum shape_id_fl_type { // This masks allows to check if a shape_id contains any ivar. // It rely on ROOT_SHAPE_WITH_OBJ_ID==1. -#define SHAPE_ID_HAS_IVAR_MASK (SHAPE_ID_FL_TOO_COMPLEX | (SHAPE_ID_OFFSET_MASK - 1)) +enum { + SHAPE_ID_HAS_IVAR_MASK = SHAPE_ID_FL_TOO_COMPLEX | (SHAPE_ID_OFFSET_MASK - 1), +}; // The interpreter doesn't care about frozen status or slot size when reading ivars. // So we normalize shape_id by clearing these bits to improve cache hits. diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs index a0446ad17b..7c8ce7bce5 100644 --- a/yjit/bindgen/src/main.rs +++ b/yjit/bindgen/src/main.rs @@ -103,6 +103,7 @@ fn main() { .allowlist_function("rb_yjit_shape_capacity") .allowlist_function("rb_yjit_shape_index") .allowlist_var("SHAPE_ID_NUM_BITS") + .allowlist_var("SHAPE_ID_HAS_IVAR_MASK") // From ruby/internal/intern/object.h .allowlist_function("rb_obj_is_kind_of") @@ -228,7 +229,6 @@ fn main() { .allowlist_function("rb_obj_as_string_result") .allowlist_function("rb_str_byte_substr") .allowlist_function("rb_str_substr_two_fixnums") - .allowlist_function("rb_str_dup_m") // From include/ruby/internal/intern/parse.h .allowlist_function("rb_backref_get") diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs index 66932fd46c..b8b15adc8b 100644 --- a/yjit/src/codegen.rs +++ b/yjit/src/codegen.rs @@ -6278,9 +6278,14 @@ fn jit_rb_str_dup( let recv_opnd = asm.stack_pop(1); let recv_opnd = asm.load(recv_opnd); + let shape_id_offset = unsafe { rb_shape_id_offset() }; + let shape_opnd = Opnd::mem(64, recv_opnd, shape_id_offset); + asm.test(shape_opnd, Opnd::UImm(SHAPE_ID_HAS_IVAR_MASK as u64)); + asm.jnz(Target::side_exit(Counter::send_str_dup_exivar)); + // Call rb_str_dup let stack_ret = asm.stack_push(Type::CString); - let ret_opnd = asm.ccall(rb_str_dup_m as *const u8, vec![recv_opnd]); + let ret_opnd = asm.ccall(rb_str_dup as *const u8, vec![recv_opnd]); asm.mov(stack_ret, ret_opnd); true diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index e36b6f9f5f..9b871c9e7c 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -689,6 +689,8 @@ pub const VM_ENV_FLAG_ISOLATED: vm_frame_env_flags = 16; pub type vm_frame_env_flags = u32; pub type attr_index_t = u16; pub type shape_id_t = u32; +pub const SHAPE_ID_HAS_IVAR_MASK: _bindgen_ty_37 = 134742014; +pub type _bindgen_ty_37 = u32; #[repr(C)] pub struct rb_cvar_class_tbl_entry { pub index: u32, @@ -1120,7 +1122,6 @@ extern "C" { pub fn rb_gvar_set(arg1: ID, arg2: VALUE) -> VALUE; pub fn rb_ensure_iv_list_size(obj: VALUE, current_len: u32, newsize: u32); pub fn rb_vm_barrier(); - pub fn rb_str_dup_m(str_: VALUE) -> VALUE; pub fn rb_str_byte_substr(str_: VALUE, beg: VALUE, len: VALUE) -> VALUE; pub fn rb_str_substr_two_fixnums( str_: VALUE,