Skip to content

Commit 4fb2f9e

Browse files
Modified storage of valid offsets in assignOffsetToStorage() and getOffsetFromStorage().
Got rid of isTuple(). Moved determination of pure struct KeyPaths into _instantiateKeyPathBuffer.
1 parent d2912dc commit 4fb2f9e

File tree

1 file changed

+35
-72
lines changed

1 file changed

+35
-72
lines changed

stdlib/public/core/KeyPath.swift

Lines changed: 35 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -149,21 +149,17 @@ public class AnyKeyPath: Hashable, _AppendKeyPath {
149149
let architectureSize = MemoryLayout<Int>.size
150150
if architectureSize == 8 {
151151
_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 {
159158
_kvcKeyPathStringPtr = nil
160159
}
161160
}
162161
}
163162

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?
167163
func getOffsetFromStorage() -> Int? {
168164
let maximumOffsetOn32BitArchitecture = 4094
169165
guard let storage = _kvcKeyPathStringPtr else {
@@ -182,14 +178,13 @@ public class AnyKeyPath: Hashable, _AppendKeyPath {
182178
return nil
183179
}
184180
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
191186
}
192-
return storageDistance
187+
return nil
193188
}
194189
}
195190

@@ -242,33 +237,6 @@ public class AnyKeyPath: Hashable, _AppendKeyPath {
242237
let base = UnsafeRawPointer(Builtin.projectTailElems(self, Int32.self))
243238
return try f(KeyPathBuffer(base: base))
244239
}
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-
}
272240

273241
@usableFromInline // Exposed as public API by MemoryLayout<Root>.offset(of:)
274242
internal var _storedInlineOffset: Int? {
@@ -2669,39 +2637,17 @@ public func _swift_getKeyPath(pattern: UnsafeMutableRawPointer,
26692637
let (keyPathClass, rootType, size, _)
26702638
= _getKeyPathClassAndInstanceSizeFromPattern(patternPtr, arguments)
26712639

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
26762641

26772642
// Allocate the instance.
26782643
let instance = keyPathClass._create(capacityInBytes: size) { instanceData in
26792644
// Instantiate the pattern into the instance.
2680-
let returnValue = _instantiateKeyPathBuffer(
2645+
pureStructOffset = _instantiateKeyPathBuffer(
26812646
patternPtr,
26822647
instanceData,
26832648
rootType,
26842649
arguments
26852650
)
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))
27052651
}
27062652

27072653
// Adopt the KVC string from the pattern.
@@ -2716,8 +2662,7 @@ public func _swift_getKeyPath(pattern: UnsafeMutableRawPointer,
27162662
instance._kvcKeyPathStringPtr =
27172663
kvcStringPtr.assumingMemoryBound(to: CChar.self)
27182664
}
2719-
2720-
if instance._kvcKeyPathStringPtr == nil, isPureStruct {
2665+
if instance._kvcKeyPathStringPtr == nil, let offset = pureStructOffset {
27212666
instance.assignOffsetToStorage(offset: Int(offset))
27222667
}
27232668
// If we can cache this instance as a shared instance, do so.
@@ -3885,7 +3830,7 @@ internal func _instantiateKeyPathBuffer(
38853830
_ origDestData: UnsafeMutableRawBufferPointer,
38863831
_ rootType: Any.Type,
38873832
_ arguments: UnsafeRawPointer
3888-
) -> (structOffset: UInt32, componentStructList: [Bool]) {
3833+
) -> UInt32? {
38893834
let destHeaderPtr = origDestData.baseAddress.unsafelyUnwrapped
38903835
var destData = UnsafeMutableRawBufferPointer(
38913836
start: destHeaderPtr.advanced(by: MemoryLayout<Int>.size),
@@ -3937,7 +3882,25 @@ internal func _instantiateKeyPathBuffer(
39373882
endOfReferencePrefixComponent.storeBytes(of: componentHeader,
39383883
as: RawKeyPathComponent.Header.self)
39393884
}
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
39413904
}
39423905

39433906
#if SWIFT_ENABLE_REFLECTION

0 commit comments

Comments
 (0)