]> git.saurik.com Git - apple/javascriptcore.git/blame - dfg/DFGOSRAvailabilityAnalysisPhase.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGOSRAvailabilityAnalysisPhase.cpp
CommitLineData
81345200 1/*
ed1e77d3 2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
81345200
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 "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"
ed1e77d3 35#include "DFGPromoteHeapAccess.h"
81345200
A
36#include "JSCInlines.h"
37
38namespace JSC { namespace DFG {
39
40class OSRAvailabilityAnalysisPhase : public Phase {
41public:
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;
ed1e77d3
A
55 block->ssa->availabilityAtHead.clear();
56 block->ssa->availabilityAtTail.clear();
81345200
A
57 }
58
59 BasicBlock* root = m_graph.block(0);
ed1e77d3
A
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);
81345200
A
66 }
67
81345200 68 // This could be made more efficient by processing blocks in reverse postorder.
ed1e77d3
A
69
70 LocalOSRAvailabilityCalculator calculator;
81345200
A
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
ed1e77d3 80 calculator.beginBlock(block);
81345200 81
ed1e77d3
A
82 for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex)
83 calculator.executeNode(block->at(nodeIndex));
81345200 84
ed1e77d3 85 if (calculator.m_availability == block->ssa->availabilityAtTail)
81345200
A
86 continue;
87
ed1e77d3 88 block->ssa->availabilityAtTail = calculator.m_availability;
81345200
A
89 changed = true;
90
91 for (unsigned successorIndex = block->numSuccessors(); successorIndex--;) {
92 BasicBlock* successor = block->successor(successorIndex);
ed1e77d3
A
93 successor->ssa->availabilityAtHead.merge(calculator.m_availability);
94 successor->ssa->availabilityAtHead.pruneByLiveness(
95 m_graph, successor->firstOrigin().forExit);
81345200
A
96 }
97 }
98 } while (changed);
99
100 return true;
101 }
102};
103
104bool performOSRAvailabilityAnalysis(Graph& graph)
105{
106 SamplingRegion samplingRegion("DFG OSR Availability Analysis Phase");
107 return runPhase<OSRAvailabilityAnalysisPhase>(graph);
108}
109
ed1e77d3
A
110LocalOSRAvailabilityCalculator::LocalOSRAvailabilityCalculator()
111{
112}
113
114LocalOSRAvailabilityCalculator::~LocalOSRAvailabilityCalculator()
115{
116}
117
118void LocalOSRAvailabilityCalculator::beginBlock(BasicBlock* block)
119{
120 m_availability = block->ssa->availabilityAtHead;
121}
122
123void LocalOSRAvailabilityCalculator::endBlock(BasicBlock* block)
124{
125 m_availability = block->ssa->availabilityAtTail;
126}
127
128void 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
81345200
A
214} } // namespace JSC::DFG
215
216#endif // ENABLE(DFG_JIT)
217