Skip to content

Commit 3cdc8ec

Browse files
author
Alexis Beingessner
committed
remove buffer header to eliminate optional traps
1 parent 931f7ba commit 3cdc8ec

File tree

1 file changed

+47
-79
lines changed

1 file changed

+47
-79
lines changed

stdlib/public/core/HashedCollections.swift.gyb

Lines changed: 47 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -46,14 +46,11 @@ import SwiftShims
4646
// |
4747
// V _RawNativeDictionaryStorage (a class)
4848
// +-----------------------------------------------------------+
49-
// | +-------------------------------------------------------+ |
50-
// | |_DictionaryBufferHeader<K,V> (a struct) | |
51-
// | | capacity | |
52-
// | | count | |
53-
// | | ptrToBits | |
54-
// | | ptrToKeys | |
55-
// | | ptrToValues | |
56-
// | +-------------------------------------------------------+ |
49+
// | capacity |
50+
// | count |
51+
// | ptrToBits |
52+
// | ptrToKeys |
53+
// | ptrToValues |
5754
// | [inline array of bits indicating whether bucket is set ] |
5855
// | [inline array of keys ] |
5956
// | [inline array of values ] |
@@ -2470,26 +2467,6 @@ collections = [
24702467

24712468
% for (Self, a_self, TypeParametersDecl, TypeParameters, AnyTypeParameters, Sequence, AnySequenceType) in collections:
24722469

2473-
/// Header part of the RawNativeSelfStorage.
2474-
internal struct _${Self}BufferHeader {
2475-
2476-
internal init(capacity: Int) {
2477-
self.capacity = capacity
2478-
}
2479-
2480-
internal let capacity: Int
2481-
internal var count: Int = 0
2482-
internal let maxLoadFactorInverse: Double =
2483-
_hashContainerDefaultMaxLoadFactorInverse
2484-
2485-
// Placeholder values until the struct can be initialized.
2486-
internal var initializedEntries: _UnsafeBitMap! = nil
2487-
internal var keys: UnsafeMutableRawPointer! = nil
2488-
% if Self == 'Dictionary':
2489-
internal var values: UnsafeMutableRawPointer! = nil
2490-
% end
2491-
}
2492-
24932470
/// An instance of this class has all `${Self}` data tail-allocated.
24942471
/// Enough bytes are allocated to hold the bitmap for marking valid entries,
24952472
/// keys, and values. The data layout starts with the bitmap, followed by the
@@ -2499,13 +2476,22 @@ internal struct _${Self}BufferHeader {
24992476
internal class _RawNative${Self}Storage:
25002477
_SwiftNativeNS${Self}, _NS${Self}Core
25012478
{
2502-
internal typealias BufferHeader = _${Self}BufferHeader
25032479
internal typealias RawStorage = _RawNative${Self}Storage
2480+
2481+
internal final var capacity: Int
2482+
internal final var count: Int
2483+
2484+
internal final var initializedEntries: _UnsafeBitMap
2485+
internal final var keys: UnsafeMutableRawPointer
2486+
% if Self == 'Dictionary':
2487+
internal final var values: UnsafeMutableRawPointer
2488+
% end
25042489

2505-
internal var _body: BufferHeader
2490+
internal final let maxLoadFactorInverse: Double =
2491+
_hashContainerDefaultMaxLoadFactorInverse
25062492

25072493
// This API is unsafe and needs a `_fixLifetime` in the caller.
2508-
internal
2494+
internal final
25092495
var _initializedHashtableEntriesBitMapBuffer: UnsafeMutablePointer<UInt> {
25102496
return UnsafeMutablePointer(Builtin.projectTailElems(self, UInt.self))
25112497
}
@@ -2521,16 +2507,21 @@ internal class _RawNative${Self}Storage:
25212507
// We set the capacity to 1 so that there's an empty hole to search.
25222508
// Any insertion will lead to a real storage being allocated, because
25232509
// Dictionary guarantees there's always another empty hole after insertion.
2524-
storage._body = BufferHeader(capacity: 1)
2510+
storage.capacity = 1
2511+
storage.count = 0
2512+
2513+
// Initialize pointers to garbage; they should never be loaded
2514+
storage.keys = UnsafeMutableRawPointer(bitPattern: 1)!
2515+
% if Self == 'Dictionary':
2516+
storage.values = UnsafeMutableRawPointer(bitPattern: 1)!
2517+
% end
25252518

25262519
let initializedEntries = _UnsafeBitMap(
25272520
storage: storage._initializedHashtableEntriesBitMapBuffer,
25282521
bitCount: 1)
25292522
initializedEntries.initializeToZero()
25302523

2531-
// We don't bother to initalize the pointers in the header because
2532-
// they should never be accessed on the empty singleton.
2533-
storage._body.initializedEntries = initializedEntries
2524+
storage.initializedEntries = initializedEntries
25342525
return storage
25352526
}()
25362527

@@ -2558,10 +2549,6 @@ internal class _RawNative${Self}Storage:
25582549
return self
25592550
}
25602551

2561-
var count: Int {
2562-
return 0
2563-
}
2564-
25652552
@objc(countByEnumeratingWithState:objects:count:)
25662553
func countByEnumerating(
25672554
with state: UnsafeMutablePointer<_SwiftNSFastEnumerationState>,
@@ -2638,12 +2625,9 @@ internal class _TypedNative${Self}Storage<${TypeParameters}> :
26382625
%end
26392626

26402627
deinit {
2641-
let capacity = _body.capacity
2642-
let initializedEntries = _UnsafeBitMap(
2643-
storage: _initializedHashtableEntriesBitMapBuffer, bitCount: capacity)
2644-
let keys = _body.keys.assumingMemoryBound(to: Key.self)
2628+
let keys = self.keys.assumingMemoryBound(to: Key.self)
26452629
%if Self == 'Dictionary':
2646-
let values = _body.values.assumingMemoryBound(to: Value.self)
2630+
let values = self.values.assumingMemoryBound(to: Value.self)
26472631
%end
26482632

26492633
if !_isPOD(Key.self) {
@@ -2721,10 +2705,6 @@ final internal class _HashableTypedNative${Self}Storage<${TypeParametersDecl}> :
27212705
return FullContainer(_nativeBuffer: buffer)
27222706
}
27232707

2724-
override var count: Int {
2725-
return full.count
2726-
}
2727-
27282708
override func enumerator() -> _NSEnumerator {
27292709
return _Native${Self}NSEnumerator<${TypeParameters}>(
27302710
Buffer(_storage: self))
@@ -2854,7 +2834,6 @@ final internal class _HashableTypedNative${Self}Storage<${TypeParametersDecl}> :
28542834
/// Hashable can be found in an extension.
28552835
internal struct _Native${Self}Buffer<${TypeParameters}> {
28562836

2857-
internal typealias BufferHeader = _${Self}BufferHeader
28582837
internal typealias RawStorage = _RawNative${Self}Storage
28592838
internal typealias TypedStorage = _TypedNative${Self}Storage<${TypeParameters}>
28602839
internal typealias Buffer = _Native${Self}Buffer<${TypeParameters}>
@@ -2892,9 +2871,8 @@ internal struct _Native${Self}Buffer<${TypeParameters}> {
28922871
/// Given a capacity and uninitialized RawStorage, completes the
28932872
/// initialization and returns a Buffer.
28942873
internal init(capacity: Int, storage: RawStorage) {
2895-
// We can initialize by assignment because _HashedContainerBufferHeader
2896-
// is a trivial type, i.e. contains no references.
2897-
storage._body = BufferHeader(capacity: capacity)
2874+
storage.capacity = capacity
2875+
storage.count = 0
28982876

28992877
self.init(_storage: storage)
29002878

@@ -2910,44 +2888,34 @@ internal struct _Native${Self}Buffer<${TypeParameters}> {
29102888
numWordsForBitmap._builtinWordValue, UInt.self, Key.self)
29112889

29122890
// Initialize header
2913-
_body.initializedEntries = initializedEntries
2914-
_body.keys = UnsafeMutableRawPointer(keysAddr)
2891+
_storage.initializedEntries = initializedEntries
2892+
_storage.keys = UnsafeMutableRawPointer(keysAddr)
29152893
%if Self == 'Dictionary':
29162894
let valuesAddr = Builtin.getTailAddr_Word(keysAddr,
29172895
capacity._builtinWordValue, Key.self, Value.self)
2918-
_body.values = UnsafeMutableRawPointer(valuesAddr)
2896+
_storage.values = UnsafeMutableRawPointer(valuesAddr)
29192897
%end
29202898
}
29212899

2922-
/// A convenience forwarding the _storage's body
2923-
internal var _body: BufferHeader {
2924-
set {
2925-
_storage._body = newValue
2926-
}
2927-
get {
2928-
return _storage._body
2929-
}
2930-
}
2931-
29322900
// Forwarding the individual fields of the storage in various forms
29332901

29342902
@_versioned
29352903
internal var capacity: Int {
2936-
return _assumeNonNegative(_body.capacity)
2904+
return _assumeNonNegative(_storage.capacity)
29372905
}
29382906

29392907
@_versioned
29402908
internal var count: Int {
29412909
set {
2942-
_body.count = newValue
2910+
_storage.count = newValue
29432911
}
29442912
get {
2945-
return _assumeNonNegative(_body.count)
2913+
return _assumeNonNegative(_storage.count)
29462914
}
29472915
}
29482916

29492917
internal var _maxLoadFactorInverse: Double {
2950-
return _body.maxLoadFactorInverse
2918+
return _storage.maxLoadFactorInverse
29512919
}
29522920

29532921
internal
@@ -2957,13 +2925,13 @@ internal struct _Native${Self}Buffer<${TypeParameters}> {
29572925

29582926
// This API is unsafe and needs a `_fixLifetime` in the caller.
29592927
internal var keys: UnsafeMutablePointer<Key> {
2960-
return _body.keys.assumingMemoryBound(to: Key.self)
2928+
return _storage.keys.assumingMemoryBound(to: Key.self)
29612929
}
29622930

29632931
%if Self == 'Dictionary':
29642932
// This API is unsafe and needs a `_fixLifetime` in the caller.
29652933
internal var values: UnsafeMutablePointer<Value> {
2966-
return _body.values.assumingMemoryBound(to: Value.self)
2934+
return _storage.values.assumingMemoryBound(to: Value.self)
29672935
}
29682936
%end
29692937

@@ -3016,7 +2984,7 @@ internal struct _Native${Self}Buffer<${TypeParameters}> {
30162984
_sanityCheck(i >= 0 && i < capacity)
30172985
defer { _fixLifetime(self) }
30182986

3019-
return _body.initializedEntries[i]
2987+
return _storage.initializedEntries[i]
30202988
}
30212989

30222990
@_transparent
@@ -3028,7 +2996,7 @@ internal struct _Native${Self}Buffer<${TypeParameters}> {
30282996
%if Self == 'Dictionary':
30292997
(values + i).deinitialize()
30302998
%end
3031-
_body.initializedEntries[i] = false
2999+
_storage.initializedEntries[i] = false
30323000
}
30333001

30343002
%if Self == 'Set':
@@ -3038,7 +3006,7 @@ internal struct _Native${Self}Buffer<${TypeParameters}> {
30383006
defer { _fixLifetime(self) }
30393007

30403008
(keys + i).initialize(to: k)
3041-
_body.initializedEntries[i] = true
3009+
_storage.initializedEntries[i] = true
30423010
}
30433011

30443012
@_transparent
@@ -3048,8 +3016,8 @@ internal struct _Native${Self}Buffer<${TypeParameters}> {
30483016
defer { _fixLifetime(self) }
30493017

30503018
(keys + toEntryAt).initialize(to: (from.keys + at).move())
3051-
from._body.initializedEntries[at] = false
3052-
_body.initializedEntries[toEntryAt] = true
3019+
from._storage.initializedEntries[at] = false
3020+
_storage.initializedEntries[toEntryAt] = true
30533021
}
30543022

30553023
/// Alias for key(at:) in Sets for better code reuse
@@ -3075,7 +3043,7 @@ internal struct _Native${Self}Buffer<${TypeParameters}> {
30753043

30763044
(keys + i).initialize(to: k)
30773045
(values + i).initialize(to: v)
3078-
_body.initializedEntries[i] = true
3046+
_storage.initializedEntries[i] = true
30793047
}
30803048

30813049
@_transparent
@@ -3085,8 +3053,8 @@ internal struct _Native${Self}Buffer<${TypeParameters}> {
30853053

30863054
(keys + toEntryAt).initialize(to: (from.keys + at).move())
30873055
(values + toEntryAt).initialize(to: (from.values + at).move())
3088-
from._body.initializedEntries[at] = false
3089-
_body.initializedEntries[toEntryAt] = true
3056+
from._storage.initializedEntries[at] = false
3057+
_storage.initializedEntries[toEntryAt] = true
30903058
}
30913059

30923060
@_versioned

0 commit comments

Comments
 (0)