@@ -149,21 +149,17 @@ public class AnyKeyPath: Hashable, _AppendKeyPath {
149
149
let architectureSize = MemoryLayout< Int> . size
150
150
if architectureSize == 8 {
151
151
_kvcKeyPathStringPtr = UnsafePointer < CChar > ( bitPattern: - offset - 1 )
152
- } else {
153
- if offset == 0 {
154
- _kvcKeyPathStringPtr =
155
- UnsafePointer < CChar > ( bitPattern: maximumOffsetOn32BitArchitecture + 1 )
156
- } else if offset < maximumOffsetOn32BitArchitecture {
157
- _kvcKeyPathStringPtr = UnsafePointer < CChar > ( bitPattern: offset)
158
- } else {
152
+ }
153
+ else {
154
+ if offset <= maximumOffsetOn32BitArchitecture {
155
+ _kvcKeyPathStringPtr = UnsafePointer < CChar > ( bitPattern: ( offset + 1 ) )
156
+ }
157
+ else {
159
158
_kvcKeyPathStringPtr = nil
160
159
}
161
160
}
162
161
}
163
162
164
- // TODO: See if this can be @inlinable since it gets called on each
165
- // KeyPath access. It would mean _kvcKeyPathStringPtr would need
166
- // to be @usableFromInline. What effect would that have on ABI stability?
167
163
func getOffsetFromStorage( ) -> Int ? {
168
164
let maximumOffsetOn32BitArchitecture = 4094
169
165
guard let storage = _kvcKeyPathStringPtr else {
@@ -182,14 +178,13 @@ public class AnyKeyPath: Hashable, _AppendKeyPath {
182
178
return nil
183
179
}
184
180
return storageDistance
185
- } else {
186
- let storageDistance = offsetBase!. distance ( to: storage) + 1
187
- if storageDistance == maximumOffsetOn32BitArchitecture + 1 {
188
- return 0
189
- } else if storageDistance > maximumOffsetOn32BitArchitecture {
190
- return nil
181
+ }
182
+ else {
183
+ let storageDistance = offsetBase!. distance ( to: storage)
184
+ if ( storageDistance <= maximumOffsetOn32BitArchitecture) {
185
+ return storageDistance
191
186
}
192
- return storageDistance
187
+ return nil
193
188
}
194
189
}
195
190
@@ -242,33 +237,6 @@ public class AnyKeyPath: Hashable, _AppendKeyPath {
242
237
let base = UnsafeRawPointer ( Builtin . projectTailElems ( self , Int32 . self) )
243
238
return try f ( KeyPathBuffer ( base: base) )
244
239
}
245
-
246
- // TODO: Find a quicker way to see if this is a tuple.
247
- internal func isTuple( _ item: Any ) -> Bool {
248
- // Unwraps type information if possible.
249
- // Otherwise, everything the Mirror handling "item"
250
- // sees would be "Optional<Any.Type>".
251
- func unwrapType< T> ( _ any: T ) -> Any {
252
- let mirror = Mirror ( reflecting: any)
253
- guard mirror. displayStyle == . optional,
254
- let first = mirror. children. first
255
- else {
256
- return any
257
- }
258
- return first. value
259
- }
260
-
261
- let mirror = Mirror ( reflecting: unwrapType ( item) )
262
- let description = mirror. description
263
- let offsetOfFirstBracketForMirrorDescriptionOfTuple = 11
264
- let idx = description. index (
265
- description. startIndex,
266
- offsetBy: offsetOfFirstBracketForMirrorDescriptionOfTuple)
267
- if description [ idx] == " ( " {
268
- return true
269
- }
270
- return false
271
- }
272
240
273
241
@usableFromInline // Exposed as public API by MemoryLayout<Root>.offset(of:)
274
242
internal var _storedInlineOffset : Int ? {
@@ -2669,39 +2637,17 @@ public func _swift_getKeyPath(pattern: UnsafeMutableRawPointer,
2669
2637
let ( keyPathClass, rootType, size, _)
2670
2638
= _getKeyPathClassAndInstanceSizeFromPattern ( patternPtr, arguments)
2671
2639
2672
- // Used to process offsets for pure struct KeyPaths.
2673
- var offset = UInt32 ( 0 )
2674
- var isPureStruct = true
2675
- var keyPathBase : Any . Type ?
2640
+ var pureStructOffset : UInt32 ? = nil
2676
2641
2677
2642
// Allocate the instance.
2678
2643
let instance = keyPathClass. _create ( capacityInBytes: size) { instanceData in
2679
2644
// Instantiate the pattern into the instance.
2680
- let returnValue = _instantiateKeyPathBuffer (
2645
+ pureStructOffset = _instantiateKeyPathBuffer (
2681
2646
patternPtr,
2682
2647
instanceData,
2683
2648
rootType,
2684
2649
arguments
2685
2650
)
2686
- offset += returnValue. structOffset
2687
-
2688
- let componentStructList = returnValue. componentStructList
2689
- if componentStructList. count == 0 {
2690
- isPureStruct = false
2691
- }
2692
- for value in componentStructList {
2693
- isPureStruct = isPureStruct && value
2694
- }
2695
- keyPathBase = rootType
2696
- }
2697
-
2698
- // TODO: See if there's a better way to eliminate
2699
- // tuples from the current `isPureStruct` optimization.
2700
- if let keyPathBase = keyPathBase, instance. isTuple ( keyPathBase) {
2701
- isPureStruct = false
2702
- }
2703
- if isPureStruct {
2704
- instance. assignOffsetToStorage ( offset: Int ( offset) )
2705
2651
}
2706
2652
2707
2653
// Adopt the KVC string from the pattern.
@@ -2716,8 +2662,7 @@ public func _swift_getKeyPath(pattern: UnsafeMutableRawPointer,
2716
2662
instance. _kvcKeyPathStringPtr =
2717
2663
kvcStringPtr. assumingMemoryBound ( to: CChar . self)
2718
2664
}
2719
-
2720
- if instance. _kvcKeyPathStringPtr == nil , isPureStruct {
2665
+ if instance. _kvcKeyPathStringPtr == nil , let offset = pureStructOffset {
2721
2666
instance. assignOffsetToStorage ( offset: Int ( offset) )
2722
2667
}
2723
2668
// If we can cache this instance as a shared instance, do so.
@@ -3885,7 +3830,7 @@ internal func _instantiateKeyPathBuffer(
3885
3830
_ origDestData: UnsafeMutableRawBufferPointer ,
3886
3831
_ rootType: Any . Type ,
3887
3832
_ arguments: UnsafeRawPointer
3888
- ) -> ( structOffset : UInt32 , componentStructList : [ Bool ] ) {
3833
+ ) -> UInt32 ? {
3889
3834
let destHeaderPtr = origDestData. baseAddress. unsafelyUnwrapped
3890
3835
var destData = UnsafeMutableRawBufferPointer (
3891
3836
start: destHeaderPtr. advanced ( by: MemoryLayout< Int> . size) ,
@@ -3937,7 +3882,25 @@ internal func _instantiateKeyPathBuffer(
3937
3882
endOfReferencePrefixComponent. storeBytes ( of: componentHeader,
3938
3883
as: RawKeyPathComponent . Header. self)
3939
3884
}
3940
- return ( walker. structOffset, walker. isPureStruct)
3885
+ var isPureStruct = true
3886
+ var offset : UInt32 ? = nil
3887
+
3888
+ for value in walker. isPureStruct {
3889
+ isPureStruct = isPureStruct && value
3890
+ }
3891
+
3892
+ // Disable the optimization in the general case of 0 components.
3893
+ // Note that a KeyPath such as \SomeStruct.self would still technically
3894
+ // have a valid offset of 0.
3895
+ // TODO: Add the logic to distinguish pure struct
3896
+ // 0-component KeyPaths (tuples too?) from others.
3897
+ if walker. isPureStruct. count == 0 {
3898
+ isPureStruct = false
3899
+ }
3900
+ if isPureStruct {
3901
+ offset = walker. structOffset
3902
+ }
3903
+ return offset
3941
3904
}
3942
3905
3943
3906
#if SWIFT_ENABLE_REFLECTION
0 commit comments