summaryrefslogtreecommitdiffstats
path: root/source/core
diff options
context:
space:
mode:
Diffstat (limited to 'source/core')
-rw-r--r--source/core/slang-dictionary.h14
-rw-r--r--source/core/slang-downstream-compiler.h2
-rw-r--r--source/core/slang-hash.h116
-rw-r--r--source/core/slang-hex-dump-util.cpp10
-rw-r--r--source/core/slang-math.h21
-rw-r--r--source/core/slang-riff.cpp18
-rw-r--r--source/core/slang-riff.h6
-rw-r--r--source/core/slang-smart-pointer.h6
-rw-r--r--source/core/slang-string.h8
-rw-r--r--source/core/slang-text-io.cpp6
-rw-r--r--source/core/slang-uint-set.cpp2
-rw-r--r--source/core/slang-uint-set.h3
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; }