/* * 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 "B3FrequentedBlock.h" #include "B3Opcode.h" #include "B3Origin.h" #include "B3SuccessorCollection.h" #include "B3Type.h" #include namespace JSC { namespace B3 { class BlockInsertionSet; class InsertionSet; class Procedure; class Value; template class GenericBlockInsertionSet; class BasicBlock { WTF_MAKE_NONCOPYABLE(BasicBlock); WTF_MAKE_FAST_ALLOCATED; public: typedef Vector ValueList; typedef Vector PredecessorList; typedef Vector SuccessorList; static constexpr unsigned uninsertedIndex = UINT_MAX; static const char* const dumpPrefix; ~BasicBlock(); unsigned index() const { return m_index; } bool isInserted() const { return m_index != uninsertedIndex; } ValueList::iterator begin() { return m_values.begin(); } ValueList::iterator end() { return m_values.end(); } ValueList::const_iterator begin() const { return m_values.begin(); } ValueList::const_iterator end() const { return m_values.end(); } size_t size() const { return m_values.size(); } Value* at(size_t index) const { return m_values[index]; } Value*& at(size_t index) { return m_values[index]; } Value* get(size_t index) const { if (index >= size()) return nullptr; return at(index); } Value* last() const { return m_values.last(); } Value*& last() { return m_values.last(); } const ValueList& values() const { return m_values; } ValueList& values() { return m_values; } JS_EXPORT_PRIVATE void append(Value*); JS_EXPORT_PRIVATE void appendNonTerminal(Value*); JS_EXPORT_PRIVATE void replaceLast(Procedure&, Value*); template ValueType* appendNew(Procedure&, Arguments...); JS_EXPORT_PRIVATE Value* appendIntConstant(Procedure&, Origin, Type, int64_t value); Value* appendIntConstant(Procedure&, Value* likeValue, int64_t value); Value* appendBoolConstant(Procedure&, Origin, bool); void removeLast(Procedure&); template ValueType* replaceLastWithNew(Procedure&, Arguments...); unsigned numSuccessors() const { return m_successors.size(); } const 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; } void clearSuccessors(); JS_EXPORT_PRIVATE void appendSuccessor(FrequentedBlock); 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 successorBlocks() { return SuccessorCollection(successors()); } SuccessorCollection successorBlocks() const { return SuccessorCollection(successors()); } bool replaceSuccessor(BasicBlock* from, BasicBlock* to); // This is only valid for Jump and Branch. const FrequentedBlock& taken() const; FrequentedBlock& taken(); // This is only valid for Branch. const FrequentedBlock& notTaken() const; FrequentedBlock& notTaken(); // This is only valid for Branch and Switch. const FrequentedBlock& fallThrough() const; FrequentedBlock& fallThrough(); 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 containsPredecessor(BasicBlock* block) { return m_predecessors.contains(block); } bool addPredecessor(BasicBlock*); bool removePredecessor(BasicBlock*); bool replacePredecessor(BasicBlock* from, BasicBlock* to); // Update predecessors starting with the successors of this block. void updatePredecessorsAfter(); double frequency() const { return m_frequency; } void dump(PrintStream&) const; void deepDump(const Procedure&, PrintStream&) const; // These are deprecated method for compatibility with the old ControlValue class. Don't use them // in new code. // FIXME: https://bugs.webkit.org/show_bug.cgi?id=159440 // Use this for Oops. JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin); // Use this for Return. JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin, Value*); // Use this for Jump. JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin, const FrequentedBlock&); // Use this for Branch. JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin, Value*, const FrequentedBlock&, const FrequentedBlock&); private: friend class BlockInsertionSet; friend class InsertionSet; friend class Procedure; template friend class GenericBlockInsertionSet; // Instantiate via Procedure. BasicBlock(unsigned index, double frequency); unsigned m_index; ValueList m_values; PredecessorList m_predecessors; SuccessorList m_successors; double m_frequency; }; class DeepBasicBlockDump { public: DeepBasicBlockDump(const Procedure& proc, const BasicBlock* block) : m_proc(proc) , m_block(block) { } void dump(PrintStream& out) const { if (m_block) m_block->deepDump(m_proc, out); else out.print(""); } private: const Procedure& m_proc; const BasicBlock* m_block; }; inline DeepBasicBlockDump deepDump(const Procedure& proc, const BasicBlock* block) { return DeepBasicBlockDump(proc, block); } } } // namespace JSC::B3 #endif // ENABLE(B3_JIT)