/* * 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 #include namespace JSC { namespace B3 { class PhiChildren { WTF_MAKE_FAST_ALLOCATED; public: PhiChildren(Procedure&); ~PhiChildren(); class ValueCollection { public: ValueCollection(Vector* 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* 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* m_values; unsigned m_index; }; iterator begin() const { return iterator(m_values); } iterator end() const { return iterator(m_values, m_values->size()); } private: Vector* m_values; }; class UpsilonCollection { public: UpsilonCollection() { } UpsilonCollection(PhiChildren* phiChildren, Value* value, Vector* 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::const_iterator iterator; Vector::const_iterator begin() const { return m_values->begin(); } Vector::const_iterator end() const { return m_values->end(); } ValueCollection values() { return ValueCollection(m_values); } template void forAllTransitiveIncomingValues(const Functor& functor) { if (m_value->opcode() != Phi) { functor(m_value); return; } GraphNodeWorklist 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* m_values { nullptr }; }; UpsilonCollection at(Value* value) { return UpsilonCollection(this, value, &m_upsilons[value]); } UpsilonCollection operator[](Value* value) { return at(value); } const Vector& phis() const { return m_phis; } private: IndexMap> m_upsilons; Vector m_phis; }; } } // namespace JSC::B3 #endif // ENABLE(B3_JIT)