Chromium Code Reviews| 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 782 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 793 TreeElements treeElements = | 793 TreeElements treeElements = |
| 794 compiler.resolver.resolveMethodElement(constructor); | 794 compiler.resolver.resolveMethodElement(constructor); |
| 795 compiler.enqueue(new WorkItem.toCodegen(bodyElement, treeElements)); | 795 compiler.enqueue(new WorkItem.toCodegen(bodyElement, treeElements)); |
| 796 classElement.backendMembers = | 796 classElement.backendMembers = |
| 797 classElement.backendMembers.prepend(bodyElement); | 797 classElement.backendMembers.prepend(bodyElement); |
| 798 } | 798 } |
| 799 assert(bodyElement.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY); | 799 assert(bodyElement.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY); |
| 800 return bodyElement; | 800 return bodyElement; |
| 801 } | 801 } |
| 802 | 802 |
| 803 void inlineSuperOrRedirect(FunctionElement constructor, | |
| 804 Send send, | |
| 805 List<FunctionElement> constructors, | |
| 806 Map<Element, HInstruction> fieldValues) { | |
| 807 constructors.addLast(constructor); | |
| 808 | |
| 809 List<HInstruction> arguments = new List<HInstruction>(); | |
| 810 addStaticSendArgumentsToList(send, constructor, arguments); | |
| 811 | |
| 812 int index = 0; | |
| 813 FunctionParameters parameters = constructor.computeParameters(compiler); | |
| 814 parameters.forEachParameter((Element parameter) { | |
| 815 HInstruction argument = arguments[index++]; | |
| 816 localsHandler.updateLocal(parameter, argument); | |
| 817 // Don't forget to update the field, if the parameter is of the | |
| 818 // form [:this.x:]. | |
| 819 if (parameter.kind == ElementKind.FIELD_PARAMETER) { | |
| 820 FieldParameterElement fieldParameterElement = parameter; | |
| 821 fieldValues[fieldParameterElement.fieldElement] = argument; | |
| 822 } | |
| 823 }); | |
| 824 | |
| 825 // Build the initializers in the context of the new constructor. | |
| 826 TreeElements oldElements = elements; | |
| 827 elements = compiler.resolver.resolveMethodElement(constructor); | |
| 828 buildInitializers(constructor, constructors, fieldValues); | |
| 829 elements = oldElements; | |
| 830 } | |
| 803 /** | 831 /** |
| 804 * Run through the initializers and inline all field initializers. Recursively | 832 * Run through the initializers and inline all field initializers. Recursively |
| 805 * inlines super initializers. | 833 * inlines super initializers. |
| 806 * | 834 * |
| 807 * The constructors of the inlined initializers is added to [constructors] | 835 * The constructors of the inlined initializers is added to [constructors] |
| 808 * with sub constructors having a lower index than super constructors. | 836 * with sub constructors having a lower index than super constructors. |
| 809 */ | 837 */ |
| 810 void inlineInitializers(FunctionElement constructor, | 838 void buildInitializers(FunctionElement constructor, |
| 811 List<FunctionElement> constructors, | 839 List<FunctionElement> constructors, |
| 812 Map<Element, HInstruction> fieldValues) { | 840 Map<Element, HInstruction> fieldValues) { |
| 813 TreeElements oldElements = elements; | |
| 814 constructors.addLast(constructor); | |
| 815 bool initializedSuper = false; | |
| 816 elements = compiler.resolver.resolveMethodElement(constructor); | |
| 817 FunctionExpression functionNode = constructor.parseNode(compiler); | 841 FunctionExpression functionNode = constructor.parseNode(compiler); |
| 818 | 842 |
| 843 bool foundSuperOrRedirect = false; | |
| 844 | |
| 819 if (functionNode.initializers !== null) { | 845 if (functionNode.initializers !== null) { |
| 820 Link<Node> initializers = functionNode.initializers.nodes; | 846 Link<Node> initializers = functionNode.initializers.nodes; |
| 821 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { | 847 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { |
| 822 assert(link.head is Send); | 848 assert(link.head is Send); |
| 823 if (link.head is !SendSet) { | 849 if (link.head is !SendSet) { |
| 824 // A super initializer or constructor redirection. | 850 // A super initializer or constructor redirection. |
| 825 Send call = link.head; | 851 Send call = link.head; |
| 826 assert(Initializers.isSuperConstructorCall(call) || | 852 assert(Initializers.isSuperConstructorCall(call) || |
| 827 Initializers.isConstructorRedirect(call)); | 853 Initializers.isConstructorRedirect(call)); |
| 828 FunctionElement nextConstructor = elements[call]; | 854 FunctionElement target = elements[call]; |
| 829 // Visit arguments and map the corresponding parameter value to | 855 inlineSuperOrRedirect(target, call, constructors, fieldValues); |
| 830 // the resulting HInstruction value. | 856 foundSuperOrRedirect = true; |
| 831 List<HInstruction> arguments = new List<HInstruction>(); | |
| 832 addStaticSendArgumentsToList(call, nextConstructor, arguments); | |
| 833 int index = 0; | |
| 834 FunctionParameters parameters = | |
| 835 nextConstructor.computeParameters(compiler); | |
| 836 parameters.forEachParameter((Element parameter) { | |
| 837 HInstruction argument = arguments[index++]; | |
| 838 localsHandler.updateLocal(parameter, argument); | |
| 839 // Don't forget to update the field, if the parameter is of the | |
| 840 // form [:this.x:]. | |
| 841 if (parameter.kind == ElementKind.FIELD_PARAMETER) { | |
| 842 FieldParameterElement fieldParameterElement = parameter; | |
| 843 fieldValues[fieldParameterElement.fieldElement] = argument; | |
| 844 } | |
| 845 }); | |
| 846 inlineInitializers(nextConstructor, constructors, fieldValues); | |
| 847 initializedSuper = true; | |
| 848 } else { | 857 } else { |
| 849 // A field initializer. | 858 // A field initializer. |
| 850 SendSet init = link.head; | 859 SendSet init = link.head; |
| 851 Link<Node> arguments = init.arguments; | 860 Link<Node> arguments = init.arguments; |
| 852 assert(!arguments.isEmpty() && arguments.tail.isEmpty()); | 861 assert(!arguments.isEmpty() && arguments.tail.isEmpty()); |
| 853 visit(arguments.head); | 862 visit(arguments.head); |
| 854 fieldValues[elements[init]] = pop(); | 863 fieldValues[elements[init]] = pop(); |
| 855 } | 864 } |
| 856 } | 865 } |
| 857 } | 866 } |
| 858 | 867 |
| 859 if (!initializedSuper) { | 868 if (!foundSuperOrRedirect) { |
| 860 // No super initializer found. Try to find the default constructor if | 869 // No super initializer found. Try to find the default constructor if |
| 861 // the class is not Object. | 870 // the class is not Object. |
| 862 ClassElement enclosingClass = constructor.enclosingElement; | 871 ClassElement enclosingClass = constructor.enclosingElement; |
| 863 ClassElement superClass = enclosingClass.superclass; | 872 ClassElement superClass = enclosingClass.superclass; |
| 864 if (enclosingClass != compiler.objectClass) { | 873 if (enclosingClass != compiler.objectClass) { |
| 865 assert(superClass !== null); | 874 assert(superClass !== null); |
| 866 assert(superClass.isResolved); | 875 assert(superClass.isResolved); |
| 867 FunctionElement nextConstructor = | 876 FunctionElement target = superClass.lookupConstructor(superClass.name); |
| 868 superClass.lookupConstructor(superClass.name); | 877 if (target === null) { |
| 869 if (nextConstructor === null) { | |
| 870 compiler.internalError("no default constructor available"); | 878 compiler.internalError("no default constructor available"); |
| 871 } | 879 } |
| 872 inlineInitializers(nextConstructor, constructors, fieldValues); | 880 NodeList emptyNodeList = new NodeList(nodes: const EmptyLink()); |
| 881 Send syntheticSend = new Send(null, null, emptyNodeList); | |
| 882 inlineSuperOrRedirect(target, syntheticSend, constructors, fieldValues); | |
| 873 } | 883 } |
| 874 } | 884 } |
| 875 | |
| 876 elements = oldElements; | |
| 877 } | 885 } |
| 878 | 886 |
| 879 /** | 887 /** |
| 880 * Build the factory function corresponding to the constructor | 888 * Build the factory function corresponding to the constructor |
| 881 * [functionElement]: | 889 * [functionElement]: |
| 882 * - Initialize fields with the values of the field initializers of the | 890 * - Initialize fields with the values of the field initializers of the |
| 883 * current constructor and super constructors or constructors redirected | 891 * current constructor and super constructors or constructors redirected |
| 884 * to, starting from the current constructor. | 892 * to, starting from the current constructor. |
| 885 * - Call the the constructor bodies, starting from the constructor(s) in the | 893 * - Call the the constructor bodies, starting from the constructor(s) in the |
| 886 * super class(es). | 894 * super class(es). |
| (...skipping 15 matching lines...) Expand all Loading... | |
| 902 // If the [element] is a field-parameter (such as [:this.x:] then | 910 // If the [element] is a field-parameter (such as [:this.x:] then |
| 903 // initialize the field element with its value. | 911 // initialize the field element with its value. |
| 904 FieldParameterElement fieldParameterElement = element; | 912 FieldParameterElement fieldParameterElement = element; |
| 905 HInstruction parameterValue = localsHandler.readLocal(element); | 913 HInstruction parameterValue = localsHandler.readLocal(element); |
| 906 fieldValues[fieldParameterElement.fieldElement] = parameterValue; | 914 fieldValues[fieldParameterElement.fieldElement] = parameterValue; |
| 907 } | 915 } |
| 908 }); | 916 }); |
| 909 | 917 |
| 910 final Map<FunctionElement, TreeElements> constructorElements = | 918 final Map<FunctionElement, TreeElements> constructorElements = |
| 911 compiler.resolver.constructorElements; | 919 compiler.resolver.constructorElements; |
| 912 List<FunctionElement> constructors = new List<FunctionElement>(); | 920 List<FunctionElement> constructors = <FunctionElement>[functionElement]; |
| 913 | 921 |
| 914 // Analyze the constructor and all referenced constructors and collect | 922 // Analyze the constructor and all referenced constructors and collect |
| 915 // initializers and constructor bodies. | 923 // initializers and constructor bodies. |
| 916 inlineInitializers(functionElement, constructors, fieldValues); | 924 buildInitializers(functionElement, constructors, fieldValues); |
| 917 | 925 |
| 918 // Call the JavaScript constructor with the fields as argument. | 926 // Call the JavaScript constructor with the fields as argument. |
| 919 List<HInstruction> constructorArguments = <HInstruction>[]; | 927 List<HInstruction> constructorArguments = <HInstruction>[]; |
| 920 classElement.forEachInstanceField( | 928 classElement.forEachInstanceField( |
| 921 includeBackendMembers: true, | 929 includeBackendMembers: true, |
| 922 includeSuperMembers: true, | 930 includeSuperMembers: true, |
| 923 f: (ClassElement enclosingClass, Element member) { | 931 f: (ClassElement enclosingClass, Element member) { |
| 924 HInstruction value = fieldValues[member]; | 932 HInstruction value = fieldValues[member]; |
| 925 if (value === null) { | 933 if (value === null) { |
| 926 // The field has no value in the initializer list. Initialize it | 934 // The field has no value in the initializer list. Initialize it |
| (...skipping 816 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1743 visit(argument); | 1751 visit(argument); |
| 1744 return pop(); | 1752 return pop(); |
| 1745 } | 1753 } |
| 1746 | 1754 |
| 1747 HInstruction compileConstant(Element constantElement) { | 1755 HInstruction compileConstant(Element constantElement) { |
| 1748 Constant constant = compiler.compileVariable(constantElement); | 1756 Constant constant = compiler.compileVariable(constantElement); |
| 1749 return graph.addConstant(constant); | 1757 return graph.addConstant(constant); |
| 1750 } | 1758 } |
| 1751 | 1759 |
| 1752 Selector selector = elements.getSelector(node); | 1760 Selector selector = elements.getSelector(node); |
| 1761 // For an implicit super call we construct a synthetic send which is not | |
| 1762 // in the elements. | |
| 1763 if (selector == null) { | |
| 1764 assert(node.argumentsNode.isEmpty()); | |
| 1765 selector = Selector.INVOCATION_0; | |
| 1766 } | |
|
ngeoffray
2012/03/30 09:10:03
I think the creation of the synthethized node, and
floitsch
2012/03/30 18:18:28
Not sure. (I changed this line from "I disagree",
| |
| 1753 FunctionParameters parameters = element.computeParameters(compiler); | 1767 FunctionParameters parameters = element.computeParameters(compiler); |
| 1754 bool succeeded = selector.addSendArgumentsToList(node, list, parameters, | 1768 bool succeeded = selector.addSendArgumentsToList(node, list, parameters, |
| 1755 compileArgument, | 1769 compileArgument, |
| 1756 compileConstant); | 1770 compileConstant); |
| 1757 if (!succeeded) { | 1771 if (!succeeded) { |
| 1758 // TODO(ngeoffray): Match the VM behavior and throw an | 1772 // TODO(ngeoffray): Match the VM behavior and throw an |
| 1759 // exception at runtime. | 1773 // exception at runtime. |
| 1760 compiler.cancel('Unimplemented non-matching static call', node: node); | 1774 compiler.cancel('Unimplemented non-matching static call', node: node); |
| 1761 } | 1775 } |
| 1762 } | 1776 } |
| (...skipping 1207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 2970 false, | 2984 false, |
| 2971 <HInstruction>[target, input])); | 2985 <HInstruction>[target, input])); |
| 2972 return builder.pop(); | 2986 return builder.pop(); |
| 2973 } | 2987 } |
| 2974 | 2988 |
| 2975 HInstruction result() { | 2989 HInstruction result() { |
| 2976 flushLiterals(); | 2990 flushLiterals(); |
| 2977 return prefix; | 2991 return prefix; |
| 2978 } | 2992 } |
| 2979 } | 2993 } |
| OLD | NEW |