The structure of the class
The structure of the class when it is first loaded from disk into memory is as followsThe first time it’s usedThe dynamically updated part is extracted and storedclass_rw_ext_t
The overall structure of the final class is as follows.ro
Clean memory, from the time it’s loaded, there’s no change,rw
Is dirty memory and is used to store dynamic changes
The cache analysis
What is the cache
We print out the contents of cache_t in the LLDB by shifting the address of the pointer. Here is the definition of cache_t. This article removes some unnecessary code
struct cache_t {
explicit_atomic<struct bucket_t *> _buckets;
explicit_atomic<mask_t> _mask;
uint16_t _flags;
uint16_t _occupied;
};
struct bucket_t {
private:
explicit_atomic<SEL> _sel;
explicit_atomic<uintptr_t> _imp;
};
Copy the code
Here is the LLDB debugging process,aboutbucket_t
Stored in the_buckets
Is through thehash
Value, where_occupied
I mean it takes up a couple of,
unsigned cache_t::capacity()
{
return mask() ? mask()+1 : 0;
}
Copy the code
_buckets = number of buckets -1. To find out how to save the _buckets
The following is a flowchart of the INSERT
LLDB calls the method
When we call methods through LLDB, we may find that the contents of the cache are not what we expected, and LLDB may increase the number of function callsWe call it in our codesetHobby:
, is called in LLDBaaaName
If theinsert
It’s only called twice, so it’s not going to be expanded, so you can see the currentoccupied = 2
.mask = 7
, indicating that the call is inaaaName
Time to expand the capacity.
The occupied = 4, mask = 7, and then output the contents of the buckets
The content of buckets is found to be extra class and respondsToSelector:, which is added by the LLDB call method. We call two methods through the code, and by the time we get to the third, we will expand, through the following source code
We will findbuckets
Will be the last onebucket_t
theIMP
Set to point to the first bucket, so when capacity is 4, only three are valid.
Added isKindOfClass & isMemberOfClass
The above results may feel more confused, so on the source coderes1~res4
Class methods are calledisKindOfClass
和 isMemberOfClass
First loop TCLS: root metaclass, CLS is NSObjet unequal second loop TCLS: The parent class of the root metaclass is NSObject equals CLS so res1 is YES analyze res2 self->ISA is the root metaclass, not equal to NSObject analyze res3 the first time TCLS: MLPerson metaclass, not equal to TCLS the second time: The parent class of MLPerson metaclass is the root metaclass, which is not equal, and the res3 metaclass is not equal to res4 analysis self->ISA is MLPerson metaclass, which is not equal to MLPersonCopy the code