|
16 | 16 | #include <unordered_map> |
17 | 17 | #include <string> |
18 | 18 | #include <vector> |
| 19 | +#include <cassert> |
19 | 20 |
|
20 | 21 | #include "symbolresolver.h" |
21 | 22 | #include "util.h" |
|
37 | 38 | static std::mutex g_cacheMutex; |
38 | 39 | static std::recursive_mutex g_cacheTypedefMutex; |
39 | 40 |
|
| 41 | +static std::mutex g_substMapMutex; |
| 42 | +static std::unordered_map<std::string, std::pair<QCString,const MemberDef *> > g_substMap; |
| 43 | + |
40 | 44 | //-------------------------------------------------------------------------------------- |
41 | 45 |
|
42 | 46 | /** Helper class representing the stack of items considered while resolving |
@@ -1154,6 +1158,7 @@ const Definition *SymbolResolver::Private::followPath(VisitedKeys &visitedKeys, |
1154 | 1158 | { |
1155 | 1159 | AUTO_TRACE("start={},path={}",start?start->name():QCString(), path); |
1156 | 1160 | int is=0,ps=0,l=0; |
| 1161 | + |
1157 | 1162 | const Definition *current=start; |
1158 | 1163 | // for each part of the explicit scope |
1159 | 1164 | while ((is=getScopeFragment(path,ps,&l))!=-1) |
@@ -1240,6 +1245,7 @@ const Definition *SymbolResolver::Private::followPath(VisitedKeys &visitedKeys, |
1240 | 1245 | } |
1241 | 1246 | ps=is+l; |
1242 | 1247 | } |
| 1248 | + |
1243 | 1249 | AUTO_TRACE_EXIT("result={}",current?current->name():QCString()); |
1244 | 1250 | return current; // path could be followed |
1245 | 1251 | } |
@@ -1497,6 +1503,24 @@ QCString SymbolResolver::Private::substTypedef( |
1497 | 1503 | MemberDef *bestMatch=nullptr; |
1498 | 1504 | int minDistance=10000; // init at "infinite" |
1499 | 1505 |
|
| 1506 | + std::string key; |
| 1507 | + const int maxAddrSize = 20; |
| 1508 | + char ptr_str[maxAddrSize]; |
| 1509 | + int num = qsnprintf(ptr_str,maxAddrSize,"%p:",(void *)scope); |
| 1510 | + assert(num>0); |
| 1511 | + key.reserve(num+name.length()+1); |
| 1512 | + key+=ptr_str; |
| 1513 | + key+=name.str(); |
| 1514 | + { |
| 1515 | + std::lock_guard lock(g_substMapMutex); |
| 1516 | + auto it = g_substMap.find(key); |
| 1517 | + if (it!=g_substMap.end()) |
| 1518 | + { |
| 1519 | + if (pTypeDef) *pTypeDef = it->second.second; |
| 1520 | + return it->second.first; |
| 1521 | + } |
| 1522 | + } |
| 1523 | + |
1500 | 1524 | for (Definition *d : range) |
1501 | 1525 | { |
1502 | 1526 | // only look at members |
@@ -1526,6 +1550,13 @@ QCString SymbolResolver::Private::substTypedef( |
1526 | 1550 | if (pTypeDef) *pTypeDef=bestMatch; |
1527 | 1551 | } |
1528 | 1552 |
|
| 1553 | + // cache the result of the computation to give a faster answers next time, especially relevant |
| 1554 | + // if `range` has many arguments (i.e. there are many symbols with the same name in different contexts) |
| 1555 | + { |
| 1556 | + std::lock_guard lock(g_substMapMutex); |
| 1557 | + g_substMap.emplace(key,std::make_pair(result,bestMatch)); |
| 1558 | + } |
| 1559 | + |
1529 | 1560 | AUTO_TRACE_EXIT("result={}",result); |
1530 | 1561 | return result; |
1531 | 1562 | } |
|
0 commit comments