/src/solidity/libsolutil/Algorithms.h
Line | Count | Source |
1 | | /* |
2 | | This file is part of solidity. |
3 | | |
4 | | solidity is free software: you can redistribute it and/or modify |
5 | | it under the terms of the GNU General Public License as published by |
6 | | the Free Software Foundation, either version 3 of the License, or |
7 | | (at your option) any later version. |
8 | | |
9 | | solidity is distributed in the hope that it will be useful, |
10 | | but WITHOUT ANY WARRANTY; without even the implied warranty of |
11 | | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
12 | | GNU General Public License for more details. |
13 | | |
14 | | You should have received a copy of the GNU General Public License |
15 | | along with solidity. If not, see <http://www.gnu.org/licenses/>. |
16 | | */ |
17 | | // SPDX-License-Identifier: GPL-3.0 |
18 | | #pragma once |
19 | | |
20 | | |
21 | | #include <functional> |
22 | | #include <list> |
23 | | #include <set> |
24 | | |
25 | | namespace solidity::util |
26 | | { |
27 | | |
28 | | /** |
29 | | * Detector for cycles in directed graphs. It returns the first |
30 | | * vertex on the path towards a cycle or a nullptr if there is |
31 | | * no reachable cycle starting from a given vertex. |
32 | | */ |
33 | | template <typename V> |
34 | | class CycleDetector |
35 | | { |
36 | | public: |
37 | | using Visitor = std::function<void(V const&, CycleDetector&, size_t)>; |
38 | | |
39 | | /// Initializes the cycle detector |
40 | | /// @param _visit function that is given the current vertex |
41 | | /// and is supposed to call @a run on all |
42 | | /// adjacent vertices. |
43 | | explicit CycleDetector(Visitor _visit): |
44 | | m_visit(std::move(_visit)) |
45 | | { } |
46 | | |
47 | | /// Recursively perform cycle detection starting |
48 | | /// (or continuing) with @param _vertex |
49 | | /// @returns the first vertex on the path towards a cycle from @a _vertex |
50 | | /// or nullptr if no cycle is reachable from @a _vertex. |
51 | | V const* run(V const& _vertex) |
52 | | { |
53 | | if (m_firstCycleVertex) |
54 | | return m_firstCycleVertex; |
55 | | if (m_processed.count(&_vertex)) |
56 | | return nullptr; |
57 | | else if (m_processing.count(&_vertex)) |
58 | | return m_firstCycleVertex = &_vertex; |
59 | | m_processing.insert(&_vertex); |
60 | | |
61 | | m_depth++; |
62 | | m_visit(_vertex, *this, m_depth); |
63 | | m_depth--; |
64 | | if (m_firstCycleVertex && m_depth == 1) |
65 | | m_firstCycleVertex = &_vertex; |
66 | | |
67 | | m_processing.erase(&_vertex); |
68 | | m_processed.insert(&_vertex); |
69 | | return m_firstCycleVertex; |
70 | | } |
71 | | |
72 | | private: |
73 | | Visitor m_visit; |
74 | | std::set<V const*> m_processing; |
75 | | std::set<V const*> m_processed; |
76 | | size_t m_depth = 0; |
77 | | V const* m_firstCycleVertex = nullptr; |
78 | | }; |
79 | | |
80 | | /** |
81 | | * Generic breadth first search. |
82 | | * |
83 | | * Note that V needs to be a comparable value type or a pointer. |
84 | | * |
85 | | * Example: Gather all (recursive) children in a graph starting at (and including) ``root``: |
86 | | * |
87 | | * Node const* root = ...; |
88 | | * std::set<Node const*> allNodes = BreadthFirstSearch<Node const*>{{root}}.run([](Node const* _node, auto&& _addChild) { |
89 | | * // Potentially process ``_node``. |
90 | | * for (Node const& _child: _node->children()) |
91 | | * // Potentially filter the children to be visited. |
92 | | * _addChild(&_child); |
93 | | * }).visited; |
94 | | */ |
95 | | template<typename V> |
96 | | struct BreadthFirstSearch |
97 | | { |
98 | | /// Runs the breadth first search. The verticesToTraverse member of the struct needs to be initialized. |
99 | | /// @param _forEachChild is a callable of the form [...](V const& _node, auto&& _addChild) { ... } |
100 | | /// that is called for each visited node and is supposed to call _addChild(childNode) for every child |
101 | | /// node of _node. |
102 | | template<typename ForEachChild> |
103 | | BreadthFirstSearch& run(ForEachChild&& _forEachChild) |
104 | 685k | { |
105 | 4.64M | while (!verticesToTraverse.empty()) |
106 | 3.96M | { |
107 | 3.96M | V v = std::move(verticesToTraverse.front()); |
108 | 3.96M | verticesToTraverse.pop_front(); |
109 | | |
110 | 3.96M | if (!visited.insert(v).second) |
111 | 955k | continue; |
112 | | |
113 | 3.24M | _forEachChild(v, [this](V _vertex) { |
114 | 3.24M | verticesToTraverse.emplace_back(std::move(_vertex)); |
115 | 3.24M | }); StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::processEntryPoint(solidity::yul::CFG::BasicBlock const&)::$_4>(solidity::yul::StackLayoutGenerator::processEntryPoint(solidity::yul::CFG::BasicBlock const&)::$_4&&)::{lambda(solidity::yul::CFG::BasicBlock const*)#1}::operator()(solidity::yul::CFG::BasicBlock const*) const Line | Count | Source | 113 | 230k | _forEachChild(v, [this](V _vertex) { | 114 | 230k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 230k | }); |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::collectBackwardsJumps(solidity::yul::CFG::BasicBlock const&) const::$_10>(solidity::yul::StackLayoutGenerator::collectBackwardsJumps(solidity::yul::CFG::BasicBlock const&) const::$_10&&)::{lambda(solidity::yul::CFG::BasicBlock const*)#1}::operator()(solidity::yul::CFG::BasicBlock const*) const Line | Count | Source | 113 | 246k | _forEachChild(v, [this](V _vertex) { | 114 | 246k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 246k | }); |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::stitchConditionalJumps(solidity::yul::CFG::BasicBlock const&)::$_11>(solidity::yul::StackLayoutGenerator::stitchConditionalJumps(solidity::yul::CFG::BasicBlock const&)::$_11&&)::{lambda(solidity::yul::CFG::BasicBlock const*)#1}::operator()(solidity::yul::CFG::BasicBlock const*) const Line | Count | Source | 113 | 212k | _forEachChild(v, [this](V _vertex) { | 114 | 212k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 212k | }); |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::reportStackTooDeep(solidity::yul::CFG::BasicBlock const&) const::$_14>(solidity::yul::StackLayoutGenerator::reportStackTooDeep(solidity::yul::CFG::BasicBlock const&) const::$_14&&)::{lambda(solidity::yul::CFG::BasicBlock const*)#1}::operator()(solidity::yul::CFG::BasicBlock const*) const Line | Count | Source | 113 | 212k | _forEachChild(v, [this](V _vertex) { | 114 | 212k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 212k | }); |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_17>(solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_17&&)::{lambda(solidity::yul::CFG::BasicBlock const*)#1}::operator()(solidity::yul::CFG::BasicBlock const*) const Line | Count | Source | 113 | 246k | _forEachChild(v, [this](V _vertex) { | 114 | 246k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 246k | }); |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_15::operator()(solidity::yul::CFG::BasicBlock const*, unsigned long) const::{lambda(solidity::yul::CFG::BasicBlock const*, auto:1)#1}>(solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_15::operator()(solidity::yul::CFG::BasicBlock const*, unsigned long) const::{lambda(solidity::yul::CFG::BasicBlock const*, auto:1)#1}&&)::{lambda(solidity::yul::CFG::BasicBlock const*)#1}::operator()(solidity::yul::CFG::BasicBlock const*) const Line | Count | Source | 113 | 28.2k | _forEachChild(v, [this](V _vertex) { | 114 | 28.2k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 28.2k | }); |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>::run<(anonymous namespace)::cleanUnreachable(solidity::yul::CFG&)::$_16>((anonymous namespace)::cleanUnreachable(solidity::yul::CFG&)::$_16&&)::{lambda(solidity::yul::CFG::BasicBlock*)#1}::operator()(solidity::yul::CFG::BasicBlock*) const Line | Count | Source | 113 | 246k | _forEachChild(v, [this](V _vertex) { | 114 | 246k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 246k | }); |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>::run<(anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_17::operator()(solidity::yul::CFG::BasicBlock*) const::{lambda(solidity::yul::CFG::BasicBlock*, auto:1)#1}>((anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_17::operator()(solidity::yul::CFG::BasicBlock*) const::{lambda(solidity::yul::CFG::BasicBlock*, auto:1)#1}&&)::{lambda(solidity::yul::CFG::BasicBlock*)#1}::operator()(solidity::yul::CFG::BasicBlock*) const Line | Count | Source | 113 | 168k | _forEachChild(v, [this](V _vertex) { | 114 | 168k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 168k | }); |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::FunctionCall*>::run<(anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_18>((anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_18&&)::{lambda(solidity::yul::CFG::FunctionCall*)#1}::operator()(solidity::yul::CFG::FunctionCall*) const Line | Count | Source | 113 | 7.79k | _forEachChild(v, [this](V _vertex) { | 114 | 7.79k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 7.79k | }); |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>::run<(anonymous namespace)::markNeedsCleanStack(solidity::yul::CFG&)::$_20>((anonymous namespace)::markNeedsCleanStack(solidity::yul::CFG&)::$_20&&)::{lambda(solidity::yul::CFG::BasicBlock*)#1}::operator()(solidity::yul::CFG::BasicBlock*) const Line | Count | Source | 113 | 118k | _forEachChild(v, [this](V _vertex) { | 114 | 118k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 118k | }); |
CircularReferencesPruner.cpp:solidity::util::BreadthFirstSearch<solidity::yul::YulString>::run<solidity::yul::CircularReferencesPruner::functionsCalledFromOutermostContext(solidity::yul::CallGraph const&)::$_0>(solidity::yul::CircularReferencesPruner::functionsCalledFromOutermostContext(solidity::yul::CallGraph const&)::$_0&&)::{lambda(solidity::yul::YulString)#1}::operator()(solidity::yul::YulString) const Line | Count | Source | 113 | 1.53M | _forEachChild(v, [this](V _vertex) { | 114 | 1.53M | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 1.53M | }); |
|
116 | 3.00M | } |
117 | 685k | return *this; |
118 | 685k | } StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::processEntryPoint(solidity::yul::CFG::BasicBlock const&)::$_4>(solidity::yul::StackLayoutGenerator::processEntryPoint(solidity::yul::CFG::BasicBlock const&)::$_4&&) Line | Count | Source | 104 | 37.8k | { | 105 | 306k | while (!verticesToTraverse.empty()) | 106 | 268k | { | 107 | 268k | V v = std::move(verticesToTraverse.front()); | 108 | 268k | verticesToTraverse.pop_front(); | 109 | | | 110 | 268k | if (!visited.insert(v).second) | 111 | 32.7k | continue; | 112 | | | 113 | 235k | _forEachChild(v, [this](V _vertex) { | 114 | 235k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 235k | }); | 116 | 235k | } | 117 | 37.8k | return *this; | 118 | 37.8k | } |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::collectBackwardsJumps(solidity::yul::CFG::BasicBlock const&) const::$_10>(solidity::yul::StackLayoutGenerator::collectBackwardsJumps(solidity::yul::CFG::BasicBlock const&) const::$_10&&) Line | Count | Source | 104 | 56.6k | { | 105 | 359k | while (!verticesToTraverse.empty()) | 106 | 302k | { | 107 | 302k | V v = std::move(verticesToTraverse.front()); | 108 | 302k | verticesToTraverse.pop_front(); | 109 | | | 110 | 302k | if (!visited.insert(v).second) | 111 | 51.3k | continue; | 112 | | | 113 | 251k | _forEachChild(v, [this](V _vertex) { | 114 | 251k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 251k | }); | 116 | 251k | } | 117 | 56.6k | return *this; | 118 | 56.6k | } |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::stitchConditionalJumps(solidity::yul::CFG::BasicBlock const&)::$_11>(solidity::yul::StackLayoutGenerator::stitchConditionalJumps(solidity::yul::CFG::BasicBlock const&)::$_11&&) Line | Count | Source | 104 | 56.6k | { | 105 | 326k | while (!verticesToTraverse.empty()) | 106 | 269k | { | 107 | 269k | V v = std::move(verticesToTraverse.front()); | 108 | 269k | verticesToTraverse.pop_front(); | 109 | | | 110 | 269k | if (!visited.insert(v).second) | 111 | 18.1k | continue; | 112 | | | 113 | 251k | _forEachChild(v, [this](V _vertex) { | 114 | 251k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 251k | }); | 116 | 251k | } | 117 | 56.6k | return *this; | 118 | 56.6k | } |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::reportStackTooDeep(solidity::yul::CFG::BasicBlock const&) const::$_14>(solidity::yul::StackLayoutGenerator::reportStackTooDeep(solidity::yul::CFG::BasicBlock const&) const::$_14&&) Line | Count | Source | 104 | 56.6k | { | 105 | 326k | while (!verticesToTraverse.empty()) | 106 | 269k | { | 107 | 269k | V v = std::move(verticesToTraverse.front()); | 108 | 269k | verticesToTraverse.pop_front(); | 109 | | | 110 | 269k | if (!visited.insert(v).second) | 111 | 18.1k | continue; | 112 | | | 113 | 251k | _forEachChild(v, [this](V _vertex) { | 114 | 251k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 251k | }); | 116 | 251k | } | 117 | 56.6k | return *this; | 118 | 56.6k | } |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_17>(solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_17&&) Line | Count | Source | 104 | 56.6k | { | 105 | 359k | while (!verticesToTraverse.empty()) | 106 | 302k | { | 107 | 302k | V v = std::move(verticesToTraverse.front()); | 108 | 302k | verticesToTraverse.pop_front(); | 109 | | | 110 | 302k | if (!visited.insert(v).second) | 111 | 51.3k | continue; | 112 | | | 113 | 251k | _forEachChild(v, [this](V _vertex) { | 114 | 251k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 251k | }); | 116 | 251k | } | 117 | 56.6k | return *this; | 118 | 56.6k | } |
StackLayoutGenerator.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock const*>::run<solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_15::operator()(solidity::yul::CFG::BasicBlock const*, unsigned long) const::{lambda(solidity::yul::CFG::BasicBlock const*, auto:1)#1}>(solidity::yul::StackLayoutGenerator::fillInJunk(solidity::yul::CFG::BasicBlock const&)::$_15::operator()(solidity::yul::CFG::BasicBlock const*, unsigned long) const::{lambda(solidity::yul::CFG::BasicBlock const*, auto:1)#1}&&) Line | Count | Source | 104 | 5.59k | { | 105 | 39.4k | while (!verticesToTraverse.empty()) | 106 | 33.8k | { | 107 | 33.8k | V v = std::move(verticesToTraverse.front()); | 108 | 33.8k | verticesToTraverse.pop_front(); | 109 | | | 110 | 33.8k | if (!visited.insert(v).second) | 111 | 6.14k | continue; | 112 | | | 113 | 27.6k | _forEachChild(v, [this](V _vertex) { | 114 | 27.6k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 27.6k | }); | 116 | 27.6k | } | 117 | 5.59k | return *this; | 118 | 5.59k | } |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>::run<(anonymous namespace)::cleanUnreachable(solidity::yul::CFG&)::$_16>((anonymous namespace)::cleanUnreachable(solidity::yul::CFG&)::$_16&&) Line | Count | Source | 104 | 25.9k | { | 105 | 328k | while (!verticesToTraverse.empty()) | 106 | 302k | { | 107 | 302k | V v = std::move(verticesToTraverse.front()); | 108 | 302k | verticesToTraverse.pop_front(); | 109 | | | 110 | 302k | if (!visited.insert(v).second) | 111 | 51.3k | continue; | 112 | | | 113 | 251k | _forEachChild(v, [this](V _vertex) { | 114 | 251k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 251k | }); | 116 | 251k | } | 117 | 25.9k | return *this; | 118 | 25.9k | } |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>::run<(anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_17::operator()(solidity::yul::CFG::BasicBlock*) const::{lambda(solidity::yul::CFG::BasicBlock*, auto:1)#1}>((anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_17::operator()(solidity::yul::CFG::BasicBlock*) const::{lambda(solidity::yul::CFG::BasicBlock*, auto:1)#1}&&) Line | Count | Source | 104 | 30.7k | { | 105 | 230k | while (!verticesToTraverse.empty()) | 106 | 199k | { | 107 | 199k | V v = std::move(verticesToTraverse.front()); | 108 | 199k | verticesToTraverse.pop_front(); | 109 | | | 110 | 199k | if (!visited.insert(v).second) | 111 | 32.5k | continue; | 112 | | | 113 | 166k | _forEachChild(v, [this](V _vertex) { | 114 | 166k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 166k | }); | 116 | 166k | } | 117 | 30.7k | return *this; | 118 | 30.7k | } |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::FunctionCall*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::FunctionCall*>::run<(anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_18>((anonymous namespace)::markRecursiveCalls(solidity::yul::CFG&)::$_18&&) Line | Count | Source | 104 | 35.1k | { | 105 | 75.9k | while (!verticesToTraverse.empty()) | 106 | 40.7k | { | 107 | 40.7k | V v = std::move(verticesToTraverse.front()); | 108 | 40.7k | verticesToTraverse.pop_front(); | 109 | | | 110 | 40.7k | if (!visited.insert(v).second) | 111 | 3.54k | continue; | 112 | | | 113 | 37.2k | _forEachChild(v, [this](V _vertex) { | 114 | 37.2k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 37.2k | }); | 116 | 37.2k | } | 117 | 35.1k | return *this; | 118 | 35.1k | } |
ControlFlowGraphBuilder.cpp:solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>& solidity::util::BreadthFirstSearch<solidity::yul::CFG::BasicBlock*>::run<(anonymous namespace)::markNeedsCleanStack(solidity::yul::CFG&)::$_20>((anonymous namespace)::markNeedsCleanStack(solidity::yul::CFG&)::$_20&&) Line | Count | Source | 104 | 39.5k | { | 105 | 197k | while (!verticesToTraverse.empty()) | 106 | 157k | { | 107 | 157k | V v = std::move(verticesToTraverse.front()); | 108 | 157k | verticesToTraverse.pop_front(); | 109 | | | 110 | 157k | if (!visited.insert(v).second) | 111 | 19.6k | continue; | 112 | | | 113 | 137k | _forEachChild(v, [this](V _vertex) { | 114 | 137k | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 137k | }); | 116 | 137k | } | 117 | 39.5k | return *this; | 118 | 39.5k | } |
CircularReferencesPruner.cpp:solidity::util::BreadthFirstSearch<solidity::yul::YulString>& solidity::util::BreadthFirstSearch<solidity::yul::YulString>::run<solidity::yul::CircularReferencesPruner::functionsCalledFromOutermostContext(solidity::yul::CallGraph const&)::$_0>(solidity::yul::CircularReferencesPruner::functionsCalledFromOutermostContext(solidity::yul::CallGraph const&)::$_0&&) Line | Count | Source | 104 | 284k | { | 105 | 2.09M | while (!verticesToTraverse.empty()) | 106 | 1.81M | { | 107 | 1.81M | V v = std::move(verticesToTraverse.front()); | 108 | 1.81M | verticesToTraverse.pop_front(); | 109 | | | 110 | 1.81M | if (!visited.insert(v).second) | 111 | 670k | continue; | 112 | | | 113 | 1.14M | _forEachChild(v, [this](V _vertex) { | 114 | 1.14M | verticesToTraverse.emplace_back(std::move(_vertex)); | 115 | 1.14M | }); | 116 | 1.14M | } | 117 | 284k | return *this; | 118 | 284k | } |
|
119 | | void abort() |
120 | 1.64k | { |
121 | 1.64k | verticesToTraverse.clear(); |
122 | 1.64k | } |
123 | | |
124 | | std::list<V> verticesToTraverse; |
125 | | std::set<V> visited{}; |
126 | | }; |
127 | | |
128 | | } |