OCのisaポインタにはどのような情報が格納されていますか?

3497 ワード

OC内のすべてのインスタンスオブジェクト、クラスオブジェクト、およびメタクラスオブジェクトには、isaというメンバー変数があり、通常はisa と呼ばれ、ポインタである以上、そこに格納されているのはアドレスであるべきである.従来の32 システムでは、isaは確かに格納されたアドレスであり、インスタンスオブジェクトのisaは対応するクラスオブジェクトのアドレスを格納し、クラスオブジェクトのisaは対応するメタオブジェクトのアドレスを格納し、メタオブジェクトのisaはルートメタオブジェクトのアドレスを格納していた.
しかし、現在の64ビットシステム(arm 64アーキテクチャ)では、アップルはisaを最適化し、1つのアドレスのほかに多くの情報を格納している.1つのポインタは8バイト、すなわち64ビットを占め、アップルはそのうちの33 だけでアドレスを格納し、残りの31ビットは他の情報を格納するために使用される.次に、arm64アーキテクチャにおけるisaの定義を見てみましょう.
#   define ISA_MASK        0x0000000ffffffff8ULL
#   define ISA_MAGIC_MASK  0x000003f000000001ULL
#   define ISA_MAGIC_VALUE 0x000001a000000001ULL
#   define ISA_BITFIELD                                                      \
      uintptr_t nonpointer        : 1;                                       \
      uintptr_t has_assoc         : 1;                                       \
      uintptr_t has_cxx_dtor      : 1;                                       \
      uintptr_t shiftcls          : 33; /*MACH_VM_MAX_ADDRESS 0x1000000000*/ \
      uintptr_t magic             : 6;                                       \
      uintptr_t weakly_referenced : 1;                                       \
      uintptr_t deallocating      : 1;                                       \
      uintptr_t has_sidetable_rc  : 1;                                       \
      uintptr_t extra_rc          : 19
#   define RC_ONE   (1ULL<<45)
#   define RC_HALF  (1ULL<<18)

上記の情報で定義されたISA_MASKのような定数は、isaを操作する過程でプログラムが使用するものであり、例えば、isaISA_MASKをビットと演算isa & ISA_MASKでisaに格納されたアドレス値を得ることができる.uintptr_tのデータに注目します.
  • nonpointer:(isaの0位(isaの一番後ろの方)、合計1位).0はこのisaがアドレス値のみを格納していることを示し、1はこれが最適化されたisaであることを示している.
  • has_assoc:(isaの1位、合計1位).このオブジェクトが関連オブジェクトかどうかを記録し、なければ解放が速くなります.
  • has_cxx_dtor:(isaの2位、合計1位).c++の構造関数があるかどうかを記録し、なければ解放が早い.
  • shiftcls:(isaの3-35位、計33位).クラスオブジェクトまたはメタオブジェクトのアドレス値を記録します.
  • magic:(isaの36-41ビット目、合計6ビット)は、デバッグ時にオブジェクトの初期化が完了したかどうかを判別するために使用されます.
  • weakly_referenced:(isaの42位、合計1位)は、そのオブジェクトが弱い参照または弱い参照を受けたことがあるかどうかを記録するために使用され、弱い参照を受けていないオブジェクトはより速く解放されることができる.
  • deallocating:(isaの43番目、合計1ビット)は、オブジェクトがメモリを解放しているかどうかを示します.
  • has_sidetable_rc:(isaの44番目、合計1ビット)は、拡張された参照カウントがあるかどうかをマークするために使用されます.1つのオブジェクトの参照カウントが比較的少ない場合、その参照カウントはisaに記録され、参照カウントがある値より大きい場合、sideTableが参照カウントの格納を支援する.
  • extra_rc:(isaの45-63ビット目、合計19ビット)は、そのオブジェクトの参照カウント値-1(例えば、参照カウントが5であればここでは4)を記録するために使用される.ここでは合計19ビットであり、参照カウントが大きい場合、19ビットが残らない場合はsideTableを用いて記憶を支援する.ルールは、19ビットが満杯になると、19ビットの半分(すなわち、上記で定義したRC_HALF)がsideTableに格納され、このとき参照カウントが+1になるとextra_rcに加算され、extra_rcが満杯になるとRC_HALFの大きさを出し続けてsideTableに格納される.参照カウントが減少すると、extra_rcの値が0に減少すると、sideTableからRC_HALFのサイズが取り出されてextra_rcに入る.以上説明したように、参照カウントは、extra_rcを直接操作することなく、増加または減少することがsideTableで行われる.これは、sideTableにスピンロックがあり、参照カウントの増加および減少操作が非常に頻繁であり、sideTableを直接操作すると性能に非常に影響を及ぼすため、sideTableへのアクセスを最小限に抑えるように設計されている.