Use std::unordered_map instead of std::map

In theory it should be faster.

Change-Id: Ibf6ce8c5dced5a075b57f89ce6e2d5ed1c5d6be7
Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
Jarek Kobus
2020-12-17 07:14:28 +01:00
parent 0e7774e75d
commit 675abca1ca
8 changed files with 73 additions and 32 deletions

View File

@@ -200,6 +200,11 @@ bool FullySpecifiedType::operator < (const FullySpecifiedType &other) const
return _type < other._type; return _type < other._type;
} }
size_t FullySpecifiedType::hash() const
{
return std::hash<Type *>()(_type) ^ std::hash<unsigned>()(_flags);
}
FullySpecifiedType FullySpecifiedType::simplified() const FullySpecifiedType FullySpecifiedType::simplified() const
{ {
if (const ReferenceType *refTy = type()->asReferenceType()) if (const ReferenceType *refTy = type()->asReferenceType())

View File

@@ -103,6 +103,8 @@ public:
bool operator != (const FullySpecifiedType &other) const; bool operator != (const FullySpecifiedType &other) const;
bool operator < (const FullySpecifiedType &other) const; bool operator < (const FullySpecifiedType &other) const;
size_t hash() const;
bool match(const FullySpecifiedType &otherTy, Matcher *matcher = nullptr) const; bool match(const FullySpecifiedType &otherTy, Matcher *matcher = nullptr) const;
FullySpecifiedType simplified() const; FullySpecifiedType simplified() const;

View File

@@ -25,6 +25,7 @@
#include "NameVisitor.h" #include "NameVisitor.h"
#include <cstring> #include <cstring>
#include <string_view>
using namespace CPlusPlus; using namespace CPlusPlus;
@@ -77,22 +78,33 @@ bool Name::match(const Name *other, Matcher *matcher) const
return Matcher::match(this, other, matcher); return Matcher::match(this, other, matcher);
} }
bool Name::Compare::operator()(const Name *name, const Name *other) const bool Name::Equals::operator()(const Name *name, const Name *other) const
{ {
if (name == nullptr)
return other != nullptr;
if (other == nullptr)
return false;
if (name == other) if (name == other)
return true;
if (name == nullptr || other == nullptr)
return false; return false;
const Identifier *id = name->identifier(); const Identifier *id = name->identifier();
const Identifier *otherId = other->identifier(); const Identifier *otherId = other->identifier();
if (id == nullptr) if (id == otherId)
return otherId != nullptr; return true;
if (otherId == nullptr) if (id == nullptr || otherId == nullptr)
return false; return false;
return std::strcmp(id->chars(), otherId->chars()) < 0; return std::strcmp(id->chars(), otherId->chars()) == 0;
}
size_t Name::Hash::operator()(const Name *name) const
{
if (name == nullptr)
return 0;
const Identifier *id = name->identifier();
if (id == nullptr)
return 0;
return std::hash<std::string_view>()(std::string_view(id->chars()));
} }

View File

@@ -59,9 +59,12 @@ public:
bool match(const Name *other, Matcher *matcher = nullptr) const; bool match(const Name *other, Matcher *matcher = nullptr) const;
public: public:
struct Compare { struct Equals {
bool operator()(const Name *name, const Name *other) const; bool operator()(const Name *name, const Name *other) const;
}; };
struct Hash {
size_t operator()(const Name *name) const;
};
protected: protected:
virtual void accept0(NameVisitor *visitor) const = 0; virtual void accept0(NameVisitor *visitor) const = 0;

View File

@@ -24,6 +24,7 @@
#include "Literals.h" #include "Literals.h"
#include <algorithm> #include <algorithm>
#include <cstring> #include <cstring>
#include <string_view>
using namespace CPlusPlus; using namespace CPlusPlus;
@@ -106,38 +107,48 @@ int TemplateNameId::templateArgumentCount() const
const TemplateArgument &TemplateNameId::templateArgumentAt(int index) const const TemplateArgument &TemplateNameId::templateArgumentAt(int index) const
{ return _templateArguments[index]; } { return _templateArguments[index]; }
bool TemplateNameId::Compare::operator()(const TemplateNameId *name, bool TemplateNameId::Equals::operator()(const TemplateNameId *name,
const TemplateNameId *other) const const TemplateNameId *other) const
{ {
if (name == nullptr)
return other != nullptr;
if (other == nullptr)
return false;
if (name == other) if (name == other)
return true;
if (name == nullptr || other == nullptr)
return false; return false;
const Identifier *id = name->identifier(); const Identifier *id = name->identifier();
const Identifier *otherId = other->identifier(); const Identifier *otherId = other->identifier();
if (id == nullptr) if (!id != !otherId) // mimic logical xor (id == nullptr ^^ otherId == nullptr)
return otherId != nullptr;
if (otherId == nullptr)
return false; return false;
const int c = std::strcmp(id->chars(), otherId->chars()); const int c = id ? std::strcmp(id->chars(), otherId->chars()) : 0; // 0 if both are nullptr
if (c == 0) { if (c == 0) {
// we have to differentiate TemplateNameId with respect to specialization or instantiation // we have to differentiate TemplateNameId with respect to specialization or instantiation
if (name->isSpecialization() == other->isSpecialization()) { if (name->isSpecialization() == other->isSpecialization()) {
return std::lexicographical_compare(name->firstTemplateArgument(), return std::equal(name->firstTemplateArgument(),
name->lastTemplateArgument(), name->lastTemplateArgument(),
other->firstTemplateArgument(), other->firstTemplateArgument(),
other->lastTemplateArgument()); other->lastTemplateArgument());
} else {
return name->isSpecialization();
} }
} }
return false;
}
return c < 0; size_t TemplateNameId::Hash::operator()(const TemplateNameId *name) const
{
if (name == nullptr)
return 0;
const Identifier *id = name->identifier();
size_t hash = id ? std::hash<std::string_view>()(std::string_view(id->chars())) : 0;
hash ^= name->isSpecialization() ? 0x1 : 0x0;
std::for_each(name->firstTemplateArgument(),
name->lastTemplateArgument(),
[&hash](const TemplateArgument &ta) {
hash ^= ta.hash();
});
return hash;
} }
OperatorNameId::OperatorNameId(Kind kind) OperatorNameId::OperatorNameId(Kind kind)

View File

@@ -113,6 +113,11 @@ public:
bool match(const TemplateArgument &otherTy, Matcher *matcher = nullptr) const; bool match(const TemplateArgument &otherTy, Matcher *matcher = nullptr) const;
size_t hash() const
{
return _expressionTy.hash() ^ std::hash<const NumericLiteral *>()(_numericLiteral);
}
private: private:
FullySpecifiedType _expressionTy; FullySpecifiedType _expressionTy;
const NumericLiteral *_numericLiteral = nullptr; const NumericLiteral *_numericLiteral = nullptr;
@@ -145,10 +150,13 @@ public:
TemplateArgumentIterator lastTemplateArgument() const { return _templateArguments.end(); } TemplateArgumentIterator lastTemplateArgument() const { return _templateArguments.end(); }
bool isSpecialization() const { return _isSpecialization; } bool isSpecialization() const { return _isSpecialization; }
// Comparator needed to distinguish between two different TemplateNameId(e.g.:used in std::map) // Comparator needed to distinguish between two different TemplateNameId(e.g.:used in std::unordered_map)
struct Compare { struct Equals {
bool operator()(const TemplateNameId *name, const TemplateNameId *other) const; bool operator()(const TemplateNameId *name, const TemplateNameId *other) const;
}; };
struct Hash {
size_t operator()(const TemplateNameId *name) const;
};
protected: protected:
void accept0(NameVisitor *visitor) const override; void accept0(NameVisitor *visitor) const override;

View File

@@ -60,7 +60,7 @@ public:
private: private:
Control *_control; Control *_control;
Subst *_previous; Subst *_previous;
std::map<const Name *, FullySpecifiedType, Name::Compare> _map; std::unordered_map<const Name *, FullySpecifiedType, Name::Hash, Name::Equals> _map;
}; };
class CPLUSPLUS_EXPORT CloneType: protected TypeVisitor class CPLUSPLUS_EXPORT CloneType: protected TypeVisitor

View File

@@ -89,8 +89,8 @@ public:
Class *rootClass() const { return _rootClass; } Class *rootClass() const { return _rootClass; }
private: private:
typedef std::map<const Name *, ClassOrNamespace *, Name::Compare> Table; typedef std::unordered_map<const Name *, ClassOrNamespace *, Name::Hash, Name::Equals> Table;
typedef std::map<const TemplateNameId *, ClassOrNamespace *, TemplateNameId::Compare> TemplateNameIdTable; typedef std::unordered_map<const TemplateNameId *, ClassOrNamespace *, TemplateNameId::Hash, TemplateNameId::Equals> TemplateNameIdTable;
typedef QHash<const AnonymousNameId *, ClassOrNamespace *> Anonymouses; typedef QHash<const AnonymousNameId *, ClassOrNamespace *> Anonymouses;
/// \internal /// \internal