Loading...
--- dyld/dyld-1340/common/PerfectHash.cpp
+++ dyld/dyld-1066.8/common/PerfectHash.cpp
@@ -40,18 +40,12 @@
------------------------------------------------------------------------------
*/
-#include <TargetConditionals.h>
-
-#if !TARGET_OS_EXCLAVEKIT
-
-#include <strings.h>
#include "PerfectHash.h"
#if BUILDING_CACHE_BUILDER || BUILDING_UNIT_TESTS || BUILDING_CACHE_BUILDER_UNIT_TESTS
+#include <dispatch/dispatch.h>
#include <string>
#include <vector>
-
-#include "Algorithm.h"
#endif
namespace objc {
@@ -184,8 +178,6 @@
return c;
}
-#if BUILDING_CACHE_BUILDER || BUILDING_UNIT_TESTS || BUILDING_CACHE_BUILDER_UNIT_TESTS
-
/*
------------------------------------------------------------------------------
This generates a minimal perfect hash function. That means, given a
@@ -334,17 +326,19 @@
* put keys in tabb according to key->b_k
* check if the initial hash might work
*/
-static int inittab(dyld3::OverflowSafeArray<bstuff>& tabb, std::span<key> keys)
+static int inittab(dyld3::OverflowSafeArray<bstuff>& tabb, dyld3::OverflowSafeArray<key>& keys, int complete)
// bstuff *tabb; /* output, list of keys with b for (a,b) */
// ub4 blen; /* length of tabb */
// key *keys; /* list of keys already hashed */
-{
+// int complete; /* TRUE means to complete init despite collisions */
+{
+ int nocollision = TRUE;
ub4 i;
- memset((void *)tabb.data(), 0, (size_t)(sizeof(bstuff)*tabb.count()));
+ memset((void *)tabb.begin(), 0, (size_t)(sizeof(bstuff)*tabb.maxCount()));
/* Two keys with the same (a,b) guarantees a collision */
- for (i = 0; i < keys.size(); i++) {
+ for (i = 0; i < keys.count(); i++) {
key *mykey = &keys[i];
key *otherkey;
@@ -354,7 +348,9 @@
{
if (mykey->a_k == otherkey->a_k)
{
- return FALSE;
+ nocollision = FALSE;
+ if (!complete)
+ return FALSE;
}
}
++tabb[mykey->b_k].listlen_b;
@@ -363,12 +359,12 @@
}
/* no two keys have the same (a,b) pair */
- return true;
+ return nocollision;
}
/* Do the initial hash for normal mode (use lookup and checksum) */
-static void initnorm(std::span<key> allKeys, ub4 alen, ub4 blen, ub4 smax, ub8 salt)
+static void initnorm(dyld3::OverflowSafeArray<key>& keys, ub4 alen, ub4 blen, ub4 smax, ub8 salt)
// key *keys; /* list of all keys */
// ub4 alen; /* (a,b) has a in 0..alen-1, a power of 2 */
// ub4 blen; /* (a,b) has b in 0..blen-1, a power of 2 */
@@ -377,18 +373,27 @@
// gencode *final; /* output, code for the final hash */
{
ub4 loga = log2u(alen); /* log based 2 of blen */
- size_t chunkSize = 0x2000;
- mapReduce(allKeys, chunkSize, ^(size_t chunkIndex, int&, std::span<key> keys) {
- for ( auto& mykey : keys ) {
- ub8 hash = lookup8(mykey.name1_k, mykey.len1_k, salt);
- if ( mykey.name2_k != nullptr ) {
- ub8 hash2 = lookup8(mykey.name2_k, mykey.len2_k, salt);
- hash = hash ^ hash2;
- }
- mykey.a_k = (loga > 0) ? (ub4)(hash >> (UB8BITS-loga)) : 0;
- mykey.b_k = (blen > 1) ? (hash & (blen-1)) : 0;
+#if BUILDING_CACHE_BUILDER || BUILDING_UNIT_TESTS || BUILDING_CACHE_BUILDER_UNIT_TESTS
+ dispatch_apply(keys.count(), DISPATCH_APPLY_AUTO, ^(size_t index) {
+ ub4 i = (ub4)index;
+ key *mykey = &keys[i];
+ ub8 hash = lookup8(mykey->name1_k, mykey->len1_k, salt);
+ if ( mykey->name2_k != nullptr ) {
+ ub8 hash2 = lookup8(mykey->name2_k, mykey->len2_k, salt);
+ hash = hash ^ hash2;
}
+ mykey->a_k = (loga > 0) ? (ub4)(hash >> (UB8BITS-loga)) : 0;
+ mykey->b_k = (blen > 1) ? (hash & (blen-1)) : 0;
});
+#else
+ for (size_t index = 0; index != keys.count(); ++index) {
+ ub4 i = (ub4)index;
+ key *mykey = &keys[i];
+ ub8 hash = lookup8(mykey->name_k, mykey->len_k, salt);
+ mykey->a_k = (loga > 0) ? (ub4)(hash >> (UB8BITS-loga)) : 0;
+ mykey->b_k = (blen > 1) ? (hash & (blen-1)) : 0;
+ };
+#endif
}
@@ -687,7 +692,7 @@
/* Try to find distinct (A,B) for all keys */
*salt = si * 0x9e3779b97f4a7c13LL; /* golden ratio (arbitrary value) */
initnorm(keys, *alen, blen, smax, *salt);
- rslinit = inittab(tabb, keys);
+ rslinit = inittab(tabb, keys, FALSE);
if (rslinit == 0)
{
/* didn't find distinct (a,b) */
@@ -779,6 +784,8 @@
}
}
+#if BUILDING_CACHE_BUILDER || BUILDING_UNIT_TESTS || BUILDING_CACHE_BUILDER_UNIT_TESTS
+
void PerfectHash::make_perfect(const std::vector<ObjCString>& strings, objc::PerfectHash& phash)
{
dyld3::OverflowSafeArray<key> keys;
@@ -799,8 +806,29 @@
make_perfect(keys, phash);
}
-#endif // BUILDING_CACHE_BUILDER || BUILDING_UNIT_TESTS || BUILDING_CACHE_BUILDER_UNIT_TESTS
+#endif
+
+void PerfectHash::make_perfect(const dyld3::OverflowSafeArray<const char*>& strings, objc::PerfectHash& phash)
+{
+ dyld3::OverflowSafeArray<key> keys;
+
+ /* read in the list of keywords */
+ keys.reserve(strings.count());
+ for (const char* s : strings) {
+ key mykey;
+#if BUILDING_CACHE_BUILDER || BUILDING_UNIT_TESTS || BUILDING_CACHE_BUILDER_UNIT_TESTS
+ mykey.name1_k = (ub1 *)s;
+ mykey.len1_k = (ub4)strlen(s);
+ mykey.name2_k = (ub1 *)nullptr;
+ mykey.len2_k = (ub4)0;
+#else
+ mykey.name_k = (ub1 *)s;
+ mykey.len_k = (ub4)strlen(s);
+#endif
+ keys.push_back(mykey);
+ }
+
+ make_perfect(keys, phash);
+}
} // namespace objc
-
-#endif // !TARGET_OS_EXCLAVEKIT