b620aa00201edd2f20eeaffb0e70f8fb0b6ec3fa
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGTierUpCheckInjectionPhase.cpp
1 /*
2  * Copyright (C) 2013, 2014 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
28 #if ENABLE(DFG_JIT)
29
30 #include "DFGTierUpCheckInjectionPhase.h"
31
32 #include "DFGGraph.h"
33 #include "DFGInsertionSet.h"
34 #include "DFGPhase.h"
35 #include "FTLCapabilities.h"
36 #include "JSCInlines.h"
37
38 namespace JSC { namespace DFG {
39
40 class TierUpCheckInjectionPhase : public Phase {
41 public:
42     TierUpCheckInjectionPhase(Graph& graph)
43         : Phase(graph, "tier-up check injection")
44     {
45     }
46     
47     bool run()
48     {
49         RELEASE_ASSERT(m_graph.m_plan.mode == DFGMode);
50         
51         if (!Options::useFTLJIT())
52             return false;
53         
54         if (m_graph.m_profiledBlock->m_didFailFTLCompilation)
55             return false;
56         
57 #if ENABLE(FTL_JIT)
58         FTL::CapabilityLevel level = FTL::canCompile(m_graph);
59         if (level == FTL::CannotCompile)
60             return false;
61         
62         if (!Options::enableOSREntryToFTL())
63             level = FTL::CanCompile;
64         
65         InsertionSet insertionSet(m_graph);
66         for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
67             BasicBlock* block = m_graph.block(blockIndex);
68             if (!block)
69                 continue;
70             
71             for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex) {
72                 Node* node = block->at(nodeIndex);
73                 if (node->op() != LoopHint)
74                     continue;
75                 
76                 // We only put OSR checks for the first LoopHint in the block. Note that
77                 // more than one LoopHint could happen in cases where we did a lot of CFG
78                 // simplification in the bytecode parser, but it should be very rare.
79                 
80                 NodeOrigin origin = node->origin;
81                 
82                 if (level != FTL::CanCompileAndOSREnter || origin.semantic.inlineCallFrame) {
83                     insertionSet.insertNode(
84                         nodeIndex + 1, SpecNone, CheckTierUpInLoop, origin);
85                     break;
86                 }
87                 
88                 bool isAtTop = true;
89                 for (unsigned subNodeIndex = nodeIndex; subNodeIndex--;) {
90                     if (!block->at(subNodeIndex)->isSemanticallySkippable()) {
91                         isAtTop = false;
92                         break;
93                     }
94                 }
95                 
96                 if (!isAtTop) {
97                     insertionSet.insertNode(
98                         nodeIndex + 1, SpecNone, CheckTierUpInLoop, origin);
99                     break;
100                 }
101                 
102                 insertionSet.insertNode(
103                     nodeIndex + 1, SpecNone, CheckTierUpAndOSREnter, origin);
104                 break;
105             }
106             
107             if (block->last()->op() == Return) {
108                 insertionSet.insertNode(
109                     block->size() - 1, SpecNone, CheckTierUpAtReturn, block->last()->origin);
110             }
111             
112             insertionSet.execute(block);
113         }
114         
115         m_graph.m_plan.willTryToTierUp = true;
116         return true;
117 #else // ENABLE(FTL_JIT)
118         RELEASE_ASSERT_NOT_REACHED();
119         return false;
120 #endif // ENABLE(FTL_JIT)
121     }
122 };
123
124 bool performTierUpCheckInjection(Graph& graph)
125 {
126     SamplingRegion samplingRegion("DFG Tier-up Check Injection");
127     return runPhase<TierUpCheckInjectionPhase>(graph);
128 }
129
130 } } // namespace JSC::DFG
131
132 #endif // ENABLE(DFG_JIT)
133
134