Memory layout
- Stack: method invocation.
- Heap: an object allocated by alloc, etc.
- Text: program code.
- BSS: uninitialized global variables, etc.
- Data: initialized global variables.
Memory management scheme
TaggedPointer
Tagged Pointer stores data directly in the Pointer itself by setting a special flag on its last bit. Since Tagged Pointer is not really an object, we need to be careful not to access its ISA variable directly when using it.
NONPOINTER_ISA
Before the ARM64 architecture, ISA was a common pointer, storing the memory address of the Class and meta-class objects. Starting with the ARM64 architecture, ISA was optimized to become a common (union) structure, and bit fields were used to store more information
Hash table
The scattering table contains weak reference table and reference count table.
Hash table principle
Sidetables is a hash table. All hash tables are made of arrays and linked lists. So sidetables is an array that stores the sidetable. The storage structure in sidetable is weak_table_t, weak_table_t stores different objects weak_entry_t,weak_entry_t stores all weak reference Pointers of this object.
SideTables structure
SideTable structure
Why not a SideTable, but SideTables?
- Because data is locked when it is modified, if all the tables of the objects are in the same sideTable, the locking is too frequent and efficiency suffers.
- Because there are multiple SideTables, you can manipulate multiple tables asynchronously with less impact on each other.
How to implement fast triage (how to quickly locate its table through an object)?
- The essence of SideTables is one
The Hash table
. The Hash table
The time complexity of search isO(1)
.- through
Address of the object
与The Hash table
thecount
takedie
Gets the target value subscript index.
Reference counter table
- The reference count table is passed
The Hash table
To achieve. The Hash table
The time complexity of search isO(1)
.
Storage of reference counts
- If the Pointer is Tagged, return; otherwise, go to the next step
- Determine whether ISA has been optimized
- If optimized, the last 19 bits of the LAST ISA store reference counts
- If ISA is not optimized, then the sidetable_retainCount function is entered to get the reference count in the sideTable
- If the last 19 bits are not enough to store, the extra reference count is stored in the sidetable, and the 20th-to-last bit is set to 1, so has_sideTABLE_rc is set to 1
- If has_SIDETABLE_rc has a value of 1, the reference count stored in sideTable is retrieved from the sidetable_getExtraRC_nolock function
A weak reference table
The key of the table is the reference object and the value is an array representing all weak Pointers. If the weak pointer does not exist, insert the weak pointer into the array. When the weak pointer is destroyed, the weak pointer is removed from the array. When the reference object is destroyed, the weak pointer array is automatically set to nil.
How are weak-reference variables added to weak-reference tables?
How is the weak variable handled when an object is released?
- According to the
object
, look for toA weak reference table
To extractWeakly referenced array
. - Go through all of them
Weak reference pointer
And set tonil
.
Memory management
MRC
The object operation | Corresponding method in OC | The corresponding retainCount changes | |
---|---|---|
Generate and hold objects | Alloc/new/copy/mutableCopy, etc | + 1 |
Hold the object | retain | + 1 |
Release object | release | – 1 |
Discarded objects | dealloc | 0 |
ARC
ARC is an automatic memory management mechanism introduced by Apple that automatically monitors the lifetime of objects based on reference counts by automatically inserting appropriate memory management code into existing code at compile time and making some optimizations at Runtime.
The principle of
Retain implementation
Release implementation
RetainCount implementation
Dealloc implementation
Object_disponse () implementation
CleanDeallocating () implementation
Dealloc function principle
- Isa is an optimized pointer, the object is not weakly referenced, there are no associated objects, there are no c++ destructors, no reference counts are stored in the Sidetable, and it is immediately released
- Otherwise, call the object_dispose function
- Entering the object_dispose function, you can see that the objc_destructInstance function is called
- Going into the objc_destructInstance function, you can see that objC was processed by setting the weak pointer to nil in the clearDeallocating function
- Going into the clearDeallocating function, you see two things again
- The ISA of the object has not been optimized
- When YOU go into the sidetable_clearDeallocating function, you can see that the weak reference is stored in SideTable
- Stored in weak_table_t of SideTable
- Look at weak_table_t, where weak is stored in a global hash table
- Weak_clear_no_lock function is used to set the weak pointer to nil and remove the weak record in the deleted list
- And are referenced by weak Pointers or store reference counts in Sidetable
- If isa is optimized and the object is weakly referenced or the reference count is stored in the Sidetable, the clearDeallocating_slow function is called
- Enter the clearDeallocating_slow function, and you can see that weak_clear_NO_lock function is called in the function and the reference count is cleared
- The ISA of the object has not been optimized
Automatic release tank
Implementation principles of AutoReleasepool
- Each AutoreleasePoolPage object takes up 4096 bytes of memory, except for its internal member variables and the remaining space for the address of the AutoRelease object
- All memory in AutoreleasePoolPage is used to store the address of an AutoRelease object, except for the initial 56 bytes for storing member variables
- When an AutoreleasePoolPage is insufficient to store the address of an AutoRelease object, an AutoreleasePoolPage is created
- All AutoreleasePoolPage objects are connected together in a bidirectional linked list
How autoreleasepool works
- Calling the push method pushes a POOL_BOUNDARY onto the stack and returns its memory address
- The pop method is called with a POOL_BOUNDARY memory address, and a release message is sent from the last object pushed until the POOL_BOUNDARY is encountered
- Id *next refers to the next area that can hold the address of an AutoRelease object
Autoreleasepool nested
Runloop and Autorelease
- IOS registers two observers in the Runloop of the main thread
- 1 the Observer
- Objc_autoreleasePoolPush () is called when the kCFRunLoopEntry event is listened on
- A second Observer
- Objc_autoreleasePoolPop (), objc_autoreleasePoolPush()
- Objc_autoreleasePoolPop () is called after listening for the kCFRunLoopBeforeExit event
A circular reference
Circular reference type
- Self-circular reference
- Cross reference
- Multiloop reference
Common circular references
-
The agent
- Use weak type
-
Block
- Using __weak
-
NSTimer
-
You can use an intermediate object to solve the circular reference problem
-
Proxy does not implement any method called by target. Instead, it forwards messages to Target through message forwarding. In this way, target can execute any method called by timer
-
-
Macrocyclic reference
- Use weak type