Browse Source

Fixed MurmurHash unaligned read.

Branimir Karadžić 10 years ago
parent
commit
96b3b9616f
4 changed files with 69 additions and 9 deletions
  1. 0 8
      include/bx/allocator.h
  2. 8 0
      include/bx/bx.h
  3. 57 1
      include/bx/hash.h
  4. 4 0
      include/bx/macros.h

+ 0 - 8
include/bx/allocator.h

@@ -58,14 +58,6 @@ namespace bx
 		return un.ptr;
 	}
 
-	/// Check if pointer is aligned. _align must be power of two.
-	inline bool isPtrAligned(const void* _ptr, size_t _align = BX_CONFIG_ALLOCATOR_NATURAL_ALIGNMENT)
-	{
-		union { const void* ptr; size_t addr; } un;
-		un.ptr = _ptr;
-		return 0 == (un.addr & (_align-1) );
-	}
-
 	struct BX_NO_VTABLE AllocatorI
 	{
 		virtual ~AllocatorI() = 0;

+ 8 - 0
include/bx/bx.h

@@ -44,6 +44,14 @@ namespace bx
 		Ty tmp = _a; _a = _b; _b = tmp;
 	}
 
+	/// Check if pointer is aligned. _align must be power of two.
+	inline bool isPtrAligned(const void* _ptr, size_t _align)
+	{
+		union { const void* ptr; size_t addr; } un;
+		un.ptr = _ptr;
+		return 0 == (un.addr & (_align-1) );
+	}
+
 } // namespace bx
 
 // Annoying C++0x stuff..

+ 57 - 1
include/bx/hash.h

@@ -30,7 +30,19 @@ namespace bx
 
 		void add(const void* _data, int _len)
 		{
-			const uint8_t* data = (uint8_t*)_data;
+			if (BX_ENABLED(BX_PLATFORM_EMSCRIPTEN)
+			&&  BX_UNLIKELY(!isPtrAligned(_data, 4) ) )
+			{
+				addUnaligned(_data, _len);
+				return;
+			}
+
+			addAligned(_data, _len);
+		}
+
+		void addAligned(const void* _data, int _len)
+		{
+			const uint8_t* data = (const uint8_t*)_data;
 			m_size += _len;
 
 			mixTail(data, _len);
@@ -48,6 +60,27 @@ namespace bx
 			mixTail(data, _len);
 		}
 
+		void addUnaligned(const void* _data, int _len)
+		{
+			const uint8_t* data = (const uint8_t*)_data;
+			m_size += _len;
+
+			mixTail(data, _len);
+
+			while(_len >= 4)
+			{
+				uint32_t kk;
+				readUnaligned(data, kk);
+
+				mmix(m_hash, kk);
+
+				data += 4;
+				_len -= 4;
+			}
+
+			mixTail(data, _len);
+		}
+
 		template<typename Ty>
 		void add(Ty _value)
 		{
@@ -67,6 +100,29 @@ namespace bx
 		}
 
 	private:
+		static void readUnaligned(const void* _data, uint32_t& _out)
+		{
+			const uint8_t* data = (const uint8_t*)_data;
+			if (BX_ENABLED(BX_CPU_ENDIAN_LITTLE) )
+			{
+				_out = 0
+					| data[0]<<24
+					| data[1]<<16
+					| data[2]<<8
+					| data[3]
+					;
+			}
+			else
+			{
+				_out = 0
+					| data[0]
+					| data[1]<<8
+					| data[2]<<16
+					| data[3]<<24
+					;
+			}
+		}
+
 		void mixTail(const uint8_t*& _data, int& _len)
 		{
 			while( _len && ((_len<4) || m_count) )

+ 4 - 0
include/bx/macros.h

@@ -53,6 +53,8 @@
 #	define BX_ALLOW_UNUSED __attribute__( (unused) )
 #	define BX_FORCE_INLINE __extension__ static __inline __attribute__( (__always_inline__) )
 #	define BX_FUNCTION __PRETTY_FUNCTION__
+#	define BX_LIKELY(_x)   __builtin_expect(!!(_x), 1)
+#	define BX_UNLIKELY(_x) __builtin_expect(!!(_x), 0)
 #	define BX_NO_INLINE __attribute__( (noinline) )
 #	define BX_NO_RETURN __attribute__( (noreturn) )
 #	define BX_NO_VTABLE
@@ -76,6 +78,8 @@
 #	define BX_ALLOW_UNUSED
 #	define BX_FORCE_INLINE __forceinline
 #	define BX_FUNCTION __FUNCTION__
+#	define BX_LIKELY(_x)   (_x)
+#	define BX_UNLIKELY(_x) (_x)
 #	define BX_NO_INLINE __declspec(noinline)
 #	define BX_NO_RETURN
 #	define BX_NO_VTABLE __declspec(novtable)