@@ -159,23 +159,8 @@ fn profile_invokesuper(profiler: &mut Profiler, profile: &mut IseqProfile) {
159159 let cme = unsafe { rb_vm_frame_method_entry ( profiler. cfp ) } ;
160160 let cme_value = VALUE ( cme as usize ) ; // CME is a T_IMEMO, which is a VALUE
161161
162- match profile. super_cme . get ( & profiler. insn_idx ) {
163- None => {
164- // If `None`, then this is our first time looking at `super` for this instruction.
165- profile. super_cme . insert ( profiler. insn_idx , Some ( cme_value) ) ;
166- } ,
167- Some ( Some ( existing_cme) ) => {
168- // Check if the stored method entry is the same as the current one. If it isn't, then
169- // mark the call site as polymorphic.
170- if * existing_cme != cme_value {
171- profile. super_cme . insert ( profiler. insn_idx , None ) ;
172- }
173- }
174- Some ( None ) => {
175- // We've visited this instruction and explicitly stored `None` to mark the call site
176- // as polymorphic.
177- }
178- }
162+ profile. super_cme . entry ( profiler. insn_idx )
163+ . or_insert_with ( || TypeDistribution :: new ( ) ) . observe ( ProfiledType :: object ( cme_value) ) ;
179164
180165 unsafe { rb_gc_writebarrier ( profiler. iseq . into ( ) , cme_value) } ;
181166
@@ -359,7 +344,7 @@ pub struct IseqProfile {
359344 num_profiles : Vec < NumProfiles > ,
360345
361346 /// Method entries for `super` calls (stored as VALUE to be GC-safe)
362- super_cme : HashMap < usize , Option < VALUE > >
347+ super_cme : HashMap < usize , TypeDistribution >
363348}
364349
365350impl IseqProfile {
@@ -377,8 +362,14 @@ impl IseqProfile {
377362 }
378363
379364 pub fn get_super_method_entry ( & self , insn_idx : usize ) -> Option < * const rb_callable_method_entry_t > {
380- self . super_cme . get ( & insn_idx)
381- . and_then ( |opt| opt. map ( |v| v. 0 as * const rb_callable_method_entry_t ) )
365+ let Some ( entry) = self . super_cme . get ( & insn_idx) else { return None } ;
366+ let summary = TypeDistributionSummary :: new ( entry) ;
367+
368+ if summary. is_monomorphic ( ) {
369+ Some ( summary. bucket ( 0 ) . class . 0 as * const rb_callable_method_entry_t )
370+ } else {
371+ None
372+ }
382373 }
383374
384375 /// Run a given callback with every object in IseqProfile
@@ -392,9 +383,9 @@ impl IseqProfile {
392383 }
393384 }
394385
395- for cme_value in self . super_cme . values ( ) {
396- if let Some ( cme ) = cme_value {
397- callback ( * cme ) ;
386+ for super_cme_values in self . super_cme . values ( ) {
387+ for profiled_type in super_cme_values . each_item ( ) {
388+ callback ( profiled_type . class )
398389 }
399390 }
400391 }
@@ -411,9 +402,9 @@ impl IseqProfile {
411402 }
412403
413404 // Update CME references if they move during compaction.
414- for cme_value in self . super_cme . values_mut ( ) {
415- if let Some ( cme ) = cme_value {
416- callback ( cme ) ;
405+ for super_cme_values in self . super_cme . values_mut ( ) {
406+ for ref mut profiled_type in super_cme_values . each_item_mut ( ) {
407+ callback ( & mut profiled_type . class )
417408 }
418409 }
419410 }
0 commit comments