diff --git a/builds/posix/prefix.linux b/builds/posix/prefix.linux
index dad8cb6cc1..56d1529570 100644
--- a/builds/posix/prefix.linux
+++ b/builds/posix/prefix.linux
@@ -25,3 +25,8 @@ WARN_FLAGS=-Wall -Wno-switch -Wno-parentheses -Wno-unknown-pragmas -Wno-unused-v
PROD_FLAGS=$(COMMON_FLAGS) $(OPTIMIZE_FLAGS)
#DEV_FLAGS=-DUSE_VALGRIND -p $(COMMON_FLAGS) $(WARN_FLAGS)
DEV_FLAGS=-p $(COMMON_FLAGS) $(WARN_FLAGS)
+
+# This file must be compiled with SSE4.2 support
+%/CRC32C.o: COMMON_FLAGS += -msse4
+
+CXXFLAGS := $(CXXFLAGS) -std=c++11
diff --git a/builds/posix/prefix.linux_amd64 b/builds/posix/prefix.linux_amd64
index 11d49a0694..394286f334 100644
--- a/builds/posix/prefix.linux_amd64
+++ b/builds/posix/prefix.linux_amd64
@@ -25,3 +25,8 @@ WARN_FLAGS=-Wall -Wno-switch -Wno-parentheses -Wno-unknown-pragmas -Wno-unused-v
PROD_FLAGS=$(COMMON_FLAGS) $(OPTIMIZE_FLAGS)
#DEV_FLAGS=-DUSE_VALGRIND $(COMMON_FLAGS) $(WARN_FLAGS) -fmax-errors=8
DEV_FLAGS=$(COMMON_FLAGS) $(WARN_FLAGS) -fmax-errors=8
+
+# This file must be compiled with SSE4.2 support
+%/CRC32C.o: COMMON_FLAGS += -msse4
+
+CXXFLAGS := $(CXXFLAGS) -std=c++11
diff --git a/builds/win32/msvc10/common.vcxproj b/builds/win32/msvc10/common.vcxproj
index c19b233b22..2ce220268e 100644
--- a/builds/win32/msvc10/common.vcxproj
+++ b/builds/win32/msvc10/common.vcxproj
@@ -30,6 +30,7 @@
+
@@ -49,6 +50,16 @@
+
+ true
+ true
+ true
+ true
+ ProgramDatabase
+ ProgramDatabase
+ ProgramDatabase
+ ProgramDatabase
+
diff --git a/builds/win32/msvc10/common.vcxproj.filters b/builds/win32/msvc10/common.vcxproj.filters
index 3b1dc2fbc1..871ca48d2f 100644
--- a/builds/win32/msvc10/common.vcxproj.filters
+++ b/builds/win32/msvc10/common.vcxproj.filters
@@ -210,6 +210,12 @@
common
+
+ classes
+
+
+ classes
+
diff --git a/builds/win32/msvc12/common.vcxproj b/builds/win32/msvc12/common.vcxproj
index d425513d3e..cd1e2084a5 100644
--- a/builds/win32/msvc12/common.vcxproj
+++ b/builds/win32/msvc12/common.vcxproj
@@ -30,6 +30,7 @@
+
@@ -49,6 +50,12 @@
+
+ true
+ StreamingSIMDExtensions2
+ true
+ StreamingSIMDExtensions2
+
diff --git a/builds/win32/msvc12/common.vcxproj.filters b/builds/win32/msvc12/common.vcxproj.filters
index 3b1dc2fbc1..fb87986102 100644
--- a/builds/win32/msvc12/common.vcxproj.filters
+++ b/builds/win32/msvc12/common.vcxproj.filters
@@ -210,6 +210,12 @@
common
+
+ classes
+
+
+ common
+
diff --git a/src/common/CRC32C.cpp b/src/common/CRC32C.cpp
new file mode 100644
index 0000000000..9630b4ab7a
--- /dev/null
+++ b/src/common/CRC32C.cpp
@@ -0,0 +1,68 @@
+/*
+ * PROGRAM: Common Library
+ * MODULE: CRC32C.cpp
+ * DESCRIPTION: Hardware-accelerated hash calculation
+ *
+ * The contents of this file are subject to the Initial
+ * Developer's Public License Version 1.0 (the "License");
+ * you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
+ *
+ * Software distributed under the License is distributed AS IS,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied.
+ * See the License for the specific language governing rights
+ * and limitations under the License.
+ *
+ * The Original Code was created by Dmitry Sibiryakov
+ * for the Firebird Open Source RDBMS project.
+ *
+ * Copyright (c) 2015 Dmitry Sibiryakov
+ * and all contributors signed below.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ *
+ */
+
+#include "firebird.h"
+
+// Can be used only on x86 architectures
+// WARNING: With GCC must be compiled separately with -msse4.2 flag
+#if defined(_M_IX86) || defined(_M_X64) || defined(__x86_64__) || defined(__i386__)
+
+#include
+
+unsigned int CRC32C(unsigned int length, const unsigned char* value)
+{
+ unsigned int hash_value = 0;
+
+ if (length == 1)
+ return _mm_crc32_u8(hash_value, *value);
+
+ if (length == 2)
+ return _mm_crc32_u16(hash_value, *(unsigned short*) value);
+
+ while (length >= 4)
+ {
+ hash_value = _mm_crc32_u32(hash_value, *(unsigned int*) value);
+ value += 4;
+ length -= 4;
+ }
+
+ if (length >= 2)
+ {
+ hash_value = _mm_crc32_u16(hash_value, *(unsigned short*) value);
+ value += 2;
+ length -= 2;
+ }
+
+ if (length)
+ {
+ hash_value = _mm_crc32_u8(hash_value, *value);
+ }
+
+ return hash_value;
+}
+
+#endif // architecture check
diff --git a/src/common/classes/Hash.cpp b/src/common/classes/Hash.cpp
new file mode 100644
index 0000000000..6614708889
--- /dev/null
+++ b/src/common/classes/Hash.cpp
@@ -0,0 +1,113 @@
+/*
+ * PROGRAM: Common Library
+ * MODULE: Hash.cpp
+ * DESCRIPTION: Hash of data
+ *
+ * The contents of this file are subject to the Initial
+ * Developer's Public License Version 1.0 (the "License");
+ * you may not use this file except in compliance with the
+ * License. You may obtain a copy of the License at
+ * http://www.ibphoenix.com/main.nfs?a=ibphoenix&page=ibp_idpl.
+ *
+ * The Original Code was created by Dmitry Sibiryakov
+ * for the Firebird Open Source RDBMS project.
+ *
+ * Copyright (c) 2015 Dmitry Sibiryakov
+ * and all contributors signed below.
+ *
+ * All Rights Reserved.
+ * Contributor(s): ______________________________________.
+ *
+ */
+
+#include "firebird.h"
+#include "../common/classes/Hash.h"
+
+#if defined(_M_IX86) || defined(_M_X64) || defined(__x86_64__) || defined(__i386__)
+#ifdef _MSC_VER
+#include
+#else
+#include
+#endif
+#endif
+
+using namespace Firebird;
+
+unsigned int CRC32C(unsigned int length, const unsigned char* value);
+
+namespace
+{
+ typedef unsigned int (*hash_func_t)(unsigned int length, const UCHAR* value);
+
+ unsigned int basicHash(unsigned int length, const UCHAR* value)
+ {
+ unsigned int hash_value = 0;
+
+ UCHAR* p;
+ const UCHAR* q = value;
+
+ while (length >= 4)
+ {
+ p = (UCHAR*) &hash_value;
+ p[0] += q[0];
+ p[1] += q[1];
+ p[2] += q[2];
+ p[3] += q[3];
+ length -= 4;
+ q += 4;
+ }
+
+ p = (UCHAR*) &hash_value;
+
+ if (length >= 2)
+ {
+ p[0] += q[0];
+ p[1] += q[1];
+ length -= 2;
+ }
+
+ if (length)
+ {
+ q += 2;
+ *p += *q;
+ }
+
+ return hash_value;
+ }
+
+#if defined(_M_IX86) || defined(_M_X64) || defined(__x86_64__) || defined(__i386__)
+
+ bool SSE4_2Supported()
+ {
+#ifdef _MSC_VER
+ const int bit_SSE4_2 = 1 << 20;
+ // MS VC has its own definition of __cpuid
+ int flags[4];
+ __cpuid(flags, 1);
+ return (flags[2] & bit_SSE4_2) != 0;
+#else
+#if defined(__clang__) && !defined(bit_SSE4_2)
+ const int bit_SSE4_2 = bit_SSE42;
+#endif
+
+ // GCC - its own
+ unsigned int eax,ebx,ecx,edx;
+ __cpuid(1, eax, ebx, ecx, edx);
+ return (ecx & bit_SSE4_2) != 0;
+#endif
+ }
+
+ hash_func_t internalHash = SSE4_2Supported() ? CRC32C : basicHash;
+
+#else // architecture check
+
+ hash_func_t internalHash = basicHash;
+
+#endif // architecture check
+
+}
+
+unsigned int InternalHash::hash(unsigned int length, const UCHAR* value)
+{
+ return internalHash(length, value);
+}
diff --git a/src/common/classes/Hash.h b/src/common/classes/Hash.h
index 307270a129..39aaa5b46f 100644
--- a/src/common/classes/Hash.h
+++ b/src/common/classes/Hash.h
@@ -41,7 +41,7 @@ namespace Firebird
size_t sum = 0;
size_t val;
- const char* data = static_cast(value);
+ const UCHAR* data = static_cast(value);
while (length >= sizeof(size_t))
{
@@ -72,7 +72,6 @@ namespace Firebird
{
return hash(&value, sizeof value, hashSize);
}
-
};
const FB_SIZE_T DEFAULT_HASH_SIZE = 97; // largest prime number < 100
@@ -82,7 +81,7 @@ namespace Firebird
typename K = C, // default key
typename KeyOfValue = DefaultKeyValue, // default keygen
typename F = DefaultHash > // hash function definition
- class Hash
+ class HashTable
{
public:
// This class is supposed to be used as a BASE class for class to be hashed
@@ -156,22 +155,22 @@ namespace Firebird
}; // class Entry
private:
- Hash(const Hash&); // not implemented
+ HashTable(const HashTable&); // not implemented
public:
- explicit Hash(MemoryPool&)
+ explicit HashTable(MemoryPool&)
: duplicates(false)
{
clean();
}
- Hash()
+ HashTable()
: duplicates(false)
{
clean();
}
- ~Hash()
+ ~HashTable()
{
// by default we let hash entries be cleaned by someone else
cleanup(NULL);
@@ -255,7 +254,7 @@ namespace Firebird
private:
// disable use of default operator=
- Hash& operator= (const Hash&);
+ HashTable& operator= (const HashTable&);
void clean()
{
@@ -266,7 +265,7 @@ namespace Firebird
class iterator
{
private:
- const Hash* hash;
+ const HashTable* hash;
FB_SIZE_T elem;
Entry* current;
@@ -286,7 +285,7 @@ namespace Firebird
}
public:
- explicit iterator(const Hash& h)
+ explicit iterator(const HashTable& h)
: hash(&h), elem(0), current(hash->data[elem])
{
next();
@@ -329,7 +328,18 @@ namespace Firebird
return !(*this == h);
}
}; // class iterator
- }; // class Hash
+ }; // class HashTable
+
+ class InternalHash
+ {
+ public:
+ static unsigned int hash(unsigned int length, const UCHAR* value);
+
+ static unsigned int hash(unsigned int length, const UCHAR* value, unsigned int hashSize)
+ {
+ return hash(length, value) % hashSize;
+ }
+ };
} // namespace Firebird
diff --git a/src/common/db_alias.cpp b/src/common/db_alias.cpp
index 8b9f629f52..b25628c4d8 100644
--- a/src/common/db_alias.cpp
+++ b/src/common/db_alias.cpp
@@ -183,7 +183,7 @@ namespace
struct DbName;
#ifdef HAVE_ID_BY_NAME
struct Id;
- typedef Hash, BinHash > IdHash;
+ typedef HashTable, BinHash > IdHash;
struct Id : public IdHash::Entry
{
@@ -206,7 +206,7 @@ namespace
};
#endif
- typedef Hash, PathHash > DbHash;
+ typedef HashTable, PathHash > DbHash;
struct DbName : public DbHash::Entry
{
DbName(MemoryPool& p, const PathName& db)
@@ -234,7 +234,7 @@ namespace
};
struct AliasName;
- typedef Hash, PathHash > AliasHash;
+ typedef HashTable, PathHash > AliasHash;
struct AliasName : public AliasHash::Entry
{
diff --git a/src/jrd/Mapping.cpp b/src/jrd/Mapping.cpp
index 6015f2f244..c1bcf0e790 100644
--- a/src/jrd/Mapping.cpp
+++ b/src/jrd/Mapping.cpp
@@ -146,7 +146,7 @@ private:
};
class Map;
-typedef Hash