Skip to content

Commit 21405f1

Browse files
Alexis BeingessnerGankra
authored andcommitted
[runtime] statically construct the Dictionary and Set singletons
1 parent d7753f6 commit 21405f1

File tree

3 files changed

+111
-25
lines changed

3 files changed

+111
-25
lines changed

stdlib/public/SwiftShims/GlobalObjects.h

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,44 @@ struct _SwiftEmptyArrayStorage {
3939
extern SWIFT_RUNTIME_STDLIB_INTERFACE
4040
struct _SwiftEmptyArrayStorage _swiftEmptyArrayStorage;
4141

42+
struct _SwiftUnsafeBitMap {
43+
__swift_uintptr_t *values;
44+
__swift_intptr_t bitCount;
45+
};
46+
47+
struct _SwiftDictionaryBodyStorage {
48+
__swift_intptr_t capacity;
49+
__swift_intptr_t count;
50+
struct _SwiftUnsafeBitMap initializedEntries;
51+
void *keys;
52+
void *values;
53+
};
54+
55+
struct _SwiftSetBodyStorage {
56+
__swift_intptr_t capacity;
57+
__swift_intptr_t count;
58+
struct _SwiftUnsafeBitMap initializedEntries;
59+
void *keys;
60+
};
61+
62+
struct _SwiftEmptyDictionaryStorage {
63+
struct HeapObject header;
64+
struct _SwiftDictionaryBodyStorage body;
65+
__swift_uintptr_t entries;
66+
};
67+
68+
struct _SwiftEmptySetStorage {
69+
struct HeapObject header;
70+
struct _SwiftSetBodyStorage body;
71+
__swift_uintptr_t entries;
72+
};
73+
74+
extern SWIFT_RUNTIME_STDLIB_INTERFACE
75+
struct _SwiftEmptyDictionaryStorage _swiftEmptyDictionaryStorage;
76+
77+
extern SWIFT_RUNTIME_STDLIB_INTERFACE
78+
struct _SwiftEmptySetStorage _swiftEmptySetStorage;
79+
4280
struct _SwiftHashingSecretKey {
4381
__swift_uint64_t key0;
4482
__swift_uint64_t key1;

stdlib/public/core/HashedCollections.swift.gyb

Lines changed: 9 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2473,6 +2473,11 @@ collections = [
24732473
/// keys, followed by the values.
24742474
//
24752475
// See the docs at the top of the file for more details on this type
2476+
//
2477+
// NOTE: The precise layout of this type is relied on in the runtime
2478+
// to provide a statically allocated empty singleton.
2479+
// See stdlib/public/stubs/GlobalObjects.cpp for details.
2480+
@objc_non_lazy_realization
24762481
internal class _RawNative${Self}Storage:
24772482
_SwiftNativeNS${Self}, _NS${Self}Core
24782483
{
@@ -2496,31 +2501,10 @@ internal class _RawNative${Self}Storage:
24962501
/// The empty singleton that is used for every single Dictionary that is
24972502
/// created without any elements. The contents of the storage should never
24982503
/// be mutated.
2499-
// FIXME: this should be set up in rodata like the Array singleton
2500-
internal static let empty: RawStorage = {
2501-
let storage = Builtin.allocWithTailElems_1(RawStorage.self,
2502-
1._builtinWordValue, UInt.self)
2503-
2504-
// We set the capacity to 1 so that there's an empty hole to search.
2505-
// Any insertion will lead to a real storage being allocated, because
2506-
// Dictionary guarantees there's always another empty hole after insertion.
2507-
storage.capacity = 1
2508-
storage.count = 0
2509-
2510-
// Initialize pointers to garbage; they should never be loaded
2511-
storage.keys = UnsafeMutableRawPointer(bitPattern: 1)!
2512-
% if Self == 'Dictionary':
2513-
storage.values = UnsafeMutableRawPointer(bitPattern: 1)!
2514-
% end
2515-
2516-
let initializedEntries = _UnsafeBitMap(
2517-
storage: storage._initializedHashtableEntriesBitMapBuffer,
2518-
bitCount: 1)
2519-
initializedEntries.initializeToZero()
2520-
2521-
storage.initializedEntries = initializedEntries
2522-
return storage
2523-
}()
2504+
internal static var empty: RawStorage {
2505+
return Builtin.bridgeFromRawPointer(
2506+
Builtin.addressof(&_swiftEmpty${Self}Storage))
2507+
}
25242508

25252509
// This type is made with allocWithTailElems, so no init is ever called.
25262510
// But we still need to have an init to satisfy the compiler.

stdlib/public/stubs/GlobalObjects.cpp

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,14 @@ namespace swift {
2626
// _direct type metadata for Swift._EmptyArrayStorage
2727
SWIFT_RUNTIME_STDLIB_INTERFACE
2828
extern "C" ClassMetadata _TMCs18_EmptyArrayStorage;
29+
30+
// _direct type metadata for Swift._RawNativeDictionaryStorage
31+
SWIFT_RUNTIME_STDLIB_INTERFACE
32+
extern "C" ClassMetadata _TMCs27_RawNativeDictionaryStorage;
33+
34+
// _direct type metadata for Swift._RawNativeSetStorage
35+
SWIFT_RUNTIME_STDLIB_INTERFACE
36+
extern "C" ClassMetadata _TMCs20_RawNativeSetStorage;
2937
}
3038

3139
swift::_SwiftEmptyArrayStorage swift::_swiftEmptyArrayStorage = {
@@ -41,6 +49,62 @@ swift::_SwiftEmptyArrayStorage swift::_swiftEmptyArrayStorage = {
4149
}
4250
};
4351

52+
53+
54+
swift::_SwiftEmptyDictionaryStorage swift::_swiftEmptyDictionaryStorage = {
55+
// HeapObject header;
56+
{
57+
&_TMCs27_RawNativeDictionaryStorage, // isa pointer
58+
},
59+
60+
// _SwiftDictionaryBodyStorage body;
61+
{
62+
// We set the capacity to 1 so that there's an empty hole to search.
63+
// Any insertion will lead to a real storage being allocated, because
64+
// Dictionary guarantees there's always another empty hole after insertion.
65+
1, // int capacity;
66+
0, // int count;
67+
68+
// _SwiftUnsafeBitMap initializedEntries
69+
{
70+
&swift::_swiftEmptyDictionaryStorage.entries, // unsigned int* values;
71+
1 // int bitCount; (1 so there's something for iterators to read)
72+
},
73+
74+
(void*)1, // void* keys; (non-null garabage)
75+
(void*)1 // void* values; (non-null garbage)
76+
},
77+
78+
0 // int entries; (zero'd bits)
79+
};
80+
81+
82+
swift::_SwiftEmptySetStorage swift::_swiftEmptySetStorage = {
83+
// HeapObject header;
84+
{
85+
&_TMCs20_RawNativeSetStorage, // isa pointer
86+
},
87+
88+
// _SwiftDictionaryBodyStorage body;
89+
{
90+
// We set the capacity to 1 so that there's an empty hole to search.
91+
// Any insertion will lead to a real storage being allocated, because
92+
// Dictionary guarantees there's always another empty hole after insertion.
93+
1, // int capacity;
94+
0, // int count;
95+
96+
// _SwiftUnsafeBitMap initializedEntries
97+
{
98+
&swift::_swiftEmptySetStorage.entries, // unsigned int* values;
99+
1 // int bitCount; (1 so there's something for iterators to read)
100+
},
101+
102+
(void*)1 // void* keys; (non-null garabage)
103+
},
104+
105+
0 // int entries; (zero'd bits)
106+
};
107+
44108
static __swift_uint64_t randomUInt64() {
45109
#if defined(__APPLE__)
46110
return static_cast<__swift_uint64_t>(arc4random()) |

0 commit comments

Comments
 (0)