]> git.saurik.com Git - apple/javascriptcore.git/blob - dfg/DFGConstantHoistingPhase.cpp
JavaScriptCore-7601.1.46.3.tar.gz
[apple/javascriptcore.git] / dfg / DFGConstantHoistingPhase.cpp
1 /*
2 * Copyright (C) 2015 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 "DFGConstantHoistingPhase.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGGraph.h"
32 #include "DFGInsertionSet.h"
33 #include "DFGPhase.h"
34 #include "DFGPredictionPropagationPhase.h"
35 #include "DFGVariableAccessDataDump.h"
36 #include "JSCInlines.h"
37
38 namespace JSC { namespace DFG {
39
40 namespace {
41
42 class ConstantHoistingPhase : public Phase {
43 public:
44 ConstantHoistingPhase(Graph& graph)
45 : Phase(graph, "constant hoisting")
46 {
47 }
48
49 bool run()
50 {
51 DFG_ASSERT(m_graph, nullptr, m_graph.m_form == SSA);
52
53 m_graph.clearReplacements();
54
55 HashMap<FrozenValue*, Node*> jsValues;
56 HashMap<FrozenValue*, Node*> doubleValues;
57 HashMap<FrozenValue*, Node*> int52Values;
58
59 auto valuesFor = [&] (NodeType op) -> HashMap<FrozenValue*, Node*>& {
60 // Use a roundabout approach because clang thinks that this closure returning a
61 // reference to a stack-allocated value in outer scope is a bug. It's not.
62 HashMap<FrozenValue*, Node*>* result;
63
64 switch (op) {
65 case JSConstant:
66 result = &jsValues;
67 break;
68 case DoubleConstant:
69 result = &doubleValues;
70 break;
71 case Int52Constant:
72 result = &int52Values;
73 break;
74 default:
75 DFG_CRASH(m_graph, nullptr, "Invalid node type in valuesFor()");
76 result = nullptr;
77 break;
78 }
79
80 return *result;
81 };
82
83 Vector<Node*> toFree;
84
85 for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
86 unsigned sourceIndex = 0;
87 unsigned targetIndex = 0;
88 while (sourceIndex < block->size()) {
89 Node* node = block->at(sourceIndex++);
90 switch (node->op()) {
91 case JSConstant:
92 case DoubleConstant:
93 case Int52Constant: {
94 HashMap<FrozenValue*, Node*>& values = valuesFor(node->op());
95 auto result = values.add(node->constant(), node);
96 if (result.isNewEntry)
97 node->origin = NodeOrigin();
98 else {
99 node->setReplacement(result.iterator->value);
100 toFree.append(node);
101 }
102 break;
103 }
104 default:
105 block->at(targetIndex++) = node;
106 break;
107 }
108 }
109 block->resize(targetIndex);
110 }
111
112 // Insert the constants into the root block.
113 InsertionSet insertionSet(m_graph);
114 auto insertConstants = [&] (const HashMap<FrozenValue*, Node*>& values) {
115 for (auto& entry : values)
116 insertionSet.insert(0, entry.value);
117 };
118 insertConstants(jsValues);
119 insertConstants(doubleValues);
120 insertConstants(int52Values);
121 insertionSet.execute(m_graph.block(0));
122
123 // Perform all of the substitutions. We want all instances of the removed constants to
124 // point at their replacements.
125 for (BasicBlock* block : m_graph.blocksInNaturalOrder()) {
126 for (Node* node : *block)
127 m_graph.performSubstitution(node);
128 }
129
130 // And finally free the constants that we removed.
131 for (Node* node : toFree)
132 m_graph.m_allocator.free(node);
133
134 return true;
135 }
136 };
137
138 } // anonymous namespace
139
140 bool performConstantHoisting(Graph& graph)
141 {
142 SamplingRegion samplingRegion("DFG Constant Hoisting Phase");
143 return runPhase<ConstantHoistingPhase>(graph);
144 }
145
146 } } // namespace JSC::DFG
147
148 #endif // ENABLE(DFG_JIT)
149