diff --git a/jit.c b/jit.c index 1a997605aaf..9bd16eab84c 100644 --- a/jit.c +++ b/jit.c @@ -34,8 +34,8 @@ enum jit_bindgen_constants { // Field offset for prime classext's fields_obj from a class pointer RCLASS_OFFSET_PRIME_FIELDS_OBJ = offsetof(struct RClass_and_rb_classext_t, classext.fields_obj), - // Field offset for fields_obj in RTypedData - RTYPEDDATA_OFFSET_FIELDS_OBJ = offsetof(struct RTypedData, fields_obj), + // Field offset for fields_obj in T_DATA + TDATA_OFFSET_FIELDS_OBJ = offsetof(struct RTypedData, fields_obj), // Field offsets for the RString struct RUBY_OFFSET_RSTRING_LEN = offsetof(struct RString, len), @@ -568,7 +568,7 @@ rb_jit_class_fields_embedded_p(VALUE klass) } bool -rb_jit_typed_data_fields_embedded_p(VALUE obj) +rb_jit_data_fields_embedded_p(VALUE obj) { VALUE fields_obj = RTYPEDDATA(obj)->fields_obj; return !fields_obj || !FL_TEST_RAW(fields_obj, OBJ_FIELD_HEAP); diff --git a/yjit/src/cruby_bindings.inc.rs b/yjit/src/cruby_bindings.inc.rs index ef7f6c0a9ef..ae372711d71 100644 --- a/yjit/src/cruby_bindings.inc.rs +++ b/yjit/src/cruby_bindings.inc.rs @@ -986,7 +986,7 @@ pub type rb_seq_param_keyword_struct = pub const ROBJECT_OFFSET_AS_HEAP_FIELDS: jit_bindgen_constants = 16; pub const ROBJECT_OFFSET_AS_ARY: jit_bindgen_constants = 16; pub const RCLASS_OFFSET_PRIME_FIELDS_OBJ: jit_bindgen_constants = 40; -pub const RTYPEDDATA_OFFSET_FIELDS_OBJ: jit_bindgen_constants = 16; +pub const TDATA_OFFSET_FIELDS_OBJ: jit_bindgen_constants = 16; pub const RUBY_OFFSET_RSTRING_LEN: jit_bindgen_constants = 16; pub const RB_SHAPE_FLAG_SHIFT: jit_bindgen_constants = 32; pub const RUBY_OFFSET_EC_CFP: jit_bindgen_constants = 16; diff --git a/zjit/bindgen/src/main.rs b/zjit/bindgen/src/main.rs index 32b75117c85..59daf0b92fe 100644 --- a/zjit/bindgen/src/main.rs +++ b/zjit/bindgen/src/main.rs @@ -321,8 +321,7 @@ fn main() { .allowlist_function("rb_jit_shape_complex_p") .allowlist_function("rb_jit_multi_ractor_p") .allowlist_function("rb_jit_class_fields_embedded_p") - .allowlist_function("rb_jit_typed_data_p") - .allowlist_function("rb_jit_typed_data_fields_embedded_p") + .allowlist_function("rb_jit_data_fields_embedded_p") .allowlist_function("rb_jit_vm_lock_then_barrier") .allowlist_function("rb_jit_vm_unlock") .allowlist_function("rb_jit_for_each_iseq") diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index c9198abbe4c..7c893a72fe8 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -2551,7 +2551,7 @@ fn gen_guard_type(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, guard asm.cmp(klass, Opnd::Value(expected_class)); asm.jne(jit, side_exit); - } else if guard_type.is_subtype(types::TypedTData) { + } else if guard_type.is_subtype(types::TData) { let side = side_exit(jit, state, GuardType(guard_type)); // Check special constant @@ -2562,11 +2562,11 @@ fn gen_guard_type(jit: &mut JITState, asm: &mut Assembler, val: lir::Opnd, guard asm.cmp(val, Qfalse.into()); asm.je(jit, side.clone()); - // Check the builtin type and RUBY_TYPED_FL_IS_TYPED_DATA with mask and compare + // Check the T_DATA builtin type. let val = asm.load_mem(val); let flags = asm.load(Opnd::mem(VALUE_BITS, val, RUBY_OFFSET_RBASIC_FLAGS)); - let mask = RUBY_T_MASK.to_usize() | RUBY_TYPED_FL_IS_TYPED_DATA.to_usize(); - let expected = RUBY_T_DATA.to_usize() | RUBY_TYPED_FL_IS_TYPED_DATA.to_usize(); + let mask = RUBY_T_MASK.to_usize(); + let expected = RUBY_T_DATA.to_usize(); let masked = asm.and(flags, mask.into()); asm.cmp(masked, expected.into()); asm.jne(jit, side); diff --git a/zjit/src/cruby.rs b/zjit/src/cruby.rs index 14db7c57d75..eb3241b0a2f 100644 --- a/zjit/src/cruby.rs +++ b/zjit/src/cruby.rs @@ -608,15 +608,13 @@ impl VALUE { unsafe { rb_jit_class_fields_embedded_p(self) } } - /// Typed `T_DATA` made from `TypedData_Make_Struct()` (e.g. Thread, ARGF) - pub fn typed_data_p(self) -> bool { + pub fn data_p(self) -> bool { !self.special_const_p() && - self.builtin_type() == RUBY_T_DATA && - 0 != (self.builtin_flags() & RUBY_TYPED_FL_IS_TYPED_DATA.to_usize()) + self.builtin_type() == RUBY_T_DATA } - pub fn typed_data_fields_embedded_p(self) -> bool { - unsafe { rb_jit_typed_data_fields_embedded_p(self) } + pub fn data_fields_embedded_p(self) -> bool { + unsafe { rb_jit_data_fields_embedded_p(self) } } pub fn as_fixnum(self) -> i64 { diff --git a/zjit/src/cruby_bindings.inc.rs b/zjit/src/cruby_bindings.inc.rs index 21a2f6bbb47..dad29087be4 100644 --- a/zjit/src/cruby_bindings.inc.rs +++ b/zjit/src/cruby_bindings.inc.rs @@ -1929,7 +1929,7 @@ pub type zjit_struct_offsets = u32; pub const ROBJECT_OFFSET_AS_HEAP_FIELDS: jit_bindgen_constants = 16; pub const ROBJECT_OFFSET_AS_ARY: jit_bindgen_constants = 16; pub const RCLASS_OFFSET_PRIME_FIELDS_OBJ: jit_bindgen_constants = 40; -pub const RTYPEDDATA_OFFSET_FIELDS_OBJ: jit_bindgen_constants = 16; +pub const TDATA_OFFSET_FIELDS_OBJ: jit_bindgen_constants = 16; pub const RUBY_OFFSET_RSTRING_LEN: jit_bindgen_constants = 16; pub const RB_SHAPE_FLAG_SHIFT: jit_bindgen_constants = 32; pub const RUBY_OFFSET_EC_CFP: jit_bindgen_constants = 16; @@ -2294,7 +2294,7 @@ unsafe extern "C" { pub fn rb_jit_shape_complex_p(shape_id: shape_id_t) -> bool; pub fn rb_jit_multi_ractor_p() -> bool; pub fn rb_jit_class_fields_embedded_p(klass: VALUE) -> bool; - pub fn rb_jit_typed_data_fields_embedded_p(obj: VALUE) -> bool; + pub fn rb_jit_data_fields_embedded_p(obj: VALUE) -> bool; pub fn rb_jit_vm_lock_then_barrier( recursive_lock_level: *mut ::std::os::raw::c_uint, file: *const ::std::os::raw::c_char, diff --git a/zjit/src/hir.rs b/zjit/src/hir.rs index 6ed3076af5d..ddd164425dd 100644 --- a/zjit/src/hir.rs +++ b/zjit/src/hir.rs @@ -4336,8 +4336,8 @@ impl Function { self.push_insn(block, Insn::GuardType { val: recv, guard_type: types::Class, state }) } else if recv_type.flags().is_t_module() { self.push_insn(block, Insn::GuardType { val: recv, guard_type: types::Module, state }) - } else if recv_type.flags().is_typed_data() { - self.push_insn(block, Insn::GuardType { val: recv, guard_type: types::TypedTData, state }) + } else if recv_type.flags().is_t_data() { + self.push_insn(block, Insn::GuardType { val: recv, guard_type: types::TData, state }) } else { // HeapBasicObject is wider than T_OBJECT, but shapes for T_OBJECTs are in a pool of // its own and are guaranteed to be different from shapes of any other T_* types. So @@ -4373,11 +4373,10 @@ impl Function { }); return self.load_ivar_from_fields(block, fields_obj, recv_type.flags().is_fields_embedded(), id, ivar_index); } - if recv_type.flags().is_typed_data() { - // Typed T_DATA: load from fields_obj at fixed offset in RTypedData + if recv_type.flags().is_t_data() { let fields_obj = self.push_insn(block, Insn::LoadField { recv: self_val, id: FieldName::fields_obj, - offset: RTYPEDDATA_OFFSET_FIELDS_OBJ as i32, + offset: TDATA_OFFSET_FIELDS_OBJ as i32, return_type: types::RubyValue, }); return self.load_ivar_from_fields(block, fields_obj, recv_type.flags().is_fields_embedded(), id, ivar_index); diff --git a/zjit/src/hir/opt_tests.rs b/zjit/src/hir/opt_tests.rs index f1d313cb727..2c992a8725e 100644 --- a/zjit/src/hir/opt_tests.rs +++ b/zjit/src/hir/opt_tests.rs @@ -7912,8 +7912,8 @@ mod hir_opt_tests { } #[test] - fn test_optimize_getivar_on_typed_data() { - // Thread is typed T_DATA: uses LoadField chain via RTypedData fields_obj + fn test_optimize_getivar_on_t_data() { + // T_DATA uses fields_obj for instance variables. eval(" class C < Thread def test = @a @@ -7936,7 +7936,7 @@ mod hir_opt_tests { Jump bb3(v4) bb3(v6:BasicObject): PatchPoint SingleRactorMode - v17:TypedTData = GuardType v6, TypedTData + v17:TData = GuardType v6, TData v18:CShape = LoadField v17, :shape_id@0x1000 v19:CShape[0x1001] = GuardBitEquals v18, CShape(0x1001) recompile v20:RubyValue = LoadField v17, :fields_obj@0x1002 @@ -7947,8 +7947,8 @@ mod hir_opt_tests { } #[test] - fn test_optimize_getivar_on_typed_data_complex_fields() { - // Typed T_DATA with enough ivars to force heap field storage + fn test_optimize_getivar_on_t_data_complex_fields() { + // T_DATA with enough ivars to force heap field storage eval(" class C < Thread def test = @var1000 @@ -8260,7 +8260,7 @@ mod hir_opt_tests { } #[test] - fn test_getivar_polymorphic_t_class_and_typed_data() { + fn test_getivar_polymorphic_t_class_and_t_data() { set_call_threshold(3); eval(r#" module Reader @@ -8295,7 +8295,7 @@ mod hir_opt_tests { PatchPoint SingleRactorMode v11:HeapBasicObject = GuardType v6, HeapBasicObject v12:CUInt64 = LoadField v11, :RBASIC_FLAGS@0x1000 - v14:CUInt64[0xffffffff0000005f] = Const CUInt64(0xffffffff0000005f) + v14:CUInt64[0xffffffff0000001f] = Const CUInt64(0xffffffff0000001f) v15:CPtr[CPtr(0x1001)] = Const CPtr(0x1001) v16 = RefineType v15, CUInt64 v17:CInt64 = IntAnd v12, v14 diff --git a/zjit/src/hir_type/gen_hir_type.rb b/zjit/src/hir_type/gen_hir_type.rb index 41f96a7a82e..2eb5ca19328 100644 --- a/zjit/src/hir_type/gen_hir_type.rb +++ b/zjit/src/hir_type/gen_hir_type.rb @@ -134,10 +134,9 @@ nil_exact = final_type "NilClass", c_name: "rb_cNilClass" true_exact = final_type "TrueClass", c_name: "rb_cTrueClass" false_exact = final_type "FalseClass", c_name: "rb_cFalseClass" -# Typed T_DATA objects (RTYPEDDATA_P). These have a distinct memory layout -# for field access (fields_obj at a fixed offset in RTypedData). These -# don't have a common class ancestor below BasicObject. -basic_object.subtype "TypedTData" +# T_DATA objects have a distinct memory layout for field access and don't have a +# common class ancestor below BasicObject. +basic_object.subtype "TData" # Build the cvalue object universe. This is for C-level types that may be # passed around when calling into the Ruby VM or after some strength reduction diff --git a/zjit/src/hir_type/hir_type.inc.rs b/zjit/src/hir_type/hir_type.inc.rs index f4c3bf34891..1dae344b360 100644 --- a/zjit/src/hir_type/hir_type.inc.rs +++ b/zjit/src/hir_type/hir_type.inc.rs @@ -4,7 +4,7 @@ mod bits { pub const Array: u64 = ArrayExact | ArraySubclass; pub const ArrayExact: u64 = 1u64 << 0; pub const ArraySubclass: u64 = 1u64 << 1; - pub const BasicObject: u64 = BasicObjectExact | BasicObjectSubclass | Object | TypedTData; + pub const BasicObject: u64 = BasicObjectExact | BasicObjectSubclass | Object | TData; pub const BasicObjectExact: u64 = 1u64 << 2; pub const BasicObjectSubclass: u64 = 1u64 << 3; pub const Bignum: u64 = 1u64 << 4; @@ -76,7 +76,7 @@ mod bits { pub const Symbol: u64 = DynamicSymbol | StaticSymbol; pub const TrueClass: u64 = 1u64 << 45; pub const Truthy: u64 = BasicObject & !Falsy; - pub const TypedTData: u64 = 1u64 << 46; + pub const TData: u64 = 1u64 << 46; pub const Undef: u64 = 1u64 << 47; pub const AllBitPatterns: [(&str, u64); 78] = [ ("Any", Any), @@ -87,7 +87,7 @@ mod bits { ("NotNil", NotNil), ("Truthy", Truthy), ("HeapBasicObject", HeapBasicObject), - ("TypedTData", TypedTData), + ("TData", TData), ("Object", Object), ("BuiltinExact", BuiltinExact), ("BoolExact", BoolExact), @@ -238,7 +238,7 @@ pub mod types { pub const Symbol: Type = Type::from_bits(bits::Symbol); pub const TrueClass: Type = Type::from_bits(bits::TrueClass); pub const Truthy: Type = Type::from_bits(bits::Truthy); - pub const TypedTData: Type = Type::from_bits(bits::TypedTData); + pub const TData: Type = Type::from_bits(bits::TData); pub const Undef: Type = Type::from_bits(bits::Undef); pub const ExactBitsAndClass: [(u64, *const VALUE); 17] = [ (bits::ObjectExact, &raw const crate::cruby::rb_cObject), diff --git a/zjit/src/hir_type/mod.rs b/zjit/src/hir_type/mod.rs index cdfc15a9355..6aa10dea55d 100644 --- a/zjit/src/hir_type/mod.rs +++ b/zjit/src/hir_type/mod.rs @@ -214,7 +214,7 @@ impl Type { else if val.class_of() == unsafe { rb_cSymbol } { bits::DynamicSymbol } else if let Some(bits) = Self::bits_from_exact_class(val.class_of()) { bits } else if let Some(bits) = Self::bits_from_subclass(val.class_of()) { bits } - else if val.typed_data_p() { bits::TypedTData } + else if val.data_p() { bits::TData } else { unreachable!("Class {} is not a subclass of BasicObject! Don't know what to do.", get_class_name(val.class_of())) @@ -445,7 +445,7 @@ impl Type { } else if self.bit_equal(types::Hash) { Some(cruby::RUBY_T_HASH) } else { - // Note that types::TypedTData is narrower than T_DATA, so not here. + // T_DATA uses a specialized guard, so not here. None } } diff --git a/zjit/src/profile.rs b/zjit/src/profile.rs index 08803c4570d..000c424da48 100644 --- a/zjit/src/profile.rs +++ b/zjit/src/profile.rs @@ -219,8 +219,8 @@ impl Flags { const IS_T_CLASS: u32 = 1 << 6; /// Object is a T_MODULE const IS_T_MODULE: u32 = 1 << 7; - /// Object is a typed T_DATA (RTYPEDDATA_P) - const IS_TYPED_DATA: u32 = 1 << 8; + /// Object is a T_DATA + const IS_T_DATA: u32 = 1 << 8; pub fn none() -> Self { Self(Self::NONE) } @@ -233,7 +233,7 @@ impl Flags { pub fn is_fields_embedded(self) -> bool { (self.0 & Self::IS_FIELDS_EMBEDDED) != 0 } pub fn is_t_class(self) -> bool { (self.0 & Self::IS_T_CLASS) != 0 } pub fn is_t_module(self) -> bool { (self.0 & Self::IS_T_MODULE) != 0 } - pub fn is_typed_data(self) -> bool { (self.0 & Self::IS_TYPED_DATA) != 0 } + pub fn is_t_data(self) -> bool { (self.0 & Self::IS_T_DATA) != 0 } } /// opt_send_without_block/opt_plus/... should store: @@ -322,9 +322,9 @@ impl ProfiledType { flags.0 |= Flags::IS_FIELDS_EMBEDDED; } } - if obj.typed_data_p() { - flags.0 |= Flags::IS_TYPED_DATA; - if obj.typed_data_fields_embedded_p() { + if obj.data_p() { + flags.0 |= Flags::IS_T_DATA; + if obj.data_fields_embedded_p() { flags.0 |= Flags::IS_FIELDS_EMBEDDED; } } @@ -365,8 +365,8 @@ impl ProfiledType { (RUBY_T_CLASS, RUBY_T_MASK) } else if self.flags().is_t_module() { (RUBY_T_MODULE, RUBY_T_MASK) - } else if self.flags().is_typed_data() { - (RUBY_T_DATA | RUBY_TYPED_FL_IS_TYPED_DATA, RUBY_T_MASK | RUBY_TYPED_FL_IS_TYPED_DATA) + } else if self.flags().is_t_data() { + (RUBY_T_DATA, RUBY_T_MASK) } else { (0, 0) };