]> git.saurik.com Git - apple/javascriptcore.git/blame - ftl/FTLStackMaps.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / ftl / FTLStackMaps.cpp
CommitLineData
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#include "config.h"
27#include "FTLStackMaps.h"
28
29#if ENABLE(FTL_JIT)
30
31#include "FTLLocation.h"
32#include <wtf/CommaPrinter.h>
33#include <wtf/DataLog.h>
34#include <wtf/ListDump.h>
35
36namespace JSC { namespace FTL {
37
38template<typename T>
39T readObject(StackMaps::ParseContext& context)
40{
41 T result;
42 result.parse(context);
43 return result;
44}
45
46void StackMaps::Constant::parse(StackMaps::ParseContext& context)
47{
48 integer = context.view->read<int64_t>(context.offset, true);
49}
50
51void StackMaps::Constant::dump(PrintStream& out) const
52{
53 out.printf("0x%016llx", static_cast<unsigned long long>(integer));
54}
55
56void StackMaps::StackSize::parse(StackMaps::ParseContext& context)
57{
58 switch (context.version) {
59 case 0:
60 functionOffset = context.view->read<uint32_t>(context.offset, true);
61 size = context.view->read<uint32_t>(context.offset, true);
62 break;
63
64 default:
65 functionOffset = context.view->read<uint64_t>(context.offset, true);
66 size = context.view->read<uint64_t>(context.offset, true);
67 break;
68 }
69}
70
71void StackMaps::StackSize::dump(PrintStream& out) const
72{
73 out.print("(off:", functionOffset, ", size:", size, ")");
74}
75
76void StackMaps::Location::parse(StackMaps::ParseContext& context)
77{
78 kind = static_cast<Kind>(context.view->read<uint8_t>(context.offset, true));
79 size = context.view->read<uint8_t>(context.offset, true);
80 dwarfReg = DWARFRegister(context.view->read<uint16_t>(context.offset, true));
81 this->offset = context.view->read<int32_t>(context.offset, true);
82}
83
84void StackMaps::Location::dump(PrintStream& out) const
85{
86 out.print("(", kind, ", ", dwarfReg, ", off:", offset, ", size:", size, ")");
87}
88
89GPRReg StackMaps::Location::directGPR() const
90{
91 return FTL::Location::forStackmaps(nullptr, *this).directGPR();
92}
93
94void StackMaps::Location::restoreInto(
95 MacroAssembler& jit, StackMaps& stackmaps, char* savedRegisters, GPRReg result) const
96{
97 FTL::Location::forStackmaps(&stackmaps, *this).restoreInto(jit, savedRegisters, result);
98}
99
100void StackMaps::LiveOut::parse(StackMaps::ParseContext& context)
101{
102 dwarfReg = DWARFRegister(context.view->read<uint16_t>(context.offset, true)); // regnum
103 context.view->read<uint8_t>(context.offset, true); // reserved
104 size = context.view->read<uint8_t>(context.offset, true); // size in bytes
105}
106
107void StackMaps::LiveOut::dump(PrintStream& out) const
108{
109 out.print("(", dwarfReg, ", ", size, ")");
110}
111
112bool StackMaps::Record::parse(StackMaps::ParseContext& context)
113{
114 int64_t id = context.view->read<int64_t>(context.offset, true);
115 ASSERT(static_cast<int32_t>(id) == id);
116 patchpointID = static_cast<uint32_t>(id);
117 if (static_cast<int32_t>(patchpointID) < 0)
118 return false;
119
120 instructionOffset = context.view->read<uint32_t>(context.offset, true);
121 flags = context.view->read<uint16_t>(context.offset, true);
122
123 unsigned length = context.view->read<uint16_t>(context.offset, true);
124 while (length--)
125 locations.append(readObject<Location>(context));
126
127 if (context.version >= 1)
128 context.view->read<uint16_t>(context.offset, true); // padding
129
130 unsigned numLiveOuts = context.view->read<uint16_t>(context.offset, true);
131 while (numLiveOuts--)
132 liveOuts.append(readObject<LiveOut>(context));
133
134 if (context.version >= 1) {
135 if (context.offset & 7) {
136 ASSERT(!(context.offset & 3));
137 context.view->read<uint32_t>(context.offset, true); // padding
138 }
139 }
140
141 return true;
142}
143
144void StackMaps::Record::dump(PrintStream& out) const
145{
146 out.print(
147 "(#", patchpointID, ", offset = ", instructionOffset, ", flags = ", flags,
148 ", locations = [", listDump(locations), "], liveOuts = [",
149 listDump(liveOuts), "])");
150}
151
152RegisterSet StackMaps::Record::locationSet() const
153{
154 RegisterSet result;
155 for (unsigned i = locations.size(); i--;) {
156 Reg reg = locations[i].dwarfReg.reg();
157 if (!reg)
158 continue;
159 result.set(reg);
160 }
161 return result;
162}
163
164RegisterSet StackMaps::Record::liveOutsSet() const
165{
166 RegisterSet result;
167 for (unsigned i = liveOuts.size(); i--;) {
168 LiveOut liveOut = liveOuts[i];
169 Reg reg = liveOut.dwarfReg.reg();
170 // FIXME: Either assert that size is not greater than sizeof(pointer), or actually
171 // save the high bits of registers.
172 // https://bugs.webkit.org/show_bug.cgi?id=130885
173 if (!reg) {
174 dataLog("Invalid liveOuts entry in: ", *this, "\n");
175 RELEASE_ASSERT_NOT_REACHED();
176 }
177 result.set(reg);
178 }
179 return result;
180}
181
182RegisterSet StackMaps::Record::usedRegisterSet() const
183{
184 RegisterSet result;
185 result.merge(locationSet());
186 result.merge(liveOutsSet());
187 return result;
188}
189
190bool StackMaps::parse(DataView* view)
191{
192 ParseContext context;
193 context.offset = 0;
194 context.view = view;
195
196 version = context.version = context.view->read<uint8_t>(context.offset, true);
197
198 context.view->read<uint8_t>(context.offset, true); // Reserved
199 context.view->read<uint8_t>(context.offset, true); // Reserved
200 context.view->read<uint8_t>(context.offset, true); // Reserved
201
202 uint32_t numFunctions;
203 uint32_t numConstants;
204 uint32_t numRecords;
205
206 numFunctions = context.view->read<uint32_t>(context.offset, true);
207 if (context.version >= 1) {
208 numConstants = context.view->read<uint32_t>(context.offset, true);
209 numRecords = context.view->read<uint32_t>(context.offset, true);
210 }
211 while (numFunctions--)
212 stackSizes.append(readObject<StackSize>(context));
213
214 if (!context.version)
215 numConstants = context.view->read<uint32_t>(context.offset, true);
216 while (numConstants--)
217 constants.append(readObject<Constant>(context));
218
219 if (!context.version)
220 numRecords = context.view->read<uint32_t>(context.offset, true);
221 while (numRecords--) {
222 Record record;
223 if (!record.parse(context))
224 return false;
225 records.append(record);
226 }
227
228 return true;
229}
230
231void StackMaps::dump(PrintStream& out) const
232{
233 out.print("Version:", version, ", StackSizes[", listDump(stackSizes), "], Constants:[", listDump(constants), "], Records:[", listDump(records), "]");
234}
235
236void StackMaps::dumpMultiline(PrintStream& out, const char* prefix) const
237{
238 out.print(prefix, "Version: ", version, "\n");
239 out.print(prefix, "StackSizes:\n");
240 for (unsigned i = 0; i < stackSizes.size(); ++i)
241 out.print(prefix, " ", stackSizes[i], "\n");
242 out.print(prefix, "Constants:\n");
243 for (unsigned i = 0; i < constants.size(); ++i)
244 out.print(prefix, " ", constants[i], "\n");
245 out.print(prefix, "Records:\n");
246 for (unsigned i = 0; i < records.size(); ++i)
247 out.print(prefix, " ", records[i], "\n");
248}
249
250StackMaps::RecordMap StackMaps::computeRecordMap() const
251{
252 RecordMap result;
253 for (unsigned i = records.size(); i--;)
254 result.add(records[i].patchpointID, Vector<Record>()).iterator->value.append(records[i]);
255 return result;
256}
257
258unsigned StackMaps::stackSize() const
259{
260 RELEASE_ASSERT(stackSizes.size() == 1);
261
262 return stackSizes[0].size;
263}
264
265} } // namespace JSC::FTL
266
267namespace WTF {
268
269using namespace JSC::FTL;
270
271void printInternal(PrintStream& out, StackMaps::Location::Kind kind)
272{
273 switch (kind) {
274 case StackMaps::Location::Unprocessed:
275 out.print("Unprocessed");
276 return;
277 case StackMaps::Location::Register:
278 out.print("Register");
279 return;
280 case StackMaps::Location::Direct:
281 out.print("Direct");
282 return;
283 case StackMaps::Location::Indirect:
284 out.print("Indirect");
285 return;
286 case StackMaps::Location::Constant:
287 out.print("Constant");
288 return;
289 case StackMaps::Location::ConstantIndex:
290 out.print("ConstantIndex");
291 return;
292 }
293 dataLog("Unrecognized kind: ", static_cast<int>(kind), "\n");
294 RELEASE_ASSERT_NOT_REACHED();
295}
296
297} // namespace WTF
298
299#endif // ENABLE(FTL_JIT)
300