Refactorization: Speedup function lookup in symboldatabase (#6277) (Part 2)

This commit is contained in:
Robert Reif 2015-01-02 21:38:19 +01:00 committed by Matthias Krüger
parent 417f42f732
commit 1aa3adbb46
2 changed files with 53 additions and 50 deletions

View File

@ -433,7 +433,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
// find the function implementation later // find the function implementation later
tok = end->next(); tok = end->next();
scope->functionList.push_back(function); scope->addFunction(function);
} }
// default or delete // default or delete
@ -445,7 +445,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
tok = end->tokAt(3); tok = end->tokAt(3);
scope->functionList.push_back(function); scope->addFunction(function);
} }
// noexcept; // noexcept;
@ -465,7 +465,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
tok = tok->tokAt(2); tok = tok->tokAt(2);
} }
scope->functionList.push_back(function); scope->addFunction(function);
} }
// noexcept(...); // noexcept(...);
@ -488,7 +488,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
tok = tok->tokAt(2); tok = tok->tokAt(2);
} }
scope->functionList.push_back(function); scope->addFunction(function);
} }
// throw(); // throw();
@ -515,7 +515,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
tok = tok->tokAt(2); tok = tok->tokAt(2);
} }
scope->functionList.push_back(function); scope->addFunction(function);
} }
// pure virtual function // pure virtual function
@ -527,13 +527,13 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
else else
tok = end->tokAt(3); tok = end->tokAt(3);
scope->functionList.push_back(function); scope->addFunction(function);
} }
// 'const' or unknown macro (#5197) // 'const' or unknown macro (#5197)
else if (Token::Match(end, ") %any% ;")) { else if (Token::Match(end, ") %any% ;")) {
tok = end->tokAt(2); tok = end->tokAt(2);
scope->functionList.push_back(function); scope->addFunction(function);
} }
// inline function // inline function
@ -569,7 +569,7 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
if (!end || end->str() == ";") if (!end || end->str() == ";")
continue; continue;
scope->functionList.push_back(function); scope->addFunction(function);
Function* funcptr = &scope->functionList.back(); Function* funcptr = &scope->functionList.back();
const Token *tok2 = funcStart; const Token *tok2 = funcStart;
@ -691,8 +691,8 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *setti
// function prototype? // function prototype?
else if (scopeBegin->str() == ";") { else if (scopeBegin->str() == ";") {
bool newFunc = true; // Is this function already in the database? bool newFunc = true; // Is this function already in the database?
for (std::list<Function>::const_iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) { for (std::multimap<std::string, const Function *>::const_iterator i = scope->functionMap.find(tok->str()); i != scope->functionMap.end() && i->first == tok->str(); ++i) {
if (i->tokenDef->str() == tok->str() && Function::argsMatch(scope, i->argDef->next(), argStart->next(), "", 0)) { if (Function::argsMatch(scope, i->second->argDef->next(), argStart->next(), "", 0)) {
newFunc = false; newFunc = false;
break; break;
} }
@ -1526,12 +1526,12 @@ bool Function::argsMatch(const Scope *scope, const Token *first, const Token *se
Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, const Token *argStart, const Token* funcStart) Function* SymbolDatabase::addGlobalFunction(Scope*& scope, const Token*& tok, const Token *argStart, const Token* funcStart)
{ {
Function* function = 0; Function* function = 0;
for (std::list<Function>::iterator i = scope->functionList.begin(); i != scope->functionList.end(); ++i) { for (std::multimap<std::string, const Function *>::iterator i = scope->functionMap.find(tok->str()); i != scope->functionMap.end() && i->first == tok->str(); ++i) {
if (i->tokenDef->str() == tok->str() && Function::argsMatch(scope, i->argDef->next(), argStart->next(), "", 0)) { if (Function::argsMatch(scope, i->second->argDef->next(), argStart->next(), "", 0)) {
function = &*i; function = const_cast<Function *>(i->second);
// copy attributes from function prototype to function // copy attributes from function prototype to function
Token* to = const_cast<Token *>(tok); Token* to = const_cast<Token *>(tok);
const Token* from = i->tokenDef; const Token* from = function->tokenDef;
to->isAttributeConstructor(from->isAttributeConstructor()); to->isAttributeConstructor(from->isAttributeConstructor());
to->isAttributeDestructor(from->isAttributeDestructor()); to->isAttributeDestructor(from->isAttributeDestructor());
to->isAttributePure(from->isAttributePure()); to->isAttributePure(from->isAttributePure());
@ -1591,7 +1591,7 @@ Function* SymbolDatabase::addGlobalFunctionDecl(Scope*& scope, const Token *tok,
if (tok1) if (tok1)
function.retDef = tok1; function.retDef = tok1;
scope->functionList.push_back(function); scope->addFunction(function);
return &scope->functionList.back(); return &scope->functionList.back();
} }
@ -1697,10 +1697,9 @@ void SymbolDatabase::addClassFunction(Scope **scope, const Token **tok, const To
} }
if (match) { if (match) {
std::list<Function>::iterator func; for (std::multimap<std::string, const Function *>::iterator it = scope1->functionMap.find((*tok)->str()); it != scope1->functionMap.end() && it->first == (*tok)->str(); ++it) {
Function * func = const_cast<Function *>(it->second);
for (func = scope1->functionList.begin(); func != scope1->functionList.end(); ++func) { if (!func->hasBody) {
if (!func->hasBody && func->tokenDef->str() == (*tok)->str()) {
if (Function::argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) { if (Function::argsMatch(scope1, func->argDef, (*tok)->next(), path, path_length)) {
if (func->type == Function::eDestructor && destructor) { if (func->type == Function::eDestructor && destructor) {
func->hasBody = true; func->hasBody = true;
@ -1882,9 +1881,10 @@ void SymbolDatabase::debugMessage(const Token *tok, const std::string &msg) cons
const Function* Type::getFunction(const std::string& funcName) const const Function* Type::getFunction(const std::string& funcName) const
{ {
if (classScope) { if (classScope) {
for (std::list<Function>::const_iterator i = classScope->functionList.begin(); i != classScope->functionList.end(); ++i) std::multimap<std::string, const Function *>::const_iterator it = classScope->functionMap.find(funcName);
if (i->name() == funcName)
return &*i; if (it != classScope->functionMap.end())
return it->second;
} }
for (std::size_t i = 0; i < derivedFrom.size(); i++) { for (std::size_t i = 0; i < derivedFrom.size(); i++) {
@ -2473,11 +2473,10 @@ bool Function::isImplicitlyVirtual_rec(const ::Type* baseType, bool& safe) const
if (derivedFromType && derivedFromType->classScope) { if (derivedFromType && derivedFromType->classScope) {
const Scope *parent = derivedFromType->classScope; const Scope *parent = derivedFromType->classScope;
std::list<Function>::const_iterator func;
// check if function defined in base class // check if function defined in base class
for (func = parent->functionList.begin(); func != parent->functionList.end(); ++func) { for (std::multimap<std::string, const Function *>::const_iterator it = parent->functionMap.find(tokenDef->str()); it != parent->functionMap.end() && it->first == tokenDef->str(); ++it) {
if (func->isVirtual && func->tokenDef->str() == tokenDef->str()) { // Base is virtual and of same name const Function * func = it->second;
if (func->isVirtual) { // Base is virtual and of same name
const Token *temp1 = func->tokenDef->previous(); const Token *temp1 = func->tokenDef->previous();
const Token *temp2 = tokenDef->previous(); const Token *temp2 = tokenDef->previous();
bool returnMatch = true; bool returnMatch = true;
@ -2898,6 +2897,7 @@ bool Scope::isVariableDeclaration(const Token* tok, const Token*& vartok, const
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *typeTok) const const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *typeTok) const
@ -2939,7 +2939,7 @@ const Type* SymbolDatabase::findVariableType(const Scope *start, const Token *ty
//--------------------------------------------------------------------------- //---------------------------------------------------------------------------
void Scope::findFunctionInBase(const Token * tok, size_t args, std::vector<const Function *> & matches) const void Scope::findFunctionInBase(const std::string & name, size_t args, std::vector<const Function *> & matches) const
{ {
if (isClassOrStruct() && definedType && !definedType->derivedFrom.empty()) { if (isClassOrStruct() && definedType && !definedType->derivedFrom.empty()) {
for (std::size_t i = 0; i < definedType->derivedFrom.size(); ++i) { for (std::size_t i = 0; i < definedType->derivedFrom.size(); ++i) {
@ -2948,16 +2948,14 @@ void Scope::findFunctionInBase(const Token * tok, size_t args, std::vector<const
if (base->classScope == this) // Ticket #5120, #5125: Recursive class; tok should have been found already if (base->classScope == this) // Ticket #5120, #5125: Recursive class; tok should have been found already
continue; continue;
for (std::list<Function>::const_iterator it = base->classScope->functionList.begin(); it != base->classScope->functionList.end(); ++it) { for (std::multimap<std::string, const Function *>::const_iterator it = base->classScope->functionMap.find(name); it != base->classScope->functionMap.end() && it->first == name; ++it) {
if (it->tokenDef->str() == tok->str()) { const Function *func = it->second;
const Function *func = &*it; if (args == func->argCount() || (args < func->argCount() && args >= func->minArgCount())) {
if (args == func->argCount() || (args < func->argCount() && args >= func->minArgCount())) { matches.push_back(func);
matches.push_back(func);
}
} }
} }
base->classScope->findFunctionInBase(tok, args, matches); base->classScope->findFunctionInBase(name, args, matches);
} }
} }
} }
@ -2989,17 +2987,15 @@ const Function* Scope::findFunction(const Token *tok) const
// find all the possible functions that could match // find all the possible functions that could match
const std::size_t args = arguments.size(); const std::size_t args = arguments.size();
for (std::list<Function>::const_iterator it = functionList.begin(); it != functionList.end(); ++it) { for (std::multimap<std::string, const Function *>::const_iterator it = functionMap.find(tok->str()); it != functionMap.end() && it->first == tok->str(); ++it) {
if (it->tokenDef->str() == tok->str()) { const Function *func = it->second;
const Function *func = &*it; if (args == func->argCount() || (args < func->argCount() && args >= func->minArgCount())) {
if (args == func->argCount() || (args < func->argCount() && args >= func->minArgCount())) { matches.push_back(func);
matches.push_back(func);
}
} }
} }
// check in base classes // check in base classes
findFunctionInBase(tok, args, matches); findFunctionInBase(tok->str(), args, matches);
// check each function against the arguments in the function call for a match // check each function against the arguments in the function call for a match
for (std::size_t i = 0; i < matches.size();) { for (std::size_t i = 0; i < matches.size();) {
@ -3451,14 +3447,11 @@ Function * SymbolDatabase::findFunctionInScope(const Token *func, const Scope *n
{ {
const Function * function = nullptr; const Function * function = nullptr;
std::list<Function>::const_iterator it; for (std::multimap<std::string, const Function *>::const_iterator it = ns->functionMap.find(func->str());
it != ns->functionMap.end() && it->first == func->str(); ++it) {
for (it = ns->functionList.begin(); it != ns->functionList.end(); ++it) { if (Function::argsMatch(ns, func->tokAt(2), it->second->argDef->next(), "", 0)) {
if (it->name() == func->str()) { function = it->second;
if (Function::argsMatch(ns, func->tokAt(2), it->argDef->next(), "", 0)) { break;
function = &*it;
break;
}
} }
} }

View File

@ -26,6 +26,7 @@
#include <vector> #include <vector>
#include <set> #include <set>
#include <algorithm> #include <algorithm>
#include <map>
#include "config.h" #include "config.h"
#include "token.h" #include "token.h"
@ -692,6 +693,7 @@ public:
const Token *classStart; // '{' token const Token *classStart; // '{' token
const Token *classEnd; // '}' token const Token *classEnd; // '}' token
std::list<Function> functionList; std::list<Function> functionList;
std::multimap<std::string, const Function *> functionMap;
std::list<Variable> varlist; std::list<Variable> varlist;
const Scope *nestedIn; const Scope *nestedIn;
std::list<Scope *> nestedList; std::list<Scope *> nestedList;
@ -763,6 +765,14 @@ public:
const Function *getDestructor() const; const Function *getDestructor() const;
void addFunction(const Function & func) {
functionList.push_back(func);
const Function * back = &functionList.back();
functionMap.insert(make_pair(back->tokenDef->str(), back));
}
/** /**
* @brief get the number of nested scopes that are not functions * @brief get the number of nested scopes that are not functions
* *
@ -800,7 +810,7 @@ private:
*/ */
bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const; bool isVariableDeclaration(const Token* tok, const Token*& vartok, const Token*& typetok) const;
void findFunctionInBase(const Token * tok, size_t args, std::vector<const Function *> & matches) const; void findFunctionInBase(const std::string & name, size_t args, std::vector<const Function *> & matches) const;
}; };
class CPPCHECKLIB SymbolDatabase { class CPPCHECKLIB SymbolDatabase {