1/*
2 * Copyright (C) 2013-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(C_LOOP)
29
30#include "GPRInfo.h"
31#include "MacroAssembler.h"
32#include "Reg.h"
33#include "TempRegisterSet.h"
34#include <wtf/Bitmap.h>
35
36namespace JSC {
37
38typedef Bitmap<MacroAssembler::numGPRs + MacroAssembler::numFPRs + 1> RegisterBitmap;
39class RegisterAtOffsetList;
40
41class RegisterSet {
42public:
43 constexpr RegisterSet() { }
44
45 template<typename... Regs>
46 constexpr explicit RegisterSet(Regs... regs)
47 {
48 setMany(regs...);
49 }
50
51 JS_EXPORT_PRIVATE static RegisterSet stackRegisters();
52 JS_EXPORT_PRIVATE static RegisterSet reservedHardwareRegisters();
53 static RegisterSet runtimeTagRegisters();
54 static RegisterSet specialRegisters(); // The union of stack, reserved hardware, and runtime registers.
55 JS_EXPORT_PRIVATE static RegisterSet calleeSaveRegisters();
56 static RegisterSet vmCalleeSaveRegisters(); // Callee save registers that might be saved and used by any tier.
57 static RegisterAtOffsetList* vmCalleeSaveRegisterOffsets();
58 static RegisterSet llintBaselineCalleeSaveRegisters(); // Registers saved and used by the LLInt.
59 static RegisterSet dfgCalleeSaveRegisters(); // Registers saved and used by the DFG JIT.
60 static RegisterSet ftlCalleeSaveRegisters(); // Registers that might be saved and used by the FTL JIT.
61#if ENABLE(WEBASSEMBLY)
62 static RegisterSet webAssemblyCalleeSaveRegisters(); // Registers saved and used by the WebAssembly JIT.
63#endif
64 static RegisterSet volatileRegistersForJSCall();
65 static RegisterSet stubUnavailableRegisters(); // The union of callee saves and special registers.
66 JS_EXPORT_PRIVATE static RegisterSet macroScratchRegisters();
67 JS_EXPORT_PRIVATE static RegisterSet allGPRs();
68 JS_EXPORT_PRIVATE static RegisterSet allFPRs();
69 static RegisterSet allRegisters();
70 JS_EXPORT_PRIVATE static RegisterSet argumentGPRS();
71
72 static RegisterSet registersToNotSaveForJSCall();
73 static RegisterSet registersToNotSaveForCCall();
74
75 void set(Reg reg, bool value = true)
76 {
77 ASSERT(!!reg);
78 m_bits.set(reg.index(), value);
79 }
80
81 void set(JSValueRegs regs, bool value = true)
82 {
83 if (regs.tagGPR() != InvalidGPRReg)
84 set(regs.tagGPR(), value);
85 set(regs.payloadGPR(), value);
86 }
87
88 void clear(Reg reg)
89 {
90 ASSERT(!!reg);
91 set(reg, false);
92 }
93
94 bool get(Reg reg) const
95 {
96 ASSERT(!!reg);
97 return m_bits.get(reg.index());
98 }
99
100 template<typename Iterable>
101 void setAll(const Iterable& iterable)
102 {
103 for (Reg reg : iterable)
104 set(reg);
105 }
106
107 // Also allow add/remove/contains terminology, which means the same thing as set/clear/get.
108 bool add(Reg reg)
109 {
110 ASSERT(!!reg);
111 return !m_bits.testAndSet(reg.index());
112 }
113 bool remove(Reg reg)
114 {
115 ASSERT(!!reg);
116 return m_bits.testAndClear(reg.index());
117 }
118 bool contains(Reg reg) const { return get(reg); }
119
120 void merge(const RegisterSet& other) { m_bits.merge(other.m_bits); }
121 void filter(const RegisterSet& other) { m_bits.filter(other.m_bits); }
122 void exclude(const RegisterSet& other) { m_bits.exclude(other.m_bits); }
123
124 bool subsumes(const RegisterSet& other) const { return m_bits.subsumes(other.m_bits); }
125
126 size_t numberOfSetGPRs() const;
127 size_t numberOfSetFPRs() const;
128 size_t numberOfSetRegisters() const { return m_bits.count(); }
129
130 bool isEmpty() const { return m_bits.isEmpty(); }
131
132 JS_EXPORT_PRIVATE void dump(PrintStream&) const;
133
134 enum EmptyValueTag { EmptyValue };
135 enum DeletedValueTag { DeletedValue };
136
137 RegisterSet(EmptyValueTag)
138 {
139 m_bits.set(hashSpecialBitIndex);
140 }
141
142 RegisterSet(DeletedValueTag)
143 {
144 m_bits.set(hashSpecialBitIndex);
145 m_bits.set(deletedBitIndex);
146 }
147
148 bool isEmptyValue() const
149 {
150 return m_bits.get(hashSpecialBitIndex) && !m_bits.get(deletedBitIndex);
151 }
152
153 bool isDeletedValue() const
154 {
155 return m_bits.get(hashSpecialBitIndex) && m_bits.get(deletedBitIndex);
156 }
157
158 bool operator==(const RegisterSet& other) const { return m_bits == other.m_bits; }
159 bool operator!=(const RegisterSet& other) const { return m_bits != other.m_bits; }
160
161 unsigned hash() const { return m_bits.hash(); }
162
163 template<typename Func>
164 void forEach(const Func& func) const
165 {
166 m_bits.forEachSetBit(
167 [&] (size_t index) {
168 func(Reg::fromIndex(index));
169 });
170 }
171
172 class iterator {
173 public:
174 iterator()
175 {
176 }
177
178 iterator(const RegisterBitmap::iterator& iter)
179 : m_iter(iter)
180 {
181 }
182
183 Reg operator*() const { return Reg::fromIndex(*m_iter); }
184
185 iterator& operator++()
186 {
187 ++m_iter;
188 return *this;
189 }
190
191 bool operator==(const iterator& other)
192 {
193 return m_iter == other.m_iter;
194 }
195
196 bool operator!=(const iterator& other)
197 {
198 return !(*this == other);
199 }
200
201 private:
202 RegisterBitmap::iterator m_iter;
203 };
204
205 iterator begin() const { return iterator(m_bits.begin()); }
206 iterator end() const { return iterator(m_bits.end()); }
207
208private:
209 void setAny(Reg reg) { set(reg); }
210 void setAny(JSValueRegs regs) { set(regs); }
211 void setAny(const RegisterSet& set) { merge(set); }
212 void setMany() { }
213 template<typename RegType, typename... Regs>
214 void setMany(RegType reg, Regs... regs)
215 {
216 setAny(reg);
217 setMany(regs...);
218 }
219
220 // These offsets mirror the logic in Reg.h.
221 static const unsigned gprOffset = 0;
222 static const unsigned fprOffset = gprOffset + MacroAssembler::numGPRs;
223 static const unsigned hashSpecialBitIndex = fprOffset + MacroAssembler::numFPRs;
224 static const unsigned deletedBitIndex = 0;
225
226 RegisterBitmap m_bits;
227};
228
229struct RegisterSetHash {
230 static unsigned hash(const RegisterSet& set) { return set.hash(); }
231 static bool equal(const RegisterSet& a, const RegisterSet& b) { return a == b; }
232 static const bool safeToCompareToEmptyOrDeleted = false;
233};
234
235} // namespace JSC
236
237namespace WTF {
238
239template<typename T> struct DefaultHash;
240template<> struct DefaultHash<JSC::RegisterSet> {
241 typedef JSC::RegisterSetHash Hash;
242};
243
244template<typename T> struct HashTraits;
245template<> struct HashTraits<JSC::RegisterSet> : public CustomHashTraits<JSC::RegisterSet> { };
246
247} // namespace WTF
248
249#endif // !ENABLE(C_LOOP)
250