@@ -2364,6 +2364,69 @@ The current list of interior pointer SIL instructions are:
2364
2364
(*) We still need to finish adding support for project_box, but all other
2365
2365
interior pointers are guarded already.
2366
2366
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
+
2367
2430
Memory Lifetime
2368
2431
~~~~~~~~~~~~~~~
2369
2432
0 commit comments