diff options
author | Nikolai Kosjar <nikolai.kosjar@qt.io> | 2018-10-08 12:15:20 +0200 |
---|---|---|
committer | Nikolai Kosjar <nikolai.kosjar@qt.io> | 2018-10-10 06:49:13 +0000 |
commit | feae30d7adefaa4ea79d3f48dbf8dd689715676f (patch) | |
tree | 24656425c76d076f0594bf8ed1d78333c8e333ec | |
parent | eb01565c9917327db12800e480e6ee80f3f0b1db (diff) | |
download | qt-creator-feae30d7adefaa4ea79d3f48dbf8dd689715676f.tar.gz |
ProjectExplorer/MSVC: Cache more predefined macros
...as for the gcc toolchain. Do not cache only the "last" predefined
macros, but cache them all.
Change-Id: I404955e7419089bb03f7d354488f8b9980e8583b
Reviewed-by: David Schulz <david.schulz@qt.io>
Reviewed-by: Ivan Donchevskii <ivan.donchevskii@qt.io>
-rw-r--r-- | src/plugins/projectexplorer/abstractmsvctoolchain.cpp | 45 | ||||
-rw-r--r-- | src/plugins/projectexplorer/abstractmsvctoolchain.h | 6 | ||||
-rw-r--r-- | src/plugins/projectexplorer/gcctoolchain.h | 78 | ||||
-rw-r--r-- | src/plugins/projectexplorer/msvctoolchain.cpp | 2 | ||||
-rw-r--r-- | src/plugins/projectexplorer/projectexplorer.pro | 1 | ||||
-rw-r--r-- | src/plugins/projectexplorer/projectexplorer.qbs | 1 | ||||
-rw-r--r-- | src/plugins/projectexplorer/toolchaincache.h | 110 |
7 files changed, 148 insertions, 95 deletions
diff --git a/src/plugins/projectexplorer/abstractmsvctoolchain.cpp b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp index 9cbed08156..3983734c75 100644 --- a/src/plugins/projectexplorer/abstractmsvctoolchain.cpp +++ b/src/plugins/projectexplorer/abstractmsvctoolchain.cpp @@ -29,6 +29,7 @@ #include "projectexplorer.h" #include "projectexplorersettings.h" #include "taskhub.h" +#include "toolchaincache.h" #include <utils/hostosinfo.h> #include <utils/qtcprocess.h> @@ -46,7 +47,7 @@ namespace Internal { AbstractMsvcToolChain::AbstractMsvcToolChain(Core::Id typeId, Core::Id l, Detection d, const Abi &abi, const QString& vcvarsBat) : ToolChain(typeId, d), - m_predefinedMacrosMutex(new QMutex), + m_predefinedMacrosCache(std::make_shared<Cache<MacroInspectionReport, 64>>()), m_lastEnvironment(Utils::Environment::systemEnvironment()), m_headerPathsMutex(new QMutex), m_abi(abi), @@ -57,20 +58,18 @@ AbstractMsvcToolChain::AbstractMsvcToolChain(Core::Id typeId, Core::Id l, Detect AbstractMsvcToolChain::AbstractMsvcToolChain(Core::Id typeId, Detection d) : ToolChain(typeId, d), + m_predefinedMacrosCache(std::make_shared<Cache<MacroInspectionReport, 64>>()), m_lastEnvironment(Utils::Environment::systemEnvironment()) { } AbstractMsvcToolChain::~AbstractMsvcToolChain() { - delete m_predefinedMacrosMutex; delete m_headerPathsMutex; } AbstractMsvcToolChain::AbstractMsvcToolChain(const AbstractMsvcToolChain &other) : ToolChain(other), m_debuggerCommand(other.m_debuggerCommand), - m_predefinedMacrosMutex(new QMutex), - m_predefinedMacros(other.m_predefinedMacros), m_lastEnvironment(other.m_lastEnvironment), m_resultEnvironment(other.m_resultEnvironment), m_headerPathsMutex(new QMutex), @@ -147,6 +146,13 @@ LanguageVersion static languageVersionForMsvc(const Core::Id &language, const Ma } } +bool static hasFlagEffectOnMacros(const QString &arg) +{ + if (arg.startsWith("-I")) + return false; + return true; +} + Q_GLOBAL_STATIC_WITH_ARGS(const QVector<QByteArray>, unwantedMacrosMsvc, ({"_MSVC_LANG", "_MSC_BUILD", @@ -157,21 +163,29 @@ ToolChain::MacroInspectionRunner AbstractMsvcToolChain::createMacroInspectionRun { Utils::Environment env(m_lastEnvironment); addToEnvironment(env); + std::shared_ptr<Cache<MacroInspectionReport, 64>> macroCache = m_predefinedMacrosCache; const Core::Id lang = language(); // This runner must be thread-safe! - return [this, env, lang](const QStringList &cxxflags) { - QMutexLocker locker(m_predefinedMacrosMutex); - if (m_predefinedMacros.isEmpty() || m_cxxFlags != cxxflags) { - m_predefinedMacros = msvcPredefinedMacros(cxxflags, env); - m_cxxFlags = cxxflags; - } + return [this, env, macroCache, lang](const QStringList &cxxflags) { + const QStringList filteredFlags = Utils::filtered(cxxflags, [](const QString &arg) { + return hasFlagEffectOnMacros(arg); + }); - const QVector<Macro> filteredMacros = Utils::filtered(m_predefinedMacros, [](const Macro &m) { + const Utils::optional<MacroInspectionReport> cachedMacros = macroCache->check(filteredFlags); + if (cachedMacros) + return cachedMacros.value(); + + const Macros macros = msvcPredefinedMacros(filteredFlags, env); + const QVector<Macro> filteredMacros = Utils::filtered(macros, [](const Macro &m) { return !ToolChain::isUnwantedMacro(m) && !unwantedMacrosMsvc->contains(m.key); }); - return MacroInspectionReport{filteredMacros, - languageVersionForMsvc(lang, m_predefinedMacros)}; + + const auto report = MacroInspectionReport{filteredMacros, + languageVersionForMsvc(lang, macros)}; + macroCache->insert(filteredFlags, report); + + return report; }; } @@ -460,6 +474,11 @@ void AbstractMsvcToolChain::inferWarningsForLevel(int warningLevel, WarningFlags flags |= WarningFlags::UnusedParams; } +void Internal::AbstractMsvcToolChain::toolChainUpdated() +{ + m_predefinedMacrosCache->invalidate(); +} + bool AbstractMsvcToolChain::operator ==(const ToolChain &other) const { if (!ToolChain::operator ==(other)) diff --git a/src/plugins/projectexplorer/abstractmsvctoolchain.h b/src/plugins/projectexplorer/abstractmsvctoolchain.h index bc6b297e74..a0836e4dc6 100644 --- a/src/plugins/projectexplorer/abstractmsvctoolchain.h +++ b/src/plugins/projectexplorer/abstractmsvctoolchain.h @@ -26,6 +26,7 @@ #pragma once #include "toolchain.h" +#include "toolchaincache.h" #include "abi.h" #include "headerpath.h" @@ -92,6 +93,7 @@ protected: }; static void inferWarningsForLevel(int warningLevel, WarningFlags &flags); + void toolChainUpdated() override; virtual Utils::Environment readEnvironmentSetting(const Utils::Environment& env) const = 0; // Function must be thread-safe! virtual Macros msvcPredefinedMacros(const QStringList cxxflags, @@ -100,9 +102,7 @@ protected: Utils::FileName m_debuggerCommand; - mutable QMutex *m_predefinedMacrosMutex = nullptr; - mutable Macros m_predefinedMacros; - mutable QStringList m_cxxFlags; + mutable std::shared_ptr<Cache<MacroInspectionReport, 64>> m_predefinedMacrosCache; mutable Utils::Environment m_lastEnvironment; // Last checked 'incoming' environment. mutable Utils::Environment m_resultEnvironment; // Resulting environment for VC diff --git a/src/plugins/projectexplorer/gcctoolchain.h b/src/plugins/projectexplorer/gcctoolchain.h index 63c2b78a44..13685101fd 100644 --- a/src/plugins/projectexplorer/gcctoolchain.h +++ b/src/plugins/projectexplorer/gcctoolchain.h @@ -28,14 +28,11 @@ #include "projectexplorer_export.h" #include "toolchain.h" +#include "toolchaincache.h" #include "abi.h" #include "headerpath.h" #include <utils/fileutils.h> -#include <utils/optional.h> - -#include <QMutex> -#include <QStringList> #include <functional> #include <memory> @@ -54,79 +51,6 @@ class LinuxIccToolChainFactory; // GccToolChain // -------------------------------------------------------------------------- -template<class T, int Size = 16> -class Cache -{ -public: - Cache() { m_cache.reserve(Size); } - Cache(const Cache &other) = delete; - Cache &operator =(const Cache &other) = delete; - - Cache(Cache &&other) - { - using std::swap; - - QMutexLocker otherLocker(&other.m_mutex); - swap(m_cache, other.m_cache); - } - - Cache &operator =(Cache &&other) - { - using std::swap; - - QMutexLocker locker(&m_mutex); - QMutexLocker otherLocker(&other.m_mutex); - auto temporay(std::move(other.m_cache)); // Make sure other.m_cache is empty! - swap(m_cache, temporay); - return *this; - } - - void insert(const QStringList &compilerArguments, const T &values) - { - CacheItem runResults; - runResults.first = compilerArguments; - runResults.second = values; - - QMutexLocker locker(&m_mutex); - if (!checkImpl(compilerArguments)) { - if (m_cache.size() < Size) { - m_cache.push_back(runResults); - } else { - std::rotate(m_cache.begin(), std::next(m_cache.begin()), m_cache.end()); - m_cache.back() = runResults; - } - } - } - - Utils::optional<T> check(const QStringList &compilerArguments) - { - QMutexLocker locker(&m_mutex); - return checkImpl(compilerArguments); - } - - void invalidate() - { - QMutexLocker locker(&m_mutex); - m_cache.clear(); - } - -private: - Utils::optional<T> checkImpl(const QStringList &compilerArguments) - { - auto it = std::stable_partition(m_cache.begin(), m_cache.end(), [&](const CacheItem &ci) { - return ci.first != compilerArguments; - }); - if (it != m_cache.end()) - return m_cache.back().second; - return {}; - } - - using CacheItem = QPair<QStringList, T>; - - QMutex m_mutex; - QVector<CacheItem> m_cache; -}; - class PROJECTEXPLORER_EXPORT GccToolChain : public ToolChain { public: diff --git a/src/plugins/projectexplorer/msvctoolchain.cpp b/src/plugins/projectexplorer/msvctoolchain.cpp index 7fb74661ec..50c3a9d369 100644 --- a/src/plugins/projectexplorer/msvctoolchain.cpp +++ b/src/plugins/projectexplorer/msvctoolchain.cpp @@ -470,8 +470,6 @@ Macros MsvcToolChain::msvcPredefinedMacros(const QStringList cxxflags, predefinedMacros.append(Macro::fromKeyValue(define)); } else if (arg.startsWith(QLatin1String("/U"))) { predefinedMacros.append({arg.mid(2).toLocal8Bit(), ProjectExplorer::MacroType::Undefine}); - } else if (arg.startsWith(QLatin1String("-I"))) { - // Include paths should not have any effect on defines } else { toProcess.append(arg); } diff --git a/src/plugins/projectexplorer/projectexplorer.pro b/src/plugins/projectexplorer/projectexplorer.pro index 8e21d9a0dd..adb2d74e37 100644 --- a/src/plugins/projectexplorer/projectexplorer.pro +++ b/src/plugins/projectexplorer/projectexplorer.pro @@ -89,6 +89,7 @@ HEADERS += projectexplorer.h \ projectmodels.h \ currentprojectfind.h \ toolchain.h \ + toolchaincache.h \ toolchainconfigwidget.h \ toolchainmanager.h \ toolchainoptionspage.h \ diff --git a/src/plugins/projectexplorer/projectexplorer.qbs b/src/plugins/projectexplorer/projectexplorer.qbs index 58646326fa..148d9f3057 100644 --- a/src/plugins/projectexplorer/projectexplorer.qbs +++ b/src/plugins/projectexplorer/projectexplorer.qbs @@ -145,6 +145,7 @@ Project { "taskmodel.cpp", "taskmodel.h", "taskwindow.cpp", "taskwindow.h", "toolchain.cpp", "toolchain.h", + "toolchaincache.h", "toolchainconfigwidget.cpp", "toolchainconfigwidget.h", "toolchainmanager.cpp", "toolchainmanager.h", "toolchainoptionspage.cpp", "toolchainoptionspage.h", diff --git a/src/plugins/projectexplorer/toolchaincache.h b/src/plugins/projectexplorer/toolchaincache.h new file mode 100644 index 0000000000..154c09162f --- /dev/null +++ b/src/plugins/projectexplorer/toolchaincache.h @@ -0,0 +1,110 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of Qt Creator. +** +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +****************************************************************************/ + +#pragma once + +#include <QMutex> +#include <QMutexLocker> +#include <QStringList> +#include <QVector> + +#include <utils/optional.h> + +namespace ProjectExplorer { + +template<class T, int Size = 16> +class Cache +{ +public: + Cache() { m_cache.reserve(Size); } + Cache(const Cache &other) = delete; + Cache &operator =(const Cache &other) = delete; + + Cache(Cache &&other) + { + using std::swap; + + QMutexLocker otherLocker(&other.m_mutex); + swap(m_cache, other.m_cache); + } + + Cache &operator =(Cache &&other) + { + using std::swap; + + QMutexLocker locker(&m_mutex); + QMutexLocker otherLocker(&other.m_mutex); + auto temporay(std::move(other.m_cache)); // Make sure other.m_cache is empty! + swap(m_cache, temporay); + return *this; + } + + void insert(const QStringList &compilerArguments, const T &values) + { + CacheItem runResults; + runResults.first = compilerArguments; + runResults.second = values; + + QMutexLocker locker(&m_mutex); + if (!checkImpl(compilerArguments)) { + if (m_cache.size() < Size) { + m_cache.push_back(runResults); + } else { + std::rotate(m_cache.begin(), std::next(m_cache.begin()), m_cache.end()); + m_cache.back() = runResults; + } + } + } + + Utils::optional<T> check(const QStringList &compilerArguments) + { + QMutexLocker locker(&m_mutex); + return checkImpl(compilerArguments); + } + + void invalidate() + { + QMutexLocker locker(&m_mutex); + m_cache.clear(); + } + +private: + Utils::optional<T> checkImpl(const QStringList &compilerArguments) + { + auto it = std::stable_partition(m_cache.begin(), m_cache.end(), [&](const CacheItem &ci) { + return ci.first != compilerArguments; + }); + if (it != m_cache.end()) + return m_cache.back().second; + return {}; + } + + using CacheItem = QPair<QStringList, T>; + + QMutex m_mutex; + QVector<CacheItem> m_cache; +}; + +} // namespace ProjectExplorer |