]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGVariableEventStream.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGVariableEventStream.cpp
CommitLineData
93a37866 1/*
ed1e77d3 2 * Copyright (C) 2012-2015 Apple Inc. All rights reserved.
93a37866
A
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
ed1e77d3 51 bool alive;
93a37866
A
52 VariableRepresentation u;
53 DataFormat format;
54
55 MinifiedGenerationInfo()
ed1e77d3
A
56 : filled(false)
57 , alive(false)
58 , format(DataFormatNone)
93a37866
A
59 {
60 }
61
62 void update(const VariableEvent& event)
63 {
64 switch (event.kind()) {
65 case BirthToFill:
66 case Fill:
67 filled = true;
ed1e77d3 68 alive = true;
93a37866
A
69 break;
70 case BirthToSpill:
71 case Spill:
72 filled = false;
ed1e77d3 73 alive = true;
93a37866 74 break;
ed1e77d3
A
75 case Birth:
76 alive = true;
77 return;
93a37866
A
78 case Death:
79 format = DataFormatNone;
ed1e77d3 80 alive = false;
93a37866
A
81 return;
82 default:
83 return;
84 }
85
86 u = event.variableRepresentation();
87 format = event.dataFormat();
88 }
89};
90
91} // namespace
92
ed1e77d3 93bool VariableEventStream::tryToSetConstantRecovery(ValueRecovery& recovery, MinifiedNode* node) const
93a37866
A
94{
95 if (!node)
96 return false;
97
ed1e77d3
A
98 if (node->hasConstant()) {
99 recovery = ValueRecovery::constant(node->constant());
93a37866
A
100 return true;
101 }
102
ed1e77d3
A
103 if (node->op() == PhantomDirectArguments) {
104 recovery = ValueRecovery::directArgumentsThatWereNotCreated(node->id());
93a37866
A
105 return true;
106 }
107
ed1e77d3
A
108 if (node->op() == PhantomClonedArguments) {
109 recovery = ValueRecovery::outOfBandArgumentsThatWereNotCreated(node->id());
93a37866
A
110 return true;
111 }
112
113 return false;
114}
115
116void VariableEventStream::reconstruct(
117 CodeBlock* codeBlock, CodeOrigin codeOrigin, MinifiedGraph& graph,
118 unsigned index, Operands<ValueRecovery>& valueRecoveries) const
119{
81345200 120 ASSERT(codeBlock->jitType() == JITCode::DFGJIT);
93a37866
A
121 CodeBlock* baselineCodeBlock = codeBlock->baselineVersion();
122
123 unsigned numVariables;
124 if (codeOrigin.inlineCallFrame)
81345200 125 numVariables = baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame)->m_numCalleeRegisters + VirtualRegister(codeOrigin.inlineCallFrame->stackOffset).toLocal() + 1;
93a37866
A
126 else
127 numVariables = baselineCodeBlock->m_numCalleeRegisters;
128
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
131 // reflect this.
132 if (!index) {
133 valueRecoveries = Operands<ValueRecovery>(codeBlock->numParameters(), numVariables);
81345200
A
134 for (size_t i = 0; i < valueRecoveries.size(); ++i) {
135 valueRecoveries[i] = ValueRecovery::displacedInJSStack(
136 VirtualRegister(valueRecoveries.operandForIndex(i)), DataFormatJS);
137 }
93a37866
A
138 return;
139 }
140
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)
144 startIndex--;
145
93a37866
A
146 // Step 2: Create a mock-up of the DFG's state and execute the events.
147 Operands<ValueSource> operandSources(codeBlock->numParameters(), numVariables);
81345200
A
148 for (unsigned i = operandSources.size(); i--;)
149 operandSources[i] = ValueSource(SourceIsDead);
93a37866
A
150 HashMap<MinifiedID, MinifiedGenerationInfo> generationInfos;
151 for (unsigned i = startIndex; i < index; ++i) {
152 const VariableEvent& event = at(i);
153 switch (event.kind()) {
154 case Reset:
155 // nothing to do.
156 break;
157 case BirthToFill:
ed1e77d3
A
158 case BirthToSpill:
159 case Birth: {
93a37866
A
160 MinifiedGenerationInfo info;
161 info.update(event);
162 generationInfos.add(event.id(), info);
163 break;
164 }
165 case Fill:
166 case Spill:
167 case Death: {
168 HashMap<MinifiedID, MinifiedGenerationInfo>::iterator iter = generationInfos.find(event.id());
169 ASSERT(iter != generationInfos.end());
170 iter->value.update(event);
171 break;
172 }
173 case MovHintEvent:
81345200
A
174 if (operandSources.hasOperand(event.bytecodeRegister()))
175 operandSources.setOperand(event.bytecodeRegister(), ValueSource(event.id()));
93a37866
A
176 break;
177 case SetLocalEvent:
81345200
A
178 if (operandSources.hasOperand(event.bytecodeRegister()))
179 operandSources.setOperand(event.bytecodeRegister(), ValueSource::forDataFormat(event.machineRegister(), event.dataFormat()));
93a37866
A
180 break;
181 default:
182 RELEASE_ASSERT_NOT_REACHED();
183 break;
184 }
185 }
186
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();
193 continue;
194 }
195
196 ASSERT(source.kind() == HaveNode);
197 MinifiedNode* node = graph.at(source.id());
93a37866 198 MinifiedGenerationInfo info = generationInfos.get(source.id());
ed1e77d3 199 if (!info.alive) {
81345200
A
200 valueRecoveries[i] = ValueRecovery::constant(jsUndefined());
201 continue;
93a37866 202 }
ed1e77d3
A
203
204 if (tryToSetConstantRecovery(valueRecoveries[i], node))
205 continue;
93a37866
A
206
207 ASSERT(info.format != DataFormatNone);
208
209 if (info.filled) {
210 if (info.format == DataFormatDouble) {
211 valueRecoveries[i] = ValueRecovery::inFPR(info.u.fpr);
212 continue;
213 }
214#if USE(JSVALUE32_64)
215 if (info.format & DataFormatJS) {
216 valueRecoveries[i] = ValueRecovery::inPair(info.u.pair.tagGPR, info.u.pair.payloadGPR);
217 continue;
218 }
219#endif
220 valueRecoveries[i] = ValueRecovery::inGPR(info.u.gpr, info.format);
221 continue;
222 }
223
224 valueRecoveries[i] =
225 ValueRecovery::displacedInJSStack(static_cast<VirtualRegister>(info.u.virtualReg), info.format);
226 }
93a37866
A
227}
228
229} } // namespace JSC::DFG
230
231#endif // ENABLE(DFG_JIT)
232