| /* |
| * Copyright (C) 2015-2017 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 "AirFrequentedBlock.h" |
| #include "AirInst.h" |
| #include "B3SuccessorCollection.h" |
| #include <wtf/FastMalloc.h> |
| #include <wtf/Noncopyable.h> |
| |
| namespace JSC { namespace B3 { |
| |
| template<typename> class GenericBlockInsertionSet; |
| |
| namespace Air { |
| |
| class BlockInsertionSet; |
| class Code; |
| class InsertionSet; |
| class PhaseInsertionSet; |
| |
| class BasicBlock { |
| WTF_MAKE_NONCOPYABLE(BasicBlock); |
| WTF_MAKE_FAST_ALLOCATED; |
| public: |
| static const char* const dumpPrefix; |
| |
| typedef Vector<Inst> InstList; |
| typedef Vector<BasicBlock*, 2> PredecessorList; |
| typedef Vector<FrequentedBlock, 2> SuccessorList; |
| |
| unsigned index() const { return m_index; } |
| |
| // This method is exposed for phases that mess with the layout of basic blocks. Currently that means just |
| // optimizeBlockOrder(). |
| void setIndex(unsigned index) { m_index = index; } |
| |
| unsigned size() const { return m_insts.size(); } |
| InstList::iterator begin() { return m_insts.begin(); } |
| InstList::iterator end() { return m_insts.end(); } |
| InstList::const_iterator begin() const { return m_insts.begin(); } |
| InstList::const_iterator end() const { return m_insts.end(); } |
| |
| const Inst& at(unsigned index) const { return m_insts[index]; } |
| Inst& at(unsigned index) { return m_insts[index]; } |
| |
| Inst* get(unsigned index) |
| { |
| return index < size() ? &at(index) : nullptr; |
| } |
| |
| const Inst& last() const { return m_insts.last(); } |
| Inst& last() { return m_insts.last(); } |
| |
| void resize(unsigned size) { m_insts.resize(size); } |
| |
| const InstList& insts() const { return m_insts; } |
| InstList& insts() { return m_insts; } |
| |
| template<typename Inst> |
| Inst& appendInst(Inst&& inst) |
| { |
| m_insts.append(std::forward<Inst>(inst)); |
| return m_insts.last(); |
| } |
| |
| template<typename... Arguments> |
| Inst& append(Arguments&&... arguments) |
| { |
| m_insts.append(Inst(std::forward<Arguments>(arguments)...)); |
| return m_insts.last(); |
| } |
| |
| // The "0" case is the case to which the branch jumps, so the "then" case. The "1" case is the |
| // "else" case, and is used to represent the fall-through of a conditional branch. |
| unsigned numSuccessors() const { return m_successors.size(); } |
| FrequentedBlock successor(unsigned index) const { return m_successors[index]; } |
| FrequentedBlock& successor(unsigned index) { return m_successors[index]; } |
| const SuccessorList& successors() const { return m_successors; } |
| SuccessorList& successors() { return m_successors; } |
| |
| JS_EXPORT_PRIVATE void setSuccessors(FrequentedBlock); |
| JS_EXPORT_PRIVATE void setSuccessors(FrequentedBlock, FrequentedBlock); |
| |
| BasicBlock* successorBlock(unsigned index) const { return successor(index).block(); } |
| BasicBlock*& successorBlock(unsigned index) { return successor(index).block(); } |
| SuccessorCollection<BasicBlock, SuccessorList> successorBlocks() |
| { |
| return SuccessorCollection<BasicBlock, SuccessorList>(m_successors); |
| } |
| SuccessorCollection<const BasicBlock, const SuccessorList> successorBlocks() const |
| { |
| return SuccessorCollection<const BasicBlock, const SuccessorList>(m_successors); |
| } |
| |
| unsigned numPredecessors() const { return m_predecessors.size(); } |
| BasicBlock* predecessor(unsigned index) const { return m_predecessors[index]; } |
| BasicBlock*& predecessor(unsigned index) { return m_predecessors[index]; } |
| const PredecessorList& predecessors() const { return m_predecessors; } |
| PredecessorList& predecessors() { return m_predecessors; } |
| |
| bool addPredecessor(BasicBlock*); |
| bool removePredecessor(BasicBlock*); |
| bool replacePredecessor(BasicBlock* from, BasicBlock* to); |
| bool containsPredecessor(BasicBlock* predecessor) const { return m_predecessors.contains(predecessor); } |
| |
| double frequency() const { return m_frequency; } |
| |
| void dump(PrintStream&) const; |
| void deepDump(PrintStream&) const; |
| |
| void dumpHeader(PrintStream&) const; |
| void dumpFooter(PrintStream&) const; |
| |
| private: |
| friend class BlockInsertionSet; |
| friend class Code; |
| friend class InsertionSet; |
| friend class PhaseInsertionSet; |
| template<typename> friend class B3::GenericBlockInsertionSet; |
| |
| BasicBlock(unsigned index, double frequency); |
| |
| unsigned m_index; |
| InstList m_insts; |
| SuccessorList m_successors; |
| PredecessorList m_predecessors; |
| double m_frequency; |
| }; |
| |
| class DeepBasicBlockDump { |
| public: |
| DeepBasicBlockDump(const BasicBlock* block) |
| : m_block(block) |
| { |
| } |
| |
| void dump(PrintStream& out) const |
| { |
| if (m_block) |
| m_block->deepDump(out); |
| else |
| out.print("<null>"); |
| } |
| |
| private: |
| const BasicBlock* m_block; |
| }; |
| |
| inline DeepBasicBlockDump deepDump(const BasicBlock* block) |
| { |
| return DeepBasicBlockDump(block); |
| } |
| |
| } } } // namespace JSC::B3::Air |
| |
| #endif // ENABLE(B3_JIT) |