| /* | 
 |  * Copyright (C) 2015 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.  | 
 |  */ | 
 |  | 
 | #pragma once | 
 |  | 
 | #if ENABLE(B3_JIT) | 
 |  | 
 | #include "B3Procedure.h" | 
 | #include "B3UpsilonValue.h" | 
 | #include <wtf/GraphNodeWorklist.h> | 
 | #include <wtf/IndexMap.h> | 
 |  | 
 | namespace JSC { namespace B3 { | 
 |  | 
 | class PhiChildren { | 
 |     WTF_MAKE_FAST_ALLOCATED; | 
 | public: | 
 |     PhiChildren(Procedure&); | 
 |     ~PhiChildren(); | 
 |  | 
 |     class ValueCollection { | 
 |     public: | 
 |         ValueCollection(Vector<UpsilonValue*>* values = nullptr) | 
 |             : m_values(values) | 
 |         { | 
 |         } | 
 |  | 
 |         unsigned size() const { return m_values->size(); } | 
 |         Value* at(unsigned index) const { return m_values->at(index)->child(0); } | 
 |         Value* operator[](unsigned index) const { return at(index); } | 
 |  | 
 |         bool contains(Value* value) const | 
 |         { | 
 |             for (unsigned i = size(); i--;) { | 
 |                 if (at(i) == value) | 
 |                     return true; | 
 |             } | 
 |             return false; | 
 |         } | 
 |  | 
 |         class iterator { | 
 |         public: | 
 |             iterator(Vector<UpsilonValue*>* values = nullptr, unsigned index = 0) | 
 |                 : m_values(values) | 
 |                 , m_index(index) | 
 |             { | 
 |             } | 
 |  | 
 |             Value* operator*() const | 
 |             { | 
 |                 return m_values->at(m_index)->child(0); | 
 |             } | 
 |  | 
 |             iterator& operator++() | 
 |             { | 
 |                 m_index++; | 
 |                 return *this; | 
 |             } | 
 |  | 
 |             bool operator==(const iterator& other) const | 
 |             { | 
 |                 ASSERT(m_values == other.m_values); | 
 |                 return m_index == other.m_index; | 
 |             } | 
 |  | 
 |             bool operator!=(const iterator& other) const | 
 |             { | 
 |                 return !(*this == other); | 
 |             } | 
 |  | 
 |         private: | 
 |             Vector<UpsilonValue*>* m_values; | 
 |             unsigned m_index; | 
 |         }; | 
 |  | 
 |         iterator begin() const { return iterator(m_values); } | 
 |         iterator end() const { return iterator(m_values, m_values->size()); } | 
 |  | 
 |     private: | 
 |         Vector<UpsilonValue*>* m_values; | 
 |     }; | 
 |      | 
 |     class UpsilonCollection { | 
 |     public: | 
 |         UpsilonCollection() | 
 |         { | 
 |         } | 
 |          | 
 |         UpsilonCollection(PhiChildren* phiChildren, Value* value, Vector<UpsilonValue*>* values) | 
 |             : m_phiChildren(phiChildren) | 
 |             , m_value(value) | 
 |             , m_values(values) | 
 |         { | 
 |         } | 
 |  | 
 |         unsigned size() const { return m_values->size(); } | 
 |         Value* at(unsigned index) const { return m_values->at(index); } | 
 |         Value* operator[](unsigned index) const { return at(index); } | 
 |  | 
 |         bool contains(Value* value) const { return m_values->contains(value); } | 
 |  | 
 |         typedef Vector<UpsilonValue*>::const_iterator iterator; | 
 |         Vector<UpsilonValue*>::const_iterator begin() const { return m_values->begin(); } | 
 |         Vector<UpsilonValue*>::const_iterator end() const { return m_values->end(); } | 
 |  | 
 |         ValueCollection values() { return ValueCollection(m_values); } | 
 |          | 
 |         template<typename Functor> | 
 |         void forAllTransitiveIncomingValues(const Functor& functor) | 
 |         { | 
 |             if (m_value->opcode() != Phi) { | 
 |                 functor(m_value); | 
 |                 return; | 
 |             } | 
 |              | 
 |             GraphNodeWorklist<Value*> worklist; | 
 |             worklist.push(m_value); | 
 |             while (Value* phi = worklist.pop()) { | 
 |                 for (Value* child : m_phiChildren->at(phi).values()) { | 
 |                     if (child->opcode() == Phi) | 
 |                         worklist.push(child); | 
 |                     else | 
 |                         functor(child); | 
 |                 } | 
 |             } | 
 |         } | 
 |  | 
 |         bool transitivelyUses(Value* candidate) | 
 |         { | 
 |             bool result = false; | 
 |             forAllTransitiveIncomingValues( | 
 |                 [&] (Value* child) { | 
 |                     result |= child == candidate; | 
 |                 }); | 
 |             return result; | 
 |         } | 
 |  | 
 |     private: | 
 |         PhiChildren* m_phiChildren { nullptr }; | 
 |         Value* m_value { nullptr }; | 
 |         Vector<UpsilonValue*>* m_values { nullptr }; | 
 |     }; | 
 |  | 
 |     UpsilonCollection at(Value* value) { return UpsilonCollection(this, value, &m_upsilons[value]); } | 
 |     UpsilonCollection operator[](Value* value) { return at(value); } | 
 |  | 
 |     const Vector<Value*, 8>& phis() const { return m_phis; } | 
 |  | 
 | private: | 
 |     IndexMap<Value*, Vector<UpsilonValue*>> m_upsilons; | 
 |     Vector<Value*, 8> m_phis; | 
 | }; | 
 |  | 
 | } } // namespace JSC::B3 | 
 |  | 
 | #endif // ENABLE(B3_JIT) |