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

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: Report bad static calls with position (regression fix). 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);
ngeoffray 2012/04/16 12:24:02 Please add a comment why this is an assert and not
floitsch 2012/04/16 14:23:14 changed to internal error.
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");
ngeoffray 2012/04/16 12:24:02 Could you also update the resolver to report the '
floitsch 2012/04/16 14:23:14 The resolver does the right thing now.
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 837 matching lines...) Expand 10 before | Expand all | Expand 10 after
1767 // Iterate through the named arguments to add them to the list 1786 // Iterate through the named arguments to add them to the list
1768 // of instructions, in an order that can be shared with 1787 // of instructions, in an order that can be shared with
1769 // selectors with the same named arguments. 1788 // selectors with the same named arguments.
1770 List<SourceString> orderedNames = selector.getOrderedNamedArguments(); 1789 List<SourceString> orderedNames = selector.getOrderedNamedArguments();
1771 for (SourceString name in orderedNames) { 1790 for (SourceString name in orderedNames) {
1772 list.add(instructions[name]); 1791 list.add(instructions[name]);
1773 } 1792 }
1774 } 1793 }
1775 } 1794 }
1776 1795
1777 void addStaticSendArgumentsToList(Send node, 1796 /**
1797 * Returns true if the arguments were compatible with the function signature.
1798 */
1799 bool addStaticSendArgumentsToList(Selector selector,
1800 Link<Node> arguments,
1778 FunctionElement element, 1801 FunctionElement element,
1779 List<HInstruction> list) { 1802 List<HInstruction> list) {
1780 HInstruction compileArgument(Node argument) { 1803 HInstruction compileArgument(Node argument) {
1781 visit(argument); 1804 visit(argument);
1782 return pop(); 1805 return pop();
1783 } 1806 }
1784 1807
1785 HInstruction compileConstant(Element constantElement) { 1808 HInstruction compileConstant(Element constantElement) {
1786 Constant constant = compiler.compileVariable(constantElement); 1809 Constant constant = compiler.compileVariable(constantElement);
1787 return graph.addConstant(constant); 1810 return graph.addConstant(constant);
1788 } 1811 }
1789 1812
1790 Selector selector = elements.getSelector(node);
1791 FunctionParameters parameters = element.computeParameters(compiler); 1813 FunctionParameters parameters = element.computeParameters(compiler);
1792 bool succeeded = selector.addSendArgumentsToList(node, list, parameters, 1814 return selector.addArgumentsToList(arguments, list, parameters,
1793 compileArgument, 1815 compileArgument, compileConstant);
1794 compileConstant);
1795 if (!succeeded) {
1796 // TODO(ngeoffray): Match the VM behavior and throw an
1797 // exception at runtime.
1798 compiler.cancel('Unimplemented non-matching static call', node: node);
1799 }
1800 } 1816 }
1801 1817
1802 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) { 1818 void addGenericSendArgumentsToList(Link<Node> link, List<HInstruction> list) {
1803 for (; !link.isEmpty(); link = link.tail) { 1819 for (; !link.isEmpty(); link = link.tail) {
1804 visit(link.head); 1820 visit(link.head);
1805 list.add(pop()); 1821 list.add(pop());
1806 } 1822 }
1807 } 1823 }
1808 1824
1809 visitDynamicSend(Send node) { 1825 visitDynamicSend(Send node) {
(...skipping 244 matching lines...) Expand 10 before | Expand all | Expand 10 after
2054 push(new HInvokeSuper(const Selector(SelectorKind.INVOCATION, 2), 2070 push(new HInvokeSuper(const Selector(SelectorKind.INVOCATION, 2),
2055 inputs)); 2071 inputs));
2056 return; 2072 return;
2057 } 2073 }
2058 HInstruction target = new HStatic(element); 2074 HInstruction target = new HStatic(element);
2059 HInstruction context = localsHandler.readThis(); 2075 HInstruction context = localsHandler.readThis();
2060 add(target); 2076 add(target);
2061 var inputs = <HInstruction>[target, context]; 2077 var inputs = <HInstruction>[target, context];
2062 if (element.kind == ElementKind.FUNCTION || 2078 if (element.kind == ElementKind.FUNCTION ||
2063 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { 2079 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
2064 addStaticSendArgumentsToList(node, element, inputs); 2080 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
2081 element, inputs);
2082 if (!succeeded) {
2083 // TODO(ngeoffray): Match the VM behavior and throw an
2084 // exception at runtime.
2085 compiler.cancel('Unimplemented non-matching static call', node);
2086 }
2065 push(new HInvokeSuper(selector, inputs)); 2087 push(new HInvokeSuper(selector, inputs));
2066 } else { 2088 } else {
2067 target = new HInvokeSuper(Selector.GETTER, inputs); 2089 target = new HInvokeSuper(Selector.GETTER, inputs);
2068 add(target); 2090 add(target);
2069 inputs = <HInstruction>[target]; 2091 inputs = <HInstruction>[target];
2070 addDynamicSendArgumentsToList(node, inputs); 2092 addDynamicSendArgumentsToList(node, inputs);
2071 push(new HInvokeClosure(selector, inputs)); 2093 push(new HInvokeClosure(selector, inputs));
2072 } 2094 }
2073 } 2095 }
2074 2096
2075 visitStaticSend(Send node) { 2097 visitStaticSend(Send node) {
2076 Selector selector = elements.getSelector(node); 2098 Selector selector = elements.getSelector(node);
2077 Element element = elements[node]; 2099 Element element = elements[node];
2078 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR) { 2100 if (element.kind === ElementKind.GENERATIVE_CONSTRUCTOR) {
2079 compiler.resolver.resolveMethodElement(element); 2101 compiler.resolver.resolveMethodElement(element);
2080 FunctionElement functionElement = element; 2102 FunctionElement functionElement = element;
2081 element = functionElement.defaultImplementation; 2103 element = functionElement.defaultImplementation;
2082 } 2104 }
2083 HInstruction target = new HStatic(element); 2105 HInstruction target = new HStatic(element);
2084 add(target); 2106 add(target);
2085 var inputs = <HInstruction>[]; 2107 var inputs = <HInstruction>[];
2086 inputs.add(target); 2108 inputs.add(target);
2087 if (element.kind == ElementKind.FUNCTION || 2109 if (element.kind == ElementKind.FUNCTION ||
2088 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) { 2110 element.kind == ElementKind.GENERATIVE_CONSTRUCTOR) {
2089 addStaticSendArgumentsToList(node, element, inputs); 2111 bool succeeded = addStaticSendArgumentsToList(selector, node.arguments,
2112 element, inputs);
2113 if (!succeeded) {
2114 // TODO(ngeoffray): Match the VM behavior and throw an
2115 // exception at runtime.
2116 compiler.cancel('Unimplemented non-matching static call', node: node);
2117 }
2090 push(new HInvokeStatic(selector, inputs)); 2118 push(new HInvokeStatic(selector, inputs));
2091 } else { 2119 } else {
2092 if (element.kind == ElementKind.GETTER) { 2120 if (element.kind == ElementKind.GETTER) {
2093 target = new HInvokeStatic(Selector.GETTER, inputs); 2121 target = new HInvokeStatic(Selector.GETTER, inputs);
2094 add(target); 2122 add(target);
2095 inputs = <HInstruction>[target]; 2123 inputs = <HInstruction>[target];
2096 } 2124 }
2097 addDynamicSendArgumentsToList(node, inputs); 2125 addDynamicSendArgumentsToList(node, inputs);
2098 push(new HInvokeClosure(selector, inputs)); 2126 push(new HInvokeClosure(selector, inputs));
2099 } 2127 }
(...skipping 924 matching lines...) Expand 10 before | Expand all | Expand 10 after
3024 false, 3052 false,
3025 <HInstruction>[target, input])); 3053 <HInstruction>[target, input]));
3026 return builder.pop(); 3054 return builder.pop();
3027 } 3055 }
3028 3056
3029 HInstruction result() { 3057 HInstruction result() {
3030 flushLiterals(); 3058 flushLiterals();
3031 return prefix; 3059 return prefix;
3032 } 3060 }
3033 } 3061 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698