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

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

Issue 10825386: Use JavaScript runtime semantics when constant folding. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address comments. Created 8 years, 3 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
« no previous file with comments | « lib/compiler/implementation/apiimpl.dart ('k') | lib/compiler/implementation/compiler.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 Constant implements Hashable { 5 class Constant implements Hashable {
6 const Constant(); 6 const Constant();
7 7
8 bool isNull() => false; 8 bool isNull() => false;
9 bool isBool() => false; 9 bool isBool() => false;
10 bool isTrue() => false; 10 bool isTrue() => false;
11 bool isFalse() => false; 11 bool isFalse() => false;
12 bool isInt() => false; 12 bool isInt() => false;
13 bool isDouble() => false; 13 bool isDouble() => false;
14 bool isNum() => false; 14 bool isNum() => false;
15 bool isString() => false; 15 bool isString() => false;
16 bool isList() => false; 16 bool isList() => false;
17 bool isMap() => false; 17 bool isMap() => false;
18 bool isConstructedObject() => false; 18 bool isConstructedObject() => false;
19 bool isFunction() => false; 19 bool isFunction() => false;
20 /** Returns true if the constant is null, a bool, a number or a string. */ 20 /** Returns true if the constant is null, a bool, a number or a string. */
21 bool isPrimitive() => false; 21 bool isPrimitive() => false;
22 /** Returns true if the constant is a list, a map or a constructed object. */ 22 /** Returns true if the constant is a list, a map or a constructed object. */
23 bool isObject() => false; 23 bool isObject() => false;
24 bool isSentinel() => false; 24 bool isSentinel() => false;
25 25
26 bool isNaN() => false; 26 bool isNaN() => false;
27 bool isMinusZero() => false;
27 28
28 abstract void _writeJsCode(CodeBuffer buffer, ConstantHandler handler); 29 abstract void _writeJsCode(CodeBuffer buffer, ConstantHandler handler);
29 /** 30 /**
30 * Unless the constant can be emitted multiple times (as for numbers and 31 * Unless the constant can be emitted multiple times (as for numbers and
31 * strings) adds its canonical name to the buffer. 32 * strings) adds its canonical name to the buffer.
32 */ 33 */
33 abstract void _writeCanonicalizedJsCode(CodeBuffer buffer, 34 abstract void _writeCanonicalizedJsCode(CodeBuffer buffer,
34 ConstantHandler handler); 35 ConstantHandler handler);
35 abstract List<Constant> getDependencies(); 36 abstract List<Constant> getDependencies();
36 } 37 }
(...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
186 return const DoubleConstant._internal(0.0); 187 return const DoubleConstant._internal(0.0);
187 } else if (value == 1.0) { 188 } else if (value == 1.0) {
188 return const DoubleConstant._internal(1.0); 189 return const DoubleConstant._internal(1.0);
189 } else { 190 } else {
190 return new DoubleConstant._internal(value); 191 return new DoubleConstant._internal(value);
191 } 192 }
192 } 193 }
193 const DoubleConstant._internal(this.value); 194 const DoubleConstant._internal(this.value);
194 bool isDouble() => true; 195 bool isDouble() => true;
195 bool isNaN() => value.isNaN(); 196 bool isNaN() => value.isNaN();
197 // We need to check for the negative sign since -0.0 == 0.0.
198 bool isMinusZero() => value == 0.0 && value.isNegative();
196 199
197 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) { 200 void _writeJsCode(CodeBuffer buffer, ConstantHandler handler) {
198 if (value.isNaN()) { 201 if (value.isNaN()) {
199 buffer.add("(0/0)"); 202 buffer.add("(0/0)");
200 } else if (value == double.INFINITY) { 203 } else if (value == double.INFINITY) {
201 buffer.add("(1/0)"); 204 buffer.add("(1/0)");
202 } else if (value == -double.INFINITY) { 205 } else if (value == -double.INFINITY) {
203 buffer.add("(-1/0)"); 206 buffer.add("(-1/0)");
204 } else { 207 } else {
205 buffer.add("$value"); 208 buffer.add("$value");
(...skipping 17 matching lines...) Expand all
223 DartString toDartString() => new DartString.literal(value.toString()); 226 DartString toDartString() => new DartString.literal(value.toString());
224 } 227 }
225 228
226 class BoolConstant extends PrimitiveConstant { 229 class BoolConstant extends PrimitiveConstant {
227 factory BoolConstant(value) { 230 factory BoolConstant(value) {
228 return value ? new TrueConstant() : new FalseConstant(); 231 return value ? new TrueConstant() : new FalseConstant();
229 } 232 }
230 const BoolConstant._internal(); 233 const BoolConstant._internal();
231 bool isBool() => true; 234 bool isBool() => true;
232 235
233 BoolConstant unaryFold(String op) {
234 if (op == "!") return new BoolConstant(!value);
235 return null;
236 }
237
238 abstract BoolConstant negate(); 236 abstract BoolConstant negate();
239 } 237 }
240 238
241 class TrueConstant extends BoolConstant { 239 class TrueConstant extends BoolConstant {
242 final bool value = true; 240 final bool value = true;
243 241
244 factory TrueConstant() => const TrueConstant._internal(); 242 factory TrueConstant() => const TrueConstant._internal();
245 const TrueConstant._internal() : super._internal(); 243 const TrueConstant._internal() : super._internal();
246 bool isTrue() => true; 244 bool isTrue() => true;
247 245
(...skipping 279 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 int hashCode() => _hashCode; 525 int hashCode() => _hashCode;
528 List<Constant> getDependencies() => fields; 526 List<Constant> getDependencies() => fields;
529 } 527 }
530 528
531 /** 529 /**
532 * The [ConstantHandler] keeps track of compile-time constants, 530 * The [ConstantHandler] keeps track of compile-time constants,
533 * initializations of global and static fields, and default values of 531 * initializations of global and static fields, and default values of
534 * optional parameters. 532 * optional parameters.
535 */ 533 */
536 class ConstantHandler extends CompilerTask { 534 class ConstantHandler extends CompilerTask {
535 final ConstantSystem constantSystem;
536
537 /** 537 /**
538 * Contains the initial value of fields. Must contain all static and global 538 * Contains the initial value of fields. Must contain all static and global
539 * initializations of const fields. May contain eagerly compiled values for 539 * initializations of const fields. May contain eagerly compiled values for
540 * statics and instance fields. 540 * statics and instance fields.
541 */ 541 */
542 final Map<VariableElement, Constant> initialVariableValues; 542 final Map<VariableElement, Constant> initialVariableValues;
543 543
544 /** Map from compile-time constants to their JS name. */ 544 /** Map from compile-time constants to their JS name. */
545 final Map<Constant, String> compiledConstants; 545 final Map<Constant, String> compiledConstants;
546 546
547 /** The set of variable elements that are in the process of being computed. */ 547 /** The set of variable elements that are in the process of being computed. */
548 final Set<VariableElement> pendingVariables; 548 final Set<VariableElement> pendingVariables;
549 549
550 /** Caches the statics where the initial value cannot be eagerly compiled. */ 550 /** Caches the statics where the initial value cannot be eagerly compiled. */
551 final Set<VariableElement> lazyStatics; 551 final Set<VariableElement> lazyStatics;
552 552
553 553
554 ConstantHandler(Compiler compiler) 554 ConstantHandler(Compiler compiler, this.constantSystem)
555 : initialVariableValues = new Map<VariableElement, Dynamic>(), 555 : initialVariableValues = new Map<VariableElement, Dynamic>(),
556 compiledConstants = new Map<Constant, String>(), 556 compiledConstants = new Map<Constant, String>(),
557 pendingVariables = new Set<VariableElement>(), 557 pendingVariables = new Set<VariableElement>(),
558 lazyStatics = new Set<VariableElement>(), 558 lazyStatics = new Set<VariableElement>(),
559 super(compiler); 559 super(compiler);
560 String get name => 'ConstantHandler'; 560 String get name => 'ConstantHandler';
561 561
562 void registerCompileTimeConstant(Constant constant) { 562 void registerCompileTimeConstant(Constant constant) {
563 Function ifAbsentThunk = (() { 563 Function ifAbsentThunk = (() {
564 return constant.isFunction() 564 return constant.isFunction()
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after
663 pendingVariables.remove(element); 663 pendingVariables.remove(element);
664 return value; 664 return value;
665 }); 665 });
666 } 666 }
667 667
668 Constant compileNodeWithDefinitions(Node node, 668 Constant compileNodeWithDefinitions(Node node,
669 TreeElements definitions, 669 TreeElements definitions,
670 [bool isConst]) { 670 [bool isConst]) {
671 return measure(() { 671 return measure(() {
672 assert(node !== null); 672 assert(node !== null);
673 CompileTimeConstantEvaluator evaluator = 673 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator(
674 new CompileTimeConstantEvaluator(definitions, compiler, isConst); 674 constantSystem, definitions, compiler, isConst);
675 return evaluator.evaluate(node); 675 return evaluator.evaluate(node);
676 }); 676 });
677 } 677 }
678 678
679 /** Attempts to compile a constant expression. Returns null if not possible */ 679 /** Attempts to compile a constant expression. Returns null if not possible */
680 Constant tryCompileNodeWithDefinitions(Node node, TreeElements definitions) { 680 Constant tryCompileNodeWithDefinitions(Node node, TreeElements definitions) {
681 return measure(() { 681 return measure(() {
682 assert(node !== null); 682 assert(node !== null);
683 try { 683 try {
684 TryCompileTimeConstantEvaluator evaluator = 684 TryCompileTimeConstantEvaluator evaluator =
685 new TryCompileTimeConstantEvaluator(definitions, compiler); 685 new TryCompileTimeConstantEvaluator(constantSystem,
686 definitions,
687 compiler);
686 return evaluator.evaluate(node); 688 return evaluator.evaluate(node);
687 } on CompileTimeConstantError catch (exn) { 689 } on CompileTimeConstantError catch (exn) {
688 return null; 690 return null;
689 } 691 }
690 }); 692 });
691 } 693 }
692 694
693 /** 695 /**
694 * Returns a [List] of static non final fields that need to be initialized. 696 * Returns a [List] of static non final fields that need to be initialized.
695 * The list must be evaluated in order since the fields might depend on each 697 * The list must be evaluated in order since the fields might depend on each
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after
817 } 819 }
818 } 820 }
819 821
820 String getJsConstructor(ClassElement element) { 822 String getJsConstructor(ClassElement element) {
821 return compiler.namer.isolatePropertiesAccess(element); 823 return compiler.namer.isolatePropertiesAccess(element);
822 } 824 }
823 } 825 }
824 826
825 class CompileTimeConstantEvaluator extends AbstractVisitor { 827 class CompileTimeConstantEvaluator extends AbstractVisitor {
826 bool isEvaluatingConstant; 828 bool isEvaluatingConstant;
829 final ConstantSystem constantSystem;
827 final TreeElements elements; 830 final TreeElements elements;
828 final Compiler compiler; 831 final Compiler compiler;
829 832
830 CompileTimeConstantEvaluator(this.elements, this.compiler, [bool isConst]) 833 CompileTimeConstantEvaluator(this.constantSystem,
834 this.elements,
835 this.compiler,
836 [bool isConst])
831 : this.isEvaluatingConstant = isConst; 837 : this.isEvaluatingConstant = isConst;
832 838
833 Constant evaluate(Node node) { 839 Constant evaluate(Node node) {
834 return node.accept(this); 840 return node.accept(this);
835 } 841 }
836 842
837 Constant evaluateConstant(Node node) { 843 Constant evaluateConstant(Node node) {
838 bool oldIsEvaluatingConstant = isEvaluatingConstant; 844 bool oldIsEvaluatingConstant = isEvaluatingConstant;
839 isEvaluatingConstant = true; 845 isEvaluatingConstant = true;
840 Constant result = node.accept(this); 846 Constant result = node.accept(this);
841 isEvaluatingConstant = oldIsEvaluatingConstant; 847 isEvaluatingConstant = oldIsEvaluatingConstant;
842 assert(result != null); 848 assert(result != null);
843 return result; 849 return result;
844 } 850 }
845 851
846 Constant visitNode(Node node) { 852 Constant visitNode(Node node) {
847 return signalNotCompileTimeConstant(node); 853 return signalNotCompileTimeConstant(node);
848 } 854 }
849 855
850 Constant visitLiteralBool(LiteralBool node) { 856 Constant visitLiteralBool(LiteralBool node) {
851 return new BoolConstant(node.value); 857 return constantSystem.createBool(node.value);
852 } 858 }
853 859
854 Constant visitLiteralDouble(LiteralDouble node) { 860 Constant visitLiteralDouble(LiteralDouble node) {
855 return new DoubleConstant(node.value); 861 return constantSystem.createDouble(node.value);
856 } 862 }
857 863
858 Constant visitLiteralInt(LiteralInt node) { 864 Constant visitLiteralInt(LiteralInt node) {
859 return new IntConstant(node.value); 865 return constantSystem.createInt(node.value);
860 } 866 }
861 867
862 Constant visitLiteralList(LiteralList node) { 868 Constant visitLiteralList(LiteralList node) {
863 if (!node.isConst()) { 869 if (!node.isConst()) {
864 return signalNotCompileTimeConstant(node); 870 return signalNotCompileTimeConstant(node);
865 } 871 }
866 List<Constant> arguments = <Constant>[]; 872 List<Constant> arguments = <Constant>[];
867 for (Link<Node> link = node.elements.nodes; 873 for (Link<Node> link = node.elements.nodes;
868 !link.isEmpty(); 874 !link.isEmpty();
869 link = link.tail) { 875 link = link.tail) {
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
917 classElement.ensureResolved(compiler); 923 classElement.ensureResolved(compiler);
918 // TODO(floitsch): copy over the generic type. 924 // TODO(floitsch): copy over the generic type.
919 DartType type = new InterfaceType(classElement); 925 DartType type = new InterfaceType(classElement);
920 compiler.registerInstantiatedClass(classElement); 926 compiler.registerInstantiatedClass(classElement);
921 Constant constant = new MapConstant(type, keysList, values, protoValue); 927 Constant constant = new MapConstant(type, keysList, values, protoValue);
922 compiler.constantHandler.registerCompileTimeConstant(constant); 928 compiler.constantHandler.registerCompileTimeConstant(constant);
923 return constant; 929 return constant;
924 } 930 }
925 931
926 Constant visitLiteralNull(LiteralNull node) { 932 Constant visitLiteralNull(LiteralNull node) {
927 return new NullConstant(); 933 return constantSystem.createNull();
928 } 934 }
929 935
930 Constant visitLiteralString(LiteralString node) { 936 Constant visitLiteralString(LiteralString node) {
931 return new StringConstant(node.dartString, node); 937 return constantSystem.createString(node.dartString, node);
932 } 938 }
933 939
934 Constant visitStringJuxtaposition(StringJuxtaposition node) { 940 Constant visitStringJuxtaposition(StringJuxtaposition node) {
935 StringConstant left = evaluate(node.first); 941 StringConstant left = evaluate(node.first);
936 StringConstant right = evaluate(node.second); 942 StringConstant right = evaluate(node.second);
937 if (left == null || right == null) return null; 943 if (left == null || right == null) return null;
938 return new StringConstant(new DartString.concat(left.value, right.value), 944 return constantSystem.createString(
939 node); 945 new DartString.concat(left.value, right.value), node);
940 } 946 }
941 947
942 Constant visitStringInterpolation(StringInterpolation node) { 948 Constant visitStringInterpolation(StringInterpolation node) {
943 StringConstant initialString = evaluate(node.string); 949 StringConstant initialString = evaluate(node.string);
944 if (initialString == null) return null; 950 if (initialString == null) return null;
945 DartString accumulator = initialString.value; 951 DartString accumulator = initialString.value;
946 for (StringInterpolationPart part in node.parts) { 952 for (StringInterpolationPart part in node.parts) {
947 Constant expression = evaluate(part.expression); 953 Constant expression = evaluate(part.expression);
948 DartString expressionString; 954 DartString expressionString;
949 if (expression.isNum() || expression.isBool()) { 955 if (expression.isNum() || expression.isBool()) {
950 PrimitiveConstant primitive = expression; 956 PrimitiveConstant primitive = expression;
951 expressionString = new DartString.literal(primitive.value.toString()); 957 expressionString = new DartString.literal(primitive.value.toString());
952 } else if (expression.isString()) { 958 } else if (expression.isString()) {
953 PrimitiveConstant primitive = expression; 959 PrimitiveConstant primitive = expression;
954 expressionString = primitive.value; 960 expressionString = primitive.value;
955 } else { 961 } else {
956 return signalNotCompileTimeConstant(part.expression); 962 return signalNotCompileTimeConstant(part.expression);
957 } 963 }
958 accumulator = new DartString.concat(accumulator, expressionString); 964 accumulator = new DartString.concat(accumulator, expressionString);
959 StringConstant partString = evaluate(part.string); 965 StringConstant partString = evaluate(part.string);
960 if (partString == null) return null; 966 if (partString == null) return null;
961 accumulator = new DartString.concat(accumulator, partString.value); 967 accumulator = new DartString.concat(accumulator, partString.value);
962 }; 968 };
963 return new StringConstant(accumulator, node); 969 return constantSystem.createString(accumulator, node);
964 } 970 }
965 971
966 // TODO(floitsch): provide better error-messages. 972 // TODO(floitsch): provide better error-messages.
967 Constant visitSend(Send send) { 973 Constant visitSend(Send send) {
968 Element element = elements[send]; 974 Element element = elements[send];
969 if (Elements.isStaticOrTopLevelField(element)) { 975 if (Elements.isStaticOrTopLevelField(element)) {
970 Constant result; 976 Constant result;
971 if (element.modifiers !== null) { 977 if (element.modifiers !== null) {
972 if (element.modifiers.isConst()) { 978 if (element.modifiers.isConst()) {
973 result = compiler.compileConstant(element); 979 result = compiler.compileConstant(element);
(...skipping 12 matching lines...) Expand all
986 compiler.constantHandler.registerCompileTimeConstant(constant); 992 compiler.constantHandler.registerCompileTimeConstant(constant);
987 return constant; 993 return constant;
988 } else if (send.isPrefix) { 994 } else if (send.isPrefix) {
989 assert(send.isOperator); 995 assert(send.isOperator);
990 Constant receiverConstant = evaluate(send.receiver); 996 Constant receiverConstant = evaluate(send.receiver);
991 if (receiverConstant == null) return null; 997 if (receiverConstant == null) return null;
992 Operator op = send.selector; 998 Operator op = send.selector;
993 Constant folded; 999 Constant folded;
994 switch (op.source.stringValue) { 1000 switch (op.source.stringValue) {
995 case "!": 1001 case "!":
996 folded = const NotOperation().fold(receiverConstant); 1002 folded = constantSystem.not.fold(receiverConstant);
997 break; 1003 break;
998 case "-": 1004 case "-":
999 folded = const NegateOperation().fold(receiverConstant); 1005 folded = constantSystem.negate.fold(receiverConstant);
1000 break; 1006 break;
1001 case "~": 1007 case "~":
1002 folded = const BitNotOperation().fold(receiverConstant); 1008 folded = constantSystem.bitNot.fold(receiverConstant);
1003 break; 1009 break;
1004 default: 1010 default:
1005 compiler.internalError("Unexpected operator.", node: op); 1011 compiler.internalError("Unexpected operator.", node: op);
1006 break; 1012 break;
1007 } 1013 }
1008 if (folded === null) return signalNotCompileTimeConstant(send); 1014 if (folded === null) return signalNotCompileTimeConstant(send);
1009 return folded; 1015 return folded;
1010 } else if (send.isOperator && !send.isPostfix) { 1016 } else if (send.isOperator && !send.isPostfix) {
1011 assert(send.argumentCount() == 1); 1017 assert(send.argumentCount() == 1);
1012 Constant left = evaluate(send.receiver); 1018 Constant left = evaluate(send.receiver);
1013 Constant right = evaluate(send.argumentsNode.nodes.head); 1019 Constant right = evaluate(send.argumentsNode.nodes.head);
1014 if (left == null || right == null) return null; 1020 if (left == null || right == null) return null;
1015 Operator op = send.selector.asOperator(); 1021 Operator op = send.selector.asOperator();
1016 Constant folded = null; 1022 Constant folded = null;
1017 switch (op.source.stringValue) { 1023 switch (op.source.stringValue) {
1018 case "+": 1024 case "+":
1019 folded = const AddOperation().fold(left, right); 1025 folded = constantSystem.add.fold(left, right);
1020 break; 1026 break;
1021 case "-": 1027 case "-":
1022 folded = const SubtractOperation().fold(left, right); 1028 folded = constantSystem.subtract.fold(left, right);
1023 break; 1029 break;
1024 case "*": 1030 case "*":
1025 folded = const MultiplyOperation().fold(left, right); 1031 folded = constantSystem.multiply.fold(left, right);
1026 break; 1032 break;
1027 case "/": 1033 case "/":
1028 folded = const DivideOperation().fold(left, right); 1034 folded = constantSystem.divide.fold(left, right);
1029 break; 1035 break;
1030 case "%": 1036 case "%":
1031 folded = const ModuloOperation().fold(left, right); 1037 folded = constantSystem.modulo.fold(left, right);
1032 break; 1038 break;
1033 case "~/": 1039 case "~/":
1034 folded = const TruncatingDivideOperation().fold(left, right); 1040 folded = constantSystem.truncatingDivide.fold(left, right);
1035 break; 1041 break;
1036 case "|": 1042 case "|":
1037 folded = const BitOrOperation().fold(left, right); 1043 folded = constantSystem.bitOr.fold(left, right);
1038 break; 1044 break;
1039 case "&": 1045 case "&":
1040 folded = const BitAndOperation().fold(left, right); 1046 folded = constantSystem.bitAnd.fold(left, right);
1041 break; 1047 break;
1042 case "^": 1048 case "^":
1043 folded = const BitXorOperation().fold(left, right); 1049 folded = constantSystem.bitXor.fold(left, right);
1044 break; 1050 break;
1045 case "||": 1051 case "||":
1046 folded = const BooleanOr().fold(left, right); 1052 folded = constantSystem.booleanOr.fold(left, right);
1047 break; 1053 break;
1048 case "&&": 1054 case "&&":
1049 folded = const BooleanAnd().fold(left, right); 1055 folded = constantSystem.booleanAnd.fold(left, right);
1050 break; 1056 break;
1051 case "<<": 1057 case "<<":
1052 folded = const ShiftLeftOperation().fold(left, right); 1058 folded = constantSystem.shiftLeft.fold(left, right);
1053 break; 1059 break;
1054 case ">>": 1060 case ">>":
1055 folded = const ShiftRightOperation().fold(left, right); 1061 folded = constantSystem.shiftRight.fold(left, right);
1056 break; 1062 break;
1057 case "<": 1063 case "<":
1058 folded = const LessOperation().fold(left, right); 1064 folded = constantSystem.less.fold(left, right);
1059 break; 1065 break;
1060 case "<=": 1066 case "<=":
1061 folded = const LessEqualOperation().fold(left, right); 1067 folded = constantSystem.lessEqual.fold(left, right);
1062 break; 1068 break;
1063 case ">": 1069 case ">":
1064 folded = const GreaterOperation().fold(left, right); 1070 folded = constantSystem.greater.fold(left, right);
1065 break; 1071 break;
1066 case ">=": 1072 case ">=":
1067 folded = const GreaterEqualOperation().fold(left, right); 1073 folded = constantSystem.greaterEqual.fold(left, right);
1068 break; 1074 break;
1069 case "==": 1075 case "==":
1070 if (left.isPrimitive() && right.isPrimitive()) { 1076 if (left.isPrimitive() && right.isPrimitive()) {
1071 folded = const EqualsOperation().fold(left, right); 1077 folded = constantSystem.equal.fold(left, right);
1072 } 1078 }
1073 break; 1079 break;
1074 case "===": 1080 case "===":
1075 if (left.isPrimitive() && right.isPrimitive()) { 1081 if (left.isPrimitive() && right.isPrimitive()) {
1076 folded = const IdentityOperation().fold(left, right); 1082 folded = constantSystem.identity.fold(left, right);
1077 } 1083 }
1078 break; 1084 break;
1079 case "!=": 1085 case "!=":
1080 if (left.isPrimitive() && right.isPrimitive()) { 1086 if (left.isPrimitive() && right.isPrimitive()) {
1081 BoolConstant areEquals = const EqualsOperation().fold(left, right); 1087 BoolConstant areEquals = constantSystem.equal.fold(left, right);
1082 if (areEquals === null) { 1088 if (areEquals === null) {
1083 folded = null; 1089 folded = null;
1084 } else { 1090 } else {
1085 folded = areEquals.negate(); 1091 folded = areEquals.negate();
1086 } 1092 }
1087 } 1093 }
1088 break; 1094 break;
1089 case "!==": 1095 case "!==":
1090 if (left.isPrimitive() && right.isPrimitive()) { 1096 if (left.isPrimitive() && right.isPrimitive()) {
1091 BoolConstant areIdentical = 1097 BoolConstant areIdentical =
1092 const IdentityOperation().fold(left, right); 1098 constantSystem.identity.fold(left, right);
1093 if (areIdentical === null) { 1099 if (areIdentical === null) {
1094 folded = null; 1100 folded = null;
1095 } else { 1101 } else {
1096 folded = areIdentical.negate(); 1102 folded = areIdentical.negate();
1097 } 1103 }
1098 } 1104 }
1099 break; 1105 break;
1100 } 1106 }
1101 if (folded === null) return signalNotCompileTimeConstant(send); 1107 if (folded === null) return signalNotCompileTimeConstant(send);
1102 return folded; 1108 return folded;
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
1137 if (classElement.isInterface()) { 1143 if (classElement.isInterface()) {
1138 compiler.resolver.resolveMethodElement(constructor); 1144 compiler.resolver.resolveMethodElement(constructor);
1139 constructor = constructor.defaultImplementation; 1145 constructor = constructor.defaultImplementation;
1140 classElement = constructor.getEnclosingClass(); 1146 classElement = constructor.getEnclosingClass();
1141 } 1147 }
1142 1148
1143 Selector selector = elements.getSelector(send); 1149 Selector selector = elements.getSelector(send);
1144 List<Constant> arguments = 1150 List<Constant> arguments =
1145 evaluateArgumentsToConstructor(selector, send.arguments, constructor); 1151 evaluateArgumentsToConstructor(selector, send.arguments, constructor);
1146 ConstructorEvaluator evaluator = 1152 ConstructorEvaluator evaluator =
1147 new ConstructorEvaluator(constructor, compiler); 1153 new ConstructorEvaluator(constructor, constantSystem, compiler);
1148 evaluator.evaluateConstructorFieldValues(arguments); 1154 evaluator.evaluateConstructorFieldValues(arguments);
1149 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement); 1155 List<Constant> jsNewArguments = evaluator.buildJsNewArguments(classElement);
1150 1156
1151 compiler.registerInstantiatedClass(classElement); 1157 compiler.registerInstantiatedClass(classElement);
1152 // TODO(floitsch): take generic types into account. 1158 // TODO(floitsch): take generic types into account.
1153 DartType type = classElement.computeType(compiler); 1159 DartType type = classElement.computeType(compiler);
1154 Constant constant = new ConstructedConstant(type, jsNewArguments); 1160 Constant constant = new ConstructedConstant(type, jsNewArguments);
1155 compiler.constantHandler.registerCompileTimeConstant(constant); 1161 compiler.constantHandler.registerCompileTimeConstant(constant);
1156 return constant; 1162 return constant;
1157 } 1163 }
(...skipping 16 matching lines...) Expand all
1174 // Else we don't need to do anything. The final handler is only 1180 // Else we don't need to do anything. The final handler is only
1175 // optimistically trying to compile constants. So it is normal that we 1181 // optimistically trying to compile constants. So it is normal that we
1176 // sometimes see non-compile time constants. 1182 // sometimes see non-compile time constants.
1177 // Simply return [:null:] which is used to propagate a failing 1183 // Simply return [:null:] which is used to propagate a failing
1178 // compile-time compilation. 1184 // compile-time compilation.
1179 return null; 1185 return null;
1180 } 1186 }
1181 } 1187 }
1182 1188
1183 class TryCompileTimeConstantEvaluator extends CompileTimeConstantEvaluator { 1189 class TryCompileTimeConstantEvaluator extends CompileTimeConstantEvaluator {
1184 TryCompileTimeConstantEvaluator(TreeElements elements, Compiler compiler): 1190 TryCompileTimeConstantEvaluator(ConstantSystem constantSystem,
1185 super(elements, compiler, isConst: true); 1191 TreeElements elements,
1192 Compiler compiler)
1193 : super(constantSystem, elements, compiler, isConst: true);
1186 1194
1187 error(Node node) { 1195 error(Node node) {
1188 // Just fail without reporting it anywhere. 1196 // Just fail without reporting it anywhere.
1189 throw new CompileTimeConstantError( 1197 throw new CompileTimeConstantError(
1190 MessageKind.NOT_A_COMPILE_TIME_CONSTANT, const []); 1198 MessageKind.NOT_A_COMPILE_TIME_CONSTANT, const []);
1191 } 1199 }
1192 } 1200 }
1193 1201
1194 class ConstructorEvaluator extends CompileTimeConstantEvaluator { 1202 class ConstructorEvaluator extends CompileTimeConstantEvaluator {
1195 FunctionElement constructor; 1203 FunctionElement constructor;
1196 final Map<Element, Constant> definitions; 1204 final Map<Element, Constant> definitions;
1197 final Map<Element, Constant> fieldValues; 1205 final Map<Element, Constant> fieldValues;
1198 1206
1199 ConstructorEvaluator(FunctionElement constructor, Compiler compiler) 1207 ConstructorEvaluator(FunctionElement constructor,
1208 ConstantSystem constantSystem,
1209 Compiler compiler)
1200 : this.constructor = constructor, 1210 : this.constructor = constructor,
1201 this.definitions = new Map<Element, Constant>(), 1211 this.definitions = new Map<Element, Constant>(),
1202 this.fieldValues = new Map<Element, Constant>(), 1212 this.fieldValues = new Map<Element, Constant>(),
1203 super(compiler.resolver.resolveMethodElement(constructor), 1213 super(constantSystem,
1214 compiler.resolver.resolveMethodElement(constructor),
1204 compiler, 1215 compiler,
1205 isConst: true); 1216 isConst: true);
1206 1217
1207 Constant visitSend(Send send) { 1218 Constant visitSend(Send send) {
1208 Element element = elements[send]; 1219 Element element = elements[send];
1209 if (Elements.isLocal(element)) { 1220 if (Elements.isLocal(element)) {
1210 Constant constant = definitions[element]; 1221 Constant constant = definitions[element];
1211 if (constant === null) { 1222 if (constant === null) {
1212 compiler.internalError("Local variable without value", node: send); 1223 compiler.internalError("Local variable without value", node: send);
1213 } 1224 }
(...skipping 20 matching lines...) Expand all
1234 } 1245 }
1235 }); 1246 });
1236 } 1247 }
1237 1248
1238 void evaluateSuperOrRedirectSend(Selector selector, 1249 void evaluateSuperOrRedirectSend(Selector selector,
1239 Link<Node> arguments, 1250 Link<Node> arguments,
1240 FunctionElement targetConstructor) { 1251 FunctionElement targetConstructor) {
1241 List<Constant> compiledArguments = 1252 List<Constant> compiledArguments =
1242 evaluateArgumentsToConstructor(selector, arguments, targetConstructor); 1253 evaluateArgumentsToConstructor(selector, arguments, targetConstructor);
1243 1254
1244 ConstructorEvaluator evaluator = 1255 ConstructorEvaluator evaluator = new ConstructorEvaluator(
1245 new ConstructorEvaluator(targetConstructor, compiler); 1256 targetConstructor, constantSystem, compiler);
1246 evaluator.evaluateConstructorFieldValues(compiledArguments); 1257 evaluator.evaluateConstructorFieldValues(compiledArguments);
1247 // Copy over the fieldValues from the super/redirect-constructor. 1258 // Copy over the fieldValues from the super/redirect-constructor.
1248 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value); 1259 evaluator.fieldValues.forEach((key, value) => fieldValues[key] = value);
1249 } 1260 }
1250 1261
1251 /** 1262 /**
1252 * Runs through the initializers of the given [constructor] and updates 1263 * Runs through the initializers of the given [constructor] and updates
1253 * the [fieldValues] map. 1264 * the [fieldValues] map.
1254 */ 1265 */
1255 void evaluateConstructorInitializers() { 1266 void evaluateConstructorInitializers() {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1328 Constant fieldValue = fieldValues[field]; 1339 Constant fieldValue = fieldValues[field];
1329 if (fieldValue === null) { 1340 if (fieldValue === null) {
1330 // Use the default value. 1341 // Use the default value.
1331 fieldValue = compiler.compileConstant(field); 1342 fieldValue = compiler.compileConstant(field);
1332 } 1343 }
1333 jsNewArguments.add(fieldValue); 1344 jsNewArguments.add(fieldValue);
1334 }); 1345 });
1335 return jsNewArguments; 1346 return jsNewArguments;
1336 } 1347 }
1337 } 1348 }
OLDNEW
« no previous file with comments | « lib/compiler/implementation/apiimpl.dart ('k') | lib/compiler/implementation/compiler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698