@@ -2107,6 +2107,94 @@ make the use of such types more convenient; it does not shift the
2107
2107
ultimate responsibility for assuring the safety of unsafe
2108
2108
language/library features away from the user.
2109
2109
2110
+ Copy-on-Write Representation
2111
+ ----------------------------
2112
+
2113
+ Copy-on-Write (COW) data structures are implemented by a reference to an object
2114
+ which is copied on mutation in case it's not uniquely referenced.
2115
+
2116
+ A COW mutation sequence in SIL typically looks like::
2117
+
2118
+ (%uniq, %buffer) = begin_cow_mutation %immutable_buffer : $BufferClass
2119
+ cond_br %uniq, bb_uniq, bb_not_unique
2120
+ bb_uniq:
2121
+ br bb_mutate(%buffer : $BufferClass)
2122
+ bb_not_unique:
2123
+ %copied_buffer = apply %copy_buffer_function(%buffer) : ...
2124
+ br bb_mutate(%copied_buffer : $BufferClass)
2125
+ bb_mutate(%mutable_buffer : $BufferClass):
2126
+ %field = ref_element_addr %mutable_buffer : $BufferClass, #BufferClass.Field
2127
+ store %value to %field : $ValueType
2128
+ %new_immutable_buffer = end_cow_mutation %buffer : $BufferClass
2129
+
2130
+ Loading from a COW data structure looks like::
2131
+
2132
+ %field1 = ref_element_addr [immutable] %immutable_buffer : $BufferClass, #BufferClass.Field
2133
+ %value1 = load %field1 : $*FieldType
2134
+ ...
2135
+ %field2 = ref_element_addr [immutable] %immutable_buffer : $BufferClass, #BufferClass.Field
2136
+ %value2 = load %field2 : $*FieldType
2137
+
2138
+ The ``immutable `` attribute means that loading values from ``ref_element_addr ``
2139
+ and ``ref_tail_addr `` instructions, which have the *same * operand, are
2140
+ equivalent.
2141
+ In other words, it's guaranteed that a buffer's properties are not mutated
2142
+ between two ``ref_element/tail_addr [immutable] `` as long as they have the
2143
+ same buffer reference as operand.
2144
+ This is even true if e.g. the buffer 'escapes' to an unknown function.
2145
+
2146
+
2147
+ In the example above, ``%value2 `` is equal to ``%value1 `` because the operand
2148
+ of both ``ref_element_addr `` instructions is the same ``%immutable_buffer ``.
2149
+ Conceptually, the content of a COW buffer object can be seen as part of
2150
+ the same *static * (immutable) SSA value as the buffer reference.
2151
+
2152
+ The lifetime of a COW value is strictly separated into *mutable * and
2153
+ *immutable * regions by ``begin_cow_mutation `` and
2154
+ ``end_cow_mutation `` instructions::
2155
+
2156
+ %b1 = alloc_ref $BufferClass
2157
+ // The buffer %b1 is mutable
2158
+ %b2 = end_cow_mutation %b1 : $BufferClass
2159
+ // The buffer %b2 is immutable
2160
+ (%u1, %b3) = begin_cow_mutation %b1 : $BufferClass
2161
+ // The buffer %b3 is mutable
2162
+ %b4 = end_cow_mutation %b3 : $BufferClass
2163
+ // The buffer %b4 is immutable
2164
+ ...
2165
+
2166
+ Both, ``begin_cow_mutation `` and ``end_cow_mutation ``, consume their operand
2167
+ and return the new buffer as an *owned * value.
2168
+ The ``begin_cow_mutation `` will compile down to a uniqueness check and
2169
+ ``end_cow_mutation `` will compile to a no-op.
2170
+
2171
+ Although the physical pointer value of the returned buffer reference is the
2172
+ same as the operand, it's important to generate a *new * buffer reference in
2173
+ SIL. It prevents the optimizer from moving buffer accesses from a *mutable * into
2174
+ a *immutable * region and vice versa.
2175
+
2176
+ Because the buffer *content * is conceptually part of the
2177
+ buffer *reference * SSA value, there must be a new buffer reference every time
2178
+ the buffer content is mutated.
2179
+
2180
+ To illustrate this, let's look at an example, where a COW value is mutated in
2181
+ a loop. As with a scalar SSA value, also mutating a COW buffer will enforce a
2182
+ phi-argument in the loop header block (for simplicity the code for copying a
2183
+ non-unique buffer is not shown)::
2184
+
2185
+ header_block(%b_phi : $BufferClass):
2186
+ (%u, %b_mutate) = begin_cow_mutation %b_phi : $BufferClass
2187
+ // Store something to %b_mutate
2188
+ %b_immutable = end_cow_mutation %b_mutate : $BufferClass
2189
+ cond_br %loop_cond, exit_block, backedge_block
2190
+ backedge_block:
2191
+ br header_block(b_immutable : $BufferClass)
2192
+ exit_block:
2193
+
2194
+ Two adjacent ``begin_cow_mutation `` and ``end_cow_mutation `` instructions
2195
+ don't need to be in the same function.
2196
+
2197
+
2110
2198
Instruction Set
2111
2199
---------------
2112
2200
@@ -3199,6 +3287,56 @@ strong reference count is greater than 1.
3199
3287
A discussion of the semantics can be found here:
3200
3288
:ref: `arcopts.is_unique `.
3201
3289
3290
+ begin_cow_mutation
3291
+ ``````````````````
3292
+
3293
+ ::
3294
+
3295
+ sil-instruction ::= 'begin_cow_mutation' '[native]'? sil-operand
3296
+
3297
+ (%1, %2) = begin_cow_mutation %0 : $C
3298
+ // $C must be a reference-counted type
3299
+ // %1 will be of type Builtin.Int1
3300
+ // %2 will be of type C
3301
+
3302
+ Checks whether %0 is a unique reference to a memory object. Returns 1 in the
3303
+ first result if the strong reference count is 1, and 0 if the strong reference
3304
+ count is greater than 1.
3305
+
3306
+ Returns the reference operand in the second result. The returned reference can
3307
+ be used to mutate the object. Technically, the returned reference is the same
3308
+ as the operand. But it's important that optimizations see the result as a
3309
+ different SSA value than the operand. This is important to ensure the
3310
+ correctness of ``ref_element_addr [immutable] ``.
3311
+
3312
+ The operand is consumed and the second result is returned as owned.
3313
+
3314
+ The optional ``native `` attribute specifies that the operand has native Swift
3315
+ reference counting.
3316
+
3317
+ end_cow_mutation
3318
+ ````````````````
3319
+
3320
+ ::
3321
+
3322
+ sil-instruction ::= 'end_cow_mutation' '[keep_unique]'? sil-operand
3323
+
3324
+ %1 = end_cow_mutation %0 : $C
3325
+ // $C must be a reference-counted type
3326
+ // %1 will be of type C
3327
+
3328
+ Marks the end of the mutation of a reference counted object.
3329
+ Returns the reference operand. Technically, the returned reference is the same
3330
+ as the operand. But it's important that optimizations see the result as a
3331
+ different SSA value than the operand. This is important to ensure the
3332
+ correctness of ``ref_element_addr [immutable] ``.
3333
+
3334
+ The operand is consumed and the result is returned as owned. The result is
3335
+ guaranteed to be uniquely referenced.
3336
+
3337
+ The optional ``keep_unique `` attribute indicates that the optimizer must not
3338
+ replace this reference with a not uniquely reference object.
3339
+
3202
3340
is_escaping_closure
3203
3341
```````````````````
3204
3342
@@ -4193,7 +4331,7 @@ ref_element_addr
4193
4331
````````````````
4194
4332
::
4195
4333
4196
- sil-instruction ::= 'ref_element_addr' sil-operand ',' sil-decl-ref
4334
+ sil-instruction ::= 'ref_element_addr' '[immutable]'? sil-operand ',' sil-decl-ref
4197
4335
4198
4336
%1 = ref_element_addr %0 : $C, #C.field
4199
4337
// %0 must be a value of class type $C
@@ -4205,11 +4343,15 @@ Given an instance of a class, derives the address of a physical instance
4205
4343
variable inside the instance. It is undefined behavior if the class value
4206
4344
is null.
4207
4345
4346
+ The ``immutable `` attribute specifies that all loads of the same instance
4347
+ variable from the same class reference operand are guaranteed to yield the
4348
+ same value.
4349
+
4208
4350
ref_tail_addr
4209
4351
`````````````
4210
4352
::
4211
4353
4212
- sil-instruction ::= 'ref_tail_addr' sil-operand ',' sil-type
4354
+ sil-instruction ::= 'ref_tail_addr' '[immutable]'? sil-operand ',' sil-type
4213
4355
4214
4356
%1 = ref_tail_addr %0 : $C, $E
4215
4357
// %0 must be a value of class type $C with tail-allocated elements $E
@@ -4222,6 +4364,10 @@ object which is created by an ``alloc_ref`` with ``tail_elems``.
4222
4364
It is undefined behavior if the class instance does not have tail-allocated
4223
4365
arrays or if the element-types do not match.
4224
4366
4367
+ The ``immutable `` attribute specifies that all loads of the same instance
4368
+ variable from the same class reference operand are guaranteed to yield the
4369
+ same value.
4370
+
4225
4371
Enums
4226
4372
~~~~~
4227
4373
0 commit comments