探索Buff -- Objc源码中常见的宏

787 阅读2分钟

「这是我参与2022首次更文挑战的第2天,活动详情查看:2022首次更文挑战」。

BUFF加持,探索不止

1、__LP64__

  • 首先,LP64 是数据模型,不是Mac架构

  • LP64 中就是 long integerspointers64 bits

  • 如表:除了 LP64 之外,还有 LLP64ILP64SILP64ILP32 等数据模型

data models
Data modelshortintlonglong longpointer
LLP641632326464
LP641632646464
ILP641664646464
SILP646464646464
ILP321632326432

注意一点:
也有在64位处理器上使用ILP32数据模型,该数据模型减小了代码大小,也减小了包含指针的数据结构的大小,所以造成的结果就是地址空间会小很多(这里应该是指操作系统给应用进程分配的虚拟内存空间)。
对于某些嵌入式系统来说,ILP32 是一个不错的选择。已在Apple Watch Series 4之后使用。所以,在Objc源码中会看到这样的判断: (__ARM_ARCH_7K__ >= 2 || (__arm64__ && !__LP64__))

2、 __ARM_ARCH_7K__

// https://github.com/llvm/llvm-project/

// Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU
// happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__.
if (getTriple().isWatchABI())
    Builder.defineMacro("__ARM_ARCH_7K__", "2");

3、SUPPORT_INDEXED_ISA

记录完__ARM_ARCH_7K__ ,接着就该记录SUPPORT_INDEXED_ISA ,这个在探索OC底层类相关的源码时是常常见到的。

// field as an index into a class table.
// Note, keep this in sync with any .s files which also define it.
// Be sure to edit objc-abi.h as well.
#if __ARM_ARCH_7K__ >= 2 || (__arm64__ && !__LP64__)
#   define SUPPORT_INDEXED_ISA 1
#else
#   define SUPPORT_INDEXED_ISA 0
#endif
  • 判断是否为Watch设备
  • 根据if条件,在iOS 中即:
    • # define SUPPORT_INDEXED_ISA 0非Watch

注意一点:
正如开篇所记录,LP64 表示的是一种数据模型,arm64才是CPU架构。

4、SUPPORT_PACKED_ISA

// Define SUPPORT_PACKED_ISA=1 on platforms that store the class in the isa 
// field as a maskable pointer with other data around it.
#if (!__LP64__  ||  TARGET_OS_WIN32  ||  \
     (TARGET_OS_SIMULATOR && !TARGET_OS_MACCATALYST && !__arm64__))
#   define SUPPORT_PACKED_ISA 0
#else
#   define SUPPORT_PACKED_ISA 1
#endif
  • 判断是否支持isa优化
  • 根据if条件,在iOS 中即:
    • #define SUPPORT_PACKED_ISA 1支持优化

类de数据结构分析(总)中分析isa_t 数据结构时,其中的ISA_BITFIELD (isa.h) 就定义在SUPPORT_PACKED_ISA

5、TARGET_OS_MACCATALYST

Mac Catalyst 是苹果在19年WWDC上发布的,一个“一键式的操作”帮助开发者将iPad 应用移植到macOS上的服务。介绍说“只需要稍加优化就可以完美在mac上运行”。所以这个宏的意义就是针对这项服务的。

6、SUPPORT_NONPOINTER_ISA

// Define SUPPORT_NONPOINTER_ISA=1 on any platform that may store something
// in the isa field that is not a raw pointer.
#if !SUPPORT_INDEXED_ISA  &&  !SUPPORT_PACKED_ISA  
#   define SUPPORT_NONPOINTER_ISA 0
#else
#   define SUPPORT_NONPOINTER_ISA 1
#endif
  • 判断是否为纯指针isa
  • if条件,在iOSSUPPORT_INDEXED_ISA==0SUPPORT_PACKED_ISA ==1,即:
    • # define SUPPORT_NONPOINTER_ISA 1非纯指针isa