summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--zjit/bindgen/src/main.rs2
-rw-r--r--zjit/src/cruby.rs32
-rw-r--r--zjit/src/cruby_bindings.inc.rs6
3 files changed, 32 insertions, 8 deletions
diff --git a/zjit/bindgen/src/main.rs b/zjit/bindgen/src/main.rs
index b40986c0f6..975a2d9157 100644
--- a/zjit/bindgen/src/main.rs
+++ b/zjit/bindgen/src/main.rs
@@ -82,7 +82,7 @@ fn main() {
.allowlist_type("ruby_rstring_flags")
// This function prints info about a value and is useful for debugging
- .allowlist_function("rb_obj_info_dump")
+ .allowlist_function("rb_raw_obj_info")
.allowlist_function("ruby_init")
.allowlist_function("ruby_init_stack")
diff --git a/zjit/src/cruby.rs b/zjit/src/cruby.rs
index 1f514787f1..1a2dce03ed 100644
--- a/zjit/src/cruby.rs
+++ b/zjit/src/cruby.rs
@@ -90,7 +90,7 @@
use std::convert::From;
use std::ffi::{c_void, CString, CStr};
-use std::fmt::{Debug, Formatter};
+use std::fmt::{Debug, Display, Formatter};
use std::os::raw::{c_char, c_int, c_uint};
use std::panic::{catch_unwind, UnwindSafe};
@@ -400,10 +400,27 @@ pub enum ClassRelationship {
NoRelation,
}
+/// A print adapator for debug info about a [VALUE]. Includes info
+/// the GC knows about the handle. Example: `println!("{}", value.obj_info());`.
+pub struct ObjInfoPrinter(VALUE);
+
+impl Display for ObjInfoPrinter {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ use std::mem::MaybeUninit;
+ const BUFFER_SIZE: usize = 0x100;
+ let mut buffer: MaybeUninit<[c_char; BUFFER_SIZE]> = MaybeUninit::uninit();
+ let info = unsafe {
+ rb_raw_obj_info(buffer.as_mut_ptr().cast(), BUFFER_SIZE, self.0);
+ CStr::from_ptr(buffer.as_ptr().cast()).to_string_lossy()
+ };
+ write!(f, "{info}")
+ }
+}
+
impl VALUE {
- /// Dump info about the value to the console similarly to rp(VALUE)
- pub fn dump_info(self) {
- unsafe { rb_obj_info_dump(self) }
+ /// Get a printer for raw debug info from `rb_obj_info()` about the value.
+ pub fn obj_info(self) -> ObjInfoPrinter {
+ ObjInfoPrinter(self)
}
/// Return whether the value is truthy or falsy in Ruby -- only nil and false are falsy.
@@ -507,8 +524,11 @@ impl VALUE {
pub fn class_of(self) -> VALUE {
if !self.special_const_p() {
let builtin_type = self.builtin_type();
- assert_ne!(builtin_type, RUBY_T_NONE, "ZJIT should only see live objects");
- assert_ne!(builtin_type, RUBY_T_MOVED, "ZJIT should only see live objects");
+ assert!(
+ builtin_type != RUBY_T_NONE && builtin_type != RUBY_T_MOVED,
+ "ZJIT saw a dead object. T_type={builtin_type}, {}",
+ self.obj_info()
+ );
}
unsafe { rb_yarv_class_of(self) }
diff --git a/zjit/src/cruby_bindings.inc.rs b/zjit/src/cruby_bindings.inc.rs
index 56b569e064..f18c0035ee 100644
--- a/zjit/src/cruby_bindings.inc.rs
+++ b/zjit/src/cruby_bindings.inc.rs
@@ -839,7 +839,6 @@ unsafe extern "C" {
pub fn rb_ivar_set(obj: VALUE, name: ID, val: VALUE) -> VALUE;
pub fn rb_ivar_defined(obj: VALUE, name: ID) -> VALUE;
pub fn rb_attr_get(obj: VALUE, name: ID) -> VALUE;
- pub fn rb_obj_info_dump(obj: VALUE);
pub fn rb_class_allocate_instance(klass: VALUE) -> VALUE;
pub fn rb_obj_equal(obj1: VALUE, obj2: VALUE) -> VALUE;
pub fn rb_reg_new_ary(ary: VALUE, options: ::std::os::raw::c_int) -> VALUE;
@@ -872,6 +871,11 @@ unsafe extern "C" {
cfp: *const rb_control_frame_t,
) -> *const rb_callable_method_entry_t;
pub fn rb_obj_info(obj: VALUE) -> *const ::std::os::raw::c_char;
+ pub fn rb_raw_obj_info(
+ buff: *mut ::std::os::raw::c_char,
+ buff_size: usize,
+ 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_gc_writebarrier_remember(obj: VALUE);
pub fn rb_shape_id_offset() -> i32;