ISAの初期化
ISA構造
組合isa_t {
isa_t(){}
isa_t(uintptr_tを値):ビット(値){}
クラスCLS;
uintptr_tをビット。
定義(ISA_BITFIELD)の#if
構造体{
ISA_BITFIELD; // isa.hで定義されています
}。
#endifの
}。
したがってコンソーシアム、データ型ISA見られ、8つのバイトを占有します。それは特徴:意味、メモリを共有、または排他的な機能を持つものではない譲渡の他のメンバーにCLSの割り当て、。ISA_BITFIELDマクロ定義であり、それは次の構造を定義するビットフィールドであります
SUPPORT_PACKED_ISAの#if
// extra_rcはMSB-ほとんどのフィールドでなければなりません(それはキャリー/オーバーフローフラグと一致するように)
//非ポインターは、LSB(FIXMEまたはそれを取り除く)でなければなりません
// shiftclsは、実際のクラスポインタであろうと同じビットを占有しなければなりません
//ビット+ RC_ONEがextra_rc + 1と同等です
// RC_HALFはextra_rcの高いビット(その範囲のすなわち半分)であります
//将来の拡張:
// uintptr_tをfast_rr:1; //なし/ Rオーバーライド
// uintptr_tをロック:2; //アトミックプロパティのロック、@synch
// uintptr_tをextraBytes:1; //余分なバイトを割り当て
#もし__arm64__
#定義ISA_MASK 0x0000000ffffffff8ULL
#定義ISA_MAGIC_MASK 0x000003f000000001ULL
#定義ISA_MAGIC_VALUE 0x000001a000000001ULL
#ISA_BITFIELDを定義します\
uintptr_tを非ポインター:1; \
uintptr_tをhas_assoc:1; \
uintptr_tをhas_cxx_dtor:1; \
uintptr_tをshiftcls:33; / * MACH_VM_MAX_ADDRESS 0x1000000000 * / \
uintptr_tをマジック:6; \
uintptr_tをはweakly_referenced:1; \
uintptr_tを割り当て解除:1; \
uintptr_tをhas_sidetable_rc:1; \
uintptr_tをextra_rc:19
#定義RC_ONE(1ULL << 45)
#定義RC_HALF(1ULL << 18)
#elifの__x86_64__
#定義ISA_MASK 0x00007ffffffffff8ULL
#定義ISA_MAGIC_MASK 0x001f800000000001ULL
#定義ISA_MAGIC_VALUE 0x001d800000000001ULL
#ISA_BITFIELDを定義します\
uintptr_tを非ポインター:1; \
uintptr_tをhas_assoc:1; \
uintptr_tをhas_cxx_dtor:1; \
uintptr_tをshiftcls:44; / * MACH_VM_MAX_ADDRESS 0x7fffffe00000 * / \
uintptr_tをマジック:6; \
uintptr_tをはweakly_referenced:1; \
uintptr_tを割り当て解除:1; \
uintptr_tをhas_sidetable_rc:1; \
uintptr_tをextra_rc:8
#定義RC_ONE(1ULL << 56)
#定義RC_HALF(1ULL << 7)
# そうしないと
パックされたISAのための#エラー未知のアーキテクチャ
#endifの
// SUPPORT_PACKED_ISA
#endifの
SUPPORT_INDEXED_ISAの#if
__ARM_ARCH_7K__> = 2の場合#|| (__arm64__ &&!__ LP64__)
// armv7kまたはarm64_32
#定義ISA_INDEX_IS_NPI_BIT 0
#定義ISA_INDEX_IS_NPI_MASKは0x00000001
#定義ISA_INDEX_MASK 0x0001FFFC
#定義ISA_INDEX_SHIFT 2
#定義ISA_INDEX_BITS 15
#定義ISA_INDEX_COUNT(1 << ISA_INDEX_BITS)
#定義ISA_INDEX_MAGIC_MASK 0x001E0001
#定義ISA_INDEX_MAGIC_VALUE 0x001C0001
#ISA_BITFIELDを定義します\
uintptr_tを非ポインター:1; \
uintptr_tをhas_assoc:1; \
uintptr_tをindexcls:15; \
uintptr_tをマジック:4。\
uintptr_tをhas_cxx_dtor:1; \
uintptr_tをはweakly_referenced:1; \
uintptr_tを割り当て解除:1; \
uintptr_tをhas_sidetable_rc:1; \
uintptr_tをextra_rc:7
#定義RC_ONE(1ULL << 25)
#定義RC_HALF(1ULL << 6)
# そうしないと
インデックス付きISAのための#エラー未知のアーキテクチャ
#endifの
// SUPPORT_INDEXED_ISA
#endifの
ISAのarm64の引数は詳しく説明します:
非ポインター:純粋ISAポインタ、1:最適化0のISAポインタをオンにするかどうかを示すだけでなく、クラスオブジェクトのアドレスである、ISAは、クラス情報が含まれている、参照カウントは、オブジェクト
関連するオブジェクトフラグ0ない1本である:has_assocは
has_cxx_dtor。デストラクタ、行われるために必要なデストラクタロジック、そうでない場合ならば、オブジェクトがにObjCまたはC ++デストラクタを持っているかどうか、オブジェクトがより早く解放される
:shiftcls
値がクラスへのポインタを格納します。オープンポインタの最適化の場合、アーキテクチャarm64店のポインタへの33個のクラスがあります。
魔法:現在のオブジェクトまたはオブジェクトを決定するために、デバッガが本当に初期化の余地がweakly_referencedされていない:チーのオブジェクトがポイントにポイントであるか、ARCが弱いの変数を持っていたかどうかは、
何の弱参照がより早く解放することはできないオブジェクト。割り当て解除:フラグオブジェクトがメモリ解放されているかどうかを
has_sidetable_rcを:オブジェクト参照技術は可変貯蔵キャリー借りる必要次いで、10よりも大きい場合
extra_rcを:オブジェクト場合、例えば、実際の参照カウントは1だけデクリメントされたオブジェクトの参照カウントを示す場合参照カウントはその後、extra_rc 9 10です。参照カウントが10より大きい場合、次のようhas_sidetable_rcを使用する必要があります。
分析の伊佐ポイント
- オブジェクト・クラスに関連付けられた
LGPerson *物体= [LGPerson ALLOC] 。
ブリーフlldbコマンド
印刷情報記憶部4 X / 4GXにObjCにObjC。拡張:X / 6gxは、情報記憶部6を印刷することです。
P / TP / Tバイナリ印刷情報; P / O進情報を印刷; P / X進印刷情報; pは/印刷情報記憶部4、第1のオブジェクトプロパティは、ISAでなければならない小数情報を、印刷D、それはNSObjectのから継承されているので、
@interface NSObjectの<NSObjectの> {
#pragma打ち鳴らす診断プッシュ
#pragma打ち鳴らす診断無視「-Wobjc-インターフェース-アイバーズ」
クラスのISA OBJC_ISA_AVAILABILITY。
#pragma打ち鳴らす診断ポップ
}
object_getClass(オブジェクト)で、話題に戻り、関連情報を見つけます
クラスobject_getClass(IDのOBJ)
{
もし(OBJ)リターンobj-> getIsa();
他のリターンナシ。
}
objc_object :: getIsa()
{
(もし!isTaggedPointer())リターンISA();
uintptr_tをPTR =(uintptr_tを)この;
IF(isExtTaggedPointer()){
uintptr_tをロック=
(PTR >> _OBJC_TAG_EXT_SLOT_SHIFT)&_OBJC_TAG_EXT_SLOT_MASK。
戻りobjc_tag_ext_classes [スロット]。
} そうしないと {
uintptr_tをロック=
(PTR >> _OBJC_TAG_SLOT_SHIFT)&_OBJC_TAG_SLOT_MASK。
戻りobjc_tag_classes [スロット]。
}
}
インラインクラス
objc_object :: ISA()
{
アサート(isTaggedPointer()!)。
SUPPORT_INDEXED_ISAの#if
IF(isa.nonpointer){
uintptr_tをスロット= isa.indexcls。
リターンclassForIndex((符号なし)スロット)。
}
リターン(クラス)isa.bits。
#そうしないと
リターン(クラス)(isa.bits&ISA_MASK)。
#endifの
}
ソースの分析は、最後のクラスが返されるから(クラス)(isa.bits&ISA_MASK)の結果を見て、その後の検証を開始する、などの点ISAクラスを証明しており、以下のことができます。
分析対象番号メモリが存在します
私たちは、あなたがそれを確認し、今、より多く作成できるかどうか、クラスが行う、複数のオブジェクトを作成することができることを知っています:
クラスClass1 = [LGPersonクラス]。
クラスクラス2 = [LGPerson ALLOC]の.class。
クラスClass3に= object_getClass([LGPerson ALLOC])。
クラスCLASS4 = [LGPerson ALLOC]の.class。
NSLog(@ "\ n個のp%\ N%のp- \ nは%p型\ nは%P"、クラス1、クラス2、Class3に、CLASS4)。
出力は、
2020-02-1000:27:37.559203 + 0800001-オブジェクトISA [7942:604270]
0x100002400-
0x100002400-
0x100002400-
0x100002400
証明は専用メモリの内部で唯一、クラスを作成することができます
ISAウォーク&継承
上記の分析を通じて、クラスのISAに物体点から見て、その後、図ISAに従って分析を歩き続けることができます
虚线代表了isa的走位。实例对象->类->元类->根元类->根根元类(根元类本身)。
实线代表了继承关系。这里值得注意的就是根元类的父类是NSObject,NSObject父类是nil。
开始验证:
1.isa从对象指向类
XDPerson *person = [XDPerson alloc];
(lldb) x/4gx person
0x10185eac0: 0x001d8001000011a9 0x0000000000000000
0x10185ead0: 0x000000010185eba0 0x000000010185ede0
(lldb) p/x 0x001d8001000011a9 & 0x0000000ffffffff8
(long) $1 = 0x00000001000011a8
(lldb) po $1
XDPerson
2.isa从类指向元类
(lldb) x/4gx $1
0x1000011a8: 0x001d800100001181 0x00000001000011f8
0x1000011b8: 0x00000001003a1e50 0x0000000000000000
(lldb) p/x 0x001d800100001181 & 0x0000000ffffffff8
(long) $2 = 0x0000000100001180
(lldb) po $2
XDPerson
我们打印类XDPerson的内存信息,通过类的isa&ISA_MASK获取到了另外一个类的信息。即isa从类XDPerson又指向了类XDPerson(其实这个类是我们XDPerson的metaClass元类,它与第一步的XDPerson的内存地址并不同)。
3.isa从元类指向根元类
(lldb) x/4gx $2
0x100001180: 0x001d800100aff0f1 0x00000001000011d0
0x100001190: 0x0000000101e142b0 0x0000000100000007
(lldb) p/x 0x001d800100aff0f1 & 0x0000000ffffffff8
(long) $3 = 0x0000000100aff0f0
(lldb) po $3
NSObject
我们打印元类XDPerson的内存信息 通过元类的isa & ISA_MASK 获取到了另外一个元类类NSObject的信息。即isa从元类XDPerson又指向了元类NSObject。这里我们可以来打印NSObjcr.class来观察,元类NSObject的内存地址NSObjcr.class的内存地址并不同。
4.isa从根元类指向根根元类
(lldb) x/4gx $3
0x100aff0f0: 0x001d800100aff0f1 0x0000000100aff140
0x100aff100: 0x0000000101e146e0 0x0000000300000007
(lldb) p/x 0x001d800100aff0f1 & 0x0000000ffffffff8
(long) $4 = 0x0000000100aff0f0
(lldb) po $4
NSObject
这里补充一下几个概念
对象 是程序员根据类实例化出来的
类 是代码写出来的,内存中只有一份,是系统创建的
元类 是系统编译的,发现有了这么一个类 - 系统也同时创建了
方法 是编译阶段产生的