]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGVariableEventStream.cpp
JavaScriptCore-7600.1.4.17.5.tar.gz
[apple/javascriptcore.git] / dfg / DFGVariableEventStream.cpp
CommitLineData
93a37866
A
1/*
2 * Copyright (C) 2012, 2013 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 "DFGVariableEventStream.h"
28
29#if ENABLE(DFG_JIT)
30
31#include "CodeBlock.h"
81345200 32#include "DFGJITCode.h"
93a37866 33#include "DFGValueSource.h"
81345200 34#include "JSCInlines.h"
93a37866
A
35#include <wtf/DataLog.h>
36#include <wtf/HashMap.h>
37
38namespace JSC { namespace DFG {
39
40void VariableEventStream::logEvent(const VariableEvent& event)
41{
42 dataLogF("seq#%u:", static_cast<unsigned>(size()));
43 event.dump(WTF::dataFile());
44 dataLogF(" ");
45}
46
47namespace {
48
49struct MinifiedGenerationInfo {
50 bool filled; // true -> in gpr/fpr/pair, false -> spilled
51 VariableRepresentation u;
52 DataFormat format;
53
54 MinifiedGenerationInfo()
55 : format(DataFormatNone)
56 {
57 }
58
59 void update(const VariableEvent& event)
60 {
61 switch (event.kind()) {
62 case BirthToFill:
63 case Fill:
64 filled = true;
65 break;
66 case BirthToSpill:
67 case Spill:
68 filled = false;
69 break;
70 case Death:
71 format = DataFormatNone;
72 return;
73 default:
74 return;
75 }
76
77 u = event.variableRepresentation();
78 format = event.dataFormat();
79 }
80};
81
82} // namespace
83
84bool VariableEventStream::tryToSetConstantRecovery(ValueRecovery& recovery, CodeBlock* codeBlock, MinifiedNode* node) const
85{
86 if (!node)
87 return false;
88
89 if (node->hasConstantNumber()) {
90 recovery = ValueRecovery::constant(
91 codeBlock->constantRegister(
92 FirstConstantRegisterIndex + node->constantNumber()).get());
93 return true;
94 }
95
96 if (node->hasWeakConstant()) {
97 recovery = ValueRecovery::constant(node->weakConstant());
98 return true;
99 }
100
101 if (node->op() == PhantomArguments) {
102 recovery = ValueRecovery::argumentsThatWereNotCreated();
103 return true;
104 }
105
106 return false;
107}
108
109void VariableEventStream::reconstruct(
110 CodeBlock* codeBlock, CodeOrigin codeOrigin, MinifiedGraph& graph,
111 unsigned index, Operands<ValueRecovery>& valueRecoveries) const
112{
81345200 113 ASSERT(codeBlock->jitType() == JITCode::DFGJIT);
93a37866
A
114 CodeBlock* baselineCodeBlock = codeBlock->baselineVersion();
115
116 unsigned numVariables;
117 if (codeOrigin.inlineCallFrame)
81345200 118 numVariables = baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame)->m_numCalleeRegisters + VirtualRegister(codeOrigin.inlineCallFrame->stackOffset).toLocal() + 1;
93a37866
A
119 else
120 numVariables = baselineCodeBlock->m_numCalleeRegisters;
121
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
124 // reflect this.
125 if (!index) {
126 valueRecoveries = Operands<ValueRecovery>(codeBlock->numParameters(), numVariables);
81345200
A
127 for (size_t i = 0; i < valueRecoveries.size(); ++i) {
128 valueRecoveries[i] = ValueRecovery::displacedInJSStack(
129 VirtualRegister(valueRecoveries.operandForIndex(i)), DataFormatJS);
130 }
93a37866
A
131 return;
132 }
133
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)
137 startIndex--;
138
93a37866
A
139 // Step 2: Create a mock-up of the DFG's state and execute the events.
140 Operands<ValueSource> operandSources(codeBlock->numParameters(), numVariables);
81345200
A
141 for (unsigned i = operandSources.size(); i--;)
142 operandSources[i] = ValueSource(SourceIsDead);
93a37866
A
143 HashMap<MinifiedID, MinifiedGenerationInfo> generationInfos;
144 for (unsigned i = startIndex; i < index; ++i) {
145 const VariableEvent& event = at(i);
146 switch (event.kind()) {
147 case Reset:
148 // nothing to do.
149 break;
150 case BirthToFill:
151 case BirthToSpill: {
152 MinifiedGenerationInfo info;
153 info.update(event);
154 generationInfos.add(event.id(), info);
155 break;
156 }
157 case Fill:
158 case Spill:
159 case Death: {
160 HashMap<MinifiedID, MinifiedGenerationInfo>::iterator iter = generationInfos.find(event.id());
161 ASSERT(iter != generationInfos.end());
162 iter->value.update(event);
163 break;
164 }
165 case MovHintEvent:
81345200
A
166 if (operandSources.hasOperand(event.bytecodeRegister()))
167 operandSources.setOperand(event.bytecodeRegister(), ValueSource(event.id()));
93a37866
A
168 break;
169 case SetLocalEvent:
81345200
A
170 if (operandSources.hasOperand(event.bytecodeRegister()))
171 operandSources.setOperand(event.bytecodeRegister(), ValueSource::forDataFormat(event.machineRegister(), event.dataFormat()));
93a37866
A
172 break;
173 default:
174 RELEASE_ASSERT_NOT_REACHED();
175 break;
176 }
177 }
178
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();
185 continue;
186 }
187
188 ASSERT(source.kind() == HaveNode);
189 MinifiedNode* node = graph.at(source.id());
190 if (tryToSetConstantRecovery(valueRecoveries[i], codeBlock, node))
191 continue;
192
193 MinifiedGenerationInfo info = generationInfos.get(source.id());
194 if (info.format == DataFormatNone) {
81345200
A
195 valueRecoveries[i] = ValueRecovery::constant(jsUndefined());
196 continue;
93a37866
A
197 }
198
199 ASSERT(info.format != DataFormatNone);
200
201 if (info.filled) {
202 if (info.format == DataFormatDouble) {
203 valueRecoveries[i] = ValueRecovery::inFPR(info.u.fpr);
204 continue;
205 }
206#if USE(JSVALUE32_64)
207 if (info.format & DataFormatJS) {
208 valueRecoveries[i] = ValueRecovery::inPair(info.u.pair.tagGPR, info.u.pair.payloadGPR);
209 continue;
210 }
211#endif
212 valueRecoveries[i] = ValueRecovery::inGPR(info.u.gpr, info.format);
213 continue;
214 }
215
216 valueRecoveries[i] =
217 ValueRecovery::displacedInJSStack(static_cast<VirtualRegister>(info.u.virtualReg), info.format);
218 }
93a37866
A
219}
220
221} } // namespace JSC::DFG
222
223#endif // ENABLE(DFG_JIT)
224