1/*
2 * Copyright (C) 2015-2017 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
17 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#pragma once
27
28#if ENABLE(B3_JIT)
29
30#include "AirFrequentedBlock.h"
31#include "AirInst.h"
32#include "B3SuccessorCollection.h"
33#include <wtf/FastMalloc.h>
34#include <wtf/Noncopyable.h>
35
36namespace JSC { namespace B3 {
37
38template<typename> class GenericBlockInsertionSet;
39
40namespace Air {
41
42class BlockInsertionSet;
43class Code;
44class InsertionSet;
45class PhaseInsertionSet;
46
47class BasicBlock {
48 WTF_MAKE_NONCOPYABLE(BasicBlock);
49 WTF_MAKE_FAST_ALLOCATED;
50public:
51 static const char* const dumpPrefix;
52
53 typedef Vector<Inst> InstList;
54 typedef Vector<BasicBlock*, 2> PredecessorList;
55 typedef Vector<FrequentedBlock, 2> SuccessorList;
56
57 unsigned index() const { return m_index; }
58
59 // This method is exposed for phases that mess with the layout of basic blocks. Currently that means just
60 // optimizeBlockOrder().
61 void setIndex(unsigned index) { m_index = index; }
62
63 unsigned size() const { return m_insts.size(); }
64 InstList::iterator begin() { return m_insts.begin(); }
65 InstList::iterator end() { return m_insts.end(); }
66 InstList::const_iterator begin() const { return m_insts.begin(); }
67 InstList::const_iterator end() const { return m_insts.end(); }
68
69 const Inst& at(unsigned index) const { return m_insts[index]; }
70 Inst& at(unsigned index) { return m_insts[index]; }
71
72 Inst* get(unsigned index)
73 {
74 return index < size() ? &at(index) : nullptr;
75 }
76
77 const Inst& last() const { return m_insts.last(); }
78 Inst& last() { return m_insts.last(); }
79
80 void resize(unsigned size) { m_insts.resize(size); }
81
82 const InstList& insts() const { return m_insts; }
83 InstList& insts() { return m_insts; }
84
85 template<typename Inst>
86 Inst& appendInst(Inst&& inst)
87 {
88 m_insts.append(std::forward<Inst>(inst));
89 return m_insts.last();
90 }
91
92 template<typename... Arguments>
93 Inst& append(Arguments&&... arguments)
94 {
95 m_insts.append(Inst(std::forward<Arguments>(arguments)...));
96 return m_insts.last();
97 }
98
99 // The "0" case is the case to which the branch jumps, so the "then" case. The "1" case is the
100 // "else" case, and is used to represent the fall-through of a conditional branch.
101 unsigned numSuccessors() const { return m_successors.size(); }
102 FrequentedBlock successor(unsigned index) const { return m_successors[index]; }
103 FrequentedBlock& successor(unsigned index) { return m_successors[index]; }
104 const SuccessorList& successors() const { return m_successors; }
105 SuccessorList& successors() { return m_successors; }
106
107 JS_EXPORT_PRIVATE void setSuccessors(FrequentedBlock);
108 JS_EXPORT_PRIVATE void setSuccessors(FrequentedBlock, FrequentedBlock);
109
110 BasicBlock* successorBlock(unsigned index) const { return successor(index).block(); }
111 BasicBlock*& successorBlock(unsigned index) { return successor(index).block(); }
112 SuccessorCollection<BasicBlock, SuccessorList> successorBlocks()
113 {
114 return SuccessorCollection<BasicBlock, SuccessorList>(m_successors);
115 }
116 SuccessorCollection<const BasicBlock, const SuccessorList> successorBlocks() const
117 {
118 return SuccessorCollection<const BasicBlock, const SuccessorList>(m_successors);
119 }
120
121 unsigned numPredecessors() const { return m_predecessors.size(); }
122 BasicBlock* predecessor(unsigned index) const { return m_predecessors[index]; }
123 BasicBlock*& predecessor(unsigned index) { return m_predecessors[index]; }
124 const PredecessorList& predecessors() const { return m_predecessors; }
125 PredecessorList& predecessors() { return m_predecessors; }
126
127 bool addPredecessor(BasicBlock*);
128 bool removePredecessor(BasicBlock*);
129 bool replacePredecessor(BasicBlock* from, BasicBlock* to);
130 bool containsPredecessor(BasicBlock* predecessor) const { return m_predecessors.contains(predecessor); }
131
132 double frequency() const { return m_frequency; }
133
134 void dump(PrintStream&) const;
135 void deepDump(PrintStream&) const;
136
137 void dumpHeader(PrintStream&) const;
138 void dumpFooter(PrintStream&) const;
139
140private:
141 friend class BlockInsertionSet;
142 friend class Code;
143 friend class InsertionSet;
144 friend class PhaseInsertionSet;
145 template<typename> friend class B3::GenericBlockInsertionSet;
146
147 BasicBlock(unsigned index, double frequency);
148
149 unsigned m_index;
150 InstList m_insts;
151 SuccessorList m_successors;
152 PredecessorList m_predecessors;
153 double m_frequency;
154};
155
156class DeepBasicBlockDump {
157public:
158 DeepBasicBlockDump(const BasicBlock* block)
159 : m_block(block)
160 {
161 }
162
163 void dump(PrintStream& out) const
164 {
165 if (m_block)
166 m_block->deepDump(out);
167 else
168 out.print("<null>");
169 }
170
171private:
172 const BasicBlock* m_block;
173};
174
175inline DeepBasicBlockDump deepDump(const BasicBlock* block)
176{
177 return DeepBasicBlockDump(block);
178}
179
180} } } // namespace JSC::B3::Air
181
182#endif // ENABLE(B3_JIT)
183