diff options
Diffstat (limited to 'Source/JavaScriptCore/b3/B3PhiChildren.h')
-rw-r--r-- | Source/JavaScriptCore/b3/B3PhiChildren.h | 177 |
1 files changed, 177 insertions, 0 deletions
diff --git a/Source/JavaScriptCore/b3/B3PhiChildren.h b/Source/JavaScriptCore/b3/B3PhiChildren.h new file mode 100644 index 000000000..22b827730 --- /dev/null +++ b/Source/JavaScriptCore/b3/B3PhiChildren.h @@ -0,0 +1,177 @@ +/* + * 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 { +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) |