DFG SSA stack accesses shouldn't speak of VariableAccessDatas
[WebKit-https.git] / Source / JavaScriptCore / dfg / DFGOSRAvailabilityAnalysisPhase.cpp
1 /*
2  * Copyright (C) 2013-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 "DFGOSRAvailabilityAnalysisPhase.h"
28
29 #if ENABLE(DFG_JIT)
30
31 #include "DFGBasicBlockInlines.h"
32 #include "DFGGraph.h"
33 #include "DFGInsertionSet.h"
34 #include "DFGPhase.h"
35 #include "DFGPromoteHeapAccess.h"
36 #include "JSCInlines.h"
37
38 namespace JSC { namespace DFG {
39
40 class OSRAvailabilityAnalysisPhase : public Phase {
41 public:
42     OSRAvailabilityAnalysisPhase(Graph& graph)
43         : Phase(graph, "OSR availability analysis")
44     {
45     }
46     
47     bool run()
48     {
49         ASSERT(m_graph.m_form == SSA);
50         
51         for (BlockIndex blockIndex = m_graph.numBlocks(); blockIndex--;) {
52             BasicBlock* block = m_graph.block(blockIndex);
53             if (!block)
54                 continue;
55             block->ssa->availabilityAtHead.clear();
56             block->ssa->availabilityAtTail.clear();
57         }
58         
59         BasicBlock* root = m_graph.block(0);
60         root->ssa->availabilityAtHead.m_locals.fill(Availability::unavailable());
61         for (unsigned argument = m_graph.m_argumentFormats.size(); argument--;) {
62             FlushedAt flushedAt = FlushedAt(
63                 m_graph.m_argumentFormats[argument],
64                 virtualRegisterForArgument(argument));
65             root->ssa->availabilityAtHead.m_locals.argument(argument) = Availability(flushedAt);
66         }
67
68         // This could be made more efficient by processing blocks in reverse postorder.
69         
70         LocalOSRAvailabilityCalculator calculator;
71         bool changed;
72         do {
73             changed = false;
74             
75             for (BlockIndex blockIndex = 0; blockIndex < m_graph.numBlocks(); ++blockIndex) {
76                 BasicBlock* block = m_graph.block(blockIndex);
77                 if (!block)
78                     continue;
79                 
80                 calculator.beginBlock(block);
81                 
82                 for (unsigned nodeIndex = 0; nodeIndex < block->size(); ++nodeIndex)
83                     calculator.executeNode(block->at(nodeIndex));
84                 
85                 calculator.m_availability.prune();
86                 
87                 if (calculator.m_availability == block->ssa->availabilityAtTail)
88                     continue;
89                 
90                 block->ssa->availabilityAtTail = calculator.m_availability;
91                 changed = true;
92                 
93                 for (unsigned successorIndex = block->numSuccessors(); successorIndex--;) {
94                     BasicBlock* successor = block->successor(successorIndex);
95                     successor->ssa->availabilityAtHead.merge(calculator.m_availability);
96                 }
97             }
98         } while (changed);
99         
100         return true;
101     }
102 };
103
104 bool performOSRAvailabilityAnalysis(Graph& graph)
105 {
106     SamplingRegion samplingRegion("DFG OSR Availability Analysis Phase");
107     return runPhase<OSRAvailabilityAnalysisPhase>(graph);
108 }
109
110 LocalOSRAvailabilityCalculator::LocalOSRAvailabilityCalculator()
111 {
112 }
113
114 LocalOSRAvailabilityCalculator::~LocalOSRAvailabilityCalculator()
115 {
116 }
117
118 void LocalOSRAvailabilityCalculator::beginBlock(BasicBlock* block)
119 {
120     m_availability = block->ssa->availabilityAtHead;
121 }
122
123 void LocalOSRAvailabilityCalculator::endBlock(BasicBlock* block)
124 {
125     m_availability = block->ssa->availabilityAtTail;
126 }
127
128 void LocalOSRAvailabilityCalculator::executeNode(Node* node)
129 {
130     switch (node->op()) {
131     case PutStack: {
132         StackAccessData* data = node->stackAccessData();
133         m_availability.m_locals.operand(data->local).setFlush(data->flushedAt());
134         break;
135     }
136         
137     case KillStack: {
138         m_availability.m_locals.operand(node->unlinkedLocal()).setFlush(FlushedAt(ConflictingFlush));
139         break;
140     }
141
142     case GetStack: {
143         StackAccessData* data = node->stackAccessData();
144         m_availability.m_locals.operand(data->local) = Availability(node, data->flushedAt());
145         break;
146     }
147
148     case MovHint: {
149         m_availability.m_locals.operand(node->unlinkedLocal()).setNode(node->child1().node());
150         break;
151     }
152
153     case ZombieHint: {
154         m_availability.m_locals.operand(node->unlinkedLocal()).setNodeUnavailable();
155         break;
156     }
157         
158     case LoadVarargs: {
159         LoadVarargsData* data = node->loadVarargsData();
160         m_availability.m_locals.operand(data->count) =
161             Availability(FlushedAt(FlushedInt32, data->machineCount));
162         for (unsigned i = data->limit; i--;) {
163             m_availability.m_locals.operand(VirtualRegister(data->start.offset() + i)) =
164                 Availability(FlushedAt(FlushedJSValue, VirtualRegister(data->machineStart.offset() + i)));
165         }
166         break;
167     }
168         
169     default:
170         break;
171     }
172     
173     promoteHeapAccess(
174         node,
175         [&] (PromotedHeapLocation location, Edge value) {
176             m_availability.m_heap.set(location, Availability(value.node()));
177         },
178         [&] (PromotedHeapLocation) { });
179 }
180
181 } } // namespace JSC::DFG
182
183 #endif // ENABLE(DFG_JIT)
184