| 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 362 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1438 List<ir.Primitive> value = <ir.Primitive>[currentValue]; | 1374 List<ir.Primitive> value = <ir.Primitive>[currentValue]; |
| 1439 // Note the order of the comparisons below. It can be the case that an | 1375 // Note the order of the comparisons below. It can be the case that an |
| 1440 // element isError and isMalformed. | 1376 // element isError and isMalformed. |
| 1441 if (Elements.isError(variableElement)) { | 1377 if (Elements.isError(variableElement)) { |
| 1442 bodyBuilder.buildStaticNoSuchMethod(selector, value); | 1378 bodyBuilder.buildStaticNoSuchMethod(selector, value); |
| 1443 } else { | 1379 } else { |
| 1444 bodyBuilder.buildErroneousInvocation(variableElement, selector, value); | 1380 bodyBuilder.buildErroneousInvocation(variableElement, selector, value); |
| 1445 } | 1381 } |
| 1446 } else if (Elements.isStaticOrTopLevel(variableElement)) { | 1382 } else if (Elements.isStaticOrTopLevel(variableElement)) { |
| 1447 if (variableElement.isField) { | 1383 if (variableElement.isField) { |
| 1448 bodyBuilder.buildStaticFieldSet(variableElement, currentValue); | 1384 bodyBuilder.addPrimitive( |
| 1385 new ir.SetStatic(variableElement, currentValue)); |
| 1449 } else { | 1386 } else { |
| 1450 bodyBuilder.buildStaticSetterSet(variableElement, currentValue); | 1387 bodyBuilder.buildStaticSetterSet(variableElement, currentValue); |
| 1451 } | 1388 } |
| 1452 } else { | 1389 } else { |
| 1453 ir.Primitive receiver = bodyBuilder.buildThis(); | 1390 ir.Primitive receiver = bodyBuilder.buildThis(); |
| 1454 assert(receiver != null); | 1391 assert(receiver != null); |
| 1455 bodyBuilder.buildDynamicSet( | 1392 bodyBuilder.buildDynamicSet( |
| 1456 receiver, variableSelector, variableMask, currentValue); | 1393 receiver, variableSelector, variableMask, currentValue); |
| 1457 } | 1394 } |
| 1458 | 1395 |
| (...skipping 293 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1752 ir.Expression body)) { | 1689 ir.Expression body)) { |
| 1753 JumpCollector join = new ForwardJumpCollector(environment); | 1690 JumpCollector join = new ForwardJumpCollector(environment); |
| 1754 IrBuilder tryCatchBuilder = makeDelimitedBuilder(); | 1691 IrBuilder tryCatchBuilder = makeDelimitedBuilder(); |
| 1755 | 1692 |
| 1756 // Variables treated as mutable in a try are not mutable outside of it. | 1693 // Variables treated as mutable in a try are not mutable outside of it. |
| 1757 // Work with a copy of the outer builder's mutable variables. | 1694 // Work with a copy of the outer builder's mutable variables. |
| 1758 tryCatchBuilder.mutableVariables = | 1695 tryCatchBuilder.mutableVariables = |
| 1759 new Map<Local, ir.MutableVariable>.from(mutableVariables); | 1696 new Map<Local, ir.MutableVariable>.from(mutableVariables); |
| 1760 for (LocalVariableElement variable in variables.boxedOnEntry) { | 1697 for (LocalVariableElement variable in variables.boxedOnEntry) { |
| 1761 assert(!tryCatchBuilder.isInMutableVariable(variable)); | 1698 assert(!tryCatchBuilder.isInMutableVariable(variable)); |
| 1762 ir.Primitive value = tryCatchBuilder.buildLocalVariableGet(variable); | 1699 ir.Primitive value = tryCatchBuilder.buildLocalGet(variable); |
| 1763 tryCatchBuilder.makeMutableVariable(variable); | 1700 tryCatchBuilder.makeMutableVariable(variable); |
| 1764 tryCatchBuilder.declareLocalVariable(variable, initialValue: value); | 1701 tryCatchBuilder.declareLocalVariable(variable, initialValue: value); |
| 1765 } | 1702 } |
| 1766 | 1703 |
| 1767 IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder(); | 1704 IrBuilder tryBuilder = tryCatchBuilder.makeDelimitedBuilder(); |
| 1768 enterTry(tryBuilder); | 1705 enterTry(tryBuilder); |
| 1769 buildTryBlock(tryBuilder); | 1706 buildTryBlock(tryBuilder); |
| 1770 if (tryBuilder.isOpen) { | 1707 if (tryBuilder.isOpen) { |
| 1771 join.enterTry(variables.boxedOnEntry); | 1708 join.enterTry(variables.boxedOnEntry); |
| 1772 tryBuilder.jumpTo(join); | 1709 tryBuilder.jumpTo(join); |
| 1773 join.leaveTry(); | 1710 join.leaveTry(); |
| 1774 } | 1711 } |
| 1775 leaveTry(tryBuilder); | 1712 leaveTry(tryBuilder); |
| 1776 | 1713 |
| 1777 IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder(); | 1714 IrBuilder catchBuilder = tryCatchBuilder.makeDelimitedBuilder(); |
| 1778 for (LocalVariableElement variable in variables.boxedOnEntry) { | 1715 for (LocalVariableElement variable in variables.boxedOnEntry) { |
| 1779 assert(catchBuilder.isInMutableVariable(variable)); | 1716 assert(catchBuilder.isInMutableVariable(variable)); |
| 1780 ir.Primitive value = catchBuilder.buildLocalVariableGet(variable); | 1717 ir.Primitive value = catchBuilder.buildLocalGet(variable); |
| 1781 // After this point, the variables that were boxed on entry to the try | 1718 // After this point, the variables that were boxed on entry to the try |
| 1782 // are no longer treated as mutable. | 1719 // are no longer treated as mutable. |
| 1783 catchBuilder.removeMutableVariable(variable); | 1720 catchBuilder.removeMutableVariable(variable); |
| 1784 catchBuilder.environment.update(variable, value); | 1721 catchBuilder.environment.update(variable, value); |
| 1785 } | 1722 } |
| 1786 | 1723 |
| 1787 List<ir.Parameter> catchParameters = buildCatch(catchBuilder, join); | 1724 List<ir.Parameter> catchParameters = buildCatch(catchBuilder, join); |
| 1788 ir.Continuation catchContinuation = new ir.Continuation(catchParameters); | 1725 ir.Continuation catchContinuation = new ir.Continuation(catchParameters); |
| 1789 catchContinuation.body = catchBuilder._root; | 1726 catchContinuation.body = catchBuilder._root; |
| 1790 tryCatchBuilder.add( | 1727 tryCatchBuilder.add( |
| (...skipping 681 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2472 value = buildTypeVariableAccess(variable.typeVariable); | 2409 value = buildTypeVariableAccess(variable.typeVariable); |
| 2473 } else { | 2410 } else { |
| 2474 value = environment.lookup(field.local); | 2411 value = environment.lookup(field.local); |
| 2475 } | 2412 } |
| 2476 arguments.add(value); | 2413 arguments.add(value); |
| 2477 } | 2414 } |
| 2478 return addPrimitive(new ir.CreateInstance( | 2415 return addPrimitive(new ir.CreateInstance( |
| 2479 classElement, arguments, const <ir.Primitive>[], sourceInformation)); | 2416 classElement, arguments, const <ir.Primitive>[], sourceInformation)); |
| 2480 } | 2417 } |
| 2481 | 2418 |
| 2482 /// Create a read access of [local] variable or parameter. | 2419 /// Create a read access of [local] function, variable, or parameter. |
| 2483 ir.Primitive _buildLocalGet(LocalElement local) { | 2420 ir.Primitive buildLocalGet(LocalElement local) { |
| 2484 assert(isOpen); | 2421 assert(isOpen); |
| 2485 ClosureLocation location = state.boxedVariables[local]; | 2422 ClosureLocation location = state.boxedVariables[local]; |
| 2486 if (location != null) { | 2423 if (location != null) { |
| 2487 ir.Primitive result = new ir.GetField(environment.lookup(location.box), | 2424 ir.Primitive result = new ir.GetField(environment.lookup(location.box), |
| 2488 location.field); | 2425 location.field); |
| 2489 result.useElementAsHint(local); | 2426 result.useElementAsHint(local); |
| 2490 return addPrimitive(result); | 2427 return addPrimitive(result); |
| 2491 } else if (isInMutableVariable(local)) { | 2428 } else if (isInMutableVariable(local)) { |
| 2492 return addPrimitive(new ir.GetMutable(getMutableVariable(local))); | 2429 return addPrimitive(new ir.GetMutable(getMutableVariable(local))); |
| 2493 } else { | 2430 } else { |
| (...skipping 405 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2899 } | 2836 } |
| 2900 | 2837 |
| 2901 class SwitchCaseInfo { | 2838 class SwitchCaseInfo { |
| 2902 final List<ir.Primitive> constants = <ir.Primitive>[]; | 2839 final List<ir.Primitive> constants = <ir.Primitive>[]; |
| 2903 final SubbuildFunction buildBody; | 2840 final SubbuildFunction buildBody; |
| 2904 | 2841 |
| 2905 SwitchCaseInfo(this.buildBody); | 2842 SwitchCaseInfo(this.buildBody); |
| 2906 | 2843 |
| 2907 void addConstant(ir.Primitive constant) => constants.add(constant); | 2844 void addConstant(ir.Primitive constant) => constants.add(constant); |
| 2908 } | 2845 } |
| OLD | NEW |