@@ -16,25 +16,36 @@ import SwiftShims
16
16
17
17
String's Index has the following layout:
18
18
19
- ┌──────────┬───────────────────┬─────────╥────────────────┬──────────┐
20
- │ b63:b16 │ b15:b14 │ b13 ║ b12:b8 │ b6:b0 │
21
- ├──────────┼───────────────────┼─────────╫────────────────┼──────────┤
22
- │ position │ transcoded offset │ aligned ║ grapheme cache │ reserved │
23
- └──────────┴───────────────────┴─────────╨────────────────┴──────────┘
24
-
25
- Position, transcoded offset, and aligned are fully exposed in the ABI. Grapheme
26
- cache and reserved are partially resilient: the fact that there are 13 bits with
27
- a default value of `0` is ABI, but not the layout, construction, or
19
+ ┌──────────┬───────────────────╥────────────────┬──────────╥────────────────┐
20
+ │ b63:b16 │ b15:b14 ║ b13:b8 │ b7:b1 ║ b0 │
21
+ ├──────────┼───────────────────╫────────────────┼──────────╫────────────────┤
22
+ │ position │ transcoded offset ║ grapheme cache │ reserved ║ scalar aligned │
23
+ └──────────┴───────────────────╨────────────────┴──────────╨────────────────┘
24
+ └──────── resilient ────────┘
25
+
26
+ Position, transcoded offset, and scalar aligned are fully exposed in the ABI.
27
+ Grapheme cache and reserved are partially resilient: the fact that there are 13
28
+ bits with a default value of `0` is ABI, but not the layout, construction, or
28
29
interpretation of those bits. All use of grapheme cache should be behind
29
- non-inlinable function calls.
30
+ non-inlinable function calls. Inlinable code should not set a non-zero value to
31
+ grapheme cache bits: doing so breaks back deployment as they will be interpreted
32
+ as a set cache.
30
33
31
34
- position aka `encodedOffset`: A 48-bit offset into the string's code units
35
+
32
36
- transcoded offset: a 2-bit sub-scalar offset, derived from transcoding
33
- - aligned, whether this index is known to be scalar-aligned (see below)
37
+
38
+ <resilience barrier>
39
+
40
+ - grapheme cache: A 6-bit value remembering the distance to the next grapheme
41
+ boundary.
42
+
43
+ - reserved: 7-bit for future use.
44
+
34
45
<resilience barrier>
35
- - grapheme cache: A 5-bit value remembering the distance to the next grapheme
36
- boundary
37
- - reserved: 8-bit for future use.
46
+
47
+ - scalar aligned, whether this index is known to be scalar-aligned (see below)
48
+
38
49
39
50
*/
40
51
extension String {
@@ -86,7 +97,7 @@ extension String.Index {
86
97
87
98
@usableFromInline
88
99
internal var characterStride : Int ? {
89
- let value = ( _rawBits & 0x1F00 ) &>> 8
100
+ let value = ( _rawBits & 0x3F00 ) &>> 8
90
101
return value > 0 ? Int ( truncatingIfNeeded: value) : nil
91
102
}
92
103
@@ -136,7 +147,7 @@ extension String.Index {
136
147
encodedOffset: Int , transcodedOffset: Int , characterStride: Int
137
148
) {
138
149
self . init ( encodedOffset: encodedOffset, transcodedOffset: transcodedOffset)
139
- if _slowPath ( characterStride > 0x1F ) { return }
150
+ if _slowPath ( characterStride > 0x3F ) { return }
140
151
self . _rawBits |= UInt64 ( truncatingIfNeeded: characterStride &<< 8 )
141
152
self . _invariantCheck ( )
142
153
}
@@ -152,7 +163,7 @@ extension String.Index {
152
163
@usableFromInline @inline ( never) @_effects ( releasenone)
153
164
internal func _invariantCheck( ) {
154
165
_internalInvariant ( _encodedOffset >= 0 )
155
- if self . _isAligned {
166
+ if self . _isScalarAligned {
156
167
_internalInvariant ( transcodedOffset == 0 )
157
168
}
158
169
}
@@ -209,35 +220,35 @@ extension String.Index {
209
220
}
210
221
211
222
/*
212
- Index Alignment
223
+ Index Scalar Alignment
213
224
214
225
SE-0180 unifies the Index type of String and all its views and allows
215
226
non-scalar-aligned indices to be used across views. In order to guarantee
216
227
behavior, we often have to check and perform scalar alignment. To speed up
217
- these checks, we allocate a bit denoting known-to-be-aligned, so that the
218
- alignment check can skip the load. The below shows what views need to check
219
- for alignment before they can operate, and whether the indices they produce
220
- are aligned.
221
-
222
- ┌───────────────╥────────────────────┬─ ─────────────────────────┐
223
- │ View ║ Requires Alignment │ Produces Aligned Indices │
224
- ╞═══════════════╬════════════════════╪═ ═════════════════════════╡
225
- │ Native UTF8 ║ no │ no │
226
- ├───────────────╫────────────────────┼─ ─────────────────────────┤
227
- │ Native UTF16 ║ yes │ no │
228
- ╞═══════════════╬════════════════════╪═ ═════════════════════════╡
229
- │ Foreign UTF8 ║ yes │ no │
230
- ├───────────────╫────────────────────┼─ ─────────────────────────┤
231
- │ Foreign UTF16 ║ no │ no │
232
- ╞═══════════════╬════════════════════╪═ ═════════════════════════╡
233
- │ UnicodeScalar ║ yes │ yes │
234
- ├───────────────╫────────────────────┼─ ─────────────────────────┤
235
- │ Character ║ yes │ yes │
236
- └───────────────╨────────────────────┴─ ─────────────────────────┘
237
-
238
- The "requires alignment" applies to any operation taking a String.Index that's
239
- not defined entirely in terms of other operations taking a String.Index. These
240
- include:
228
+ these checks, we allocate a bit denoting known-to-be-scalar- aligned, so that
229
+ the alignment check can skip the load. The below shows what views need to
230
+ check for alignment before they can operate, and whether the indices they
231
+ produce are aligned.
232
+
233
+ ┌───────────────╥───────────────────────────┬ ─────────────────────────┐
234
+ │ View ║ Requires Scalar Alignment │ Produces Scalar Aligned │
235
+ ╞═══════════════╬═══════════════════════════╪ ═════════════════════════╡
236
+ │ Native UTF8 ║ no │ no │
237
+ ├───────────────╫───────────────────────────┼ ─────────────────────────┤
238
+ │ Native UTF16 ║ yes │ no │
239
+ ╞═══════════════╬═══════════════════════════╪ ═════════════════════════╡
240
+ │ Foreign UTF8 ║ yes │ no │
241
+ ├───────────────╫───────────────────────────┼ ─────────────────────────┤
242
+ │ Foreign UTF16 ║ no │ no │
243
+ ╞═══════════════╬═══════════════════════════╪ ═════════════════════════╡
244
+ │ UnicodeScalar ║ yes │ yes │
245
+ ├───────────────╫───────────────────────────┼ ─────────────────────────┤
246
+ │ Character ║ yes │ yes │
247
+ └───────────────╨───────────────────────────┴ ─────────────────────────┘
248
+
249
+ The "requires scalar alignment" applies to any operation taking a String.Index
250
+ that's not defined entirely in terms of other operations taking a
251
+ String.Index. These include:
241
252
242
253
* index(after:)
243
254
* index(before:)
@@ -249,13 +260,13 @@ extension String.Index {
249
260
extension String . Index {
250
261
@_alwaysEmitIntoClient // Swift 5.1
251
262
@inline ( __always)
252
- internal var _isAligned : Bool { return 0 != _rawBits & 0x2000 }
263
+ internal var _isScalarAligned : Bool { return 0 != _rawBits & 0x1 }
253
264
254
265
@_alwaysEmitIntoClient // Swift 5.1
255
266
@inline ( __always)
256
- internal var _aligned : String . Index {
267
+ internal var _scalarAligned : String . Index {
257
268
var idx = self
258
- idx. _rawBits |= 0x2000
269
+ idx. _rawBits |= 0x1
259
270
idx. _invariantCheck ( )
260
271
return idx
261
272
}
0 commit comments