ZJIT: Fix singleton class qualified method names in stats

Now methods on singleton classes (for example, `new`) get split up into
`String*#new`, `Array*#new`, ... (where the `*` indicates a singleton
class) instead of all looking like `Class#new`.

before:

```
***ZJIT: Printing ZJIT statistics on exit***
Top-20 not inlined C methods (59.8% of total 10,506,888):
                                  String#<<: 987,752 ( 9.4%)
                               Kernel#is_a?: 755,223 ( 7.2%)
                                   Hash#[]=: 700,802 ( 6.7%)
                              Regexp#match?: 400,129 ( 3.8%)
                              String#empty?: 353,775 ( 3.4%)
                         String#start_with?: 334,961 ( 3.2%)
                                  Hash#key?: 331,080 ( 3.2%)
                 ObjectSpace::WeakKeyMap#[]: 238,978 ( 2.3%)
                              TrueClass#===: 235,771 ( 2.2%)
                             FalseClass#===: 231,144 ( 2.2%)
                             Array#include?: 213,362 ( 2.0%)
                         Kernel#respond_to?: 198,730 ( 1.9%)
                                 Kernel#dup: 178,920 ( 1.7%)
                        Kernel#block_given?: 178,767 ( 1.7%)
                             BasicObject#!=: 170,602 ( 1.6%)
                                  Class#new: 168,079 ( 1.6%)
                            Kernel#kind_of?: 165,600 ( 1.6%)
                                  String#==: 158,036 ( 1.5%)
                       Module#clock_gettime: 144,992 ( 1.4%)
                               NilClass#===: 137,833 ( 1.3%)
```

after:

```
***ZJIT: Printing ZJIT statistics on exit***
Top-20 not inlined C methods (59.8% of total 10,506,906):
                                  String#<<: 987,752 ( 9.4%)
                               Kernel#is_a?: 755,237 ( 7.2%)
                                   Hash#[]=: 700,802 ( 6.7%)
                              Regexp#match?: 400,129 ( 3.8%)
                              String#empty?: 353,775 ( 3.4%)
                         String#start_with?: 334,961 ( 3.2%)
                                  Hash#key?: 331,080 ( 3.2%)
                 ObjectSpace::WeakKeyMap#[]: 238,978 ( 2.3%)
                              TrueClass#===: 235,771 ( 2.2%)
                             FalseClass#===: 231,144 ( 2.2%)
                             Array#include?: 213,362 ( 2.0%)
                         Kernel#respond_to?: 198,730 ( 1.9%)
                                 Kernel#dup: 178,920 ( 1.7%)
                        Kernel#block_given?: 178,767 ( 1.7%)
                             BasicObject#!=: 170,602 ( 1.6%)
                                String*#new: 166,696 ( 1.6%)
                            Kernel#kind_of?: 165,600 ( 1.6%)
                                  String#==: 158,039 ( 1.5%)
                     Process*#clock_gettime: 144,992 ( 1.4%)
                               NilClass#===: 137,833 ( 1.3%)
```
This commit is contained in:
Max Bernstein 2025-10-16 12:57:00 -04:00 committed by Max Bernstein
parent 037b6e24ea
commit 9598b4449d
Notes: git 2025-10-16 20:48:20 +00:00

View File

@ -2506,12 +2506,22 @@ impl Function {
Err(())
}
fn qualified_method_name(class: VALUE, method_id: ID) -> String {
let method_name = method_id.contents_lossy();
// rb_zjit_singleton_class_p also checks if it's a class
if unsafe { rb_zjit_singleton_class_p(class) } {
let class_name = get_class_name(unsafe { rb_class_attached_object(class) });
format!("{}.{}", class_name, method_name)
} else {
let class_name = get_class_name(class);
format!("{}#{}", class_name, method_name)
}
}
fn count_not_inlined_cfunc(fun: &mut Function, block: BlockId, cme: *const rb_callable_method_entry_t) {
let owner = unsafe { (*cme).owner };
let called_id = unsafe { (*cme).called_id };
let class_name = get_class_name(owner);
let method_name = called_id.contents_lossy();
let qualified_method_name = format!("{}#{}", class_name, method_name);
let qualified_method_name = qualified_method_name(owner, called_id);
let not_inlined_cfunc_counter_pointers = ZJITState::get_not_inlined_cfunc_counter_pointers();
let counter_ptr = not_inlined_cfunc_counter_pointers.entry(qualified_method_name.clone()).or_insert_with(|| Box::new(0));
let counter_ptr = &mut **counter_ptr as *mut u64;
@ -2522,9 +2532,7 @@ impl Function {
fn count_not_annotated_cfunc(fun: &mut Function, block: BlockId, cme: *const rb_callable_method_entry_t) {
let owner = unsafe { (*cme).owner };
let called_id = unsafe { (*cme).called_id };
let class_name = get_class_name(owner);
let method_name = called_id.contents_lossy();
let qualified_method_name = format!("{}#{}", class_name, method_name);
let qualified_method_name = qualified_method_name(owner, called_id);
let not_annotated_cfunc_counter_pointers = ZJITState::get_not_annotated_cfunc_counter_pointers();
let counter_ptr = not_annotated_cfunc_counter_pointers.entry(qualified_method_name.clone()).or_insert_with(|| Box::new(0));
let counter_ptr = &mut **counter_ptr as *mut u64;