@@ -279,9 +279,7 @@ struct rb_callcache {
279279 const VALUE flags ;
280280
281281 /* inline cache: key */
282- const VALUE klass ; // should not mark it because klass can not be free'd
283- // because of this marking. When klass is collected,
284- // cc will be cleared (cc->klass = 0) at vm_ccs_free().
282+ const VALUE klass ; // Weak reference. When klass is collected, `cc->klass = Qundef`.
285283
286284 /* inline cache: values */
287285 const struct rb_callable_method_entry_struct * const cme_ ;
@@ -324,12 +322,20 @@ vm_cc_attr_index_initialize(const struct rb_callcache *cc, shape_id_t shape_id)
324322 vm_cc_attr_index_set (cc , (attr_index_t )- 1 , shape_id );
325323}
326324
325+ static inline VALUE
326+ cc_check_class (VALUE klass )
327+ {
328+ VM_ASSERT (klass == Qundef || RB_TYPE_P (klass , T_CLASS ) || RB_TYPE_P (klass , T_ICLASS ));
329+ return klass ;
330+ }
331+
327332static inline const struct rb_callcache *
328333vm_cc_new (VALUE klass ,
329334 const struct rb_callable_method_entry_struct * cme ,
330335 vm_call_handler call ,
331336 enum vm_cc_type type )
332337{
338+ cc_check_class (klass );
333339 struct rb_callcache * cc = IMEMO_NEW (struct rb_callcache , imemo_callcache , klass );
334340 * ((struct rb_callable_method_entry_struct * * )& cc -> cme_ ) = (struct rb_callable_method_entry_struct * )cme ;
335341 * ((vm_call_handler * )& cc -> call_ ) = call ;
@@ -374,7 +380,7 @@ vm_cc_refinement_p(const struct rb_callcache *cc)
374380 (imemo_callcache << FL_USHIFT) | \
375381 VM_CALLCACHE_UNMARKABLE | \
376382 VM_CALLCACHE_ON_STACK, \
377- .klass = clazz, \
383+ .klass = cc_check_class( clazz), \
378384 .cme_ = cme, \
379385 .call_ = call, \
380386 .aux_ = aux, \
@@ -384,7 +390,7 @@ static inline bool
384390vm_cc_class_check (const struct rb_callcache * cc , VALUE klass )
385391{
386392 VM_ASSERT (IMEMO_TYPE_P (cc , imemo_callcache ));
387- VM_ASSERT (cc -> klass == 0 ||
393+ VM_ASSERT (cc -> klass == Qundef ||
388394 RB_TYPE_P (cc -> klass , T_CLASS ) || RB_TYPE_P (cc -> klass , T_ICLASS ));
389395 return cc -> klass == klass ;
390396}
@@ -396,6 +402,13 @@ vm_cc_markable(const struct rb_callcache *cc)
396402 return FL_TEST_RAW ((VALUE )cc , VM_CALLCACHE_UNMARKABLE ) == 0 ;
397403}
398404
405+ static inline bool
406+ vm_cc_valid (const struct rb_callcache * cc )
407+ {
408+ VM_ASSERT (IMEMO_TYPE_P (cc , imemo_callcache ));
409+ return cc -> klass && !UNDEF_P (cc -> klass );
410+ }
411+
399412static inline const struct rb_callable_method_entry_struct *
400413vm_cc_cme (const struct rb_callcache * cc )
401414{
@@ -447,7 +460,7 @@ vm_cc_cmethod_missing_reason(const struct rb_callcache *cc)
447460static inline bool
448461vm_cc_invalidated_p (const struct rb_callcache * cc )
449462{
450- if (cc -> klass && !METHOD_ENTRY_INVALIDATED (vm_cc_cme (cc ))) {
463+ if (vm_cc_valid ( cc ) && !METHOD_ENTRY_INVALIDATED (vm_cc_cme (cc ))) {
451464 return false;
452465 }
453466 else {
@@ -543,9 +556,9 @@ vm_cc_invalidate(const struct rb_callcache *cc)
543556{
544557 VM_ASSERT (IMEMO_TYPE_P (cc , imemo_callcache ));
545558 VM_ASSERT (cc != vm_cc_empty ());
546- VM_ASSERT (cc -> klass != 0 ); // should be enable
559+ VM_ASSERT (cc -> klass != Qundef ); // should be enable
547560
548- * (VALUE * )& cc -> klass = 0 ;
561+ * (VALUE * )& cc -> klass = Qundef ;
549562 RB_DEBUG_COUNTER_INC (cc_ent_invalidate );
550563}
551564
0 commit comments