Swift底层原理-属性

2022-12-08  本文已影响0人  祀梦_

Swift底层原理-属性

存储属性

class Test {
    let a: Int = 10
    var b: Int = 0
}
class Test {
  @_hasStorage @_hasInitialValue final let a: Int { get }
  @_hasStorage @_hasInitialValue var b: Int { get set }
  @objc deinit
  init()
}

计算属性

class Test {
    var a: Int = 0
    var b: Int {
        set {
            self.a = newValue
        }
        get {
            return 10
        }
    }
}

let test = Test()
test.b = 20

sil文件中声明

class Test {
  @_hasStorage @_hasInitialValue var a: Int { get set }
  var b: Int { get set }
  @objc deinit
  init()
}

getter/setter实现

// Test.b.setter
sil hidden [ossa] @$s4main4TestC1bSivs : $@convention(method) (Int, @guaranteed Test) -> () {
// %0 "newValue"                                  // users: %5, %2
// %1 "self"                                      // users: %5, %4, %3
bb0(%0 : $Int, %1 : @guaranteed $Test):
  debug_value %0 : $Int, let, name "newValue", argno 1, implicit // id: %2
  debug_value %1 : $Test, let, name "self", argno 2, implicit // id: %3
  %4 = class_method %1 : $Test, #Test.a!setter : (Test) -> (Int) -> (), $@convention(method) (Int, @guaranteed Test) -> () // user: %5
  %5 = apply %4(%0, %1) : $@convention(method) (Int, @guaranteed Test) -> ()
  %6 = tuple ()                                   // user: %7
  return %6 : $()                                 // id: %7
} // end sil function '$s4main4TestC1bSivs'
// Test.b.getter
sil hidden [ossa] @$s4main4TestC1bSivg : $@convention(method) (@guaranteed Test) -> Int {
// %0 "self"                                      // user: %1
bb0(%0 : @guaranteed $Test):
  debug_value %0 : $Test, let, name "self", argno 1, implicit // id: %1
  %2 = integer_literal $Builtin.IntLiteral, 10    // user: %5
  %3 = metatype $@thin Int.Type                   // user: %5
  // function_ref Int.init(_builtinIntegerLiteral:)
  %4 = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int // user: %5
  %5 = apply %4(%2, %3) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int // user: %6
  return %5 : $Int                                // id: %6
} // end sil function '$s4main4TestC1bSivg'

延迟属性

class Test {
    lazy var a: Int = 20
}
class Test {
  lazy var a: Int { get set }
  @_hasStorage @_hasInitialValue final var $__lazy_storage_$_a: Int? { get set }
  @objc deinit
  init()
}
// Test.a.getter
sil hidden [lazy_getter] [noinline] [ossa] @$s4main4TestC1aSivg : $@convention(method) (@guaranteed Test) -> Int {
// %0 "self"                                      // users: %16, %2, %1
bb0(%0 : @guaranteed $Test):
  debug_value %0 : $Test, let, name "self", argno 1, implicit // id: %1
  %2 = ref_element_addr %0 : $Test, #Test.$__lazy_storage_$_a // user: %3
  %3 = begin_access [read] [dynamic] %2 : $*Optional<Int> // users: %5, %4
  %4 = load [trivial] %3 : $*Optional<Int>        // user: %6
  end_access %3 : $*Optional<Int>                 // id: %5
  switch_enum %4 : $Optional<Int>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2 // id: %6

// %7                                             // users: %9, %8
bb1(%7 : $Int):                                   // Preds: bb0
  debug_value %7 : $Int, let, name "tmp1", implicit // id: %8
  br bb3(%7 : $Int)                               // id: %9

bb2:                                              // Preds: bb0
  %10 = integer_literal $Builtin.IntLiteral, 20   // user: %13
  %11 = metatype $@thin Int.Type                  // user: %13
  // function_ref Int.init(_builtinIntegerLiteral:)
  %12 = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int // user: %13
  %13 = apply %12(%10, %11) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int // users: %20, %15, %14
  debug_value %13 : $Int, let, name "tmp2", implicit // id: %14
  %15 = enum $Optional<Int>, #Optional.some!enumelt, %13 : $Int // user: %18
  %16 = ref_element_addr %0 : $Test, #Test.$__lazy_storage_$_a // user: %17
  %17 = begin_access [modify] [dynamic] %16 : $*Optional<Int> // users: %19, %18
  assign %15 to %17 : $*Optional<Int>             // id: %18
  end_access %17 : $*Optional<Int>                // id: %19
  br bb3(%13 : $Int)                              // id: %20

// %21                                            // user: %22
bb3(%21 : $Int):                                  // Preds: bb2 bb1
  return %21 : $Int                               // id: %22
} // end sil function '$s4main4TestC1aSivg'
switch_enum %4 : $Optional<Int>, case #Optional.some!enumelt: bb1, case #Optional.none!enumelt: bb2 // id: %6
// function_ref Int.init(_builtinIntegerLiteral:)
  %12 = function_ref @$sSi22_builtinIntegerLiteralSiBI_tcfC : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int // user: %13
  %13 = apply %12(%10, %11) : $@convention(method) (Builtin.IntLiteral, @thin Int.Type) -> Int // users: %20, %15, %14

属性观察器

class Test {
    var a: Int = 10 {
        willSet {
            print("new value = \(newValue)")
        }
        didSet {
            print("old value = \(oldValue)")
        }
    }
}
// Test.a.setter
sil hidden [ossa] @$s4main4TestC1aSivs : $@convention(method) (Int, @guaranteed Test) -> () {
// %0 "value"                                     // users: %13, %10, %2
// %1 "self"                                      // users: %16, %11, %10, %4, %3
bb0(%0 : $Int, %1 : @guaranteed $Test):
  debug_value %0 : $Int, let, name "value", argno 1, implicit // id: %2
  debug_value %1 : $Test, let, name "self", argno 2, implicit // id: %3
  %4 = ref_element_addr %1 : $Test, #Test.a       // user: %5
  %5 = begin_access [read] [dynamic] %4 : $*Int   // users: %7, %6
  %6 = load [trivial] %5 : $*Int                  // users: %16, %8
  end_access %5 : $*Int                           // id: %7
  debug_value %6 : $Int, let, name "tmp", implicit // id: %8
  // function_ref Test.a.willset
  %9 = function_ref @$s4main4TestC1aSivw : $@convention(method) (Int, @guaranteed Test) -> () // user: %10
  %10 = apply %9(%0, %1) : $@convention(method) (Int, @guaranteed Test) -> ()
  %11 = ref_element_addr %1 : $Test, #Test.a      // user: %12
  %12 = begin_access [modify] [dynamic] %11 : $*Int // users: %14, %13
  assign %0 to %12 : $*Int                        // id: %13
  end_access %12 : $*Int                          // id: %14
  // function_ref Test.a.didset
  %15 = function_ref @$s4main4TestC1aSivW : $@convention(method) (Int, @guaranteed Test) -> () // user: %16
  %16 = apply %15(%6, %1) : $@convention(method) (Int, @guaranteed Test) -> ()
  %17 = tuple ()                                  // user: %18
  return %17 : $()                                // id: %18
} // end sil function '$s4main4TestC1aSivs'
// function_ref Test.a.willset
%9 = function_ref @$s4main4TestC1aSivw : $@convention(method) (Int, @guaranteed Test) -> () // user: %10
%10 = apply %9(%0, %1) : $@convention(method) (Int, @guaranteed Test) -> ()
// function_ref Test.a.didset
%15 = function_ref @$s4main4TestC1aSivW : $@convention(method) (Int, @guaranteed Test) -> () // user: %16
%16 = apply %15(%6, %1) : $@convention(method) (Int, @guaranteed Test) -> ()

类型属性

class Test {
    static var a: Int = 10
}
class Test {
  @_hasStorage @_hasInitialValue static var a: Int { get set }
  @objc deinit
  init()
}

// one-time initialization token for a
sil_global private @$s4main4TestC1a_Wz : $Builtin.Word

// static Test.a
sil_global hidden @$s4main4TestC1aSivpZ : $Int
// Test.a.unsafeMutableAddressor
sil hidden [global_init] [ossa] @$s4main4TestC1aSivau : $@convention(thin) () -> Builtin.RawPointer {
bb0:
  %0 = global_addr @$s4main4TestC1a_Wz : $*Builtin.Word // user: %1
  %1 = address_to_pointer %0 : $*Builtin.Word to $Builtin.RawPointer // user: %3
  // function_ref one-time initialization function for a
  %2 = function_ref @$s4main4TestC1a_WZ : $@convention(c) () -> () // user: %3
  %3 = builtin "once"(%1 : $Builtin.RawPointer, %2 : $@convention(c) () -> ()) : $()
  %4 = global_addr @$s4main4TestC1aSivpZ : $*Int  // user: %5
  %5 = address_to_pointer %4 : $*Int to $Builtin.RawPointer // user: %6
  return %5 : $Builtin.RawPointer                 // id: %6
} // end sil function '$s4main4TestC1aSivau'
void swift::swift_once(swift_once_t *predicate, void (*fn)(void *),
                       void *context) {
#ifdef SWIFT_STDLIB_SINGLE_THREADED_RUNTIME
  if (! *predicate) {
    *predicate = true;
    fn(context);
  }
#elif 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 Test {
    static let share: Test = Test();
    
    private init() {
        
    }
}
上一篇 下一篇

猜你喜欢

热点阅读