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

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

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