OLD | NEW |
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 Loading... |
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 Loading... |
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 Loading... |
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 } |
OLD | NEW |