| 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 | 4 |
| 5 library dart2js.ir_builder; | 5 library dart2js.ir_builder; |
| 6 | 6 |
| 7 import '../closure.dart' as closure; | 7 import '../closure.dart' as closure; |
| 8 import '../common.dart'; | 8 import '../common.dart'; |
| 9 import '../common/names.dart' show | 9 import '../common/names.dart' show |
| 10 Names, | 10 Names, |
| (...skipping 191 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 202 /// Call [enterTry] before translating a try block and call this function | 202 /// Call [enterTry] before translating a try block and call this function |
| 203 /// after translating it. | 203 /// after translating it. |
| 204 void leaveTry() { | 204 void leaveTry() { |
| 205 _boxedTryVariables.removeLast(); | 205 _boxedTryVariables.removeLast(); |
| 206 } | 206 } |
| 207 | 207 |
| 208 void _buildTryExit(IrBuilder builder) { | 208 void _buildTryExit(IrBuilder builder) { |
| 209 for (Iterable<LocalVariableElement> boxedOnEntry in _boxedTryVariables) { | 209 for (Iterable<LocalVariableElement> boxedOnEntry in _boxedTryVariables) { |
| 210 for (LocalVariableElement variable in boxedOnEntry) { | 210 for (LocalVariableElement variable in boxedOnEntry) { |
| 211 assert(builder.isInMutableVariable(variable)); | 211 assert(builder.isInMutableVariable(variable)); |
| 212 ir.Primitive value = builder.buildLocalVariableGet(variable); | 212 ir.Primitive value = builder.buildLocalGet(variable); |
| 213 builder.environment.update(variable, value); | 213 builder.environment.update(variable, value); |
| 214 } | 214 } |
| 215 } | 215 } |
| 216 } | 216 } |
| 217 | 217 |
| 218 /// True if a jump inserted now will escape from a try block. | 218 /// True if a jump inserted now will escape from a try block. |
| 219 /// | 219 /// |
| 220 /// Concretely, this is true when [enterTry] has been called without | 220 /// Concretely, this is true when [enterTry] has been called without |
| 221 /// its corresponding [leaveTry] call. | 221 /// its corresponding [leaveTry] call. |
| 222 bool get isEscapingTry => _boxedTryVariables.isNotEmpty; | 222 bool get isEscapingTry => _boxedTryVariables.isNotEmpty; |
| (...skipping 525 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 748 /// Creates a non-constant list literal of the provided [type] and with the | 748 /// Creates a non-constant list literal of the provided [type] and with the |
| 749 /// provided [values]. | 749 /// provided [values]. |
| 750 ir.Primitive buildListLiteral(InterfaceType type, | 750 ir.Primitive buildListLiteral(InterfaceType type, |
| 751 Iterable<ir.Primitive> values, | 751 Iterable<ir.Primitive> values, |
| 752 {TypeMask allocationSiteType}) { | 752 {TypeMask allocationSiteType}) { |
| 753 assert(isOpen); | 753 assert(isOpen); |
| 754 return addPrimitive(new ir.LiteralList(type, values.toList(), | 754 return addPrimitive(new ir.LiteralList(type, values.toList(), |
| 755 allocationSiteType: allocationSiteType)); | 755 allocationSiteType: allocationSiteType)); |
| 756 } | 756 } |
| 757 | 757 |
| 758 /// Creates a non-constant map literal of the provided [type] and with the | |
| 759 /// entries build from the [keys] and [values] using [build]. | |
| 760 ir.Primitive buildMapLiteral(InterfaceType type, | |
| 761 Iterable keys, | |
| 762 Iterable values, | |
| 763 BuildFunction build) { | |
| 764 assert(isOpen); | |
| 765 List<ir.LiteralMapEntry> entries = <ir.LiteralMapEntry>[]; | |
| 766 Iterator key = keys.iterator; | |
| 767 Iterator value = values.iterator; | |
| 768 while (key.moveNext() && value.moveNext()) { | |
| 769 entries.add(new ir.LiteralMapEntry( | |
| 770 build(key.current), build(value.current))); | |
| 771 } | |
| 772 assert(!key.moveNext() && !value.moveNext()); | |
| 773 return addPrimitive(new ir.LiteralMap(type, entries)); | |
| 774 } | |
| 775 | |
| 776 /// Creates a conditional expression with the provided [condition] where the | 758 /// Creates a conditional expression with the provided [condition] where the |
| 777 /// then and else expression are created through the [buildThenExpression] | 759 /// then and else expression are created through the [buildThenExpression] |
| 778 /// and [buildElseExpression] functions, respectively. | 760 /// and [buildElseExpression] functions, respectively. |
| 779 ir.Primitive buildConditional( | 761 ir.Primitive buildConditional( |
| 780 ir.Primitive condition, | 762 ir.Primitive condition, |
| 781 ir.Primitive buildThenExpression(IrBuilder builder), | 763 ir.Primitive buildThenExpression(IrBuilder builder), |
| 782 ir.Primitive buildElseExpression(IrBuilder builder)) { | 764 ir.Primitive buildElseExpression(IrBuilder builder)) { |
| 783 assert(isOpen); | 765 assert(isOpen); |
| 784 | 766 |
| 785 // The then and else expressions are delimited. | 767 // The then and else expressions are delimited. |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 976 TypeMask mask, | 958 TypeMask mask, |
| 977 ir.Primitive index, | 959 ir.Primitive index, |
| 978 ir.Primitive value, | 960 ir.Primitive value, |
| 979 {SourceInformation sourceInformation}) { | 961 {SourceInformation sourceInformation}) { |
| 980 _buildInvokeDynamic( | 962 _buildInvokeDynamic( |
| 981 receiver, new Selector.indexSet(), mask, <ir.Primitive>[index, value], | 963 receiver, new Selector.indexSet(), mask, <ir.Primitive>[index, value], |
| 982 sourceInformation); | 964 sourceInformation); |
| 983 return value; | 965 return value; |
| 984 } | 966 } |
| 985 | 967 |
| 986 /// Create a read access of the [local] variable or parameter. | |
| 987 ir.Primitive buildLocalVariableGet(LocalElement local) { | |
| 988 // TODO(johnniwinther): Separate function access from variable access. | |
| 989 return _buildLocalGet(local); | |
| 990 } | |
| 991 | |
| 992 /// Create a read access of the local [function], i.e. closurization of | |
| 993 /// [function]. | |
| 994 ir.Primitive buildLocalFunctionGet(LocalFunctionElement function) { | |
| 995 // TODO(johnniwinther): Separate function access from variable access. | |
| 996 return _buildLocalGet(function); | |
| 997 } | |
| 998 | |
| 999 /// Create an invocation of the the [local] variable or parameter where | |
| 1000 /// argument structure is defined by [callStructure] and the argument values | |
| 1001 /// are defined by [arguments]. | |
| 1002 ir.Primitive buildLocalVariableInvocation( | |
| 1003 LocalVariableElement local, | |
| 1004 CallStructure callStructure, | |
| 1005 List<ir.Primitive> arguments, | |
| 1006 {SourceInformation callSourceInformation}) { | |
| 1007 return buildCallInvocation( | |
| 1008 buildLocalVariableGet(local), callStructure, arguments, | |
| 1009 sourceInformation: callSourceInformation); | |
| 1010 } | |
| 1011 | |
| 1012 /// Create an invocation of the local [function] where argument structure is | 968 /// Create an invocation of the local [function] where argument structure is |
| 1013 /// defined by [callStructure] and the argument values are defined by | 969 /// defined by [callStructure] and the argument values are defined by |
| 1014 /// [arguments]. | 970 /// [arguments]. |
| 1015 ir.Primitive buildLocalFunctionInvocation( | 971 ir.Primitive buildLocalFunctionInvocation( |
| 1016 LocalFunctionElement function, | 972 LocalFunctionElement function, |
| 1017 CallStructure callStructure, | 973 CallStructure callStructure, |
| 1018 List<ir.Primitive> arguments, | 974 List<ir.Primitive> arguments, |
| 1019 SourceInformation sourceInformation) { | 975 SourceInformation sourceInformation) { |
| 1020 // TODO(johnniwinther): Maybe this should have its own ir node. | 976 // TODO(johnniwinther): Maybe this should have its own ir node. |
| 1021 return buildCallInvocation( | 977 return buildCallInvocation( |
| 1022 buildLocalFunctionGet(function), callStructure, arguments, | 978 buildLocalGet(function), callStructure, arguments, |
| 1023 sourceInformation: sourceInformation); | 979 sourceInformation: sourceInformation); |
| 1024 } | 980 } |
| 1025 | 981 |
| 1026 /// Create a static invocation of [function]. | 982 /// Create a static invocation of [function]. |
| 1027 /// | 983 /// |
| 1028 /// The arguments are not named and their values are defined by [arguments]. | 984 /// The arguments are not named and their values are defined by [arguments]. |
| 1029 ir.Primitive buildStaticFunctionInvocation( | 985 ir.Primitive buildStaticFunctionInvocation( |
| 1030 MethodElement function, | 986 MethodElement function, |
| 1031 List<ir.Primitive> arguments, | 987 List<ir.Primitive> arguments, |
| 1032 {SourceInformation sourceInformation}) { | 988 {SourceInformation sourceInformation}) { |
| 1033 Selector selector = new Selector.call( | 989 Selector selector = new Selector.call( |
| 1034 function.memberName, new CallStructure(arguments.length)); | 990 function.memberName, new CallStructure(arguments.length)); |
| 1035 return buildInvokeStatic(function, selector, arguments, sourceInformation); | 991 return buildInvokeStatic(function, selector, arguments, sourceInformation); |
| 1036 } | 992 } |
| 1037 | 993 |
| 1038 /// Create a read access of the static [field]. | |
| 1039 ir.Primitive buildStaticFieldGet(FieldElement field, | |
| 1040 SourceInformation sourceInformation) { | |
| 1041 return addPrimitive(new ir.GetStatic(field, sourceInformation)); | |
| 1042 } | |
| 1043 | |
| 1044 /// Create a read access of a static [field] that might not have been | |
| 1045 /// initialized yet. | |
| 1046 ir.Primitive buildStaticFieldLazyGet(FieldElement field, | |
| 1047 SourceInformation sourceInformation) { | |
| 1048 return addPrimitive(new ir.GetLazyStatic(field, sourceInformation)); | |
| 1049 } | |
| 1050 | |
| 1051 /// Create a getter invocation of the static [getter]. | 994 /// Create a getter invocation of the static [getter]. |
| 1052 ir.Primitive buildStaticGetterGet(MethodElement getter, | 995 ir.Primitive buildStaticGetterGet(MethodElement getter, |
| 1053 SourceInformation sourceInformation) { | 996 SourceInformation sourceInformation) { |
| 1054 Selector selector = new Selector.getter(getter.memberName); | 997 Selector selector = new Selector.getter(getter.memberName); |
| 1055 return buildInvokeStatic( | 998 return buildInvokeStatic( |
| 1056 getter, selector, const <ir.Primitive>[], sourceInformation); | 999 getter, selector, const <ir.Primitive>[], sourceInformation); |
| 1057 } | 1000 } |
| 1058 | 1001 |
| 1059 /// Create a read access of the static [function], i.e. a closurization of | |
| 1060 /// [function]. | |
| 1061 ir.Primitive buildStaticFunctionGet(MethodElement function, | |
| 1062 {SourceInformation sourceInformation}) { | |
| 1063 return addPrimitive(new ir.GetStatic(function, sourceInformation)); | |
| 1064 } | |
| 1065 | |
| 1066 /// Create a write access to the static [field] with the [value]. | 1002 /// Create a write access to the static [field] with the [value]. |
| 1067 ir.Primitive buildStaticFieldSet(FieldElement field, | 1003 ir.Primitive buildStaticFieldSet(FieldElement field, |
| 1068 ir.Primitive value, | 1004 ir.Primitive value, |
| 1069 [SourceInformation sourceInformation]) { | 1005 [SourceInformation sourceInformation]) { |
| 1070 addPrimitive(new ir.SetStatic(field, value, sourceInformation)); | 1006 addPrimitive(new ir.SetStatic(field, value, sourceInformation)); |
| 1071 return value; | 1007 return value; |
| 1072 } | 1008 } |
| 1073 | 1009 |
| 1074 /// Create a setter invocation of the static [setter] with the [value]. | 1010 /// Create a setter invocation of the static [setter] with the [value]. |
| 1075 ir.Primitive buildStaticSetterSet(MethodElement setter, | 1011 ir.Primitive buildStaticSetterSet(MethodElement setter, |
| (...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1436 List<ir.Primitive> value = <ir.Primitive>[currentValue]; | 1372 List<ir.Primitive> value = <ir.Primitive>[currentValue]; |
| 1437 // Note the order of the comparisons below. It can be the case that an | 1373 // Note the order of the comparisons below. It can be the case that an |
| 1438 // element isError and isMalformed. | 1374 // element isError and isMalformed. |
| 1439 if (Elements.isError(variableElement)) { | 1375 if (Elements.isError(variableElement)) { |
| 1440 bodyBuilder.buildStaticNoSuchMethod(selector, value); | 1376 bodyBuilder.buildStaticNoSuchMethod(selector, value); |
| 1441 } else { | 1377 } else { |
| 1442 bodyBuilder.buildErroneousInvocation(variableElement, selector, value); | 1378 bodyBuilder.buildErroneousInvocation(variableElement, selector, value); |
| 1443 } | 1379 } |
| 1444 } else if (Elements.isStaticOrTopLevel(variableElement)) { | 1380 } else if (Elements.isStaticOrTopLevel(variableElement)) { |
| 1445 if (variableElement.isField) { | 1381 if (variableElement.isField) { |
| 1446 bodyBuilder.buildStaticFieldSet(variableElement, currentValue); | 1382 bodyBuilder.addPrimitive( |
| 1383 new ir.SetStatic(variableElement, currentValue)); |
| 1447 } else { | 1384 } else { |
| 1448 bodyBuilder.buildStaticSetterSet(variableElement, currentValue); | 1385 bodyBuilder.buildStaticSetterSet(variableElement, currentValue); |
| 1449 } | 1386 } |
| 1450 } else { | 1387 } else { |
| 1451 ir.Primitive receiver = bodyBuilder.buildThis(); | 1388 ir.Primitive receiver = bodyBuilder.buildThis(); |
| 1452 assert(receiver != null); | 1389 assert(receiver != null); |
| 1453 bodyBuilder.buildDynamicSet( | 1390 bodyBuilder.buildDynamicSet( |
| 1454 receiver, variableSelector, variableMask, currentValue); | 1391 receiver, variableSelector, variableMask, currentValue); |
| 1455 } | 1392 } |
| 1456 | 1393 |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1750 ir.Expression body)) { | 1687 ir.Expression body)) { |
| 1751 JumpCollector join = new ForwardJumpCollector(environment); | 1688 JumpCollector join = new ForwardJumpCollector(environment); |
| 1752 IrBuilder tryCatchBuilder = makeDelimitedBuilder(); | 1689 IrBuilder tryCatchBuilder = makeDelimitedBuilder(); |
| 1753 | 1690 |
| 1754 // Variables treated as mutable in a try are not mutable outside of it. | 1691 // Variables treated as mutable in a try are not mutable outside of it. |
| 1755 // Work with a copy of the outer builder's mutable variables. | 1692 // Work with a copy of the outer builder's mutable variables. |
| 1756 tryCatchBuilder.mutableVariables = | 1693 tryCatchBuilder.mutableVariables = |
| 1757 new Map<Local, ir.MutableVariable>.from(mutableVariables); | 1694 new Map<Local, ir.MutableVariable>.from(mutableVariables); |
| 1758 for (LocalVariableElement variable in variables.boxedOnEntry) { | 1695 for (LocalVariableElement variable in variables.boxedOnEntry) { |
| 1759 assert(!tryCatchBuilder.isInMutableVariable(variable)); | 1696 assert(!tryCatchBuilder.isInMutableVariable(variable)); |
| 1760 ir.Primitive value = tryCatchBuilder.buildLocalVariableGet(variable); | 1697 ir.Primitive value = tryCatchBuilder.buildLocalGet(variable); |
| 1761 tryCatchBuilder.makeMutableVariable(variable); | 1698 tryCatchBuilder.makeMutableVariable(variable); |
| 1762 tryCatchBuilder.declareLocalVariable(variable, initialValue: value); | 1699 tryCatchBuilder.declareLocalVariable(variable, initialValue: value); |
| 1763 } | 1700 } |
| 1764 | 1701 |
| 1765 IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder(); | 1702 IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder(); |
| 1766 enterTry(tryBuilder); | 1703 enterTry(tryBuilder); |
| 1767 buildTryBlock(tryBuilder); | 1704 buildTryBlock(tryBuilder); |
| 1768 if (tryBuilder.isOpen) { | 1705 if (tryBuilder.isOpen) { |
| 1769 join.enterTry(variables.boxedOnEntry); | 1706 join.enterTry(variables.boxedOnEntry); |
| 1770 tryBuilder.jumpTo(join); | 1707 tryBuilder.jumpTo(join); |
| 1771 join.leaveTry(); | 1708 join.leaveTry(); |
| 1772 } | 1709 } |
| 1773 leaveTry(tryBuilder); | 1710 leaveTry(tryBuilder); |
| 1774 | 1711 |
| 1775 IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder(); | 1712 IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder(); |
| 1776 for (LocalVariableElement variable in variables.boxedOnEntry) { | 1713 for (LocalVariableElement variable in variables.boxedOnEntry) { |
| 1777 assert(catchBuilder.isInMutableVariable(variable)); | 1714 assert(catchBuilder.isInMutableVariable(variable)); |
| 1778 ir.Primitive value = catchBuilder.buildLocalVariableGet(variable); | 1715 ir.Primitive value = catchBuilder.buildLocalGet(variable); |
| 1779 // After this point, the variables that were boxed on entry to the try | 1716 // After this point, the variables that were boxed on entry to the try |
| 1780 // are no longer treated as mutable. | 1717 // are no longer treated as mutable. |
| 1781 catchBuilder.removeMutableVariable(variable); | 1718 catchBuilder.removeMutableVariable(variable); |
| 1782 catchBuilder.environment.update(variable, value); | 1719 catchBuilder.environment.update(variable, value); |
| 1783 } | 1720 } |
| 1784 | 1721 |
| 1785 List<ir.Parameter> catchParameters = buildCatch(catchBuilder, join); | 1722 List<ir.Parameter> catchParameters = buildCatch(catchBuilder, join); |
| 1786 ir.Continuation catchContinuation = new ir.Continuation(catchParameters); | 1723 ir.Continuation catchContinuation = new ir.Continuation(catchParameters); |
| 1787 catchContinuation.body = catchBuilder._root; | 1724 catchContinuation.body = catchBuilder._root; |
| 1788 tryCatchBuilder.add( | 1725 tryCatchBuilder.add( |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2470 value = buildTypeVariableAccess(variable.typeVariable); | 2407 value = buildTypeVariableAccess(variable.typeVariable); |
| 2471 } else { | 2408 } else { |
| 2472 value = environment.lookup(field.local); | 2409 value = environment.lookup(field.local); |
| 2473 } | 2410 } |
| 2474 arguments.add(value); | 2411 arguments.add(value); |
| 2475 } | 2412 } |
| 2476 return addPrimitive(new ir.CreateInstance( | 2413 return addPrimitive(new ir.CreateInstance( |
| 2477 classElement, arguments, const <ir.Primitive>[], sourceInformation)); | 2414 classElement, arguments, const <ir.Primitive>[], sourceInformation)); |
| 2478 } | 2415 } |
| 2479 | 2416 |
| 2480 /// Create a read access of [local] variable or parameter. | 2417 /// Create a read access of [local] function, variable, or parameter. |
| 2481 ir.Primitive _buildLocalGet(LocalElement local) { | 2418 ir.Primitive buildLocalGet(LocalElement local) { |
| 2482 assert(isOpen); | 2419 assert(isOpen); |
| 2483 ClosureLocation location = state.boxedVariables[local]; | 2420 ClosureLocation location = state.boxedVariables[local]; |
| 2484 if (location != null) { | 2421 if (location != null) { |
| 2485 ir.Primitive result = new ir.GetField(environment.lookup(location.box), | 2422 ir.Primitive result = new ir.GetField(environment.lookup(location.box), |
| 2486 location.field); | 2423 location.field); |
| 2487 result.useElementAsHint(local); | 2424 result.useElementAsHint(local); |
| 2488 return addPrimitive(result); | 2425 return addPrimitive(result); |
| 2489 } else if (isInMutableVariable(local)) { | 2426 } else if (isInMutableVariable(local)) { |
| 2490 return addPrimitive(new ir.GetMutable(getMutableVariable(local))); | 2427 return addPrimitive(new ir.GetMutable(getMutableVariable(local))); |
| 2491 } else { | 2428 } else { |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2897 } | 2834 } |
| 2898 | 2835 |
| 2899 class SwitchCaseInfo { | 2836 class SwitchCaseInfo { |
| 2900 final List<ir.Primitive> constants = <ir.Primitive>[]; | 2837 final List<ir.Primitive> constants = <ir.Primitive>[]; |
| 2901 final SubbuildFunction buildBody; | 2838 final SubbuildFunction buildBody; |
| 2902 | 2839 |
| 2903 SwitchCaseInfo(this.buildBody); | 2840 SwitchCaseInfo(this.buildBody); |
| 2904 | 2841 |
| 2905 void addConstant(ir.Primitive constant) => constants.add(constant); | 2842 void addConstant(ir.Primitive constant) => constants.add(constant); |
| 2906 } | 2843 } |
| OLD | NEW |