]>
git.saurik.com Git - apple/javascriptcore.git/blob - ftl/FTLStackMaps.cpp
2 * Copyright (C) 2013, 2014 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "FTLStackMaps.h"
31 #include "FTLLocation.h"
32 #include <wtf/CommaPrinter.h>
33 #include <wtf/DataLog.h>
34 #include <wtf/ListDump.h>
36 namespace JSC
{ namespace FTL
{
39 T
readObject(StackMaps::ParseContext
& context
)
42 result
.parse(context
);
46 void StackMaps::Constant::parse(StackMaps::ParseContext
& context
)
48 integer
= context
.view
->read
<int64_t>(context
.offset
, true);
51 void StackMaps::Constant::dump(PrintStream
& out
) const
53 out
.printf("0x%016llx", static_cast<unsigned long long>(integer
));
56 void StackMaps::StackSize::parse(StackMaps::ParseContext
& context
)
58 switch (context
.version
) {
60 functionOffset
= context
.view
->read
<uint32_t>(context
.offset
, true);
61 size
= context
.view
->read
<uint32_t>(context
.offset
, true);
65 functionOffset
= context
.view
->read
<uint64_t>(context
.offset
, true);
66 size
= context
.view
->read
<uint64_t>(context
.offset
, true);
71 void StackMaps::StackSize::dump(PrintStream
& out
) const
73 out
.print("(off:", functionOffset
, ", size:", size
, ")");
76 void StackMaps::Location::parse(StackMaps::ParseContext
& context
)
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);
84 void StackMaps::Location::dump(PrintStream
& out
) const
86 out
.print("(", kind
, ", ", dwarfReg
, ", off:", offset
, ", size:", size
, ")");
89 GPRReg
StackMaps::Location::directGPR() const
91 return FTL::Location::forStackmaps(nullptr, *this).directGPR();
94 void StackMaps::Location::restoreInto(
95 MacroAssembler
& jit
, StackMaps
& stackmaps
, char* savedRegisters
, GPRReg result
) const
97 FTL::Location::forStackmaps(&stackmaps
, *this).restoreInto(jit
, savedRegisters
, result
);
100 void StackMaps::LiveOut::parse(StackMaps::ParseContext
& context
)
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
107 void StackMaps::LiveOut::dump(PrintStream
& out
) const
109 out
.print("(", dwarfReg
, ", ", size
, ")");
112 bool StackMaps::Record::parse(StackMaps::ParseContext
& context
)
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)
120 instructionOffset
= context
.view
->read
<uint32_t>(context
.offset
, true);
121 flags
= context
.view
->read
<uint16_t>(context
.offset
, true);
123 unsigned length
= context
.view
->read
<uint16_t>(context
.offset
, true);
125 locations
.append(readObject
<Location
>(context
));
127 if (context
.version
>= 1)
128 context
.view
->read
<uint16_t>(context
.offset
, true); // padding
130 unsigned numLiveOuts
= context
.view
->read
<uint16_t>(context
.offset
, true);
131 while (numLiveOuts
--)
132 liveOuts
.append(readObject
<LiveOut
>(context
));
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
144 void StackMaps::Record::dump(PrintStream
& out
) const
147 "(#", patchpointID
, ", offset = ", instructionOffset
, ", flags = ", flags
,
148 ", locations = [", listDump(locations
), "], liveOuts = [",
149 listDump(liveOuts
), "])");
152 RegisterSet
StackMaps::Record::locationSet() const
155 for (unsigned i
= locations
.size(); i
--;) {
156 Reg reg
= locations
[i
].dwarfReg
.reg();
164 RegisterSet
StackMaps::Record::liveOutsSet() const
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
174 dataLog("Invalid liveOuts entry in: ", *this, "\n");
175 RELEASE_ASSERT_NOT_REACHED();
182 RegisterSet
StackMaps::Record::usedRegisterSet() const
185 result
.merge(locationSet());
186 result
.merge(liveOutsSet());
190 bool StackMaps::parse(DataView
* view
)
192 ParseContext context
;
196 version
= context
.version
= context
.view
->read
<uint8_t>(context
.offset
, true);
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
202 uint32_t numFunctions
;
203 uint32_t numConstants
;
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);
211 while (numFunctions
--)
212 stackSizes
.append(readObject
<StackSize
>(context
));
214 if (!context
.version
)
215 numConstants
= context
.view
->read
<uint32_t>(context
.offset
, true);
216 while (numConstants
--)
217 constants
.append(readObject
<Constant
>(context
));
219 if (!context
.version
)
220 numRecords
= context
.view
->read
<uint32_t>(context
.offset
, true);
221 while (numRecords
--) {
223 if (!record
.parse(context
))
225 records
.append(record
);
231 void StackMaps::dump(PrintStream
& out
) const
233 out
.print("Version:", version
, ", StackSizes[", listDump(stackSizes
), "], Constants:[", listDump(constants
), "], Records:[", listDump(records
), "]");
236 void StackMaps::dumpMultiline(PrintStream
& out
, const char* prefix
) const
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");
250 StackMaps::RecordMap
StackMaps::computeRecordMap() const
253 for (unsigned i
= records
.size(); i
--;)
254 result
.add(records
[i
].patchpointID
, Vector
<Record
>()).iterator
->value
.append(records
[i
]);
258 unsigned StackMaps::stackSize() const
260 RELEASE_ASSERT(stackSizes
.size() == 1);
262 return stackSizes
[0].size
;
265 } } // namespace JSC::FTL
269 using namespace JSC::FTL
;
271 void printInternal(PrintStream
& out
, StackMaps::Location::Kind kind
)
274 case StackMaps::Location::Unprocessed
:
275 out
.print("Unprocessed");
277 case StackMaps::Location::Register
:
278 out
.print("Register");
280 case StackMaps::Location::Direct
:
283 case StackMaps::Location::Indirect
:
284 out
.print("Indirect");
286 case StackMaps::Location::Constant
:
287 out
.print("Constant");
289 case StackMaps::Location::ConstantIndex
:
290 out
.print("ConstantIndex");
293 dataLog("Unrecognized kind: ", static_cast<int>(kind
), "\n");
294 RELEASE_ASSERT_NOT_REACHED();
299 #endif // ENABLE(FTL_JIT)