Study in harmony! Not anxious not impatient!! I am your old friend Xiao Qinglong
-
IOS low-level analysis and other exploration – Cache insert, objc_msgSend
-
Objc_msgSend Message dynamic resolution for iOS low-level analysis
-
Objc_msgSend message forwarding for iOS low-level analysis
The previous articles have taken you step by step to analyze the general flow of the underlying calls to objc_msgSend, and let’s summarize it:
A flowchart
Detailed process
What has been done for each of them is described as follows:
_objc_msgSend{non-empty judgment; Get the isa; Get the Class; CacheLookup NORMAL, _objc_msgSend, __objc_msgSend_uncached }Copy the code
CacheLookup{
/** ** ** ** ** ** ** ** ** ** **
1,classMemory offset foundcache_t2,cache_tAnd on themaskgetmaskThe address,cache_tAnd on thebucketgetbucketAddress; 3,maskAnd on theselgetsel-impThe subscriptindex; 4,bucketAccording to theindexI'm going to shift it in memory and get the correspondingbucket5, removebuckettheselandobj_msgSendincomingselCompare, agree, enterCacheHit; 6, inconsistentbucketIf you can't find it, go to step 5MissLabelDynamicThe content corresponding to the parameter; }Copy the code
CacheHit{determine the value of the first argument:1If equal to NORMAL, enter the TailCallCachedImp function.2Enter AuthAndResignAsIMP if GETIMP;3If it is equivalent to LOOKUP, enter AuthAndResignAsIMP; }Copy the code
// Cache imp decode, get real IMP, and enter IMP
TailCallCachedImp{
// $0 = cached imp, $1 = address of cached imp, $2 = SEL, $3 = isa
eor $0, $0, $3
br $0
}
// The imp is the real imp
AuthAndResignAsIMP{
$0 = cache IMP, $1 = address. $2 = SEL $3 = class
$0 = $0 ^ $3 = imp ^ class = imp
eor $0, $0, $3
}
Copy the code
// This step has started the slow search
__objc_msgSend_uncached{
1, MethodTableLookup// Perform a lookup of the method class table
2, TailCallFunctionPointer// Return to the function
}
Copy the code
// Method list lookup
MethodTableLookup{
_lookUpImpOrForward/ / find the imp
}
Copy the code
lookUpImpOrForward{
1, _objc_msgForward_impcache// Generate a default forward_IMP
2, checkIsKnownClass// Check whether the class has been registered
3, realizeAndInitializeIfNeeded_locked// Initialize class, superclass, metaclass, root metaclass
4,forThe body of the loop looks like this: look in the class method list with dichotomy, -> find, call log_and_fill_cache and write to the cache; -> curClass = 'curClass'; curClass = 'curClass'; curClass = 'curClass'; Keep going through this loop, write it to the cache when you find it, until curClass becomes nil (NSObject's parent class is nil), pass the default forward_IMP to IMP, jump outforCycle; }Copy the code
LGetImpMissDynamic{does just one thing: return0
}
Copy the code
_cache_getImp{
GetClassFromIsa_p16 p0, 0/ / get the isa
CacheLookup GETIMP, _cache_getImp, LGetImpMissDynamic, LGetImpMissConstant// Cache lookup
}
Copy the code
__objc_msgForward_impcache{
b __objc_msgForward // Jump to __objc_msgForward
END_ENTRY __objc_msgForward_impcache
}
Copy the code
__objc_msgForward{
adrp x17, __objc_forward_handler@PAGE
ldr p17, [x17, __objc_forward_handler@PAGEOFF]
/** TailCallFunctionPointer = $0; /** TailCallFunctionPointer = $0; /** TailCallFunctionPointer = $0; So __objc_msgForward is going into __objc_forward_handler */
TailCallFunctionPointer x17
}
Copy the code
__attribute__((noreturn, cold)) void
objc_defaultForwardHandler(id self, SEL sel)
{
_objc_fatal("%c[%s %s]: unrecognized selector sent to instance %p "
"(no message forward handler is installed)",
class_isMetaClass(object_getClass(self)) ? '+' : The '-',
object_getClassName(self), sel_getName(sel), self);
}
/ / is _objc_forward_handler objc_defaultForwardHandler
void *_objc_forward_handler = (void*)objc_defaultForwardHandler;
Copy the code
+ (BOOL)resolveInstanceMethod:(SEL)sel {
// Add a method implementation to an object. For example, if sel is run, then the imp returned can be the IMP of sleep;
}
+ (BOOL)resolveClassMethod:(SEL)sel{
// Add a method implementation to the class, ibid
}
Copy the code
// Quick message forwarding
- (id)forwardingTargetForSelector:(SEL)aSelector{
// Set the new message receiver
}
Copy the code
// Slow forwarding of messages
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
// Return the method signature
}
/// The method invocation contains the method signature information,
// In the forwardInvocation method, we can handle the exception method invocation or not, and it won't crash
- (void)forwardInvocation:(NSInvocation *)anInvocation{
// Some handling of exception methods
}
Copy the code