From fd7813eeec6ebfb53bd2d972128067760d6c475c Mon Sep 17 00:00:00 2001 From: Zelentsov Dmitry Date: Tue, 2 Sep 2025 13:41:58 +0300 Subject: [PATCH] Use declaration cache only from driver Issue: https://gitee.com/openharmony/arkcompiler_ets_frontend/issues/ICW1OU Tests: use Test-U-Runner and CI Signed-off-by: Zelentsov Dmitry --- ets2panda/compiler/core/compilerImpl.cpp | 15 +++-- ets2panda/parser/ETSparser.cpp | 47 +++++++++----- ets2panda/parser/ETSparser.h | 5 +- ets2panda/parser/program/DeclarationCache.cpp | 63 ++++++++++++++++--- ets2panda/parser/program/DeclarationCache.h | 28 ++++++--- ets2panda/util/options.yaml | 7 ++- 6 files changed, 121 insertions(+), 44 deletions(-) diff --git a/ets2panda/compiler/core/compilerImpl.cpp b/ets2panda/compiler/core/compilerImpl.cpp index 01ee4a204c..9241405012 100644 --- a/ets2panda/compiler/core/compilerImpl.cpp +++ b/ets2panda/compiler/core/compilerImpl.cpp @@ -122,9 +122,8 @@ void HandleGenerateDecl(const parser::Program &program, util::DiagnosticEngine & outFile << result; outFile.close(); - // Add generated declaration to the cache - auto &declarationCache = parser::DeclarationCache::Instance(); - declarationCache.AddDeclaration(outputPath, std::make_shared(std::move(result))); + // Try to add generated declaration to the cache (if it is activated) + parser::DeclarationCache::CacheIfPossible(outputPath, std::make_shared(std::move(result))); } static bool CheckOptionsAfterPhase(const util::Options &options, const parser::Program &program, @@ -369,9 +368,13 @@ static bool ExecuteParsingAndCompiling(const CompilationUnit &unit, public_lib:: { ES2PANDA_PERF_SCOPE("@phases"); parser::Program *program = context->parserProgram; - if (unit.ext == ScriptExtension::ETS && - context->compilingState == public_lib::CompilingState::MULTI_COMPILING_FOLLOW) { - AddExternalPrograms(context, unit, program); + if (unit.ext == ScriptExtension::ETS) { + if (context->config->options->IsUseDeclarationCache()) { + parser::DeclarationCache::ActivateCache(); + } + if (context->compilingState == public_lib::CompilingState::MULTI_COMPILING_FOLLOW) { + AddExternalPrograms(context, unit, program); + } } if (context->config->options->GetCompilationMode() == CompilationMode::GEN_ABC_FOR_EXTERNAL_SOURCE && diff --git a/ets2panda/parser/ETSparser.cpp b/ets2panda/parser/ETSparser.cpp index 0ede9666e1..9e1d99f680 100644 --- a/ets2panda/parser/ETSparser.cpp +++ b/ets2panda/parser/ETSparser.cpp @@ -14,13 +14,12 @@ */ #include "ETSparser.h" +#include #include "ETSNolintParser.h" #include "program/program.h" +#include "program/DeclarationCache.h" #include "public/public.h" -#include -#include "util/es2pandaMacros.h" -#include "parser/parserFlags.h" #include "parser/parserStatusContext.h" #include "util/helpers.h" #include "util/language.h" @@ -364,19 +363,18 @@ static bool SearchImportedExternalSources(ETSParser *parser, const std::string_v return false; } -bool ETSParser::TryMergeFromCache(size_t idx, ArenaVector &parseList) +bool ETSParser::TryMergeFromCache(util::ImportPathManager::ImportMetadata const &importData) { if (Context()->globalContext == nullptr) { return false; } - auto &importData = parseList[idx].importData; auto src = importData.HasSpecifiedDeclPath() ? importData.declPath : importData.resolvedSource; const auto &absPath = std::string {util::Path {src, Allocator()}.GetAbsolutePath()}; auto cacheExtProgs = Context()->globalContext->cachedExternalPrograms; if (cacheExtProgs.find(absPath) != cacheExtProgs.end() && cacheExtProgs[absPath] != nullptr) { if (globalProgram_->MergeExternalSource(cacheExtProgs[absPath])) { - importPathManager_->MarkAsParsed(parseList[idx].importData.resolvedSource); + importPathManager_->MarkAsParsed(importData.resolvedSource); return true; } } @@ -384,24 +382,39 @@ bool ETSParser::TryMergeFromCache(size_t idx, ArenaVector ETSParser::GetDeclarationSource(std::string &&fileToParse) const { - static auto &declarationCache = DeclarationCache::Instance(); - - auto declaration = declarationCache.GetDeclaration(fileToParse); - if (declaration == DeclarationCache::ABSENT) { + auto const readFromFile = [this, &fileToParse]() -> std::optional { if (std::ifstream inputStream {fileToParse}; !inputStream) { util::DiagnosticMessageParams diagParams = {std::move(fileToParse)}; DiagnosticEngine().LogDiagnostic(diagnostic::OPEN_FAILED, diagParams); + return std::nullopt; } else { std::stringstream ss {}; ss << inputStream.rdbuf(); - declaration = - declarationCache.AddDeclaration(std::move(fileToParse), std::make_shared(ss.str())); + return std::make_optional(ss.str()); + } + }; + + if (!DeclarationCache::IsCacheActivated()) { + auto externalSource = readFromFile(); + if (!externalSource.has_value()) { + return std::nullopt; + } + return std::make_optional(Allocator()->New(*externalSource, Allocator())->View().Utf8()); + } + + auto declaration = DeclarationCache::GetFromCache(fileToParse); + if (declaration == DeclarationCache::ABSENT) { + auto externalSource = readFromFile(); + if (!externalSource.has_value()) { + return std::nullopt; } + declaration = DeclarationCache::CacheIfPossible(std::move(fileToParse), + std::make_shared(std::move(*externalSource))); } - return declaration; + return std::make_optional(std::string_view {*declaration}); } std::vector ETSParser::SearchForNotParsed(ArenaVector &parseList, @@ -421,7 +434,7 @@ std::vector ETSParser::SearchForNotParsed(ArenaVectorisParsed = true; const auto &data = notParsedElement->importData; - if (data.declPath.empty()) { + if (data.declPath.empty() || TryMergeFromCache(data)) { notParsedElement = findNotParsed(); continue; } @@ -437,8 +450,8 @@ std::vector ETSParser::SearchForNotParsed(ArenaVector ParseETSInitModuleStatements(); ir::Statement *ParseImportDeclarationHelper(lexer::SourcePosition startLoc, ArenaVector &specifiers, ir::ImportKinds importKind); - bool TryMergeFromCache(size_t idx, ArenaVector &parseList); + bool TryMergeFromCache(util::ImportPathManager::ImportMetadata const &importData); - DeclarationType GetDeclaration(std::string &&fileToParse) const; + std::optional GetDeclarationSource(std::string &&fileToParse) const; std::vector SearchForNotParsed(ArenaVector &parseList, ArenaVector &directImportsFromMainSource); parser::Program *ParseSource(const SourceFile &sourceFile); diff --git a/ets2panda/parser/program/DeclarationCache.cpp b/ets2panda/parser/program/DeclarationCache.cpp index cb103fb184..017abdb769 100644 --- a/ets2panda/parser/program/DeclarationCache.cpp +++ b/ets2panda/parser/program/DeclarationCache.cpp @@ -59,7 +59,7 @@ void ReadWriteSpinMutex::lock_shared() // Atomic with relaxed order reason: read of field while (spin_.load(std::memory_order_relaxed) < LOCK_OFF || // Atomic with acquire order reason: other threads should see correct value - spin_.fetch_add(1, std::memory_order_acquire) < LOCK_OFF) { + spin_.fetch_add(1, std::memory_order_acquire) <= LOCK_OFF) { std::this_thread::yield(); } } @@ -77,7 +77,7 @@ bool ReadWriteSpinMutex::try_lock_shared() // Atomic with relaxed order reason: read of field return spin_.load(std::memory_order_relaxed) >= LOCK_OFF && // Atomic with acquire order reason: other threads should see correct value - spin_.fetch_add(1, std::memory_order_acquire) >= LOCK_OFF; + spin_.fetch_add(1, std::memory_order_acquire) > LOCK_OFF; } DeclarationCache::~DeclarationCache() @@ -85,32 +85,75 @@ DeclarationCache::~DeclarationCache() ClearAll(); } -DeclarationCache::DeclarationCache([[maybe_unused]] Tag &&tag) {} +constexpr std::size_t INITIAL_CACHE_SIZE = 256U; + +DeclarationCache::DeclarationCache([[maybe_unused]] Tag &&tag) +{ + declarations_.reserve(INITIAL_CACHE_SIZE); +} //--------------------------------------------------------------------------------------------------------// // Creates the new instance of DeclarationCache class (a singleton object) //--------------------------------------------------------------------------------------------------------// -DeclarationCache &DeclarationCache::Instance() +void DeclarationCache::ActivateCache() { - if (!DeclarationCache::globalDeclarationCache_) { - DeclarationCache::globalDeclarationCache_ = std::make_unique(DeclarationCache::Tag {}); + std::scoped_lock lock(globalGuard_); + if (!static_cast(DeclarationCache::globalDeclarationCache_)) { + DeclarationCache::globalDeclarationCache_ = std::make_shared(DeclarationCache::Tag {}); } - return *DeclarationCache::globalDeclarationCache_; +} + +bool DeclarationCache::IsCacheActivated() noexcept +{ + std::shared_lock lock(globalGuard_); + return static_cast(DeclarationCache::globalDeclarationCache_); +} + +std::shared_ptr DeclarationCache::Instance() noexcept +{ + std::shared_lock lock(globalGuard_); + return DeclarationCache::globalDeclarationCache_; } void DeclarationCache::ClearAll() noexcept +{ + if (auto cache = DeclarationCache::Instance(); static_cast(cache)) { + cache->Clear(); + } +} + +void DeclarationCache::RemoveFromCache(std::string const &fileName) noexcept +{ + if (auto cache = DeclarationCache::Instance(); static_cast(cache)) { + cache->Remove(fileName); + } +} + +DeclarationType DeclarationCache::GetFromCache(std::string const &fileName) noexcept +{ + auto cache = DeclarationCache::Instance(); + return static_cast(cache) ? cache->Get(fileName) : ABSENT; +} + +DeclarationType DeclarationCache::CacheIfPossible(std::string fileName, DeclarationType decl) +{ + auto cache = DeclarationCache::Instance(); + return static_cast(cache) ? cache->Add(std::move(fileName), std::move(decl)) : decl; +} + +void DeclarationCache::Clear() noexcept { std::scoped_lock lock(dataGuard_); declarations_.clear(); } -void DeclarationCache::RemoveDeclaration(std::string const &fileName) noexcept +void DeclarationCache::Remove(std::string const &fileName) noexcept { std::scoped_lock lock(dataGuard_); declarations_.erase(fileName); } -DeclarationType DeclarationCache::GetDeclaration(std::string const &fileName) const noexcept +DeclarationType DeclarationCache::Get(std::string const &fileName) const noexcept { std::shared_lock lock(dataGuard_); auto const it = declarations_.find(fileName); @@ -120,7 +163,7 @@ DeclarationType DeclarationCache::GetDeclaration(std::string const &fileName) co //--------------------------------------------------------------------------------------------------------// // Adds specified declaration file to the cache (or replaces the existing one). //--------------------------------------------------------------------------------------------------------// -DeclarationType DeclarationCache::AddDeclaration(std::string fileName, DeclarationType decl) +DeclarationType DeclarationCache::Add(std::string fileName, DeclarationType decl) { std::scoped_lock lock(dataGuard_); auto [it, _] = declarations_.insert_or_assign(std::move(fileName), std::move(decl)); diff --git a/ets2panda/parser/program/DeclarationCache.h b/ets2panda/parser/program/DeclarationCache.h index a21e3889d7..b245bb860b 100644 --- a/ets2panda/parser/program/DeclarationCache.h +++ b/ets2panda/parser/program/DeclarationCache.h @@ -19,6 +19,7 @@ #include #include #include +#include #include #include @@ -93,23 +94,36 @@ public: explicit DeclarationCache(Tag &&tag); - static DeclarationCache &Instance(); + static void ActivateCache(); - void ClearAll() noexcept; + [[nodiscard]] static bool IsCacheActivated() noexcept; - void RemoveDeclaration(std::string const &fileName) noexcept; + static void ClearAll() noexcept; - DeclarationType GetDeclaration(std::string const &fileName) const noexcept; + static void RemoveFromCache(std::string const &fileName) noexcept; - DeclarationType AddDeclaration(std::string fileName, DeclarationType decl); + [[nodiscard]] static DeclarationType GetFromCache(std::string const &fileName) noexcept; + + static DeclarationType CacheIfPossible(std::string fileName, DeclarationType decl); private: - inline static std::unique_ptr globalDeclarationCache_ = nullptr; + static std::shared_ptr Instance() noexcept; - std::unordered_map declarations_ {}; + void Clear() noexcept; + void Remove(std::string const &fileName) noexcept; + + DeclarationType Get(std::string const &fileName) const noexcept; + DeclarationType Add(std::string fileName, DeclarationType decl); + +private: +private: + inline static std::shared_mutex globalGuard_ {}; + inline static std::shared_ptr globalDeclarationCache_ = nullptr; +private: // Synchronization object to control access to cached data: mutable ReadWriteSpinMutex dataGuard_ {}; + std::unordered_map declarations_ {}; }; } // namespace ark::es2panda::parser diff --git a/ets2panda/util/options.yaml b/ets2panda/util/options.yaml index a27bac139c..4da1349603 100644 --- a/ets2panda/util/options.yaml +++ b/ets2panda/util/options.yaml @@ -380,11 +380,16 @@ options: default: false description: Dump es2panda performance metrics -- name: simultaneous +- name: simultaneous type: bool default: false description: compile all the files to abc in once. +- name: use-declaration-cache + type: bool + default: false + description: Activate and use common internal cache for generated declarations. + #26986 - name: ets-strings-concat type: bool -- Gitee