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 oneThe Hash table.
  • The Hash tableThe time complexity of search isO(1).
  • throughAddress of the objectThe Hash tablethecounttakedieGets the target value subscript index.

Reference counter table

  • The reference count table is passedThe Hash tableTo achieve.
  • The Hash tableThe 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 theobject, look for toA weak reference tableTo extractWeakly referenced array.
  • Go through all of themWeak reference pointerAnd 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

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