2 * Copyright (C) 2013, 2014 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 "DFGOSREntrypointCreationPhase.h"
31 #include "DFGBasicBlockInlines.h"
32 #include "DFGBlockInsertionSet.h"
34 #include "DFGLoopPreHeaderCreationPhase.h"
36 #include "JSCInlines.h"
38 namespace JSC
{ namespace DFG
{
40 class OSREntrypointCreationPhase
: public Phase
{
42 OSREntrypointCreationPhase(Graph
& graph
)
43 : Phase(graph
, "OSR entrypoint creation")
49 RELEASE_ASSERT(m_graph
.m_plan
.mode
== FTLForOSREntryMode
);
50 RELEASE_ASSERT(m_graph
.m_form
== ThreadedCPS
);
52 unsigned bytecodeIndex
= m_graph
.m_plan
.osrEntryBytecodeIndex
;
53 RELEASE_ASSERT(bytecodeIndex
);
54 RELEASE_ASSERT(bytecodeIndex
!= UINT_MAX
);
56 // Needed by createPreHeader().
57 m_graph
.m_dominators
.computeIfNecessary(m_graph
);
59 CodeBlock
* baseline
= m_graph
.m_profiledBlock
;
61 BasicBlock
* target
= 0;
62 for (unsigned blockIndex
= m_graph
.numBlocks(); blockIndex
--;) {
63 BasicBlock
* block
= m_graph
.block(blockIndex
);
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
)) {
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.
84 BlockInsertionSet
insertionSet(m_graph
);
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
;
94 Vector
<Node
*> locals(baseline
->m_numCalleeRegisters
);
95 for (int local
= 0; local
< baseline
->m_numCalleeRegisters
; ++local
) {
96 Node
* previousHead
= target
->variablesAtHead
.local(local
);
99 VariableAccessData
* variable
= previousHead
->variableAccessData();
100 locals
[local
] = newRoot
->appendNode(
101 m_graph
, variable
->prediction(), ExtractOSREntryLocal
, origin
,
102 OpInfo(variable
->local().offset()));
105 m_graph
, SpecNone
, MovHint
, origin
, OpInfo(variable
->local().offset()),
106 Edge(locals
[local
]));
109 for (int argument
= 0; argument
< baseline
->numParameters(); ++argument
) {
110 Node
* oldNode
= target
->variablesAtHead
.argument(argument
);
112 // Just for sanity, always have a SetArgument even if it's not needed.
113 oldNode
= m_graph
.m_arguments
[argument
];
115 Node
* node
= newRoot
->appendNode(
116 m_graph
, SpecNone
, SetArgument
, origin
,
117 OpInfo(oldNode
->variableAccessData()));
118 m_graph
.m_arguments
[argument
] = node
;
121 for (int local
= 0; local
< baseline
->m_numCalleeRegisters
; ++local
) {
122 Node
* previousHead
= target
->variablesAtHead
.local(local
);
125 VariableAccessData
* variable
= previousHead
->variableAccessData();
126 Node
* node
= locals
[local
];
128 m_graph
, SpecNone
, SetLocal
, origin
, OpInfo(variable
), Edge(node
));
132 m_graph
, SpecNone
, Jump
, origin
,
133 OpInfo(createPreHeader(m_graph
, insertionSet
, target
)));
135 insertionSet
.execute();
136 m_graph
.resetReachability();
137 m_graph
.killUnreachableBlocks();
142 bool performOSREntrypointCreation(Graph
& graph
)
144 SamplingRegion
samplingRegion("DFG OSR Entrypoint Creation");
145 return runPhase
<OSREntrypointCreationPhase
>(graph
);
148 } } // namespace JSC::DFG
150 #endif // ENABLE(DFG_JIT)