@@ -154,8 +154,37 @@ public class AnyKeyPath: _AppendKeyPath {
154
154
) -> Self {
155
155
_internalInvariant ( bytes > 0 && bytes % 4 == 0 ,
156
156
" capacity must be multiple of 4 bytes " )
157
- let result = Builtin . allocWithTailElems_1 ( self , ( bytes/ 4 ) . _builtinWordValue,
158
- Int32 . self)
157
+
158
+ // Subtract the buffer header and any padding it may have from the number of
159
+ // bytes we need to allocate. The alloc below has a 0 sized 16 byte aligned
160
+ // tail element that will force the compiler to insert buffer header + any
161
+ // padding necessary to accomodate.
162
+ let bytesWithoutHeader = bytes &- MemoryLayout< Int> . size
163
+
164
+ let result = Builtin . allocWithTailElems_2 (
165
+ self ,
166
+
167
+ // This tail element accomplishes two things:
168
+ // 1. Guarantees a 16 byte alignment for the allocated object pointer.
169
+ // 2. Forces the compiler to add padding after the kvc string to support
170
+ // this 16 byte aligned tail element.
171
+ //
172
+ // The size of keypath objects before any tail elements is 24 bytes large
173
+ // on 64 bit platforms and 12 bytes large on 32 bit platforms.
174
+ // (Isa, RC, and KVC). The amount of padding bytes needed after the kvc
175
+ // string pointer to support a 16 byte aligned tail element is the exact
176
+ // same amount of bytes that the keypath buffer header occupies on both
177
+ // 64 & 32 bit platforms (because we always start component headers on
178
+ // pointer aligned addresses). That is the purpose for the subtraction
179
+ // above. The result of this tail element should just be the 16 byte
180
+ // pointer aligned requirement and no extra bytes allocated.
181
+ 0 . _builtinWordValue,
182
+ SIMD16< Int8> . self ,
183
+
184
+ ( bytesWithoutHeader/ 4 ) . _builtinWordValue,
185
+ Int32 . self
186
+ )
187
+
159
188
unsafe result. _kvcKeyPathStringPtr = nil
160
189
let base = UnsafeMutableRawPointer ( Builtin . projectTailElems ( result,
161
190
Int32 . self) )
@@ -3071,7 +3100,7 @@ public func _swift_getKeyPath(pattern: UnsafeMutableRawPointer,
3071
3100
// Instantiate a new key path object modeled on the pattern.
3072
3101
// Do a pass to determine the class of the key path we'll be instantiating
3073
3102
// and how much space we'll need for it.
3074
- let ( keyPathClass, rootType, size, sizeWithMaxSize, _ )
3103
+ let ( keyPathClass, rootType, size, sizeWithMaxSize)
3075
3104
= unsafe _getKeyPathClassAndInstanceSizeFromPattern( patternPtr, arguments)
3076
3105
3077
3106
var pureStructOffset : UInt32 ? = nil
@@ -3633,6 +3662,9 @@ internal struct GetKeyPathClassAndInstanceSizeFromPattern
3633
3662
// start with one word for the header
3634
3663
var size : Int = MemoryLayout< Int> . size
3635
3664
var sizeWithMaxSize : Int = 0
3665
+ var sizeWithObjectHeaderAndKvc : Int {
3666
+ size &+ MemoryLayout < Int > . size * 3
3667
+ }
3636
3668
3637
3669
var capability : KeyPathKind = . value
3638
3670
var didChain : Bool = false
@@ -3735,13 +3767,24 @@ internal struct GetKeyPathClassAndInstanceSizeFromPattern
3735
3767
// Argument size and witnesses ptr.
3736
3768
unsafe size &+= MemoryLayout < Int > . size &* 2
3737
3769
3770
+ // If we also have external arguments, we need to store the size of the
3771
+ // local arguments so we can find the external component arguments.
3772
+ if unsafe externalArgs != nil {
3773
+ unsafe size &+= RawKeyPathComponent . Header. externalWithArgumentsExtraSize
3774
+ }
3775
+
3738
3776
let ( typeSize, typeAlignMask) = unsafe arguments. getLayout ( patternArgs)
3739
3777
3740
3778
// We are known to be pointer aligned at this point in the KeyPath buffer.
3741
3779
// However, for types who have an alignment large than pointers, we need
3742
3780
// to determine if the current position is suitable for the argument, or
3743
3781
// if we need to add padding bytes to align ourselves.
3744
- let misaligned = unsafe size & typeAlignMask
3782
+ //
3783
+ // Note: We need to account for the object header and kvc pointer because
3784
+ // it's an odd number of words which will affect whether the size visitor
3785
+ // determines if we need padding. It would cause out of sync answers when
3786
+ // going to actually instantiate the buffer.
3787
+ let misaligned = unsafe sizeWithObjectHeaderAndKvc & typeAlignMask
3745
3788
3746
3789
if misaligned != 0 {
3747
3790
// We were misaligned, add the padding to the total size of the keypath
@@ -3761,12 +3804,6 @@ internal struct GetKeyPathClassAndInstanceSizeFromPattern
3761
3804
unsafe size &+= MemoryLayout < Int > . size &* 2
3762
3805
}
3763
3806
3764
- // We also need to store the size of the local arguments so we can
3765
- // find the external component arguments.
3766
- if unsafe arguments != nil {
3767
- unsafe size &+= RawKeyPathComponent . Header. externalWithArgumentsExtraSize
3768
- }
3769
-
3770
3807
unsafe size &+= MemoryLayout < Int > . size &* externalArgs. count
3771
3808
}
3772
3809
}
@@ -3813,8 +3850,7 @@ internal func _getKeyPathClassAndInstanceSizeFromPattern(
3813
3850
keyPathClass: AnyKeyPath . Type,
3814
3851
rootType: Any . Type,
3815
3852
size: Int,
3816
- sizeWithMaxSize: Int,
3817
- alignmentMask: Int
3853
+ sizeWithMaxSize: Int
3818
3854
) {
3819
3855
var walker = unsafe GetKeyPathClassAndInstanceSizeFromPattern( patternArgs: arguments)
3820
3856
unsafe _walkKeyPathPattern( pattern, walker: & walker)
@@ -3840,12 +3876,12 @@ internal func _getKeyPathClassAndInstanceSizeFromPattern(
3840
3876
}
3841
3877
let classTy = unsafe _openExistential ( walker. root!, do: openRoot)
3842
3878
3843
- return unsafe ( keyPathClass : classTy ,
3844
- rootType : walker . root! ,
3845
- size : walker. size ,
3846
- sizeWithMaxSize : walker. sizeWithMaxSize ,
3847
- // FIXME: Handle overalignment
3848
- alignmentMask : MemoryLayout < Int > . _alignmentMask )
3879
+ return unsafe (
3880
+ keyPathClass : classTy ,
3881
+ rootType : walker. root! ,
3882
+ size : walker. size ,
3883
+ sizeWithMaxSize : walker . sizeWithMaxSize
3884
+ )
3849
3885
}
3850
3886
3851
3887
internal func _getTypeSize< Type> ( _: Type . Type) - > Int {
@@ -4279,7 +4315,6 @@ internal struct ValidatingInstantiateKeyPathBuffer: KeyPathPatternVisitor {
4279
4315
offset: offset)
4280
4316
unsafe checkSizeConsistency ( )
4281
4317
unsafe structOffset = unsafe instantiateVisitor . structOffset
4282
- unsafe isPureStruct . append ( contentsOf: instantiateVisitor. isPureStruct)
4283
4318
}
4284
4319
mutating func visitComputedComponent( mutating: Bool ,
4285
4320
idKind: KeyPathComputedIDKind ,
@@ -4311,31 +4346,26 @@ internal struct ValidatingInstantiateKeyPathBuffer: KeyPathPatternVisitor {
4311
4346
// Note: For this function and the ones below, modification of structOffset
4312
4347
// is omitted since these types of KeyPaths won't have a pureStruct
4313
4348
// offset anyway.
4314
- unsafe isPureStruct . append ( contentsOf: instantiateVisitor. isPureStruct)
4315
4349
unsafe checkSizeConsistency ( )
4316
4350
}
4317
4351
mutating func visitOptionalChainComponent( ) {
4318
4352
unsafe sizeVisitor . visitOptionalChainComponent ( )
4319
4353
unsafe instantiateVisitor . visitOptionalChainComponent ( )
4320
- unsafe isPureStruct . append ( contentsOf: instantiateVisitor. isPureStruct)
4321
4354
unsafe checkSizeConsistency ( )
4322
4355
}
4323
4356
mutating func visitOptionalWrapComponent( ) {
4324
4357
unsafe sizeVisitor . visitOptionalWrapComponent ( )
4325
4358
unsafe instantiateVisitor . visitOptionalWrapComponent ( )
4326
- unsafe isPureStruct . append ( contentsOf: instantiateVisitor. isPureStruct)
4327
4359
unsafe checkSizeConsistency ( )
4328
4360
}
4329
4361
mutating func visitOptionalForceComponent( ) {
4330
4362
unsafe sizeVisitor . visitOptionalForceComponent ( )
4331
4363
unsafe instantiateVisitor . visitOptionalForceComponent ( )
4332
- unsafe isPureStruct . append ( contentsOf: instantiateVisitor. isPureStruct)
4333
4364
unsafe checkSizeConsistency ( )
4334
4365
}
4335
4366
mutating func visitIntermediateComponentType( metadataRef: MetadataReference ) {
4336
4367
unsafe sizeVisitor . visitIntermediateComponentType ( metadataRef: metadataRef)
4337
4368
unsafe instantiateVisitor . visitIntermediateComponentType ( metadataRef: metadataRef)
4338
- unsafe isPureStruct . append ( contentsOf: instantiateVisitor. isPureStruct)
4339
4369
unsafe checkSizeConsistency ( )
4340
4370
}
4341
4371
0 commit comments