From 0d948ebf8173501bb928f6e8b83c2a81dc09f407 Mon Sep 17 00:00:00 2001 From: chriseth Date: Tue, 1 Jun 2021 14:55:35 +0200 Subject: [PATCH] Cache functions by name. --- libsolidity/ast/AST.cpp | 16 +++++++++++++--- libsolidity/ast/AST.h | 13 +++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index e217fecfa..e006e88cf 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -276,6 +276,17 @@ FunctionDefinition const* ContractDefinition::nextConstructor(ContractDefinition return nullptr; } +multimap const& ContractDefinition::definedFunctionsByName() const +{ + return m_definedFunctionsByName.init([&]{ + std::multimap result; + for (FunctionDefinition const* fun: filteredNodes(m_subNodes)) + result.insert({fun->name(), fun}); + return result; + }); +} + + TypeNameAnnotation& TypeName::annotation() const { return initAnnotation(); @@ -397,6 +408,7 @@ FunctionDefinition const& FunctionDefinition::resolveVirtual( ) const { solAssert(!isConstructor(), ""); + solAssert(!name().empty(), ""); // If we are not doing super-lookup and the function is not virtual, we can stop here. if (_searchStart == nullptr && !virtualSemantics()) @@ -416,10 +428,8 @@ FunctionDefinition const& FunctionDefinition::resolveVirtual( else foundSearchStart = true; - for (FunctionDefinition const* function: c->definedFunctions()) + for (FunctionDefinition const* function: c->definedFunctions(name())) if ( - function->name() == name() && - !function->isConstructor() && // With super lookup analysis guarantees that there is an implemented function in the chain. // With virtual lookup there are valid cases where returning an unimplemented one is fine. (function->isImplemented() || _searchStart == nullptr) && diff --git a/libsolidity/ast/AST.h b/libsolidity/ast/AST.h index 7a1609e81..123d06f74 100644 --- a/libsolidity/ast/AST.h +++ b/libsolidity/ast/AST.h @@ -36,6 +36,9 @@ #include +#include +#include + #include #include #include @@ -497,6 +500,13 @@ public: std::vector stateVariables() const { return filteredNodes(m_subNodes); } std::vector functionModifiers() const { return filteredNodes(m_subNodes); } std::vector definedFunctions() const { return filteredNodes(m_subNodes); } + /// @returns a view of all functions + /// defined in this contract of the given name (excluding inherited functions). + auto definedFunctions(std::string const& _name) const + { + auto&& [b, e] = definedFunctionsByName().equal_range(_name); + return ranges::subrange(b, e) | ranges::views::values; + } std::vector events() const { return filteredNodes(m_subNodes); } std::vector const& interfaceEvents() const; /// @returns all errors defined in this contract or any base contract @@ -546,6 +556,8 @@ public: FunctionDefinition const* nextConstructor(ContractDefinition const& _mostDerivedContract) const; private: + std::multimap const& definedFunctionsByName() const; + std::vector> m_baseContracts; std::vector> m_subNodes; ContractKind m_contractKind; @@ -553,6 +565,7 @@ private: util::LazyInit, FunctionTypePointer>>> m_interfaceFunctionList[2]; util::LazyInit> m_interfaceEvents; + util::LazyInit> m_definedFunctionsByName; }; /**