Do value types get allocated in the heap in these cases?

Bird's-eye view approximation:

class Foo {
  let a: Int
  var b: Int
}

Here both a and b are allocated inline within the storage allocated for the class instance, e.g. a would be at offset 16, b at offset 24 of that storage and the overall instance size would be 32. Typically that would be allocated on heap unless compiler could prove that heap allocation is not needed.

enum Globals {
  static var someMutableSharedState = 42
  static let someImmutableSharedState = 24
}

These will be allocated in writeable and read-only data segments correspondingly (special areas of heap). The latter could in theory be allocated in the code segment or even not be allocated at all, if compiler decides to use 24 literal instead. Could well depend upon the constant in question, if it's small like 0 and 1 that's one scenario, if it's a big value like 0x1122334455667788 that's another scenario.

This is very approximate, and if you need to know exactly what your version of compiler is doing for your target environment - check the generated code or check the actual address in runtime with something like this:

func isStackMemory(_ ptr: UnsafeRawPointer) -> Bool {
    let stackBase = pthread_get_stackaddr_np(pthread_self())
    let stackSize = pthread_get_stacksize_np(pthread_self())
    return ptr <= stackBase && ptr >= stackBase - stackSize
}

Bear in mind that the presence of the extra check might have effect on the code being generated (like in quantum mechanics), so it's worth checking the generated code still or check the address in debugger without having the check in your actual code.

8 Likes