| 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 |