实例与类的对比 - swift_0x03

接上篇:编译过程补充

语法分析 Parse --> 语义分析 Sema --> SILGen --> IRGen --> 汇编 --> MachO

网上找到一张图片:

Swift 编译过程

具体命令:

-dump—parse --> -dump—ast --> -emit-silgen --> -emit-sil --> -emit-ir

Swift 对象创建过程 —— allocating_init()

创建一个swift对象会调用类的__allocating_init()方法,然后调用私有方法_swift_allocObject_()方法

这个方法实现在 HeapObject.cpp 中:

static HeapObject *_swift_allocObject_(HeapMetadata const *metadata,
                                       size_t requiredSize,
                                       size_t requiredAlignmentMask) {
  assert(isAlignmentMask(requiredAlignmentMask));
  auto object = reinterpret_cast(
      swift_slowAlloc(requiredSize, requiredAlignmentMask));

  // NOTE: this relies on the C++17 guaranteed semantics of no null-pointer
  // check on the placement new allocator which we have observed on Windows,
  // Linux, and macOS.
  new (object) HeapObject(metadata);

  // If leak tracking is enabled, start tracking this object.
  SWIFT_LEAKS_START_TRACKING_OBJECT(object);

  SWIFT_RT_TRACK_INVOCATION(object, swift_allocObject);
  return object;
}

swift_slowAlloc()

首先使用 assert 检查了传递的参数的内存对齐规范,然后调用了 swift_slowAlloc(requiredSize, requiredAlignmentMask),方法如下,在Heap.cpp中

void *swift::swift_slowAlloc(size_t size, size_t alignMask) {
  void *p;
  // This check also forces "default" alignment to use AlignedAlloc.
  if (alignMask <= MALLOC_ALIGN_MASK) {
#if defined(__APPLE__)
    p = malloc_zone_malloc(DEFAULT_ZONE(), size);
#else
    p = malloc(size);
#endif
  } else {
    size_t alignment = (alignMask == ~(size_t(0)))
                           ? _swift_MinAllocationAlignment
                           : alignMask + 1;
    p = AlignedAlloc(size, alignment);
  }
  if (!p) swift::crash("Could not allocate memory.");
  return p;
}

这里看到了熟悉的 malloc(size),OC也是调用的这个。

HeapObject

然后回到_swift_allocObject_()方法,继续调用了

  new (object) HeapObject(metadata);

使用入参 metadata 调用 HeapObject 的初始化方法,创建了一个 HeapObject。

HeapObject 是一个结构体,声明在 HeapObject.h 文件中

/// The Swift heap-object header.
/// This must match RefCountedStructTy in IRGen.
struct HeapObject {
  /// This is always a valid pointer to a metadata object.
  HeapMetadata const *metadata;

  SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;

#ifndef __swift__
  HeapObject() = default;

// 初始化函数
  // Initialize a HeapObject header as appropriate for a newly-allocated object.
  constexpr HeapObject(HeapMetadata const *newMetadata) 
    : metadata(newMetadata)
    , refCounts(InlineRefCounts::Initialized)
  { }
  
  // Initialize a HeapObject header for an immortal object
  constexpr HeapObject(HeapMetadata const *newMetadata,
                       InlineRefCounts::Immortal_t immortal)
  : metadata(newMetadata)
  , refCounts(InlineRefCounts::Immortal)
  { }

#ifndef NDEBUG
  void dump() const LLVM_ATTRIBUTE_USED;
#endif

#endif // __swift__
};

可以看到成员变量:

  1. metadata指针
  2. SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS

所以一个 HeapObject 对象什么属性都不声明,就默认占用16字节的大小。

Swift 对象是一个 HeapObject,默认占用16字节。
OC 对象是一个结构体 objc_object,默认只有 isa 指针,占用8字节。

isa指针具体解释如下图,更多详情参考 footnote 第一个链接。


-w600

类结构

上面创建实例对象的方法有一个入参,叫做metadata,也叫元数据,这个就好像OC的class一样,类是创建实例对象的模板,就是这个metadata。

HeapMetadata const *metadata;

点击可以查看到 HeapMetadata 的定义:

using HeapMetadata = TargetHeapMetadata;

TargetHeapMetadata 类型的别名,继续看到 TargetHeapMetadata 结构体的定义:

struct TargetHeapMetadata : TargetMetadata {
  using HeaderType = TargetHeapMetadataHeader;

  TargetHeapMetadata() = default;
  constexpr TargetHeapMetadata(MetadataKind kind)
    : TargetMetadata(kind) {}
#if SWIFT_OBJC_INTEROP
  constexpr TargetHeapMetadata(TargetAnyClassMetadata *isa)
    : TargetMetadata(isa) {}
#endif
};

TargetHeapMetadata 继承自 TargetMetadata。

class的类型其实是TargetMetadata的 kind 传入 class 的 kind,具体的类是TargetAnyCkassMetadata,这里不是特别确定,但是看到这个类确实是如此的。

类相关的继承关系是这样的:

TargetClassMetadata → TargetAnyClassMetadata → TargetHeapMetadata → TargetMetadata

UML

image

如果 swift 的类继承了 OC 的类,那么这个 kind 就会指向 objc_class。

如上图,OC class 结构为:objc_class → objc_object。

objc_class 结构如下:

struct objc_class : objc_object {
    // Class ISA;
    Class superclass;
    cache_t cache;             // formerly cache pointer and vtable
    class_data_bits_t bits;    // class_rw_t * plus custom rr/alloc flags
    class_rw_t *data() const {
        return bits.data();
    }
}

这里先后存储的东西分四个:

  1. 继承来的 isa 结构的指针,占8字节
  2. superClass 的 Class 指针,占8字节
  3. cache类型,本篇跳过。
  4. class_data_bits_t类型的bits。

关于 class_data_bits_tclass_rw_tclass_ro_tclass_rwe_t,请参考Footnote第一个链接。

Footnote

OC Runtime 底层类结构2020最新

官方SIL语法文档

官方SIL编程手册

Swift进阶

Swift之源码编译的环境搭建和编译流程

你可能感兴趣的:(实例与类的对比 - swift_0x03)