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

Side by Side Diff: pkg/compiler/lib/src/ssa/builder.dart

Issue 2360673003: kernel->ssa: Implement for-loops and while-loops (Closed)
Patch Set: Created 4 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
OLDNEW
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file 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 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. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 import 'dart:collection'; 5 import 'dart:collection';
6 6
7 import 'package:js_runtime/shared/embedded_names.dart'; 7 import 'package:js_runtime/shared/embedded_names.dart';
8 8
9 import '../closure.dart'; 9 import '../closure.dart';
10 import '../common.dart'; 10 import '../common.dart';
(...skipping 22 matching lines...) Expand all
33 import '../tree/tree.dart' as ast; 33 import '../tree/tree.dart' as ast;
34 import '../types/types.dart'; 34 import '../types/types.dart';
35 import '../universe/call_structure.dart' show CallStructure; 35 import '../universe/call_structure.dart' show CallStructure;
36 import '../universe/selector.dart' show Selector; 36 import '../universe/selector.dart' show Selector;
37 import '../universe/side_effects.dart' show SideEffects; 37 import '../universe/side_effects.dart' show SideEffects;
38 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse; 38 import '../universe/use.dart' show DynamicUse, StaticUse, TypeUse;
39 import '../util/util.dart'; 39 import '../util/util.dart';
40 import '../world.dart' show ClassWorld; 40 import '../world.dart' show ClassWorld;
41 41
42 import 'graph_builder.dart'; 42 import 'graph_builder.dart';
43 import 'jump_handler.dart';
43 import 'locals_handler.dart'; 44 import 'locals_handler.dart';
45 import 'loop_handler.dart';
44 import 'nodes.dart'; 46 import 'nodes.dart';
45 import 'optimize.dart'; 47 import 'optimize.dart';
46 import 'ssa_branch_builder.dart'; 48 import 'ssa_branch_builder.dart';
47 import 'types.dart'; 49 import 'types.dart';
48 50
49 /// A synthetic local variable only used with the SSA graph. 51 /// A synthetic local variable only used with the SSA graph.
50 /// 52 ///
51 /// For instance used for holding return value of function or the exception of a 53 /// For instance used for holding return value of function or the exception of a
52 /// try-catch statement. 54 /// try-catch statement.
53 class SyntheticLocal extends Local { 55 class SyntheticLocal extends Local {
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after
118 } 120 }
119 compiler.tracer.traceCompilation(name); 121 compiler.tracer.traceCompilation(name);
120 compiler.tracer.traceGraph('builder', graph); 122 compiler.tracer.traceGraph('builder', graph);
121 } 123 }
122 return graph; 124 return graph;
123 }); 125 });
124 }); 126 });
125 } 127 }
126 } 128 }
127 129
128 // Represents a single break/continue instruction.
129 class JumpHandlerEntry {
130 final HJump jumpInstruction;
131 final LocalsHandler locals;
132 bool isBreak() => jumpInstruction is HBreak;
133 bool isContinue() => jumpInstruction is HContinue;
134 JumpHandlerEntry(this.jumpInstruction, this.locals);
135 }
136
137 abstract class JumpHandler {
138 factory JumpHandler(SsaBuilder builder, JumpTarget target) {
139 return new TargetJumpHandler(builder, target);
140 }
141 void generateBreak([LabelDefinition label]);
142 void generateContinue([LabelDefinition label]);
143 void forEachBreak(void action(HBreak instruction, LocalsHandler locals));
144 void forEachContinue(
145 void action(HContinue instruction, LocalsHandler locals));
146 bool hasAnyContinue();
147 bool hasAnyBreak();
148 void close();
149 final JumpTarget target;
150 List<LabelDefinition> labels();
151 }
152
153 // Insert break handler used to avoid null checks when a target isn't
154 // used as the target of a break, and therefore doesn't need a break
155 // handler associated with it.
156 class NullJumpHandler implements JumpHandler {
157 final DiagnosticReporter reporter;
158
159 NullJumpHandler(this.reporter);
160
161 void generateBreak([LabelDefinition label]) {
162 reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
163 'NullJumpHandler.generateBreak should not be called.');
164 }
165
166 void generateContinue([LabelDefinition label]) {
167 reporter.internalError(CURRENT_ELEMENT_SPANNABLE,
168 'NullJumpHandler.generateContinue should not be called.');
169 }
170
171 void forEachBreak(Function ignored) {}
172 void forEachContinue(Function ignored) {}
173 void close() {}
174 bool hasAnyContinue() => false;
175 bool hasAnyBreak() => false;
176
177 List<LabelDefinition> labels() => const <LabelDefinition>[];
178 JumpTarget get target => null;
179 }
180
181 // Records breaks until a target block is available.
182 // Breaks are always forward jumps.
183 // Continues in loops are implemented as breaks of the body.
184 // Continues in switches is currently not handled.
185 class TargetJumpHandler implements JumpHandler {
186 final SsaBuilder builder;
187 final JumpTarget target;
188 final List<JumpHandlerEntry> jumps;
189
190 TargetJumpHandler(SsaBuilder builder, this.target)
191 : this.builder = builder,
192 jumps = <JumpHandlerEntry>[] {
193 assert(builder.jumpTargets[target] == null);
194 builder.jumpTargets[target] = this;
195 }
196
197 void generateBreak([LabelDefinition label]) {
198 HInstruction breakInstruction;
199 if (label == null) {
200 breakInstruction = new HBreak(target);
201 } else {
202 breakInstruction = new HBreak.toLabel(label);
203 }
204 LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
205 builder.close(breakInstruction);
206 jumps.add(new JumpHandlerEntry(breakInstruction, locals));
207 }
208
209 void generateContinue([LabelDefinition label]) {
210 HInstruction continueInstruction;
211 if (label == null) {
212 continueInstruction = new HContinue(target);
213 } else {
214 continueInstruction = new HContinue.toLabel(label);
215 // Switch case continue statements must be handled by the
216 // [SwitchCaseJumpHandler].
217 assert(label.target.statement is! ast.SwitchCase);
218 }
219 LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
220 builder.close(continueInstruction);
221 jumps.add(new JumpHandlerEntry(continueInstruction, locals));
222 }
223
224 void forEachBreak(Function action) {
225 for (JumpHandlerEntry entry in jumps) {
226 if (entry.isBreak()) action(entry.jumpInstruction, entry.locals);
227 }
228 }
229
230 void forEachContinue(Function action) {
231 for (JumpHandlerEntry entry in jumps) {
232 if (entry.isContinue()) action(entry.jumpInstruction, entry.locals);
233 }
234 }
235
236 bool hasAnyContinue() {
237 for (JumpHandlerEntry entry in jumps) {
238 if (entry.isContinue()) return true;
239 }
240 return false;
241 }
242
243 bool hasAnyBreak() {
244 for (JumpHandlerEntry entry in jumps) {
245 if (entry.isBreak()) return true;
246 }
247 return false;
248 }
249
250 void close() {
251 // The mapping from TargetElement to JumpHandler is no longer needed.
252 builder.jumpTargets.remove(target);
253 }
254
255 List<LabelDefinition> labels() {
256 List<LabelDefinition> result = null;
257 for (LabelDefinition element in target.labels) {
258 if (result == null) result = <LabelDefinition>[];
259 result.add(element);
260 }
261 return (result == null) ? const <LabelDefinition>[] : result;
262 }
263 }
264
265 /// Special [JumpHandler] implementation used to handle continue statements
266 /// targeting switch cases.
267 class SwitchCaseJumpHandler extends TargetJumpHandler {
268 /// Map from switch case targets to indices used to encode the flow of the
269 /// switch case loop.
270 final Map<JumpTarget, int> targetIndexMap = new Map<JumpTarget, int>();
271
272 SwitchCaseJumpHandler(
273 SsaBuilder builder, JumpTarget target, ast.SwitchStatement node)
274 : super(builder, target) {
275 // The switch case indices must match those computed in
276 // [SsaFromAstMixin.buildSwitchCaseConstants].
277 // Switch indices are 1-based so we can bypass the synthetic loop when no
278 // cases match simply by branching on the index (which defaults to null).
279 int switchIndex = 1;
280 for (ast.SwitchCase switchCase in node.cases) {
281 for (ast.Node labelOrCase in switchCase.labelsAndCases) {
282 ast.Node label = labelOrCase.asLabel();
283 if (label != null) {
284 LabelDefinition labelElement =
285 builder.elements.getLabelDefinition(label);
286 if (labelElement != null && labelElement.isContinueTarget) {
287 JumpTarget continueTarget = labelElement.target;
288 targetIndexMap[continueTarget] = switchIndex;
289 assert(builder.jumpTargets[continueTarget] == null);
290 builder.jumpTargets[continueTarget] = this;
291 }
292 }
293 }
294 switchIndex++;
295 }
296 }
297
298 void generateBreak([LabelDefinition label]) {
299 if (label == null) {
300 // Creates a special break instruction for the synthetic loop generated
301 // for a switch statement with continue statements. See
302 // [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
303
304 HInstruction breakInstruction =
305 new HBreak(target, breakSwitchContinueLoop: true);
306 LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
307 builder.close(breakInstruction);
308 jumps.add(new JumpHandlerEntry(breakInstruction, locals));
309 } else {
310 super.generateBreak(label);
311 }
312 }
313
314 bool isContinueToSwitchCase(LabelDefinition label) {
315 return label != null && targetIndexMap.containsKey(label.target);
316 }
317
318 void generateContinue([LabelDefinition label]) {
319 if (isContinueToSwitchCase(label)) {
320 // Creates the special instructions 'label = i; continue l;' used in
321 // switch statements with continue statements. See
322 // [SsaFromAstMixin.buildComplexSwitchStatement] for detail.
323
324 assert(label != null);
325 HInstruction value = builder.graph
326 .addConstantInt(targetIndexMap[label.target], builder.compiler);
327 builder.localsHandler.updateLocal(target, value);
328
329 assert(label.target.labels.contains(label));
330 HInstruction continueInstruction = new HContinue(target);
331 LocalsHandler locals = new LocalsHandler.from(builder.localsHandler);
332 builder.close(continueInstruction);
333 jumps.add(new JumpHandlerEntry(continueInstruction, locals));
334 } else {
335 super.generateContinue(label);
336 }
337 }
338
339 void close() {
340 // The mapping from TargetElement to JumpHandler is no longer needed.
341 for (JumpTarget target in targetIndexMap.keys) {
342 builder.jumpTargets.remove(target);
343 }
344 super.close();
345 }
346 }
347
348 /** 130 /**
349 * This class builds SSA nodes for functions represented in AST. 131 * This class builds SSA nodes for functions represented in AST.
350 */ 132 */
351 class SsaBuilder extends ast.Visitor 133 class SsaBuilder extends ast.Visitor
352 with 134 with
353 BaseImplementationOfCompoundsMixin, 135 BaseImplementationOfCompoundsMixin,
354 BaseImplementationOfSetIfNullsMixin, 136 BaseImplementationOfSetIfNullsMixin,
355 BaseImplementationOfSuperIndexSetIfNullMixin, 137 BaseImplementationOfSuperIndexSetIfNullMixin,
356 SemanticSendResolvedMixin, 138 SemanticSendResolvedMixin,
357 NewBulkMixin, 139 NewBulkMixin,
(...skipping 11 matching lines...) Expand all
369 151
370 /// Registry used to enqueue work during codegen, may be null to avoid 152 /// Registry used to enqueue work during codegen, may be null to avoid
371 /// enqueing any work. 153 /// enqueing any work.
372 // TODO(sigmund,johnniwinther): get rid of registry entirely. We should be 154 // TODO(sigmund,johnniwinther): get rid of registry entirely. We should be
373 // able to return the impact as a result after building and avoid enqueing 155 // able to return the impact as a result after building and avoid enqueing
374 // things here. Later the codegen task can decide whether to enqueue 156 // things here. Later the codegen task can decide whether to enqueue
375 // something. In the past this didn't matter as much because the SSA graph was 157 // something. In the past this didn't matter as much because the SSA graph was
376 // used only for codegen, but currently we want to experiment using it for 158 // used only for codegen, but currently we want to experiment using it for
377 // code-analysis too. 159 // code-analysis too.
378 final CodegenRegistry registry; 160 final CodegenRegistry registry;
379 final Compiler compiler;
380 final GlobalTypeInferenceResults inferenceResults; 161 final GlobalTypeInferenceResults inferenceResults;
381 final JavaScriptBackend backend; 162 final JavaScriptBackend backend;
382 final ConstantSystem constantSystem; 163 final ConstantSystem constantSystem;
383 final RuntimeTypes rti; 164 final RuntimeTypes rti;
384 165
385 SourceInformationBuilder sourceInformationBuilder; 166 SourceInformationBuilder sourceInformationBuilder;
386 167
387 bool inLazyInitializerExpression = false; 168 bool inLazyInitializerExpression = false;
388 169
389 // TODO(sigmund): make all comments /// instead of /* */ 170 // TODO(sigmund): make all comments /// instead of /* */
390 /* This field is used by the native handler. */ 171 /* This field is used by the native handler. */
391 final NativeEmitter nativeEmitter; 172 final NativeEmitter nativeEmitter;
392 173
393 /** 174 /**
394 * True if we are visiting the expression of a throw statement; we assume this 175 * True if we are visiting the expression of a throw statement; we assume this
395 * is a slow path. 176 * is a slow path.
396 */ 177 */
397 bool inExpressionOfThrow = false; 178 bool inExpressionOfThrow = false;
398 179
399 /** 180 /**
400 * The loop nesting is consulted when inlining a function invocation in
401 * [tryInlineMethod]. The inlining heuristics take this information into
402 * account.
403 */
404 int loopNesting = 0;
405
406 /**
407 * This stack contains declaration elements of the functions being built 181 * This stack contains declaration elements of the functions being built
408 * or inlined by this builder. 182 * or inlined by this builder.
409 */ 183 */
410 final List<Element> sourceElementStack = <Element>[]; 184 final List<Element> sourceElementStack = <Element>[];
411 185
412 HInstruction rethrowableException; 186 HInstruction rethrowableException;
413 187
414 Map<JumpTarget, JumpHandler> jumpTargets = <JumpTarget, JumpHandler>{};
415
416 /// Returns `true` if the current element is an `async` function. 188 /// Returns `true` if the current element is an `async` function.
417 bool get isBuildingAsyncFunction { 189 bool get isBuildingAsyncFunction {
418 Element element = sourceElement; 190 Element element = sourceElement;
419 return (element is FunctionElement && 191 return (element is FunctionElement &&
420 element.asyncMarker == AsyncMarker.ASYNC); 192 element.asyncMarker == AsyncMarker.ASYNC);
421 } 193 }
422 194
195 /// Handles the building of loops.
196 LoopHandler<ast.Node> loopHandler;
197
423 // TODO(sigmund): make most args optional 198 // TODO(sigmund): make most args optional
424 SsaBuilder( 199 SsaBuilder(
425 this.target, 200 this.target,
426 this.resolvedAst, 201 this.resolvedAst,
427 this.registry, 202 this.registry,
428 JavaScriptBackend backend, 203 JavaScriptBackend backend,
429 this.nativeEmitter, 204 this.nativeEmitter,
430 SourceInformationStrategy sourceInformationFactory) 205 SourceInformationStrategy sourceInformationFactory)
431 : this.compiler = backend.compiler, 206 : this.infoReporter = backend.compiler.dumpInfoTask,
432 this.infoReporter = backend.compiler.dumpInfoTask,
433 this.backend = backend, 207 this.backend = backend,
434 this.constantSystem = backend.constantSystem, 208 this.constantSystem = backend.constantSystem,
435 this.rti = backend.rti, 209 this.rti = backend.rti,
436 this.inferenceResults = backend.compiler.globalInference.results { 210 this.inferenceResults = backend.compiler.globalInference.results {
437 assert(target.isImplementation); 211 assert(target.isImplementation);
212 compiler = backend.compiler;
438 graph.element = target; 213 graph.element = target;
439 sourceElementStack.add(target); 214 sourceElementStack.add(target);
440 sourceInformationBuilder = 215 sourceInformationBuilder =
441 sourceInformationFactory.createBuilderForContext(resolvedAst); 216 sourceInformationFactory.createBuilderForContext(resolvedAst);
442 graph.sourceInformation = 217 graph.sourceInformation =
443 sourceInformationBuilder.buildVariableDeclaration(); 218 sourceInformationBuilder.buildVariableDeclaration();
444 localsHandler = new LocalsHandler(this, target, null, compiler); 219 localsHandler = new LocalsHandler(this, target, null, compiler);
220 loopHandler = new SsaLoopHandler(this);
445 } 221 }
446 222
447 BackendHelpers get helpers => backend.helpers; 223 BackendHelpers get helpers => backend.helpers;
448 224
449 RuntimeTypesEncoder get rtiEncoder => backend.rtiEncoder; 225 RuntimeTypesEncoder get rtiEncoder => backend.rtiEncoder;
450 226
451 DiagnosticReporter get reporter => compiler.reporter; 227 DiagnosticReporter get reporter => compiler.reporter;
452 228
453 CoreClasses get coreClasses => compiler.coreClasses; 229 CoreClasses get coreClasses => compiler.coreClasses;
454 230
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
625 return false; 401 return false;
626 } 402 }
627 403
628 // Ensure that [element] is an implementation element. 404 // Ensure that [element] is an implementation element.
629 element = element.implementation; 405 element = element.implementation;
630 406
631 if (compiler.elementHasCompileTimeError(element)) return false; 407 if (compiler.elementHasCompileTimeError(element)) return false;
632 408
633 FunctionElement function = element; 409 FunctionElement function = element;
634 ResolvedAst functionResolvedAst = function.resolvedAst; 410 ResolvedAst functionResolvedAst = function.resolvedAst;
635 bool insideLoop = loopNesting > 0 || graph.calledInLoop; 411 bool insideLoop = loopDepth > 0 || graph.calledInLoop;
636 412
637 // Bail out early if the inlining decision is in the cache and we can't 413 // Bail out early if the inlining decision is in the cache and we can't
638 // inline (no need to check the hard constraints). 414 // inline (no need to check the hard constraints).
639 bool cachedCanBeInlined = 415 bool cachedCanBeInlined =
640 backend.inlineCache.canInline(function, insideLoop: insideLoop); 416 backend.inlineCache.canInline(function, insideLoop: insideLoop);
641 if (cachedCanBeInlined == false) return false; 417 if (cachedCanBeInlined == false) return false;
642 418
643 bool meetsHardConstraints() { 419 bool meetsHardConstraints() {
644 if (compiler.options.disableInlining) return false; 420 if (compiler.options.disableInlining) return false;
645 421
(...skipping 1300 matching lines...) Expand 10 before | Expand all | Expand 10 after
1946 visitThrowExpression(throwExpression.expression); 1722 visitThrowExpression(throwExpression.expression);
1947 handleInTryStatement(); 1723 handleInTryStatement();
1948 closeAndGotoExit( 1724 closeAndGotoExit(
1949 new HThrow(pop(), sourceInformationBuilder.buildThrow(node))); 1725 new HThrow(pop(), sourceInformationBuilder.buildThrow(node)));
1950 } else { 1726 } else {
1951 visit(node.expression); 1727 visit(node.expression);
1952 pop(); 1728 pop();
1953 } 1729 }
1954 } 1730 }
1955 1731
1956 /**
1957 * Creates a new loop-header block. The previous [current] block
1958 * is closed with an [HGoto] and replaced by the newly created block.
1959 * Also notifies the locals handler that we're entering a loop.
1960 */
1961 JumpHandler beginLoopHeader(ast.Node node) {
1962 assert(!isAborted());
1963 HBasicBlock previousBlock = close(new HGoto());
1964
1965 JumpHandler jumpHandler = createJumpHandler(node, isLoopJump: true);
1966 HBasicBlock loopEntry =
1967 graph.addNewLoopHeaderBlock(jumpHandler.target, jumpHandler.labels());
1968 previousBlock.addSuccessor(loopEntry);
1969 open(loopEntry);
1970
1971 localsHandler.beginLoopHeader(loopEntry);
1972 return jumpHandler;
1973 }
1974
1975 /**
1976 * Ends the loop:
1977 * - creates a new block and adds it as successor to the [branchExitBlock] and
1978 * any blocks that end in break.
1979 * - opens the new block (setting as [current]).
1980 * - notifies the locals handler that we're exiting a loop.
1981 * [savedLocals] are the locals from the end of the loop condition.
1982 * [branchExitBlock] is the exit (branching) block of the condition. Generally
1983 * this is not the top of the loop, since this would lead to critical edges.
1984 * It is null for degenerate do-while loops that have
1985 * no back edge because they abort (throw/return/break in the body and have
1986 * no continues).
1987 */
1988 void endLoop(HBasicBlock loopEntry, HBasicBlock branchExitBlock,
1989 JumpHandler jumpHandler, LocalsHandler savedLocals) {
1990 HBasicBlock loopExitBlock = addNewBlock();
1991
1992 List<LocalsHandler> breakHandlers = <LocalsHandler>[];
1993 // Collect data for the successors and the phis at each break.
1994 jumpHandler.forEachBreak((HBreak breakInstruction, LocalsHandler locals) {
1995 breakInstruction.block.addSuccessor(loopExitBlock);
1996 breakHandlers.add(locals);
1997 });
1998
1999 // The exit block is a successor of the loop condition if it is reached.
2000 // We don't add the successor in the case of a while/for loop that aborts
2001 // because the caller of endLoop will be wiring up a special empty else
2002 // block instead.
2003 if (branchExitBlock != null) {
2004 branchExitBlock.addSuccessor(loopExitBlock);
2005 }
2006 // Update the phis at the loop entry with the current values of locals.
2007 localsHandler.endLoop(loopEntry);
2008
2009 // Start generating code for the exit block.
2010 open(loopExitBlock);
2011
2012 // Create a new localsHandler for the loopExitBlock with the correct phis.
2013 if (!breakHandlers.isEmpty) {
2014 if (branchExitBlock != null) {
2015 // Add the values of the locals at the end of the condition block to
2016 // the phis. These are the values that flow to the exit if the
2017 // condition fails.
2018 breakHandlers.add(savedLocals);
2019 }
2020 localsHandler = savedLocals.mergeMultiple(breakHandlers, loopExitBlock);
2021 } else {
2022 localsHandler = savedLocals;
2023 }
2024 }
2025
2026 HSubGraphBlockInformation wrapStatementGraph(SubGraph statements) {
2027 if (statements == null) return null;
2028 return new HSubGraphBlockInformation(statements);
2029 }
2030
2031 HSubExpressionBlockInformation wrapExpressionGraph(SubExpression expression) {
2032 if (expression == null) return null;
2033 return new HSubExpressionBlockInformation(expression);
2034 }
2035
2036 // For while loops, initializer and update are null.
2037 // The condition function must return a boolean result.
2038 // None of the functions must leave anything on the stack.
2039 void handleLoop(ast.Node loop, void initialize(), HInstruction condition(),
2040 void update(), void body()) {
2041 // Generate:
2042 // <initializer>
2043 // loop-entry:
2044 // if (!<condition>) goto loop-exit;
2045 // <body>
2046 // <updates>
2047 // goto loop-entry;
2048 // loop-exit:
2049
2050 localsHandler.startLoop(loop);
2051
2052 // The initializer.
2053 SubExpression initializerGraph = null;
2054 HBasicBlock startBlock;
2055 if (initialize != null) {
2056 HBasicBlock initializerBlock = openNewBlock();
2057 startBlock = initializerBlock;
2058 initialize();
2059 assert(!isAborted());
2060 initializerGraph = new SubExpression(initializerBlock, current);
2061 }
2062
2063 loopNesting++;
2064 JumpHandler jumpHandler = beginLoopHeader(loop);
2065 HLoopInformation loopInfo = current.loopInformation;
2066 HBasicBlock conditionBlock = current;
2067 if (startBlock == null) startBlock = conditionBlock;
2068
2069 HInstruction conditionInstruction = condition();
2070 HBasicBlock conditionEndBlock =
2071 close(new HLoopBranch(conditionInstruction));
2072 SubExpression conditionExpression =
2073 new SubExpression(conditionBlock, conditionEndBlock);
2074
2075 // Save the values of the local variables at the end of the condition
2076 // block. These are the values that will flow to the loop exit if the
2077 // condition fails.
2078 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
2079
2080 // The body.
2081 HBasicBlock beginBodyBlock = addNewBlock();
2082 conditionEndBlock.addSuccessor(beginBodyBlock);
2083 open(beginBodyBlock);
2084
2085 localsHandler.enterLoopBody(loop);
2086 body();
2087
2088 SubGraph bodyGraph = new SubGraph(beginBodyBlock, lastOpenedBlock);
2089 HBasicBlock bodyBlock = current;
2090 if (current != null) close(new HGoto());
2091
2092 SubExpression updateGraph;
2093
2094 bool loopIsDegenerate = !jumpHandler.hasAnyContinue() && bodyBlock == null;
2095 if (!loopIsDegenerate) {
2096 // Update.
2097 // We create an update block, even when we are in a while loop. There the
2098 // update block is the jump-target for continue statements. We could avoid
2099 // the creation if there is no continue, but for now we always create it.
2100 HBasicBlock updateBlock = addNewBlock();
2101
2102 List<LocalsHandler> continueHandlers = <LocalsHandler>[];
2103 jumpHandler
2104 .forEachContinue((HContinue instruction, LocalsHandler locals) {
2105 instruction.block.addSuccessor(updateBlock);
2106 continueHandlers.add(locals);
2107 });
2108
2109 if (bodyBlock != null) {
2110 continueHandlers.add(localsHandler);
2111 bodyBlock.addSuccessor(updateBlock);
2112 }
2113
2114 open(updateBlock);
2115 localsHandler =
2116 continueHandlers[0].mergeMultiple(continueHandlers, updateBlock);
2117
2118 List<LabelDefinition> labels = jumpHandler.labels();
2119 JumpTarget target = elements.getTargetDefinition(loop);
2120 if (!labels.isEmpty) {
2121 beginBodyBlock.setBlockFlow(
2122 new HLabeledBlockInformation(
2123 new HSubGraphBlockInformation(bodyGraph), jumpHandler.labels(),
2124 isContinue: true),
2125 updateBlock);
2126 } else if (target != null && target.isContinueTarget) {
2127 beginBodyBlock.setBlockFlow(
2128 new HLabeledBlockInformation.implicit(
2129 new HSubGraphBlockInformation(bodyGraph), target,
2130 isContinue: true),
2131 updateBlock);
2132 }
2133
2134 localsHandler.enterLoopUpdates(loop);
2135
2136 update();
2137
2138 HBasicBlock updateEndBlock = close(new HGoto());
2139 // The back-edge completing the cycle.
2140 updateEndBlock.addSuccessor(conditionBlock);
2141 updateGraph = new SubExpression(updateBlock, updateEndBlock);
2142
2143 // Avoid a critical edge from the condition to the loop-exit body.
2144 HBasicBlock conditionExitBlock = addNewBlock();
2145 open(conditionExitBlock);
2146 close(new HGoto());
2147 conditionEndBlock.addSuccessor(conditionExitBlock);
2148
2149 endLoop(conditionBlock, conditionExitBlock, jumpHandler, savedLocals);
2150
2151 conditionBlock.postProcessLoopHeader();
2152 HLoopBlockInformation info = new HLoopBlockInformation(
2153 _loopKind(loop),
2154 wrapExpressionGraph(initializerGraph),
2155 wrapExpressionGraph(conditionExpression),
2156 wrapStatementGraph(bodyGraph),
2157 wrapExpressionGraph(updateGraph),
2158 conditionBlock.loopInformation.target,
2159 conditionBlock.loopInformation.labels,
2160 sourceInformationBuilder.buildLoop(loop));
2161
2162 startBlock.setBlockFlow(info, current);
2163 loopInfo.loopBlockInformation = info;
2164 } else {
2165 // The body of the for/while loop always aborts, so there is no back edge.
2166 // We turn the code into:
2167 // if (condition) {
2168 // body;
2169 // } else {
2170 // // We always create an empty else block to avoid critical edges.
2171 // }
2172 //
2173 // If there is any break in the body, we attach a synthetic
2174 // label to the if.
2175 HBasicBlock elseBlock = addNewBlock();
2176 open(elseBlock);
2177 close(new HGoto());
2178 // Pass the elseBlock as the branchBlock, because that's the block we go
2179 // to just before leaving the 'loop'.
2180 endLoop(conditionBlock, elseBlock, jumpHandler, savedLocals);
2181
2182 SubGraph elseGraph = new SubGraph(elseBlock, elseBlock);
2183 // Remove the loop information attached to the header.
2184 conditionBlock.loopInformation = null;
2185
2186 // Remove the [HLoopBranch] instruction and replace it with
2187 // [HIf].
2188 HInstruction condition = conditionEndBlock.last.inputs[0];
2189 conditionEndBlock.addAtExit(new HIf(condition));
2190 conditionEndBlock.addSuccessor(elseBlock);
2191 conditionEndBlock.remove(conditionEndBlock.last);
2192 HIfBlockInformation info = new HIfBlockInformation(
2193 wrapExpressionGraph(conditionExpression),
2194 wrapStatementGraph(bodyGraph),
2195 wrapStatementGraph(elseGraph));
2196
2197 conditionEndBlock.setBlockFlow(info, current);
2198 HIf ifBlock = conditionEndBlock.last;
2199 ifBlock.blockInformation = conditionEndBlock.blockFlow;
2200
2201 // If the body has any break, attach a synthesized label to the
2202 // if block.
2203 if (jumpHandler.hasAnyBreak()) {
2204 JumpTarget target = elements.getTargetDefinition(loop);
2205 LabelDefinition label = target.addLabel(null, 'loop');
2206 label.setBreakTarget();
2207 SubGraph labelGraph = new SubGraph(conditionBlock, current);
2208 HLabeledBlockInformation labelInfo = new HLabeledBlockInformation(
2209 new HSubGraphBlockInformation(labelGraph),
2210 <LabelDefinition>[label]);
2211
2212 conditionBlock.setBlockFlow(labelInfo, current);
2213
2214 jumpHandler.forEachBreak((HBreak breakInstruction, _) {
2215 HBasicBlock block = breakInstruction.block;
2216 block.addAtExit(new HBreak.toLabel(label));
2217 block.remove(breakInstruction);
2218 });
2219 }
2220 }
2221 jumpHandler.close();
2222 loopNesting--;
2223 }
2224
2225 visitFor(ast.For node) { 1732 visitFor(ast.For node) {
2226 assert(isReachable); 1733 assert(isReachable);
2227 assert(node.body != null); 1734 assert(node.body != null);
2228 void buildInitializer() { 1735 void buildInitializer() {
2229 ast.Node initializer = node.initializer; 1736 ast.Node initializer = node.initializer;
2230 if (initializer == null) return; 1737 if (initializer == null) return;
2231 visit(initializer); 1738 visit(initializer);
2232 if (initializer.asExpression() != null) { 1739 if (initializer.asExpression() != null) {
2233 pop(); 1740 pop();
2234 } 1741 }
(...skipping 14 matching lines...) Expand all
2249 // The result of the update instruction isn't used, and can just 1756 // The result of the update instruction isn't used, and can just
2250 // be dropped. 1757 // be dropped.
2251 pop(); 1758 pop();
2252 } 1759 }
2253 } 1760 }
2254 1761
2255 void buildBody() { 1762 void buildBody() {
2256 visit(node.body); 1763 visit(node.body);
2257 } 1764 }
2258 1765
2259 handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody); 1766 loopHandler.handleLoop(
1767 node, buildInitializer, buildCondition, buildUpdate, buildBody);
2260 } 1768 }
2261 1769
2262 visitWhile(ast.While node) { 1770 visitWhile(ast.While node) {
2263 assert(isReachable); 1771 assert(isReachable);
2264 HInstruction buildCondition() { 1772 HInstruction buildCondition() {
2265 visit(node.condition); 1773 visit(node.condition);
2266 return popBoolified(); 1774 return popBoolified();
2267 } 1775 }
2268 1776
2269 handleLoop(node, () {}, buildCondition, () {}, () { 1777 loopHandler.handleLoop(node, () {}, buildCondition, () {}, () {
2270 visit(node.body); 1778 visit(node.body);
2271 }); 1779 });
2272 } 1780 }
2273 1781
2274 visitDoWhile(ast.DoWhile node) { 1782 visitDoWhile(ast.DoWhile node) {
2275 assert(isReachable); 1783 assert(isReachable);
2276 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler); 1784 LocalsHandler savedLocals = new LocalsHandler.from(localsHandler);
2277 localsHandler.startLoop(node); 1785 localsHandler.startLoop(node);
2278 loopNesting++; 1786 loopDepth++;
2279 JumpHandler jumpHandler = beginLoopHeader(node); 1787 JumpHandler jumpHandler = loopHandler.beginLoopHeader(node);
2280 HLoopInformation loopInfo = current.loopInformation; 1788 HLoopInformation loopInfo = current.loopInformation;
2281 HBasicBlock loopEntryBlock = current; 1789 HBasicBlock loopEntryBlock = current;
2282 HBasicBlock bodyEntryBlock = current; 1790 HBasicBlock bodyEntryBlock = current;
2283 JumpTarget target = elements.getTargetDefinition(node); 1791 JumpTarget target = elements.getTargetDefinition(node);
2284 bool hasContinues = target != null && target.isContinueTarget; 1792 bool hasContinues = target != null && target.isContinueTarget;
2285 if (hasContinues) { 1793 if (hasContinues) {
2286 // Add extra block to hang labels on. 1794 // Add extra block to hang labels on.
2287 // It doesn't currently work if they are on the same block as the 1795 // It doesn't currently work if they are on the same block as the
2288 // HLoopInfo. The handling of HLabeledBlockInformation will visit a 1796 // HLoopInfo. The handling of HLabeledBlockInformation will visit a
2289 // SubGraph that starts at the same block again, so the HLoopInfo is 1797 // SubGraph that starts at the same block again, so the HLoopInfo is
(...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after
2356 1864
2357 conditionExpression = 1865 conditionExpression =
2358 new SubExpression(conditionBlock, conditionEndBlock); 1866 new SubExpression(conditionBlock, conditionEndBlock);
2359 1867
2360 // Avoid a critical edge from the condition to the loop-exit body. 1868 // Avoid a critical edge from the condition to the loop-exit body.
2361 HBasicBlock conditionExitBlock = addNewBlock(); 1869 HBasicBlock conditionExitBlock = addNewBlock();
2362 open(conditionExitBlock); 1870 open(conditionExitBlock);
2363 close(new HGoto()); 1871 close(new HGoto());
2364 conditionEndBlock.addSuccessor(conditionExitBlock); 1872 conditionEndBlock.addSuccessor(conditionExitBlock);
2365 1873
2366 endLoop(loopEntryBlock, conditionExitBlock, jumpHandler, localsHandler); 1874 loopHandler.endLoop(
1875 loopEntryBlock, conditionExitBlock, jumpHandler, localsHandler);
2367 1876
2368 loopEntryBlock.postProcessLoopHeader(); 1877 loopEntryBlock.postProcessLoopHeader();
2369 SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock); 1878 SubGraph bodyGraph = new SubGraph(loopEntryBlock, bodyExitBlock);
2370 HLoopBlockInformation loopBlockInfo = new HLoopBlockInformation( 1879 HLoopBlockInformation loopBlockInfo = new HLoopBlockInformation(
2371 HLoopBlockInformation.DO_WHILE_LOOP, 1880 HLoopBlockInformation.DO_WHILE_LOOP,
2372 null, 1881 null,
2373 wrapExpressionGraph(conditionExpression), 1882 wrapExpressionGraph(conditionExpression),
2374 wrapStatementGraph(bodyGraph), 1883 wrapStatementGraph(bodyGraph),
2375 null, 1884 null,
2376 loopEntryBlock.loopInformation.target, 1885 loopEntryBlock.loopInformation.target,
2377 loopEntryBlock.loopInformation.labels, 1886 loopEntryBlock.loopInformation.labels,
2378 sourceInformationBuilder.buildLoop(node)); 1887 sourceInformationBuilder.buildLoop(node));
2379 loopEntryBlock.setBlockFlow(loopBlockInfo, current); 1888 loopEntryBlock.setBlockFlow(loopBlockInfo, current);
2380 loopInfo.loopBlockInformation = loopBlockInfo; 1889 loopInfo.loopBlockInformation = loopBlockInfo;
2381 } else { 1890 } else {
2382 // Since the loop has no back edge, we remove the loop information on the 1891 // Since the loop has no back edge, we remove the loop information on the
2383 // header. 1892 // header.
2384 loopEntryBlock.loopInformation = null; 1893 loopEntryBlock.loopInformation = null;
2385 1894
2386 if (jumpHandler.hasAnyBreak()) { 1895 if (jumpHandler.hasAnyBreak()) {
2387 // Null branchBlock because the body of the do-while loop always aborts, 1896 // Null branchBlock because the body of the do-while loop always aborts,
2388 // so we never get to the condition. 1897 // so we never get to the condition.
2389 endLoop(loopEntryBlock, null, jumpHandler, localsHandler); 1898 loopHandler.endLoop(loopEntryBlock, null, jumpHandler, localsHandler);
2390 1899
2391 // Since the body of the loop has a break, we attach a synthesized label 1900 // Since the body of the loop has a break, we attach a synthesized label
2392 // to the body. 1901 // to the body.
2393 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock); 1902 SubGraph bodyGraph = new SubGraph(bodyEntryBlock, bodyExitBlock);
2394 JumpTarget target = elements.getTargetDefinition(node); 1903 JumpTarget target = elements.getTargetDefinition(node);
2395 LabelDefinition label = target.addLabel(null, 'loop'); 1904 LabelDefinition label = target.addLabel(null, 'loop');
2396 label.setBreakTarget(); 1905 label.setBreakTarget();
2397 HLabeledBlockInformation info = new HLabeledBlockInformation( 1906 HLabeledBlockInformation info = new HLabeledBlockInformation(
2398 new HSubGraphBlockInformation(bodyGraph), <LabelDefinition>[label]); 1907 new HSubGraphBlockInformation(bodyGraph), <LabelDefinition>[label]);
2399 loopEntryBlock.setBlockFlow(info, current); 1908 loopEntryBlock.setBlockFlow(info, current);
2400 jumpHandler.forEachBreak((HBreak breakInstruction, _) { 1909 jumpHandler.forEachBreak((HBreak breakInstruction, _) {
2401 HBasicBlock block = breakInstruction.block; 1910 HBasicBlock block = breakInstruction.block;
2402 block.addAtExit(new HBreak.toLabel(label)); 1911 block.addAtExit(new HBreak.toLabel(label));
2403 block.remove(breakInstruction); 1912 block.remove(breakInstruction);
2404 }); 1913 });
2405 } 1914 }
2406 } 1915 }
2407 jumpHandler.close(); 1916 jumpHandler.close();
2408 loopNesting--; 1917 loopDepth--;
2409 } 1918 }
2410 1919
2411 visitFunctionExpression(ast.FunctionExpression node) { 1920 visitFunctionExpression(ast.FunctionExpression node) {
2412 ClosureClassMap nestedClosureData = 1921 ClosureClassMap nestedClosureData =
2413 compiler.closureToClassMapper.getMappingForNestedFunction(node); 1922 compiler.closureToClassMapper.getMappingForNestedFunction(node);
2414 assert(nestedClosureData != null); 1923 assert(nestedClosureData != null);
2415 assert(nestedClosureData.closureClassElement != null); 1924 assert(nestedClosureData.closureClassElement != null);
2416 ClosureClassElement closureClassElement = 1925 ClosureClassElement closureClassElement =
2417 nestedClosureData.closureClassElement; 1926 nestedClosureData.closureClassElement;
2418 FunctionElement callElement = nestedClosureData.callElement; 1927 FunctionElement callElement = nestedClosureData.callElement;
(...skipping 3630 matching lines...) Expand 10 before | Expand all | Expand 10 after
6049 handler.generateContinue(label); 5558 handler.generateContinue(label);
6050 } 5559 }
6051 } 5560 }
6052 5561
6053 /** 5562 /**
6054 * Creates a [JumpHandler] for a statement. The node must be a jump 5563 * Creates a [JumpHandler] for a statement. The node must be a jump
6055 * target. If there are no breaks or continues targeting the statement, 5564 * target. If there are no breaks or continues targeting the statement,
6056 * a special "null handler" is returned. 5565 * a special "null handler" is returned.
6057 * 5566 *
6058 * [isLoopJump] is [:true:] when the jump handler is for a loop. This is used 5567 * [isLoopJump] is [:true:] when the jump handler is for a loop. This is used
6059 * to distinguish the synthetized loop created for a switch statement with 5568 * to distinguish the synthesized loop created for a switch statement with
6060 * continue statements from simple switch statements. 5569 * continue statements from simple switch statements.
6061 */ 5570 */
6062 JumpHandler createJumpHandler(ast.Statement node, {bool isLoopJump}) { 5571 JumpHandler createJumpHandler(ast.Statement node, {bool isLoopJump}) {
6063 JumpTarget element = elements.getTargetDefinition(node); 5572 JumpTarget element = elements.getTargetDefinition(node);
6064 if (element == null || !identical(element.statement, node)) { 5573 if (element == null || !identical(element.statement, node)) {
6065 // No breaks or continues to this node. 5574 // No breaks or continues to this node.
6066 return new NullJumpHandler(reporter); 5575 return new NullJumpHandler(reporter);
6067 } 5576 }
6068 if (isLoopJump && node is ast.SwitchStatement) { 5577 if (isLoopJump && node is ast.SwitchStatement) {
6069 // Create a special jump handler for loops created for switch statements 5578 // Create a special jump handler for loops created for switch statements
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
6118 generateNonInstanceSetter(null, variable, value, location: identifier); 5627 generateNonInstanceSetter(null, variable, value, location: identifier);
6119 } 5628 }
6120 pop(); // Pop the value pushed by the setter call. 5629 pop(); // Pop the value pushed by the setter call.
6121 5630
6122 visit(node.body); 5631 visit(node.body);
6123 } 5632 }
6124 5633
6125 void buildUpdate() {} 5634 void buildUpdate() {}
6126 5635
6127 buildProtectedByFinally(() { 5636 buildProtectedByFinally(() {
6128 handleLoop( 5637 loopHandler.handleLoop(
6129 node, buildInitializer, buildCondition, buildUpdate, buildBody); 5638 node, buildInitializer, buildCondition, buildUpdate, buildBody);
6130 }, () { 5639 }, () {
6131 pushInvokeDynamic(node, Selectors.cancel, null, [streamIterator]); 5640 pushInvokeDynamic(node, Selectors.cancel, null, [streamIterator]);
6132 push(new HAwait( 5641 push(new HAwait(
6133 pop(), 5642 pop(),
6134 new TypeMask.subclass( 5643 new TypeMask.subclass(
6135 coreClasses.objectClass, compiler.closedWorld))); 5644 coreClasses.objectClass, compiler.closedWorld)));
6136 pop(); 5645 pop();
6137 }); 5646 });
6138 } 5647 }
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
6188 } 5697 }
6189 5698
6190 void buildBody() { 5699 void buildBody() {
6191 Selector call = Selectors.current; 5700 Selector call = Selectors.current;
6192 TypeMask mask = inferenceResults.typeOfIteratorCurrent(node, elements); 5701 TypeMask mask = inferenceResults.typeOfIteratorCurrent(node, elements);
6193 pushInvokeDynamic(node, call, mask, [iterator]); 5702 pushInvokeDynamic(node, call, mask, [iterator]);
6194 buildAssignLoopVariable(node, pop()); 5703 buildAssignLoopVariable(node, pop());
6195 visit(node.body); 5704 visit(node.body);
6196 } 5705 }
6197 5706
6198 handleLoop(node, buildInitializer, buildCondition, () {}, buildBody); 5707 loopHandler.handleLoop(
5708 node, buildInitializer, buildCondition, () {}, buildBody);
6199 } 5709 }
6200 5710
6201 buildAssignLoopVariable(ast.ForIn node, HInstruction value) { 5711 buildAssignLoopVariable(ast.ForIn node, HInstruction value) {
6202 ast.Node identifier = node.declaredIdentifier; 5712 ast.Node identifier = node.declaredIdentifier;
6203 Element variable = elements.getForInVariable(node); 5713 Element variable = elements.getForInVariable(node);
6204 Selector selector = elements.getSelector(identifier); 5714 Selector selector = elements.getSelector(identifier);
6205 5715
6206 if (identifier.asSend() != null && 5716 if (identifier.asSend() != null &&
6207 Elements.isInstanceSend(identifier, elements)) { 5717 Elements.isInstanceSend(identifier, elements)) {
6208 TypeMask mask = inferenceResults.typeOfSend(identifier, elements); 5718 TypeMask mask = inferenceResults.typeOfSend(identifier, elements);
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
6307 // but the code is horrible as `i+1` is carried around the loop in an 5817 // but the code is horrible as `i+1` is carried around the loop in an
6308 // additional variable. 5818 // additional variable.
6309 HInstruction index = localsHandler.readLocal(indexVariable); 5819 HInstruction index = localsHandler.readLocal(indexVariable);
6310 HInstruction one = graph.addConstantInt(1, compiler); 5820 HInstruction one = graph.addConstantInt(1, compiler);
6311 HInstruction addInstruction = 5821 HInstruction addInstruction =
6312 new HAdd(index, one, null, backend.positiveIntType); 5822 new HAdd(index, one, null, backend.positiveIntType);
6313 add(addInstruction); 5823 add(addInstruction);
6314 localsHandler.updateLocal(indexVariable, addInstruction); 5824 localsHandler.updateLocal(indexVariable, addInstruction);
6315 } 5825 }
6316 5826
6317 handleLoop(node, buildInitializer, buildCondition, buildUpdate, buildBody); 5827 loopHandler.handleLoop(
5828 node, buildInitializer, buildCondition, buildUpdate, buildBody);
6318 } 5829 }
6319 5830
6320 visitLabel(ast.Label node) { 5831 visitLabel(ast.Label node) {
6321 reporter.internalError(node, 'SsaFromAstMixin.visitLabel.'); 5832 reporter.internalError(node, 'SsaFromAstMixin.visitLabel.');
6322 } 5833 }
6323 5834
6324 visitLabeledStatement(ast.LabeledStatement node) { 5835 visitLabeledStatement(ast.LabeledStatement node) {
6325 ast.Statement body = node.statement; 5836 ast.Statement body = node.statement;
6326 if (body is ast.Loop || 5837 if (body is ast.Loop ||
6327 body is ast.SwitchStatement || 5838 body is ast.SwitchStatement ||
(...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after
6651 node, 6162 node,
6652 new NullJumpHandler(reporter), 6163 new NullJumpHandler(reporter),
6653 buildExpression, 6164 buildExpression,
6654 node.cases, 6165 node.cases,
6655 getConstants, 6166 getConstants,
6656 (_) => false, // No case is default. 6167 (_) => false, // No case is default.
6657 buildSwitchCase); 6168 buildSwitchCase);
6658 } 6169 }
6659 6170
6660 void buildLoop() { 6171 void buildLoop() {
6661 handleLoop(node, () {}, buildCondition, () {}, buildSwitch); 6172 loopHandler.handleLoop(node, () {}, buildCondition, () {}, buildSwitch);
6662 } 6173 }
6663 6174
6664 if (hasDefault) { 6175 if (hasDefault) {
6665 buildLoop(); 6176 buildLoop();
6666 } else { 6177 } else {
6667 // If the switch statement has no default case, surround the loop with 6178 // If the switch statement has no default case, surround the loop with
6668 // a test of the target. 6179 // a test of the target.
6669 void buildCondition() { 6180 void buildCondition() {
6670 js.Template code = js.js.parseForeignJS('#'); 6181 js.Template code = js.js.parseForeignJS('#');
6671 push(new HForeignCode( 6182 push(new HForeignCode(
(...skipping 881 matching lines...) Expand 10 before | Expand all | Expand 10 after
7553 if (unaliased is TypedefType) throw 'unable to unalias $type'; 7064 if (unaliased is TypedefType) throw 'unable to unalias $type';
7554 unaliased.accept(this, builder); 7065 unaliased.accept(this, builder);
7555 } 7066 }
7556 7067
7557 void visitDynamicType(DynamicType type, SsaBuilder builder) { 7068 void visitDynamicType(DynamicType type, SsaBuilder builder) {
7558 JavaScriptBackend backend = builder.compiler.backend; 7069 JavaScriptBackend backend = builder.compiler.backend;
7559 ClassElement cls = backend.helpers.DynamicRuntimeType; 7070 ClassElement cls = backend.helpers.DynamicRuntimeType;
7560 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld))); 7071 builder.push(new HDynamicType(type, new TypeMask.exact(cls, classWorld)));
7561 } 7072 }
7562 } 7073 }
7563
7564 /// Determine what kind of loop [node] represents. The result is one of the
7565 /// kinds defined in [HLoopBlockInformation].
7566 int _loopKind(ast.Node node) => node.accept(const _LoopTypeVisitor());
7567
7568 class _LoopTypeVisitor extends ast.Visitor {
7569 const _LoopTypeVisitor();
7570 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP;
7571 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP;
7572 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP;
7573 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP;
7574 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
7575 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP;
7576 int visitSwitchStatement(ast.SwitchStatement node) =>
7577 HLoopBlockInformation.SWITCH_CONTINUE_LOOP;
7578 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/kernel/kernel_visitor.dart ('k') | pkg/compiler/lib/src/ssa/builder_kernel.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698