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

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

Issue 2790063008: dart2js: Avoid recursion in visiting blocks of subgraph (Closed)
Patch Set: simplify Created 3 years, 8 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
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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:math' as math; 5 import 'dart:math' as math;
6 import 'dart:collection' show Queue;
6 import '../common.dart'; 7 import '../common.dart';
7 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem; 8 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
8 import '../common/tasks.dart' show CompilerTask; 9 import '../common/tasks.dart' show CompilerTask;
9 import '../constants/constant_system.dart'; 10 import '../constants/constant_system.dart';
10 import '../constants/values.dart'; 11 import '../constants/values.dart';
11 import '../common_elements.dart' show CommonElements; 12 import '../common_elements.dart' show CommonElements;
12 import '../elements/elements.dart' 13 import '../elements/elements.dart'
13 show AsyncMarker, JumpTarget, LabelDefinition, MethodElement, ResolvedAst; 14 show AsyncMarker, JumpTarget, LabelDefinition, MethodElement, ResolvedAst;
14 import '../elements/entities.dart'; 15 import '../elements/entities.dart';
15 import '../elements/types.dart'; 16 import '../elements/types.dart';
(...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after
199 200
200 HGraph currentGraph; 201 HGraph currentGraph;
201 202
202 // Records a block-information that is being handled specially. 203 // Records a block-information that is being handled specially.
203 // Used to break bad recursion. 204 // Used to break bad recursion.
204 HBlockInformation currentBlockInformation; 205 HBlockInformation currentBlockInformation;
205 // The subgraph is used to delimit traversal for some constructions, e.g., 206 // The subgraph is used to delimit traversal for some constructions, e.g.,
206 // if branches. 207 // if branches.
207 SubGraph subGraph; 208 SubGraph subGraph;
208 209
210 // Pending blocks than need to be visited as part of current subgraph.
211 Queue<HBasicBlock> blockQueue;
212
209 SsaCodeGenerator( 213 SsaCodeGenerator(
210 this._options, 214 this._options,
211 this._emitter, 215 this._emitter,
212 this._nativeEnqueuer, 216 this._nativeEnqueuer,
213 this._helpers, 217 this._helpers,
214 this._checkedModeHelpers, 218 this._checkedModeHelpers,
215 this._nativeData, 219 this._nativeData,
216 this._interceptorData, 220 this._interceptorData,
217 this._oneShotInterceptorData, 221 this._oneShotInterceptorData,
218 this._rtiSubstitutions, 222 this._rtiSubstitutions,
(...skipping 193 matching lines...) Expand 10 before | Expand all | Expand 10 after
412 var declarationList = new js.VariableDeclarationList(declarations) 416 var declarationList = new js.VariableDeclarationList(declarations)
413 .withSourceInformation(sourceInformation); 417 .withSourceInformation(sourceInformation);
414 ; 418 ;
415 insertStatementAtStart(new js.ExpressionStatement(declarationList)); 419 insertStatementAtStart(new js.ExpressionStatement(declarationList));
416 } 420 }
417 } 421 }
418 422
419 visitGraph(HGraph graph) { 423 visitGraph(HGraph graph) {
420 preGenerateMethod(graph); 424 preGenerateMethod(graph);
421 currentGraph = graph; 425 currentGraph = graph;
422 subGraph = new SubGraph(graph.entry, graph.exit); 426 visitSubGraph(new SubGraph(graph.entry, graph.exit));
423 visitBasicBlock(graph.entry);
424 handleDelayedVariableDeclarations(graph.sourceInformation); 427 handleDelayedVariableDeclarations(graph.sourceInformation);
425 } 428 }
426 429
427 void visitSubGraph(SubGraph newSubGraph) { 430 void visitSubGraph(SubGraph newSubGraph) {
428 SubGraph oldSubGraph = subGraph; 431 SubGraph oldSubGraph = subGraph;
432 Queue<HBasicBlock> oldBlockQueue = blockQueue;
429 subGraph = newSubGraph; 433 subGraph = newSubGraph;
430 visitBasicBlock(subGraph.start); 434 blockQueue = new Queue<HBasicBlock>();
435 enterSubGraph(subGraph.start);
436 blockQueue = oldBlockQueue;
431 subGraph = oldSubGraph; 437 subGraph = oldSubGraph;
432 } 438 }
433 439
434 /** 440 /**
435 * Check whether a sub-graph can be generated as an expression, or even 441 * Check whether a sub-graph can be generated as an expression, or even
436 * as a declaration, or if it has to fall back to being generated as 442 * as a declaration, or if it has to fall back to being generated as
437 * a statement. 443 * a statement.
438 * Expressions are anything that doesn't generate control flow constructs. 444 * Expressions are anything that doesn't generate control flow constructs.
439 * Declarations must only generate assignments on the form "id = expression", 445 * Declarations must only generate assignments on the form "id = expression",
440 * and not, e.g., expressions where the value isn't assigned, or where it's 446 * and not, e.g., expressions where the value isn't assigned, or where it's
(...skipping 753 matching lines...) Expand 10 before | Expand all | Expand 10 after
1194 // the same block, don't handle it again. 1200 // the same block, don't handle it again.
1195 // When the structure graph is complete, we will be able to have 1201 // When the structure graph is complete, we will be able to have
1196 // different structures starting on the same basic block (e.g., an 1202 // different structures starting on the same basic block (e.g., an
1197 // "if" and its condition). 1203 // "if" and its condition).
1198 if (identical(info, currentBlockInformation)) return false; 1204 if (identical(info, currentBlockInformation)) return false;
1199 1205
1200 HBlockInformation oldBlockInformation = currentBlockInformation; 1206 HBlockInformation oldBlockInformation = currentBlockInformation;
1201 currentBlockInformation = info; 1207 currentBlockInformation = info;
1202 bool success = info.accept(this); 1208 bool success = info.accept(this);
1203 currentBlockInformation = oldBlockInformation; 1209 currentBlockInformation = oldBlockInformation;
1210
1204 if (success) { 1211 if (success) {
1205 HBasicBlock continuation = block.continuation; 1212 HBasicBlock continuation = block.continuation;
1206 if (continuation != null) { 1213 if (continuation != null) {
1207 visitBasicBlock(continuation); 1214 continueSubGraph(continuation);
1208 } 1215 }
1209 } 1216 }
1210 return success; 1217 return success;
1211 } 1218 }
1212 1219
1213 void visitBasicBlock(HBasicBlock node) { 1220 void enterSubGraph(HBasicBlock node) {
1221 assert(blockQueue.isEmpty);
1222 assert(node != null);
1223 continueSubGraph(node);
1224 while (blockQueue.isNotEmpty) {
1225 node = blockQueue.removeFirst();
1226 assert(node.isLive);
1227 assert(subGraph.contains(node));
1228
1229 // If this node has block-structure based information attached,
1230 // try using that to traverse from here.
1231 if (node.blockFlow != null && handleBlockFlow(node.blockFlow)) {
1232 continue;
1233 }
1234
1235 iterateBasicBlock(node);
1236 }
1237 }
1238
1239 void continueSubGraph(HBasicBlock node) {
1214 if (!node.isLive) return; 1240 if (!node.isLive) return;
1215 1241 // Don't follow edges out of the current sub-graph.
1216 // Abort traversal if we are leaving the currently active sub-graph.
1217 if (!subGraph.contains(node)) return; 1242 if (!subGraph.contains(node)) return;
1218 1243 blockQueue.add(node);
1219 // If this node has block-structure based information attached,
1220 // try using that to traverse from here.
1221 if (node.blockFlow != null && handleBlockFlow(node.blockFlow)) {
1222 return;
1223 }
1224 iterateBasicBlock(node);
1225 } 1244 }
1226 1245
1227 void emitAssignment(String destination, String source) { 1246 void emitAssignment(String destination, String source) {
1228 assignVariable(destination, new js.VariableUse(source), null); 1247 assignVariable(destination, new js.VariableUse(source), null);
1229 } 1248 }
1230 1249
1231 /** 1250 /**
1232 * Sequentialize a list of conceptually parallel copies. Parallel 1251 * Sequentialize a list of conceptually parallel copies. Parallel
1233 * copies may contain cycles, that this method breaks. 1252 * copies may contain cycles, that this method breaks.
1234 */ 1253 */
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
1477 if (dominated.isEmpty) return; 1496 if (dominated.isEmpty) return;
1478 if (dominated.length > 2) { 1497 if (dominated.length > 2) {
1479 throw new SpannableAssertionFailure( 1498 throw new SpannableAssertionFailure(
1480 node, 'dominated.length = ${dominated.length}'); 1499 node, 'dominated.length = ${dominated.length}');
1481 } 1500 }
1482 if (dominated.length == 2 && block != currentGraph.entry) { 1501 if (dominated.length == 2 && block != currentGraph.entry) {
1483 throw new SpannableAssertionFailure( 1502 throw new SpannableAssertionFailure(
1484 node, 'node.block != currentGraph.entry'); 1503 node, 'node.block != currentGraph.entry');
1485 } 1504 }
1486 assert(dominated[0] == block.successors[0]); 1505 assert(dominated[0] == block.successors[0]);
1487 visitBasicBlock(dominated[0]); 1506 continueSubGraph(dominated.first);
1488 } 1507 }
1489 1508
1490 visitLoopBranch(HLoopBranch node) { 1509 visitLoopBranch(HLoopBranch node) {
1491 assert(node.block == subGraph.end); 1510 assert(node.block == subGraph.end);
1492 // We are generating code for a loop condition. 1511 // We are generating code for a loop condition.
1493 // If we are generating the subgraph as an expression, the 1512 // If we are generating the subgraph as an expression, the
1494 // condition will be generated as the expression. 1513 // condition will be generated as the expression.
1495 // Otherwise, we don't generate the expression, and leave that 1514 // Otherwise, we don't generate the expression, and leave that
1496 // to the code that called [visitSubGraph]. 1515 // to the code that called [visitSubGraph].
1497 if (isGeneratingExpression) { 1516 if (isGeneratingExpression) {
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1556 } 1575 }
1557 } 1576 }
1558 } 1577 }
1559 1578
1560 visitExitTry(HExitTry node) { 1579 visitExitTry(HExitTry node) {
1561 // An [HExitTry] is used to represent the control flow graph of a 1580 // An [HExitTry] is used to represent the control flow graph of a
1562 // try/catch block, ie the try body is always a predecessor 1581 // try/catch block, ie the try body is always a predecessor
1563 // of the catch and finally. Here, we continue visiting the try 1582 // of the catch and finally. Here, we continue visiting the try
1564 // body by visiting the block that contains the user-level control 1583 // body by visiting the block that contains the user-level control
1565 // flow instruction. 1584 // flow instruction.
1566 visitBasicBlock(node.bodyTrySuccessor); 1585 continueSubGraph(node.bodyTrySuccessor);
1567 } 1586 }
1568 1587
1569 visitTry(HTry node) { 1588 visitTry(HTry node) {
1570 // We should never get here. Try/catch/finally is always handled using block 1589 // We should never get here. Try/catch/finally is always handled using block
1571 // information in [visitTryInfo]. 1590 // information in [visitTryInfo].
1572 throw new SpannableAssertionFailure(node, 'visitTry should not be called.'); 1591 throw new SpannableAssertionFailure(node, 'visitTry should not be called.');
1573 } 1592 }
1574 1593
1575 bool tryControlFlowOperation(HIf node) { 1594 bool tryControlFlowOperation(HIf node) {
1576 if (!controlFlowOperators.contains(node)) return false; 1595 if (!controlFlowOperators.contains(node)) return false;
1577 HPhi phi = node.joinBlock.phis.first; 1596 HPhi phi = node.joinBlock.phis.first;
1578 bool atUseSite = isGenerateAtUseSite(phi); 1597 bool atUseSite = isGenerateAtUseSite(phi);
1579 // Don't generate a conditional operator in this situation: 1598 // Don't generate a conditional operator in this situation:
1580 // i = condition ? bar() : i; 1599 // i = condition ? bar() : i;
1581 // But generate this instead: 1600 // But generate this instead:
1582 // if (condition) i = bar(); 1601 // if (condition) i = bar();
1583 // Usually, the variable name is longer than 'if' and it takes up 1602 // Usually, the variable name is longer than 'if' and it takes up
1584 // more space to duplicate the name. 1603 // more space to duplicate the name.
1585 if (!atUseSite && 1604 if (!atUseSite &&
1586 variableNames.getName(phi) == variableNames.getName(phi.inputs[1])) { 1605 variableNames.getName(phi) == variableNames.getName(phi.inputs[1])) {
1587 return false; 1606 return false;
1588 } 1607 }
1589 if (!atUseSite) define(phi); 1608 if (!atUseSite) define(phi);
1590 visitBasicBlock(node.joinBlock); 1609 continueSubGraph(node.joinBlock);
1591 return true; 1610 return true;
1592 } 1611 }
1593 1612
1594 void generateIf(HIf node, HIfBlockInformation info) { 1613 void generateIf(HIf node, HIfBlockInformation info) {
1595 use(node.inputs[0]); 1614 use(node.inputs[0]);
1596 js.Expression test = pop(); 1615 js.Expression test = pop();
1597 1616
1598 HStatementInformation thenGraph = info.thenGraph; 1617 HStatementInformation thenGraph = info.thenGraph;
1599 HStatementInformation elseGraph = info.elseGraph; 1618 HStatementInformation elseGraph = info.elseGraph;
1600 js.Statement thenPart = 1619 js.Statement thenPart =
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
1638 } 1657 }
1639 } else { 1658 } else {
1640 generateIf(node, info); 1659 generateIf(node, info);
1641 } 1660 }
1642 1661
1643 HBasicBlock joinBlock = node.joinBlock; 1662 HBasicBlock joinBlock = node.joinBlock;
1644 if (joinBlock != null && !identical(joinBlock.dominator, node.block)) { 1663 if (joinBlock != null && !identical(joinBlock.dominator, node.block)) {
1645 // The join block is dominated by a block in one of the branches. 1664 // The join block is dominated by a block in one of the branches.
1646 // The subgraph traversal never reached it, so we visit it here 1665 // The subgraph traversal never reached it, so we visit it here
1647 // instead. 1666 // instead.
1648 visitBasicBlock(joinBlock); 1667 continueSubGraph(joinBlock);
1649 } 1668 }
1650 1669
1651 // Visit all the dominated blocks that are not part of the then or else 1670 // Visit all the dominated blocks that are not part of the then or else
1652 // branches, and is not the join block. 1671 // branches, and is not the join block.
1653 // Depending on how the then/else branches terminate 1672 // Depending on how the then/else branches terminate
1654 // (e.g., return/throw/break) there can be any number of these. 1673 // (e.g., return/throw/break) there can be any number of these.
1655 List<HBasicBlock> dominated = node.block.dominatedBlocks; 1674 List<HBasicBlock> dominated = node.block.dominatedBlocks;
1656 for (int i = 2; i < dominated.length; i++) { 1675 for (int i = 2; i < dominated.length; i++) {
1657 visitBasicBlock(dominated[i]); 1676 continueSubGraph(dominated[i]);
1658 } 1677 }
1659 } 1678 }
1660 1679
1661 void visitInterceptor(HInterceptor node) { 1680 void visitInterceptor(HInterceptor node) {
1662 if (node.isConditionalConstantInterceptor) { 1681 if (node.isConditionalConstantInterceptor) {
1663 assert(node.inputs.length == 2); 1682 assert(node.inputs.length == 2);
1664 use(node.receiver); 1683 use(node.receiver);
1665 js.Expression receiverExpression = pop(); 1684 js.Expression receiverExpression = pop();
1666 use(node.conditionalConstantInterceptor); 1685 use(node.conditionalConstantInterceptor);
1667 js.Expression constant = pop(); 1686 js.Expression constant = pop();
(...skipping 1344 matching lines...) Expand 10 before | Expand all | Expand 10 after
3012 return _closedWorld.anyStrictSubclassOf(cls, (ClassEntity subclass) { 3031 return _closedWorld.anyStrictSubclassOf(cls, (ClassEntity subclass) {
3013 return !_rtiSubstitutions.isTrivialSubstitution(subclass, cls); 3032 return !_rtiSubstitutions.isTrivialSubstitution(subclass, cls);
3014 }); 3033 });
3015 } 3034 }
3016 3035
3017 @override 3036 @override
3018 void visitRef(HRef node) { 3037 void visitRef(HRef node) {
3019 visit(node.value); 3038 visit(node.value);
3020 } 3039 }
3021 } 3040 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698