前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >swift底层探索 01 - 类初始化&类结构swift底层探索 01 - 类初始化&类结构

swift底层探索 01 - 类初始化&类结构swift底层探索 01 - 类初始化&类结构

作者头像
用户8893176
发布2021-08-09 11:28:13
8440
发布2021-08-09 11:28:13
举报
文章被收录于专栏:小黑娃Henry

探索swift可以通过:源码调试Sil文件xcode断点调试这些方式来进行探索,除Sil文件这种方式其他的都会在本文中出现。OC底层探索01-找到底层探索的钥匙会有解释。

探索路径同样是参考oc的探索路径,先从类开始。

类初始化

1. 使用Xcodel断点调试
  • 创建一个简单的类,开启汇编断点
  • 1步骤就是__allocation_initswift对象初始化入口
  • 通过2步骤可以进入下一步(下断点,按住control+↓)
  • swift_allocObject是初始化第二步
  • 下断点,按住control+↓进入下一步
  • swift_slowAlloc是初始化第三步
  • 下断点,按住control+↓进入下一步
  • malloc_zone_malloc是初始化第四步,在这一步完成内存的分配,最终完成alloc步骤
2. 使用源码调试

现在通过源码调试来验证一下之前的论点。源码编译方式Swift-5.3.1 源码编译.

代码语言:javascript
复制
static HeapObject *_swift_allocObject_(HeapMetadata const *metadata,
                                       size_t requiredSize,
                                       size_t requiredAlignmentMask) {
  assert(isAlignmentMask(requiredAlignmentMask));
  //swift慢速创建流程
  auto object = reinterpret_cast<HeapObject *>(
      swift_slowAlloc(requiredSize, requiredAlignmentMask));
  //为创建好的内存赋值
  new (object) HeapObject(metadata);

  SWIFT_LEAKS_START_TRACKING_OBJECT(object);

  SWIFT_RT_TRACK_INVOCATION(object, swift_allocObject);

  return object;
}

void *swift::swift_slowAlloc(size_t size, size_t alignMask) {
  void *p;
  
  //一般使用 8字节对齐 
  //#  define MALLOC_ALIGN_MASK 15
  if (alignMask <= MALLOC_ALIGN_MASK) {
#if defined(__APPLE__)
    //apple的类会进入这里
    p = malloc_zone_malloc(DEFAULT_ZONE(), size);
#else
    p = malloc(size);
#endif
  } else {
  //大于16字节对齐的情况,比较少见
    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;
}
  • 根据源码也可以跟到具体的流程
  • alignMask <= MALLOC_ALIGN_MASK进入这个判断可以看出swift类一般使用的是8字节对齐
代码语言:javascript
复制
#define malloc_zone_malloc(zone,size) malloc(size)
  • malloc_zone_malloc只是一个宏定义,最终调用malloc
3. 初始化流程图

类结构 - HeapObject结构

1. 编译器断点
  • 在进行类创建,源码调试的时候发现swift的类结构是这样的。和oc比起来是有一些不同的。我们换种方式看看.
2. lldb
  • 相比于OC不同的是,除了第一位之外,还将引用计数当做第二个参数保存到对象中
3. 源码查看

swift对象继承自**HeapObject**

代码语言:javascript
复制
struct HeapObject {
  /// This is always a valid pointer to a metadata object.
  HeapMetadata const *metadata;

//#define SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS       \
  InlineRefCounts refCounts
  SWIFT_HEAPOBJECT_NON_OBJC_MEMBERS;
  
  ...
}
swift-类的结构图

HeapMetadata结构

如果说metaData相比于oc对象中的isa的而言的话,应该要包含isa,superclass,cache_t,date等类的信息。我们就来看看HeapMetadata结构都有些什么呢~

代码语言:javascript
复制
//相当于宏定义 
using HeapMetadata = TargetHeapMetadata<InProcess>

//template 模板类
struct TargetHeapMetadata : TargetMetadata<InProcess>{
    。。。
}

struct TargetMetadata<InProcess>{
    StoredPointer Kind; //用来区分是什么类型的原数据 

//一个相关的方法
    getObjCClassObject() const {
    return reinterpret_cast<Class>(
      const_cast<TargetClassMetadata<InProcess>*>(
        getClassObject()));
  }
}
  • TargetHeapMetadata是一个模板类,想要了解内部结构需要继续向下查看
  • <InProcess>类似于泛型,限制泛型的具体类型
  • 没有看到其他相关定义,只能借助其他方式来查看getClassObject
借助getClassObject方法查看HeapMetadata结构
代码语言:javascript
复制
//获取类对象
  Metadata::getClassObject() const {
    switch (getKind()) {
    case MetadataKind::Class: {
      return static_cast<const ClassMetadata *>(this);
    }
    //如果是类,指针强转为ClassMetadata
    case MetadataKind::ObjCClassWrapper: {
      auto wrapper = static_cast<const ObjCClassWrapperMetadata *>(this);
      return wrapper->Class;
    }
      return nullptr;
    }
  }
  • 我们发现将当前指针强转为ClassMetadata。指针可以强转则表示内部结构是相同的,我们可以转换角度去查看ClassMetadata.
ClassMetadata
代码语言:javascript
复制
using ClassMetadata = TargetClassMetadata<InProcess>;
struct TargetClassMetadata : TargetAnyClassMetadata<Runtime> {
    ClassFlags Flags;
    uint32_t InstanceAddressPoint;
    uint32_t InstanceSize;
    ...
}

struct TargetAnyClassMetadata : TargetHeapMetadata
{
  ConstTargetMetadataPointer  Superclass;
  TargetPointer CacheData[2];
  StoredSize Data;
  ...
}
元类结构图

swift类结构.png

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/12/11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 类初始化
    • 1. 使用Xcodel断点调试
      • 2. 使用源码调试
        • 3. 初始化流程图
        • 类结构 - HeapObject结构
          • 1. 编译器断点
            • 2. lldb
              • 3. 源码查看
                • swift-类的结构图
                • HeapMetadata结构
                  • 借助getClassObject方法查看HeapMetadata结构
                    • ClassMetadata
                      • 元类结构图
                      领券
                      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档