+void cache_t::bad_cache(id receiver, SEL sel)
+{
+ // Log in separate steps in case the logging itself causes a crash.
+ _objc_inform_now_and_on_crash
+ ("Method cache corrupted. This may be a message to an "
+ "invalid object, or a memory error somewhere else.");
+#if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_OUTLINED
+ bucket_t *b = buckets();
+ _objc_inform_now_and_on_crash
+ ("%s %p, SEL %p, isa %p, cache %p, buckets %p, "
+ "mask 0x%x, occupied 0x%x",
+ receiver ? "receiver" : "unused", receiver,
+ sel, cls(), this, b,
+ _maybeMask.load(memory_order_relaxed),
+ _occupied);
+ _objc_inform_now_and_on_crash
+ ("%s %zu bytes, buckets %zu bytes",
+ receiver ? "receiver" : "unused", malloc_size(receiver),
+ malloc_size(b));
+#elif (CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16 || \
+ CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16_BIG_ADDRS || \
+ CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_LOW_4)
+ uintptr_t maskAndBuckets = _bucketsAndMaybeMask.load(memory_order_relaxed);
+ _objc_inform_now_and_on_crash
+ ("%s %p, SEL %p, isa %p, cache %p, buckets and mask 0x%lx, "
+ "occupied 0x%x",
+ receiver ? "receiver" : "unused", receiver,
+ sel, cls(), this, maskAndBuckets, _occupied);
+ _objc_inform_now_and_on_crash
+ ("%s %zu bytes, buckets %zu bytes",
+ receiver ? "receiver" : "unused", malloc_size(receiver),
+ malloc_size(buckets()));
+#else
+#error Unknown cache mask storage type.
+#endif
+ _objc_inform_now_and_on_crash
+ ("selector '%s'", sel_getName(sel));
+ _objc_inform_now_and_on_crash
+ ("isa '%s'", cls()->nameForLogging());
+ _objc_fatal
+ ("Method cache corrupted. This may be a message to an "
+ "invalid object, or a memory error somewhere else.");
+}
+
+void cache_t::insert(SEL sel, IMP imp, id receiver)