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 "B3FrequentedBlock.h"
31#include "B3Opcode.h"
32#include "B3Origin.h"
33#include "B3SuccessorCollection.h"
34#include "B3Type.h"
35#include <wtf/Vector.h>
36
37namespace JSC { namespace B3 {
38
39class BlockInsertionSet;
40class InsertionSet;
41class Procedure;
42class Value;
43template<typename> class GenericBlockInsertionSet;
44
45class BasicBlock {
46 WTF_MAKE_NONCOPYABLE(BasicBlock);
47 WTF_MAKE_FAST_ALLOCATED;
48public:
49 typedef Vector<Value*> ValueList;
50 typedef Vector<BasicBlock*, 2> PredecessorList;
51 typedef Vector<FrequentedBlock, 2> SuccessorList;
52
53 static const char* const dumpPrefix;
54
55 ~BasicBlock();
56
57 unsigned index() const { return m_index; }
58
59 ValueList::iterator begin() { return m_values.begin(); }
60 ValueList::iterator end() { return m_values.end(); }
61 ValueList::const_iterator begin() const { return m_values.begin(); }
62 ValueList::const_iterator end() const { return m_values.end(); }
63
64 size_t size() const { return m_values.size(); }
65 Value* at(size_t index) const { return m_values[index]; }
66 Value*& at(size_t index) { return m_values[index]; }
67
68 Value* get(size_t index) const
69 {
70 if (index >= size())
71 return nullptr;
72 return at(index);
73 }
74
75 Value* last() const { return m_values.last(); }
76 Value*& last() { return m_values.last(); }
77
78 const ValueList& values() const { return m_values; }
79 ValueList& values() { return m_values; }
80
81 JS_EXPORT_PRIVATE void append(Value*);
82 JS_EXPORT_PRIVATE void appendNonTerminal(Value*);
83 JS_EXPORT_PRIVATE void replaceLast(Procedure&, Value*);
84
85 template<typename ValueType, typename... Arguments>
86 ValueType* appendNew(Procedure&, Arguments...);
87
88 JS_EXPORT_PRIVATE Value* appendIntConstant(Procedure&, Origin, Type, int64_t value);
89 Value* appendIntConstant(Procedure&, Value* likeValue, int64_t value);
90 Value* appendBoolConstant(Procedure&, Origin, bool);
91
92 void removeLast(Procedure&);
93
94 template<typename ValueType, typename... Arguments>
95 ValueType* replaceLastWithNew(Procedure&, Arguments...);
96
97 unsigned numSuccessors() const { return m_successors.size(); }
98 const FrequentedBlock& successor(unsigned index) const { return m_successors[index]; }
99 FrequentedBlock& successor(unsigned index) { return m_successors[index]; }
100 const SuccessorList& successors() const { return m_successors; }
101 SuccessorList& successors() { return m_successors; }
102
103 void clearSuccessors();
104 JS_EXPORT_PRIVATE void appendSuccessor(FrequentedBlock);
105 JS_EXPORT_PRIVATE void setSuccessors(FrequentedBlock);
106 JS_EXPORT_PRIVATE void setSuccessors(FrequentedBlock, FrequentedBlock);
107
108 BasicBlock* successorBlock(unsigned index) const { return successor(index).block(); }
109 BasicBlock*& successorBlock(unsigned index) { return successor(index).block(); }
110 SuccessorCollection<BasicBlock, SuccessorList> successorBlocks()
111 {
112 return SuccessorCollection<BasicBlock, SuccessorList>(successors());
113 }
114 SuccessorCollection<const BasicBlock, const SuccessorList> successorBlocks() const
115 {
116 return SuccessorCollection<const BasicBlock, const SuccessorList>(successors());
117 }
118
119 bool replaceSuccessor(BasicBlock* from, BasicBlock* to);
120
121 // This is only valid for Jump and Branch.
122 const FrequentedBlock& taken() const;
123 FrequentedBlock& taken();
124 // This is only valid for Branch.
125 const FrequentedBlock& notTaken() const;
126 FrequentedBlock& notTaken();
127 // This is only valid for Branch and Switch.
128 const FrequentedBlock& fallThrough() const;
129 FrequentedBlock& fallThrough();
130
131 unsigned numPredecessors() const { return m_predecessors.size(); }
132 BasicBlock* predecessor(unsigned index) const { return m_predecessors[index]; }
133 BasicBlock*& predecessor(unsigned index) { return m_predecessors[index]; }
134 const PredecessorList& predecessors() const { return m_predecessors; }
135 PredecessorList& predecessors() { return m_predecessors; }
136 bool containsPredecessor(BasicBlock* block) { return m_predecessors.contains(block); }
137
138 bool addPredecessor(BasicBlock*);
139 bool removePredecessor(BasicBlock*);
140 bool replacePredecessor(BasicBlock* from, BasicBlock* to);
141
142 // Update predecessors starting with the successors of this block.
143 void updatePredecessorsAfter();
144
145 double frequency() const { return m_frequency; }
146
147 void dump(PrintStream&) const;
148 void deepDump(const Procedure&, PrintStream&) const;
149
150 // These are deprecated method for compatibility with the old ControlValue class. Don't use them
151 // in new code.
152 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=159440
153
154 // Use this for Oops.
155 JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin);
156 // Use this for Return.
157 JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin, Value*);
158 // Use this for Jump.
159 JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin, const FrequentedBlock&);
160 // Use this for Branch.
161 JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin, Value*, const FrequentedBlock&, const FrequentedBlock&);
162
163private:
164 friend class BlockInsertionSet;
165 friend class InsertionSet;
166 friend class Procedure;
167 template<typename> friend class GenericBlockInsertionSet;
168
169 // Instantiate via Procedure.
170 BasicBlock(unsigned index, double frequency);
171
172 unsigned m_index;
173 ValueList m_values;
174 PredecessorList m_predecessors;
175 SuccessorList m_successors;
176 double m_frequency;
177};
178
179class DeepBasicBlockDump {
180public:
181 DeepBasicBlockDump(const Procedure& proc, const BasicBlock* block)
182 : m_proc(proc)
183 , m_block(block)
184 {
185 }
186
187 void dump(PrintStream& out) const
188 {
189 if (m_block)
190 m_block->deepDump(m_proc, out);
191 else
192 out.print("<null>");
193 }
194
195private:
196 const Procedure& m_proc;
197 const BasicBlock* m_block;
198};
199
200inline DeepBasicBlockDump deepDump(const Procedure& proc, const BasicBlock* block)
201{
202 return DeepBasicBlockDump(proc, block);
203}
204
205} } // namespace JSC::B3
206
207#endif // ENABLE(B3_JIT)
208