Commit c3f90741 authored by Erik Verbruggen's avatar Erik Verbruggen Committed by Erik Verbruggen

C++: cache fully qualified name lookupus in scopes.

Task-number: QTCREATORBUG-8724

Change-Id: I00b0712cf5514bcec04b674052ad4b5b66cca506
Reviewed-by: default avatarPrzemyslaw Gorszkowski <pgorszkowski@gmail.com>
Reviewed-by: default avatarNikolai Kosjar <nikolai.kosjar@digia.com>
parent 413b153b
...@@ -92,7 +92,7 @@ static void path_helper(Symbol *symbol, QList<const Name *> *names) ...@@ -92,7 +92,7 @@ static void path_helper(Symbol *symbol, QList<const Name *> *names)
namespace CPlusPlus { namespace CPlusPlus {
bool compareName(const Name *name, const Name *other) static inline bool compareName(const Name *name, const Name *other)
{ {
if (name == other) if (name == other)
return true; return true;
...@@ -123,6 +123,30 @@ bool compareFullyQualifiedName(const QList<const Name *> &path, const QList<cons ...@@ -123,6 +123,30 @@ bool compareFullyQualifiedName(const QList<const Name *> &path, const QList<cons
} }
namespace CPlusPlus {
namespace Internal {
bool operator==(const FullyQualifiedName &left, const FullyQualifiedName &right)
{
return compareFullyQualifiedName(left.fqn, right.fqn);
}
uint qHash(const FullyQualifiedName &fullyQualifiedName)
{
uint h = 0;
for (int i = 0; i < fullyQualifiedName.fqn.size(); ++i) {
if (const Name *n = fullyQualifiedName.fqn.at(i)) {
if (const Identifier *id = n->identifier()) {
h <<= 1;
h += id->hashCode();
}
}
}
return h;
}
}
}
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
// LookupContext // LookupContext
///////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////
...@@ -393,13 +417,22 @@ ClassOrNamespace *LookupContext::lookupParent(Symbol *symbol) const ...@@ -393,13 +417,22 @@ ClassOrNamespace *LookupContext::lookupParent(Symbol *symbol) const
} }
ClassOrNamespace::ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent) ClassOrNamespace::ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent)
: _factory(factory), _parent(parent), _templateId(0), _instantiationOrigin(0) : _factory(factory)
, _parent(parent)
, _scopeLookupCache(0)
, _templateId(0)
, _instantiationOrigin(0)
#ifdef DEBUG_LOOKUP #ifdef DEBUG_LOOKUP
, _name(0) , _name(0)
#endif // DEBUG_LOOKUP #endif // DEBUG_LOOKUP
{ {
} }
ClassOrNamespace::~ClassOrNamespace()
{
delete _scopeLookupCache;
}
const TemplateNameId *ClassOrNamespace::templateId() const const TemplateNameId *ClassOrNamespace::templateId() const
{ {
return _templateId; return _templateId;
...@@ -464,7 +497,7 @@ QList<LookupItem> ClassOrNamespace::lookup_helper(const Name *name, bool searchI ...@@ -464,7 +497,7 @@ QList<LookupItem> ClassOrNamespace::lookup_helper(const Name *name, bool searchI
if (name) { if (name) {
if (const QualifiedNameId *q = name->asQualifiedNameId()) { if (const QualifiedNameId *q = name->asQualifiedNameId()) {
if (! q->base()) if (! q->base()) // e.g. ::std::string
result = globalNamespace()->find(q->name()); result = globalNamespace()->find(q->name());
else if (ClassOrNamespace *binding = lookupType(q->base())) { else if (ClassOrNamespace *binding = lookupType(q->base())) {
...@@ -477,23 +510,10 @@ QList<LookupItem> ClassOrNamespace::lookup_helper(const Name *name, bool searchI ...@@ -477,23 +510,10 @@ QList<LookupItem> ClassOrNamespace::lookup_helper(const Name *name, bool searchI
// a qualified name. For instance, a nested class which is forward declared // a qualified name. For instance, a nested class which is forward declared
// in the class but defined outside it - we should capture both. // in the class but defined outside it - we should capture both.
Symbol *match = 0; Symbol *match = 0;
ClassOrNamespace *parentBinding = binding->parent(); for (ClassOrNamespace *parentBinding = binding->parent();
while (parentBinding && !match) { parentBinding && !match;
for (int j = 0; j < parentBinding->symbols().size() && !match; ++j) { parentBinding = parentBinding->parent())
if (Scope *scope = parentBinding->symbols().at(j)->asScope()) { match = parentBinding->lookupInScope(fullName);
for (unsigned i = 0; i < scope->memberCount(); ++i) {
Symbol *candidate = scope->memberAt(i);
if (compareFullyQualifiedName(
fullName,
LookupContext::fullyQualifiedName(candidate))) {
match = candidate;
break;
}
}
}
}
parentBinding = parentBinding->parent();
}
if (match) { if (match) {
LookupItem item; LookupItem item;
...@@ -634,6 +654,24 @@ ClassOrNamespace *ClassOrNamespace::findType(const Name *name) ...@@ -634,6 +654,24 @@ ClassOrNamespace *ClassOrNamespace::findType(const Name *name)
return lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ false, this); return lookupType_helper(name, &processed, /*searchInEnclosingScope =*/ false, this);
} }
Symbol *ClassOrNamespace::lookupInScope(const QList<const Name *> &fullName)
{
if (!_scopeLookupCache) {
_scopeLookupCache = new QHash<Internal::FullyQualifiedName, Symbol *>;
for (int j = 0; j < symbols().size(); ++j) {
if (Scope *scope = symbols().at(j)->asScope()) {
for (unsigned i = 0; i < scope->memberCount(); ++i) {
Symbol *s = scope->memberAt(i);
_scopeLookupCache->insert(LookupContext::fullyQualifiedName(s), s);
}
}
}
}
return _scopeLookupCache->value(fullName, 0);
}
ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name, ClassOrNamespace *ClassOrNamespace::lookupType_helper(const Name *name,
QSet<ClassOrNamespace *> *processed, QSet<ClassOrNamespace *> *processed,
bool searchInEnclosingScope, bool searchInEnclosingScope,
......
...@@ -45,12 +45,24 @@ ...@@ -45,12 +45,24 @@
namespace CPlusPlus { namespace CPlusPlus {
namespace Internal {
struct FullyQualifiedName
{
QList<const Name *> fqn;
FullyQualifiedName(const QList<const Name *> &fqn)
: fqn(fqn)
{}
};
} // namespace Internal;
class CreateBindings; class CreateBindings;
class CPLUSPLUS_EXPORT ClassOrNamespace class CPLUSPLUS_EXPORT ClassOrNamespace
{ {
public: public:
ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent); ClassOrNamespace(CreateBindings *factory, ClassOrNamespace *parent);
~ClassOrNamespace();
const TemplateNameId *templateId() const; const TemplateNameId *templateId() const;
ClassOrNamespace *instantiationOrigin() const; ClassOrNamespace *instantiationOrigin() const;
...@@ -68,6 +80,8 @@ public: ...@@ -68,6 +80,8 @@ public:
ClassOrNamespace *lookupType(const Name *name); ClassOrNamespace *lookupType(const Name *name);
ClassOrNamespace *findType(const Name *name); ClassOrNamespace *findType(const Name *name);
Symbol *lookupInScope(const QList<const Name *> &fullName);
private: private:
typedef std::map<const Name *, ClassOrNamespace *, Name::Compare> Table; typedef std::map<const Name *, ClassOrNamespace *, Name::Compare> Table;
typedef std::map<const TemplateNameId *, ClassOrNamespace *, TemplateNameId::Compare> TemplateNameIdTable; typedef std::map<const TemplateNameId *, ClassOrNamespace *, TemplateNameId::Compare> TemplateNameIdTable;
...@@ -115,6 +129,8 @@ private: ...@@ -115,6 +129,8 @@ private:
TemplateNameIdTable _specializations; TemplateNameIdTable _specializations;
QMap<const TemplateNameId *, ClassOrNamespace *> _instantiations; QMap<const TemplateNameId *, ClassOrNamespace *> _instantiations;
QHash<Internal::FullyQualifiedName, Symbol *> *_scopeLookupCache;
// it's an instantiation. // it's an instantiation.
const TemplateNameId *_templateId; const TemplateNameId *_templateId;
ClassOrNamespace *_instantiationOrigin; ClassOrNamespace *_instantiationOrigin;
...@@ -308,7 +324,6 @@ private: ...@@ -308,7 +324,6 @@ private:
bool m_expandTemplates; bool m_expandTemplates;
}; };
bool CPLUSPLUS_EXPORT compareName(const Name *name, const Name *other);
bool CPLUSPLUS_EXPORT compareFullyQualifiedName(const QList<const Name *> &path, bool CPLUSPLUS_EXPORT compareFullyQualifiedName(const QList<const Name *> &path,
const QList<const Name *> &other); const QList<const Name *> &other);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment