From f61d50526ecfe971dbd920f644035f2d62840e93 Mon Sep 17 00:00:00 2001 From: Vyacheslav Cherkashin Date: Wed, 11 Jun 2025 22:28:50 +0300 Subject: [PATCH] Speed up checker::RelationHolder Issue: #ICFICM Signed-off-by: Vyacheslav Cherkashin --- ets2panda/checker/checker.cpp | 10 ++-- ets2panda/checker/checker.h | 10 ++-- ets2panda/checker/types/type.h | 7 +-- ets2panda/checker/types/typeRelation.cpp | 28 ++++++----- ets2panda/checker/types/typeRelation.h | 60 ++++++++++++------------ 5 files changed, 58 insertions(+), 57 deletions(-) diff --git a/ets2panda/checker/checker.cpp b/ets2panda/checker/checker.cpp index 39c4be1b59..74c90e7452 100644 --- a/ets2panda/checker/checker.cpp +++ b/ets2panda/checker/checker.cpp @@ -183,11 +183,11 @@ void Checker::CleanUp() } context_ = CheckerContext(this, CheckerStatus::NO_OPTS); relation_ = allocator_->New(this); - identicalResults_.cached.clear(); - assignableResults_.cached.clear(); - comparableResults_.cached.clear(); - uncheckedCastableResults_.cached.clear(); - supertypeResults_.cached.clear(); + identicalResults_.Clear(); + assignableResults_.Clear(); + comparableResults_.Clear(); + uncheckedCastableResults_.Clear(); + supertypeResults_.Clear(); typeStack_.clear(); namedTypeStack_.clear(); } diff --git a/ets2panda/checker/checker.h b/ets2panda/checker/checker.h index c41af2dbd8..475bf73ce8 100644 --- a/ets2panda/checker/checker.h +++ b/ets2panda/checker/checker.h @@ -255,11 +255,11 @@ private: varbinder::Scope *scope_ {}; util::DiagnosticEngine &diagnosticEngine_; - RelationHolder identicalResults_ {Allocator(), RelationType::IDENTICAL}; - RelationHolder assignableResults_ {Allocator(), RelationType::ASSIGNABLE}; - RelationHolder comparableResults_ {Allocator(), RelationType::COMPARABLE}; - RelationHolder uncheckedCastableResults_ {Allocator(), RelationType::UNCHECKED_CASTABLE}; - RelationHolder supertypeResults_ {Allocator(), RelationType::SUPERTYPE}; + RelationHolder identicalResults_ {Allocator()}; + RelationHolder assignableResults_ {Allocator()}; + RelationHolder comparableResults_ {Allocator()}; + RelationHolder uncheckedCastableResults_ {Allocator()}; + RelationHolder supertypeResults_ {Allocator()}; std::unordered_map typeStack_; std::unordered_set namedTypeStack_; diff --git a/ets2panda/checker/types/type.h b/ets2panda/checker/types/type.h index d3f83e9d37..76571861aa 100644 --- a/ets2panda/checker/types/type.h +++ b/ets2panda/checker/types/type.h @@ -50,7 +50,8 @@ public: explicit Type(TypeFlag flag) : typeFlags_(flag) { std::lock_guard lock(idLock_); - static uint64_t typeId = 0; + static uint32_t typeId = 0; + ES2PANDA_ASSERT(typeId < std::numeric_limits::max()); id_ = ++typeId; } @@ -180,7 +181,7 @@ public: typeFlags_ &= ~typeFlag; } - uint64_t Id() const + uint32_t Id() const { return id_; } @@ -272,7 +273,7 @@ protected: // NOLINTBEGIN(misc-non-private-member-variables-in-classes) TypeFlag typeFlags_; varbinder::Variable *variable_ {}; // Variable associated with the type if any - uint64_t id_; + uint32_t id_; // NOLINTEND(misc-non-private-member-variables-in-classes) }; diff --git a/ets2panda/checker/types/typeRelation.cpp b/ets2panda/checker/types/typeRelation.cpp index a9a9e59d95..130fa19dbb 100644 --- a/ets2panda/checker/types/typeRelation.cpp +++ b/ets2panda/checker/types/typeRelation.cpp @@ -36,17 +36,17 @@ RelationResult TypeRelation::CacheLookup(const Type *source, const Type *target, ES2PANDA_ASSERT(source != nullptr); ES2PANDA_ASSERT(target != nullptr); - RelationKey relationKey {source->Id(), target->Id()}; - auto res = holder.cached.find(relationKey); - if (res == holder.cached.end()) { + auto key = RelationHolder::MakeKey(source->Id(), target->Id()); + auto res = holder.Find(key); + if (res == nullptr) { return RelationResult::CACHE_MISS; } - if (res->second.type >= type && res->second.result == RelationResult::TRUE) { + if (res->type >= type && res->result == RelationResult::TRUE) { return RelationResult::TRUE; } - if (res->second.type <= type && res->second.result == RelationResult::FALSE) { + if (res->type <= type && res->result == RelationResult::FALSE) { return RelationResult::FALSE; } @@ -69,7 +69,8 @@ bool TypeRelation::IsIdenticalTo(Type *source, Type *target) checker_->ResolveStructuredTypeMembers(target); result_ = RelationResult::FALSE; target->Identical(this, source); - checker_->IdenticalResults().cached.insert({{source->Id(), target->Id()}, {result_, RelationType::IDENTICAL}}); + auto key = RelationHolder::MakeKey(source->Id(), target->Id()); + checker_->IdenticalResults().Insert(key, {result_, RelationType::IDENTICAL}); } return IsTrue(); @@ -143,8 +144,8 @@ bool TypeRelation::IsAssignableTo(Type *source, Type *target) } if (flags_ == TypeRelationFlag::NONE) { - checker_->AssignableResults().cached.insert( - {{source->Id(), target->Id()}, {result_, RelationType::ASSIGNABLE}}); + auto key = RelationHolder::MakeKey(source->Id(), target->Id()); + checker_->AssignableResults().Insert(key, {result_, RelationType::ASSIGNABLE}); } } @@ -161,8 +162,8 @@ bool TypeRelation::IsComparableTo(Type *source, Type *target) result_ = RelationResult::FALSE; target->Compare(this, source); - checker_->ComparableResults().cached.insert( - {{source->Id(), target->Id()}, {result_, RelationType::COMPARABLE}}); + auto key = RelationHolder::MakeKey(source->Id(), target->Id()); + checker_->ComparableResults().Insert(key, {result_, RelationType::COMPARABLE}); } return result_ == RelationResult::TRUE; @@ -185,8 +186,8 @@ bool TypeRelation::IsCastableTo(Type *const source, Type *const target) } if (UncheckedCast() && !node_->HasAstNodeFlags(ir::AstNodeFlags::GENERATE_VALUE_OF)) { - checker_->UncheckedCastableResult().cached.insert( - {{source->Id(), target->Id()}, {result_, RelationType::UNCHECKED_CASTABLE}}); + auto key = RelationHolder::MakeKey(source->Id(), target->Id()); + checker_->UncheckedCastableResult().Insert(key, {result_, RelationType::UNCHECKED_CASTABLE}); } return true; @@ -270,7 +271,8 @@ bool TypeRelation::IsSupertypeOf(Type *super, Type *sub) } if (flags_ == TypeRelationFlag::NONE) { - checker_->SupertypeResults().cached.insert({{super->Id(), sub->Id()}, {result_, RelationType::SUPERTYPE}}); + auto key = RelationHolder::MakeKey(super->Id(), sub->Id()); + checker_->SupertypeResults().Insert(key, {result_, RelationType::SUPERTYPE}); } } diff --git a/ets2panda/checker/types/typeRelation.h b/ets2panda/checker/types/typeRelation.h index c5abfa2e85..ac87200fbc 100644 --- a/ets2panda/checker/types/typeRelation.h +++ b/ets2panda/checker/types/typeRelation.h @@ -71,9 +71,9 @@ enum class TypeRelationFlag : uint32_t { CASTING_CONTEXT = WIDENING | BOXING | UNBOXING | UNCHECKED_CAST, }; -enum class RelationResult { TRUE, FALSE, UNKNOWN, MAYBE, CACHE_MISS, ERROR }; +enum class RelationResult : uint8_t { TRUE, FALSE, UNKNOWN, MAYBE, CACHE_MISS, ERROR }; -enum class RelationType { COMPARABLE, ASSIGNABLE, IDENTICAL, UNCHECKED_CASTABLE, SUPERTYPE }; +enum class RelationType : uint8_t { COMPARABLE, ASSIGNABLE, IDENTICAL, UNCHECKED_CASTABLE, SUPERTYPE }; enum class VarianceFlag { COVARIANT, CONTRAVARIANT, INVARIANT }; @@ -85,47 +85,45 @@ struct enumbitops::IsAllowedType : std namespace ark::es2panda::checker { -class RelationKey { +class RelationHolder { public: - uint64_t sourceId; - uint64_t targetId; -}; + using RelationKey = uint64_t; -class RelationKeyHasher { -public: - size_t operator()(const RelationKey &key) const noexcept + class RelationEntry { + public: + RelationResult result; + RelationType type; + }; + + explicit RelationHolder(ThreadSafeArenaAllocator *allocator) : cached_(allocator->Adapter()) {} + + static RelationKey MakeKey(uint32_t sourceId, uint32_t targetId) { - return static_cast(key.sourceId ^ key.targetId); + constexpr size_t U32_NR_BITS = 32; // CC-OFF(G.NAM.03-CPP) project code style + return (static_cast(sourceId) << U32_NR_BITS) | targetId; } -}; -class RelationKeyComparator { -public: - bool operator()(const RelationKey &lhs, const RelationKey &rhs) const + const RelationEntry *Find(RelationKey key) const { - return lhs.sourceId == rhs.sourceId && lhs.targetId == rhs.targetId; + auto it = cached_.find(key); + if (it == cached_.cend()) { + return nullptr; + } + return &it->second; } -}; -class RelationEntry { -public: - RelationResult result; - RelationType type; -}; - -using RelationMap = ArenaUnorderedMap; + void Insert(RelationKey key, RelationEntry entry) + { + cached_.insert({key, entry}); + } -class RelationHolder { -public: - RelationHolder(ThreadSafeArenaAllocator *allocator, RelationType relationType) - : cached(allocator->Adapter()), type(relationType) + void Clear() { + cached_.clear(); } - // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) - RelationMap cached; - // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes) - RelationType type {}; +private: + ArenaUnorderedMap cached_; }; class TypeRelation { -- Gitee