| 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 part of dart2js.ir_builder; | 5 part of dart2js.ir_builder; |
| 6 | 6 |
| 7 /** | 7 /** |
| 8 * This task iterates through all resolved elements and builds [ir.Node]s. The | 8 * This task iterates through all resolved elements and builds [ir.Node]s. The |
| 9 * nodes are stored in the [nodes] map and accessible through [hasIr] and | 9 * nodes are stored in the [nodes] map and accessible through [hasIr] and |
| 10 * [getIr]. | 10 * [getIr]. |
| (...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 137 /** | 137 /** |
| 138 * Builds the [ir.ExecutableDefinition] for an executable element. In case the | 138 * Builds the [ir.ExecutableDefinition] for an executable element. In case the |
| 139 * function uses features that cannot be expressed in the IR, this element | 139 * function uses features that cannot be expressed in the IR, this element |
| 140 * returns `null`. | 140 * returns `null`. |
| 141 */ | 141 */ |
| 142 ir.ExecutableDefinition buildExecutable(ExecutableElement element); | 142 ir.ExecutableDefinition buildExecutable(ExecutableElement element); |
| 143 | 143 |
| 144 ClosureScope getClosureScopeForNode(ast.Node node); | 144 ClosureScope getClosureScopeForNode(ast.Node node); |
| 145 ClosureEnvironment getClosureEnvironment(); | 145 ClosureEnvironment getClosureEnvironment(); |
| 146 | 146 |
| 147 /// Normalizes the argument list to a static invocation (i.e. where the target |
| 148 /// element is known). |
| 149 /// |
| 150 /// For the JS backend, inserts default arguments and normalizes order of |
| 151 /// named arguments. |
| 152 /// |
| 153 /// For the Dart backend, returns [arguments]. |
| 154 List<ir.Primitive> normalizeStaticArguments( |
| 155 Selector selector, |
| 156 FunctionElement target, |
| 157 List<ir.Primitive> arguments); |
| 147 | 158 |
| 159 /// Normalizes the argument list of a dynamic invocation (i.e. where the |
| 160 /// target element is unknown). |
| 161 /// |
| 162 /// For the JS backend, normalizes order of named arguments. |
| 163 /// |
| 164 /// For the Dart backend, returns [arguments]. |
| 165 List<ir.Primitive> normalizeDynamicArguments( |
| 166 Selector selector, |
| 167 List<ir.Primitive> arguments); |
| 148 | 168 |
| 149 ir.FunctionDefinition _makeFunctionBody(FunctionElement element, | 169 ir.FunctionDefinition _makeFunctionBody(FunctionElement element, |
| 150 ast.FunctionExpression node) { | 170 ast.FunctionExpression node) { |
| 151 FunctionSignature signature = element.functionSignature; | 171 FunctionSignature signature = element.functionSignature; |
| 152 List<ParameterElement> parameters = []; | 172 List<ParameterElement> parameters = []; |
| 153 signature.orderedForEachParameter(parameters.add); | 173 signature.orderedForEachParameter(parameters.add); |
| 154 | 174 |
| 155 irBuilder.buildFunctionHeader(parameters, | 175 irBuilder.buildFunctionHeader(parameters, |
| 156 closureScope: getClosureScopeForNode(node), | 176 closureScope: getClosureScopeForNode(node), |
| 157 env: getClosureEnvironment()); | 177 env: getClosureEnvironment()); |
| (...skipping 384 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 542 } | 562 } |
| 543 | 563 |
| 544 ir.Primitive visitNamedArgument(ast.NamedArgument node) { | 564 ir.Primitive visitNamedArgument(ast.NamedArgument node) { |
| 545 assert(irBuilder.isOpen); | 565 assert(irBuilder.isOpen); |
| 546 return visit(node.expression); | 566 return visit(node.expression); |
| 547 } | 567 } |
| 548 | 568 |
| 549 ir.Primitive visitClosureSend(ast.Send node) { | 569 ir.Primitive visitClosureSend(ast.Send node) { |
| 550 assert(irBuilder.isOpen); | 570 assert(irBuilder.isOpen); |
| 551 Element element = elements[node]; | 571 Element element = elements[node]; |
| 552 Selector closureSelector = elements.getSelector(node); | 572 Selector selector = elements.getSelector(node); |
| 553 if (element == null) { | 573 ir.Primitive receiver = (element == null) |
| 554 ir.Primitive closureTarget = visit(node.selector); | 574 ? visit(node.selector) |
| 555 List<ir.Primitive> args = | 575 : irBuilder.buildLocalGet(element); |
| 556 node.arguments.mapToList(visit, growable:false); | 576 List<ir.Primitive> arguments = node.arguments.mapToList(visit); |
| 557 return irBuilder.buildFunctionExpressionInvocation( | 577 arguments = normalizeDynamicArguments(selector, arguments); |
| 558 closureTarget, elements.getSelector(node), args); | 578 return irBuilder.buildFunctionExpressionInvocation( |
| 559 } else { | 579 receiver, selector, arguments); |
| 560 List<ir.Primitive> args = | |
| 561 node.arguments.mapToList(visit, growable:false); | |
| 562 return irBuilder.buildLocalInvocation( | |
| 563 element, elements.getSelector(node), args); | |
| 564 } | |
| 565 } | 580 } |
| 566 | 581 |
| 567 /// If [node] is null, returns this. | 582 /// If [node] is null, returns this. |
| 568 /// If [node] is super, returns null (for special handling) | 583 /// If [node] is super, returns null (for special handling) |
| 569 /// Otherwise visits [node] and returns the result. | 584 /// Otherwise visits [node] and returns the result. |
| 570 ir.Primitive visitReceiver(ast.Expression node) { | 585 ir.Primitive visitReceiver(ast.Expression node) { |
| 571 if (node == null) return irBuilder.buildThis(); | 586 if (node == null) return irBuilder.buildThis(); |
| 572 if (node.isSuper()) return null; | 587 if (node.isSuper()) return null; |
| 573 return visit(node); | 588 return visit(node); |
| 574 } | 589 } |
| 575 | 590 |
| 576 /// Returns `true` if [node] is a super call. | 591 /// Returns `true` if [node] is a super call. |
| 577 // TODO(johnniwinther): Remove the need for this. | 592 // TODO(johnniwinther): Remove the need for this. |
| 578 bool isSuperCall(ast.Send node) { | 593 bool isSuperCall(ast.Send node) { |
| 579 return node != null && node.receiver != null && node.receiver.isSuper(); | 594 return node != null && node.receiver != null && node.receiver.isSuper(); |
| 580 } | 595 } |
| 581 | 596 |
| 582 ir.Primitive visitDynamicSend(ast.Send node) { | 597 ir.Primitive visitDynamicSend(ast.Send node) { |
| 583 assert(irBuilder.isOpen); | 598 assert(irBuilder.isOpen); |
| 584 Selector selector = elements.getSelector(node); | 599 Selector selector = elements.getSelector(node); |
| 585 ir.Primitive receiver = visitReceiver(node.receiver); | 600 ir.Primitive receiver = visitReceiver(node.receiver); |
| 586 List<ir.Primitive> arguments = new List<ir.Primitive>(); | 601 List<ir.Primitive> arguments = node.arguments.mapToList(visit); |
| 587 for (ast.Node n in node.arguments) { | 602 arguments = normalizeDynamicArguments(selector, arguments); |
| 588 arguments.add(visit(n)); | |
| 589 } | |
| 590 return irBuilder.buildDynamicInvocation(receiver, selector, arguments); | 603 return irBuilder.buildDynamicInvocation(receiver, selector, arguments); |
| 591 } | 604 } |
| 592 | 605 |
| 593 _GetterElements translateGetter(ast.Send node, Selector selector) { | 606 _GetterElements translateGetter(ast.Send node, Selector selector) { |
| 594 Element element = elements[node]; | 607 Element element = elements[node]; |
| 595 ir.Primitive result; | 608 ir.Primitive result; |
| 596 ir.Primitive receiver; | 609 ir.Primitive receiver; |
| 597 ir.Primitive index; | 610 ir.Primitive index; |
| 598 | 611 |
| 599 if (element != null && element.isConst) { | 612 if (element != null && element.isConst) { |
| (...skipping 105 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 705 assert(irBuilder.isOpen); | 718 assert(irBuilder.isOpen); |
| 706 Element element = elements[node]; | 719 Element element = elements[node]; |
| 707 assert(!element.isConstructor); | 720 assert(!element.isConstructor); |
| 708 // TODO(lry): support foreign functions. | 721 // TODO(lry): support foreign functions. |
| 709 if (element.isForeign(compiler.backend)) { | 722 if (element.isForeign(compiler.backend)) { |
| 710 return giveup(node, 'StaticSend: foreign'); | 723 return giveup(node, 'StaticSend: foreign'); |
| 711 } | 724 } |
| 712 | 725 |
| 713 Selector selector = elements.getSelector(node); | 726 Selector selector = elements.getSelector(node); |
| 714 | 727 |
| 715 // TODO(lry): support default arguments, need support for locals. | |
| 716 List<ir.Primitive> arguments = | 728 List<ir.Primitive> arguments = |
| 717 node.arguments.mapToList(visit, growable:false); | 729 node.arguments.mapToList(visit, growable:false); |
| 730 arguments = normalizeStaticArguments(selector, element, arguments); |
| 718 return irBuilder.buildStaticInvocation(element, selector, arguments); | 731 return irBuilder.buildStaticInvocation(element, selector, arguments); |
| 719 } | 732 } |
| 720 | 733 |
| 721 ir.Primitive visitSuperSend(ast.Send node) { | 734 ir.Primitive visitSuperSend(ast.Send node) { |
| 722 assert(irBuilder.isOpen); | 735 assert(irBuilder.isOpen); |
| 723 if (node.isPropertyAccess) { | 736 if (node.isPropertyAccess) { |
| 724 return visitGetterSend(node); | 737 return visitGetterSend(node); |
| 725 } else { | 738 } else { |
| 726 Selector selector = elements.getSelector(node); | 739 Selector selector = elements.getSelector(node); |
| 727 Element target = elements[node]; | 740 Element target = elements[node]; |
| 728 List<ir.Primitive> arguments = new List<ir.Primitive>(); | 741 List<ir.Primitive> arguments = node.arguments.mapToList(visit); |
| 729 for (ast.Node n in node.arguments) { | 742 arguments = normalizeStaticArguments(selector, target, arguments); |
| 730 arguments.add(visit(n)); | |
| 731 } | |
| 732 return irBuilder.buildSuperInvocation(target, selector, arguments); | 743 return irBuilder.buildSuperInvocation(target, selector, arguments); |
| 733 } | 744 } |
| 734 } | 745 } |
| 735 | 746 |
| 736 visitTypePrefixSend(ast.Send node) { | 747 visitTypePrefixSend(ast.Send node) { |
| 737 compiler.internalError(node, "visitTypePrefixSend should not be called."); | 748 compiler.internalError(node, "visitTypePrefixSend should not be called."); |
| 738 } | 749 } |
| 739 | 750 |
| 740 ir.Primitive visitTypeLiteralSend(ast.Send node) { | 751 ir.Primitive visitTypeLiteralSend(ast.Send node) { |
| 741 assert(irBuilder.isOpen); | 752 assert(irBuilder.isOpen); |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 854 } | 865 } |
| 855 | 866 |
| 856 ir.Primitive visitNewExpression(ast.NewExpression node) { | 867 ir.Primitive visitNewExpression(ast.NewExpression node) { |
| 857 if (node.isConst) { | 868 if (node.isConst) { |
| 858 return translateConstant(node); | 869 return translateConstant(node); |
| 859 } | 870 } |
| 860 FunctionElement element = elements[node.send]; | 871 FunctionElement element = elements[node.send]; |
| 861 Selector selector = elements.getSelector(node.send); | 872 Selector selector = elements.getSelector(node.send); |
| 862 DartType type = elements.getType(node); | 873 DartType type = elements.getType(node); |
| 863 ast.Node selectorNode = node.send.selector; | 874 ast.Node selectorNode = node.send.selector; |
| 864 List<ir.Definition> arguments = | 875 List<ir.Primitive> arguments = |
| 865 node.send.arguments.mapToList(visit, growable:false); | 876 node.send.arguments.mapToList(visit, growable:false); |
| 877 arguments = normalizeStaticArguments(selector, element, arguments); |
| 866 return irBuilder.buildConstructorInvocation( | 878 return irBuilder.buildConstructorInvocation( |
| 867 element, selector, type, arguments); | 879 element, selector, type, arguments); |
| 868 } | 880 } |
| 869 | 881 |
| 870 ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) { | 882 ir.Primitive visitStringJuxtaposition(ast.StringJuxtaposition node) { |
| 871 assert(irBuilder.isOpen); | 883 assert(irBuilder.isOpen); |
| 872 ir.Primitive first = visit(node.first); | 884 ir.Primitive first = visit(node.first); |
| 873 ir.Primitive second = visit(node.second); | 885 ir.Primitive second = visit(node.second); |
| 874 return irBuilder.buildStringConcatenation([first, second]); | 886 return irBuilder.buildStringConcatenation([first, second]); |
| 875 } | 887 } |
| 876 | 888 |
| 877 ir.Primitive visitStringInterpolation(ast.StringInterpolation node) { | 889 ir.Primitive visitStringInterpolation(ast.StringInterpolation node) { |
| 878 assert(irBuilder.isOpen); | 890 assert(irBuilder.isOpen); |
| 879 List<ir.Primitive> arguments = []; | 891 List<ir.Primitive> arguments = []; |
| 880 arguments.add(visitLiteralString(node.string)); | 892 arguments.add(visitLiteralString(node.string)); |
| 881 var it = node.parts.iterator; | 893 var it = node.parts.iterator; |
| 882 while (it.moveNext()) { | 894 while (it.moveNext()) { |
| 883 ast.StringInterpolationPart part = it.current; | 895 ast.StringInterpolationPart part = it.current; |
| 884 arguments.add(visit(part.expression)); | 896 arguments.add(visit(part.expression)); |
| 885 arguments.add(visitLiteralString(part.string)); | 897 arguments.add(visitLiteralString(part.string)); |
| 886 } | 898 } |
| 887 return irBuilder.buildStringConcatenation(arguments); | 899 return irBuilder.buildStringConcatenation(arguments); |
| 888 } | 900 } |
| 889 | 901 |
| 890 ir.Primitive translateConstant(ast.Node node, [ConstantExpression constant]) { | 902 ir.Primitive translateConstant(ast.Node node) { |
| 891 assert(irBuilder.isOpen); | 903 assert(irBuilder.isOpen); |
| 892 if (constant == null) { | 904 return irBuilder.buildConstantLiteral(getConstantForNode(node)); |
| 893 constant = getConstantForNode(node); | |
| 894 } | |
| 895 return irBuilder.buildConstantLiteral(constant); | |
| 896 } | 905 } |
| 897 | 906 |
| 898 ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) { | 907 ir.ExecutableDefinition nullIfGiveup(ir.ExecutableDefinition action()) { |
| 899 try { | 908 try { |
| 900 return action(); | 909 return action(); |
| 901 } catch(e, tr) { | 910 } catch(e, tr) { |
| 902 if (e == ABORT_IRNODE_BUILDER) { | 911 if (e == ABORT_IRNODE_BUILDER) { |
| 903 return null; | 912 return null; |
| 904 } | 913 } |
| 905 rethrow; | 914 rethrow; |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1100 SynthesizedConstructorElementX constructor = element; | 1109 SynthesizedConstructorElementX constructor = element; |
| 1101 if (!constructor.isDefaultConstructor) { | 1110 if (!constructor.isDefaultConstructor) { |
| 1102 giveup(null, 'cannot handle synthetic forwarding constructors'); | 1111 giveup(null, 'cannot handle synthetic forwarding constructors'); |
| 1103 } | 1112 } |
| 1104 } | 1113 } |
| 1105 | 1114 |
| 1106 IrBuilder builder = makeIRBuilder(node, element); | 1115 IrBuilder builder = makeIRBuilder(node, element); |
| 1107 | 1116 |
| 1108 return withBuilder(builder, () => _makeFunctionBody(element, node)); | 1117 return withBuilder(builder, () => _makeFunctionBody(element, node)); |
| 1109 } | 1118 } |
| 1119 |
| 1120 List<ir.Primitive> normalizeStaticArguments( |
| 1121 Selector selector, |
| 1122 FunctionElement target, |
| 1123 List<ir.Primitive> arguments) { |
| 1124 return arguments; |
| 1125 } |
| 1126 |
| 1127 List<ir.Primitive> normalizeDynamicArguments( |
| 1128 Selector selector, |
| 1129 List<ir.Primitive> arguments) { |
| 1130 return arguments; |
| 1131 } |
| 1110 } | 1132 } |
| 1111 | 1133 |
| 1112 /// IR builder specific to the JavaScript backend, coupled to the [JsIrBuilder]. | 1134 /// IR builder specific to the JavaScript backend, coupled to the [JsIrBuilder]. |
| 1113 class JsIrBuilderVisitor extends IrBuilderVisitor { | 1135 class JsIrBuilderVisitor extends IrBuilderVisitor { |
| 1114 /// Promote the type of [irBuilder] to [JsIrBuilder]. | 1136 /// Promote the type of [irBuilder] to [JsIrBuilder]. |
| 1115 JsIrBuilder get irBuilder => super.irBuilder; | 1137 JsIrBuilder get irBuilder => super.irBuilder; |
| 1116 | 1138 |
| 1117 /// Result of closure conversion for the current body of code. | 1139 /// Result of closure conversion for the current body of code. |
| 1118 /// | 1140 /// |
| 1119 /// Will be initialized upon entering the body of a function. | 1141 /// Will be initialized upon entering the body of a function. |
| (...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1235 /// Such expressions need to be compiled with a different [sourceFile] and | 1257 /// Such expressions need to be compiled with a different [sourceFile] and |
| 1236 /// [elements] mapping. | 1258 /// [elements] mapping. |
| 1237 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) { | 1259 ir.Primitive inlineExpression(AstElement context, ast.Expression expression) { |
| 1238 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor( | 1260 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor( |
| 1239 context.resolvedAst.elements, | 1261 context.resolvedAst.elements, |
| 1240 compiler, | 1262 compiler, |
| 1241 elementSourceFile(context)); | 1263 elementSourceFile(context)); |
| 1242 return visitor.withBuilder(irBuilder, () => visitor.visit(expression)); | 1264 return visitor.withBuilder(irBuilder, () => visitor.visit(expression)); |
| 1243 } | 1265 } |
| 1244 | 1266 |
| 1267 /// Builds the IR for a constant taken from a different [context]. |
| 1268 /// |
| 1269 /// Such constants need to be compiled with a different [sourceFile] and |
| 1270 /// [elements] mapping. |
| 1271 ir.Primitive inlineConstant(AstElement context, ast.Expression exp) { |
| 1272 JsIrBuilderVisitor visitor = new JsIrBuilderVisitor( |
| 1273 context.resolvedAst.elements, |
| 1274 compiler, |
| 1275 elementSourceFile(context)); |
| 1276 return visitor.withBuilder(irBuilder, () => visitor.translateConstant(exp)); |
| 1277 } |
| 1278 |
| 1245 /// Builds the IR for a given constructor. | 1279 /// Builds the IR for a given constructor. |
| 1246 /// | 1280 /// |
| 1247 /// 1. Evaluates all own or inherited field initializers. | 1281 /// 1. Evaluates all own or inherited field initializers. |
| 1248 /// 2. Creates the object and assigns its fields. | 1282 /// 2. Creates the object and assigns its fields. |
| 1249 /// 3. Calls constructor body and super constructor bodies. | 1283 /// 3. Calls constructor body and super constructor bodies. |
| 1250 /// 4. Returns the created object. | 1284 /// 4. Returns the created object. |
| 1251 ir.FunctionDefinition buildConstructor(ConstructorElement constructor) { | 1285 ir.FunctionDefinition buildConstructor(ConstructorElement constructor) { |
| 1252 constructor = constructor.implementation; | 1286 constructor = constructor.implementation; |
| 1253 ClassElement classElement = constructor.enclosingClass.implementation; | 1287 ClassElement classElement = constructor.enclosingClass.implementation; |
| 1254 | 1288 |
| (...skipping 283 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1538 | 1572 |
| 1539 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping( | 1573 closureMap = compiler.closureToClassMapper.computeClosureToClassMapping( |
| 1540 element, | 1574 element, |
| 1541 node, | 1575 node, |
| 1542 elements); | 1576 elements); |
| 1543 IrBuilder builder = | 1577 IrBuilder builder = |
| 1544 new JsIrBuilder(compiler.backend.constantSystem, element); | 1578 new JsIrBuilder(compiler.backend.constantSystem, element); |
| 1545 return withBuilder(builder, () => _makeFunctionBody(element, node)); | 1579 return withBuilder(builder, () => _makeFunctionBody(element, node)); |
| 1546 } | 1580 } |
| 1547 | 1581 |
| 1582 /// Creates a primitive for the default value of [parameter]. |
| 1583 ir.Primitive translateDefaultValue(ParameterElement parameter) { |
| 1584 if (parameter.initializer == null) { |
| 1585 return irBuilder.buildNullLiteral(); |
| 1586 } else { |
| 1587 return inlineConstant(parameter.executableContext, parameter.initializer); |
| 1588 } |
| 1589 } |
| 1590 |
| 1591 /// Inserts default arguments and normalizes order of named arguments. |
| 1592 List<ir.Primitive> normalizeStaticArguments( |
| 1593 Selector selector, |
| 1594 FunctionElement target, |
| 1595 List<ir.Primitive> arguments) { |
| 1596 target = target.implementation; |
| 1597 if (!target.functionSignature.optionalParametersAreNamed && |
| 1598 target.functionSignature.parameterCount == arguments.length) { |
| 1599 // Optimization: don't copy the argument list for trivial cases. |
| 1600 return arguments; |
| 1601 } |
| 1602 return selector.makeArgumentsList( |
| 1603 target, |
| 1604 arguments, |
| 1605 translateDefaultValue); |
| 1606 } |
| 1607 |
| 1608 /// Normalizes order of named arguments. |
| 1609 List<ir.Primitive> normalizeDynamicArguments( |
| 1610 Selector selector, |
| 1611 List<ir.Primitive> arguments) { |
| 1612 // Optimization: don't copy the argument list for trivial cases. |
| 1613 if (selector.namedArguments.isEmpty) return arguments; |
| 1614 return selector.makeDynamicArgumentsList(arguments); |
| 1615 } |
| 1616 |
| 1548 } | 1617 } |
| 1549 | 1618 |
| OLD | NEW |