OC class principle exploration series articles
- OC class principle exploration: Class structure analysis
- OC class principle exploration: Class structure analysis supplement
- OC class principles exploration: the underlying principles of attributes
- OC class principle Exploration: Structural analysis of cache_t
- OC class principle exploration: Cache structure analysis supplement
preface
OC class principle exploration: Cache_t structure analysis of the structure of the cache has been introduced, with insert function as the starting point to analyze the use of member variables in the cache, today the cache structure to do some additions and extensions.
The preparatory work
- Objc4-818.2 – the source code
- LLVM source
1. _bucketsAndMaybeMask authentication
As stated in cache_T, _bucketsAndMaybeMask stores the first address of buckets. We use LLDB to verify this:
_bucketsAndMaybeMask
theValue
In order to16
Print in base form, the result is0x00000001006444a0
;buckets()
the16
The same is true for typing in base form0x00000001006444a0
;- According to the printed results, you can prove that
_bucketsAndMaybeMask
What is stored isbuckets
The initial address of.
B) buckets C) buckets D) buckets
Debug source breakpoints when adding methods:
-
The values of addr and buckets() are equal at 0x00000001003623A0.
-
buckets()
againaddr & bucketsMask
The result, the descriptionbucketsMask
Takes the following values:Expressed in binary: -
The value of bucketsMask varies according to the architecture:
3. Imp algorithm
The imp function in bucket_t has such a code return (IMP)(imp ^ (uintPtr_t) CLS); As follows:
- Here’s what’s involved
coding
anddecoding
In the process; - Storage of
imp
Is auintptr_t
(long integer), is not aA function pointer
; - through
^
The (xor) operation gets the address of the true pointer, but the reason it does this is because it does the same thing when storing (encoding). Let’s move on.
Encoding and decoding algorithm
Look at the set function and its encodeImp encoding function:
^
(XOR) algorithmc = a ^ b
;a = c ^ b
.
imp
The codecset
When,Imp = function pointer ^ CLS
;- When I take it,
Function pointer = IMP ^ CLS
; cls
It’s the salt of the algorithm.
LLDB encoding and decoding
Debug imp function at breakpoint:
To debug LLDB:
The say1 method was finally obtained through LLDB, which verified the above conclusion.
4, LLDB call method mask defaults to 7
- inOC class principle Exploration: Structural analysis of cache_tWe call with normal code
say1
Method,_maybeMask
The value is3
And here it becomes7
Why is that? _maybeMask
The value is7
“Indicates that there was an expansion. This expansion should be an insertsay1
Method or insertsay1
Method, because there’s no need to insert those methods later on, so we’re insertingsay1
Method to do some printing to analyze.
Insert the following code into the insert function:
Run the program, LLDB debug:
- As shown above in insert
say1
Method, insert firstrespondsToSelector
andclass
In the insertsay1
When we expand, we clear out the previous method, so eventually_maybeMask
The value is7
._occupied
The value is1
; - We also found that
buckets
Of the fourth storage unitimp
It stores the first address0x101906760
And that explains why jean Valjean_maybeMask
=capacity - 1
, also can be inobjc
Find the corresponding method in the source code.
Why insert response to Selector and class in advance
As to why the respondsToSelector and class are inserted in advance, the LLVM source code is also described;
Buckets the last storage unit
The IMP of the last storage unit of Buckets, which stores the first address of buckets, is also found in the OBJC source code.
Real environment for cache_NEXT
See the related source code for cache_next:
arm
The environment is our real environment, and in the real environment,cache_next
Is constantly looking for null values in the previous position;- In a non-real machine environment,
cache_next
It’s going to keep looking for a null in the last position.
What did you do before the insert() function
Now that we know a bit about insert(), what did we do before insert()? Let’s do a search on ->insert to see where it was called.
We did not find the cache-related insert() function, so we can make a breakpoint to see the stack information.
Search log_and_fill_cache to find the call to lookUpImpOrForward().
In addition to this method, we can see the following comment in objc-cache.mm:
We see that objc_msgSend is called before insert. Objc_msgSend is a very important method and will be explored in the next article.