Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(82)

Side by Side Diff: lib/compiler/implementation/ssa/builder.dart

Issue 10094013: Reapply "Use default values of named arguments when invoking the default super constructor." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix test. Created 8 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 785 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 TreeElements treeElements = 796 TreeElements treeElements =
797 compiler.resolver.resolveMethodElement(constructor); 797 compiler.resolver.resolveMethodElement(constructor);
798 compiler.enqueue(new WorkItem.toCodegen(bodyElement, treeElements)); 798 compiler.enqueue(new WorkItem.toCodegen(bodyElement, treeElements));
799 classElement.backendMembers = 799 classElement.backendMembers =
800 classElement.backendMembers.prepend(bodyElement); 800 classElement.backendMembers.prepend(bodyElement);
801 } 801 }
802 assert(bodyElement.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY); 802 assert(bodyElement.kind === ElementKind.GENERATIVE_CONSTRUCTOR_BODY);
803 return bodyElement; 803 return bodyElement;
804 } 804 }
805 805
806 void inlineSuperOrRedirect(FunctionElement constructor,
807 Selector selector,
808 Link<Node> arguments,
809 List<FunctionElement> constructors,
810 Map<Element, HInstruction> fieldValues) {
811 constructors.addLast(constructor);
812
813 List<HInstruction> compiledArguments = new List<HInstruction>();
814 bool succeeded = addStaticSendArgumentsToList(selector,
815 arguments,
816 constructor,
817 compiledArguments);
818 if (!succeeded) {
819 // Non-matching super and redirects are compile-time errors and thus
820 // checked by the resolver.
821 compiler.internalError(
822 "Parameters and arguments didn't match for super/redirect call",
823 element: constructor);
824 }
825
826 int index = 0;
827 FunctionParameters parameters = constructor.computeParameters(compiler);
828 parameters.forEachParameter((Element parameter) {
829 HInstruction argument = compiledArguments[index++];
830 localsHandler.updateLocal(parameter, argument);
831 // Don't forget to update the field, if the parameter is of the
832 // form [:this.x:].
833 if (parameter.kind == ElementKind.FIELD_PARAMETER) {
834 FieldParameterElement fieldParameterElement = parameter;
835 fieldValues[fieldParameterElement.fieldElement] = argument;
836 }
837 });
838
839 // Build the initializers in the context of the new constructor.
840 TreeElements oldElements = elements;
841 elements = compiler.resolver.resolveMethodElement(constructor);
842 buildInitializers(constructor, constructors, fieldValues);
843 elements = oldElements;
844 }
806 /** 845 /**
807 * Run through the initializers and inline all field initializers. Recursively 846 * Run through the initializers and inline all field initializers. Recursively
808 * inlines super initializers. 847 * inlines super initializers.
809 * 848 *
810 * The constructors of the inlined initializers is added to [constructors] 849 * The constructors of the inlined initializers is added to [constructors]
811 * with sub constructors having a lower index than super constructors. 850 * with sub constructors having a lower index than super constructors.
812 */ 851 */
813 void inlineInitializers(FunctionElement constructor, 852 void buildInitializers(FunctionElement constructor,
814 List<FunctionElement> constructors, 853 List<FunctionElement> constructors,
815 Map<Element, HInstruction> fieldValues) { 854 Map<Element, HInstruction> fieldValues) {
816 TreeElements oldElements = elements;
817 constructors.addLast(constructor);
818 bool initializedSuper = false;
819 elements = compiler.resolver.resolveMethodElement(constructor);
820 FunctionExpression functionNode = constructor.parseNode(compiler); 855 FunctionExpression functionNode = constructor.parseNode(compiler);
821 856
857 bool foundSuperOrRedirect = false;
858
822 if (functionNode.initializers !== null) { 859 if (functionNode.initializers !== null) {
823 Link<Node> initializers = functionNode.initializers.nodes; 860 Link<Node> initializers = functionNode.initializers.nodes;
824 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) { 861 for (Link<Node> link = initializers; !link.isEmpty(); link = link.tail) {
825 assert(link.head is Send); 862 assert(link.head is Send);
826 if (link.head is !SendSet) { 863 if (link.head is !SendSet) {
827 // A super initializer or constructor redirection. 864 // A super initializer or constructor redirection.
828 Send call = link.head; 865 Send call = link.head;
829 assert(Initializers.isSuperConstructorCall(call) || 866 assert(Initializers.isSuperConstructorCall(call) ||
830 Initializers.isConstructorRedirect(call)); 867 Initializers.isConstructorRedirect(call));
831 FunctionElement nextConstructor = elements[call]; 868 FunctionElement target = elements[call];
832 // Visit arguments and map the corresponding parameter value to 869 Selector selector = elements.getSelector(call);
833 // the resulting HInstruction value. 870 Link<Node> arguments = call.arguments;
834 List<HInstruction> arguments = new List<HInstruction>(); 871 inlineSuperOrRedirect(target, selector, arguments, constructors,
835 addStaticSendArgumentsToList(call, nextConstructor, arguments); 872 fieldValues);
836 int index = 0; 873 foundSuperOrRedirect = true;
837 FunctionParameters parameters =
838 nextConstructor.computeParameters(compiler);
839 parameters.forEachParameter((Element parameter) {
840 HInstruction argument = arguments[index++];
841 localsHandler.updateLocal(parameter, argument);
842 // Don't forget to update the field, if the parameter is of the
843 // form [:this.x:].
844 if (parameter.kind == ElementKind.FIELD_PARAMETER) {
845 FieldParameterElement fieldParameterElement = parameter;
846 fieldValues[fieldParameterElement.fieldElement] = argument;
847 }
848 });
849 inlineInitializers(nextConstructor, constructors, fieldValues);
850 initializedSuper = true;
851 } else { 874 } else {
852 // A field initializer. 875 // A field initializer.
853 SendSet init = link.head; 876 SendSet init = link.head;
854 Link<Node> arguments = init.arguments; 877 Link<Node> arguments = init.arguments;
855 assert(!arguments.isEmpty() && arguments.tail.isEmpty()); 878 assert(!arguments.isEmpty() && arguments.tail.isEmpty());
856 visit(arguments.head); 879 visit(arguments.head);
857 fieldValues[elements[init]] = pop(); 880 fieldValues[elements[init]] = pop();
858 } 881 }
859 } 882 }
860 } 883 }
861 884
862 if (!initializedSuper) { 885 if (!foundSuperOrRedirect) {
863 // No super initializer found. Try to find the default constructor if 886 // No super initializer found. Try to find the default constructor if
864 // the class is not Object. 887 // the class is not Object.
865 ClassElement enclosingClass = constructor.enclosingElement; 888 ClassElement enclosingClass = constructor.enclosingElement;
866 ClassElement superClass = enclosingClass.superclass; 889 ClassElement superClass = enclosingClass.superclass;
867 if (enclosingClass != compiler.objectClass) { 890 if (enclosingClass != compiler.objectClass) {
868 assert(superClass !== null); 891 assert(superClass !== null);
869 assert(superClass.isResolved); 892 assert(superClass.isResolved);
870 FunctionElement nextConstructor = 893 FunctionElement target = superClass.lookupConstructor(superClass.name);
871 superClass.lookupConstructor(superClass.name); 894 if (target === null) {
872 if (nextConstructor === null) {
873 compiler.internalError("no default constructor available"); 895 compiler.internalError("no default constructor available");
874 } 896 }
875 inlineInitializers(nextConstructor, constructors, fieldValues); 897 inlineSuperOrRedirect(target,
898 Selector.INVOCATION_0,
899 const EmptyLink<Node>(),
900 constructors,
901 fieldValues);
876 } 902 }
877 } 903 }
878
879 elements = oldElements;
880 } 904 }
881 905
882 /** 906 /**
883 * Build the factory function corresponding to the constructor 907 * Build the factory function corresponding to the constructor
884 * [functionElement]: 908 * [functionElement]:
885 * - Initialize fields with the values of the field initializers of the 909 * - Initialize fields with the values of the field initializers of the
886 * current constructor and super constructors or constructors redirected 910 * current constructor and super constructors or constructors redirected
887 * to, starting from the current constructor. 911 * to, starting from the current constructor.
888 * - Call the the constructor bodies, starting from the constructor(s) in the 912 * - Call the the constructor bodies, starting from the constructor(s) in the
889 * super class(es). 913 * super class(es).
(...skipping 15 matching lines...) Expand all
905 // If the [element] is a field-parameter (such as [:this.x:] then 929 // If the [element] is a field-parameter (such as [:this.x:] then
906 // initialize the field element with its value. 930 // initialize the field element with its value.
907 FieldParameterElement fieldParameterElement = element; 931 FieldParameterElement fieldParameterElement = element;
908 HInstruction parameterValue = localsHandler.readLocal(element); 932 HInstruction parameterValue = localsHandler.readLocal(element);
909 fieldValues[fieldParameterElement.fieldElement] = parameterValue; 933 fieldValues[fieldParameterElement.fieldElement] = parameterValue;
910 } 934 }
911 }); 935 });
912 936
913 final Map<FunctionElement, TreeElements> constructorElements = 937 final Map<FunctionElement, TreeElements> constructorElements =
914 compiler.resolver.constructorElements; 938 compiler.resolver.constructorElements;
915 List<FunctionElement> constructors = new List<FunctionElement>(); 939 List<FunctionElement> constructors = <FunctionElement>[functionElement];
916 940
917 // Analyze the constructor and all referenced constructors and collect 941 // Analyze the constructor and all referenced constructors and collect
918 // initializers and constructor bodies. 942 // initializers and constructor bodies.
919 inlineInitializers(functionElement, constructors, fieldValues); 943 buildInitializers(functionElement, constructors, fieldValues);
920 944
921 // Call the JavaScript constructor with the fields as argument. 945 // Call the JavaScript constructor with the fields as argument.
922 List<HInstruction> constructorArguments = <HInstruction>[]; 946 List<HInstruction> constructorArguments = <HInstruction>[];
923 classElement.forEachInstanceField( 947 classElement.forEachInstanceField(
924 includeBackendMembers: true, 948 includeBackendMembers: true,
925 includeSuperMembers: true, 949 includeSuperMembers: true,
926 f: (ClassElement enclosingClass, Element member) { 950 f: (ClassElement enclosingClass, Element member) {
927 HInstruction value = fieldValues[member]; 951 HInstruction value = fieldValues[member];
928 if (value === null) { 952 if (value === null) {
929 // The field has no value in the initializer list. Initialize it 953 // The field has no value in the initializer list. Initialize it
(...skipping 841 matching lines...) Expand 10 before | Expand all | Expand 10 after
1771 // Iterate through the named arguments to add them to the list 1795 // Iterate through the named arguments to add them to the list
1772 // of instructions, in an order that can be shared with 1796 // of instructions, in an order that can be shared with
1773 // selectors with the same named arguments. 1797 // selectors with the same named arguments.
1774 List<SourceString> orderedNames = selector.getOrderedNamedArguments(); 1798 List<SourceString> orderedNames = selector.getOrderedNamedArguments();
1775 for (SourceString name in orderedNames) { 1799 for (SourceString name in orderedNames) {
1776 list.add(instructions[name]); 1800 list.add(instructions[name]);
1777 } 1801 }
1778 } 1802 }
1779 } 1803 }
1780 1804
1781 void addStaticSendArgumentsToList(Send node, 1805 /**
1806 * Returns true if the arguments were compatible with the function signature.
1807 */
1808 bool addStaticSendArgumentsToList(Selector selector,
1809 Link<Node> arguments,
1782 FunctionElement element, 1810 FunctionElement element,
1783 List<HInstruction> list) { 1811 List<HInstruction> list) {
1784 HInstruction compileArgument(Node argument) { 1812 HInstruction compileArgument(Node argument) {
1785 visit(argument); 1813 visit(argument);
1786 return pop(); 1814 return pop();
1787 } 1815 }
1788 1816
1789 HInstruction compileConstant(Element constantElement) { 1817 HInstruction compileConstant(Element constantElement) {
1790 Constant constant = compiler.compileVariable(constantElement); 1818 Constant constant = compiler.compileVariable(constantElement);
1791 return graph.addConstant(constant); 1819 return graph.addConstant(constant);
1792 } 1820 }
1793 1821
1794 Selector selector = elements.getSelector(node);
1795 FunctionParameters parameters = element.computeParameters(compiler); 1822 FunctionParameters parameters = element.computeParameters(compiler);
1796 bool succeeded = selector.addSendArgumentsToList(node, list, parameters, 1823 return selector.addArgumentsToList(arguments, list, parameters,
1797 compileArgument, 1824 compileArgument, compileConstant);
1798 compileConstant);
1799 if (!succeeded) {
1800 // TODO(ngeoffray): Match the VM behavior and throw an
1801 // exception at runtime.
1802 compiler.cancel('Unimplemented non-matching static call', node: node);
1803 }
1804 } 1825 }
1805 1826
1806 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { 1827 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) {
1807 for (; !link.isEmpty(); link = link.tail) { 1828 for (; !link.isEmpty(); link = link.tail) {
1808 visit(link.head); 1829 visit(link.head);
1809 list.add(pop()); 1830 list.add(pop());
1810 } 1831 }
1811 } 1832 }
1812 1833
1813 visitDynamicSend(Send node) { 1834 visitDynamicSend(Send node) {
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
2059 push(new HInvokeSuper(const Selector(SelectorKind.INVOCATION, 2), 2080 push(new HInvokeSuper(const Selector(SelectorKind.INVOCATION, 2),
2060 inputs)); 2081 inputs));
2061 return; 2082 return;
2062 } 2083 }
2063 HInstruction target = new HStatic(element); 2084 HInstruction target = new HStatic(element);
2064 HInstruction context = localsHandler.readThis(); 2085 HInstruction context = localsHandler.readThis();
2065 add(target); 2086 add(target);
2066 var inputs = <HInstruction>[target, context]; 2087 var inputs = <HInstruction>[target, context];
2067 if (element.kind == ElementKind.FUNCTION || 2088 if (element.kind == ElementKind.FUNCTION ||
2068 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { 2089 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
2069 addStaticSendArgumentsToList(node, element, inputs); 2090 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
2091 element, inputs);
2092 if (!succeeded) {
2093 // TODO(ngeoffray): Match the VM behavior and throw an
2094 // exception at runtime.
2095 compiler.cancel('Unimplemented non-matching static call', node);
2096 }
2070 push(new HInvokeSuper(selector, inputs)); 2097 push(new HInvokeSuper(selector, inputs));
2071 } else { 2098 } else {
2072 target = new HInvokeSuper(Selector.GETTER, inputs); 2099 target = new HInvokeSuper(Selector.GETTER, inputs);
2073 add(target); 2100 add(target);
2074 inputs = <HInstruction>[target]; 2101 inputs = <HInstruction>[target];
2075 addDynamicSendArgumentsToList(node, inputs); 2102 addDynamicSendArgumentsToList(node, inputs);
2076 push(new HInvokeClosure(selector, inputs)); 2103 push(new HInvokeClosure(selector, inputs));
2077 } 2104 }
2078 } 2105 }
2079 2106
2080 visitStaticSend(Send node) { 2107 visitStaticSend(Send node) {
2081 Selector selector = elements.getSelector(node); 2108 Selector selector = elements.getSelector(node);
2082 Element element = elements[node]; 2109 Element element = elements[node];
2083 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR) { 2110 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR) {
2084 compiler.resolver.resolveMethodElement(element); 2111 compiler.resolver.resolveMethodElement(element);
2085 FunctionElement functionElement = element; 2112 FunctionElement functionElement = element;
2086 element = functionElement.defaultImplementation; 2113 element = functionElement.defaultImplementation;
2087 } 2114 }
2088 HInstruction target = new HStatic(element); 2115 HInstruction target = new HStatic(element);
2089 add(target); 2116 add(target);
2090 var inputs = <HInstruction>[]; 2117 var inputs = <HInstruction>[];
2091 inputs.add(target); 2118 inputs.add(target);
2092 if (element.kind == ElementKind.FUNCTION || 2119 if (element.kind == ElementKind.FUNCTION ||
2093 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { 2120 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
2094 addStaticSendArgumentsToList(node, element, inputs); 2121 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
2122 element, inputs);
2123 if (!succeeded) {
2124 // TODO(ngeoffray): Match the VM behavior and throw an
2125 // exception at runtime.
2126 compiler.cancel('Unimplemented non-matching static call', node: node);
2127 }
2095 push(new HInvokeStatic(selector, inputs)); 2128 push(new HInvokeStatic(selector, inputs));
2096 } else { 2129 } else {
2097 if (element.kind == ElementKind.GETTER) { 2130 if (element.kind == ElementKind.GETTER) {
2098 target = new HInvokeStatic(Selector.GETTER, inputs); 2131 target = new HInvokeStatic(Selector.GETTER, inputs);
2099 add(target); 2132 add(target);
2100 inputs = <HInstruction>[target]; 2133 inputs = <HInstruction>[target];
2101 } 2134 }
2102 addDynamicSendArgumentsToList(node, inputs); 2135 addDynamicSendArgumentsToList(node, inputs);
2103 push(new HInvokeClosure(selector, inputs)); 2136 push(new HInvokeClosure(selector, inputs));
2104 } 2137 }
(...skipping 935 matching lines...) Expand 10 before | Expand all | Expand 10 after
3040 false, 3073 false,
3041 <HInstruction>[target, input])); 3074 <HInstruction>[target, input]));
3042 return builder.pop(); 3075 return builder.pop();
3043 } 3076 }
3044 3077
3045 HInstruction result() { 3078 HInstruction result() {
3046 flushLiterals(); 3079 flushLiterals();
3047 return prefix; 3080 return prefix;
3048 } 3081 }
3049 } 3082 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/compile_time_constants.dart ('k') | lib/compiler/implementation/universe.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698