diff --git a/crates/rb-sys-tests/src/stable_api_test.rs b/crates/rb-sys-tests/src/stable_api_test.rs index 43d3db54..05a851cd 100644 --- a/crates/rb-sys-tests/src/stable_api_test.rs +++ b/crates/rb-sys-tests/src/stable_api_test.rs @@ -1,4 +1,4 @@ -use rb_sys::{stable_api, StableApiDefinition, RTYPEDDATA_EMBEDDED_P, RTYPEDDATA_P, VALUE}; +use rb_sys::{stable_api, StableApiDefinition, RTYPEDDATA_P, VALUE}; use rb_sys_test_helpers::rstring as gen_rstring; macro_rules! parity_test { @@ -53,14 +53,6 @@ fn gen_typed_data() -> VALUE { ruby_eval!("Time.now") } -fn gen_embedded_typed_data() -> VALUE { - ruby_eval!("Time.at(0)") -} - -fn gen_non_embedded_typed_data() -> VALUE { - ruby_eval!("require 'stringio'; StringIO.new('a' * 1000)") -} - parity_test!( name: test_rstring_len_basic, func: rstring_len, @@ -677,14 +669,6 @@ parity_test! ( expected: true ); -parity_test! ( - name: test_rtypeddata_embedded_p_for_typed_data, - func: rtypeddata_embedded_p, - data_factory: { - gen_typed_data() - } -); - parity_test! ( name: test_rtypeddata_type_for_typed_data, func: rtypeddata_type, @@ -701,68 +685,18 @@ parity_test! ( } ); -parity_test! ( - name: test_rtypeddata_p_for_large_typed_data, - func: rtypeddata_p, - data_factory: { - gen_non_embedded_typed_data() - } -); - -parity_test! ( - name: test_rtypeddata_embedded_p_for_small_data, - func: rtypeddata_embedded_p, - data_factory: { - gen_embedded_typed_data() - } -); - -parity_test! ( - name: test_rtypeddata_embedded_p_for_large_data, - func: rtypeddata_embedded_p, - data_factory: { - gen_non_embedded_typed_data() - } -); - -parity_test! ( - name: test_rtypeddata_get_data_for_small_data, - func: rtypeddata_get_data, - data_factory: { - gen_embedded_typed_data() - } -); - -parity_test! ( - name: test_rtypeddata_get_data_for_large_data, - func: rtypeddata_get_data, - data_factory: { - gen_non_embedded_typed_data() - } -); - #[rb_sys_test_helpers::ruby_test] fn test_rtypeddata_functions_with_usage() { - let small_time = gen_embedded_typed_data(); - let large_time = gen_non_embedded_typed_data(); + let obj = gen_typed_data(); unsafe { - for obj in [small_time, large_time].iter() { - assert!(RTYPEDDATA_P(*obj)); - - let type_ptr = stable_api::get_default().rtypeddata_type(*obj); - assert!(!type_ptr.is_null()); - - let data_ptr = stable_api::get_default().rtypeddata_get_data(*obj); - assert!(!data_ptr.is_null()); - } + assert!(RTYPEDDATA_P(obj)); - let _small_embedded = RTYPEDDATA_EMBEDDED_P(small_time); - let large_embedded = RTYPEDDATA_EMBEDDED_P(large_time); + let type_ptr = stable_api::get_default().rtypeddata_type(obj); + assert!(!type_ptr.is_null()); - #[cfg(ruby_gte_3_3)] - assert!(_small_embedded); - assert!(!large_embedded); + let data_ptr = stable_api::get_default().rtypeddata_get_data(obj); + assert!(!data_ptr.is_null()); } } diff --git a/crates/rb-sys/src/macros.rs b/crates/rb-sys/src/macros.rs index e8ef8ffe..702f5a63 100644 --- a/crates/rb-sys/src/macros.rs +++ b/crates/rb-sys/src/macros.rs @@ -301,21 +301,6 @@ pub unsafe fn RTYPEDDATA_P(obj: VALUE) -> bool { api().rtypeddata_p(obj) } -/// Checks if the given RTypedData is embedded. -/// -/// @param[in] obj An RTypedData object. -/// @retval true The data is embedded in the object itself. -/// @retval false The data is stored separately. -/// -/// # Safety -/// This function is unsafe because it could dereference a raw pointer when -/// accessing the underlying data structure. The caller must ensure the object -/// is a valid RTypedData. -#[inline(always)] -pub unsafe fn RTYPEDDATA_EMBEDDED_P(obj: VALUE) -> bool { - api().rtypeddata_embedded_p(obj) -} - /// Gets the data type information from an RTypedData object. /// /// @param[in] obj An RTypedData object. diff --git a/crates/rb-sys/src/stable_api.rs b/crates/rb-sys/src/stable_api.rs index 85951c60..db3f2798 100644 --- a/crates/rb-sys/src/stable_api.rs +++ b/crates/rb-sys/src/stable_api.rs @@ -195,14 +195,6 @@ pub trait StableApiDefinition { /// is valid and points to a T_DATA object. unsafe fn rtypeddata_p(&self, obj: VALUE) -> bool; - /// Checks if the given RTypedData is embedded. - /// - /// # Safety - /// This function is unsafe because it dereferences a raw pointer to get - /// access to underlying Ruby data. The caller must ensure that the pointer - /// is valid and points to an RTypedData object. - unsafe fn rtypeddata_embedded_p(&self, obj: VALUE) -> bool; - /// Gets the data type from an RTypedData object. /// /// # Safety diff --git a/crates/rb-sys/src/stable_api/compiled.c b/crates/rb-sys/src/stable_api/compiled.c index 412005a7..ff86c116 100644 --- a/crates/rb-sys/src/stable_api/compiled.c +++ b/crates/rb-sys/src/stable_api/compiled.c @@ -152,16 +152,6 @@ int impl_rtypeddata_p(VALUE obj) return RTYPEDDATA_P(obj); } -int impl_rtypeddata_embedded_p(VALUE obj) -{ -#if RUBY_VERSION_AT_LEAST_3_3 - return RTYPEDDATA_EMBEDDED_P(obj); -#else - // On Ruby versions before 3.3, embedded typed data is not supported - return 0; -#endif -} - const struct rb_data_type_struct * impl_rtypeddata_type(VALUE obj) { diff --git a/crates/rb-sys/src/stable_api/compiled.rs b/crates/rb-sys/src/stable_api/compiled.rs index 6f0ee221..8e249001 100644 --- a/crates/rb-sys/src/stable_api/compiled.rs +++ b/crates/rb-sys/src/stable_api/compiled.rs @@ -85,9 +85,6 @@ extern "C" { #[link_name = "impl_rtypeddata_p"] fn impl_rtypeddata_p(obj: VALUE) -> bool; - #[link_name = "impl_rtypeddata_embedded_p"] - fn impl_rtypeddata_embedded_p(obj: VALUE) -> bool; - #[link_name = "impl_rtypeddata_type"] fn impl_rtypeddata_type(obj: VALUE) -> *const crate::rb_data_type_t; @@ -268,18 +265,6 @@ impl StableApiDefinition for Definition { impl_rtypeddata_p(obj) } - #[inline] - #[cfg(ruby_gte_3_3)] - unsafe fn rtypeddata_embedded_p(&self, obj: VALUE) -> bool { - impl_rtypeddata_embedded_p(obj) - } - - #[inline] - #[cfg(ruby_lt_3_3)] - unsafe fn rtypeddata_embedded_p(&self, _obj: VALUE) -> bool { - false - } - #[inline] unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t { impl_rtypeddata_type(obj) diff --git a/crates/rb-sys/src/stable_api/ruby_2_7.rs b/crates/rb-sys/src/stable_api/ruby_2_7.rs index 3930d47c..99f3a12a 100644 --- a/crates/rb-sys/src/stable_api/ruby_2_7.rs +++ b/crates/rb-sys/src/stable_api/ruby_2_7.rs @@ -291,12 +291,6 @@ impl StableApiDefinition for Definition { typed_flag == 1 } - #[inline] - unsafe fn rtypeddata_embedded_p(&self, _obj: VALUE) -> bool { - // Ruby 2.7 doesn't support embedded data - false - } - #[inline] unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t { debug_ruby_assert_type!( diff --git a/crates/rb-sys/src/stable_api/ruby_3_0.rs b/crates/rb-sys/src/stable_api/ruby_3_0.rs index f6c9d4c1..42160a1e 100644 --- a/crates/rb-sys/src/stable_api/ruby_3_0.rs +++ b/crates/rb-sys/src/stable_api/ruby_3_0.rs @@ -299,12 +299,6 @@ impl StableApiDefinition for Definition { typed_flag == 1 } - #[inline] - unsafe fn rtypeddata_embedded_p(&self, _obj: VALUE) -> bool { - // Ruby 3.0 and lower don't support embedded data - false - } - #[inline] unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t { debug_ruby_assert_type!( diff --git a/crates/rb-sys/src/stable_api/ruby_3_1.rs b/crates/rb-sys/src/stable_api/ruby_3_1.rs index 2c891be7..a3ad6dbf 100644 --- a/crates/rb-sys/src/stable_api/ruby_3_1.rs +++ b/crates/rb-sys/src/stable_api/ruby_3_1.rs @@ -292,12 +292,6 @@ impl StableApiDefinition for Definition { typed_flag == 1 } - #[inline] - unsafe fn rtypeddata_embedded_p(&self, _obj: VALUE) -> bool { - // Ruby 3.1 and lower don't support embedded data - false - } - #[inline] unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t { debug_ruby_assert_type!( diff --git a/crates/rb-sys/src/stable_api/ruby_3_2.rs b/crates/rb-sys/src/stable_api/ruby_3_2.rs index 62a611e9..95f763ee 100644 --- a/crates/rb-sys/src/stable_api/ruby_3_2.rs +++ b/crates/rb-sys/src/stable_api/ruby_3_2.rs @@ -290,12 +290,6 @@ impl StableApiDefinition for Definition { typed_flag == 1 } - #[inline] - unsafe fn rtypeddata_embedded_p(&self, _obj: VALUE) -> bool { - // Ruby 3.2 and lower don't support embedded data - false - } - #[inline] unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t { debug_ruby_assert_type!( diff --git a/crates/rb-sys/src/stable_api/ruby_3_3.rs b/crates/rb-sys/src/stable_api/ruby_3_3.rs index 31ae8f66..943b5bf5 100644 --- a/crates/rb-sys/src/stable_api/ruby_3_3.rs +++ b/crates/rb-sys/src/stable_api/ruby_3_3.rs @@ -282,24 +282,6 @@ impl StableApiDefinition for Definition { typed_flag != 0 && typed_flag <= 3 } - #[inline] - unsafe fn rtypeddata_embedded_p(&self, obj: VALUE) -> bool { - debug_ruby_assert_type!( - obj, - RUBY_T_DATA, - "rtypeddata_embedded_p called on non-T_DATA object" - ); - - let rdata = obj as *const crate::internal::RTypedData; - let typed_flag = (*rdata).typed_flag; - #[cfg(target_pointer_width = "64")] - const FLAG: u64 = crate::TYPED_DATA_EMBEDDED as u64; - #[cfg(target_pointer_width = "32")] - const FLAG: u32 = crate::TYPED_DATA_EMBEDDED as u32; - - (typed_flag & FLAG) != 0 - } - #[inline] unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t { debug_ruby_assert_type!( @@ -320,7 +302,14 @@ impl StableApiDefinition for Definition { "rtypeddata_get_data called on non-T_DATA object" ); - if self.rtypeddata_embedded_p(obj) { + let rdata = obj as *const crate::internal::RTypedData; + let typed_flag = (*rdata).typed_flag; + #[cfg(target_pointer_width = "64")] + const FLAG: u64 = crate::TYPED_DATA_EMBEDDED as u64; + #[cfg(target_pointer_width = "32")] + const FLAG: u32 = crate::TYPED_DATA_EMBEDDED as u32; + + if (typed_flag & FLAG) != 0 { // For embedded data, calculate pointer based on struct layout // The formula matches Ruby's implementation: // embedded_typed_data_size = sizeof(RTypedData) - sizeof(void *) diff --git a/crates/rb-sys/src/stable_api/ruby_3_4.rs b/crates/rb-sys/src/stable_api/ruby_3_4.rs index e3892489..fc5bcb2f 100644 --- a/crates/rb-sys/src/stable_api/ruby_3_4.rs +++ b/crates/rb-sys/src/stable_api/ruby_3_4.rs @@ -297,24 +297,6 @@ impl StableApiDefinition for Definition { typed_flag != 0 && typed_flag <= 3 } - #[inline(always)] - unsafe fn rtypeddata_embedded_p(&self, obj: VALUE) -> bool { - debug_ruby_assert_type!( - obj, - RUBY_T_DATA, - "rtypeddata_embedded_p called on non-T_DATA object" - ); - - let rdata = obj as *const RTypedData; - let typed_flag = (*rdata).typed_flag; - #[cfg(target_pointer_width = "64")] - const FLAG: u64 = crate::TYPED_DATA_EMBEDDED as u64; - #[cfg(target_pointer_width = "32")] - const FLAG: u32 = crate::TYPED_DATA_EMBEDDED as u32; - - (typed_flag & FLAG) != 0 - } - #[inline(always)] unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t { debug_ruby_assert_type!( @@ -335,7 +317,14 @@ impl StableApiDefinition for Definition { "rtypeddata_get_data called on non-T_DATA object" ); - if self.rtypeddata_embedded_p(obj) { + let rdata = obj as *const RTypedData; + let typed_flag = (*rdata).typed_flag; + #[cfg(target_pointer_width = "64")] + const FLAG: u64 = crate::TYPED_DATA_EMBEDDED as u64; + #[cfg(target_pointer_width = "32")] + const FLAG: u32 = crate::TYPED_DATA_EMBEDDED as u32; + + if (typed_flag & FLAG) != 0 { // For embedded data, calculate pointer based on struct layout // The formula matches Ruby's implementation: // embedded_typed_data_size = sizeof(RTypedData) - sizeof(void *) diff --git a/crates/rb-sys/src/stable_api/ruby_4_0.rs b/crates/rb-sys/src/stable_api/ruby_4_0.rs index 91884781..24373396 100644 --- a/crates/rb-sys/src/stable_api/ruby_4_0.rs +++ b/crates/rb-sys/src/stable_api/ruby_4_0.rs @@ -295,19 +295,6 @@ impl StableApiDefinition for Definition { ((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_USERPRIV0 as VALUE) != 0 } - #[inline(always)] - unsafe fn rtypeddata_embedded_p(&self, obj: VALUE) -> bool { - debug_ruby_assert_type!( - obj, - RUBY_T_DATA, - "rtypeddata_embedded_p called on non-T_DATA object" - ); - - // Ruby 4.0: TYPED_DATA_EMBEDDED is bit 0 of the type field - let rdata = obj as *const RTypedData; - ((*rdata).type_ & 1) != 0 - } - #[inline(always)] unsafe fn rtypeddata_type(&self, obj: VALUE) -> *const crate::rb_data_type_t { debug_ruby_assert_type!( @@ -330,7 +317,9 @@ impl StableApiDefinition for Definition { "rtypeddata_get_data called on non-T_DATA object" ); - if self.rtypeddata_embedded_p(obj) { + // Ruby 4.0: TYPED_DATA_EMBEDDED is bit 0 of the type field + let rdata = obj as *const RTypedData; + if ((*rdata).type_ & 1) != 0 { // For embedded data, calculate pointer based on struct layout // The formula matches Ruby's implementation: // embedded_typed_data_size = sizeof(RTypedData) - sizeof(void *) diff --git a/script/show-asm b/script/show-asm index 3d958cd2..b5c42b98 100755 --- a/script/show-asm +++ b/script/show-asm @@ -198,12 +198,6 @@ FUNCTIONS = [ c: {expr: "RTYPEDDATA_P(v)", ret: "int"}, ruby_source: "include/ruby/internal/core/rtypeddata.h:RTYPEDDATA_P" }, - { - name: "rtypeddata_embedded_p", - rust: {unsafe: true, ret: "bool", expr: "rb_sys::RTYPEDDATA_EMBEDDED_P(v)"}, - c: {expr: "RTYPEDDATA_EMBEDDED_P(v)", ret: "int"}, - ruby_source: "include/ruby/internal/core/rtypeddata.h:RTYPEDDATA_EMBEDDED_P" - }, { name: "rtypeddata_type", rust: {unsafe: true, ret: "*const rb_sys::rb_data_type_t", expr: "rb_sys::RTYPEDDATA_TYPE(v)"},