aboutsummaryrefslogtreecommitdiffstats
path: root/yjit/src/utils.rs
diff options
context:
space:
mode:
authorNoah Gibbs <the.codefolio.guy@gmail.com>2022-07-28 16:45:08 +0100
committerTakashi Kokubun <takashikkbn@gmail.com>2022-08-24 10:42:45 -0700
commitb4be3c00c5737649166db676278fd28f768a5e3c (patch)
tree73ad75aa40351021832e44943a40a349172568d7 /yjit/src/utils.rs
parent0ad9cc16966c2e56f0fe7e5992edf76033d3a83f (diff)
downloadruby-b4be3c00c5737649166db676278fd28f768a5e3c.tar.gz
add --yjit-dump-iseqs param (https://github.com/Shopify/ruby/pull/332)
Diffstat (limited to 'yjit/src/utils.rs')
-rw-r--r--yjit/src/utils.rs35
1 files changed, 35 insertions, 0 deletions
diff --git a/yjit/src/utils.rs b/yjit/src/utils.rs
index 02fbce47d8..ade573b8da 100644
--- a/yjit/src/utils.rs
+++ b/yjit/src/utils.rs
@@ -71,6 +71,41 @@ macro_rules! offset_of {
#[allow(unused)]
pub(crate) use offset_of;
+// Convert a CRuby UTF-8-encoded RSTRING into a Rust string.
+// This should work fine on ASCII strings and anything else
+// that is considered legal UTF-8, including embedded nulls.
+fn ruby_str_to_rust(v: VALUE) -> String {
+ // Make sure the CRuby encoding is UTF-8 compatible
+ let encoding = unsafe { rb_ENCODING_GET(v) } as u32;
+ assert!(encoding == RUBY_ENCINDEX_ASCII_8BIT || encoding == RUBY_ENCINDEX_UTF_8 || encoding == RUBY_ENCINDEX_US_ASCII);
+
+ let str_ptr = unsafe { rb_RSTRING_PTR(v) } as *mut u8;
+ let str_len: usize = unsafe { rb_RSTRING_LEN(v) }.try_into().unwrap();
+ let str_slice: &[u8] = unsafe { slice::from_raw_parts(str_ptr, str_len) };
+ String::from_utf8(str_slice.to_vec()).unwrap() // does utf8 validation
+}
+
+// Location is the file defining the method, colon, method name.
+// Filenames are sometimes internal strings supplied to eval,
+// so be careful with them.
+pub fn iseq_get_location(iseq: IseqPtr) -> String {
+ let iseq_path = unsafe { rb_iseq_path(iseq) };
+ let iseq_method = unsafe { rb_iseq_method_name(iseq) };
+
+ let mut s = if iseq_path == Qnil {
+ "None".to_string()
+ } else {
+ ruby_str_to_rust(iseq_path)
+ };
+ s.push_str(":");
+ if iseq_method == Qnil {
+ s.push_str("None");
+ } else {
+ s.push_str(& ruby_str_to_rust(iseq_method));
+ }
+ s
+}
+
#[cfg(test)]
mod tests {
#[test]