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

Side by Side Diff: frog/leg/ssa/bailout.dart

Issue 9873021: Move frog/leg to lib/compiler/implementation. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 9 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 | « frog/leg/source_file.dart ('k') | frog/leg/ssa/builder.dart » ('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 (c) 2012, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file.
4
5 class BailoutInfo {
6 int instructionId;
7 int bailoutId;
8 BailoutInfo(this.instructionId, this.bailoutId);
9 }
10
11 /**
12 * Keeps track of the execution environment for instructions. An
13 * execution environment contains the SSA instructions that are live.
14 */
15 class Environment {
16 final Set<HInstruction> lives;
17 final Set<HBasicBlock> loopMarkers;
18 Environment() : lives = new Set<HInstruction>(),
19 loopMarkers = new Set<HBasicBlock>();
20 Environment.from(Environment other)
21 : lives = new Set<HInstruction>.from(other.lives),
22 loopMarkers = new Set<HBasicBlock>.from(other.loopMarkers);
23
24 Environment.forLoopBody(Environment other)
25 : lives = new Set<HInstruction>(),
26 loopMarkers = new Set<HBasicBlock>.from(other.loopMarkers);
27
28 void remove(HInstruction instruction) {
29 lives.remove(instruction);
30 }
31
32 void add(HInstruction instruction) {
33 if (!instruction.isCodeMotionInvariant()) {
34 lives.add(instruction);
35 } else {
36 for (int i = 0, len = instruction.inputs.length; i < len; i++) {
37 add(instruction.inputs[i]);
38 }
39 }
40 }
41
42 void addLoopMarker(HBasicBlock block) {
43 loopMarkers.add(block);
44 }
45
46 void removeLoopMarker(HBasicBlock block) {
47 loopMarkers.remove(block);
48 }
49
50 void addAll(Environment other) {
51 lives.addAll(other.lives);
52 loopMarkers.addAll(other.loopMarkers);
53 }
54
55 List<HInstruction> buildAndSetLast(HInstruction instruction) {
56 remove(instruction);
57 List<HInstruction> result = new List<HInstruction>.from(lives);
58 result.addLast(instruction);
59 add(instruction);
60 return result;
61 }
62
63 bool isEmpty() => lives.isEmpty();
64 bool contains(HInstruction instruction) => lives.contains(instruction);
65 bool containsLoopMarker(HBasicBlock block) => loopMarkers.contains(block);
66 void clear() => lives.clear();
67 }
68
69 /**
70 * Computes the environment for each SSA instruction: visits the graph
71 * in post-dominator order. Removes an instruction from the environment
72 * and adds its inputs to the environment at the instruction's
73 * definition.
74 *
75 * At the end of the computation, insert type guards in the graph.
76 */
77 class SsaTypeGuardBuilder extends HBaseVisitor implements OptimizationPhase {
78 final Compiler compiler;
79 final WorkItem work;
80 final String name = 'SsaTypeGuardBuilder';
81 Environment environment;
82 SubGraph subGraph;
83
84 final Map<HInstruction, Environment> capturedEnvironments;
85
86 SsaTypeGuardBuilder(Compiler this.compiler, WorkItem this.work)
87 : capturedEnvironments = new Map<HInstruction, Environment>();
88
89
90 void visitGraph(HGraph graph) {
91 subGraph = new SubGraph(graph.entry, graph.exit);
92 environment = new Environment();
93 visitBasicBlock(graph.entry);
94 if (!environment.isEmpty()) {
95 compiler.internalError('Bailout environment computation',
96 node: compiler.currentElement.parseNode(compiler));
97 }
98 insertCapturedEnvironments();
99 }
100
101 void maybeCaptureEnvironment(HInstruction instruction) {
102 if (shouldCaptureEnvironment(instruction)) {
103 capturedEnvironments[instruction] = new Environment.from(environment);
104 }
105 }
106
107 void visitSubGraph(SubGraph newSubGraph) {
108 SubGraph oldSubGraph = subGraph;
109 subGraph = newSubGraph;
110 visitBasicBlock(subGraph.start);
111 subGraph = oldSubGraph;
112 }
113
114 void visitBasicBlock(HBasicBlock block) {
115 if (!subGraph.contains(block)) return;
116 block.last.accept(this);
117
118 HInstruction instruction = block.last.previous;
119 while (instruction != null) {
120 HInstruction previous = instruction.previous;
121 instruction.accept(this);
122 instruction = previous;
123 }
124
125 for (HPhi phi = block.phis.first; phi != null; phi = phi.next) {
126 phi.accept(this);
127 }
128
129 if (block.isLoopHeader()) {
130 // If the block is a loop header, we need to change every uses
131 // of its loop marker to the current set of live instructions.
132 // For example with the following loop (read the example in
133 // reverse):
134 //
135 // while (true) { <-- (4) update the marker with the environment
136 // use(x); <-- (3) environment = {x}
137 // bailout; <-- (2) has the marker when computed
138 // } <-- (1) create a loop marker
139 //
140 // The bailout instruction first captures the marker, but it
141 // will be replaced by the live environment at the loop entry,
142 // in this case {x}.
143 environment.removeLoopMarker(block);
144 capturedEnvironments.forEach((instruction, env) {
145 if (env.containsLoopMarker(block)) {
146 env.removeLoopMarker(block);
147 env.addAll(environment);
148 }
149 });
150 }
151 }
152
153 void visitPhi(HPhi phi) {
154 maybeCaptureEnvironment(phi);
155 environment.remove(phi);
156 // If the block is a loop header, we insert the incoming values of
157 // the phis, and remove the loop values.
158 // If the block is not a loop header, the phi will be handled by
159 // the control flow instruction.
160 if (phi.block.isLoopHeader()) {
161 environment.add(phi.inputs[0]);
162 for (int i = 1, len = phi.inputs.length; i < len; i++) {
163 environment.remove(phi.inputs[i]);
164 }
165 }
166 }
167
168 void visitInstruction(HInstruction instruction) {
169 maybeCaptureEnvironment(instruction);
170 environment.remove(instruction);
171 for (int i = 0, len = instruction.inputs.length; i < len; i++) {
172 environment.add(instruction.inputs[i]);
173 }
174 }
175
176 void visitIf(HIf instruction) {
177 HIfBlockInformation info = instruction.blockInformation;
178 HBasicBlock joinBlock = info.joinBlock;
179
180 if (joinBlock != null) {
181 visitBasicBlock(joinBlock);
182 }
183 Environment thenEnvironment = new Environment.from(environment);
184 Environment elseEnvironment = environment;
185
186 if (joinBlock != null) {
187 for (HPhi phi = joinBlock.phis.first; phi != null; phi = phi.next) {
188 if (joinBlock.predecessors[0] == instruction.block) {
189 // We're dealing with an 'if' without an else branch.
190 thenEnvironment.add(phi.inputs[1]);
191 elseEnvironment.add(phi.inputs[0]);
192 } else {
193 thenEnvironment.add(phi.inputs[0]);
194 elseEnvironment.add(phi.inputs[1]);
195 }
196 }
197 }
198
199 if (instruction.hasElse) {
200 environment = elseEnvironment;
201 visitSubGraph(info.elseGraph);
202 elseEnvironment = environment;
203 }
204
205 environment = thenEnvironment;
206 visitSubGraph(info.thenGraph);
207 environment.addAll(elseEnvironment);
208 }
209
210 void visitGoto(HGoto goto) {
211 HBasicBlock block = goto.block;
212 if (block.successors[0].dominator != block) return;
213 visitBasicBlock(block.successors[0]);
214 }
215
216 void visitBreak(HBreak breakInstruction) {
217 compiler.unimplemented("SsaEnvironmentBuilder.visitBreak");
218 }
219
220 void visitLoopBranch(HLoopBranch branch) {
221 HBasicBlock block = branch.block;
222
223 // Visit the code after the loop.
224 visitBasicBlock(block.successors[1]);
225
226 Environment joinEnvironment = environment;
227
228 // When visiting the loop body, we don't require the live
229 // instructions after the loop body to be in the environment. They
230 // will be either recomputed in the loop header, or inserted
231 // with the loop marker. We still need to transfer existing loop
232 // markers from the current environment, because they must be live
233 // for this loop body.
234 environment = new Environment.forLoopBody(environment);
235
236 // Put the loop phis in the environment.
237 HBasicBlock header = block.isLoopHeader() ? block : block.parentLoopHeader;
238 for (HPhi phi = header.phis.first; phi != null; phi = phi.next) {
239 for (int i = 1, len = phi.inputs.length; i < len; i++) {
240 environment.add(phi.inputs[i]);
241 }
242 }
243
244 // Add the loop marker
245 environment.addLoopMarker(header);
246
247 if (!branch.isDoWhile()) {
248 assert(block.successors[0] == block.dominatedBlocks[0]);
249 visitBasicBlock(block.successors[0]);
250 }
251
252 // We merge the environment required by the code after the loop,
253 // and the code inside the loop.
254 environment.addAll(joinEnvironment);
255 }
256
257 // Deal with all kinds of control flow instructions. In case we add
258 // a new one, we will hit an internal error.
259 void visitExit(HExit exit) {}
260
261 void visitReturn(HReturn instruction) {
262 environment.clear();
263 visitInstruction(instruction);
264 }
265
266 void visitThrow(HThrow instruction) {
267 environment.clear();
268 visitInstruction(instruction);
269 }
270
271 void visitControlFlow(HControlFlow instruction) {
272 compiler.internalError('Control flow instructions already dealt with.',
273 instruction: instruction);
274 }
275
276 bool shouldCaptureEnvironment(HInstruction instruction) {
277 return instruction.type.isKnown() && !instruction.hasExpectedType();
278 }
279
280 void insertCapturedEnvironments() {
281 work.guards = <HTypeGuard>[];
282 int state = 1;
283 capturedEnvironments.forEach((HInstruction instruction, Environment env) {
284 List<HInstruction> inputs = env.buildAndSetLast(instruction);
285 HTypeGuard guard = new HTypeGuard(state++, inputs);
286 work.guards.add(guard);
287 instruction.block.rewrite(instruction, guard);
288 HInstruction insertionPoint = (instruction is HPhi)
289 ? instruction.block.first
290 : instruction.next;
291 insertionPoint.block.addBefore(insertionPoint, guard);
292 });
293 }
294 }
295
296 /**
297 * Propagates bailout information to blocks that need it. This visitor
298 * is run before codegen, to know which blocks have to deal with
299 * bailouts.
300 */
301 class SsaBailoutPropagator extends HBaseVisitor {
302 final Compiler compiler;
303 final List<HBasicBlock> blocks;
304
305 SsaBailoutPropagator(Compiler this.compiler) : blocks = <HBasicBlock>[];
306
307 void visitGraph(HGraph graph) {
308 blocks.addLast(graph.entry);
309 visitBasicBlock(graph.entry);
310 }
311
312 void visitBasicBlock(HBasicBlock block) {
313 if (block.isLoopHeader()) blocks.addLast(block);
314 HInstruction instruction = block.first;
315 while (instruction != null) {
316 instruction.accept(this);
317 instruction = instruction.next;
318 }
319 }
320
321 void enterBlock(HBasicBlock block) {
322 if (block == null) return;
323 blocks.addLast(block);
324 visitBasicBlock(block);
325 blocks.removeLast();
326 }
327
328 void visitIf(HIf instruction) {
329 enterBlock(instruction.thenBlock);
330 enterBlock(instruction.elseBlock);
331 enterBlock(instruction.joinBlock);
332 }
333
334 void visitGoto(HGoto goto) {
335 HBasicBlock block = goto.block;
336 if (block.successors[0].dominator != block) return;
337 visitBasicBlock(block.successors[0]);
338 }
339
340 void visitLoopBranch(HLoopBranch branch) {
341 HBasicBlock branchBlock = branch.block;
342 if (!branch.isDoWhile()) {
343 // Not a do while loop. We visit the body of the loop.
344 visitBasicBlock(branchBlock.dominatedBlocks[0]);
345 }
346 blocks.removeLast();
347 visitBasicBlock(branchBlock.successors[1]);
348 }
349
350 // Deal with all kinds of control flow instructions. In case we add
351 // a new one, we will hit an internal error.
352 void visitExit(HExit exit) {}
353 void visitReturn(HReturn instruction) {}
354 void visitThrow(HThrow instruction) {}
355
356 void visitControlFlow(HControlFlow instruction) {
357 compiler.internalError('Control flow instructions already dealt with.',
358 instruction: instruction);
359 }
360
361 visitTypeGuard(HTypeGuard guard) {
362 blocks.forEach((HBasicBlock block) {
363 block.guards.add(guard);
364 });
365 }
366 }
OLDNEW
« no previous file with comments | « frog/leg/source_file.dart ('k') | frog/leg/ssa/builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698