2 * Copyright (C) 2012, 2013 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
51 VariableRepresentation u
;
54 MinifiedGenerationInfo()
55 : format(DataFormatNone
)
59 void update(const VariableEvent
& event
)
61 switch (event
.kind()) {
71 format
= DataFormatNone
;
77 u
= event
.variableRepresentation();
78 format
= event
.dataFormat();
84 bool VariableEventStream::tryToSetConstantRecovery(ValueRecovery
& recovery
, CodeBlock
* codeBlock
, MinifiedNode
* node
) const
89 if (node
->hasConstantNumber()) {
90 recovery
= ValueRecovery::constant(
91 codeBlock
->constantRegister(
92 FirstConstantRegisterIndex
+ node
->constantNumber()).get());
96 if (node
->hasWeakConstant()) {
97 recovery
= ValueRecovery::constant(node
->weakConstant());
101 if (node
->op() == PhantomArguments
) {
102 recovery
= ValueRecovery::argumentsThatWereNotCreated();
109 void VariableEventStream::reconstruct(
110 CodeBlock
* codeBlock
, CodeOrigin codeOrigin
, MinifiedGraph
& graph
,
111 unsigned index
, Operands
<ValueRecovery
>& valueRecoveries
) const
113 ASSERT(codeBlock
->jitType() == JITCode::DFGJIT
);
114 CodeBlock
* baselineCodeBlock
= codeBlock
->baselineVersion();
116 unsigned numVariables
;
117 if (codeOrigin
.inlineCallFrame
)
118 numVariables
= baselineCodeBlockForInlineCallFrame(codeOrigin
.inlineCallFrame
)->m_numCalleeRegisters
+ VirtualRegister(codeOrigin
.inlineCallFrame
->stackOffset
).toLocal() + 1;
120 numVariables
= baselineCodeBlock
->m_numCalleeRegisters
;
122 // Crazy special case: if we're at index == 0 then this must be an argument check
123 // failure, in which case all variables are already set up. The recoveries should
126 valueRecoveries
= Operands
<ValueRecovery
>(codeBlock
->numParameters(), numVariables
);
127 for (size_t i
= 0; i
< valueRecoveries
.size(); ++i
) {
128 valueRecoveries
[i
] = ValueRecovery::displacedInJSStack(
129 VirtualRegister(valueRecoveries
.operandForIndex(i
)), DataFormatJS
);
134 // Step 1: Find the last checkpoint, and figure out the number of virtual registers as we go.
135 unsigned startIndex
= index
- 1;
136 while (at(startIndex
).kind() != Reset
)
139 // Step 2: Create a mock-up of the DFG's state and execute the events.
140 Operands
<ValueSource
> operandSources(codeBlock
->numParameters(), numVariables
);
141 for (unsigned i
= operandSources
.size(); i
--;)
142 operandSources
[i
] = ValueSource(SourceIsDead
);
143 HashMap
<MinifiedID
, MinifiedGenerationInfo
> generationInfos
;
144 for (unsigned i
= startIndex
; i
< index
; ++i
) {
145 const VariableEvent
& event
= at(i
);
146 switch (event
.kind()) {
152 MinifiedGenerationInfo info
;
154 generationInfos
.add(event
.id(), info
);
160 HashMap
<MinifiedID
, MinifiedGenerationInfo
>::iterator iter
= generationInfos
.find(event
.id());
161 ASSERT(iter
!= generationInfos
.end());
162 iter
->value
.update(event
);
166 if (operandSources
.hasOperand(event
.bytecodeRegister()))
167 operandSources
.setOperand(event
.bytecodeRegister(), ValueSource(event
.id()));
170 if (operandSources
.hasOperand(event
.bytecodeRegister()))
171 operandSources
.setOperand(event
.bytecodeRegister(), ValueSource::forDataFormat(event
.machineRegister(), event
.dataFormat()));
174 RELEASE_ASSERT_NOT_REACHED();
179 // Step 3: Compute value recoveries!
180 valueRecoveries
= Operands
<ValueRecovery
>(codeBlock
->numParameters(), numVariables
);
181 for (unsigned i
= 0; i
< operandSources
.size(); ++i
) {
182 ValueSource
& source
= operandSources
[i
];
183 if (source
.isTriviallyRecoverable()) {
184 valueRecoveries
[i
] = source
.valueRecovery();
188 ASSERT(source
.kind() == HaveNode
);
189 MinifiedNode
* node
= graph
.at(source
.id());
190 if (tryToSetConstantRecovery(valueRecoveries
[i
], codeBlock
, node
))
193 MinifiedGenerationInfo info
= generationInfos
.get(source
.id());
194 if (info
.format
== DataFormatNone
) {
195 valueRecoveries
[i
] = ValueRecovery::constant(jsUndefined());
199 ASSERT(info
.format
!= DataFormatNone
);
202 if (info
.format
== DataFormatDouble
) {
203 valueRecoveries
[i
] = ValueRecovery::inFPR(info
.u
.fpr
);
206 #if USE(JSVALUE32_64)
207 if (info
.format
& DataFormatJS
) {
208 valueRecoveries
[i
] = ValueRecovery::inPair(info
.u
.pair
.tagGPR
, info
.u
.pair
.payloadGPR
);
212 valueRecoveries
[i
] = ValueRecovery::inGPR(info
.u
.gpr
, info
.format
);
217 ValueRecovery::displacedInJSStack(static_cast<VirtualRegister
>(info
.u
.virtualReg
), info
.format
);
221 } } // namespace JSC::DFG
223 #endif // ENABLE(DFG_JIT)