2 * Copyright (C) 2012-2015 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 "DFGVariableEventStream.h"
31 #include "CodeBlock.h"
32 #include "DFGJITCode.h"
33 #include "DFGValueSource.h"
34 #include "JSCInlines.h"
35 #include <wtf/DataLog.h>
36 #include <wtf/HashMap.h>
38 namespace JSC
{ namespace DFG
{
40 void VariableEventStream::logEvent(const VariableEvent
& event
)
42 dataLogF("seq#%u:", static_cast<unsigned>(size()));
43 event
.dump(WTF::dataFile());
49 struct MinifiedGenerationInfo
{
50 bool filled
; // true -> in gpr/fpr/pair, false -> spilled
52 VariableRepresentation u
;
55 MinifiedGenerationInfo()
58 , format(DataFormatNone
)
62 void update(const VariableEvent
& event
)
64 switch (event
.kind()) {
79 format
= DataFormatNone
;
86 u
= event
.variableRepresentation();
87 format
= event
.dataFormat();
93 bool VariableEventStream::tryToSetConstantRecovery(ValueRecovery
& recovery
, MinifiedNode
* node
) const
98 if (node
->hasConstant()) {
99 recovery
= ValueRecovery::constant(node
->constant());
103 if (node
->op() == PhantomDirectArguments
) {
104 recovery
= ValueRecovery::directArgumentsThatWereNotCreated(node
->id());
108 if (node
->op() == PhantomClonedArguments
) {
109 recovery
= ValueRecovery::outOfBandArgumentsThatWereNotCreated(node
->id());
116 void VariableEventStream::reconstruct(
117 CodeBlock
* codeBlock
, CodeOrigin codeOrigin
, MinifiedGraph
& graph
,
118 unsigned index
, Operands
<ValueRecovery
>& valueRecoveries
) const
120 ASSERT(codeBlock
->jitType() == JITCode::DFGJIT
);
121 CodeBlock
* baselineCodeBlock
= codeBlock
->baselineVersion();
123 unsigned numVariables
;
124 if (codeOrigin
.inlineCallFrame
)
125 numVariables
= baselineCodeBlockForInlineCallFrame(codeOrigin
.inlineCallFrame
)->m_numCalleeRegisters
+ VirtualRegister(codeOrigin
.inlineCallFrame
->stackOffset
).toLocal() + 1;
127 numVariables
= baselineCodeBlock
->m_numCalleeRegisters
;
129 // Crazy special case: if we're at index == 0 then this must be an argument check
130 // failure, in which case all variables are already set up. The recoveries should
133 valueRecoveries
= Operands
<ValueRecovery
>(codeBlock
->numParameters(), numVariables
);
134 for (size_t i
= 0; i
< valueRecoveries
.size(); ++i
) {
135 valueRecoveries
[i
] = ValueRecovery::displacedInJSStack(
136 VirtualRegister(valueRecoveries
.operandForIndex(i
)), DataFormatJS
);
141 // Step 1: Find the last checkpoint, and figure out the number of virtual registers as we go.
142 unsigned startIndex
= index
- 1;
143 while (at(startIndex
).kind() != Reset
)
146 // Step 2: Create a mock-up of the DFG's state and execute the events.
147 Operands
<ValueSource
> operandSources(codeBlock
->numParameters(), numVariables
);
148 for (unsigned i
= operandSources
.size(); i
--;)
149 operandSources
[i
] = ValueSource(SourceIsDead
);
150 HashMap
<MinifiedID
, MinifiedGenerationInfo
> generationInfos
;
151 for (unsigned i
= startIndex
; i
< index
; ++i
) {
152 const VariableEvent
& event
= at(i
);
153 switch (event
.kind()) {
160 MinifiedGenerationInfo info
;
162 generationInfos
.add(event
.id(), info
);
168 HashMap
<MinifiedID
, MinifiedGenerationInfo
>::iterator iter
= generationInfos
.find(event
.id());
169 ASSERT(iter
!= generationInfos
.end());
170 iter
->value
.update(event
);
174 if (operandSources
.hasOperand(event
.bytecodeRegister()))
175 operandSources
.setOperand(event
.bytecodeRegister(), ValueSource(event
.id()));
178 if (operandSources
.hasOperand(event
.bytecodeRegister()))
179 operandSources
.setOperand(event
.bytecodeRegister(), ValueSource::forDataFormat(event
.machineRegister(), event
.dataFormat()));
182 RELEASE_ASSERT_NOT_REACHED();
187 // Step 3: Compute value recoveries!
188 valueRecoveries
= Operands
<ValueRecovery
>(codeBlock
->numParameters(), numVariables
);
189 for (unsigned i
= 0; i
< operandSources
.size(); ++i
) {
190 ValueSource
& source
= operandSources
[i
];
191 if (source
.isTriviallyRecoverable()) {
192 valueRecoveries
[i
] = source
.valueRecovery();
196 ASSERT(source
.kind() == HaveNode
);
197 MinifiedNode
* node
= graph
.at(source
.id());
198 MinifiedGenerationInfo info
= generationInfos
.get(source
.id());
200 valueRecoveries
[i
] = ValueRecovery::constant(jsUndefined());
204 if (tryToSetConstantRecovery(valueRecoveries
[i
], node
))
207 ASSERT(info
.format
!= DataFormatNone
);
210 if (info
.format
== DataFormatDouble
) {
211 valueRecoveries
[i
] = ValueRecovery::inFPR(info
.u
.fpr
);
214 #if USE(JSVALUE32_64)
215 if (info
.format
& DataFormatJS
) {
216 valueRecoveries
[i
] = ValueRecovery::inPair(info
.u
.pair
.tagGPR
, info
.u
.pair
.payloadGPR
);
220 valueRecoveries
[i
] = ValueRecovery::inGPR(info
.u
.gpr
, info
.format
);
225 ValueRecovery::displacedInJSStack(static_cast<VirtualRegister
>(info
.u
.virtualReg
), info
.format
);
229 } } // namespace JSC::DFG
231 #endif // ENABLE(DFG_JIT)