Move back primary header includes next to config.h
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGVariableEventStream.cpp
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"
32 #include "DFGJITCode.h"
33 #include "DFGValueSource.h"
34 #include "JSCInlines.h"
35 #include <wtf/DataLog.h>
36 #include <wtf/HashMap.h>
37
38 namespace JSC { namespace DFG {
39
40 void VariableEventStream::logEvent(const VariableEvent& event)
41 {
42     dataLogF("seq#%u:", static_cast<unsigned>(size()));
43     event.dump(WTF::dataFile());
44     dataLogF(" ");
45 }
46
47 namespace {
48
49 struct 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
84 bool 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
109 void VariableEventStream::reconstruct(
110     CodeBlock* codeBlock, CodeOrigin codeOrigin, MinifiedGraph& graph,
111     unsigned index, Operands<ValueRecovery>& valueRecoveries) const
112 {
113     ASSERT(codeBlock->jitType() == JITCode::DFGJIT);
114     CodeBlock* baselineCodeBlock = codeBlock->baselineVersion();
115     
116     unsigned numVariables;
117     if (codeOrigin.inlineCallFrame)
118         numVariables = baselineCodeBlockForInlineCallFrame(codeOrigin.inlineCallFrame)->m_numCalleeRegisters + VirtualRegister(codeOrigin.inlineCallFrame->stackOffset).toLocal() + 1;
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);
127         for (size_t i = 0; i < valueRecoveries.size(); ++i) {
128             valueRecoveries[i] = ValueRecovery::displacedInJSStack(
129                 VirtualRegister(valueRecoveries.operandForIndex(i)), DataFormatJS);
130         }
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     
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()) {
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:
166             if (operandSources.hasOperand(event.bytecodeRegister()))
167                 operandSources.setOperand(event.bytecodeRegister(), ValueSource(event.id()));
168             break;
169         case SetLocalEvent:
170             if (operandSources.hasOperand(event.bytecodeRegister()))
171                 operandSources.setOperand(event.bytecodeRegister(), ValueSource::forDataFormat(event.machineRegister(), event.dataFormat()));
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) {
195             valueRecoveries[i] = ValueRecovery::constant(jsUndefined());
196             continue;
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     }
219 }
220
221 } } // namespace JSC::DFG
222
223 #endif // ENABLE(DFG_JIT)
224