]> git.saurik.com Git - apple/objc4.git/blob - runtime/objc-cache.mm
objc4-818.2.tar.gz
[apple/objc4.git] / runtime / objc-cache.mm
1 /*
2 * Copyright (c) 1999-2007 Apple Inc. All Rights Reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. Please obtain a copy of the License at
10 * http://www.opensource.apple.com/apsl/ and read it before using this
11 * file.
12 *
13 * The Original Code and all software distributed under the License are
14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
18 * Please see the License for the specific language governing rights and
19 * limitations under the License.
20 *
21 * @APPLE_LICENSE_HEADER_END@
22 */
23
24 /***********************************************************************
25 * objc-cache.m
26 * Method cache management
27 * Cache flushing
28 * Cache garbage collection
29 * Cache instrumentation
30 * Dedicated allocator for large caches
31 **********************************************************************/
32
33
34 /***********************************************************************
35 * Method cache locking (GrP 2001-1-14)
36 *
37 * For speed, objc_msgSend does not acquire any locks when it reads
38 * method caches. Instead, all cache changes are performed so that any
39 * objc_msgSend running concurrently with the cache mutator will not
40 * crash or hang or get an incorrect result from the cache.
41 *
42 * When cache memory becomes unused (e.g. the old cache after cache
43 * expansion), it is not immediately freed, because a concurrent
44 * objc_msgSend could still be using it. Instead, the memory is
45 * disconnected from the data structures and placed on a garbage list.
46 * The memory is now only accessible to instances of objc_msgSend that
47 * were running when the memory was disconnected; any further calls to
48 * objc_msgSend will not see the garbage memory because the other data
49 * structures don't point to it anymore. The collecting_in_critical
50 * function checks the PC of all threads and returns FALSE when all threads
51 * are found to be outside objc_msgSend. This means any call to objc_msgSend
52 * that could have had access to the garbage has finished or moved past the
53 * cache lookup stage, so it is safe to free the memory.
54 *
55 * All functions that modify cache data or structures must acquire the
56 * cacheUpdateLock to prevent interference from concurrent modifications.
57 * The function that frees cache garbage must acquire the cacheUpdateLock
58 * and use collecting_in_critical() to flush out cache readers.
59 * The cacheUpdateLock is also used to protect the custom allocator used
60 * for large method cache blocks.
61 *
62 * Cache readers (PC-checked by collecting_in_critical())
63 * objc_msgSend*
64 * cache_getImp
65 *
66 * Cache readers/writers (hold cacheUpdateLock during access; not PC-checked)
67 * cache_t::copyCacheNolock (caller must hold the lock)
68 * cache_t::eraseNolock (caller must hold the lock)
69 * cache_t::collectNolock (caller must hold the lock)
70 * cache_t::insert (acquires lock)
71 * cache_t::destroy (acquires lock)
72 *
73 * UNPROTECTED cache readers (NOT thread-safe; used for debug info only)
74 * cache_print
75 * _class_printMethodCaches
76 * _class_printDuplicateCacheEntries
77 * _class_printMethodCacheStatistics
78 *
79 ***********************************************************************/
80
81
82 #if __OBJC2__
83
84 #include "objc-private.h"
85
86 #if TARGET_OS_OSX
87 #include <Cambria/Traps.h>
88 #include <Cambria/Cambria.h>
89 #endif
90
91 #if __arm__ || __x86_64__ || __i386__
92
93 // objc_msgSend has few registers available.
94 // Cache scan increments and wraps at special end-marking bucket.
95 #define CACHE_END_MARKER 1
96
97 // Historical fill ratio of 75% (since the new objc runtime was introduced).
98 static inline mask_t cache_fill_ratio(mask_t capacity) {
99 return capacity * 3 / 4;
100 }
101
102 #elif __arm64__ && !__LP64__
103
104 // objc_msgSend has lots of registers available.
105 // Cache scan decrements. No end marker needed.
106 #define CACHE_END_MARKER 0
107
108 // Historical fill ratio of 75% (since the new objc runtime was introduced).
109 static inline mask_t cache_fill_ratio(mask_t capacity) {
110 return capacity * 3 / 4;
111 }
112
113 #elif __arm64__ && __LP64__
114
115 // objc_msgSend has lots of registers available.
116 // Cache scan decrements. No end marker needed.
117 #define CACHE_END_MARKER 0
118
119 // Allow 87.5% fill ratio in the fast path for all cache sizes.
120 // Increasing the cache fill ratio reduces the fragmentation and wasted space
121 // in imp-caches at the cost of potentially increasing the average lookup of
122 // a selector in imp-caches by increasing collision chains. Another potential
123 // change is that cache table resizes / resets happen at different moments.
124 static inline mask_t cache_fill_ratio(mask_t capacity) {
125 return capacity * 7 / 8;
126 }
127
128 // Allow 100% cache utilization for smaller cache sizes. This has the same
129 // advantages and disadvantages as the fill ratio. A very large percentage
130 // of caches end up with very few entries and the worst case of collision
131 // chains in small tables is relatively small.
132 // NOTE: objc_msgSend properly handles a cache lookup with a full cache.
133 #define CACHE_ALLOW_FULL_UTILIZATION 1
134
135 #else
136 #error unknown architecture
137 #endif
138
139 /* Initial cache bucket count. INIT_CACHE_SIZE must be a power of two. */
140 enum {
141 #if CACHE_END_MARKER || (__arm64__ && !__LP64__)
142 // When we have a cache end marker it fills a bucket slot, so having a
143 // initial cache size of 2 buckets would not be efficient when one of the
144 // slots is always filled with the end marker. So start with a cache size
145 // 4 buckets.
146 INIT_CACHE_SIZE_LOG2 = 2,
147 #else
148 // Allow an initial bucket size of 2 buckets, since a large number of
149 // classes, especially metaclasses, have very few imps, and we support
150 // the ability to fill 100% of the cache before resizing.
151 INIT_CACHE_SIZE_LOG2 = 1,
152 #endif
153 INIT_CACHE_SIZE = (1 << INIT_CACHE_SIZE_LOG2),
154 MAX_CACHE_SIZE_LOG2 = 16,
155 MAX_CACHE_SIZE = (1 << MAX_CACHE_SIZE_LOG2),
156 FULL_UTILIZATION_CACHE_SIZE_LOG2 = 3,
157 FULL_UTILIZATION_CACHE_SIZE = (1 << FULL_UTILIZATION_CACHE_SIZE_LOG2),
158 };
159
160 static int _collecting_in_critical(void);
161 static void _garbage_make_room(void);
162
163 #if DEBUG_TASK_THREADS
164 static kern_return_t objc_task_threads
165 (
166 task_t target_task,
167 thread_act_array_t *act_list,
168 mach_msg_type_number_t *act_listCnt
169 );
170 #endif
171
172 #if DEBUG_TASK_THREADS
173 #undef HAVE_TASK_RESTARTABLE_RANGES
174 #endif
175
176 /***********************************************************************
177 * Cache statistics for OBJC_PRINT_CACHE_SETUP
178 **********************************************************************/
179 static unsigned int cache_counts[16];
180 static size_t cache_allocations;
181 static size_t cache_collections;
182
183 static void recordNewCache(mask_t capacity)
184 {
185 size_t bucket = log2u(capacity);
186 if (bucket < countof(cache_counts)) {
187 cache_counts[bucket]++;
188 }
189 cache_allocations++;
190 }
191
192 static void recordDeadCache(mask_t capacity)
193 {
194 size_t bucket = log2u(capacity);
195 if (bucket < countof(cache_counts)) {
196 cache_counts[bucket]--;
197 }
198 }
199
200 /***********************************************************************
201 * Pointers used by compiled class objects
202 * These use asm to avoid conflicts with the compiler's internal declarations
203 **********************************************************************/
204
205 // EMPTY_BYTES includes space for a cache end marker bucket.
206 // This end marker doesn't actually have the wrap-around pointer
207 // because cache scans always find an empty bucket before they might wrap.
208 // 1024 buckets is fairly common.
209 #if DEBUG
210 // Use a smaller size to exercise heap-allocated empty caches.
211 # define EMPTY_BYTES ((8+1)*16)
212 #else
213 # define EMPTY_BYTES ((1024+1)*16)
214 #endif
215
216 #define stringize(x) #x
217 #define stringize2(x) stringize(x)
218
219 // "cache" is cache->buckets; "vtable" is cache->mask/occupied
220 // hack to avoid conflicts with compiler's internal declaration
221 asm("\n .section __TEXT,__const"
222 "\n .globl __objc_empty_vtable"
223 "\n .set __objc_empty_vtable, 0"
224 "\n .globl __objc_empty_cache"
225 #if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_LOW_4
226 "\n .align 4"
227 "\n L__objc_empty_cache: .space " stringize2(EMPTY_BYTES)
228 "\n .set __objc_empty_cache, L__objc_empty_cache + 0xf"
229 #else
230 "\n .align 3"
231 "\n __objc_empty_cache: .space " stringize2(EMPTY_BYTES)
232 #endif
233 );
234
235 #if CONFIG_USE_PREOPT_CACHES
236 __attribute__((used, section("__DATA_CONST,__objc_scoffs")))
237 uintptr_t objc_opt_offsets[__OBJC_OPT_OFFSETS_COUNT];
238 #endif
239
240 #if CACHE_END_MARKER
241 static inline mask_t cache_next(mask_t i, mask_t mask) {
242 return (i+1) & mask;
243 }
244 #elif __arm64__
245 static inline mask_t cache_next(mask_t i, mask_t mask) {
246 return i ? i-1 : mask;
247 }
248 #else
249 #error unexpected configuration
250 #endif
251
252
253 // mega_barrier doesn't really work, but it works enough on ARM that
254 // we leave well enough alone and keep using it there.
255 #if __arm__
256 #define mega_barrier() \
257 __asm__ __volatile__( \
258 "dsb ish" \
259 : : : "memory")
260
261 #endif
262
263 #if __arm64__
264
265 // Pointer-size register prefix for inline asm
266 # if __LP64__
267 # define p "x" // true arm64
268 # else
269 # define p "w" // arm64_32
270 # endif
271
272 // Use atomic double-word instructions to update cache entries.
273 // This requires cache buckets not cross cache line boundaries.
274 static ALWAYS_INLINE void
275 stp(uintptr_t onep, uintptr_t twop, void *destp)
276 {
277 __asm__ ("stp %" p "[one], %" p "[two], [%x[dest]]"
278 : "=m" (((uintptr_t *)(destp))[0]),
279 "=m" (((uintptr_t *)(destp))[1])
280 : [one] "r" (onep),
281 [two] "r" (twop),
282 [dest] "r" (destp)
283 : /* no clobbers */
284 );
285 }
286
287 static ALWAYS_INLINE void __unused
288 ldp(uintptr_t& onep, uintptr_t& twop, const void *srcp)
289 {
290 __asm__ ("ldp %" p "[one], %" p "[two], [%x[src]]"
291 : [one] "=r" (onep),
292 [two] "=r" (twop)
293 : "m" (((const uintptr_t *)(srcp))[0]),
294 "m" (((const uintptr_t *)(srcp))[1]),
295 [src] "r" (srcp)
296 : /* no clobbers */
297 );
298 }
299
300 #undef p
301 #endif
302
303
304 // Class points to cache. SEL is key. Cache buckets store SEL+IMP.
305 // Caches are never built in the dyld shared cache.
306
307 static inline mask_t cache_hash(SEL sel, mask_t mask)
308 {
309 uintptr_t value = (uintptr_t)sel;
310 #if CONFIG_USE_PREOPT_CACHES
311 value ^= value >> 7;
312 #endif
313 return (mask_t)(value & mask);
314 }
315
316 #if __arm64__
317
318 template<Atomicity atomicity, IMPEncoding impEncoding>
319 void bucket_t::set(bucket_t *base, SEL newSel, IMP newImp, Class cls)
320 {
321 ASSERT(_sel.load(memory_order_relaxed) == 0 ||
322 _sel.load(memory_order_relaxed) == newSel);
323
324 static_assert(offsetof(bucket_t,_imp) == 0 &&
325 offsetof(bucket_t,_sel) == sizeof(void *),
326 "bucket_t layout doesn't match arm64 bucket_t::set()");
327
328 uintptr_t encodedImp = (impEncoding == Encoded
329 ? encodeImp(base, newImp, newSel, cls)
330 : (uintptr_t)newImp);
331
332 // LDP/STP guarantees that all observers get
333 // either imp/sel or newImp/newSel
334 stp(encodedImp, (uintptr_t)newSel, this);
335 }
336
337 #else
338
339 template<Atomicity atomicity, IMPEncoding impEncoding>
340 void bucket_t::set(bucket_t *base, SEL newSel, IMP newImp, Class cls)
341 {
342 ASSERT(_sel.load(memory_order_relaxed) == 0 ||
343 _sel.load(memory_order_relaxed) == newSel);
344
345 // objc_msgSend uses sel and imp with no locks.
346 // It is safe for objc_msgSend to see new imp but NULL sel
347 // (It will get a cache miss but not dispatch to the wrong place.)
348 // It is unsafe for objc_msgSend to see old imp and new sel.
349 // Therefore we write new imp, wait a lot, then write new sel.
350
351 uintptr_t newIMP = (impEncoding == Encoded
352 ? encodeImp(base, newImp, newSel, cls)
353 : (uintptr_t)newImp);
354
355 if (atomicity == Atomic) {
356 _imp.store(newIMP, memory_order_relaxed);
357
358 if (_sel.load(memory_order_relaxed) != newSel) {
359 #ifdef __arm__
360 mega_barrier();
361 _sel.store(newSel, memory_order_relaxed);
362 #elif __x86_64__ || __i386__
363 _sel.store(newSel, memory_order_release);
364 #else
365 #error Don't know how to do bucket_t::set on this architecture.
366 #endif
367 }
368 } else {
369 _imp.store(newIMP, memory_order_relaxed);
370 _sel.store(newSel, memory_order_relaxed);
371 }
372 }
373
374 #endif
375
376 void cache_t::initializeToEmpty()
377 {
378 _bucketsAndMaybeMask.store((uintptr_t)&_objc_empty_cache, std::memory_order_relaxed);
379 _originalPreoptCache.store(nullptr, std::memory_order_relaxed);
380 }
381
382 #if CONFIG_USE_PREOPT_CACHES
383 /*
384 * The shared cache builder will sometimes have prebuilt an IMP cache
385 * for the class and left a `preopt_cache_t` pointer in _originalPreoptCache.
386 *
387 * However we have this tension:
388 * - when the class is realized it has to have a cache that can't resolve any
389 * selector until the class is properly initialized so that every
390 * caller falls in the slowpath and synchronizes with the class initializing,
391 * - we need to remember that cache pointer and we have no space for that.
392 *
393 * The caches are designed so that preopt_cache::bit_one is set to 1,
394 * so we "disguise" the pointer so that it looks like a cache of capacity 1
395 * where that bit one aliases with where the top bit of a SEL in the bucket_t
396 * would live:
397 *
398 * +----------------+----------------+
399 * | IMP | SEL | << a bucket_t
400 * +----------------+----------------+--------------...
401 * preopt_cache_t >>| 1| ...
402 * +----------------+--------------...
403 *
404 * The shared cache guarantees that there's valid memory to read under "IMP"
405 *
406 * This lets us encode the original preoptimized cache pointer during
407 * initialization, and we can reconstruct its original address and install
408 * it back later.
409 */
410 void cache_t::initializeToPreoptCacheInDisguise(const preopt_cache_t *cache)
411 {
412 // preopt_cache_t::bit_one is 1 which sets the top bit
413 // and is never set on any valid selector
414
415 uintptr_t value = (uintptr_t)cache + sizeof(preopt_cache_t) -
416 (bucket_t::offsetOfSel() + sizeof(SEL));
417
418 _originalPreoptCache.store(nullptr, std::memory_order_relaxed);
419 setBucketsAndMask((bucket_t *)value, 0);
420 _occupied = cache->occupied;
421 }
422
423 void cache_t::maybeConvertToPreoptimized()
424 {
425 const preopt_cache_t *cache = disguised_preopt_cache();
426
427 if (cache == nil) {
428 return;
429 }
430
431 if (!cls()->allowsPreoptCaches() ||
432 (cache->has_inlines && !cls()->allowsPreoptInlinedSels())) {
433 if (PrintCaches) {
434 _objc_inform("CACHES: %sclass %s: dropping cache (from %s)",
435 cls()->isMetaClass() ? "meta" : "",
436 cls()->nameForLogging(), "setInitialized");
437 }
438 return setBucketsAndMask(emptyBuckets(), 0);
439 }
440
441 uintptr_t value = (uintptr_t)&cache->entries;
442 #if __has_feature(ptrauth_calls)
443 value = (uintptr_t)ptrauth_sign_unauthenticated((void *)value,
444 ptrauth_key_process_dependent_data, (uintptr_t)cls());
445 #endif
446 value |= preoptBucketsHashParams(cache) | preoptBucketsMarker;
447 _bucketsAndMaybeMask.store(value, memory_order_relaxed);
448 _occupied = cache->occupied;
449 }
450
451 void cache_t::initializeToEmptyOrPreoptimizedInDisguise()
452 {
453 if (os_fastpath(!DisablePreoptCaches)) {
454 if (!objc::dataSegmentsRanges.inSharedCache((uintptr_t)this)) {
455 if (dyld_shared_cache_some_image_overridden()) {
456 // If the system has roots, then we must disable preoptimized
457 // caches completely. If a class in another image has a
458 // superclass in the root, the offset to the superclass will
459 // be wrong. rdar://problem/61601961
460 cls()->setDisallowPreoptCachesRecursively("roots");
461 }
462 return initializeToEmpty();
463 }
464
465 auto cache = _originalPreoptCache.load(memory_order_relaxed);
466 if (cache) {
467 return initializeToPreoptCacheInDisguise(cache);
468 }
469 }
470
471 return initializeToEmpty();
472 }
473
474 const preopt_cache_t *cache_t::preopt_cache() const
475 {
476 auto addr = _bucketsAndMaybeMask.load(memory_order_relaxed);
477 addr &= preoptBucketsMask;
478 #if __has_feature(ptrauth_calls)
479 #if __BUILDING_OBJCDT__
480 addr = (uintptr_t)ptrauth_strip((preopt_cache_entry_t *)addr,
481 ptrauth_key_process_dependent_data);
482 #else
483 addr = (uintptr_t)ptrauth_auth_data((preopt_cache_entry_t *)addr,
484 ptrauth_key_process_dependent_data, (uintptr_t)cls());
485 #endif
486 #endif
487 return (preopt_cache_t *)(addr - sizeof(preopt_cache_t));
488 }
489
490 const preopt_cache_t *cache_t::disguised_preopt_cache() const
491 {
492 bucket_t *b = buckets();
493 if ((intptr_t)b->sel() >= 0) return nil;
494
495 uintptr_t value = (uintptr_t)b + bucket_t::offsetOfSel() + sizeof(SEL);
496 return (preopt_cache_t *)(value - sizeof(preopt_cache_t));
497 }
498
499 Class cache_t::preoptFallbackClass() const
500 {
501 return (Class)((uintptr_t)cls() + preopt_cache()->fallback_class_offset);
502 }
503
504 bool cache_t::isConstantOptimizedCache(bool strict, uintptr_t empty_addr) const
505 {
506 uintptr_t addr = _bucketsAndMaybeMask.load(memory_order_relaxed);
507 if (addr & preoptBucketsMarker) {
508 return true;
509 }
510 if (strict) {
511 return false;
512 }
513 return mask() == 0 && addr != empty_addr;
514 }
515
516 bool cache_t::shouldFlush(SEL sel, IMP imp) const
517 {
518 // This test isn't backwards: disguised caches aren't "strict"
519 // constant optimized caches
520 if (!isConstantOptimizedCache(/*strict*/true)) {
521 const preopt_cache_t *cache = disguised_preopt_cache();
522 if (cache) {
523 uintptr_t offs = (uintptr_t)sel - (uintptr_t)@selector(🤯);
524 uintptr_t slot = ((offs >> cache->shift) & cache->mask);
525 auto &entry = cache->entries[slot];
526
527 return entry.sel_offs == offs &&
528 (uintptr_t)cls() - entry.imp_offs ==
529 (uintptr_t)ptrauth_strip(imp, ptrauth_key_function_pointer);
530 }
531 }
532
533 return cache_getImp(cls(), sel) == imp;
534 }
535
536 bool cache_t::isConstantOptimizedCacheWithInlinedSels() const
537 {
538 return isConstantOptimizedCache(/* strict */true) && preopt_cache()->has_inlines;
539 }
540 #endif // CONFIG_USE_PREOPT_CACHES
541
542 #if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_OUTLINED
543
544 void cache_t::setBucketsAndMask(struct bucket_t *newBuckets, mask_t newMask)
545 {
546 // objc_msgSend uses mask and buckets with no locks.
547 // It is safe for objc_msgSend to see new buckets but old mask.
548 // (It will get a cache miss but not overrun the buckets' bounds).
549 // It is unsafe for objc_msgSend to see old buckets and new mask.
550 // Therefore we write new buckets, wait a lot, then write new mask.
551 // objc_msgSend reads mask first, then buckets.
552
553 #ifdef __arm__
554 // ensure other threads see buckets contents before buckets pointer
555 mega_barrier();
556
557 _bucketsAndMaybeMask.store((uintptr_t)newBuckets, memory_order_relaxed);
558
559 // ensure other threads see new buckets before new mask
560 mega_barrier();
561
562 _maybeMask.store(newMask, memory_order_relaxed);
563 _occupied = 0;
564 #elif __x86_64__ || i386
565 // ensure other threads see buckets contents before buckets pointer
566 _bucketsAndMaybeMask.store((uintptr_t)newBuckets, memory_order_release);
567
568 // ensure other threads see new buckets before new mask
569 _maybeMask.store(newMask, memory_order_release);
570 _occupied = 0;
571 #else
572 #error Don't know how to do setBucketsAndMask on this architecture.
573 #endif
574 }
575
576 mask_t cache_t::mask() const
577 {
578 return _maybeMask.load(memory_order_relaxed);
579 }
580
581 #elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16 || CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16_BIG_ADDRS
582
583 void cache_t::setBucketsAndMask(struct bucket_t *newBuckets, mask_t newMask)
584 {
585 uintptr_t buckets = (uintptr_t)newBuckets;
586 uintptr_t mask = (uintptr_t)newMask;
587
588 ASSERT(buckets <= bucketsMask);
589 ASSERT(mask <= maxMask);
590
591 _bucketsAndMaybeMask.store(((uintptr_t)newMask << maskShift) | (uintptr_t)newBuckets, memory_order_relaxed);
592 _occupied = 0;
593 }
594
595 mask_t cache_t::mask() const
596 {
597 uintptr_t maskAndBuckets = _bucketsAndMaybeMask.load(memory_order_relaxed);
598 return maskAndBuckets >> maskShift;
599 }
600
601 #elif CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_LOW_4
602
603 void cache_t::setBucketsAndMask(struct bucket_t *newBuckets, mask_t newMask)
604 {
605 uintptr_t buckets = (uintptr_t)newBuckets;
606 unsigned mask = (unsigned)newMask;
607
608 ASSERT(buckets == (buckets & bucketsMask));
609 ASSERT(mask <= 0xffff);
610
611 _bucketsAndMaybeMask.store(buckets | objc::mask16ShiftBits(mask), memory_order_relaxed);
612 _occupied = 0;
613
614 ASSERT(this->buckets() == newBuckets);
615 ASSERT(this->mask() == newMask);
616 }
617
618 mask_t cache_t::mask() const
619 {
620 uintptr_t maskAndBuckets = _bucketsAndMaybeMask.load(memory_order_relaxed);
621 uintptr_t maskShift = (maskAndBuckets & maskMask);
622 return 0xffff >> maskShift;
623 }
624
625 #else
626 #error Unknown cache mask storage type.
627 #endif
628
629 struct bucket_t *cache_t::buckets() const
630 {
631 uintptr_t addr = _bucketsAndMaybeMask.load(memory_order_relaxed);
632 return (bucket_t *)(addr & bucketsMask);
633 }
634
635 mask_t cache_t::occupied() const
636 {
637 return _occupied;
638 }
639
640 void cache_t::incrementOccupied()
641 {
642 _occupied++;
643 }
644
645 unsigned cache_t::capacity() const
646 {
647 return mask() ? mask()+1 : 0;
648 }
649
650 Class cache_t::cls() const
651 {
652 return (Class)((uintptr_t)this - offsetof(objc_class, cache));
653 }
654
655 size_t cache_t::bytesForCapacity(uint32_t cap)
656 {
657 return sizeof(bucket_t) * cap;
658 }
659
660 #if CACHE_END_MARKER
661
662 bucket_t *cache_t::endMarker(struct bucket_t *b, uint32_t cap)
663 {
664 return (bucket_t *)((uintptr_t)b + bytesForCapacity(cap)) - 1;
665 }
666
667 bucket_t *cache_t::allocateBuckets(mask_t newCapacity)
668 {
669 // Allocate one extra bucket to mark the end of the list.
670 // This can't overflow mask_t because newCapacity is a power of 2.
671 bucket_t *newBuckets = (bucket_t *)calloc(bytesForCapacity(newCapacity), 1);
672
673 bucket_t *end = endMarker(newBuckets, newCapacity);
674
675 #if __arm__
676 // End marker's sel is 1 and imp points BEFORE the first bucket.
677 // This saves an instruction in objc_msgSend.
678 end->set<NotAtomic, Raw>(newBuckets, (SEL)(uintptr_t)1, (IMP)(newBuckets - 1), nil);
679 #else
680 // End marker's sel is 1 and imp points to the first bucket.
681 end->set<NotAtomic, Raw>(newBuckets, (SEL)(uintptr_t)1, (IMP)newBuckets, nil);
682 #endif
683
684 if (PrintCaches) recordNewCache(newCapacity);
685
686 return newBuckets;
687 }
688
689 #else
690
691 bucket_t *cache_t::allocateBuckets(mask_t newCapacity)
692 {
693 if (PrintCaches) recordNewCache(newCapacity);
694
695 return (bucket_t *)calloc(bytesForCapacity(newCapacity), 1);
696 }
697
698 #endif
699
700 struct bucket_t *cache_t::emptyBuckets()
701 {
702 return (bucket_t *)((uintptr_t)&_objc_empty_cache & bucketsMask);
703 }
704
705 bucket_t *cache_t::emptyBucketsForCapacity(mask_t capacity, bool allocate)
706 {
707 #if CONFIG_USE_CACHE_LOCK
708 cacheUpdateLock.assertLocked();
709 #else
710 runtimeLock.assertLocked();
711 #endif
712
713 size_t bytes = bytesForCapacity(capacity);
714
715 // Use _objc_empty_cache if the buckets is small enough.
716 if (bytes <= EMPTY_BYTES) {
717 return emptyBuckets();
718 }
719
720 // Use shared empty buckets allocated on the heap.
721 static bucket_t **emptyBucketsList = nil;
722 static mask_t emptyBucketsListCount = 0;
723
724 mask_t index = log2u(capacity);
725
726 if (index >= emptyBucketsListCount) {
727 if (!allocate) return nil;
728
729 mask_t newListCount = index + 1;
730 bucket_t *newBuckets = (bucket_t *)calloc(bytes, 1);
731 emptyBucketsList = (bucket_t**)
732 realloc(emptyBucketsList, newListCount * sizeof(bucket_t *));
733 // Share newBuckets for every un-allocated size smaller than index.
734 // The array is therefore always fully populated.
735 for (mask_t i = emptyBucketsListCount; i < newListCount; i++) {
736 emptyBucketsList[i] = newBuckets;
737 }
738 emptyBucketsListCount = newListCount;
739
740 if (PrintCaches) {
741 _objc_inform("CACHES: new empty buckets at %p (capacity %zu)",
742 newBuckets, (size_t)capacity);
743 }
744 }
745
746 return emptyBucketsList[index];
747 }
748
749 bool cache_t::isConstantEmptyCache() const
750 {
751 return
752 occupied() == 0 &&
753 buckets() == emptyBucketsForCapacity(capacity(), false);
754 }
755
756 bool cache_t::canBeFreed() const
757 {
758 return !isConstantEmptyCache() && !isConstantOptimizedCache();
759 }
760
761 ALWAYS_INLINE
762 void cache_t::reallocate(mask_t oldCapacity, mask_t newCapacity, bool freeOld)
763 {
764 bucket_t *oldBuckets = buckets();
765 bucket_t *newBuckets = allocateBuckets(newCapacity);
766
767 // Cache's old contents are not propagated.
768 // This is thought to save cache memory at the cost of extra cache fills.
769 // fixme re-measure this
770
771 ASSERT(newCapacity > 0);
772 ASSERT((uintptr_t)(mask_t)(newCapacity-1) == newCapacity-1);
773
774 setBucketsAndMask(newBuckets, newCapacity - 1);
775
776 if (freeOld) {
777 collect_free(oldBuckets, oldCapacity);
778 }
779 }
780
781
782 void cache_t::bad_cache(id receiver, SEL sel)
783 {
784 // Log in separate steps in case the logging itself causes a crash.
785 _objc_inform_now_and_on_crash
786 ("Method cache corrupted. This may be a message to an "
787 "invalid object, or a memory error somewhere else.");
788 #if CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_OUTLINED
789 bucket_t *b = buckets();
790 _objc_inform_now_and_on_crash
791 ("%s %p, SEL %p, isa %p, cache %p, buckets %p, "
792 "mask 0x%x, occupied 0x%x",
793 receiver ? "receiver" : "unused", receiver,
794 sel, cls(), this, b,
795 _maybeMask.load(memory_order_relaxed),
796 _occupied);
797 _objc_inform_now_and_on_crash
798 ("%s %zu bytes, buckets %zu bytes",
799 receiver ? "receiver" : "unused", malloc_size(receiver),
800 malloc_size(b));
801 #elif (CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16 || \
802 CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_HIGH_16_BIG_ADDRS || \
803 CACHE_MASK_STORAGE == CACHE_MASK_STORAGE_LOW_4)
804 uintptr_t maskAndBuckets = _bucketsAndMaybeMask.load(memory_order_relaxed);
805 _objc_inform_now_and_on_crash
806 ("%s %p, SEL %p, isa %p, cache %p, buckets and mask 0x%lx, "
807 "occupied 0x%x",
808 receiver ? "receiver" : "unused", receiver,
809 sel, cls(), this, maskAndBuckets, _occupied);
810 _objc_inform_now_and_on_crash
811 ("%s %zu bytes, buckets %zu bytes",
812 receiver ? "receiver" : "unused", malloc_size(receiver),
813 malloc_size(buckets()));
814 #else
815 #error Unknown cache mask storage type.
816 #endif
817 _objc_inform_now_and_on_crash
818 ("selector '%s'", sel_getName(sel));
819 _objc_inform_now_and_on_crash
820 ("isa '%s'", cls()->nameForLogging());
821 _objc_fatal
822 ("Method cache corrupted. This may be a message to an "
823 "invalid object, or a memory error somewhere else.");
824 }
825
826 void cache_t::insert(SEL sel, IMP imp, id receiver)
827 {
828 runtimeLock.assertLocked();
829
830 // Never cache before +initialize is done
831 if (slowpath(!cls()->isInitialized())) {
832 return;
833 }
834
835 if (isConstantOptimizedCache()) {
836 _objc_fatal("cache_t::insert() called with a preoptimized cache for %s",
837 cls()->nameForLogging());
838 }
839
840 #if DEBUG_TASK_THREADS
841 return _collecting_in_critical();
842 #else
843 #if CONFIG_USE_CACHE_LOCK
844 mutex_locker_t lock(cacheUpdateLock);
845 #endif
846
847 ASSERT(sel != 0 && cls()->isInitialized());
848
849 // Use the cache as-is if until we exceed our expected fill ratio.
850 mask_t newOccupied = occupied() + 1;
851 unsigned oldCapacity = capacity(), capacity = oldCapacity;
852 if (slowpath(isConstantEmptyCache())) {
853 // Cache is read-only. Replace it.
854 if (!capacity) capacity = INIT_CACHE_SIZE;
855 reallocate(oldCapacity, capacity, /* freeOld */false);
856 }
857 else if (fastpath(newOccupied + CACHE_END_MARKER <= cache_fill_ratio(capacity))) {
858 // Cache is less than 3/4 or 7/8 full. Use it as-is.
859 }
860 #if CACHE_ALLOW_FULL_UTILIZATION
861 else if (capacity <= FULL_UTILIZATION_CACHE_SIZE && newOccupied + CACHE_END_MARKER <= capacity) {
862 // Allow 100% cache utilization for small buckets. Use it as-is.
863 }
864 #endif
865 else {
866 capacity = capacity ? capacity * 2 : INIT_CACHE_SIZE;
867 if (capacity > MAX_CACHE_SIZE) {
868 capacity = MAX_CACHE_SIZE;
869 }
870 reallocate(oldCapacity, capacity, true);
871 }
872
873 bucket_t *b = buckets();
874 mask_t m = capacity - 1;
875 mask_t begin = cache_hash(sel, m);
876 mask_t i = begin;
877
878 // Scan for the first unused slot and insert there.
879 // There is guaranteed to be an empty slot.
880 do {
881 if (fastpath(b[i].sel() == 0)) {
882 incrementOccupied();
883 b[i].set<Atomic, Encoded>(b, sel, imp, cls());
884 return;
885 }
886 if (b[i].sel() == sel) {
887 // The entry was added to the cache by some other thread
888 // before we grabbed the cacheUpdateLock.
889 return;
890 }
891 } while (fastpath((i = cache_next(i, m)) != begin));
892
893 bad_cache(receiver, (SEL)sel);
894 #endif // !DEBUG_TASK_THREADS
895 }
896
897 void cache_t::copyCacheNolock(objc_imp_cache_entry *buffer, int len)
898 {
899 #if CONFIG_USE_CACHE_LOCK
900 cacheUpdateLock.assertLocked();
901 #else
902 runtimeLock.assertLocked();
903 #endif
904 int wpos = 0;
905
906 #if CONFIG_USE_PREOPT_CACHES
907 if (isConstantOptimizedCache()) {
908 auto cache = preopt_cache();
909 auto mask = cache->mask;
910 uintptr_t sel_base = objc_opt_offsets[OBJC_OPT_METHODNAME_START];
911 uintptr_t imp_base = (uintptr_t)&cache->entries;
912
913 for (uintptr_t index = 0; index <= mask && wpos < len; index++) {
914 auto &ent = cache->entries[index];
915 if (~ent.sel_offs) {
916 buffer[wpos].sel = (SEL)(sel_base + ent.sel_offs);
917 buffer[wpos].imp = (IMP)(imp_base - ent.imp_offs);
918 wpos++;
919 }
920 }
921 return;
922 }
923 #endif
924 {
925 bucket_t *buckets = this->buckets();
926 uintptr_t count = capacity();
927
928 for (uintptr_t index = 0; index < count && wpos < len; index++) {
929 if (buckets[index].sel()) {
930 buffer[wpos].imp = buckets[index].imp(buckets, cls());
931 buffer[wpos].sel = buckets[index].sel();
932 wpos++;
933 }
934 }
935 }
936 }
937
938 // Reset this entire cache to the uncached lookup by reallocating it.
939 // This must not shrink the cache - that breaks the lock-free scheme.
940 void cache_t::eraseNolock(const char *func)
941 {
942 #if CONFIG_USE_CACHE_LOCK
943 cacheUpdateLock.assertLocked();
944 #else
945 runtimeLock.assertLocked();
946 #endif
947
948 if (isConstantOptimizedCache()) {
949 auto c = cls();
950 if (PrintCaches) {
951 _objc_inform("CACHES: %sclass %s: dropping and disallowing preopt cache (from %s)",
952 c->isMetaClass() ? "meta" : "",
953 c->nameForLogging(), func);
954 }
955 setBucketsAndMask(emptyBuckets(), 0);
956 c->setDisallowPreoptCaches();
957 } else if (occupied() > 0) {
958 auto capacity = this->capacity();
959 auto oldBuckets = buckets();
960 auto buckets = emptyBucketsForCapacity(capacity);
961
962 setBucketsAndMask(buckets, capacity - 1); // also clears occupied
963 collect_free(oldBuckets, capacity);
964 }
965 }
966
967
968 void cache_t::destroy()
969 {
970 #if CONFIG_USE_CACHE_LOCK
971 mutex_locker_t lock(cacheUpdateLock);
972 #else
973 runtimeLock.assertLocked();
974 #endif
975 if (canBeFreed()) {
976 if (PrintCaches) recordDeadCache(capacity());
977 free(buckets());
978 }
979 }
980
981
982 /***********************************************************************
983 * cache collection.
984 **********************************************************************/
985
986 #if !TARGET_OS_WIN32
987
988 // A sentinel (magic value) to report bad thread_get_state status.
989 // Must not be a valid PC.
990 // Must not be zero - thread_get_state() on a new thread returns PC == 0.
991 #define PC_SENTINEL 1
992
993 static uintptr_t _get_pc_for_thread(thread_t thread)
994 #if defined(__i386__)
995 {
996 i386_thread_state_t state;
997 unsigned int count = i386_THREAD_STATE_COUNT;
998 kern_return_t okay = thread_get_state (thread, i386_THREAD_STATE, (thread_state_t)&state, &count);
999 return (okay == KERN_SUCCESS) ? state.__eip : PC_SENTINEL;
1000 }
1001 #elif defined(__x86_64__)
1002 {
1003 x86_thread_state64_t state;
1004 unsigned int count = x86_THREAD_STATE64_COUNT;
1005 kern_return_t okay = thread_get_state (thread, x86_THREAD_STATE64, (thread_state_t)&state, &count);
1006 return (okay == KERN_SUCCESS) ? state.__rip : PC_SENTINEL;
1007 }
1008 #elif defined(__arm__)
1009 {
1010 arm_thread_state_t state;
1011 unsigned int count = ARM_THREAD_STATE_COUNT;
1012 kern_return_t okay = thread_get_state (thread, ARM_THREAD_STATE, (thread_state_t)&state, &count);
1013 return (okay == KERN_SUCCESS) ? state.__pc : PC_SENTINEL;
1014 }
1015 #elif defined(__arm64__)
1016 {
1017 arm_thread_state64_t state;
1018 unsigned int count = ARM_THREAD_STATE64_COUNT;
1019 kern_return_t okay = thread_get_state (thread, ARM_THREAD_STATE64, (thread_state_t)&state, &count);
1020 return (okay == KERN_SUCCESS) ? (uintptr_t)arm_thread_state64_get_pc(state) : PC_SENTINEL;
1021 }
1022 #else
1023 {
1024 #error _get_pc_for_thread () not implemented for this architecture
1025 }
1026 #endif
1027
1028 #endif
1029
1030 /***********************************************************************
1031 * _collecting_in_critical.
1032 * Returns TRUE if some thread is currently executing a cache-reading
1033 * function. Collection of cache garbage is not allowed when a cache-
1034 * reading function is in progress because it might still be using
1035 * the garbage memory.
1036 **********************************************************************/
1037 #if HAVE_TASK_RESTARTABLE_RANGES
1038 #include <kern/restartable.h>
1039 #else
1040 typedef struct {
1041 uint64_t location;
1042 unsigned short length;
1043 unsigned short recovery_offs;
1044 unsigned int flags;
1045 } task_restartable_range_t;
1046 #endif
1047
1048 extern "C" task_restartable_range_t objc_restartableRanges[];
1049
1050 #if HAVE_TASK_RESTARTABLE_RANGES
1051 static bool shouldUseRestartableRanges = true;
1052 #endif
1053
1054 void cache_t::init()
1055 {
1056 #if HAVE_TASK_RESTARTABLE_RANGES
1057 mach_msg_type_number_t count = 0;
1058 kern_return_t kr;
1059
1060 while (objc_restartableRanges[count].location) {
1061 count++;
1062 }
1063
1064 kr = task_restartable_ranges_register(mach_task_self(),
1065 objc_restartableRanges, count);
1066 if (kr == KERN_SUCCESS) return;
1067 _objc_fatal("task_restartable_ranges_register failed (result 0x%x: %s)",
1068 kr, mach_error_string(kr));
1069 #endif // HAVE_TASK_RESTARTABLE_RANGES
1070 }
1071
1072 static int _collecting_in_critical(void)
1073 {
1074 #if TARGET_OS_WIN32
1075 return TRUE;
1076 #elif HAVE_TASK_RESTARTABLE_RANGES
1077 // Only use restartable ranges if we registered them earlier.
1078 if (shouldUseRestartableRanges) {
1079 kern_return_t kr = task_restartable_ranges_synchronize(mach_task_self());
1080 if (kr == KERN_SUCCESS) return FALSE;
1081 _objc_fatal("task_restartable_ranges_synchronize failed (result 0x%x: %s)",
1082 kr, mach_error_string(kr));
1083 }
1084 #endif // !HAVE_TASK_RESTARTABLE_RANGES
1085
1086 // Fallthrough if we didn't use restartable ranges.
1087
1088 thread_act_port_array_t threads;
1089 unsigned number;
1090 unsigned count;
1091 kern_return_t ret;
1092 int result;
1093
1094 mach_port_t mythread = pthread_mach_thread_np(objc_thread_self());
1095
1096 // Get a list of all the threads in the current task
1097 #if !DEBUG_TASK_THREADS
1098 ret = task_threads(mach_task_self(), &threads, &number);
1099 #else
1100 ret = objc_task_threads(mach_task_self(), &threads, &number);
1101 #endif
1102
1103 if (ret != KERN_SUCCESS) {
1104 // See DEBUG_TASK_THREADS below to help debug this.
1105 _objc_fatal("task_threads failed (result 0x%x)\n", ret);
1106 }
1107
1108 // Check whether any thread is in the cache lookup code
1109 result = FALSE;
1110 for (count = 0; count < number; count++)
1111 {
1112 int region;
1113 uintptr_t pc;
1114
1115 // Don't bother checking ourselves
1116 if (threads[count] == mythread)
1117 continue;
1118
1119 // Find out where thread is executing
1120 #if TARGET_OS_OSX
1121 if (oah_is_current_process_translated()) {
1122 kern_return_t ret = objc_thread_get_rip(threads[count], (uint64_t*)&pc);
1123 if (ret != KERN_SUCCESS) {
1124 pc = PC_SENTINEL;
1125 }
1126 } else {
1127 pc = _get_pc_for_thread (threads[count]);
1128 }
1129 #else
1130 pc = _get_pc_for_thread (threads[count]);
1131 #endif
1132
1133 // Check for bad status, and if so, assume the worse (can't collect)
1134 if (pc == PC_SENTINEL)
1135 {
1136 result = TRUE;
1137 goto done;
1138 }
1139
1140 // Check whether it is in the cache lookup code
1141 for (region = 0; objc_restartableRanges[region].location != 0; region++)
1142 {
1143 uint64_t loc = objc_restartableRanges[region].location;
1144 if ((pc > loc) &&
1145 (pc - loc < (uint64_t)objc_restartableRanges[region].length))
1146 {
1147 result = TRUE;
1148 goto done;
1149 }
1150 }
1151 }
1152
1153 done:
1154 // Deallocate the port rights for the threads
1155 for (count = 0; count < number; count++) {
1156 mach_port_deallocate(mach_task_self (), threads[count]);
1157 }
1158
1159 // Deallocate the thread list
1160 vm_deallocate (mach_task_self (), (vm_address_t) threads, sizeof(threads[0]) * number);
1161
1162 // Return our finding
1163 return result;
1164 }
1165
1166
1167 /***********************************************************************
1168 * _garbage_make_room. Ensure that there is enough room for at least
1169 * one more ref in the garbage.
1170 **********************************************************************/
1171
1172 // amount of memory represented by all refs in the garbage
1173 static size_t garbage_byte_size = 0;
1174
1175 // do not empty the garbage until garbage_byte_size gets at least this big
1176 static size_t garbage_threshold = 32*1024;
1177
1178 // table of refs to free
1179 static bucket_t **garbage_refs = 0;
1180
1181 // current number of refs in garbage_refs
1182 static size_t garbage_count = 0;
1183
1184 // capacity of current garbage_refs
1185 static size_t garbage_max = 0;
1186
1187 // capacity of initial garbage_refs
1188 enum {
1189 INIT_GARBAGE_COUNT = 128
1190 };
1191
1192 static void _garbage_make_room(void)
1193 {
1194 static int first = 1;
1195
1196 // Create the collection table the first time it is needed
1197 if (first)
1198 {
1199 first = 0;
1200 garbage_refs = (bucket_t**)
1201 malloc(INIT_GARBAGE_COUNT * sizeof(void *));
1202 garbage_max = INIT_GARBAGE_COUNT;
1203 }
1204
1205 // Double the table if it is full
1206 else if (garbage_count == garbage_max)
1207 {
1208 garbage_refs = (bucket_t**)
1209 realloc(garbage_refs, garbage_max * 2 * sizeof(void *));
1210 garbage_max *= 2;
1211 }
1212 }
1213
1214
1215 /***********************************************************************
1216 * cache_t::collect_free. Add the specified malloc'd memory to the list
1217 * of them to free at some later point.
1218 * size is used for the collection threshold. It does not have to be
1219 * precisely the block's size.
1220 * Cache locks: cacheUpdateLock must be held by the caller.
1221 **********************************************************************/
1222 void cache_t::collect_free(bucket_t *data, mask_t capacity)
1223 {
1224 #if CONFIG_USE_CACHE_LOCK
1225 cacheUpdateLock.assertLocked();
1226 #else
1227 runtimeLock.assertLocked();
1228 #endif
1229
1230 if (PrintCaches) recordDeadCache(capacity);
1231
1232 _garbage_make_room ();
1233 garbage_byte_size += cache_t::bytesForCapacity(capacity);
1234 garbage_refs[garbage_count++] = data;
1235 cache_t::collectNolock(false);
1236 }
1237
1238
1239 /***********************************************************************
1240 * cache_collect. Try to free accumulated dead caches.
1241 * collectALot tries harder to free memory.
1242 * Cache locks: cacheUpdateLock must be held by the caller.
1243 **********************************************************************/
1244 void cache_t::collectNolock(bool collectALot)
1245 {
1246 #if CONFIG_USE_CACHE_LOCK
1247 cacheUpdateLock.assertLocked();
1248 #else
1249 runtimeLock.assertLocked();
1250 #endif
1251
1252 // Done if the garbage is not full
1253 if (garbage_byte_size < garbage_threshold && !collectALot) {
1254 return;
1255 }
1256
1257 // Synchronize collection with objc_msgSend and other cache readers
1258 if (!collectALot) {
1259 if (_collecting_in_critical ()) {
1260 // objc_msgSend (or other cache reader) is currently looking in
1261 // the cache and might still be using some garbage.
1262 if (PrintCaches) {
1263 _objc_inform ("CACHES: not collecting; "
1264 "objc_msgSend in progress");
1265 }
1266 return;
1267 }
1268 }
1269 else {
1270 // No excuses.
1271 while (_collecting_in_critical())
1272 ;
1273 }
1274
1275 // No cache readers in progress - garbage is now deletable
1276
1277 // Log our progress
1278 if (PrintCaches) {
1279 cache_collections++;
1280 _objc_inform ("CACHES: COLLECTING %zu bytes (%zu allocations, %zu collections)", garbage_byte_size, cache_allocations, cache_collections);
1281 }
1282
1283 // Dispose all refs now in the garbage
1284 // Erase each entry so debugging tools don't see stale pointers.
1285 while (garbage_count--) {
1286 auto dead = garbage_refs[garbage_count];
1287 garbage_refs[garbage_count] = nil;
1288 free(dead);
1289 }
1290
1291 // Clear the garbage count and total size indicator
1292 garbage_count = 0;
1293 garbage_byte_size = 0;
1294
1295 if (PrintCaches) {
1296 size_t i;
1297 size_t total_count = 0;
1298 size_t total_size = 0;
1299
1300 for (i = 0; i < countof(cache_counts); i++) {
1301 int count = cache_counts[i];
1302 int slots = 1 << i;
1303 size_t size = count * slots * sizeof(bucket_t);
1304
1305 if (!count) continue;
1306
1307 _objc_inform("CACHES: %4d slots: %4d caches, %6zu bytes",
1308 slots, count, size);
1309
1310 total_count += count;
1311 total_size += size;
1312 }
1313
1314 _objc_inform("CACHES: total: %4zu caches, %6zu bytes",
1315 total_count, total_size);
1316 }
1317 }
1318
1319
1320 /***********************************************************************
1321 * objc_task_threads
1322 * Replacement for task_threads(). Define DEBUG_TASK_THREADS to debug
1323 * crashes when task_threads() is failing.
1324 *
1325 * A failure in task_threads() usually means somebody has botched their
1326 * Mach or MIG traffic. For example, somebody's error handling was wrong
1327 * and they left a message queued on the MIG reply port for task_threads()
1328 * to trip over.
1329 *
1330 * The code below is a modified version of task_threads(). It logs
1331 * the msgh_id of the reply message. The msgh_id can identify the sender
1332 * of the message, which can help pinpoint the faulty code.
1333 * DEBUG_TASK_THREADS also calls collecting_in_critical() during every
1334 * message dispatch, which can increase reproducibility of bugs.
1335 *
1336 * This code can be regenerated by running
1337 * `mig /usr/include/mach/task.defs`.
1338 **********************************************************************/
1339 #if DEBUG_TASK_THREADS
1340
1341 #include <mach/mach.h>
1342 #include <mach/message.h>
1343 #include <mach/mig.h>
1344
1345 #define __MIG_check__Reply__task_subsystem__ 1
1346 #define mig_internal static inline
1347 #define __DeclareSendRpc(a, b)
1348 #define __BeforeSendRpc(a, b)
1349 #define __AfterSendRpc(a, b)
1350 #define msgh_request_port msgh_remote_port
1351 #define msgh_reply_port msgh_local_port
1352
1353 #ifndef __MachMsgErrorWithTimeout
1354 #define __MachMsgErrorWithTimeout(_R_) { \
1355 switch (_R_) { \
1356 case MACH_SEND_INVALID_DATA: \
1357 case MACH_SEND_INVALID_DEST: \
1358 case MACH_SEND_INVALID_HEADER: \
1359 mig_put_reply_port(InP->Head.msgh_reply_port); \
1360 break; \
1361 case MACH_SEND_TIMED_OUT: \
1362 case MACH_RCV_TIMED_OUT: \
1363 default: \
1364 mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
1365 } \
1366 }
1367 #endif /* __MachMsgErrorWithTimeout */
1368
1369 #ifndef __MachMsgErrorWithoutTimeout
1370 #define __MachMsgErrorWithoutTimeout(_R_) { \
1371 switch (_R_) { \
1372 case MACH_SEND_INVALID_DATA: \
1373 case MACH_SEND_INVALID_DEST: \
1374 case MACH_SEND_INVALID_HEADER: \
1375 mig_put_reply_port(InP->Head.msgh_reply_port); \
1376 break; \
1377 default: \
1378 mig_dealloc_reply_port(InP->Head.msgh_reply_port); \
1379 } \
1380 }
1381 #endif /* __MachMsgErrorWithoutTimeout */
1382
1383
1384 #if ( __MigTypeCheck )
1385 #if __MIG_check__Reply__task_subsystem__
1386 #if !defined(__MIG_check__Reply__task_threads_t__defined)
1387 #define __MIG_check__Reply__task_threads_t__defined
1388
1389 mig_internal kern_return_t __MIG_check__Reply__task_threads_t(__Reply__task_threads_t *Out0P)
1390 {
1391
1392 typedef __Reply__task_threads_t __Reply;
1393 boolean_t msgh_simple;
1394 #if __MigTypeCheck
1395 unsigned int msgh_size;
1396 #endif /* __MigTypeCheck */
1397 if (Out0P->Head.msgh_id != 3502) {
1398 if (Out0P->Head.msgh_id == MACH_NOTIFY_SEND_ONCE)
1399 { return MIG_SERVER_DIED; }
1400 else
1401 { return MIG_REPLY_MISMATCH; }
1402 }
1403
1404 msgh_simple = !(Out0P->Head.msgh_bits & MACH_MSGH_BITS_COMPLEX);
1405 #if __MigTypeCheck
1406 msgh_size = Out0P->Head.msgh_size;
1407
1408 if ((msgh_simple || Out0P->msgh_body.msgh_descriptor_count != 1 ||
1409 msgh_size != (mach_msg_size_t)sizeof(__Reply)) &&
1410 (!msgh_simple || msgh_size != (mach_msg_size_t)sizeof(mig_reply_error_t) ||
1411 ((mig_reply_error_t *)Out0P)->RetCode == KERN_SUCCESS))
1412 { return MIG_TYPE_ERROR ; }
1413 #endif /* __MigTypeCheck */
1414
1415 if (msgh_simple) {
1416 return ((mig_reply_error_t *)Out0P)->RetCode;
1417 }
1418
1419 #if __MigTypeCheck
1420 if (Out0P->act_list.type != MACH_MSG_OOL_PORTS_DESCRIPTOR ||
1421 Out0P->act_list.disposition != 17) {
1422 return MIG_TYPE_ERROR;
1423 }
1424 #endif /* __MigTypeCheck */
1425
1426 return MACH_MSG_SUCCESS;
1427 }
1428 #endif /* !defined(__MIG_check__Reply__task_threads_t__defined) */
1429 #endif /* __MIG_check__Reply__task_subsystem__ */
1430 #endif /* ( __MigTypeCheck ) */
1431
1432
1433 /* Routine task_threads */
1434 static kern_return_t objc_task_threads
1435 (
1436 task_t target_task,
1437 thread_act_array_t *act_list,
1438 mach_msg_type_number_t *act_listCnt
1439 )
1440 {
1441
1442 #ifdef __MigPackStructs
1443 #pragma pack(4)
1444 #endif
1445 typedef struct {
1446 mach_msg_header_t Head;
1447 } Request;
1448 #ifdef __MigPackStructs
1449 #pragma pack()
1450 #endif
1451
1452 #ifdef __MigPackStructs
1453 #pragma pack(4)
1454 #endif
1455 typedef struct {
1456 mach_msg_header_t Head;
1457 /* start of the kernel processed data */
1458 mach_msg_body_t msgh_body;
1459 mach_msg_ool_ports_descriptor_t act_list;
1460 /* end of the kernel processed data */
1461 NDR_record_t NDR;
1462 mach_msg_type_number_t act_listCnt;
1463 mach_msg_trailer_t trailer;
1464 } Reply;
1465 #ifdef __MigPackStructs
1466 #pragma pack()
1467 #endif
1468
1469 #ifdef __MigPackStructs
1470 #pragma pack(4)
1471 #endif
1472 typedef struct {
1473 mach_msg_header_t Head;
1474 /* start of the kernel processed data */
1475 mach_msg_body_t msgh_body;
1476 mach_msg_ool_ports_descriptor_t act_list;
1477 /* end of the kernel processed data */
1478 NDR_record_t NDR;
1479 mach_msg_type_number_t act_listCnt;
1480 } __Reply;
1481 #ifdef __MigPackStructs
1482 #pragma pack()
1483 #endif
1484 /*
1485 * typedef struct {
1486 * mach_msg_header_t Head;
1487 * NDR_record_t NDR;
1488 * kern_return_t RetCode;
1489 * } mig_reply_error_t;
1490 */
1491
1492 union {
1493 Request In;
1494 Reply Out;
1495 } Mess;
1496
1497 Request *InP = &Mess.In;
1498 Reply *Out0P = &Mess.Out;
1499
1500 mach_msg_return_t msg_result;
1501
1502 #ifdef __MIG_check__Reply__task_threads_t__defined
1503 kern_return_t check_result;
1504 #endif /* __MIG_check__Reply__task_threads_t__defined */
1505
1506 __DeclareSendRpc(3402, "task_threads")
1507
1508 InP->Head.msgh_bits =
1509 MACH_MSGH_BITS(19, MACH_MSG_TYPE_MAKE_SEND_ONCE);
1510 /* msgh_size passed as argument */
1511 InP->Head.msgh_request_port = target_task;
1512 InP->Head.msgh_reply_port = mig_get_reply_port();
1513 InP->Head.msgh_id = 3402;
1514
1515 __BeforeSendRpc(3402, "task_threads")
1516 msg_result = mach_msg(&InP->Head, MACH_SEND_MSG|MACH_RCV_MSG|MACH_MSG_OPTION_NONE, (mach_msg_size_t)sizeof(Request), (mach_msg_size_t)sizeof(Reply), InP->Head.msgh_reply_port, MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL);
1517 __AfterSendRpc(3402, "task_threads")
1518 if (msg_result != MACH_MSG_SUCCESS) {
1519 _objc_inform("task_threads received unexpected reply msgh_id 0x%zx",
1520 (size_t)Out0P->Head.msgh_id);
1521 __MachMsgErrorWithoutTimeout(msg_result);
1522 { return msg_result; }
1523 }
1524
1525
1526 #if defined(__MIG_check__Reply__task_threads_t__defined)
1527 check_result = __MIG_check__Reply__task_threads_t((__Reply__task_threads_t *)Out0P);
1528 if (check_result != MACH_MSG_SUCCESS)
1529 { return check_result; }
1530 #endif /* defined(__MIG_check__Reply__task_threads_t__defined) */
1531
1532 *act_list = (thread_act_array_t)(Out0P->act_list.address);
1533 *act_listCnt = Out0P->act_listCnt;
1534
1535 return KERN_SUCCESS;
1536 }
1537
1538 // DEBUG_TASK_THREADS
1539 #endif
1540
1541 OBJC_EXPORT bucket_t * objc_cache_buckets(const cache_t * cache) {
1542 return cache->buckets();
1543 }
1544
1545 #if CONFIG_USE_PREOPT_CACHES
1546
1547 OBJC_EXPORT const preopt_cache_t * _Nonnull objc_cache_preoptCache(const cache_t * _Nonnull cache) {
1548 return cache->preopt_cache();
1549 }
1550
1551 OBJC_EXPORT bool objc_cache_isConstantOptimizedCache(const cache_t * _Nonnull cache, bool strict, uintptr_t empty_addr) {
1552 return cache->isConstantOptimizedCache(strict, empty_addr);
1553 }
1554
1555 OBJC_EXPORT unsigned objc_cache_preoptCapacity(const cache_t * _Nonnull cache) {
1556 return cache->preopt_cache()->capacity();
1557 }
1558
1559 OBJC_EXPORT Class _Nonnull objc_cache_preoptFallbackClass(const cache_t * _Nonnull cache) {
1560 return cache->preoptFallbackClass();
1561 }
1562
1563 #endif
1564
1565 OBJC_EXPORT size_t objc_cache_bytesForCapacity(uint32_t cap) {
1566 return cache_t::bytesForCapacity(cap);
1567 }
1568
1569 OBJC_EXPORT uint32_t objc_cache_occupied(const cache_t * _Nonnull cache) {
1570 return cache->occupied();
1571 }
1572
1573 OBJC_EXPORT unsigned objc_cache_capacity(const struct cache_t * _Nonnull cache) {
1574 return cache->capacity();
1575 }
1576
1577 // __OBJC2__
1578 #endif