Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(65)

Side by Side Diff: src/hydrogen-flow-engine.h

Issue 25254002: Implement first version of HFlowEngine, a framework for performing global flow-sensitive analyses. (Closed) Base URL: https://v8.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix compile error in making NoEffects zone-allocated. Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | tools/gyp/v8.gyp » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2013 the V8 project authors. All rights reserved.
2 // Redistribution and use in source and binary forms, with or without
3 // modification, are permitted provided that the following conditions are
4 // met:
5 //
6 // * Redistributions of source code must retain the above copyright
7 // notice, this list of conditions and the following disclaimer.
8 // * Redistributions in binary form must reproduce the above
9 // copyright notice, this list of conditions and the following
10 // disclaimer in the documentation and/or other materials provided
11 // with the distribution.
12 // * Neither the name of Google Inc. nor the names of its
13 // contributors may be used to endorse or promote products derived
14 // from this software without specific prior written permission.
15 //
16 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19 // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20 // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27
28 #ifndef V8_HYDROGEN_FLOW_ENGINE_H_
29 #define V8_HYDROGEN_FLOW_ENGINE_H_
30
31 #include "hydrogen.h"
32 #include "hydrogen-instructions.h"
33 #include "zone.h"
34
35 namespace v8 {
36 namespace internal {
37
38 // An example implementation of effects that doesn't collect anything.
39 class NoEffects : public ZoneObject {
40 public:
41 explicit NoEffects(Zone* zone) { }
42
43 inline bool Disabled() {
44 return true; // Nothing to do.
45 }
46 template <class State>
47 inline void Apply(State* state) {
48 // do nothing.
Michael Starzinger 2013/10/10 13:00:44 If Disabled() returns true above, none of these me
49 }
50 inline void Process(HValue* value, Zone* zone) {
Michael Starzinger 2013/10/10 13:00:44 I think the value here should be an HInstruction a
51 // do nothing.
Michael Starzinger 2013/10/10 13:00:44 Likewise.
52 }
53 inline void Union(NoEffects* other, Zone* zone) {
54 // do nothing.
Michael Starzinger 2013/10/10 13:00:44 Likewise.
55 }
56 };
57
58
59 // An example implementation of state that doesn't track anything.
60 class NoState {
61 public:
62 inline NoState* Copy(HBasicBlock* succ, Zone* zone) {
63 return this;
64 }
65 inline NoState* Process(HValue* value, Zone* zone) {
Michael Starzinger 2013/10/10 13:00:44 I think the value here should be an HInstruction a
66 return this;
67 }
68 inline NoState* Merge(HBasicBlock* succ, NoState* other, Zone* zone) {
69 return this;
70 }
71 };
72
73
74 // This class implements an engine that can drive flow-sensitive analyses
75 // over a graph of basic blocks, either one block at a time (local analysis)
76 // or over the entire graph (global analysis). The flow engine is parameterized
77 // by the type of the state and the effects collected while walking over the
78 // graph.
79 //
80 // The "State" collects which facts are known while passing over instructions
81 // in control flow order, and the "Effects" collect summary information about
82 // which facts could be invalidated on other control flow paths. The effects
83 // are necessary to correctly handle loops in the control flow graph without
84 // doing a fixed-point iteration. Thus the flow engine is guaranteed to visit
85 // each block at most twice; once for effects and once for state.
86 //
87 // The flow engine requires the State and Effects classes to implement methods
88 // like the example NoState and NoEffects above. It's not necessary to provide
89 // an effects implementation for local analysis.
90 template <class State, class Effects>
91 class HFlowEngine {
92 public:
93 HFlowEngine(HGraph* graph, Zone* zone)
94 : graph_(graph),
95 zone_(zone),
96 #if DEBUG
97 pred_counts_(graph->blocks()->length(), zone),
98 #endif
99 block_states_(graph->blocks()->length(), zone),
100 loop_effects_(graph->blocks()->length(), zone) {
101 loop_effects_.AddBlock(NULL, graph_->blocks()->length(), zone);
102 }
103
104 // Local analysis. Iterates over the instructions in the given block.
105 State* AnalyzeOneBlock(HBasicBlock* block, State* state) {
106 // Go through all instructions of the current block, updating the state.
107 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
108 State* new_state = state->Process(it.Current(), zone_);
109 if (new_state != state) SetStateAt(block, new_state);
Michael Starzinger 2013/10/10 13:00:44 Should we really update the state for each block h
110 }
111 return StateAt(block);
112 }
113
114 // Global analysis. Iterates over all blocks that are dominated by the given
115 // block, starting with the initial state. Computes effects for nested loops.
116 void AnalyzeDominatedBlocks(HBasicBlock* root, State* initial) {
117 InitializeStates();
118 SetStateAt(root, initial);
119
120 // Iterate all dominated blocks starting from the given start block.
121 for (int i = root->block_id(); i < graph_->blocks()->length(); i++) {
122 HBasicBlock* block = graph_->blocks()->at(i);
123
124 // Skip blocks not dominated by the root node.
125 if (SkipNonDominatedBlock(root, block)) continue;
126 State* state = StateAt(block);
127
128 if (block->IsLoopHeader()) {
129 // Apply loop effects before analyzing loop body.
130 ComputeLoopEffects(block)->Apply(state);
131 } else {
132 // Must have visited all predecessors before this block.
133 CheckPredecessorCount(block);
134 }
135
136 // Go through all instructions of the current block, updating the state.
137 for (HInstructionIterator it(block); !it.Done(); it.Advance()) {
138 State* new_state = state->Process(it.Current(), zone_);
139 if (new_state != state) SetStateAt(block, new_state);
Michael Starzinger 2013/10/10 13:00:44 See comment above.
140 }
141
142 // Propagate the block state forward to all successor blocks.
143 for (int i = 0; i < block->end()->SuccessorCount(); i++) {
144 HBasicBlock* succ = block->end()->SuccessorAt(i);
145 IncrementPredecessorCount(succ);
146 if (StateAt(succ) == NULL) {
147 // This is the first state to reach the successor.
148 SetStateAt(succ, state->Copy(succ, zone_));
149 } else {
150 // Merge the current state with the state already at the successor.
151 SetStateAt(succ, state->Merge(succ, StateAt(succ), zone_));
152 }
153 }
154 }
155 }
156
157 private:
158 // Computes and caches the loop effects for the loop which has the given
159 // block as its loop header.
160 Effects* ComputeLoopEffects(HBasicBlock* block) {
161 ASSERT(block->IsLoopHeader());
162 Effects* effects = loop_effects_[block->block_id()];
163 if (effects != NULL) return effects; // Already analyzed this loop.
164
165 effects = new(zone_) Effects(zone_);
166 loop_effects_[block->block_id()] = effects;
167 if (effects->Disabled()) return effects; // No effects for this analysis.
168
169 HLoopInformation* loop = block->loop_information();
170 int end = loop->GetLastBackEdge()->block_id();
171 // Process the blocks between the header and the end.
172 for (int i = block->block_id(); i <= end; i++) {
173 HBasicBlock* member = graph_->blocks()->at(i);
174 if (i != block->block_id() && member->IsLoopHeader()) {
175 // Recursively compute and cache the effects of the nested loop.
176 ASSERT(member->loop_information()->parent_loop() == loop);
177 Effects* nested = ComputeLoopEffects(member);
178 effects->Union(nested, zone_);
179 // Skip the nested loop's blocks.
180 i = member->loop_information()->GetLastBackEdge()->block_id();
181 } else {
182 // Process all the effects of the block.
183 ASSERT(member->current_loop() == loop);
184 for (HInstructionIterator it(member); !it.Done(); it.Advance()) {
185 effects->Process(it.Current(), zone_);
186 }
187 }
188 }
189 return effects;
190 }
191
192 inline bool SkipNonDominatedBlock(HBasicBlock* root, HBasicBlock* other) {
193 if (root->block_id() == 0) return false; // Visit the whole graph.
194 if (root == other) return false; // Always visit the root.
195 return !root->Dominates(other); // Only visit dominated blocks.
196 }
197
198 inline State* StateAt(HBasicBlock* block) {
199 return block_states_.at(block->block_id());
200 }
201
202 inline void SetStateAt(HBasicBlock* block, State* state) {
203 block_states_.Set(block->block_id(), state);
204 }
205
206 inline void InitializeStates() {
207 #if DEBUG
208 pred_counts_.Rewind(0);
209 pred_counts_.AddBlock(0, graph_->blocks()->length(), zone_);
210 #endif
211 block_states_.Rewind(0);
212 block_states_.AddBlock(NULL, graph_->blocks()->length(), zone_);
213 }
214
215 inline void CheckPredecessorCount(HBasicBlock* block) {
216 ASSERT(block->predecessors()->length() == pred_counts_[block->block_id()]);
217 }
218
219 inline void IncrementPredecessorCount(HBasicBlock* block) {
220 #if DEBUG
221 pred_counts_[block->block_id()]++;
222 #endif
223 }
224
225 HGraph* graph_; // The hydrogen graph.
226 Zone* zone_; // Temporary zone.
227 #if DEBUG
228 ZoneList<int> pred_counts_; // Finished predecessors (by block id).
229 #endif
230 ZoneList<State*> block_states_; // Block states (by block id).
231 ZoneList<Effects*> loop_effects_; // Loop effects (by block id).
232 };
233
234
235 } } // namespace v8::internal
236
237 #endif // V8_HYDROGEN_FLOW_ENGINE_H_
OLDNEW
« no previous file with comments | « no previous file | tools/gyp/v8.gyp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698