diff options
Diffstat (limited to 'source/core')
| -rw-r--r-- | source/core/slang-dictionary.h | 14 | ||||
| -rw-r--r-- | source/core/slang-downstream-compiler.h | 2 | ||||
| -rw-r--r-- | source/core/slang-hash.h | 116 | ||||
| -rw-r--r-- | source/core/slang-hex-dump-util.cpp | 10 | ||||
| -rw-r--r-- | source/core/slang-math.h | 21 | ||||
| -rw-r--r-- | source/core/slang-riff.cpp | 18 | ||||
| -rw-r--r-- | source/core/slang-riff.h | 6 | ||||
| -rw-r--r-- | source/core/slang-smart-pointer.h | 6 | ||||
| -rw-r--r-- | source/core/slang-string.h | 8 | ||||
| -rw-r--r-- | source/core/slang-text-io.cpp | 6 | ||||
| -rw-r--r-- | source/core/slang-uint-set.cpp | 2 | ||||
| -rw-r--r-- | source/core/slang-uint-set.h | 3 |
12 files changed, 141 insertions, 71 deletions
diff --git a/source/core/slang-dictionary.h b/source/core/slang-dictionary.h index be7cc21f5..72b24f81c 100644 --- a/source/core/slang-dictionary.h +++ b/source/core/slang-dictionary.h @@ -54,11 +54,11 @@ namespace Slang Value = that.Value; return *this; } - int GetHashCode() + HashCode getHashCode() { return combineHash( - Slang::GetHashCode(Key), - Slang::GetHashCode(Value)); + Slang::getHashCode(Key), + Slang::getHashCode(Value)); } bool operator==(const KeyValuePair<TKey, TValue>& that) const { @@ -135,8 +135,10 @@ namespace Slang }; inline int GetHashPos(TKey& key) const - { - return ((unsigned int)(GetHashCode(key) * 2654435761)) % bucketSizeMinusOne; + { + SLANG_ASSERT(bucketSizeMinusOne > 0); + const unsigned int hash = (unsigned int)getHashCode(key); + return (hash * 2654435761u) % (unsigned int)(bucketSizeMinusOne); } FindPositionResult FindPosition(const TKey& key) const { @@ -166,7 +168,7 @@ namespace Slang } if (insertPos != -1) return FindPositionResult(-1, insertPos); - throw InvalidOperationException("Hash map is full. This indicates an error in Key::Equal or Key::GetHashCode."); + throw InvalidOperationException("Hash map is full. This indicates an error in Key::Equal or Key::getHashCode."); } TValue & _Insert(KeyValuePair<TKey, TValue>&& kvPair, int pos) { diff --git a/source/core/slang-downstream-compiler.h b/source/core/slang-downstream-compiler.h index bcf53d065..f43c4b560 100644 --- a/source/core/slang-downstream-compiler.h +++ b/source/core/slang-downstream-compiler.h @@ -154,7 +154,7 @@ public: { typedef Desc ThisType; - UInt GetHashCode() const { return combineHash(int(type), combineHash(int(majorVersion), int(minorVersion))); } + HashCode getHashCode() const { return combineHash(HashCode(type), combineHash(HashCode(majorVersion), HashCode(minorVersion))); } bool operator==(const ThisType& rhs) const { return type == rhs.type && majorVersion == rhs.majorVersion && minorVersion == rhs.minorVersion; } bool operator!=(const ThisType& rhs) const { return !(*this == rhs); } diff --git a/source/core/slang-hash.h b/source/core/slang-hash.h index 08a40491c..5a0766c98 100644 --- a/source/core/slang-hash.h +++ b/source/core/slang-hash.h @@ -7,56 +7,102 @@ namespace Slang { - typedef int HashCode; + // Ideally Hash codes should be unsigned types - makes accumulation simpler (as overflow/underflow behavior are defined) + // Only downside is around multiply, where unsigned multiply can be slightly slower on some targets. - inline int GetHashCode(double key) + // HashCode - size may vary by platform. Typically has 'best' combination of bits/performance. Should not be exposed externally as value from same input may change depending on compilation platform. + typedef unsigned int HashCode; + + // A fixed 64bit wide hash on all targets. + typedef uint64_t HashCode64; + // A fixed 32bit wide hash on all targets. + typedef uint32_t HashCode32; + + SLANG_FORCE_INLINE HashCode32 toHash32(HashCode value) { return (sizeof(HashCode) == sizeof(int64_t)) ? (HashCode32(uint64_t(value) >> 32) ^ HashCode(value)) : HashCode32(value); } + SLANG_FORCE_INLINE HashCode64 toHash64(HashCode value) { return (sizeof(HashCode) == sizeof(int64_t)) ? HashCode(value) : ((HashCode64(value) << 32) | value); } + + SLANG_FORCE_INLINE HashCode getHashCode(int64_t value) + { + return (sizeof(HashCode) == sizeof(int64_t)) ? HashCode(value) : (HashCode(uint64_t(value) >> 32) ^ HashCode(value)); + } + SLANG_FORCE_INLINE HashCode getHashCode(uint64_t value) + { + return (sizeof(HashCode) == sizeof(uint64_t)) ? HashCode(value) : (HashCode(value >> 32) ^ HashCode(value)); + } + + inline HashCode getHashCode(double key) { - return FloatAsInt((float)key); + return getHashCode(DoubleAsInt64(key)); } - inline int GetHashCode(float key) + inline HashCode getHashCode(float key) { return FloatAsInt(key); - } - inline int GetHashCode(const char * buffer) + } + inline HashCode getHashCode(const char* buffer) { if (!buffer) return 0; - int hash = 0; - int c; + HashCode hash = 0; auto str = buffer; - c = *str++; + HashCode c = HashCode(*str++); while (c) { hash = c + (hash << 6) + (hash << 16) - hash; - c = *str++; + c = HashCode(*str++); } return hash; - } - inline int GetHashCode(char * buffer) + } + inline HashCode getHashCode(char* buffer) { - return GetHashCode(const_cast<const char *>(buffer)); + return getHashCode(const_cast<const char *>(buffer)); } - inline int GetHashCode(const char * buffer, size_t numChars) + inline HashCode getHashCode(const char* buffer, size_t numChars) { - int hash = 0; + HashCode hash = 0; for (size_t i = 0; i < numChars; ++i) { - hash = int(buffer[i]) + (hash << 6) + (hash << 16) - hash; + hash = HashCode(buffer[i]) + (hash << 6) + (hash << 16) - hash; } return hash; } - inline uint64_t GetHashCode64(const char * buffer, size_t numChars) + /* The 'Stable' hash code functions produce hashes that must be + + * The same result for the same inputs on all targets + * Rarely change - as their values can change the output of the Slang API/Serialization + + Hash value used from the 'Stable' functions can also be used as part of serialization - + so it is in effect part of the API. + + In effect this means changing a 'Stable' algorithm will typically require doing a new release. + */ + inline HashCode32 getStableHashCode32(const char* buffer, size_t numChars) + { + HashCode32 hash = 0; + for (size_t i = 0; i < numChars; ++i) + { + hash = HashCode32(buffer[i]) + (hash << 6) + (hash << 16) - hash; + } + return hash; + } + + inline HashCode64 getStableHashCode64(const char* buffer, size_t numChars) { - // Use uints because hash requires wrap around behavior and int is undefined on over/underflows - uint64_t hash = 0; + // Use HashCode64 is assumed unsigned because hash requires wrap around behavior and int is undefined on over/underflows + HashCode64 hash = 0; for (size_t i = 0; i < numChars; ++i) { - hash = uint64_t(int64_t(buffer[i])) + (hash << 6) + (hash << 16) - hash; + hash = HashCode64(HashCode64(buffer[i])) + (hash << 6) + (hash << 16) - hash; } return hash; } + // Hash functions with specific sized results + // TODO(JS): We might want to implement HashCode as just an alias a suitable Hash32/Hash32 based on target. + // For now just use Stable for 64bit. + SLANG_FORCE_INLINE HashCode64 getHashCode64(const char* buffer, size_t numChars) { return getStableHashCode64(buffer, numChars); } + SLANG_FORCE_INLINE HashCode32 getHashCode32(const char* buffer, size_t numChars) { return toHash32(getHashCode(buffer, numChars)); } + template<int IsInt> class Hash { @@ -67,9 +113,9 @@ namespace Slang { public: template<typename TKey> - static int GetHashCode(TKey & key) + static HashCode getHashCode(TKey& key) { - return (int)key; + return (HashCode)key; } }; template<> @@ -77,9 +123,9 @@ namespace Slang { public: template<typename TKey> - static int GetHashCode(TKey & key) + static HashCode getHashCode(TKey& key) { - return int(key.GetHashCode()); + return HashCode(key.getHashCode()); } }; template<int IsPointer> @@ -90,9 +136,9 @@ namespace Slang { public: template<typename TKey> - static int GetHashCode(TKey const& key) + static HashCode getHashCode(TKey const& key) { - return (int)((PtrInt)key) / 16; // sizeof(typename std::remove_pointer<TKey>::type); + return (HashCode)((PtrInt)key) / 16; // sizeof(typename std::remove_pointer<TKey>::type); } }; template<> @@ -100,25 +146,25 @@ namespace Slang { public: template<typename TKey> - static int GetHashCode(TKey & key) + static HashCode getHashCode(TKey& key) { - return Hash<std::is_integral<TKey>::value || std::is_enum<TKey>::value>::GetHashCode(key); + return Hash<std::is_integral<TKey>::value || std::is_enum<TKey>::value>::getHashCode(key); } }; template<typename TKey> - int GetHashCode(const TKey & key) + HashCode getHashCode(const TKey& key) { - return PointerHash<std::is_pointer<TKey>::value>::GetHashCode(key); + return PointerHash<std::is_pointer<TKey>::value>::getHashCode(key); } template<typename TKey> - int GetHashCode(TKey & key) + HashCode getHashCode(TKey& key) { - return PointerHash<std::is_pointer<TKey>::value>::GetHashCode(key); + return PointerHash<std::is_pointer<TKey>::value>::getHashCode(key); } - inline int combineHash(int left, int right) + inline HashCode combineHash(HashCode left, HashCode right) { return (left * 16777619) ^ right; } @@ -131,13 +177,13 @@ namespace Slang template<typename T> void hashValue(T const& value) { - m_hashCode = combineHash(m_hashCode, GetHashCode(value)); + m_hashCode = combineHash(m_hashCode, getHashCode(value)); } template<typename T> void hashObject(T const& object) { - m_hashCode = combineHash(m_hashCode, object->GetHashCode()); + m_hashCode = combineHash(m_hashCode, object->getHashCode()); } HashCode getResult() const diff --git a/source/core/slang-hex-dump-util.cpp b/source/core/slang-hex-dump-util.cpp index 69c6d3f21..cb7187499 100644 --- a/source/core/slang-hex-dump-util.cpp +++ b/source/core/slang-hex-dump-util.cpp @@ -26,8 +26,8 @@ static const char s_hex[] = "0123456789abcdef"; SLANG_RETURN_ON_FAIL(helper.write(s_start.begin(), s_start.getLength())); SLANG_RETURN_ON_FAIL(helper.print(" %zu", dataCount)); - const int hash = GetHashCode((const char*)data, dataCount); - SLANG_RETURN_ON_FAIL(helper.print(" %d\n", hash )); + const HashCode32 hash = getStableHashCode32((const char*)data, dataCount); + SLANG_RETURN_ON_FAIL(helper.print(" %d\n", int(hash) )); SLANG_RETURN_ON_FAIL(dump(data, dataCount, maxBytesPerLine, writer)); @@ -191,7 +191,7 @@ static SlangResult _findLine(const UnownedStringSlice& find, UnownedStringSlice& UnownedStringSlice startLine, endLine; SLANG_RETURN_ON_FAIL(findStartAndEndLines(lines, startLine, endLine)); - int hash; + HashCode32 hash; size_t size; { // Get the size and the hash @@ -203,13 +203,13 @@ static SlangResult _findLine(const UnownedStringSlice& find, UnownedStringSlice& } // Extract the size size = StringToInt(String(slices[1])); - hash = int(StringToInt(String(slices[2]))); + hash = HashCode32(StringToInt(String(slices[2]))); } SLANG_RETURN_ON_FAIL(parse(UnownedStringSlice(startLine.end(), endLine.begin()), outBytes)); // Calc the hash - const int readHash = GetHashCode((const char*)outBytes.begin(), outBytes.getCount()); + const HashCode32 readHash = getStableHashCode32((const char*)outBytes.begin(), outBytes.getCount()); if (readHash != hash || size_t(outBytes.getCount()) != size) { diff --git a/source/core/slang-math.h b/source/core/slang-math.h index 7d3a741a4..2378b73a0 100644 --- a/source/core/slang-math.h +++ b/source/core/slang-math.h @@ -21,10 +21,16 @@ namespace Slang float fvalue; int ivalue; - inline static FloatIntUnion makeFromInt(int i) { FloatIntUnion cast; cast.ivalue = i; return cast; } - inline static FloatIntUnion makeFromFloat(float f) { FloatIntUnion cast; cast.fvalue = f; return cast; } + SLANG_FORCE_INLINE static FloatIntUnion makeFromInt(int i) { FloatIntUnion cast; cast.ivalue = i; return cast; } + SLANG_FORCE_INLINE static FloatIntUnion makeFromFloat(float f) { FloatIntUnion cast; cast.fvalue = f; return cast; } + }; + union DoubleInt64Union + { + double dvalue; + int64_t ivalue; + SLANG_FORCE_INLINE static DoubleInt64Union makeFromInt64(int64_t i) { DoubleInt64Union cast; cast.ivalue = i; return cast; } + SLANG_FORCE_INLINE static DoubleInt64Union makeFromDouble(double d) { DoubleInt64Union cast; cast.dvalue = d; return cast; } }; - static const float Pi; @@ -171,6 +177,15 @@ namespace Slang return Math::FloatIntUnion::makeFromInt(val).fvalue; } + SLANG_FORCE_INLINE int64_t DoubleAsInt64(double val) + { + return Math::DoubleInt64Union::makeFromDouble(val).ivalue; + } + SLANG_FORCE_INLINE double Int64AsDouble(int64_t value) + { + return Math::DoubleInt64Union::makeFromInt64(value).dvalue; + } + inline unsigned short FloatToHalf(float val) { const auto x = FloatAsInt(val); diff --git a/source/core/slang-riff.cpp b/source/core/slang-riff.cpp index da547319b..9fc23fbc8 100644 --- a/source/core/slang-riff.cpp +++ b/source/core/slang-riff.cpp @@ -32,7 +32,7 @@ namespace Slang { stream->read(&outChunk, sizeof(RiffHeader)); } - catch (IOException&) + catch (const IOException&) { return SLANG_FAIL; } @@ -77,7 +77,7 @@ namespace Slang out->write(end, padSize - payloadSize); } } - catch (IOException&) + catch (const IOException&) { return SLANG_FAIL; } @@ -99,7 +99,7 @@ namespace Slang } outReadSize = alignedSize; } - catch (IOException&) + catch (const IOException&) { return SLANG_FAIL; } @@ -126,7 +126,7 @@ namespace Slang stream->read(outHeader + 1, headerSize - sizeof(RiffHeader)); } } - catch (IOException&) + catch (const IOException&) { return SLANG_FAIL; } @@ -187,7 +187,7 @@ struct DumpVisitor : public RiffContainer::Visitor _dumpRiffType(data->m_fourCC); m_writer.put(" "); - int hash = data->calcHash(); + const RiffHashCode hash = data->calcHash(); // We don't know in general what the contents is or means... but we can display a hash HexDumpUtil::dump(uint32_t(hash), m_writer.getWriter()); @@ -630,21 +630,21 @@ RiffReadHelper RiffContainer::DataChunk::asReadHelper() const return RiffReadHelper(nullptr, 0); } -int RiffContainer::DataChunk::calcHash() const +RiffHashCode RiffContainer::DataChunk::calcHash() const { - int hash = 0; + RiffHashCode hash = 0; Data* data = m_dataList; while (data) { - // This is a little contrived (in that we don't use the function GetHashCode), but the + // This is a little contrived (in that we don't use the function getHashCode), but the // reason to be careful is we want the same result however many Data blocks there are. const char* buffer = (const char*)data->getPayload(); const size_t size = data->getSize(); for (size_t i = 0; i < size; ++i) { - hash = int(buffer[i]) + (hash << 6) + (hash << 16) - hash; + hash = RiffHashCode(buffer[i]) + (hash << 6) + (hash << 16) - hash; } data = data->m_next; diff --git a/source/core/slang-riff.h b/source/core/slang-riff.h index 535eaffc2..6eeb0a722 100644 --- a/source/core/slang-riff.h +++ b/source/core/slang-riff.h @@ -39,6 +39,9 @@ enum kRiffPadMask = kRiffPadSize - 1, }; +// Uses it's own version of a hash +typedef int RiffHashCode; + struct RiffHeader { FourCC type; ///< The FourCC code that identifies this chunk @@ -186,6 +189,7 @@ public: struct ListChunk; struct DataChunk; + struct Data { /// Get the payload @@ -297,7 +301,7 @@ public: SLANG_FORCE_INLINE static bool isType(const Chunk* chunk) { return chunk->m_kind == Kind::Data; } /// Calculate a hash (not necessarily very fast) - int calcHash() const; + RiffHashCode calcHash() const; /// Calculate the payload size size_t calcPayloadSize() const; diff --git a/source/core/slang-smart-pointer.h b/source/core/slang-smart-pointer.h index 1bbcffe47..53ac010ed 100644 --- a/source/core/slang-smart-pointer.h +++ b/source/core/slang-smart-pointer.h @@ -24,6 +24,8 @@ namespace Slang : referenceCount(0) {} + RefObject& operator=(const RefObject& rhs) = default; + virtual ~RefObject() {} @@ -152,13 +154,13 @@ namespace Slang releaseReference(old); } - int GetHashCode() + HashCode getHashCode() { // Note: We need a `RefPtr<T>` to hash the same as a `T*`, // so that a `T*` can be used as a key in a dictionary with // `RefPtr<T>` keys, and vice versa. // - return Slang::GetHashCode(pointer); + return Slang::getHashCode(pointer); } bool operator==(const T * ptr) const diff --git a/source/core/slang-string.h b/source/core/slang-string.h index 5eb113dc1..02a43a806 100644 --- a/source/core/slang-string.h +++ b/source/core/slang-string.h @@ -170,9 +170,9 @@ namespace Slang UnownedStringSlice trim() const; - int GetHashCode() const + HashCode getHashCode() const { - return Slang::GetHashCode(m_begin, size_t(m_end - m_begin)); + return Slang::getHashCode(m_begin, size_t(m_end - m_begin)); } template <size_t SIZE> @@ -802,9 +802,9 @@ namespace Slang return contains(str.begin()); } - int GetHashCode() const + HashCode getHashCode() const { - return Slang::GetHashCode((const char*)begin()); + return Slang::getHashCode(StringRepresentation::asSlice(m_buffer)); } UnownedStringSlice getUnownedSlice() const diff --git a/source/core/slang-text-io.cpp b/source/core/slang-text-io.cpp index 4e989b627..ca3b9447c 100644 --- a/source/core/slang-text-io.cpp +++ b/source/core/slang-text-io.cpp @@ -278,7 +278,7 @@ namespace Slang } destBuffer[i] = ch; } - catch (EndOfStreamException) + catch (const EndOfStreamException& ) { break; } @@ -307,7 +307,7 @@ namespace Slang } sb.Append(ch); } - catch (EndOfStreamException) + catch (const EndOfStreamException&) { break; } @@ -333,7 +333,7 @@ namespace Slang else sb.Append(ch); } - catch (EndOfStreamException) + catch (const EndOfStreamException&) { break; } diff --git a/source/core/slang-uint-set.cpp b/source/core/slang-uint-set.cpp index 656bd8ba8..3ac1c530a 100644 --- a/source/core/slang-uint-set.cpp +++ b/source/core/slang-uint-set.cpp @@ -27,7 +27,7 @@ UIntSet& UIntSet::operator=(const UIntSet& other) return *this; } -int UIntSet::GetHashCode() +HashCode UIntSet::getHashCode() { int rs = 0; for (auto val : m_buffer) diff --git a/source/core/slang-uint-set.h b/source/core/slang-uint-set.h index 77930ba0d..7833ffa25 100644 --- a/source/core/slang-uint-set.h +++ b/source/core/slang-uint-set.h @@ -4,6 +4,7 @@ #include "slang-list.h" #include "slang-math.h" #include "slang-common.h" +#include "slang-hash.h" #include <memory.h> @@ -24,7 +25,7 @@ public: UIntSet& operator=(UIntSet&& other); UIntSet& operator=(const UIntSet& other); - int GetHashCode(); + HashCode getHashCode(); /// Return the count of all bits directly represented Int getCount() const { return Int(m_buffer.getCount()) * kElementSize; } |
