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

Side by Side Diff: frog/leg/ssa/builder.dart

Issue 9699033: Introduce FieldParameterElement. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments and create a separate map for the fields. Created 8 years, 9 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 258 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
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
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 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698