OLD | NEW |
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 20 matching lines...) Expand all Loading... |
31 import '../resolution/semantic_visitor.dart'; | 31 import '../resolution/semantic_visitor.dart'; |
32 import '../resolution/tree_elements.dart' show TreeElements; | 32 import '../resolution/tree_elements.dart' show TreeElements; |
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 import 'codegen.dart'; | 41 import 'graph_builder.dart'; |
42 import 'nodes.dart'; | 42 import 'nodes.dart'; |
43 import 'optimize.dart'; | 43 import 'optimize.dart'; |
44 import 'types.dart'; | 44 import 'types.dart'; |
45 | 45 |
46 /// A synthetic local variable only used with the SSA graph. | 46 /// A synthetic local variable only used with the SSA graph. |
47 /// | 47 /// |
48 /// For instance used for holding return value of function or the exception of a | 48 /// For instance used for holding return value of function or the exception of a |
49 /// try-catch statement. | 49 /// try-catch statement. |
50 class SyntheticLocal extends Local { | 50 class SyntheticLocal extends Local { |
51 final String name; | 51 final String name; |
(...skipping 920 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
972 /** | 972 /** |
973 * This class builds SSA nodes for functions represented in AST. | 973 * This class builds SSA nodes for functions represented in AST. |
974 */ | 974 */ |
975 class SsaBuilder extends ast.Visitor | 975 class SsaBuilder extends ast.Visitor |
976 with | 976 with |
977 BaseImplementationOfCompoundsMixin, | 977 BaseImplementationOfCompoundsMixin, |
978 BaseImplementationOfSetIfNullsMixin, | 978 BaseImplementationOfSetIfNullsMixin, |
979 BaseImplementationOfSuperIndexSetIfNullMixin, | 979 BaseImplementationOfSuperIndexSetIfNullMixin, |
980 SemanticSendResolvedMixin, | 980 SemanticSendResolvedMixin, |
981 NewBulkMixin, | 981 NewBulkMixin, |
982 ErrorBulkMixin | 982 ErrorBulkMixin, |
| 983 GraphBuilder |
983 implements SemanticSendVisitor { | 984 implements SemanticSendVisitor { |
984 /// The element for which this SSA builder is being used. | 985 /// The element for which this SSA builder is being used. |
985 final Element target; | 986 final Element target; |
986 | 987 |
987 ResolvedAst resolvedAst; | 988 ResolvedAst resolvedAst; |
988 | 989 |
989 /// Used to report information about inlining (which occurs while building the | 990 /// Used to report information about inlining (which occurs while building the |
990 /// SSA graph), when dump-info is enabled. | 991 /// SSA graph), when dump-info is enabled. |
991 final InfoReporter infoReporter; | 992 final InfoReporter infoReporter; |
992 | 993 |
(...skipping 16 matching lines...) Expand all Loading... |
1009 final RuntimeTypes rti; | 1010 final RuntimeTypes rti; |
1010 | 1011 |
1011 SourceInformationBuilder sourceInformationBuilder; | 1012 SourceInformationBuilder sourceInformationBuilder; |
1012 | 1013 |
1013 bool inLazyInitializerExpression = false; | 1014 bool inLazyInitializerExpression = false; |
1014 | 1015 |
1015 // TODO(sigmund): make all comments /// instead of /* */ | 1016 // TODO(sigmund): make all comments /// instead of /* */ |
1016 /* This field is used by the native handler. */ | 1017 /* This field is used by the native handler. */ |
1017 final NativeEmitter nativeEmitter; | 1018 final NativeEmitter nativeEmitter; |
1018 | 1019 |
1019 /// Holds the resulting SSA graph. | |
1020 final HGraph graph = new HGraph(); | |
1021 | |
1022 /** | |
1023 * The current block to add instructions to. Might be null, if we are | |
1024 * visiting dead code, but see [isReachable]. | |
1025 */ | |
1026 HBasicBlock _current; | |
1027 | |
1028 HBasicBlock get current => _current; | |
1029 | |
1030 void set current(c) { | |
1031 isReachable = c != null; | |
1032 _current = c; | |
1033 } | |
1034 | |
1035 /** | |
1036 * The most recently opened block. Has the same value as [current] while | |
1037 * the block is open, but unlike [current], it isn't cleared when the | |
1038 * current block is closed. | |
1039 */ | |
1040 HBasicBlock lastOpenedBlock; | |
1041 | |
1042 /** | |
1043 * Indicates whether the current block is dead (because it has a throw or a | |
1044 * return further up). If this is false, then [current] may be null. If the | |
1045 * block is dead then it may also be aborted, but for simplicity we only | |
1046 * abort on statement boundaries, not in the middle of expressions. See | |
1047 * isAborted. | |
1048 */ | |
1049 bool isReachable = true; | |
1050 | |
1051 /** | 1020 /** |
1052 * True if we are visiting the expression of a throw statement; we assume this | 1021 * True if we are visiting the expression of a throw statement; we assume this |
1053 * is a slow path. | 1022 * is a slow path. |
1054 */ | 1023 */ |
1055 bool inExpressionOfThrow = false; | 1024 bool inExpressionOfThrow = false; |
1056 | 1025 |
1057 /** | 1026 /** |
1058 * The loop nesting is consulted when inlining a function invocation in | 1027 * The loop nesting is consulted when inlining a function invocation in |
1059 * [tryInlineMethod]. The inlining heuristics take this information into | 1028 * [tryInlineMethod]. The inlining heuristics take this information into |
1060 * account. | 1029 * account. |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1176 } else { | 1145 } else { |
1177 result = buildLazyInitializer(target); | 1146 result = buildLazyInitializer(target); |
1178 } | 1147 } |
1179 } else { | 1148 } else { |
1180 reporter.internalError(target, 'Unexpected element kind $target.'); | 1149 reporter.internalError(target, 'Unexpected element kind $target.'); |
1181 } | 1150 } |
1182 assert(result.isValid()); | 1151 assert(result.isValid()); |
1183 return result; | 1152 return result; |
1184 } | 1153 } |
1185 | 1154 |
1186 HBasicBlock addNewBlock() { | |
1187 HBasicBlock block = graph.addNewBlock(); | |
1188 // If adding a new block during building of an expression, it is due to | |
1189 // conditional expressions or short-circuit logical operators. | |
1190 return block; | |
1191 } | |
1192 | |
1193 void open(HBasicBlock block) { | |
1194 block.open(); | |
1195 current = block; | |
1196 lastOpenedBlock = block; | |
1197 } | |
1198 | |
1199 HBasicBlock close(HControlFlow end) { | |
1200 HBasicBlock result = current; | |
1201 current.close(end); | |
1202 current = null; | |
1203 return result; | |
1204 } | |
1205 | |
1206 HBasicBlock closeAndGotoExit(HControlFlow end) { | |
1207 HBasicBlock result = current; | |
1208 current.close(end); | |
1209 current = null; | |
1210 result.addSuccessor(graph.exit); | |
1211 return result; | |
1212 } | |
1213 | |
1214 void goto(HBasicBlock from, HBasicBlock to) { | |
1215 from.close(new HGoto()); | |
1216 from.addSuccessor(to); | |
1217 } | |
1218 | |
1219 bool isAborted() { | |
1220 return current == null; | |
1221 } | |
1222 | |
1223 /** | |
1224 * Creates a new block, transitions to it from any current block, and | |
1225 * opens the new block. | |
1226 */ | |
1227 HBasicBlock openNewBlock() { | |
1228 HBasicBlock newBlock = addNewBlock(); | |
1229 if (!isAborted()) goto(current, newBlock); | |
1230 open(newBlock); | |
1231 return newBlock; | |
1232 } | |
1233 | |
1234 void add(HInstruction instruction) { | |
1235 current.add(instruction); | |
1236 } | |
1237 | |
1238 void addWithPosition(HInstruction instruction, ast.Node node) { | 1155 void addWithPosition(HInstruction instruction, ast.Node node) { |
1239 add(attachPosition(instruction, node)); | 1156 add(attachPosition(instruction, node)); |
1240 } | 1157 } |
1241 | 1158 |
1242 /** | 1159 /** |
1243 * Returns a complete argument list for a call of [function]. | 1160 * Returns a complete argument list for a call of [function]. |
1244 */ | 1161 */ |
1245 List<HInstruction> completeSendArgumentsList( | 1162 List<HInstruction> completeSendArgumentsList( |
1246 FunctionElement function, | 1163 FunctionElement function, |
1247 Selector selector, | 1164 Selector selector, |
(...skipping 421 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1669 if (backend.isJsInterop(functionElement)) { | 1586 if (backend.isJsInterop(functionElement)) { |
1670 push(invokeJsInteropFunction(functionElement, parameters.values.toList(), | 1587 push(invokeJsInteropFunction(functionElement, parameters.values.toList(), |
1671 sourceInformationBuilder.buildGeneric(function))); | 1588 sourceInformationBuilder.buildGeneric(function))); |
1672 var value = pop(); | 1589 var value = pop(); |
1673 closeAndGotoExit(new HReturn( | 1590 closeAndGotoExit(new HReturn( |
1674 value, sourceInformationBuilder.buildReturn(functionElement.node))); | 1591 value, sourceInformationBuilder.buildReturn(functionElement.node))); |
1675 return closeFunction(); | 1592 return closeFunction(); |
1676 } | 1593 } |
1677 assert(invariant(functionElement, !function.modifiers.isExternal)); | 1594 assert(invariant(functionElement, !function.modifiers.isExternal)); |
1678 | 1595 |
1679 // If [functionElement] is `operator==` we explicitely add a null check at | 1596 // If [functionElement] is `operator==` we explicitly add a null check at |
1680 // the beginning of the method. This is to avoid having call sites do the | 1597 // the beginning of the method. This is to avoid having call sites do the |
1681 // null check. | 1598 // null check. |
1682 if (name == '==') { | 1599 if (name == '==') { |
1683 if (!backend.operatorEqHandlesNullArgument(functionElement)) { | 1600 if (!backend.operatorEqHandlesNullArgument(functionElement)) { |
1684 handleIf(function, visitCondition: () { | 1601 handleIf(function, visitCondition: () { |
1685 HParameterValue parameter = parameters.values.first; | 1602 HParameterValue parameter = parameters.values.first; |
1686 push(new HIdentity(parameter, graph.addConstantNull(compiler), null, | 1603 push(new HIdentity(parameter, graph.addConstantNull(compiler), null, |
1687 backend.boolType)); | 1604 backend.boolType)); |
1688 }, visitThen: () { | 1605 }, visitThen: () { |
1689 closeAndGotoExit(new HReturn(graph.addConstantBool(false, compiler), | 1606 closeAndGotoExit(new HReturn(graph.addConstantBool(false, compiler), |
1690 sourceInformationBuilder.buildImplicitReturn(functionElement))); | 1607 sourceInformationBuilder.buildImplicitReturn(functionElement))); |
1691 }, | 1608 }, |
1692 visitElse: null, | 1609 visitElse: null, |
1693 sourceInformation: sourceInformationBuilder.buildIf(function.body)); | 1610 sourceInformation: sourceInformationBuilder.buildIf(function.body)); |
1694 } | 1611 } |
1695 } | 1612 } |
1696 if (const bool.fromEnvironment('unreachable-throw') == true) { | 1613 if (const bool.fromEnvironment('unreachable-throw')) { |
1697 var emptyParameters = | 1614 var emptyParameters = |
1698 parameters.values.where((p) => p.instructionType.isEmpty); | 1615 parameters.values.where((p) => p.instructionType.isEmpty); |
1699 if (emptyParameters.length > 0) { | 1616 if (emptyParameters.length > 0) { |
1700 addComment('${emptyParameters} inferred as [empty]'); | 1617 addComment('${emptyParameters} inferred as [empty]'); |
1701 pushInvokeStatic(function.body, helpers.assertUnreachableMethod, []); | 1618 pushInvokeStatic(function.body, helpers.assertUnreachableMethod, []); |
1702 pop(); | 1619 pop(); |
1703 return closeFunction(); | 1620 return closeFunction(); |
1704 } | 1621 } |
1705 } | 1622 } |
1706 function.body.accept(this); | 1623 function.body.accept(this); |
(...skipping 6899 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
8606 const _LoopTypeVisitor(); | 8523 const _LoopTypeVisitor(); |
8607 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; | 8524 int visitNode(ast.Node node) => HLoopBlockInformation.NOT_A_LOOP; |
8608 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; | 8525 int visitWhile(ast.While node) => HLoopBlockInformation.WHILE_LOOP; |
8609 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; | 8526 int visitFor(ast.For node) => HLoopBlockInformation.FOR_LOOP; |
8610 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; | 8527 int visitDoWhile(ast.DoWhile node) => HLoopBlockInformation.DO_WHILE_LOOP; |
8611 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; | 8528 int visitAsyncForIn(ast.AsyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; |
8612 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; | 8529 int visitSyncForIn(ast.SyncForIn node) => HLoopBlockInformation.FOR_IN_LOOP; |
8613 int visitSwitchStatement(ast.SwitchStatement node) => | 8530 int visitSwitchStatement(ast.SwitchStatement node) => |
8614 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; | 8531 HLoopBlockInformation.SWITCH_CONTINUE_LOOP; |
8615 } | 8532 } |
OLD | NEW |