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

Side by Side Diff: pkg/compiler/lib/src/cps_ir/cps_ir_nodes.dart

Issue 1251083002: dart2js cps: Avoid deep recursion using trampolines and basic blocks. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Rebase Created 5 years, 5 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) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, 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 library dart2js.ir_nodes; 4 library dart2js.ir_nodes;
5 5
6 import '../constants/values.dart' as values show ConstantValue; 6 import '../constants/values.dart' as values show ConstantValue;
7 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType; 7 import '../dart_types.dart' show DartType, InterfaceType, TypeVariableType;
8 import '../elements/elements.dart'; 8 import '../elements/elements.dart';
9 import '../io/source_information.dart' show SourceInformation; 9 import '../io/source_information.dart' show SourceInformation;
10 import '../types/types.dart' show TypeMask; 10 import '../types/types.dart' show TypeMask;
(...skipping 1132 matching lines...) Expand 10 before | Expand all | Expand 10 after
1143 T visitGetIndex(GetIndex node); 1143 T visitGetIndex(GetIndex node);
1144 T visitSetIndex(SetIndex node); 1144 T visitSetIndex(SetIndex node);
1145 1145
1146 // Conditions. 1146 // Conditions.
1147 T visitIsTrue(IsTrue node); 1147 T visitIsTrue(IsTrue node);
1148 1148
1149 // Support for literal foreign code. 1149 // Support for literal foreign code.
1150 T visitForeignCode(ForeignCode node); 1150 T visitForeignCode(ForeignCode node);
1151 } 1151 }
1152 1152
1153 /// Recursively visits the entire CPS term, and calls abstract `process*` 1153 /// Visits all non-recursive children of a CPS term, i.e. anything
1154 /// (i.e. `processLetPrim`) functions in pre-order. 1154 /// not of type [Expression] or [Continuation].
1155 class RecursiveVisitor implements Visitor { 1155 ///
1156 const RecursiveVisitor(); 1156 /// Note that the non-recursive nodes can contain other nodes inside of them,
1157 /// e.g. [Branch] contains an [IsTrue] which contains a [Reference].
1158 ///
1159 /// The `process*` methods are called in pre-order for every node visited.
1160 /// These can be overridden without disrupting the visitor traversal.
1161 class LeafVisitor implements Visitor {
1162 const LeafVisitor();
1157 1163
1158 visit(Node node) => node.accept(this); 1164 visit(Node node) => node.accept(this);
1159 1165
1160 processReference(Reference ref) {} 1166 processReference(Reference ref) {}
1161 1167
1162 processFunctionDefinition(FunctionDefinition node) {} 1168 processFunctionDefinition(FunctionDefinition node) {}
1163 visitFunctionDefinition(FunctionDefinition node) { 1169 visitFunctionDefinition(FunctionDefinition node) {
1164 processFunctionDefinition(node); 1170 processFunctionDefinition(node);
1165 if (node.thisParameter != null) visit(node.thisParameter); 1171 if (node.thisParameter != null) visit(node.thisParameter);
1166 node.parameters.forEach(visit); 1172 node.parameters.forEach(visit);
1167 visit(node.returnContinuation); 1173 visit(node.returnContinuation);
1168 visit(node.body);
1169 } 1174 }
1170 1175
1171 // Expressions. 1176 // Expressions.
1172 1177
1173 processLetPrim(LetPrim node) {} 1178 processLetPrim(LetPrim node) {}
1174 visitLetPrim(LetPrim node) { 1179 visitLetPrim(LetPrim node) {
1175 processLetPrim(node); 1180 processLetPrim(node);
1176 visit(node.primitive); 1181 visit(node.primitive);
1177 visit(node.body);
1178 } 1182 }
1179 1183
1180 processLetCont(LetCont node) {} 1184 processLetCont(LetCont node) {}
1181 visitLetCont(LetCont node) { 1185 visitLetCont(LetCont node) {
1182 processLetCont(node); 1186 processLetCont(node);
1183 node.continuations.forEach(visit); 1187 node.continuations.forEach(visit);
1184 visit(node.body);
1185 } 1188 }
1186 1189
1187 processLetHandler(LetHandler node) {} 1190 processLetHandler(LetHandler node) {}
1188 visitLetHandler(LetHandler node) { 1191 visitLetHandler(LetHandler node) {
1189 processLetHandler(node); 1192 processLetHandler(node);
1190 visit(node.handler);
1191 visit(node.body);
1192 } 1193 }
1193 1194
1194 processLetMutable(LetMutable node) {} 1195 processLetMutable(LetMutable node) {}
1195 visitLetMutable(LetMutable node) { 1196 visitLetMutable(LetMutable node) {
1196 processLetMutable(node); 1197 processLetMutable(node);
1197 visit(node.variable); 1198 visit(node.variable);
1198 processReference(node.value); 1199 processReference(node.value);
1199 visit(node.body);
1200 } 1200 }
1201 1201
1202 processInvokeStatic(InvokeStatic node) {} 1202 processInvokeStatic(InvokeStatic node) {}
1203 visitInvokeStatic(InvokeStatic node) { 1203 visitInvokeStatic(InvokeStatic node) {
1204 processInvokeStatic(node); 1204 processInvokeStatic(node);
1205 processReference(node.continuation); 1205 processReference(node.continuation);
1206 node.arguments.forEach(processReference); 1206 node.arguments.forEach(processReference);
1207 } 1207 }
1208 1208
1209 processInvokeContinuation(InvokeContinuation node) {} 1209 processInvokeContinuation(InvokeContinuation node) {}
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1322 1322
1323 processParameter(Parameter node) {} 1323 processParameter(Parameter node) {}
1324 visitParameter(Parameter node) { 1324 visitParameter(Parameter node) {
1325 processParameter(node); 1325 processParameter(node);
1326 } 1326 }
1327 1327
1328 processContinuation(Continuation node) {} 1328 processContinuation(Continuation node) {}
1329 visitContinuation(Continuation node) { 1329 visitContinuation(Continuation node) {
1330 processContinuation(node); 1330 processContinuation(node);
1331 node.parameters.forEach(visitParameter); 1331 node.parameters.forEach(visitParameter);
1332 if (node.body != null) visit(node.body);
1333 } 1332 }
1334 1333
1335 processIsTrue(IsTrue node) {} 1334 processIsTrue(IsTrue node) {}
1336 visitIsTrue(IsTrue node) { 1335 visitIsTrue(IsTrue node) {
1337 processIsTrue(node); 1336 processIsTrue(node);
1338 processReference(node.value); 1337 processReference(node.value);
1339 } 1338 }
1340 1339
1341 processInterceptor(Interceptor node) {} 1340 processInterceptor(Interceptor node) {}
1342 visitInterceptor(Interceptor node) { 1341 visitInterceptor(Interceptor node) {
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
1439 1438
1440 processSetIndex(SetIndex node) {} 1439 processSetIndex(SetIndex node) {}
1441 visitSetIndex(SetIndex node) { 1440 visitSetIndex(SetIndex node) {
1442 processSetIndex(node); 1441 processSetIndex(node);
1443 processReference(node.object); 1442 processReference(node.object);
1444 processReference(node.index); 1443 processReference(node.index);
1445 processReference(node.value); 1444 processReference(node.value);
1446 } 1445 }
1447 } 1446 }
1448 1447
1448 typedef void StackAction();
1449
1450 /// Calls `process*` for all nodes in a tree.
1451 /// For simple usage, only override the `process*` methods.
1452 ///
1453 /// To avoid deep recursion, this class uses an "action stack" containing
1454 /// callbacks to be invoked after the processing of some term has finished.
1455 ///
1456 /// To avoid excessive overhead from the action stack, basic blocks of
1457 /// interior nodes are iterated in a loop without using the action stack.
1458 ///
1459 /// The iteration order can be controlled by overriding the `traverse*`
1460 /// methods for [LetCont], [LetPrim], [LetMutable], [LetHandler] and
1461 /// [Continuation].
1462 ///
1463 /// The `traverse*` methods return the expression to visit next, and may
1464 /// push other subterms onto the stack using [push] or [pushAction] to visit
1465 /// them later. Actions pushed onto the stack will be executed after the body
1466 /// has been processed (and the stack actions it pushed have been executed).
1467 ///
1468 /// By default, the `traverse` methods visit all non-recursive subterms,
1469 /// push all bound continuations on the stack, and return the body of the term.
1470 ///
1471 /// Subclasses should not override the `visit` methods for the nodes that have
1472 /// a `traverse` method.
1473 class RecursiveVisitor extends LeafVisitor {
1474 List<StackAction> _stack = <StackAction>[];
1475
1476 void pushAction(StackAction callback) {
1477 _stack.add(callback);
1478 }
1479
1480 void push(Continuation cont) {
1481 _stack.add(() {
1482 if (cont.isReturnContinuation) {
1483 traverseContinuation(cont);
1484 } else {
1485 _processBlock(traverseContinuation(cont));
1486 }
1487 });
1488 }
1489
1490 visitFunctionDefinition(FunctionDefinition node) {
1491 processFunctionDefinition(node);
1492 if (node.thisParameter != null) visit(node.thisParameter);
1493 node.parameters.forEach(visit);
1494 visit(node.returnContinuation);
1495 visit(node.body);
1496 }
1497
1498 visitContinuation(Continuation cont) {
1499 if (cont.isReturnContinuation) {
1500 traverseContinuation(cont);
1501 } else {
1502 _trampoline(traverseContinuation(cont));
1503 }
1504 }
1505
1506 visitLetPrim(LetPrim node) => _trampoline(node);
1507 visitLetCont(LetCont node) => _trampoline(node);
1508 visitLetHandler(LetHandler node) => _trampoline(node);
1509 visitLetMutable(LetMutable node) => _trampoline(node);
1510
1511 Expression traverseContinuation(Continuation cont) {
1512 processContinuation(cont);
1513 cont.parameters.forEach(visitParameter);
1514 return cont.body;
1515 }
1516
1517 Expression traverseLetCont(LetCont node) {
1518 processLetCont(node);
1519 node.continuations.forEach(push);
1520 return node.body;
1521 }
1522
1523 Expression traverseLetHandler(LetHandler node) {
1524 processLetHandler(node);
1525 push(node.handler);
1526 return node.body;
1527 }
1528
1529 Expression traverseLetPrim(LetPrim node) {
1530 processLetPrim(node);
1531 visit(node.primitive);
1532 return node.body;
1533 }
1534
1535 Expression traverseLetMutable(LetMutable node) {
1536 processLetMutable(node);
1537 visit(node.variable);
1538 processReference(node.value);
1539 return node.body;
1540 }
1541
1542 void _trampoline(Expression node) {
1543 int initialHeight = _stack.length;
1544 _processBlock(node);
1545 while (_stack.length > initialHeight) {
1546 StackAction callback = _stack.removeLast();
1547 callback();
1548 }
1549 }
1550
1551 _processBlock(Expression node) {
1552 while (node is InteriorExpression) {
1553 if (node is LetCont) {
1554 node = traverseLetCont(node);
1555 } else if (node is LetHandler) {
1556 node = traverseLetHandler(node);
1557 } else if (node is LetPrim) {
1558 node = traverseLetPrim(node);
1559 } else {
1560 node = traverseLetMutable(node);
1561 }
1562 }
1563 visit(node);
1564 }
1565 }
1566
1449 /// Visit a just-deleted subterm and unlink all [Reference]s in it. 1567 /// Visit a just-deleted subterm and unlink all [Reference]s in it.
1450 class RemovalVisitor extends RecursiveVisitor { 1568 class RemovalVisitor extends RecursiveVisitor {
1451 const RemovalVisitor();
1452
1453 processReference(Reference reference) { 1569 processReference(Reference reference) {
1454 reference.unlink(); 1570 reference.unlink();
1455 } 1571 }
1456 1572
1457 static void remove(Node node) { 1573 static void remove(Node node) {
1458 (const RemovalVisitor()).visit(node); 1574 (new RemovalVisitor()).visit(node);
1459 } 1575 }
1460 } 1576 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/cps_ir/cps_ir_integrity.dart ('k') | pkg/compiler/lib/src/cps_ir/let_sinking.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698