2 * Copyright (C) 2013-2015 Apple Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
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.
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.
27 #include "DFGOSRAvailabilityAnalysisPhase.h"
31 #include "DFGBasicBlockInlines.h"
33 #include "DFGInsertionSet.h"
35 #include "DFGPromoteHeapAccess.h"
36 #include "JSCInlines.h"
38 namespace JSC
{ namespace DFG
{
40 class OSRAvailabilityAnalysisPhase
: public Phase
{
42 OSRAvailabilityAnalysisPhase(Graph
& graph
)
43 : Phase(graph
, "OSR availability analysis")
49 ASSERT(m_graph
.m_form
== SSA
);
51 for (BlockIndex blockIndex
= m_graph
.numBlocks(); blockIndex
--;) {
52 BasicBlock
* block
= m_graph
.block(blockIndex
);
55 block
->ssa
->availabilityAtHead
.clear();
56 block
->ssa
->availabilityAtTail
.clear();
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
);
68 // This could be made more efficient by processing blocks in reverse postorder.
70 LocalOSRAvailabilityCalculator calculator
;
75 for (BlockIndex blockIndex
= 0; blockIndex
< m_graph
.numBlocks(); ++blockIndex
) {
76 BasicBlock
* block
= m_graph
.block(blockIndex
);
80 calculator
.beginBlock(block
);
82 for (unsigned nodeIndex
= 0; nodeIndex
< block
->size(); ++nodeIndex
)
83 calculator
.executeNode(block
->at(nodeIndex
));
85 if (calculator
.m_availability
== block
->ssa
->availabilityAtTail
)
88 block
->ssa
->availabilityAtTail
= calculator
.m_availability
;
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
);
104 bool performOSRAvailabilityAnalysis(Graph
& graph
)
106 SamplingRegion
samplingRegion("DFG OSR Availability Analysis Phase");
107 return runPhase
<OSRAvailabilityAnalysisPhase
>(graph
);
110 LocalOSRAvailabilityCalculator::LocalOSRAvailabilityCalculator()
114 LocalOSRAvailabilityCalculator::~LocalOSRAvailabilityCalculator()
118 void LocalOSRAvailabilityCalculator::beginBlock(BasicBlock
* block
)
120 m_availability
= block
->ssa
->availabilityAtHead
;
123 void LocalOSRAvailabilityCalculator::endBlock(BasicBlock
* block
)
125 m_availability
= block
->ssa
->availabilityAtTail
;
128 void LocalOSRAvailabilityCalculator::executeNode(Node
* node
)
130 switch (node
->op()) {
132 StackAccessData
* data
= node
->stackAccessData();
133 m_availability
.m_locals
.operand(data
->local
).setFlush(data
->flushedAt());
138 m_availability
.m_locals
.operand(node
->unlinkedLocal()).setFlush(FlushedAt(ConflictingFlush
));
143 StackAccessData
* data
= node
->stackAccessData();
144 m_availability
.m_locals
.operand(data
->local
) = Availability(node
, data
->flushedAt());
149 m_availability
.m_locals
.operand(node
->unlinkedLocal()).setNode(node
->child1().node());
154 m_availability
.m_locals
.operand(node
->unlinkedLocal()).setNodeUnavailable();
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
)));
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.
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
);
184 m_availability
.m_heap
.set(PromotedHeapLocation(ArgumentCountPLoc
, node
), argumentCount
);
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
);
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
));
197 m_availability
.m_heap
.set(PromotedHeapLocation(ArgumentPLoc
, node
, i
), argument
);
203 m_availability
.m_heap
.set(
204 PromotedHeapLocation(node
->child1().node(), node
->promotedLocationDescriptor()),
205 Availability(node
->child2().node()));
214 } } // namespace JSC::DFG
216 #endif // ENABLE(DFG_JIT)