]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGOSRAvailabilityAnalysisPhase.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGOSRAvailabilityAnalysisPhase.cpp
1 /*
2 * Copyright (C) 2013-2015 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 "DFGOSRAvailabilityAnalysisPhase.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGBasicBlockInlines.h"
32 #include "DFGGraph.h"
33 #include "DFGInsertionSet.h"
34 #include "DFGPhase.h"
35 #include "DFGPromoteHeapAccess.h"
36 #include "JSCInlines.h"
37
38 namespace JSC { namespace DFG {
39
40 class OSRAvailabilityAnalysisPhase : public Phase {
41 public:
42 OSRAvailabilityAnalysisPhase(Graph& graph)
43 : Phase(graph, "OSR availability analysis")
44 {
45 }
46
47 bool run()
48 {
49 ASSERT(m_graph.m_form == SSA);
50
51 for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
52 BasicBlock* block = m_graph.block(blockIndex);
53 if (!block)
54 continue;
55 block->ssa->availabilityAtHead.clear();
56 block->ssa->availabilityAtTail.clear();
57 }
58
59 BasicBlock* root = m_graph.block(0);
60 root->ssa->availabilityAtHead.m_locals.fill(Availability::unavailable());
61 for (unsigned argument = m_graph.m_argumentFormats.size(); argument--;) {
62 FlushedAt flushedAt = FlushedAt(
63 m_graph.m_argumentFormats[argument],
64 virtualRegisterForArgument(argument));
65 root->ssa->availabilityAtHead.m_locals.argument(argument) = Availability(flushedAt);
66 }
67
68 // This could be made more efficient by processing blocks in reverse postorder.
69
70 LocalOSRAvailabilityCalculator calculator;
71 bool changed;
72 do {
73 changed = false;
74
75 for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
76 BasicBlock* block = m_graph.block(blockIndex);
77 if (!block)
78 continue;
79
80 calculator.beginBlock(block);
81
82 for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex)
83 calculator.executeNode(block->at(nodeIndex));
84
85 if (calculator.m_availability == block->ssa->availabilityAtTail)
86 continue;
87
88 block->ssa->availabilityAtTail = calculator.m_availability;
89 changed = true;
90
91 for (unsigned successorIndex = block->numSuccessors(); successorIndex--;) {
92 BasicBlock* successor = block->successor(successorIndex);
93 successor->ssa->availabilityAtHead.merge(calculator.m_availability);
94 successor->ssa->availabilityAtHead.pruneByLiveness(
95 m_graph, successor->firstOrigin().forExit);
96 }
97 }
98 } while (changed);
99
100 return true;
101 }
102 };
103
104 bool performOSRAvailabilityAnalysis(Graph& graph)
105 {
106 SamplingRegion samplingRegion("DFG OSR Availability Analysis Phase");
107 return runPhase<OSRAvailabilityAnalysisPhase>(graph);
108 }
109
110 LocalOSRAvailabilityCalculator::LocalOSRAvailabilityCalculator()
111 {
112 }
113
114 LocalOSRAvailabilityCalculator::~LocalOSRAvailabilityCalculator()
115 {
116 }
117
118 void LocalOSRAvailabilityCalculator::beginBlock(BasicBlock* block)
119 {
120 m_availability = block->ssa->availabilityAtHead;
121 }
122
123 void LocalOSRAvailabilityCalculator::endBlock(BasicBlock* block)
124 {
125 m_availability = block->ssa->availabilityAtTail;
126 }
127
128 void LocalOSRAvailabilityCalculator::executeNode(Node* node)
129 {
130 switch (node->op()) {
131 case PutStack: {
132 StackAccessData* data = node->stackAccessData();
133 m_availability.m_locals.operand(data->local).setFlush(data->flushedAt());
134 break;
135 }
136
137 case KillStack: {
138 m_availability.m_locals.operand(node->unlinkedLocal()).setFlush(FlushedAt(ConflictingFlush));
139 break;
140 }
141
142 case GetStack: {
143 StackAccessData* data = node->stackAccessData();
144 m_availability.m_locals.operand(data->local) = Availability(node, data->flushedAt());
145 break;
146 }
147
148 case MovHint: {
149 m_availability.m_locals.operand(node->unlinkedLocal()).setNode(node->child1().node());
150 break;
151 }
152
153 case ZombieHint: {
154 m_availability.m_locals.operand(node->unlinkedLocal()).setNodeUnavailable();
155 break;
156 }
157
158 case LoadVarargs:
159 case ForwardVarargs: {
160 LoadVarargsData* data = node->loadVarargsData();
161 m_availability.m_locals.operand(data->count) =
162 Availability(FlushedAt(FlushedInt32, data->machineCount));
163 for (unsigned i = data->limit; i--;) {
164 m_availability.m_locals.operand(VirtualRegister(data->start.offset() + i)) =
165 Availability(FlushedAt(FlushedJSValue, VirtualRegister(data->machineStart.offset() + i)));
166 }
167 break;
168 }
169
170 case PhantomDirectArguments:
171 case PhantomClonedArguments: {
172 InlineCallFrame* inlineCallFrame = node->origin.semantic.inlineCallFrame;
173 if (!inlineCallFrame) {
174 // We don't need to record anything about how the arguments are to be recovered. It's just a
175 // given that we can read them from the stack.
176 break;
177 }
178
179 if (inlineCallFrame->isVarargs()) {
180 // Record how to read each argument and the argument count.
181 Availability argumentCount =
182 m_availability.m_locals.operand(inlineCallFrame->stackOffset + JSStack::ArgumentCount);
183
184 m_availability.m_heap.set(PromotedHeapLocation(ArgumentCountPLoc, node), argumentCount);
185 }
186
187 if (inlineCallFrame->isClosureCall) {
188 Availability callee = m_availability.m_locals.operand(
189 inlineCallFrame->stackOffset + JSStack::Callee);
190 m_availability.m_heap.set(PromotedHeapLocation(ArgumentsCalleePLoc, node), callee);
191 }
192
193 for (unsigned i = 0; i < inlineCallFrame->arguments.size() - 1; ++i) {
194 Availability argument = m_availability.m_locals.operand(
195 inlineCallFrame->stackOffset + CallFrame::argumentOffset(i));
196
197 m_availability.m_heap.set(PromotedHeapLocation(ArgumentPLoc, node, i), argument);
198 }
199 break;
200 }
201
202 case PutHint: {
203 m_availability.m_heap.set(
204 PromotedHeapLocation(node->child1().node(), node->promotedLocationDescriptor()),
205 Availability(node->child2().node()));
206 break;
207 }
208
209 default:
210 break;
211 }
212 }
213
214 } } // namespace JSC::DFG
215
216 #endif // ENABLE(DFG_JIT)
217