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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/compile_time_constants.dart

Issue 19754002: Rewrite how we handle synthesized constructors in the compiler. This was motivated by issue https:/… (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 5 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 part of dart2js; 5 part of dart2js;
6 6
7 /** 7 /**
8 * The [ConstantHandler] keeps track of compile-time constants, 8 * The [ConstantHandler] keeps track of compile-time constants,
9 * initializations of global and static fields, and default values of 9 * initializations of global and static fields, and default values of
10 * optional parameters. 10 * optional parameters.
(...skipping 671 matching lines...) Expand 10 before | Expand all | Expand 10 after
682 } 682 }
683 683
684 Send send = node.send; 684 Send send = node.send;
685 FunctionElement constructor = elements[send]; 685 FunctionElement constructor = elements[send];
686 // TODO(ahe): This is nasty: we must eagerly analyze the 686 // TODO(ahe): This is nasty: we must eagerly analyze the
687 // constructor to ensure the redirectionTarget has been computed 687 // constructor to ensure the redirectionTarget has been computed
688 // correctly. Find a way to avoid this. 688 // correctly. Find a way to avoid this.
689 compiler.analyzeElement(constructor.declaration); 689 compiler.analyzeElement(constructor.declaration);
690 690
691 InterfaceType type = elements.getType(node); 691 InterfaceType type = elements.getType(node);
692 if ( constructor.isRedirectingFactory) { 692 if (constructor.isRedirectingFactory) {
693 type = constructor.computeTargetType(compiler, type); 693 type = constructor.computeTargetType(compiler, type);
694 } 694 }
695 695
696 constructor = constructor.redirectionTarget; 696 constructor = constructor.redirectionTarget;
697 ClassElement classElement = constructor.getEnclosingClass(); 697 ClassElement classElement = constructor.getEnclosingClass();
698 // The constructor must be an implementation to ensure that field 698 // The constructor must be an implementation to ensure that field
699 // initializers are handled correctly. 699 // initializers are handled correctly.
700 constructor = constructor.implementation; 700 constructor = constructor.implementation;
701 assert(invariant(node, constructor.isImplementation)); 701 assert(invariant(node, constructor.isImplementation));
702 702
703 Selector selector = elements.getSelector(send); 703 Selector selector = elements.getSelector(send);
704 List<Constant> arguments = evaluateArgumentsToConstructor( 704 List<Constant> arguments = evaluateArgumentsToConstructor(
705 node, selector, send.arguments, constructor); 705 node, selector, send.arguments, constructor);
706 ConstructorEvaluator evaluator = 706 ConstructorEvaluator evaluator =
707 new ConstructorEvaluator(node, constructor, handler, compiler); 707 new ConstructorEvaluator(constructor, handler, compiler);
708 evaluator.evaluateConstructorFieldValues(arguments); 708 evaluator.evaluateConstructorFieldValues(arguments);
709 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); 709 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement);
710 710
711 handler.registerInstantiatedType(type, elements); 711 handler.registerInstantiatedType(type, elements);
712 Constant constant = new ConstructedConstant(type, jsNewArguments); 712 Constant constant = new ConstructedConstant(type, jsNewArguments);
713 handler.registerCompileTimeConstant(constant, elements); 713 handler.registerCompileTimeConstant(constant, elements);
714 return constant; 714 return constant;
715 } 715 }
716 716
717 Constant visitParenthesizedExpression(ParenthesizedExpression node) { 717 Constant visitParenthesizedExpression(ParenthesizedExpression node) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
754 class ConstructorEvaluator extends CompileTimeConstantEvaluator { 754 class ConstructorEvaluator extends CompileTimeConstantEvaluator {
755 final FunctionElement constructor; 755 final FunctionElement constructor;
756 final Map<Element, Constant> definitions; 756 final Map<Element, Constant> definitions;
757 final Map<Element, Constant> fieldValues; 757 final Map<Element, Constant> fieldValues;
758 758
759 /** 759 /**
760 * Documentation wanted -- johnniwinther 760 * Documentation wanted -- johnniwinther
761 * 761 *
762 * Invariant: [constructor] must be an implementation element. 762 * Invariant: [constructor] must be an implementation element.
763 */ 763 */
764 ConstructorEvaluator(Node node, 764 ConstructorEvaluator(FunctionElement constructor,
765 FunctionElement constructor,
766 ConstantHandler handler, 765 ConstantHandler handler,
767 Compiler compiler) 766 Compiler compiler)
768 : this.constructor = constructor, 767 : this.constructor = constructor,
769 this.definitions = new Map<Element, Constant>(), 768 this.definitions = new Map<Element, Constant>(),
770 this.fieldValues = new Map<Element, Constant>(), 769 this.fieldValues = new Map<Element, Constant>(),
771 super(handler, 770 super(handler,
772 compiler.resolver.resolveMethodElement(constructor.declaration), 771 compiler.resolver.resolveMethodElement(constructor.declaration),
773 compiler, 772 compiler,
774 isConst: true) { 773 isConst: true) {
775 assert(invariant(node, constructor.isImplementation)); 774 assert(invariant(constructor, constructor.isImplementation));
776 } 775 }
777 776
778 Constant visitSend(Send send) { 777 Constant visitSend(Send send) {
779 Element element = elements[send]; 778 Element element = elements[send];
780 if (Elements.isLocal(element)) { 779 if (Elements.isLocal(element)) {
781 Constant constant = definitions[element]; 780 Constant constant = definitions[element];
782 if (constant == null) { 781 if (constant == null) {
783 compiler.internalError("Local variable without value", node: send); 782 compiler.internalError("Local variable without value", node: send);
784 } 783 }
785 return constant; 784 return constant;
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
821 Node node = parameter.parseNode(compiler); 820 Node node = parameter.parseNode(compiler);
822 potentiallyCheckType(node, parameter, argument); 821 potentiallyCheckType(node, parameter, argument);
823 definitions[parameter] = argument; 822 definitions[parameter] = argument;
824 if (parameter.kind == ElementKind.FIELD_PARAMETER) { 823 if (parameter.kind == ElementKind.FIELD_PARAMETER) {
825 FieldParameterElement fieldParameterElement = parameter; 824 FieldParameterElement fieldParameterElement = parameter;
826 updateFieldValue(node, fieldParameterElement.fieldElement, argument); 825 updateFieldValue(node, fieldParameterElement.fieldElement, argument);
827 } 826 }
828 }); 827 });
829 } 828 }
830 829
831 void evaluateSuperOrRedirectSend(Node currentNode, 830 void evaluateSuperOrRedirectSend(List<Constant> compiledArguments,
832 Selector selector,
833 Link<Node> arguments,
834 FunctionElement targetConstructor) { 831 FunctionElement targetConstructor) {
835 List<Constant> compiledArguments = evaluateArgumentsToConstructor(
836 currentNode, selector, arguments, targetConstructor);
837
838 ConstructorEvaluator evaluator = new ConstructorEvaluator( 832 ConstructorEvaluator evaluator = new ConstructorEvaluator(
839 currentNode, targetConstructor, handler, compiler); 833 targetConstructor, handler, compiler);
840 evaluator.evaluateConstructorFieldValues(compiledArguments); 834 evaluator.evaluateConstructorFieldValues(compiledArguments);
841 // Copy over the fieldValues from the super/redirect-constructor. 835 // Copy over the fieldValues from the super/redirect-constructor.
842 // No need to go through [updateFieldValue] because the 836 // No need to go through [updateFieldValue] because the
843 // assignments have already been checked in checked mode. 837 // assignments have already been checked in checked mode.
844 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); 838 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value);
845 } 839 }
846 840
847 /** 841 /**
848 * Runs through the initializers of the given [constructor] and updates 842 * Runs through the initializers of the given [constructor] and updates
849 * the [fieldValues] map. 843 * the [fieldValues] map.
850 */ 844 */
851 void evaluateConstructorInitializers() { 845 void evaluateConstructorInitializers() {
846 if (constructor.isSynthesized) {
847 List<Constant> compiledArguments = <Constant>[];
848
849 Function compileArgument = (element) => definitions[element];
850 Function compileConstant = handler.compileConstant;
851 FunctionElement target = constructor.targetConstructor.implementation;
852 Selector.addForwardingElementArgumentsToList(constructor,
853 compiledArguments,
854 target,
855 compileArgument,
856 compileConstant,
857 compiler);
858 evaluateSuperOrRedirectSend(compiledArguments, target);
859 return;
860 }
852 FunctionExpression functionNode = constructor.parseNode(compiler); 861 FunctionExpression functionNode = constructor.parseNode(compiler);
853 NodeList initializerList = functionNode.initializers; 862 NodeList initializerList = functionNode.initializers;
854 863
855 bool foundSuperOrRedirect = false; 864 bool foundSuperOrRedirect = false;
856 865
857 if (initializerList != null) { 866 if (initializerList != null) {
858 for (Link<Node> link = initializerList.nodes; 867 for (Link<Node> link = initializerList.nodes;
859 !link.isEmpty; 868 !link.isEmpty;
860 link = link.tail) { 869 link = link.tail) {
861 assert(link.head is Send); 870 assert(link.head is Send);
862 if (link.head is !SendSet) { 871 if (link.head is !SendSet) {
863 // A super initializer or constructor redirection. 872 // A super initializer or constructor redirection.
864 Send call = link.head; 873 Send call = link.head;
865 FunctionElement targetConstructor = elements[call]; 874 FunctionElement target = elements[call];
866 Selector selector = elements.getSelector(call); 875 List<Constant> compiledArguments = evaluateArgumentsToConstructor(
867 Link<Node> arguments = call.arguments; 876 call, elements.getSelector(call), call.arguments, target);
868 evaluateSuperOrRedirectSend( 877 evaluateSuperOrRedirectSend(compiledArguments, target);
869 call, selector, arguments, targetConstructor);
870 foundSuperOrRedirect = true; 878 foundSuperOrRedirect = true;
871 } else { 879 } else {
872 // A field initializer. 880 // A field initializer.
873 SendSet init = link.head; 881 SendSet init = link.head;
874 Link<Node> initArguments = init.arguments; 882 Link<Node> initArguments = init.arguments;
875 assert(!initArguments.isEmpty && initArguments.tail.isEmpty); 883 assert(!initArguments.isEmpty && initArguments.tail.isEmpty);
876 Constant fieldValue = evaluate(initArguments.head); 884 Constant fieldValue = evaluate(initArguments.head);
877 updateFieldValue(init, elements[init], fieldValue); 885 updateFieldValue(init, elements[init], fieldValue);
878 } 886 }
879 } 887 }
(...skipping 10 matching lines...) Expand all
890 898
891 Selector selector = 899 Selector selector =
892 new Selector.callDefaultConstructor(enclosingClass.getLibrary()); 900 new Selector.callDefaultConstructor(enclosingClass.getLibrary());
893 901
894 FunctionElement targetConstructor = 902 FunctionElement targetConstructor =
895 superClass.lookupConstructor(selector); 903 superClass.lookupConstructor(selector);
896 if (targetConstructor == null) { 904 if (targetConstructor == null) {
897 compiler.internalError("no default constructor available", 905 compiler.internalError("no default constructor available",
898 node: functionNode); 906 node: functionNode);
899 } 907 }
900 908 List<Constant> compiledArguments = evaluateArgumentsToConstructor(
901 evaluateSuperOrRedirectSend(functionNode, 909 functionNode, selector, const Link<Node>(), targetConstructor);
902 selector, 910 evaluateSuperOrRedirectSend(compiledArguments, targetConstructor);
903 const Link<Node>(),
904 targetConstructor);
905 } 911 }
906 } 912 }
907 } 913 }
908 914
909 /** 915 /**
910 * Simulates the execution of the [constructor] with the given 916 * Simulates the execution of the [constructor] with the given
911 * [arguments] to obtain the field values that need to be passed to the 917 * [arguments] to obtain the field values that need to be passed to the
912 * native JavaScript constructor. 918 * native JavaScript constructor.
913 */ 919 */
914 void evaluateConstructorFieldValues(List<Constant> arguments) { 920 void evaluateConstructorFieldValues(List<Constant> arguments) {
(...skipping 11 matching lines...) Expand all
926 if (fieldValue == null) { 932 if (fieldValue == null) {
927 // Use the default value. 933 // Use the default value.
928 fieldValue = handler.compileConstant(field); 934 fieldValue = handler.compileConstant(field);
929 } 935 }
930 jsNewArguments.add(fieldValue); 936 jsNewArguments.add(fieldValue);
931 }, 937 },
932 includeSuperAndInjectedMembers: true); 938 includeSuperAndInjectedMembers: true);
933 return jsNewArguments; 939 return jsNewArguments;
934 } 940 }
935 } 941 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/closure.dart ('k') | sdk/lib/_internal/compiler/implementation/compiler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698