Swift类、对象、属性

2020-12-11  本文已影响0人  浪的出名

Swift编译简介

SIL介绍

SIL分析

class XQTeacher {
    var age:Int = 18
    var name:String = "xq"
}

var t = XQTeacher()
// main
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
  alloc_global @$s4main1tAA9XQTeacherCvp          // id: %2
  %3 = global_addr @$s4main1tAA9XQTeacherCvp : $*XQTeacher // user: %7
  %4 = metatype $@thick XQTeacher.Type            // user: %6
  // function_ref XQTeacher.__allocating_init()
  %5 = function_ref @$s4main9XQTeacherCACycfC : $@convention(method) (@thick XQTeacher.Type) -> @owned XQTeacher // user: %6
  %6 = apply %5(%4) : $@convention(method) (@thick XQTeacher.Type) -> @owned XQTeacher // user: %7
  store %6 to %3 : $*XQTeacher                    // id: %7
  %8 = integer_literal $Builtin.Int32, 0          // user: %9
  %9 = struct $Int32 (%8 : $Builtin.Int32)        // user: %10
  return %9 : $Int32                              // id: %10
} // end sil function 'main'
// XQTeacher.__allocating_init()
sil hidden [exact_self_class] @$s4main9XQTeacherCACycfC : $@convention(method) (@thick XQTeacher.Type) -> @owned XQTeacher {
// %0 "$metatype"
bb0(%0 : $@thick XQTeacher.Type):
  %1 = alloc_ref $XQTeacher                       // user: %3
  // function_ref XQTeacher.init()
  %2 = function_ref @$s4main9XQTeacherCACycfc : $@convention(method) (@owned XQTeacher) -> @owned XQTeacher // user: %3
  %3 = apply %2(%1) : $@convention(method) (@owned XQTeacher) -> @owned XQTeacher // user: %4
  return %3 : $XQTeacher                          // id: %4
} // end sil function '$s4main9XQTeacherCACycfC'

通过符号断点调试

源码调试

swift_allocObject

static HeapObject *_swift_allocObject_(HeapMetadata const *metadata,
                                       size_t requiredSize,
                                       size_t requiredAlignmentMask) {
  assert(isAlignmentMask(requiredAlignmentMask));
  auto object = reinterpret_cast<HeapObject *>(
      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;
}
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;
}
struct HeapObject {
  /// This is always a valid pointer to a metadata object.
  HeapMetadata const *metadata;
  // InlineRefCounts refCounts
  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)
  { }
  ......
}
using HeapMetadata = TargetHeapMetadata<InProcess>;
struct TargetHeapMetadata : TargetMetadata<Runtime> {
  using HeaderType = TargetHeapMetadataHeader<Runtime>;

  TargetHeapMetadata() = default;
  constexpr TargetHeapMetadata(MetadataKind kind)
    : TargetMetadata<Runtime>(kind) {}
#if SWIFT_OBJC_INTEROP
  constexpr TargetHeapMetadata(TargetAnyClassMetadata<Runtime> *isa)
    : TargetMetadata<Runtime>(isa) {}
#endif
};
struct swift_class_t: NSObject{
    void *kind;//相当于OC中的isa,kind的实际类型是unsigned long
    void *superClass;
    void *cacheData;
    void *data;
    uint32_t flags; //4字节
    uint32_t instanceAddressOffset;//4字节
    uint32_t instanceSize;//4字节
    uint16_t instanceAlignMask;//2字节
    uint16_t reserved;//2字节
    
    uint32_t classSize;//4字节
    uint32_t classAddressOffset;//4字节
    void *description;
    ...
}

Swift属性

存储属性

class XQTeacher {
    var age:Int = 18
    var name:String = "xq"
}
class XQTeacher {
  @_hasStorage @_hasInitialValue var age: Int { get set }
  @_hasStorage @_hasInitialValue var name: String { get set }
  @objc deinit
  init()
}

计算属性

class Square {
    var width:Double = 10
    var area:Double {
        get {
            Double(width * width)
        }
        set {
           width = sqrt(newValue)
        }
    }
}
print(class_getInstanceSize(Square.self))
class Square {
  @_hasStorage @_hasInitialValue var width: Double { get set }
  var area: Double { get set }
  @objc deinit
  init()
}

属性观察者

class XQTeacher {
    var name:String = "xq" {
        willSet {
            print("newValue:\(newValue)")
        }
        didSet {
            print("oldValue:\(oldValue)")
        }
    }
}
var t = XQTeacher()
t.name = "dp"
newValue:dp
oldValue:xq
class XQTeacher {
    var name:String = "xq" {
        willSet {
            print("newValue:\(newValue)")
        }
        didSet {
            print("oldValue:\(oldValue)")
        }
    }
    init() {
        self.name = "test"
    }
}
var t = XQTeacher()
class XQTeacher {
    var name:String = "xq" {
        willSet {
            print("newValue:\(newValue)")
        }
        didSet {
            print("oldValue:\(oldValue)")
        }
    }
}
class XQSpecialTeacher: XQTeacher {
    override var name: String {
        willSet {
            print("newValue:\(newValue)")
        }
        didSet {
            print("oldValue:\(oldValue)")
        }
    }
}
class XQTeacher {
    var age:Int = 18
    
    var age2:Int {
        get {
            return age
        }
        set {
            age = newValue
        }
    }
}

class XQSpecialTeacher: XQTeacher {
    override var age2: Int {
        willSet {
            print("override newValue:\(newValue)")
        }
        didSet {
            print("override oldValue:\(oldValue)")
        }
    }
}
class XQTeacher {
    var age:Int = 18 {
        willSet {
            print("newValue:\(newValue)")
        }
        didSet {
            print("oldValue:\(oldValue)")
        }
    }
    
    var age2:Int {
        get {
            return age
        }
        set {
            age = newValue
        }
    }
}

class XQSpecialTeacher: XQTeacher {
    override var age: Int {
        willSet {
            print("override newValue:\(newValue)")
        }
        didSet {
            print("override oldValue:\(oldValue)")
        }
    }
}
override newValue:99
newValue:99
oldValue:18
override oldValue:18
class XQSpecialTeacher: XQTeacher {
    override var age: Int {
        willSet {
            print("override newValue:\(newValue)")
        }
        didSet {
            print("override oldValue:\(oldValue)")
        }
    }
    override init() {
        super.init()
        self.age = 66
    }
}

延迟存储属性

class XQTeacher {
   lazy var age:Int = 18
}

类型属性

class XQTeacher {
    static var age : Int = 18
}
var t = XQTeacher()
XQTeacher.age = 20
// static XQTeacher.age
sil_global hidden @$s4main9XQTeacherC3ageSivpZ : $Int
// XQTeacher.age.unsafeMutableAddressor
sil hidden [global_init] @$s4main9XQTeacherC3ageSivau : $@convention(thin) () -> Builtin.RawPointer {
bb0:
  %0 = global_addr @globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_token0 : $*Builtin.Word // user: %1
  %1 = address_to_pointer %0 : $*Builtin.Word to $Builtin.RawPointer // user: %3
  // function_ref globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_func0
  %2 = function_ref @globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_func0 : $@convention(c) () -> () // user: %3
  %3 = builtin "once"(%1 : $Builtin.RawPointer, %2 : $@convention(c) () -> ()) : $()
  %4 = global_addr @$s4main9XQTeacherC3ageSivpZ : $*Int // user: %5
  %5 = address_to_pointer %4 : $*Int to $Builtin.RawPointer // user: %6
  return %5 : $Builtin.RawPointer                 // id: %6
} // end sil function '$s4main9XQTeacherC3ageSivau'
// globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_func0
sil private @globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_func0 : $@convention(c) () -> () {
bb0:
  alloc_global @$s4main9XQTeacherC3ageSivpZ       // id: %0 
  %1 = global_addr @$s4main9XQTeacherC3ageSivpZ : $*Int // user: %4 获取到age的地址
  %2 = integer_literal $Builtin.Int64, 18         // user: %3  初始化的值18
  %3 = struct $Int (%2 : $Builtin.Int64)          // user: %4
  store %3 to %1 : $*Int                          // id: %4  将%3的值放到地址中
  %5 = tuple ()                                   // user: %6
  return %5 : $()                                 // id: %6
} // end sil function 'globalinit_029_12232F587A4C5CD8B1EEDF696793B2FC_func0'
/// Runs the given function with the given context argument exactly once.
/// The predicate argument must point to a global or static variable of static
/// extent of type swift_once_t.
void swift::swift_once(swift_once_t *predicate, void (*fn)(void *),
                       void *context) {
#if defined(__APPLE__)
  dispatch_once_f(predicate, context, fn);
#elif defined(__CYGWIN__)
  _swift_once_f(predicate, context, fn);
#else
  std::call_once(*predicate, [fn, context]() { fn(context); });
#endif
}

实现单列

class XQTeacher {
    static let sharedInstance = XQTeacher()
    
    private init() {
        
    }
}
var t = XQTeacher.sharedInstance
上一篇 下一篇

猜你喜欢

热点阅读