Skip to content

Commit 66a6c5c

Browse files
committed
YJIT: Remove CString allocation when using src_loc!()
Since we often take the VM lock as the first thing we do when entering YJIT, and that needs a `src_loc!()`, this removes a allocation from that. The main trick here is `concat!(file!(), '\0')` to get a C string statically baked into the binary.
1 parent adae813 commit 66a6c5c

File tree

1 file changed

+11
-12
lines changed

1 file changed

+11
-12
lines changed

yjit/src/cruby.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@
8383
#![allow(non_upper_case_globals)]
8484

8585
use std::convert::From;
86-
use std::ffi::CString;
86+
use std::ffi::{CString, CStr};
8787
use std::os::raw::{c_char, c_int, c_uint};
8888
use std::panic::{catch_unwind, UnwindSafe};
8989

@@ -208,8 +208,6 @@ pub use rb_RCLASS_ORIGIN as RCLASS_ORIGIN;
208208

209209
/// Helper so we can get a Rust string for insn_name()
210210
pub fn insn_name(opcode: usize) -> String {
211-
use std::ffi::CStr;
212-
213211
unsafe {
214212
// Look up Ruby's NULL-terminated insn name string
215213
let op_name = raw_insn_name(VALUE(opcode));
@@ -608,7 +606,6 @@ pub fn rust_str_to_sym(str: &str) -> VALUE {
608606
pub fn cstr_to_rust_string(c_char_ptr: *const c_char) -> Option<String> {
609607
assert!(c_char_ptr != std::ptr::null());
610608

611-
use std::ffi::CStr;
612609
let c_str: &CStr = unsafe { CStr::from_ptr(c_char_ptr) };
613610

614611
match c_str.to_str() {
@@ -620,17 +617,20 @@ pub fn cstr_to_rust_string(c_char_ptr: *const c_char) -> Option<String> {
620617
/// A location in Rust code for integrating with debugging facilities defined in C.
621618
/// Use the [src_loc!] macro to crate an instance.
622619
pub struct SourceLocation {
623-
pub file: CString,
620+
pub file: &'static CStr,
624621
pub line: c_int,
625622
}
626623

627624
/// Make a [SourceLocation] at the current spot.
628625
macro_rules! src_loc {
629626
() => {
630-
// NOTE(alan): `CString::new` allocates so we might want to limit this to debug builds.
631-
$crate::cruby::SourceLocation {
632-
file: std::ffi::CString::new(file!()).unwrap(), // ASCII source file paths
633-
line: line!().try_into().unwrap(), // not that many lines
627+
{
628+
// Nul-terminated string with static lifetime, make a CStr out of it safely.
629+
let file: &'static str = concat!(file!(), '\0');
630+
$crate::cruby::SourceLocation {
631+
file: unsafe { std::ffi::CStr::from_ptr(file.as_ptr().cast()) },
632+
line: line!().try_into().unwrap(),
633+
}
634634
}
635635
};
636636
}
@@ -668,17 +668,16 @@ where
668668
Err(_) => {
669669
// Theoretically we can recover from some of these panics,
670670
// but it's too late if the unwind reaches here.
671-
use std::{process, str};
672671

673672
let _ = catch_unwind(|| {
674673
// IO functions can panic too.
675674
eprintln!(
676675
"YJIT panicked while holding VM lock acquired at {}:{}. Aborting...",
677-
str::from_utf8(loc.file.as_bytes()).unwrap_or("<not utf8>"),
676+
loc.file.to_string_lossy(),
678677
line,
679678
);
680679
});
681-
process::abort();
680+
std::process::abort();
682681
}
683682
};
684683

0 commit comments

Comments
 (0)