Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
The beginnings
  • Loading branch information
grendello committed Feb 14, 2024
commit 9a3a2ecfc0f4676466ed1d6746a9bf948bc1a30e
3 changes: 2 additions & 1 deletion build-tools/scripts/generate-pinvoke-tables.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ GENERATOR_BINARY="${MONODROID_SOURCE_DIR}/generate-pinvoke-tables"
TARGET_FILE="${MONODROID_SOURCE_DIR}/pinvoke-tables.include"
GENERATED_FILE="${TARGET_FILE}.generated"
DIFF_FILE="${TARGET_FILE}.diff"
EXTERNAL_DIR="${MY_DIR}/../../external/"

function die()
{
Expand Down Expand Up @@ -62,7 +63,7 @@ case ${HOST} in
*) die Unsupported OS ;;
esac

${COMPILER} -O2 -std=c++20 "${GENERATOR_SOURCE}" -o "${GENERATOR_BINARY}"
${COMPILER} -O2 -std=c++20 -I${EXTERNAL_DIR}/xxHash -I${EXTERNAL_DIR}/constexpr-xxh3 "${GENERATOR_SOURCE}" -o "${GENERATOR_BINARY}"
"${GENERATOR_BINARY}" "${GENERATED_FILE}"

FILES_DIFFER="no"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public AssemblyStoreIndexEntry (string name, uint blobID, uint mappingIndex, uin

byte[] nameBytes = Encoding.UTF8.GetBytes (name);
NameHash32 = XxHash32.HashToUInt32 (nameBytes);
NameHash64 = XxHash64.HashToUInt64 (nameBytes);
NameHash64 = XxHash3.HashToUInt64 (nameBytes);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public static ulong GetXxHash (string str, bool is64Bit)
{
byte[] stringBytes = Encoding.UTF8.GetBytes (str);
if (is64Bit) {
return XxHash64.HashToUInt64 (stringBytes);
return XxHash3.HashToUInt64 (stringBytes);
}

return (ulong)XxHash32.HashToUInt32 (stringBytes);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,16 +415,7 @@ ulong HashName (string name, bool is64Bit)

// Native code (EmbeddedAssemblies::typemap_java_to_managed in embedded-assemblies.cc) will operate on wchar_t cast to a byte array, we need to do
// the same
return HashBytes (Encoding.Unicode.GetBytes (name), is64Bit);
}

ulong HashBytes (byte[] bytes, bool is64Bit)
{
if (is64Bit) {
return XxHash64.HashToUInt64 (bytes);
}

return (ulong)XxHash32.HashToUInt32 (bytes);
return GetXxHash (name, is64Bit);
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/monodroid/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,8 @@ set(LZ4_INCLUDE_DIR ${LZ4_SRC_DIR})
set(XA_BIN_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/${XA_BUILD_CONFIGURATION}")
set(XA_BUILD_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../bin/Build${XA_BUILD_CONFIGURATION}")
set(ROBIN_MAP_DIR "${EXTERNAL_DIR}/robin-map")
set(XXHASH_DIR "${EXTERNAL_DIR}/xxHash")
set(CONSTEXPR_XXH3_DIR "${EXTERNAL_DIR}/constexpr-xxh3")

if(NOT ANDROID)
if(WIN32 OR MINGW)
Expand Down Expand Up @@ -202,6 +204,8 @@ set(LZ4_SOURCES
# Include directories
include_directories(${CMAKE_CURRENT_BINARY_DIR}/include/ ${CMAKE_SOURCE_DIR}/include)
include_directories(${ROBIN_MAP_DIR}/include)
include_directories(${EXTERNAL_DIR})
include_directories(${CONSTEXPR_XXH3_DIR})

if(NOT ANDROID)
string(REPLACE " " ";" JDK_INCLUDE_LIST ${JDK_INCLUDE})
Expand Down
8 changes: 4 additions & 4 deletions src/monodroid/jni/generate-pinvoke-tables.cc
Original file line number Diff line number Diff line change
Expand Up @@ -688,9 +688,9 @@ struct constexpr_test {

constexpr_test<xxhash32::hash<0> ("", 0), 0x2CC5D05U> constexprTest_1;
constexpr_test<xxhash32::hash<2654435761U> ("", 0), 0x36B78AE7U> constexprTest_2;
constexpr_test<xxhash64::hash<0> ("", 0), 0xEF46DB3751D8E999ULL> constexprTest_3;
constexpr_test<xxhash64::hash<2654435761U> ("", 0), 0xAC75FDA2929B17EFULL> constexprTest_4;
//constexpr_test<xxhash64::hash<0> ("", 0), 0xEF46DB3751D8E999ULL> constexprTest_3;
//constexpr_test<xxhash64::hash<2654435761U> ("", 0), 0xAC75FDA2929B17EFULL> constexprTest_4;
constexpr_test<xxhash32::hash<0> ("test", 4), 0x3E2023CFU> constexprTest32_5;
constexpr_test<xxhash32::hash<2654435761U> ("test", 4), 0xA9C14438U> constexprTest32_6;
constexpr_test<xxhash64::hash<0> ("test", 4), 0x4fdcca5ddb678139ULL> constexprTest64_7;
constexpr_test<xxhash64::hash<2654435761U> ("test", 4), 0x5A183B8150E2F651ULL> constexprTest64_8;
//constexpr_test<xxhash64::hash<0> ("test", 4), 0x4fdcca5ddb678139ULL> constexprTest64_7;
//constexpr_test<xxhash64::hash<2654435761U> ("test", 4), 0x5A183B8150E2F651ULL> constexprTest64_8;
964 changes: 482 additions & 482 deletions src/monodroid/jni/pinvoke-tables.include

Large diffs are not rendered by default.

4 changes: 0 additions & 4 deletions src/monodroid/jni/platform-compat.hh
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@ typedef struct dirent monodroid_dirent_t;
#define never_inline
#endif

#ifndef inline
#define inline inline
#endif

#ifndef XA_LIKELY
#define XA_LIKELY(expr) (expr)
#endif
Expand Down
120 changes: 20 additions & 100 deletions src/monodroid/jni/xxhash.hh
Original file line number Diff line number Diff line change
@@ -1,6 +1,16 @@
#if !defined (__XXHASH_HH)
#define __XXHASH_HH

#if INTPTR_MAX == INT64_MAX
#define XXH_NO_STREAM
#define XXH_INLINE_ALL
#define XXH_NAMESPACE xaInternal_
#include <xxHash/xxhash.h>
#include <constexpr-xxh3.h>
#endif

#include <type_traits>

//
// Based on original code at https://github.com/ekpyron/xxhashct
//
Expand Down Expand Up @@ -135,116 +145,26 @@ namespace xamarin::android
}
};

#if INTPTR_MAX == INT64_MAX
class xxhash64 final
{
static constexpr uint64_t PRIME1 = 11400714785074694791ULL;
static constexpr uint64_t PRIME2 = 14029467366897019727ULL;
static constexpr uint64_t PRIME3 = 1609587929392839161ULL;
static constexpr uint64_t PRIME4 = 9650029242287828579ULL;
static constexpr uint64_t PRIME5 = 2870177450012600261ULL;

public:
// We don't use any special seed in XA, the template parameter is just to keep the algorithm more easily
// understood and to run compile-time algorithm correctness tests
template<uint64_t Seed = 0>
force_inline static constexpr uint64_t hash (const char *p, size_t len) noexcept
{
return finalize ((len >= 32 ? h32bytes<Seed> (p, len) : Seed + PRIME5) + len, p + (len & ~0x1FU), len & 0x1F);
}

template<size_t Size, uint64_t Seed = 0>
force_inline static constexpr uint64_t hash (const char (&input)[Size]) noexcept
{
return hash<Seed> (input, Size - 1);
}

private:
template<int Bits>
force_inline static constexpr uint64_t rotl (uint64_t x) noexcept
{
return ((x << Bits) | (x >> (64 - Bits)));
}

template<int RShift>
force_inline static constexpr uint64_t mix1 (const uint64_t h, const uint64_t prime) noexcept
{
return (h ^ (h >> RShift)) * prime;
}

force_inline static constexpr uint64_t mix2 (const uint64_t p, const uint64_t v = 0) noexcept
{
return rotl<31> (v + p * PRIME2) * PRIME1;
}

force_inline static constexpr uint64_t mix3 (const uint64_t h, const uint64_t v) noexcept
{
return (h ^ mix2 (v)) * PRIME1 + PRIME4;
}

// little-endian versions: all our target platforms are little-endian
force_inline static constexpr uint32_t endian32 (const char *v) noexcept
force_inline static constexpr XXH64_hash_t hash (const char *p, size_t len) noexcept
{
return
static_cast<uint32_t>(static_cast<uint8_t>(v[0])) |
(static_cast<uint32_t>(static_cast<uint8_t>(v[1])) << 8) |
(static_cast<uint32_t>(static_cast<uint8_t>(v[2])) << 16) |
(static_cast<uint32_t>(static_cast<uint8_t>(v[3])) << 24);
return XXH3_64bits (static_cast<const void*>(p), len);
}

force_inline static constexpr uint64_t endian64 (const char *v)
// The C XXH64_64bits function from xxhash.h is not `constexpr` or `consteval`, so we cannot call it here.
// At the same time, at build time performance is not that important, so we call the "unoptmized" `consteval`
// C++ implementation here
template<size_t Size>
force_inline static consteval XXH64_hash_t hash (const char (&input)[Size]) noexcept
{
return
static_cast<uint64_t>(static_cast<uint8_t>(v[0])) |
(static_cast<uint64_t>(static_cast<uint8_t>(v[1])) << 8) |
(static_cast<uint64_t>(static_cast<uint8_t>(v[2])) << 16) |
(static_cast<uint64_t>(static_cast<uint8_t>(v[3])) << 24) |
(static_cast<uint64_t>(static_cast<uint8_t>(v[4])) << 32) |
(static_cast<uint64_t>(static_cast<uint8_t>(v[5])) << 40) |
(static_cast<uint64_t>(static_cast<uint8_t>(v[6])) << 48) |
(static_cast<uint64_t>(static_cast<uint8_t>(v[7])) << 56);
}

force_inline static constexpr uint64_t fetch64 (const char *p, const uint64_t v = 0) noexcept
{
return mix2 (endian64 (p), v);
}

force_inline static constexpr uint64_t fetch32 (const char *p) noexcept
{
return static_cast<uint64_t>(endian32 (p)) * PRIME1;
}

force_inline static constexpr uint64_t fetch8 (const char *p) noexcept
{
return static_cast<uint8_t> (*p) * PRIME5;
}

force_inline static constexpr uint64_t finalize (const uint64_t h, const char *p, size_t len) noexcept
{
return
(len >= 8) ? (finalize (rotl<27> (h ^ fetch64 (p)) * PRIME1 + PRIME4, p + 8, len - 8)) :
((len >= 4) ? (finalize (rotl<23> (h ^ fetch32 (p)) * PRIME2 + PRIME3, p + 4, len - 4)) :
((len > 0) ? (finalize (rotl<11> (h ^ fetch8 (p)) * PRIME1, p + 1, len - 1)) :
(mix1<32> (mix1<29> (mix1<33> (h, PRIME2), PRIME3), 1))));
}

force_inline static constexpr uint64_t h32bytes (const char *p, size_t len, const uint64_t v1,const uint64_t v2, const uint64_t v3, const uint64_t v4) noexcept
{
return (len >= 32) ? h32bytes (p + 32, len - 32, fetch64 (p, v1), fetch64 (p + 8, v2), fetch64 (p + 16, v3), fetch64 (p + 24, v4)) :
mix3 (mix3 (mix3 (mix3 (rotl<1> (v1) + rotl<7> (v2) + rotl<12> (v3) + rotl<18> (v4), v1), v2), v3), v4);
}

// We don't use any special seed in XA, the template parameter is just to keep the algorithm more easily
// understood
template<uint64_t Seed = 0>
force_inline static constexpr uint64_t h32bytes (const char *p, size_t len) noexcept
{
return h32bytes (p, len, Seed + PRIME1 + PRIME2, Seed + PRIME2, Seed, Seed - PRIME1);
return constexpr_xxh3::XXH3_64bits_const (input);
}
};

#if INTPTR_MAX == INT64_MAX
using hash_t = uint64_t;
using hash_t = XXH64_hash_t;
using xxhash = xxhash64;
#else
using hash_t = uint32_t;
Expand Down