The DFG should be able to tier-up and OSR enter into the FTL
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGOSREntrypointCreationPhase.cpp
1 /*
2  * Copyright (C) 2013 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 "DFGOSREntrypointCreationPhase.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGBasicBlockInlines.h"
32 #include "DFGBlockInsertionSet.h"
33 #include "DFGGraph.h"
34 #include "DFGLoopPreHeaderCreationPhase.h"
35 #include "DFGPhase.h"
36 #include "Operations.h"
37
38 namespace JSC { namespace DFG {
39
40 class OSREntrypointCreationPhase : public Phase {
41 public:
42     OSREntrypointCreationPhase(Graph& graph)
43         : Phase(graph, "OSR entrypoint creation")
44     {
45     }
46     
47     bool run()
48     {
49         RELEASE_ASSERT(m_graph.m_plan.mode == FTLForOSREntryMode);
50         RELEASE_ASSERT(m_graph.m_form == ThreadedCPS);
51         
52         unsigned bytecodeIndex = m_graph.m_plan.osrEntryBytecodeIndex;
53         RELEASE_ASSERT(bytecodeIndex);
54         RELEASE_ASSERT(bytecodeIndex != UINT_MAX);
55         
56         // Needed by createPreHeader().
57         m_graph.m_dominators.computeIfNecessary(m_graph);
58         
59         CodeBlock* baseline = m_graph.m_profiledBlock;
60         
61         BasicBlock* target = 0;
62         for (unsigned blockIndex = m_graph.numBlocks(); blockIndex--;) {
63             BasicBlock* block = m_graph.block(blockIndex);
64             if (!block)
65                 continue;
66             Node* firstNode = block->at(0);
67             if (firstNode->op() == LoopHint
68                 && firstNode->codeOrigin == CodeOrigin(bytecodeIndex)) {
69                 target = block;
70                 break;
71             }
72         }
73
74         if (!target) {
75             // This is a terrible outcome. It shouldn't often happen but it might
76             // happen and so we should defend against it. If it happens, then this
77             // compilation is a failure.
78             return false;
79         }
80         
81         BlockInsertionSet insertionSet(m_graph);
82         
83         BasicBlock* newRoot = insertionSet.insert(0);
84         CodeOrigin codeOrigin = target->at(0)->codeOrigin;
85         
86         for (int argument = 0; argument < baseline->numParameters(); ++argument) {
87             Node* oldNode = target->variablesAtHead.argument(argument);
88             if (!oldNode) {
89                 // Just for sanity, always have a SetArgument even if it's not needed.
90                 oldNode = m_graph.m_arguments[argument];
91             }
92             Node* node = newRoot->appendNode(
93                 m_graph, SpecNone, SetArgument, codeOrigin,
94                 OpInfo(oldNode->variableAccessData()));
95             m_graph.m_arguments[argument] = node;
96         }
97         for (int local = 0; local < baseline->m_numCalleeRegisters; ++local) {
98             Node* previousHead = target->variablesAtHead.local(local);
99             if (!previousHead)
100                 continue;
101             VariableAccessData* variable = previousHead->variableAccessData();
102             Node* node = newRoot->appendNode(
103                 m_graph, variable->prediction(), ExtractOSREntryLocal, codeOrigin,
104                 OpInfo(variable->local()));
105             newRoot->appendNode(
106                 m_graph, SpecNone, SetLocal, codeOrigin, OpInfo(variable), Edge(node));
107         }
108         
109         newRoot->appendNode(
110             m_graph, SpecNone, Jump, codeOrigin,
111             OpInfo(createPreHeader(m_graph, insertionSet, target)));
112         
113         insertionSet.execute();
114         m_graph.resetReachability();
115         m_graph.killUnreachableBlocks();
116         return true;
117     }
118 };
119
120 bool performOSREntrypointCreation(Graph& graph)
121 {
122     SamplingRegion samplingRegion("DFG OSR Entrypoint Creation");
123     return runPhase<OSREntrypointCreationPhase>(graph);
124 }
125
126 } } // namespace JSC::DFG
127
128 #endif // ENABLE(DFG_JIT)
129
130