From ef007519b180c6c3e20dce1b70696b11689742c4 Mon Sep 17 00:00:00 2001 From: Erik Eckstein Date: Wed, 22 Jan 2020 14:49:01 +0100 Subject: [PATCH] stdlib: move Dictionary's find functions into __RawDictionaryStorage. The find functions do not require the generic Value parameter. Moving them to __RawDictionaryStorage allows to define them with only one generic parameter: the Key. This allows the optimizer to share specializations for dictionaries which have the same Key, but a different Value. Also, prevent inlining of the find-functions to save some additional code size. --- stdlib/public/core/DictionaryStorage.swift | 29 ++++++++++++++++++++++ stdlib/public/core/NativeDictionary.swift | 12 ++------- 2 files changed, 31 insertions(+), 10 deletions(-) diff --git a/stdlib/public/core/DictionaryStorage.swift b/stdlib/public/core/DictionaryStorage.swift index 39ac76578f126..ac931fd2ed51c 100644 --- a/stdlib/public/core/DictionaryStorage.swift +++ b/stdlib/public/core/DictionaryStorage.swift @@ -196,6 +196,35 @@ extension __RawDictionaryStorage { return Builtin.bridgeFromRawPointer( Builtin.addressof(&_swiftEmptyDictionarySingleton)) } + + @_alwaysEmitIntoClient + @inline(__always) + internal final func uncheckedKey(at bucket: _HashTable.Bucket) -> Key { + defer { _fixLifetime(self) } + _internalInvariant(_hashTable.isOccupied(bucket)) + let keys = _rawKeys.assumingMemoryBound(to: Key.self) + return keys[bucket.offset] + } + + @_alwaysEmitIntoClient + @inline(never) + internal final func find(_ key: Key) -> (bucket: _HashTable.Bucket, found: Bool) { + return find(key, hashValue: key._rawHashValue(seed: _seed)) + } + + @_alwaysEmitIntoClient + @inline(never) + internal final func find(_ key: Key, hashValue: Int) -> (bucket: _HashTable.Bucket, found: Bool) { + let hashTable = _hashTable + var bucket = hashTable.idealBucket(forHashValue: hashValue) + while hashTable._isOccupied(bucket) { + if uncheckedKey(at: bucket) == key { + return (bucket, true) + } + bucket = hashTable.bucket(wrappedAfter: bucket) + } + return (bucket, false) + } } @usableFromInline diff --git a/stdlib/public/core/NativeDictionary.swift b/stdlib/public/core/NativeDictionary.swift index 4dcbd68ce642d..6aa6a45a03dbc 100644 --- a/stdlib/public/core/NativeDictionary.swift +++ b/stdlib/public/core/NativeDictionary.swift @@ -161,7 +161,7 @@ extension _NativeDictionary { // Low-level lookup operations @inlinable @inline(__always) internal func find(_ key: Key) -> (bucket: Bucket, found: Bool) { - return find(key, hashValue: self.hashValue(for: key)) + return _storage.find(key) } /// Search for a given element, assuming it has the specified hash value. @@ -174,15 +174,7 @@ extension _NativeDictionary { // Low-level lookup operations _ key: Key, hashValue: Int ) -> (bucket: Bucket, found: Bool) { - let hashTable = self.hashTable - var bucket = hashTable.idealBucket(forHashValue: hashValue) - while hashTable._isOccupied(bucket) { - if uncheckedKey(at: bucket) == key { - return (bucket, true) - } - bucket = hashTable.bucket(wrappedAfter: bucket) - } - return (bucket, false) + return _storage.find(key, hashValue: hashValue) } }