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 "DFGTierUpCheckInjectionPhase.h"
32 #include "DFGInsertionSet.h"
34 #include "FTLCapabilities.h"
35 #include "JSCInlines.h"
37 namespace JSC
{ namespace DFG
{
39 class TierUpCheckInjectionPhase
: public Phase
{
41 TierUpCheckInjectionPhase(Graph
& graph
)
42 : Phase(graph
, "tier-up check injection")
48 RELEASE_ASSERT(m_graph
.m_plan
.mode
== DFGMode
);
50 if (!Options::useFTLJIT())
53 if (m_graph
.m_profiledBlock
->m_didFailFTLCompilation
)
57 FTL::CapabilityLevel level
= FTL::canCompile(m_graph
);
58 if (level
== FTL::CannotCompile
)
61 if (!Options::enableOSREntryToFTL())
62 level
= FTL::CanCompile
;
64 // First we find all the loops that contain a LoopHint for which we cannot OSR enter.
65 // We use that information to decide if we need CheckTierUpAndOSREnter or CheckTierUpWithNestedTriggerAndOSREnter.
66 NaturalLoops
& naturalLoops
= m_graph
.m_naturalLoops
;
67 naturalLoops
.computeIfNecessary(m_graph
);
69 HashSet
<const NaturalLoop
*> loopsContainingLoopHintWithoutOSREnter
= findLoopsContainingLoopHintWithoutOSREnter(naturalLoops
, level
);
71 InsertionSet
insertionSet(m_graph
);
72 for (BlockIndex blockIndex
= m_graph
.numBlocks(); blockIndex
--;) {
73 BasicBlock
* block
= m_graph
.block(blockIndex
);
77 for (unsigned nodeIndex
= 0; nodeIndex
< block
->size(); ++nodeIndex
) {
78 Node
* node
= block
->at(nodeIndex
);
79 if (node
->op() != LoopHint
)
82 NodeOrigin origin
= node
->origin
;
83 if (canOSREnterAtLoopHint(level
, block
, nodeIndex
)) {
84 const NaturalLoop
* loop
= naturalLoops
.innerMostLoopOf(block
);
85 if (loop
&& loopsContainingLoopHintWithoutOSREnter
.contains(loop
))
86 insertionSet
.insertNode(nodeIndex
+ 1, SpecNone
, CheckTierUpWithNestedTriggerAndOSREnter
, origin
);
88 insertionSet
.insertNode(nodeIndex
+ 1, SpecNone
, CheckTierUpAndOSREnter
, origin
);
90 insertionSet
.insertNode(nodeIndex
+ 1, SpecNone
, CheckTierUpInLoop
, origin
);
94 NodeAndIndex terminal
= block
->findTerminal();
95 if (terminal
.node
->op() == Return
) {
96 insertionSet
.insertNode(
97 terminal
.index
, SpecNone
, CheckTierUpAtReturn
, terminal
.node
->origin
);
100 insertionSet
.execute(block
);
103 m_graph
.m_plan
.willTryToTierUp
= true;
105 #else // ENABLE(FTL_JIT)
106 RELEASE_ASSERT_NOT_REACHED();
108 #endif // ENABLE(FTL_JIT)
113 bool canOSREnterAtLoopHint(FTL::CapabilityLevel level
, const BasicBlock
* block
, unsigned nodeIndex
)
115 Node
* node
= block
->at(nodeIndex
);
116 ASSERT(node
->op() == LoopHint
);
118 NodeOrigin origin
= node
->origin
;
119 if (level
!= FTL::CanCompileAndOSREnter
|| origin
.semantic
.inlineCallFrame
)
122 // We only put OSR checks for the first LoopHint in the block. Note that
123 // more than one LoopHint could happen in cases where we did a lot of CFG
124 // simplification in the bytecode parser, but it should be very rare.
125 for (unsigned subNodeIndex
= nodeIndex
; subNodeIndex
--;) {
126 if (!block
->at(subNodeIndex
)->isSemanticallySkippable())
132 HashSet
<const NaturalLoop
*> findLoopsContainingLoopHintWithoutOSREnter(const NaturalLoops
& naturalLoops
, FTL::CapabilityLevel level
)
134 HashSet
<const NaturalLoop
*> loopsContainingLoopHintWithoutOSREnter
;
135 for (BasicBlock
* block
: m_graph
.blocksInNaturalOrder()) {
136 for (unsigned nodeIndex
= 0; nodeIndex
< block
->size(); ++nodeIndex
) {
137 Node
* node
= block
->at(nodeIndex
);
138 if (node
->op() != LoopHint
)
141 if (!canOSREnterAtLoopHint(level
, block
, nodeIndex
)) {
142 const NaturalLoop
* loop
= naturalLoops
.innerMostLoopOf(block
);
144 loopsContainingLoopHintWithoutOSREnter
.add(loop
);
145 loop
= naturalLoops
.innerMostOuterLoop(*loop
);
150 return loopsContainingLoopHintWithoutOSREnter
;
155 bool performTierUpCheckInjection(Graph
& graph
)
157 SamplingRegion
samplingRegion("DFG Tier-up Check Injection");
158 return runPhase
<TierUpCheckInjectionPhase
>(graph
);
161 } } // namespace JSC::DFG
163 #endif // ENABLE(DFG_JIT)