]>
Commit | Line | Data |
---|---|---|
81345200 A |
1 | /* |
2 | * Copyright (C) 2013, 2014 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 | #ifndef FTLLocation_h | |
27 | #define FTLLocation_h | |
28 | ||
29 | #if ENABLE(FTL_JIT) | |
30 | ||
31 | #include "FPRInfo.h" | |
32 | #include "FTLDWARFRegister.h" | |
33 | #include "FTLStackMaps.h" | |
34 | #include "GPRInfo.h" | |
35 | #include <wtf/HashMap.h> | |
36 | ||
37 | namespace JSC { namespace FTL { | |
38 | ||
39 | class Location { | |
40 | public: | |
41 | enum Kind { | |
42 | Unprocessed, | |
43 | Register, | |
44 | Indirect, | |
45 | Constant | |
46 | }; | |
47 | ||
48 | Location() | |
49 | : m_kind(Unprocessed) | |
50 | { | |
51 | u.constant = 0; | |
52 | } | |
53 | ||
54 | Location(WTF::HashTableDeletedValueType) | |
55 | : m_kind(Unprocessed) | |
56 | { | |
57 | u.constant = 1; | |
58 | } | |
59 | ||
60 | static Location forRegister(DWARFRegister dwarfReg, int32_t addend) | |
61 | { | |
62 | Location result; | |
63 | result.m_kind = Register; | |
64 | result.u.variable.dwarfRegNum = dwarfReg.dwarfRegNum(); | |
65 | result.u.variable.offset = addend; | |
66 | return result; | |
67 | } | |
68 | ||
69 | static Location forIndirect(DWARFRegister dwarfReg, int32_t offset) | |
70 | { | |
71 | Location result; | |
72 | result.m_kind = Indirect; | |
73 | result.u.variable.dwarfRegNum = dwarfReg.dwarfRegNum(); | |
74 | result.u.variable.offset = offset; | |
75 | return result; | |
76 | } | |
77 | ||
78 | static Location forConstant(int64_t constant) | |
79 | { | |
80 | Location result; | |
81 | result.m_kind = Constant; | |
82 | result.u.constant = constant; | |
83 | return result; | |
84 | } | |
85 | ||
86 | // You can pass a null StackMaps if you are confident that the location doesn't | |
87 | // involve a wide constant. | |
88 | static Location forStackmaps(const StackMaps*, const StackMaps::Location&); | |
89 | ||
90 | Kind kind() const { return m_kind; } | |
91 | ||
92 | bool hasDwarfRegNum() const { return kind() == Register || kind() == Indirect; } | |
93 | int16_t dwarfRegNum() const | |
94 | { | |
95 | ASSERT(hasDwarfRegNum()); | |
96 | return u.variable.dwarfRegNum; | |
97 | } | |
98 | ||
99 | bool hasDwarfReg() const { return hasDwarfRegNum(); } | |
100 | DWARFRegister dwarfReg() const { return DWARFRegister(dwarfRegNum()); } | |
101 | ||
102 | bool hasOffset() const { return kind() == Indirect; } | |
103 | int32_t offset() const | |
104 | { | |
105 | ASSERT(hasOffset()); | |
106 | return u.variable.offset; | |
107 | } | |
108 | ||
109 | bool hasAddend() const { return kind() == Register; } | |
110 | int32_t addend() const | |
111 | { | |
112 | ASSERT(hasAddend()); | |
113 | return u.variable.offset; | |
114 | } | |
115 | ||
116 | bool hasConstant() const { return kind() == Constant; } | |
117 | int64_t constant() const | |
118 | { | |
119 | ASSERT(hasConstant()); | |
120 | return u.constant; | |
121 | } | |
122 | ||
123 | bool operator!() const { return kind() == Unprocessed && !u.variable.offset; } | |
124 | ||
125 | bool isHashTableDeletedValue() const { return kind() == Unprocessed && u.variable.offset; } | |
126 | ||
127 | bool operator==(const Location& other) const | |
128 | { | |
129 | return m_kind == other.m_kind | |
130 | && u.constant == other.u.constant; | |
131 | } | |
132 | ||
133 | unsigned hash() const | |
134 | { | |
135 | unsigned result = m_kind; | |
136 | ||
137 | switch (kind()) { | |
138 | case Unprocessed: | |
139 | result ^= u.variable.offset; | |
140 | break; | |
141 | ||
142 | case Register: | |
143 | result ^= u.variable.dwarfRegNum; | |
144 | break; | |
145 | ||
146 | case Indirect: | |
147 | result ^= u.variable.dwarfRegNum; | |
148 | result ^= u.variable.offset; | |
149 | break; | |
150 | ||
151 | case Constant: | |
152 | result ^= WTF::IntHash<int64_t>::hash(u.constant); | |
153 | break; | |
154 | } | |
155 | ||
156 | return WTF::IntHash<unsigned>::hash(result); | |
157 | } | |
158 | ||
159 | void dump(PrintStream&) const; | |
160 | ||
161 | bool isGPR() const; | |
162 | bool involvesGPR() const; | |
163 | GPRReg gpr() const; | |
164 | GPRReg directGPR() const; // Get the GPR and assert that there is no addend. | |
165 | ||
166 | bool isFPR() const; | |
167 | FPRReg fpr() const; | |
168 | ||
169 | // Assuming that all registers are saved to the savedRegisters buffer according | |
170 | // to FTLSaveRestore convention, this loads the value into the given register. | |
171 | // The code that this generates isn't exactly super fast. This assumes that FP | |
172 | // and SP contain the same values that they would have contained in the original | |
173 | // frame, or that you've done one or more canonically formed calls (i.e. can | |
174 | // restore the FP by following the call frame linked list numFramesToPop times, | |
175 | // and SP can be recovered by popping FP numFramesToPop-1 times and adding 16). | |
176 | void restoreInto(MacroAssembler&, char* savedRegisters, GPRReg result, unsigned numFramesToPop = 0) const; | |
177 | ||
178 | private: | |
179 | Kind m_kind; | |
180 | union { | |
181 | int64_t constant; | |
182 | struct { | |
183 | int16_t dwarfRegNum; | |
184 | int32_t offset; | |
185 | } variable; | |
186 | } u; | |
187 | }; | |
188 | ||
189 | struct LocationHash { | |
190 | static unsigned hash(const Location& key) { return key.hash(); } | |
191 | static bool equal(const Location& a, const Location& b) { return a == b; } | |
192 | static const bool safeToCompareToEmptyOrDeleted = true; | |
193 | }; | |
194 | ||
195 | } } // namespace JSC::FTL | |
196 | ||
197 | namespace WTF { | |
198 | ||
199 | void printInternal(PrintStream&, JSC::FTL::Location::Kind); | |
200 | ||
201 | template<typename T> struct DefaultHash; | |
202 | template<> struct DefaultHash<JSC::FTL::Location> { | |
203 | typedef JSC::FTL::LocationHash Hash; | |
204 | }; | |
205 | ||
206 | template<typename T> struct HashTraits; | |
207 | template<> struct HashTraits<JSC::FTL::Location> : SimpleClassHashTraits<JSC::FTL::Location> { }; | |
208 | ||
209 | } // namespace WTF | |
210 | ||
211 | #endif // ENABLE(FTL_JIT) | |
212 | ||
213 | #endif // FTLLocation_h | |
214 |