LJoy
LJoy

Reputation: 51

Where Singleton object is allocated?

I wanted to know where myClass objects allocated exactly so I drew allocation flow

class MyClass {
    static let shared = MyClass()
    private init() { }
}

let myClass = MyClass.shared 
  1. myClass constant is allocated in Stack

  2. myClass constant point to Heap where MyClass is allocated

  3. MyClass.shared static property point to MyClass() where allocated in Heap

Is this flow right? Am I misunderstood something?

data diagram

Upvotes: 1

Views: 807

Answers (1)

rob mayoff
rob mayoff

Reputation: 385870

  • Swift allocates storage for MyClass.shared in the data segment, initialized to nil. The data segment's layout and initial contents are defined by the executable file. Historically, the heap started immediately at the end of the data segment, but on modern 64-bit systems with address space layout randomization (ASLR), I don't know if that's still true.

  • Swift also allocates a swift_once_t in the data segment to record whether MyClass.shared has been initialized yet.

  • Swift generates a getter function for MyClass.shared in the code segment. The getter function uses the swift_once_t to initialize the storage of MyClass.shared the first time the getter is called. It looks approximately like this:

    var _storage_MyClass_shared: MyClass? = nil
    var _once_MyClass_shared: swift_once_t = .init() // essentially, false
    
    func _getter_MyClass_shared() -> MyClass {
        swift_once(&_once_MyClass_shared, {
            _storage_MyClass_shared = MyClass()
        })
        return _storage_MyClass_shared!
    }
    
  • The instance of MyClass is stored on the heap. It starts with a word containing the isa pointer (to the MyClass metadata), followed by a word containing (usually) reference counts, followed by storage for the object's instance variables. In your case, there are no instance variables, so there is no additional storage. The blue box labeled Myclass() in your diagram, and the arrow pointing to it, do not exist.

  • If myClass is at top-level (not inside a method or data type declaration), then it is also stored in the data segment along with another swift_once_t that tracks whether it's been initialized, and Swift generates a getter for it in the code segment.

  • If myClass is an instance variable of a data type, then it is stored as part of its containing object, which may be either on the stack or the heap (in the case of a struct, enum, or tuple) or always on the heap (in the case of a class or actor).

  • If myClass is a local variable in a function, then it is stored on the stack.

Upvotes: 2

Related Questions