/* * Copyright (C) 2015-2016 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef GraphNodeWorklist_h #define GraphNodeWorklist_h #include namespace WTF { template> class GraphNodeWorklist { public: GraphNodeWorklist() { } ~GraphNodeWorklist() { } // Returns true if we didn't know about the node before. bool push(Node node) { if (!m_seen.add(node)) return false; m_stack.append(node); return true; } template void pushAll(const Iterable& iterable) { for (Node node : iterable) push(node); } bool isEmpty() const { return m_stack.isEmpty(); } bool notEmpty() const { return !m_stack.isEmpty(); } Node pop() { if (m_stack.isEmpty()) return Node(); return m_stack.takeLast(); } bool saw(Node node) { return m_seen.contains(node); } private: Set m_seen; Vector m_stack; }; template struct GraphNodeWith { GraphNodeWith() : node() , data() { } GraphNodeWith(Node node, const T& data) : node(node) , data(data) { } explicit operator bool() const { return !!node; } Node node; T data; }; template> class ExtendedGraphNodeWorklist { public: ExtendedGraphNodeWorklist() { } void forcePush(const GraphNodeWith& entry) { m_stack.append(entry); } void forcePush(Node node, const T& data) { forcePush(GraphNodeWith(node, data)); } bool push(const GraphNodeWith& entry) { if (!m_seen.add(entry.node)) return false; forcePush(entry); return true; } bool push(Node node, const T& data) { return push(GraphNodeWith(node, data)); } bool notEmpty() const { return !m_stack.isEmpty(); } GraphNodeWith pop() { if (m_stack.isEmpty()) return GraphNodeWith(); return m_stack.takeLast(); } private: Set m_seen; Vector> m_stack; }; enum class GraphVisitOrder : uint8_t { Pre, Post }; template struct GraphNodeWithOrder { GraphNodeWithOrder() : node() , order(GraphVisitOrder::Pre) { } GraphNodeWithOrder(Node node, GraphVisitOrder order) : node(node) , order(order) { } explicit operator bool() const { return node; } Node node; GraphVisitOrder order; }; template> class PostOrderGraphNodeWorklist { public: PostOrderGraphNodeWorklist() { } ~PostOrderGraphNodeWorklist() { } bool pushPre(Node node) { return m_worklist.push(node, GraphVisitOrder::Pre); } void pushPost(Node node) { m_worklist.forcePush(node, GraphVisitOrder::Post); } bool push(Node node, GraphVisitOrder order = GraphVisitOrder::Pre) { switch (order) { case GraphVisitOrder::Pre: return pushPre(node); case GraphVisitOrder::Post: pushPost(node); return true; } RELEASE_ASSERT_NOT_REACHED(); return false; } bool push(const GraphNodeWithOrder& data) { return push(data.node, data.order); } bool notEmpty() const { return m_worklist.notEmpty(); } GraphNodeWithOrder pop() { GraphNodeWith result = m_worklist.pop(); return GraphNodeWithOrder(result.node, result.data); } private: ExtendedGraphNodeWorklist m_worklist; }; } // namespace WTF using WTF::GraphNodeWorklist; using WTF::GraphNodeWith; using WTF::ExtendedGraphNodeWorklist; using WTF::GraphVisitOrder; using WTF::GraphNodeWithOrder; using WTF::PostOrderGraphNodeWorklist; #endif // GraphNodeWorklist_h