summaryrefslogtreecommitdiff
path: root/yjit
diff options
context:
space:
mode:
Diffstat (limited to 'yjit')
-rw-r--r--yjit/bindgen/src/main.rs3
-rw-r--r--yjit/src/asm/x86_64/mod.rs10
-rw-r--r--yjit/src/asm/x86_64/tests.rs1
-rw-r--r--yjit/src/backend/x86_64/mod.rs30
-rw-r--r--yjit/src/codegen.rs10
-rw-r--r--yjit/src/cruby.rs12
-rw-r--r--yjit/src/cruby_bindings.inc.rs28
7 files changed, 43 insertions, 51 deletions
diff --git a/yjit/bindgen/src/main.rs b/yjit/bindgen/src/main.rs
index a139892741..41d383f8bd 100644
--- a/yjit/bindgen/src/main.rs
+++ b/yjit/bindgen/src/main.rs
@@ -95,13 +95,13 @@ fn main() {
// From shape.h
.allowlist_function("rb_obj_shape_id")
- .allowlist_function("rb_shape_lookup")
.allowlist_function("rb_shape_id_offset")
.allowlist_function("rb_shape_get_iv_index")
.allowlist_function("rb_shape_transition_add_ivar_no_warnings")
.allowlist_function("rb_yjit_shape_obj_too_complex_p")
.allowlist_function("rb_yjit_shape_too_complex_p")
.allowlist_function("rb_yjit_shape_capacity")
+ .allowlist_function("rb_yjit_shape_index")
.allowlist_var("SHAPE_ID_NUM_BITS")
// From ruby/internal/intern/object.h
@@ -228,6 +228,7 @@ 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/asm/x86_64/mod.rs b/yjit/src/asm/x86_64/mod.rs
index fbbfa714d8..0ef5e92117 100644
--- a/yjit/src/asm/x86_64/mod.rs
+++ b/yjit/src/asm/x86_64/mod.rs
@@ -1027,7 +1027,10 @@ pub fn mov(cb: &mut CodeBlock, dst: X86Opnd, src: X86Opnd) {
}
let output_num_bits:u32 = if mem.num_bits > 32 { 32 } else { mem.num_bits.into() };
- assert!(imm_num_bits(imm.value) <= (output_num_bits as u8));
+ assert!(
+ mem.num_bits < 64 || imm_num_bits(imm.value) <= (output_num_bits as u8),
+ "immediate value should be small enough to survive sign extension"
+ );
cb.write_int(imm.value as u64, output_num_bits);
},
// M + UImm
@@ -1042,7 +1045,10 @@ pub fn mov(cb: &mut CodeBlock, dst: X86Opnd, src: X86Opnd) {
}
let output_num_bits = if mem.num_bits > 32 { 32 } else { mem.num_bits.into() };
- assert!(imm_num_bits(uimm.value as i64) <= (output_num_bits as u8));
+ assert!(
+ mem.num_bits < 64 || imm_num_bits(uimm.value as i64) <= (output_num_bits as u8),
+ "immediate value should be small enough to survive sign extension"
+ );
cb.write_int(uimm.value, output_num_bits);
},
// * + Imm/UImm
diff --git a/yjit/src/asm/x86_64/tests.rs b/yjit/src/asm/x86_64/tests.rs
index 5ae983270f..eefcbfd52e 100644
--- a/yjit/src/asm/x86_64/tests.rs
+++ b/yjit/src/asm/x86_64/tests.rs
@@ -193,6 +193,7 @@ fn test_mov() {
check_bytes("48c7470801000000", |cb| mov(cb, mem_opnd(64, RDI, 8), imm_opnd(1)));
//check_bytes("67c7400411000000", |cb| mov(cb, mem_opnd(32, EAX, 4), imm_opnd(0x34))); // We don't distinguish between EAX and RAX here - that's probably fine?
check_bytes("c7400411000000", |cb| mov(cb, mem_opnd(32, RAX, 4), imm_opnd(17)));
+ check_bytes("c7400401000080", |cb| mov(cb, mem_opnd(32, RAX, 4), uimm_opnd(0x80000001)));
check_bytes("41895814", |cb| mov(cb, mem_opnd(32, R8, 20), EBX));
check_bytes("4d8913", |cb| mov(cb, mem_opnd(64, R11, 0), R10));
check_bytes("48c742f8f4ffffff", |cb| mov(cb, mem_opnd(64, RDX, -8), imm_opnd(-12)));
diff --git a/yjit/src/backend/x86_64/mod.rs b/yjit/src/backend/x86_64/mod.rs
index c0d42e79e6..ef435bca7e 100644
--- a/yjit/src/backend/x86_64/mod.rs
+++ b/yjit/src/backend/x86_64/mod.rs
@@ -315,19 +315,24 @@ impl Assembler
let opnd1 = asm.load(*src);
asm.mov(*dest, opnd1);
},
- (Opnd::Mem(_), Opnd::UImm(value)) => {
- // 32-bit values will be sign-extended
- if imm_num_bits(*value as i64) > 32 {
+ (Opnd::Mem(Mem { num_bits, .. }), Opnd::UImm(value)) => {
+ // For 64 bit destinations, 32-bit values will be sign-extended
+ if *num_bits == 64 && imm_num_bits(*value as i64) > 32 {
let opnd1 = asm.load(*src);
asm.mov(*dest, opnd1);
} else {
asm.mov(*dest, *src);
}
},
- (Opnd::Mem(_), Opnd::Imm(value)) => {
- if imm_num_bits(*value) > 32 {
+ (Opnd::Mem(Mem { num_bits, .. }), Opnd::Imm(value)) => {
+ // For 64 bit destinations, 32-bit values will be sign-extended
+ if *num_bits == 64 && imm_num_bits(*value) > 32 {
let opnd1 = asm.load(*src);
asm.mov(*dest, opnd1);
+ } else if uimm_num_bits(*value as u64) <= *num_bits {
+ // If the bit string is short enough for the destination, use the unsigned representation.
+ // Note that 64-bit and negative values are ruled out.
+ asm.mov(*dest, Opnd::UImm(*value as u64));
} else {
asm.mov(*dest, *src);
}
@@ -1317,4 +1322,19 @@ mod tests {
0x13: mov qword ptr [rbx], rax
"});
}
+
+ #[test]
+ fn test_mov_m32_imm32() {
+ let (mut asm, mut cb) = setup_asm();
+
+ let shape_opnd = Opnd::mem(32, C_RET_OPND, 0);
+ asm.mov(shape_opnd, Opnd::UImm(0x8000_0001));
+ asm.mov(shape_opnd, Opnd::Imm(0x8000_0001));
+
+ asm.compile_with_num_regs(&mut cb, 0);
+ assert_disasm!(cb, "c70001000080c70001000080", {"
+ 0x0: mov dword ptr [rax], 0x80000001
+ 0x6: mov dword ptr [rax], 0x80000001
+ "});
+ }
}
diff --git a/yjit/src/codegen.rs b/yjit/src/codegen.rs
index 5f7d61f8b3..3e08857295 100644
--- a/yjit/src/codegen.rs
+++ b/yjit/src/codegen.rs
@@ -3128,8 +3128,6 @@ fn gen_set_ivar(
if new_shape_too_complex {
Some((next_shape_id, None, 0_usize))
} else {
- let current_shape = unsafe { rb_shape_lookup(current_shape_id) };
-
let current_capacity = unsafe { rb_yjit_shape_capacity(current_shape_id) };
let next_capacity = unsafe { rb_yjit_shape_capacity(next_shape_id) };
@@ -3138,7 +3136,7 @@ fn gen_set_ivar(
let needs_extension = next_capacity != current_capacity;
// We can write to the object, but we need to transition the shape
- let ivar_index = unsafe { (*current_shape).next_field_index } as usize;
+ let ivar_index = unsafe { rb_yjit_shape_index(next_shape_id) } as usize;
let needs_extension = if needs_extension {
Some((current_capacity, next_capacity))
@@ -6277,16 +6275,12 @@ fn jit_rb_str_dup(
jit_prepare_call_with_gc(jit, asm);
- // Check !FL_ANY_RAW(str, FL_EXIVAR), which is part of BARE_STRING_P.
let recv_opnd = asm.stack_pop(1);
let recv_opnd = asm.load(recv_opnd);
- let flags_opnd = Opnd::mem(64, recv_opnd, RUBY_OFFSET_RBASIC_FLAGS);
- asm.test(flags_opnd, Opnd::Imm(RUBY_FL_EXIVAR as i64));
- 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 as *const u8, vec![recv_opnd]);
+ let ret_opnd = asm.ccall(rb_str_dup_m as *const u8, vec![recv_opnd]);
asm.mov(stack_ret, ret_opnd);
true
diff --git a/yjit/src/cruby.rs b/yjit/src/cruby.rs
index ecb6475319..725a29fa70 100644
--- a/yjit/src/cruby.rs
+++ b/yjit/src/cruby.rs
@@ -448,18 +448,6 @@ impl VALUE {
unsafe { rb_obj_shape_id(self) }
}
- pub fn shape_of(self) -> *mut rb_shape {
- unsafe {
- let shape = rb_shape_lookup(self.shape_id_of());
-
- if shape.is_null() {
- panic!("Shape should not be null");
- } else {
- shape
- }
- }
- }
-
pub fn embedded_p(self) -> bool {
unsafe {
FL_TEST_RAW(self, VALUE(ROBJECT_EMBED as usize)) != VALUE(0)
diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs
index 23682ac63c..1d7ffca165 100644
--- a/yjit/src/cruby_bindings.inc.rs
+++ b/yjit/src/cruby_bindings.inc.rs
@@ -225,10 +225,11 @@ pub const RUBY_FL_PROMOTED: ruby_fl_type = 32;
pub const RUBY_FL_UNUSED6: ruby_fl_type = 64;
pub const RUBY_FL_FINALIZE: ruby_fl_type = 128;
pub const RUBY_FL_TAINT: ruby_fl_type = 0;
+pub const RUBY_FL_EXIVAR: ruby_fl_type = 0;
pub const RUBY_FL_SHAREABLE: ruby_fl_type = 256;
pub const RUBY_FL_UNTRUSTED: ruby_fl_type = 0;
pub const RUBY_FL_UNUSED9: ruby_fl_type = 512;
-pub const RUBY_FL_EXIVAR: ruby_fl_type = 1024;
+pub const RUBY_FL_UNUSED10: ruby_fl_type = 1024;
pub const RUBY_FL_FREEZE: ruby_fl_type = 2048;
pub const RUBY_FL_USER0: ruby_fl_type = 4096;
pub const RUBY_FL_USER1: ruby_fl_type = 8192;
@@ -409,6 +410,7 @@ pub const imemo_parser_strterm: imemo_type = 10;
pub const imemo_callinfo: imemo_type = 11;
pub const imemo_callcache: imemo_type = 12;
pub const imemo_constcache: imemo_type = 13;
+pub const imemo_class_fields: imemo_type = 14;
pub type imemo_type = u32;
#[repr(C)]
#[derive(Debug, Copy, Clone)]
@@ -687,27 +689,6 @@ 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 type redblack_id_t = u32;
-pub type redblack_node_t = redblack_node;
-#[repr(C)]
-pub struct rb_shape {
- pub edges: VALUE,
- pub edge_name: ID,
- pub ancestor_index: *mut redblack_node_t,
- pub parent_id: shape_id_t,
- pub next_field_index: attr_index_t,
- pub capacity: attr_index_t,
- pub type_: u8,
-}
-pub type rb_shape_t = rb_shape;
-#[repr(C)]
-#[derive(Debug, Copy, Clone)]
-pub struct redblack_node {
- pub key: ID,
- pub value: *mut rb_shape_t,
- pub l: redblack_id_t,
- pub r: redblack_id_t,
-}
#[repr(C)]
pub struct rb_cvar_class_tbl_entry {
pub index: u32,
@@ -1132,7 +1113,6 @@ extern "C" {
pub fn rb_obj_info(obj: VALUE) -> *const ::std::os::raw::c_char;
pub fn rb_ec_stack_check(ec: *mut rb_execution_context_struct) -> ::std::os::raw::c_int;
pub fn rb_shape_id_offset() -> i32;
- pub fn rb_shape_lookup(shape_id: shape_id_t) -> *mut rb_shape_t;
pub fn rb_obj_shape_id(obj: VALUE) -> shape_id_t;
pub fn rb_shape_get_iv_index(shape_id: shape_id_t, id: ID, value: *mut attr_index_t) -> bool;
pub fn rb_shape_transition_add_ivar_no_warnings(obj: VALUE, id: ID) -> shape_id_t;
@@ -1140,6 +1120,7 @@ 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,
@@ -1264,6 +1245,7 @@ extern "C" {
pub fn rb_yjit_shape_too_complex_p(shape_id: shape_id_t) -> bool;
pub fn rb_yjit_shape_obj_too_complex_p(obj: VALUE) -> bool;
pub fn rb_yjit_shape_capacity(shape_id: shape_id_t) -> attr_index_t;
+ pub fn rb_yjit_shape_index(shape_id: shape_id_t) -> attr_index_t;
pub fn rb_yjit_assert_holding_vm_lock();
pub fn rb_yjit_sendish_sp_pops(ci: *const rb_callinfo) -> usize;
pub fn rb_yjit_invokeblock_sp_pops(ci: *const rb_callinfo) -> usize;