OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 'package:kernel/ast.dart' as ir; | 5 import 'package:kernel/ast.dart' as ir; |
6 | 6 |
| 7 import '../closure.dart'; |
7 import '../elements/elements.dart' show JumpTarget, LabelDefinition; | 8 import '../elements/elements.dart' show JumpTarget, LabelDefinition; |
8 import '../io/source_information.dart'; | 9 import '../io/source_information.dart'; |
9 import '../tree/tree.dart' as ast; | 10 import '../tree/tree.dart' as ast; |
10 | 11 |
11 import 'builder.dart'; | 12 import 'builder.dart'; |
12 import 'builder_kernel.dart'; | 13 import 'builder_kernel.dart'; |
13 import 'graph_builder.dart'; | 14 import 'graph_builder.dart'; |
14 import 'jump_handler.dart'; | 15 import 'jump_handler.dart'; |
15 import 'kernel_ast_adapter.dart'; | 16 import 'kernel_ast_adapter.dart'; |
16 import 'locals_handler.dart'; | 17 import 'locals_handler.dart'; |
(...skipping 14 matching lines...) Expand all Loading... |
31 void update(), void body()) { | 32 void update(), void body()) { |
32 // Generate: | 33 // Generate: |
33 // <initializer> | 34 // <initializer> |
34 // loop-entry: | 35 // loop-entry: |
35 // if (!<condition>) goto loop-exit; | 36 // if (!<condition>) goto loop-exit; |
36 // <body> | 37 // <body> |
37 // <updates> | 38 // <updates> |
38 // goto loop-entry; | 39 // goto loop-entry; |
39 // loop-exit: | 40 // loop-exit: |
40 | 41 |
41 builder.localsHandler.startLoop(getNode(loop)); | 42 builder.localsHandler.startLoop(getClosureScopeForLoop(loop)); |
42 | 43 |
43 // The initializer. | 44 // The initializer. |
44 SubExpression initializerGraph = null; | 45 SubExpression initializerGraph = null; |
45 HBasicBlock startBlock; | 46 HBasicBlock startBlock; |
46 if (initialize != null) { | 47 if (initialize != null) { |
47 HBasicBlock initializerBlock = builder.openNewBlock(); | 48 HBasicBlock initializerBlock = builder.openNewBlock(); |
48 startBlock = initializerBlock; | 49 startBlock = initializerBlock; |
49 initialize(); | 50 initialize(); |
50 assert(!builder.isAborted()); | 51 assert(!builder.isAborted()); |
51 initializerGraph = new SubExpression(initializerBlock, builder.current); | 52 initializerGraph = new SubExpression(initializerBlock, builder.current); |
(...skipping 14 matching lines...) Expand all Loading... |
66 // Save the values of the local variables at the end of the condition | 67 // Save the values of the local variables at the end of the condition |
67 // block. These are the values that will flow to the loop exit if the | 68 // block. These are the values that will flow to the loop exit if the |
68 // condition fails. | 69 // condition fails. |
69 LocalsHandler savedLocals = new LocalsHandler.from(builder.localsHandler); | 70 LocalsHandler savedLocals = new LocalsHandler.from(builder.localsHandler); |
70 | 71 |
71 // The body. | 72 // The body. |
72 HBasicBlock beginBodyBlock = builder.addNewBlock(); | 73 HBasicBlock beginBodyBlock = builder.addNewBlock(); |
73 conditionEndBlock.addSuccessor(beginBodyBlock); | 74 conditionEndBlock.addSuccessor(beginBodyBlock); |
74 builder.open(beginBodyBlock); | 75 builder.open(beginBodyBlock); |
75 | 76 |
76 builder.localsHandler.enterLoopBody(getNode(loop)); | 77 builder.localsHandler.enterLoopBody(getClosureScopeForLoop(loop)); |
77 body(); | 78 body(); |
78 | 79 |
79 SubGraph bodyGraph = new SubGraph(beginBodyBlock, builder.lastOpenedBlock); | 80 SubGraph bodyGraph = new SubGraph(beginBodyBlock, builder.lastOpenedBlock); |
80 HBasicBlock bodyBlock = builder.current; | 81 HBasicBlock bodyBlock = builder.current; |
81 if (builder.current != null) builder.close(new HGoto()); | 82 if (builder.current != null) builder.close(new HGoto()); |
82 | 83 |
83 SubExpression updateGraph; | 84 SubExpression updateGraph; |
84 | 85 |
85 bool loopIsDegenerate = !jumpHandler.hasAnyContinue() && bodyBlock == null; | 86 bool loopIsDegenerate = !jumpHandler.hasAnyContinue() && bodyBlock == null; |
86 if (!loopIsDegenerate) { | 87 if (!loopIsDegenerate) { |
(...skipping 28 matching lines...) Expand all Loading... |
115 isContinue: true), | 116 isContinue: true), |
116 updateBlock); | 117 updateBlock); |
117 } else if (target != null && target.isContinueTarget) { | 118 } else if (target != null && target.isContinueTarget) { |
118 beginBodyBlock.setBlockFlow( | 119 beginBodyBlock.setBlockFlow( |
119 new HLabeledBlockInformation.implicit( | 120 new HLabeledBlockInformation.implicit( |
120 new HSubGraphBlockInformation(bodyGraph), target, | 121 new HSubGraphBlockInformation(bodyGraph), target, |
121 isContinue: true), | 122 isContinue: true), |
122 updateBlock); | 123 updateBlock); |
123 } | 124 } |
124 | 125 |
125 builder.localsHandler.enterLoopUpdates(getNode(loop)); | 126 builder.localsHandler.enterLoopUpdates(getClosureScopeForLoop(loop)); |
126 | 127 |
127 update(); | 128 update(); |
128 | 129 |
129 HBasicBlock updateEndBlock = builder.close(new HGoto()); | 130 HBasicBlock updateEndBlock = builder.close(new HGoto()); |
130 // The back-edge completing the cycle. | 131 // The back-edge completing the cycle. |
131 updateEndBlock.addSuccessor(conditionBlock); | 132 updateEndBlock.addSuccessor(conditionBlock); |
132 updateGraph = new SubExpression(updateBlock, updateEndBlock); | 133 updateGraph = new SubExpression(updateBlock, updateEndBlock); |
133 | 134 |
134 // Avoid a critical edge from the condition to the loop-exit body. | 135 // Avoid a critical edge from the condition to the loop-exit body. |
135 HBasicBlock conditionExitBlock = builder.addNewBlock(); | 136 HBasicBlock conditionExitBlock = builder.addNewBlock(); |
(...skipping 144 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
280 builder.localsHandler = | 281 builder.localsHandler = |
281 savedLocals.mergeMultiple(breakHandlers, loopExitBlock); | 282 savedLocals.mergeMultiple(breakHandlers, loopExitBlock); |
282 } else { | 283 } else { |
283 builder.localsHandler = savedLocals; | 284 builder.localsHandler = savedLocals; |
284 } | 285 } |
285 } | 286 } |
286 | 287 |
287 /// Returns the jump target defined by [node]. | 288 /// Returns the jump target defined by [node]. |
288 JumpTarget getTargetDefinition(T node); | 289 JumpTarget getTargetDefinition(T node); |
289 | 290 |
290 /// Returns the corresponding AST node for [node]. | 291 /// Returns closure scope data for [node]. |
291 ast.Node getNode(T node); | 292 ClosureScope getClosureScopeForLoop(T node); |
292 | 293 |
293 /// Determine what kind of loop [node] represents. | 294 /// Determine what kind of loop [node] represents. |
294 /// | 295 /// |
295 /// The result is one of the kinds defined in [HLoopBlockInformation]. | 296 /// The result is one of the kinds defined in [HLoopBlockInformation]. |
296 int loopKind(T node); | 297 int loopKind(T node); |
297 | 298 |
298 /// Returns the source information for the loop [node]. | 299 /// Returns the source information for the loop [node]. |
299 SourceInformation loopSourceInformation(T node); | 300 SourceInformation loopSourceInformation(T node); |
300 | 301 |
301 /// Creates a [JumpHandler] for a statement. The node must be a jump | 302 /// Creates a [JumpHandler] for a statement. The node must be a jump |
(...skipping 13 matching lines...) Expand all Loading... |
315 SsaLoopHandler(SsaBuilder builder) | 316 SsaLoopHandler(SsaBuilder builder) |
316 : this.builder = builder, | 317 : this.builder = builder, |
317 super(builder); | 318 super(builder); |
318 | 319 |
319 @override | 320 @override |
320 JumpTarget getTargetDefinition(ast.Node node) { | 321 JumpTarget getTargetDefinition(ast.Node node) { |
321 return builder.elements.getTargetDefinition(node); | 322 return builder.elements.getTargetDefinition(node); |
322 } | 323 } |
323 | 324 |
324 @override | 325 @override |
325 ast.Node getNode(ast.Node node) => node; | 326 ClosureScope getClosureScopeForLoop(ast.Node node) { |
| 327 return builder.localsHandler.closureData.capturingScopes[node]; |
| 328 } |
326 | 329 |
327 @override | 330 @override |
328 int loopKind(ast.Node node) => node.accept(const _SsaLoopTypeVisitor()); | 331 int loopKind(ast.Node node) => node.accept(const _SsaLoopTypeVisitor()); |
329 | 332 |
330 @override | 333 @override |
331 SourceInformation loopSourceInformation(ast.Node node) => | 334 SourceInformation loopSourceInformation(ast.Node node) => |
332 builder.sourceInformationBuilder.buildLoop(node); | 335 builder.sourceInformationBuilder.buildLoop(node); |
333 | 336 |
334 @override | 337 @override |
335 JumpHandler createJumpHandler(ast.Node node, {bool isLoopJump}) => | 338 JumpHandler createJumpHandler(ast.Node node, {bool isLoopJump}) => |
(...skipping 21 matching lines...) Expand all Loading... |
357 | 360 |
358 KernelLoopHandler(KernelSsaBuilder builder) | 361 KernelLoopHandler(KernelSsaBuilder builder) |
359 : this.builder = builder, | 362 : this.builder = builder, |
360 super(builder); | 363 super(builder); |
361 | 364 |
362 @override | 365 @override |
363 JumpHandler createJumpHandler(ir.TreeNode node, {bool isLoopJump}) => | 366 JumpHandler createJumpHandler(ir.TreeNode node, {bool isLoopJump}) => |
364 builder.createJumpHandler(node, isLoopJump: isLoopJump); | 367 builder.createJumpHandler(node, isLoopJump: isLoopJump); |
365 | 368 |
366 @override | 369 @override |
367 ast.Node getNode(ir.TreeNode node) => astAdapter.getNode(node); | 370 ClosureScope getClosureScopeForLoop(ir.TreeNode node) { |
| 371 return builder.localsMap |
| 372 .getClosureScopeForLoop(builder.localsHandler.closureData, node); |
| 373 } |
368 | 374 |
369 @override | 375 @override |
370 JumpTarget getTargetDefinition(ir.TreeNode node) => | 376 JumpTarget getTargetDefinition(ir.TreeNode node) => |
371 astAdapter.getJumpTarget(node); | 377 builder.localsMap.getJumpTarget(node); |
372 | 378 |
373 @override | 379 @override |
374 int loopKind(ir.TreeNode node) => node.accept(new _KernelLoopTypeVisitor()); | 380 int loopKind(ir.TreeNode node) => node.accept(new _KernelLoopTypeVisitor()); |
375 | 381 |
376 // TODO(het): return the actual source information | 382 // TODO(het): return the actual source information |
377 @override | 383 @override |
378 SourceInformation loopSourceInformation(ir.TreeNode node) => null; | 384 SourceInformation loopSourceInformation(ir.TreeNode node) => null; |
379 } | 385 } |
380 | 386 |
381 class _KernelLoopTypeVisitor extends ir.Visitor<int> { | 387 class _KernelLoopTypeVisitor extends ir.Visitor<int> { |
(...skipping 12 matching lines...) Expand all Loading... |
394 HLoopBlockInformation.DO_WHILE_LOOP; | 400 HLoopBlockInformation.DO_WHILE_LOOP; |
395 | 401 |
396 @override | 402 @override |
397 int visitForInStatement(ir.ForInStatement node) => | 403 int visitForInStatement(ir.ForInStatement node) => |
398 HLoopBlockInformation.FOR_IN_LOOP; | 404 HLoopBlockInformation.FOR_IN_LOOP; |
399 | 405 |
400 @override | 406 @override |
401 int visitSwitchStatement(ir.SwitchStatement node) => | 407 int visitSwitchStatement(ir.SwitchStatement node) => |
402 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; | 408 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; |
403 } | 409 } |
OLD | NEW |