Skip to content

Commit

Permalink
Implementing StableApiDefinition RBasic methods for TruffleRuby. (#458)
Browse files Browse the repository at this point in the history
* First pass at implementing StableApiDefinition RArray methods for TruffleRuby.

* Tests & tweaks StableApiDefinition RArray methods for TruffleRuby.

* Renamed rbasic_frozen_p to frozen_p and implemented it using bit masking instead of fcalls

* Review Suggestion: Make rbasic_class return Option<NonNull<VALUE>>.

* Reorganizing after rebase.
  • Loading branch information
goyox86 authored Dec 9, 2024
1 parent 3f54d0b commit 40146c2
Show file tree
Hide file tree
Showing 11 changed files with 231 additions and 10 deletions.
42 changes: 41 additions & 1 deletion crates/rb-sys-tests/src/stable_api_test.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use rb_sys::StableApiDefinition;
use rb_sys::{StableApiDefinition, VALUE};
use rb_sys_test_helpers::rstring as gen_rstring;

macro_rules! parity_test {
Expand Down Expand Up @@ -181,6 +181,46 @@ parity_test!(
}
);

parity_test!(
name: test_rbasic_class_of_array,
func: rbasic_class,
data_factory: {
unsafe { rb_sys::rb_ary_new() as VALUE }
},
expected: {
unsafe { Some(std::ptr::NonNull::new_unchecked(rb_sys::rb_cArray as _)) }
}
);

parity_test!(
name: test_rbasic_class_of_array_evaled,
func: rbasic_class,
data_factory: {
ruby_eval!("[]")
},
expected: {
unsafe { Some(std::ptr::NonNull::new_unchecked(ruby_eval!("Array") as *mut VALUE)) }
}
);

parity_test!(
name: test_rbasic_frozen_p_not_frozen_obj,
func: frozen_p,
data_factory: {
ruby_eval!("[1]")
},
expected: false
);

parity_test!(
name: test_rbasic_frozen_p_frozen_obj,
func: frozen_p,
data_factory: {
ruby_eval!("[1].freeze")
},
expected: true
);

parity_test!(
name: test_special_const_p_for_bool,
func: special_const_p,
Expand Down
15 changes: 14 additions & 1 deletion crates/rb-sys/src/stable_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,10 @@
//! changes in production.
use crate::VALUE;
use std::os::raw::{c_char, c_long};
use std::{
os::raw::{c_char, c_long},
ptr::NonNull,
};

pub trait StableApiDefinition {
const VERSION_MAJOR: u32;
Expand Down Expand Up @@ -54,6 +57,16 @@ pub trait StableApiDefinition {
/// is valid.
unsafe fn rarray_const_ptr(&self, obj: VALUE) -> *const VALUE;

/// Get the class from a VALUE which contains an RBasic struct.
///
/// `VALUE` is a valid pointer to a non-immediate object.
unsafe fn rbasic_class(&self, obj: VALUE) -> Option<NonNull<VALUE>>;

/// Checks if the given object is frozen.
///
/// `VALUE` is a valid pointer to a non-immediate object.
unsafe fn frozen_p(&self, obj: VALUE) -> bool;

/// Tests if a bignum is positive.
///
/// # Safety
Expand Down
10 changes: 10 additions & 0 deletions crates/rb-sys/src/stable_api/compiled.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,16 @@ impl_rarray_const_ptr(VALUE obj) {
return RARRAY_CONST_PTR(obj);
}

VALUE
impl_rbasic_class(VALUE obj) {
return RBASIC_CLASS(obj);
}

int
impl_frozen_p(VALUE obj) {
return RB_OBJ_FROZEN(obj);
}

int
impl_special_const_p(VALUE obj) {
return SPECIAL_CONST_P(obj);
Expand Down
20 changes: 19 additions & 1 deletion crates/rb-sys/src/stable_api/compiled.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use super::StableApiDefinition;
use crate::{ruby_value_type, VALUE};
use std::os::raw::{c_char, c_long};
use std::{
os::raw::{c_char, c_long},
ptr::NonNull,
};

#[allow(dead_code)]
extern "C" {
Expand All @@ -16,6 +19,12 @@ extern "C" {
#[link_name = "impl_rarray_const_ptr"]
fn impl_rarray_const_ptr(ary: VALUE) -> *const VALUE;

#[link_name = "impl_rbasic_class"]
fn impl_rbasic_class(obj: VALUE) -> VALUE;

#[link_name = "impl_frozen_p"]
fn impl_frozen_p(obj: VALUE) -> bool;

#[link_name = "impl_special_const_p"]
fn impl_special_const_p(value: VALUE) -> bool;

Expand Down Expand Up @@ -94,6 +103,15 @@ impl StableApiDefinition for Definition {
impl_rarray_const_ptr(obj)
}

#[inline]
unsafe fn rbasic_class(&self, obj: VALUE) -> Option<NonNull<VALUE>> {
NonNull::<VALUE>::new(impl_rbasic_class(obj) as _)
}

unsafe fn frozen_p(&self, obj: VALUE) -> bool {
impl_frozen_p(obj)
}

#[inline]
fn special_const_p(&self, value: VALUE) -> bool {
unsafe { impl_special_const_p(value) }
Expand Down
22 changes: 21 additions & 1 deletion crates/rb-sys/src/stable_api/ruby_2_6.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ use crate::{
internal::{RArray, RString},
value_type, VALUE,
};
use std::os::raw::{c_char, c_long};
use std::{
os::raw::{c_char, c_long},
ptr::NonNull,
};

#[cfg(not(ruby_eq_2_6))]
compile_error!("This file should only be included in Ruby 2.6 builds");
Expand Down Expand Up @@ -88,6 +91,23 @@ impl StableApiDefinition for Definition {
ptr
}

#[inline]
unsafe fn rbasic_class(&self, obj: VALUE) -> Option<NonNull<VALUE>> {
let rbasic = obj as *const crate::RBasic;

NonNull::<VALUE>::new((*rbasic).klass as _)
}

#[inline]
unsafe fn frozen_p(&self, obj: VALUE) -> bool {
if self.special_const_p(obj) {
true
} else {
let rbasic = obj as *const crate::Rbasic;
((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_FREEZE as VALUE) != 0
}
}

#[inline]
unsafe fn bignum_positive_p(&self, obj: VALUE) -> bool {
let rbasic = obj as *const crate::RBasic;
Expand Down
22 changes: 21 additions & 1 deletion crates/rb-sys/src/stable_api/ruby_2_7.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use crate::{
internal::{RArray, RString},
value_type, VALUE,
};
use std::os::raw::{c_char, c_long};
use std::{
os::raw::{c_char, c_long},
ptr::NonNull,
};

#[cfg(not(ruby_eq_2_7))]
compile_error!("This file should only be included in Ruby 2.7 builds");
Expand Down Expand Up @@ -88,6 +91,23 @@ impl StableApiDefinition for Definition {
ptr
}

#[inline]
unsafe fn rbasic_class(&self, obj: VALUE) -> Option<NonNull<VALUE>> {
let rbasic = obj as *const crate::RBasic;

NonNull::<VALUE>::new((*rbasic).klass as _)
}

#[inline]
unsafe fn frozen_p(&self, obj: VALUE) -> bool {
if self.special_const_p(obj) {
true
} else {
let rbasic = obj as *const crate::RBasic;
((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_FREEZE as VALUE) != 0
}
}

#[inline]
unsafe fn bignum_positive_p(&self, obj: VALUE) -> bool {
let rbasic = obj as *const crate::RBasic;
Expand Down
22 changes: 21 additions & 1 deletion crates/rb-sys/src/stable_api/ruby_3_0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use crate::{
internal::{RArray, RString},
value_type, VALUE,
};
use std::os::raw::{c_char, c_long};
use std::{
os::raw::{c_char, c_long},
ptr::NonNull,
};

#[cfg(not(ruby_eq_3_0))]
compile_error!("This file should only be included in Ruby 3.0 builds");
Expand Down Expand Up @@ -96,6 +99,23 @@ impl StableApiDefinition for Definition {
}
}

#[inline]
unsafe fn rbasic_class(&self, obj: VALUE) -> Option<NonNull<VALUE>> {
let rbasic = obj as *const crate::RBasic;

NonNull::<VALUE>::new((*rbasic).klass as _)
}

#[inline]
unsafe fn frozen_p(&self, obj: VALUE) -> bool {
if self.special_const_p(obj) {
true
} else {
let rbasic = obj as *const crate::RBasic;
((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_FREEZE as VALUE) != 0
}
}

#[inline]
unsafe fn bignum_positive_p(&self, obj: VALUE) -> bool {
let rbasic = obj as *const crate::RBasic;
Expand Down
22 changes: 21 additions & 1 deletion crates/rb-sys/src/stable_api/ruby_3_1.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use crate::{
internal::{RArray, RString},
value_type, VALUE,
};
use std::os::raw::{c_char, c_long};
use std::{
os::raw::{c_char, c_long},
ptr::NonNull,
};

#[cfg(not(ruby_eq_3_1))]
compile_error!("This file should only be included in Ruby 3.1 builds");
Expand Down Expand Up @@ -89,6 +92,23 @@ impl StableApiDefinition for Definition {
ret
}

#[inline]
unsafe fn rbasic_class(&self, obj: VALUE) -> Option<NonNull<VALUE>> {
let rbasic = obj as *const crate::RBasic;

NonNull::<VALUE>::new((*rbasic).klass as _)
}

#[inline]
unsafe fn frozen_p(&self, obj: VALUE) -> bool {
if self.special_const_p(obj) {
true
} else {
let rbasic = obj as *const crate::RBasic;
((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_FREEZE as VALUE) != 0
}
}

#[inline]
unsafe fn bignum_positive_p(&self, obj: VALUE) -> bool {
let rbasic = obj as *const crate::RBasic;
Expand Down
22 changes: 21 additions & 1 deletion crates/rb-sys/src/stable_api/ruby_3_2.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use crate::{
internal::{RArray, RString},
value_type, VALUE,
};
use std::os::raw::{c_char, c_long};
use std::{
os::raw::{c_char, c_long},
ptr::NonNull,
};

#[cfg(not(ruby_eq_3_2))]
compile_error!("This file should only be included in Ruby 3.2 builds");
Expand Down Expand Up @@ -83,6 +86,23 @@ impl StableApiDefinition for Definition {
ptr
}

#[inline]
unsafe fn rbasic_class(&self, obj: VALUE) -> Option<NonNull<VALUE>> {
let rbasic = obj as *const crate::RBasic;

NonNull::<VALUE>::new((*rbasic).klass as _)
}

#[inline]
unsafe fn frozen_p(&self, obj: VALUE) -> bool {
if self.special_const_p(obj) {
true
} else {
let rbasic = obj as *const crate::RBasic;
((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_FREEZE as VALUE) != 0
}
}

#[inline]
unsafe fn bignum_positive_p(&self, obj: VALUE) -> bool {
let rbasic = obj as *const crate::RBasic;
Expand Down
22 changes: 21 additions & 1 deletion crates/rb-sys/src/stable_api/ruby_3_3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use crate::{
internal::{RArray, RString},
value_type, VALUE,
};
use std::os::raw::{c_char, c_long};
use std::{
os::raw::{c_char, c_long},
ptr::NonNull,
};

#[cfg(not(ruby_eq_3_3))]
compile_error!("This file should only be included in Ruby 3.3 builds");
Expand Down Expand Up @@ -76,6 +79,23 @@ impl StableApiDefinition for Definition {
ptr
}

#[inline]
unsafe fn rbasic_class(&self, obj: VALUE) -> Option<NonNull<VALUE>> {
let rbasic = obj as *const crate::RBasic;

NonNull::<VALUE>::new((*rbasic).klass as _)
}

#[inline]
unsafe fn frozen_p(&self, obj: VALUE) -> bool {
if self.special_const_p(obj) {
true
} else {
let rbasic = obj as *const crate::RBasic;
((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_FREEZE as VALUE) != 0
}
}

#[inline]
unsafe fn bignum_positive_p(&self, obj: VALUE) -> bool {
let rbasic = obj as *const crate::RBasic;
Expand Down
22 changes: 21 additions & 1 deletion crates/rb-sys/src/stable_api/ruby_3_4.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ use crate::{
internal::{RArray, RString},
value_type, VALUE,
};
use std::os::raw::{c_char, c_long};
use std::{
os::raw::{c_char, c_long},
ptr::NonNull,
};

#[cfg(not(ruby_eq_3_4))]
compile_error!("This file should only be included in Ruby 3.3 builds");
Expand Down Expand Up @@ -76,6 +79,23 @@ impl StableApiDefinition for Definition {
ptr
}

#[inline]
unsafe fn rbasic_class(&self, obj: VALUE) -> Option<NonNull<VALUE>> {
let rbasic = obj as *const crate::RBasic;

NonNull::<VALUE>::new((*rbasic).klass as _)
}

#[inline]
unsafe fn frozen_p(&self, obj: VALUE) -> bool {
if self.special_const_p(obj) {
true
} else {
let rbasic = obj as *const crate::RBasic;
((*rbasic).flags & crate::ruby_fl_type::RUBY_FL_FREEZE as VALUE) != 0
}
}

#[inline]
fn special_const_p(&self, value: VALUE) -> bool {
let is_immediate = (value) & (crate::special_consts::IMMEDIATE_MASK as VALUE) != 0;
Expand Down

0 comments on commit 40146c2

Please sign in to comment.