]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGOSREntrypointCreationPhase.cpp
29cc66a53cfebb29cc0dde51f53ad2e1bb2399fc
[apple/javascriptcore.git] / dfg / DFGOSREntrypointCreationPhase.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 #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 "JSCInlines.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 unsigned nodeIndex = 0;
67 Node* firstNode = block->at(0);
68 while (firstNode->isSemanticallySkippable())
69 firstNode = block->at(++nodeIndex);
70 if (firstNode->op() == LoopHint
71 && firstNode->origin.semantic == CodeOrigin(bytecodeIndex)) {
72 target = block;
73 break;
74 }
75 }
76
77 if (!target) {
78 // This is a terrible outcome. It shouldn't often happen but it might
79 // happen and so we should defend against it. If it happens, then this
80 // compilation is a failure.
81 return false;
82 }
83
84 BlockInsertionSet insertionSet(m_graph);
85
86 // We say that the execution count of the entry block is 1, because we know for sure
87 // that this must be the case. Under our definition of executionCount, "1" means "once
88 // per invocation". We could have said NaN here, since that would ask any clients of
89 // executionCount to use best judgement - but that seems unnecessary since we know for
90 // sure what the executionCount should be in this case.
91 BasicBlock* newRoot = insertionSet.insert(0, 1);
92 NodeOrigin origin = target->at(0)->origin;
93
94 Vector<Node*> locals(baseline->m_numCalleeRegisters);
95 for (int local = 0; local < baseline->m_numCalleeRegisters; ++local) {
96 Node* previousHead = target->variablesAtHead.local(local);
97 if (!previousHead)
98 continue;
99 VariableAccessData* variable = previousHead->variableAccessData();
100 locals[local] = newRoot->appendNode(
101 m_graph, variable->prediction(), ExtractOSREntryLocal, origin,
102 OpInfo(variable->local().offset()));
103
104 newRoot->appendNode(
105 m_graph, SpecNone, MovHint, origin, OpInfo(variable->local().offset()),
106 Edge(locals[local]));
107 }
108
109 for (int argument = 0; argument < baseline->numParameters(); ++argument) {
110 Node* oldNode = target->variablesAtHead.argument(argument);
111 if (!oldNode) {
112 // Just for sanity, always have a SetArgument even if it's not needed.
113 oldNode = m_graph.m_arguments[argument];
114 }
115 Node* node = newRoot->appendNode(
116 m_graph, SpecNone, SetArgument, origin,
117 OpInfo(oldNode->variableAccessData()));
118 m_graph.m_arguments[argument] = node;
119 }
120
121 for (int local = 0; local < baseline->m_numCalleeRegisters; ++local) {
122 Node* previousHead = target->variablesAtHead.local(local);
123 if (!previousHead)
124 continue;
125 VariableAccessData* variable = previousHead->variableAccessData();
126 Node* node = locals[local];
127 newRoot->appendNode(
128 m_graph, SpecNone, SetLocal, origin, OpInfo(variable), Edge(node));
129 }
130
131 newRoot->appendNode(
132 m_graph, SpecNone, Jump, origin,
133 OpInfo(createPreHeader(m_graph, insertionSet, target)));
134
135 insertionSet.execute();
136 m_graph.resetReachability();
137 m_graph.killUnreachableBlocks();
138 return true;
139 }
140 };
141
142 bool performOSREntrypointCreation(Graph& graph)
143 {
144 SamplingRegion samplingRegion("DFG OSR Entrypoint Creation");
145 return runPhase<OSREntrypointCreationPhase>(graph);
146 }
147
148 } } // namespace JSC::DFG
149
150 #endif // ENABLE(DFG_JIT)
151
152