| 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 class Interceptors { | 5 class Interceptors { |
| 6 Compiler compiler; | 6 Compiler compiler; |
| 7 Interceptors(Compiler this.compiler); | 7 Interceptors(Compiler this.compiler); |
| 8 | 8 |
| 9 SourceString mapOperatorToMethodName(Operator op) { | 9 SourceString mapOperatorToMethodName(Operator op) { |
| 10 String name = op.source.stringValue; | 10 String name = op.source.stringValue; |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 FunctionExpression node) { | 269 FunctionExpression node) { |
| 270 | 270 |
| 271 ClosureTranslator translator = | 271 ClosureTranslator translator = |
| 272 new ClosureTranslator(builder.compiler, builder.elements); | 272 new ClosureTranslator(builder.compiler, builder.elements); |
| 273 closureData = translator.translate(node); | 273 closureData = translator.translate(node); |
| 274 | 274 |
| 275 FunctionParameters params = function.computeParameters(builder.compiler); | 275 FunctionParameters params = function.computeParameters(builder.compiler); |
| 276 params.forEachParameter((Element element) { | 276 params.forEachParameter((Element element) { |
| 277 HParameterValue parameter = new HParameterValue(element); | 277 HParameterValue parameter = new HParameterValue(element); |
| 278 builder.add(parameter); | 278 builder.add(parameter); |
| 279 // Note that for constructors [element] could be a field-element which we | |
| 280 // treat as if it was a local. | |
| 281 directLocals[element] = parameter; | 279 directLocals[element] = parameter; |
| 282 }); | 280 }); |
| 283 if (closureData.thisElement !== null) { | 281 if (closureData.thisElement !== null) { |
| 284 // Once closures have been mapped to classes their instance members might | 282 // Once closures have been mapped to classes their instance members might |
| 285 // not have any thisElement if the closure was created inside a static | 283 // not have any thisElement if the closure was created inside a static |
| 286 // context. | 284 // context. |
| 287 assert(function.isInstanceMember() || function.isGenerativeConstructor()); | 285 assert(function.isInstanceMember() || function.isGenerativeConstructor()); |
| 288 // We have to introduce 'this' before we enter the scope, since it might | 286 // We have to introduce 'this' before we enter the scope, since it might |
| 289 // need to be copied into a box (if it is captured). This is similar | 287 // need to be copied into a box (if it is captured). This is similar |
| 290 // to all other parameters that are introduced. | 288 // to all other parameters that are introduced. |
| (...skipping 475 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 766 classElement.backendMembers.prepend(bodyElement); | 764 classElement.backendMembers.prepend(bodyElement); |
| 767 } | 765 } |
| 768 assert(bodyElement.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY); | 766 assert(bodyElement.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY); |
| 769 return bodyElement; | 767 return bodyElement; |
| 770 } | 768 } |
| 771 | 769 |
| 772 /** | 770 /** |
| 773 * Run through the initializers and inline all field initializers. Returns the | 771 * Run through the initializers and inline all field initializers. Returns the |
| 774 * next constructor to analyze. | 772 * next constructor to analyze. |
| 775 */ | 773 */ |
| 776 FunctionElement analyzeInitializers(Link<Node> initializers) { | 774 FunctionElement analyzeInitializers(Link<Node> initializers, |
| 775 Map<Element, HInstruction> fieldValues) { |
| 777 FunctionElement nextConstructor; | 776 FunctionElement nextConstructor; |
| 778 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { | 777 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { |
| 779 assert(link.head is Send); | 778 assert(link.head is Send); |
| 780 if (link.head is !SendSet) { | 779 if (link.head is !SendSet) { |
| 781 // A super initializer or constructor redirection. | 780 // A super initializer or constructor redirection. |
| 782 Send call = link.head; | 781 Send call = link.head; |
| 783 assert(Initializers.isSuperConstructorCall(call) || | 782 assert(Initializers.isSuperConstructorCall(call) || |
| 784 Initializers.isConstructorRedirect(call)); | 783 Initializers.isConstructorRedirect(call)); |
| 785 assert(nextConstructor === null); | 784 assert(nextConstructor === null); |
| 786 nextConstructor = elements[call]; | 785 nextConstructor = elements[call]; |
| 787 // Visit arguments and map the corresponding parameter value to | 786 // Visit arguments and map the corresponding parameter value to |
| 788 // the resulting HInstruction value. | 787 // the resulting HInstruction value. |
| 789 List<HInstruction> arguments = new List<HInstruction>(); | 788 List<HInstruction> arguments = new List<HInstruction>(); |
| 790 addStaticSendArgumentsToList(call, nextConstructor, arguments); | 789 addStaticSendArgumentsToList(call, nextConstructor, arguments); |
| 791 int index = 0; | 790 int index = 0; |
| 792 FunctionParameters parameters = | 791 FunctionParameters parameters = |
| 793 nextConstructor.computeParameters(compiler); | 792 nextConstructor.computeParameters(compiler); |
| 794 parameters.forEachParameter((parameter) { | 793 parameters.forEachParameter((Element parameter) { |
| 795 localsHandler.updateLocal(parameter, arguments[index++]); | 794 HInstruction argument = arguments[index++]; |
| 795 localsHandler.updateLocal(parameter, argument); |
| 796 // Don't forget to update the field, if the parameter is of the |
| 797 // form [:this.x:]. |
| 798 if (parameter.kind == ElementKind.FIELD_PARAMETER) { |
| 799 FieldParameterElement fieldParameterElement = parameter; |
| 800 fieldValues[fieldParameterElement.fieldElement] = argument; |
| 801 } |
| 796 }); | 802 }); |
| 797 } else { | 803 } else { |
| 798 // A field initializer. | 804 // A field initializer. |
| 799 SendSet init = link.head; | 805 SendSet init = link.head; |
| 800 Link<Node> arguments = init.arguments; | 806 Link<Node> arguments = init.arguments; |
| 801 assert(!arguments.isEmpty() && arguments.tail.isEmpty()); | 807 assert(!arguments.isEmpty() && arguments.tail.isEmpty()); |
| 802 visit(arguments.head); | 808 visit(arguments.head); |
| 803 // We treat the init field-elements like locals. In the context of | 809 fieldValues[elements[init]] = pop(); |
| 804 // the factory this is correct, and simplifies dealing with | |
| 805 // parameter-initializers (like A(this.x)). | |
| 806 localsHandler.updateLocal(elements[init], pop()); | |
| 807 } | 810 } |
| 808 } | 811 } |
| 809 return nextConstructor; | 812 return nextConstructor; |
| 810 } | 813 } |
| 811 | 814 |
| 812 /** | 815 /** |
| 813 * Build the factory function corresponding to the constructor | 816 * Build the factory function corresponding to the constructor |
| 814 * [functionElement]: | 817 * [functionElement]: |
| 815 * - Initialize fields with the values of the field initializers of the | 818 * - Initialize fields with the values of the field initializers of the |
| 816 * current constructor and super constructors or constructors redirected | 819 * current constructor and super constructors or constructors redirected |
| 817 * to, starting from the current constructor. | 820 * to, starting from the current constructor. |
| 818 * - Call the the constructor bodies, starting from the constructor(s) in the | 821 * - Call the the constructor bodies, starting from the constructor(s) in the |
| 819 * super class(es). | 822 * super class(es). |
| 820 */ | 823 */ |
| 821 HGraph buildFactory(ClassElement classElement, | 824 HGraph buildFactory(ClassElement classElement, |
| 822 FunctionElement functionElement) { | 825 FunctionElement functionElement) { |
| 823 FunctionExpression function = functionElement.parseNode(compiler); | 826 FunctionExpression function = functionElement.parseNode(compiler); |
| 827 // Note that constructors (like any other static function) do not need |
| 828 // to deal with optional arguments. It is the callers job to provide all |
| 829 // arguments as if they were positional. |
| 830 |
| 824 // The initializer list could contain closures. | 831 // The initializer list could contain closures. |
| 825 openFunction(functionElement, function); | 832 openFunction(functionElement, function); |
| 826 | 833 |
| 834 Map<Element, HInstruction> fieldValues = new Map<Element, HInstruction>(); |
| 835 FunctionParameters parameters = functionElement.computeParameters(compiler); |
| 836 parameters.forEachParameter((Element element) { |
| 837 if (element.kind == ElementKind.FIELD_PARAMETER) { |
| 838 // If the [element] is a field-parameter (such as [:this.x:] then |
| 839 // initialize the field element with its value. |
| 840 FieldParameterElement fieldParameterElement = element; |
| 841 HInstruction parameterValue = localsHandler.readLocal(element); |
| 842 fieldValues[fieldParameterElement.fieldElement] = parameterValue; |
| 843 } |
| 844 }); |
| 845 |
| 827 final Map<FunctionElement, TreeElements> constructorElements = | 846 final Map<FunctionElement, TreeElements> constructorElements = |
| 828 compiler.resolver.constructorElements; | 847 compiler.resolver.constructorElements; |
| 829 List<FunctionElement> constructors = new List<FunctionElement>(); | 848 List<FunctionElement> constructors = new List<FunctionElement>(); |
| 830 | 849 |
| 831 // Analyze the constructor and all referenced constructors and collect | 850 // Analyze the constructor and all referenced constructors and collect |
| 832 // initializers and constructor bodies. | 851 // initializers and constructor bodies. |
| 833 FunctionElement nextConstructor = functionElement; | 852 FunctionElement nextConstructor = functionElement; |
| 834 while (nextConstructor != null) { | 853 while (nextConstructor != null) { |
| 835 FunctionElement constructor = nextConstructor; | 854 FunctionElement constructor = nextConstructor; |
| 836 constructors.addLast(constructor); | 855 constructors.addLast(constructor); |
| 837 nextConstructor = null; | 856 nextConstructor = null; |
| 838 elements = compiler.resolver.resolveMethodElement(constructor); | 857 elements = compiler.resolver.resolveMethodElement(constructor); |
| 839 FunctionExpression functionNode = constructor.parseNode(compiler); | 858 FunctionExpression functionNode = constructor.parseNode(compiler); |
| 840 Link<Node> initializers = const EmptyLink<Node>(); | 859 Link<Node> initializers = const EmptyLink<Node>(); |
| 841 if (functionNode.initializers !== null) { | 860 if (functionNode.initializers !== null) { |
| 842 nextConstructor = analyzeInitializers(functionNode.initializers.nodes); | 861 nextConstructor = |
| 862 analyzeInitializers(functionNode.initializers.nodes, fieldValues); |
| 843 } | 863 } |
| 844 if (nextConstructor === null) { | 864 if (nextConstructor === null) { |
| 845 // No super initializer found. Try to find the default constructor if | 865 // No super initializer found. Try to find the default constructor if |
| 846 // the class is not Object. | 866 // the class is not Object. |
| 847 ClassElement enclosingClass = constructor.enclosingElement; | 867 ClassElement enclosingClass = constructor.enclosingElement; |
| 848 ClassElement superClass = enclosingClass.superclass; | 868 ClassElement superClass = enclosingClass.superclass; |
| 849 ClassElement objectElement = compiler.coreLibrary.find(Types.OBJECT); | 869 ClassElement objectElement = compiler.coreLibrary.find(Types.OBJECT); |
| 850 if (enclosingClass != objectElement) { | 870 if (enclosingClass != objectElement) { |
| 851 assert(superClass !== null); | 871 assert(superClass !== null); |
| 852 assert(superClass.isResolved); | 872 assert(superClass.isResolved); |
| 853 nextConstructor = superClass.lookupConstructor(superClass.name); | 873 nextConstructor = superClass.lookupConstructor(superClass.name); |
| 854 if (nextConstructor === null) { | 874 if (nextConstructor === null) { |
| 855 compiler.internalError("no default constructor available"); | 875 compiler.internalError("no default constructor available"); |
| 856 } | 876 } |
| 857 } | 877 } |
| 858 } | 878 } |
| 859 } | 879 } |
| 860 // Call the JavaScript constructor with the fields as argument. | 880 // Call the JavaScript constructor with the fields as argument. |
| 861 // TODO(floitsch,karlklose): move this code to ClassElement and share with | 881 // TODO(floitsch,karlklose): move this code to ClassElement and share with |
| 862 // the emitter. | 882 // the emitter. |
| 863 List<HInstruction> constructorArguments = <HInstruction>[]; | 883 List<HInstruction> constructorArguments = <HInstruction>[]; |
| 864 ClassElement element = classElement; | 884 ClassElement element = classElement; |
| 865 while (element != null) { | 885 while (element != null) { |
| 866 for (Element member in element.members) { | 886 for (Element member in element.members) { |
| 867 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { | 887 if (member.isInstanceMember() && member.kind == ElementKind.FIELD) { |
| 868 HInstruction value; | 888 HInstruction value = fieldValues[member]; |
| 869 if (localsHandler.hasValueForDirectLocal(member)) { | 889 if (value === null) { |
| 870 value = localsHandler.readLocal(member); | 890 // The field has no value in the initializer list. Initialize it |
| 871 } else { | 891 // with the declaration-site constant (if any). |
| 872 Constant fieldValue = | 892 Constant fieldValue = |
| 873 compiler.constantHandler.compileVariable(member); | 893 compiler.constantHandler.compileVariable(member); |
| 874 value = graph.addConstant(fieldValue); | 894 value = graph.addConstant(fieldValue); |
| 875 } | 895 } |
| 876 constructorArguments.add(value); | 896 constructorArguments.add(value); |
| 877 } | 897 } |
| 878 } | 898 } |
| 879 element = element.superclass; | 899 element = element.superclass; |
| 880 } | 900 } |
| 881 HForeignNew newObject = new HForeignNew(classElement, constructorArguments); | 901 HForeignNew newObject = new HForeignNew(classElement, constructorArguments); |
| (...skipping 1638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2520 buildBody() { | 2540 buildBody() { |
| 2521 // TODO(lrn): Make sure to take continue into account. | 2541 // TODO(lrn): Make sure to take continue into account. |
| 2522 visit(body); | 2542 visit(body); |
| 2523 if (isAborted()) { | 2543 if (isAborted()) { |
| 2524 compiler.reportWarning(body, "aborting loop body"); | 2544 compiler.reportWarning(body, "aborting loop body"); |
| 2525 } | 2545 } |
| 2526 } | 2546 } |
| 2527 handleIf(buildBody, null); | 2547 handleIf(buildBody, null); |
| 2528 } | 2548 } |
| 2529 } | 2549 } |
| OLD | NEW |