@@ -2364,6 +2364,69 @@ The current list of interior pointer SIL instructions are:
23642364(*) We still need to finish adding support for project_box, but all other
23652365interior pointers are guarded already.
23662366
2367+ Variable Lifetimes
2368+ ~~~~~~~~~~~~~~~~~~
2369+
2370+ In order for programmer intended lifetimes to be maintained under optimization,
2371+ the lifetimes of SIL values which correspond to named source-level values can
2372+ only be modified in limited ways. Generally, the behavior is that the lifetime
2373+ of a named source-level value cannot _observably_ end before the end of the
2374+ lexical scope in which that value is defined. Specifically, code motion may
2375+ not move the ends of these lifetimes across a **deinit barrier **.
2376+
2377+ A few sorts of SIL value have lifetimes that are constrained that way:
2378+
2379+ 1: `begin_borrow [lexical] `
2380+ 2: `move_value [lexical] `
2381+ 3: @owned function arguments
2382+ 4: `alloc_stack [lexical] `
2383+
2384+ That these three have constrained lifetimes is encoded in ValueBase::isLexical,
2385+ which should be checked before changing the lifetime of a value.
2386+
2387+ The reason that only @owned function arguments are constrained is that a
2388+ @guaranteed function argument is guaranteed by the function's caller to live for
2389+ the full duration of the function already. Optimization of the function alone
2390+ can't shorten it. When such a function is inlined into its caller, though, a
2391+ lexical borrow scope is added for each of its @guaranteed arguments, ensuring
2392+ that the lifetime of the corresponding source-level value is not shortened in a
2393+ way that doesn't respect deinit barriers.
2394+
2395+ Unlike the other sorts, `alloc_stack [lexical] ` isn't a SILValue. Instead, it
2396+ constrains the lifetime of an addressable variable. Since the constraint is
2397+ applied to the in-memory representation, no additional lexical SILValue is
2398+ required.
2399+
2400+ Deinit Barriers
2401+ ```````````````
2402+
2403+ Deinit barriers (see swift::isDeinitBarrier) are instructions which would be
2404+ affected by the side effects of deinitializers. To maintain the order of
2405+ effects that is visible to the programmer, destroys of lexical values cannot be
2406+ reordered with respect to them. There are three kinds:
2407+
2408+ 1. synchronization points (locks, memory barriers, syscalls, etc.)
2409+ 2. loads of weak or unowned values
2410+ 3. accesses of pointers
2411+
2412+ Examples:
2413+
2414+ 1. Given an instance of a class which owns a file handle and closes the file
2415+ handle on deinit, writing to the file handle and then deallocating the
2416+ instance would result in changes being written. If the destroy of the
2417+ instance were hoisted above the call to write to the file handle, an error
2418+ would be raised instead.
2419+ 2. Given an instance `c ` of a class `C ` which weakly references an instance `d `
2420+ of a second class `D `, if `d ` is referenced via a local variable `v `, then
2421+ loading that weak reference from `c ` within the variable scope should return
2422+ a non-nil reference to `d `. Hoisting the destroy of `v ` above the weak load
2423+ from `c `, however, would result in the destruction of `d ` before that load
2424+ and a nil weak reference to `D `.
2425+ 3. Given an instance of a class which owns a buffer and deallocates it on
2426+ deinitialization, accessing the pointer and then deallocating the instance
2427+ is defined behavior. Hoisting the destroy of the instance above the access
2428+ to the memory would result in accessing a freed pointer.
2429+
23672430Memory Lifetime
23682431~~~~~~~~~~~~~~~
23692432
0 commit comments