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 template<typename ValueType, typename... Arguments>
88 ValueType* appendNewNonTerminal(Procedure&, Arguments...);
89
90 JS_EXPORT_PRIVATE Value* appendIntConstant(Procedure&, Origin, Type, int64_t value);
91 Value* appendIntConstant(Procedure&, Value* likeValue, int64_t value);
92 Value* appendBoolConstant(Procedure&, Origin, bool);
93
94 void removeLast(Procedure&);
95
96 template<typename ValueType, typename... Arguments>
97 ValueType* replaceLastWithNew(Procedure&, Arguments...);
98
99 unsigned numSuccessors() const { return m_successors.size(); }
100 const FrequentedBlock& successor(unsigned index) const { return m_successors[index]; }
101 FrequentedBlock& successor(unsigned index) { return m_successors[index]; }
102 const SuccessorList& successors() const { return m_successors; }
103 SuccessorList& successors() { return m_successors; }
104
105 void clearSuccessors();
106 JS_EXPORT_PRIVATE void appendSuccessor(FrequentedBlock);
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>(successors());
115 }
116 SuccessorCollection<const BasicBlock, const SuccessorList> successorBlocks() const
117 {
118 return SuccessorCollection<const BasicBlock, const SuccessorList>(successors());
119 }
120
121 bool replaceSuccessor(BasicBlock* from, BasicBlock* to);
122
123 // This is only valid for Jump and Branch.
124 const FrequentedBlock& taken() const;
125 FrequentedBlock& taken();
126 // This is only valid for Branch.
127 const FrequentedBlock& notTaken() const;
128 FrequentedBlock& notTaken();
129 // This is only valid for Branch and Switch.
130 const FrequentedBlock& fallThrough() const;
131 FrequentedBlock& fallThrough();
132
133 unsigned numPredecessors() const { return m_predecessors.size(); }
134 BasicBlock* predecessor(unsigned index) const { return m_predecessors[index]; }
135 BasicBlock*& predecessor(unsigned index) { return m_predecessors[index]; }
136 const PredecessorList& predecessors() const { return m_predecessors; }
137 PredecessorList& predecessors() { return m_predecessors; }
138 bool containsPredecessor(BasicBlock* block) { return m_predecessors.contains(block); }
139
140 bool addPredecessor(BasicBlock*);
141 bool removePredecessor(BasicBlock*);
142 bool replacePredecessor(BasicBlock* from, BasicBlock* to);
143
144 // Update predecessors starting with the successors of this block.
145 void updatePredecessorsAfter();
146
147 double frequency() const { return m_frequency; }
148
149 void dump(PrintStream&) const;
150 void deepDump(const Procedure&, PrintStream&) const;
151
152 // These are deprecated method for compatibility with the old ControlValue class. Don't use them
153 // in new code.
154 // FIXME: https://bugs.webkit.org/show_bug.cgi?id=159440
155
156 // Use this for Oops.
157 JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin);
158 // Use this for Return.
159 JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin, Value*);
160 // Use this for Jump.
161 JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin, const FrequentedBlock&);
162 // Use this for Branch.
163 JS_EXPORT_PRIVATE Value* appendNewControlValue(Procedure&, Opcode, Origin, Value*, const FrequentedBlock&, const FrequentedBlock&);
164
165private:
166 friend class BlockInsertionSet;
167 friend class InsertionSet;
168 friend class Procedure;
169 template<typename> friend class GenericBlockInsertionSet;
170
171 // Instantiate via Procedure.
172 BasicBlock(unsigned index, double frequency);
173
174 unsigned m_index;
175 ValueList m_values;
176 PredecessorList m_predecessors;
177 SuccessorList m_successors;
178 double m_frequency;
179};
180
181class DeepBasicBlockDump {
182public:
183 DeepBasicBlockDump(const Procedure& proc, const BasicBlock* block)
184 : m_proc(proc)
185 , m_block(block)
186 {
187 }
188
189 void dump(PrintStream& out) const
190 {
191 if (m_block)
192 m_block->deepDump(m_proc, out);
193 else
194 out.print("<null>");
195 }
196
197private:
198 const Procedure& m_proc;
199 const BasicBlock* m_block;
200};
201
202inline DeepBasicBlockDump deepDump(const Procedure& proc, const BasicBlock* block)
203{
204 return DeepBasicBlockDump(proc, block);
205}
206
207} } // namespace JSC::B3
208
209#endif // ENABLE(B3_JIT)
210