summaryrefslogtreecommitdiffstats
path: root/qmake
diff options
context:
space:
mode:
authorOswald Buddenhagen <oswald.buddenhagen@digia.com>2013-06-03 19:08:10 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-07-19 17:15:16 +0200
commit3a6a462ad9cfcc0da6a0157bdf24b8c2254c3bb3 (patch)
tree6464158074cbd82233dfdefddf8224bf4b6af7be /qmake
parent547b7ed29ce74c164d75fec7bc80af2919d99f56 (diff)
cache results of feature search
looking up the same files in the same locations over and over again is a rather significant waste. in particular, looking up the CONFIG flags that don't correspond with features has a measurable impact on qt creator's project loading time. Task-number: QTCREATORBUG-9154 Change-Id: Ibae3d8b7797e706a6416a7d45c77734ab1281b51 Reviewed-by: Daniel Teske <daniel.teske@digia.com> (cherry picked from qtcreator/fa27cd79e05aed4ebd16d5648480cc7d48fefd43) Reviewed-by: Joerg Bornemann <joerg.bornemann@digia.com>
Diffstat (limited to 'qmake')
-rw-r--r--qmake/library/qmakeevaluator.cpp66
-rw-r--r--qmake/library/qmakeevaluator.h20
2 files changed, 62 insertions, 24 deletions
diff --git a/qmake/library/qmakeevaluator.cpp b/qmake/library/qmakeevaluator.cpp
index 85e08095a5..25e4e8511d 100644
--- a/qmake/library/qmakeevaluator.cpp
+++ b/qmake/library/qmakeevaluator.cpp
@@ -1503,7 +1503,7 @@ void QMakeEvaluator::updateFeaturePaths()
foreach (const QString &root, feature_roots)
if (IoUtils::exists(root))
ret << root;
- m_featureRoots = ret;
+ m_featureRoots = new QMakeFeatureRoots(ret);
}
ProString QMakeEvaluator::propertyValue(const ProKey &name) const
@@ -1861,35 +1861,55 @@ QMakeEvaluator::VisitReturn QMakeEvaluator::evaluateFeatureFile(
if (!fn.endsWith(QLatin1String(".prf")))
fn += QLatin1String(".prf");
- if (m_featureRoots.isEmpty())
+ if (!m_featureRoots)
updateFeaturePaths();
- int start_root = 0;
+#ifdef PROEVALUATOR_THREAD_SAFE
+ m_featureRoots->mutex.lock();
+#endif
QString currFn = currentFileName();
- if (IoUtils::fileName(currFn) == IoUtils::fileName(fn)) {
- QStringRef currPath = IoUtils::pathName(currFn);
- for (int root = 0; root < m_featureRoots.size(); ++root)
- if (currPath == m_featureRoots.at(root)) {
- start_root = root + 1;
- break;
+ if (IoUtils::fileName(currFn) != IoUtils::fileName(fn))
+ currFn.clear();
+ // Null values cannot regularly exist in the hash, so they indicate that the value still
+ // needs to be determined. Failed lookups are represented via non-null empty strings.
+ QString *fnp = &m_featureRoots->cache[qMakePair(fn, currFn)];
+ if (fnp->isNull()) {
+ int start_root = 0;
+ const QStringList &paths = m_featureRoots->paths;
+ if (!currFn.isEmpty()) {
+ QStringRef currPath = IoUtils::pathName(currFn);
+ for (int root = 0; root < paths.size(); ++root)
+ if (currPath == paths.at(root)) {
+ start_root = root + 1;
+ break;
+ }
+ }
+ for (int root = start_root; root < paths.size(); ++root) {
+ QString fname = paths.at(root) + fn;
+ if (IoUtils::exists(fname)) {
+ fn = fname;
+ goto cool;
}
- }
- for (int root = start_root; root < m_featureRoots.size(); ++root) {
- QString fname = m_featureRoots.at(root) + fn;
- if (IoUtils::exists(fname)) {
- fn = fname;
- goto cool;
}
- }
#ifdef QMAKE_BUILTIN_PRFS
- fn.prepend(QLatin1String(":/qmake/features/"));
- if (QFileInfo(fn).exists())
- goto cool;
+ fn.prepend(QLatin1String(":/qmake/features/"));
+ if (QFileInfo(fn).exists())
+ goto cool;
#endif
- if (!silent)
- evalError(fL1S("Cannot find feature %1").arg(fileName));
- return ReturnFalse;
+ fn = QLatin1String(""); // Indicate failed lookup. See comment above.
- cool:
+ cool:
+ *fnp = fn;
+ } else {
+ fn = *fnp;
+ }
+#ifdef PROEVALUATOR_THREAD_SAFE
+ m_featureRoots->mutex.unlock();
+#endif
+ if (fn.isEmpty()) {
+ if (!silent)
+ evalError(fL1S("Cannot find feature %1").arg(fileName));
+ return ReturnFalse;
+ }
ProStringList &already = valuesRef(ProKey("QMAKE_INTERNAL_INCLUDED_FEATURES"));
ProString afn(fn);
if (already.contains(afn)) {
diff --git a/qmake/library/qmakeevaluator.h b/qmake/library/qmakeevaluator.h
index 09617ba019..91433302d0 100644
--- a/qmake/library/qmakeevaluator.h
+++ b/qmake/library/qmakeevaluator.h
@@ -55,9 +55,13 @@
#include <qstack.h>
#include <qstring.h>
#include <qstringlist.h>
+#include <qshareddata.h>
#ifndef QT_BOOTSTRAPPED
# include <qprocess.h>
#endif
+#ifdef PROEVALUATOR_THREAD_SAFE
+# include <qmutex.h>
+#endif
QT_BEGIN_NAMESPACE
@@ -83,6 +87,20 @@ public:
virtual void doneWithEval(ProFile *parent) = 0;
};
+typedef QPair<QString, QString> QMakeFeatureKey; // key, parent
+typedef QHash<QMakeFeatureKey, QString> QMakeFeatureHash;
+
+class QMAKE_EXPORT QMakeFeatureRoots : public QSharedData
+{
+public:
+ QMakeFeatureRoots(const QStringList &_paths) : paths(_paths) {}
+ const QStringList paths;
+ mutable QMakeFeatureHash cache;
+#ifdef PROEVALUATOR_THREAD_SAFE
+ mutable QMutex mutex;
+#endif
+};
+
// We use a QLinkedList based stack instead of a QVector based one (QStack), so that
// the addresses of value maps stay constant. The qmake generators rely on that.
class QMAKE_EXPORT ProValueMapStack : public QLinkedList<ProValueMap>
@@ -284,7 +302,7 @@ public:
QStringList m_qmakepath;
QStringList m_qmakefeatures;
QStringList m_mkspecPaths;
- QStringList m_featureRoots;
+ QExplicitlySharedDataPointer<QMakeFeatureRoots> m_featureRoots;
ProString m_dirSep;
ProFunctionDefs m_functionDefs;
ProStringList m_returnValue;