diff --git a/vm_insnhelper.c b/vm_insnhelper.c index 2357a8d08b0ea4..58f1457cd57fa3 100644 --- a/vm_insnhelper.c +++ b/vm_insnhelper.c @@ -2184,6 +2184,18 @@ rb_vm_search_method_slowpath(const struct rb_callinfo *ci, VALUE klass) { const struct rb_callcache *cc; + VM_ASSERT(!SPECIAL_CONST_P(klass)); + + if (RB_BUILTIN_TYPE(klass) == T_NONE) { + // If we find a T_NONE here, it's most likely we called CLASS_OF(obj) on a + // garbage collected object (the freelist is stored in the class pointer), + // but it's possible that just the class was GC'd. + // This message intentionally tries to imply the former, but make an + // accurate statement for either case. + rb_bug("attempted to search method '%s' on a garbage collected object", + rb_id2name(vm_ci_mid(ci))); + } + VM_ASSERT_TYPE2(klass, T_CLASS, T_ICLASS); RB_VM_LOCK_ENTER(); diff --git a/vm_method.c b/vm_method.c index 7288fdd2ec5cd0..31dfa7b388f9e1 100644 --- a/vm_method.c +++ b/vm_method.c @@ -1488,6 +1488,18 @@ callable_method_entry_or_negative(VALUE klass, ID mid, VALUE *defined_class_ptr) { const rb_callable_method_entry_t *cme; + VM_ASSERT(!SPECIAL_CONST_P(klass)); + + if (RB_BUILTIN_TYPE(klass) == T_NONE) { + // If we find a T_NONE here, it's most likely we called CLASS_OF(obj) on a + // garbage collected object (the freelist is stored in the class pointer), + // but it's possible that just the class was GC'd. + // This message intentionally tries to imply the former, but make an + // accurate statement for either case. + rb_bug("attempted to search method '%s' on a garbage collected object", + rb_id2name(mid)); + } + VM_ASSERT_TYPE2(klass, T_CLASS, T_ICLASS); RB_VM_LOCK_ENTER(); {