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

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

Issue 226953003: Revert "Compute frontend/backend specific constants." (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 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 part of dart2js; 5 part of dart2js;
6 6
7 /// A [ConstantEnvironment] provides access for constants compiled for variable
8 /// initializers.
9 abstract class ConstantEnvironment {
10 /// Returns the constant for the initializer of [element].
11 Constant getConstantForVariable(VariableElement element);
12 }
13
14 /// A class that can compile and provide constants for variables, nodes and
15 /// metadata.
16 abstract class ConstantCompiler extends ConstantEnvironment {
17 /// Compiles the compile-time constant for the initializer of [element], or
18 /// reports an error if the initializer is not a compile-time constant.
19 ///
20 /// Depending on implementation, the constant compiler might also compute
21 /// the compile-time constant for the backend interpretation of constants.
22 ///
23 /// The returned constant is always of the frontend interpretation.
24 Constant compileConstant(VariableElement element);
25
26 /// Computes the compile-time constant for the variable initializer,
27 /// if possible.
28 void compileVariable(VariableElement element);
29
30 /// Compiles the compile-time constant for [node], or reports an error if
31 /// [node] is not a compile-time constant.
32 ///
33 /// Depending on implementation, the constant compiler might also compute
34 /// the compile-time constant for the backend interpretation of constants.
35 ///
36 /// The returned constant is always of the frontend interpretation.
37 Constant compileNode(Node node, TreeElements elements);
38
39 /// Compiles the compile-time constant for the value [metadata], or reports an
40 /// error if the value is not a compile-time constant.
41 ///
42 /// Depending on implementation, the constant compiler might also compute
43 /// the compile-time constant for the backend interpretation of constants.
44 ///
45 /// The returned constant is always of the frontend interpretation.
46 Constant compileMetadata(MetadataAnnotation metadata,
47 Node node, TreeElements elements);
48 }
49
50 /// A [BackendConstantEnvironment] provides access to constants needed for
51 /// backend implementation.
52 abstract class BackendConstantEnvironment extends ConstantEnvironment {
53 /// Returns the compile-time constant associated with [node].
54 ///
55 /// Depending on implementation, the constant might be stored in [elements].
56 Constant getConstantForNode(Node node, TreeElements elements);
57
58 /// Returns the compile-time constant value of [metadata].
59 Constant getConstantForMetadata(MetadataAnnotation metadata);
60 }
61
62 /// Interface for the task that compiles the constant environments for the
63 /// frontend and backend interpretation of compile-time constants.
64 abstract class ConstantCompilerTask extends CompilerTask
65 implements ConstantCompiler {
66 ConstantCompilerTask(Compiler compiler) : super(compiler);
67 }
68
69 /** 7 /**
70 * The [ConstantCompilerBase] is provides base implementation for compilation of 8 * The [ConstantHandler] keeps track of compile-time constants,
71 * compile-time constants for both the Dart and JavaScript interpretation of 9 * initializations of global and static fields, and default values of
72 * constants. It keeps track of compile-time constants for initializations of 10 * optional parameters.
73 * global and static fields, and default values of optional parameters.
74 */ 11 */
75 abstract class ConstantCompilerBase implements ConstantCompiler { 12 class ConstantHandler extends CompilerTask {
76 final Compiler compiler;
77 final ConstantSystem constantSystem; 13 final ConstantSystem constantSystem;
14 final bool isMetadata;
78 15
79 /** 16 /**
80 * Contains the initial value of fields. Must contain all static and global 17 * Contains the initial value of fields. Must contain all static and global
81 * initializations of const fields. May contain eagerly compiled values for 18 * initializations of const fields. May contain eagerly compiled values for
82 * statics and instance fields. 19 * statics and instance fields.
83 * 20 *
84 * Invariant: The keys in this map are declarations. 21 * Invariant: The keys in this map are declarations.
85 */ 22 */
86 final Map<VariableElement, Constant> initialVariableValues = 23 final Map<VariableElement, Constant> initialVariableValues;
87 new Map<VariableElement, Constant>(); 24
25 /** Set of all registered compiled constants. */
26 final Set<Constant> compiledConstants;
88 27
89 /** The set of variable elements that are in the process of being computed. */ 28 /** The set of variable elements that are in the process of being computed. */
90 final Set<VariableElement> pendingVariables = new Set<VariableElement>(); 29 final Set<VariableElement> pendingVariables;
91 30
92 ConstantCompilerBase(this.compiler, this.constantSystem); 31 /** Caches the statics where the initial value cannot be eagerly compiled. */
32 final Set<VariableElement> lazyStatics;
33
34 ConstantHandler(Compiler compiler, this.constantSystem,
35 { bool this.isMetadata: false })
36 : initialVariableValues = new Map<VariableElement, dynamic>(),
37 compiledConstants = new Set<Constant>(),
38 pendingVariables = new Set<VariableElement>(),
39 lazyStatics = new Set<VariableElement>(),
40 super(compiler);
41
42 String get name => 'ConstantHandler';
43
44 void addCompileTimeConstantForEmission(Constant constant) {
45 compiledConstants.add(constant);
46 }
93 47
94 Constant getConstantForVariable(VariableElement element) { 48 Constant getConstantForVariable(VariableElement element) {
95 return initialVariableValues[element.declaration]; 49 return initialVariableValues[element.declaration];
96 } 50 }
97 51
52 /**
53 * Returns a compile-time constant, or reports an error if the element is not
54 * a compile-time constant.
55 */
98 Constant compileConstant(VariableElement element) { 56 Constant compileConstant(VariableElement element) {
99 return compileVariable(element, isConst: true); 57 return compileVariable(element, isConst: true);
100 } 58 }
101 59
60 /**
61 * Returns the a compile-time constant if the variable could be compiled
62 * eagerly. Otherwise returns `null`.
63 */
102 Constant compileVariable(VariableElement element, {bool isConst: false}) { 64 Constant compileVariable(VariableElement element, {bool isConst: false}) {
103 65 return measure(() {
104 if (initialVariableValues.containsKey(element.declaration)) { 66 if (initialVariableValues.containsKey(element.declaration)) {
105 Constant result = initialVariableValues[element.declaration]; 67 Constant result = initialVariableValues[element.declaration];
106 return result; 68 return result;
107 } 69 }
108 Element currentElement = element; 70 Element currentElement = element;
109 if (element.isParameter() || 71 if (element.isParameter()
110 element.isFieldParameter() || 72 || element.isFieldParameter()
111 element.isVariable()) { 73 || element.isVariable()) {
112 currentElement = element.enclosingElement; 74 currentElement = element.enclosingElement;
113 } 75 }
114 return compiler.withCurrentElement(currentElement, () { 76 return compiler.withCurrentElement(currentElement, () {
115 TreeElements definitions = 77 TreeElements definitions =
116 compiler.analyzeElement(currentElement.declaration); 78 compiler.analyzeElement(currentElement.declaration);
117 Constant constant = compileVariableWithDefinitions( 79 Constant constant = compileVariableWithDefinitions(
118 element, definitions, isConst: isConst); 80 element, definitions, isConst: isConst);
119 return constant; 81 return constant;
82 });
120 }); 83 });
121 } 84 }
122 85
123 /** 86 /**
124 * Returns the a compile-time constant if the variable could be compiled 87 * Returns the a compile-time constant if the variable could be compiled
125 * eagerly. If the variable needs to be initialized lazily returns `null`. 88 * eagerly. If the variable needs to be initialized lazily returns `null`.
126 * If the variable is `const` but cannot be compiled eagerly reports an 89 * If the variable is `const` but cannot be compiled eagerly reports an
127 * error. 90 * error.
128 */ 91 */
129 Constant compileVariableWithDefinitions(VariableElement element, 92 Constant compileVariableWithDefinitions(VariableElement element,
130 TreeElements definitions, 93 TreeElements definitions,
131 {bool isConst: false}) { 94 {bool isConst: false}) {
132 Node node = element.parseNode(compiler); 95 return measure(() {
133 if (pendingVariables.contains(element)) { 96 if (!isConst && lazyStatics.contains(element)) return null;
134 if (isConst) { 97
135 compiler.reportFatalError( 98 Node node = element.parseNode(compiler);
136 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS); 99 if (pendingVariables.contains(element)) {
100 if (isConst) {
101 compiler.reportFatalError(
102 node, MessageKind.CYCLIC_COMPILE_TIME_CONSTANTS);
103 } else {
104 lazyStatics.add(element);
105 return null;
106 }
137 } 107 }
138 return null; 108 pendingVariables.add(element);
139 }
140 pendingVariables.add(element);
141 109
142 Expression initializer = element.initializer; 110 Expression initializer = element.initializer;
143 Constant value; 111 Constant value;
144 if (initializer == null) { 112 if (initializer == null) {
145 // No initial value. 113 // No initial value.
146 value = new NullConstant(); 114 value = new NullConstant();
147 } else { 115 } else {
148 value = compileNodeWithDefinitions( 116 value = compileNodeWithDefinitions(
149 initializer, definitions, isConst: isConst); 117 initializer, definitions, isConst: isConst);
150 if (compiler.enableTypeAssertions && 118 if (compiler.enableTypeAssertions &&
151 value != null && 119 value != null &&
152 element.isField()) { 120 element.isField()) {
153 DartType elementType = element.type; 121 DartType elementType = element.type;
154 if (elementType.kind == TypeKind.MALFORMED_TYPE && !value.isNull) { 122 if (elementType.kind == TypeKind.MALFORMED_TYPE && !value.isNull) {
155 if (isConst) { 123 if (isConst) {
156 ErroneousElement element = elementType.element; 124 ErroneousElement element = elementType.element;
157 compiler.reportFatalError( 125 compiler.reportFatalError(
158 node, element.messageKind, element.messageArguments); 126 node, element.messageKind, element.messageArguments);
127 } else {
128 // We need to throw an exception at runtime.
129 value = null;
130 }
159 } else { 131 } else {
160 // We need to throw an exception at runtime. 132 DartType constantType = value.computeType(compiler);
161 value = null; 133 if (!constantSystem.isSubtype(compiler,
162 } 134 constantType, elementType)) {
163 } else { 135 if (isConst) {
164 DartType constantType = value.computeType(compiler); 136 compiler.reportFatalError(
165 if (!constantSystem.isSubtype(compiler, 137 node, MessageKind.NOT_ASSIGNABLE,
166 constantType, elementType)) { 138 {'fromType': constantType, 'toType': elementType});
167 if (isConst) { 139 } else {
168 compiler.reportFatalError( 140 // If the field cannot be lazily initialized, we will throw
169 node, MessageKind.NOT_ASSIGNABLE, 141 // the exception at runtime.
170 {'fromType': constantType, 'toType': elementType}); 142 value = null;
171 } else { 143 }
172 // If the field cannot be lazily initialized, we will throw
173 // the exception at runtime.
174 value = null;
175 } 144 }
176 } 145 }
177 } 146 }
178 } 147 }
179 } 148 if (value != null) {
180 if (value != null) { 149 initialVariableValues[element.declaration] = value;
181 initialVariableValues[element.declaration] = value; 150 } else {
182 } else { 151 assert(!isConst);
183 assert(!isConst); 152 lazyStatics.add(element);
184 } 153 }
185 pendingVariables.remove(element); 154 pendingVariables.remove(element);
186 return value; 155 return value;
156 });
187 } 157 }
188 158
189 Constant compileNodeWithDefinitions(Node node, 159 Constant compileNodeWithDefinitions(Node node,
190 TreeElements definitions, 160 TreeElements definitions,
191 {bool isConst: true}) { 161 {bool isConst: false}) {
192 assert(node != null); 162 return measure(() {
193 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator( 163 assert(node != null);
194 this, definitions, compiler, isConst: isConst); 164 Constant constant = definitions.getConstant(node);
195 return evaluator.evaluate(node); 165 if (constant != null) {
166 return constant;
167 }
168 CompileTimeConstantEvaluator evaluator = new CompileTimeConstantEvaluator(
169 this, definitions, compiler, isConst: isConst);
170 constant = evaluator.evaluate(node);
171 if (constant != null) {
172 definitions.setConstant(node, constant);
173 }
174 return constant;
175 });
196 } 176 }
197 177
198 Constant compileNode(Node node, TreeElements elements) { 178 /**
199 return compileNodeWithDefinitions(node, elements); 179 * Returns an [Iterable] of static non final fields that need to be
180 * initialized. The fields list must be evaluated in order since they might
181 * depend on each other.
182 */
183 Iterable<VariableElement> getStaticNonFinalFieldsForEmission() {
184 return initialVariableValues.keys.where((element) {
185 return element.kind == ElementKind.FIELD
186 && !element.isInstanceMember()
187 && !element.modifiers.isFinal()
188 // The const fields are all either emitted elsewhere or inlined.
189 && !element.modifiers.isConst();
190 });
200 } 191 }
201 192
202 Constant compileMetadata(MetadataAnnotation metadata, 193 List<VariableElement> getLazilyInitializedFieldsForEmission() {
203 Node node, 194 return new List<VariableElement>.from(lazyStatics);
204 TreeElements elements) {
205 return compileNodeWithDefinitions(node, elements);
206 }
207 }
208
209 /// [ConstantCompiler] that uses the Dart semantics for the compile-time
210 /// constant evaluation.
211 class DartConstantCompiler extends ConstantCompilerBase {
212 DartConstantCompiler(Compiler compiler)
213 : super(compiler, const DartConstantSystem());
214
215 Constant getConstantForNode(Node node, TreeElements definitions) {
216 return definitions.getConstant(node);
217 } 195 }
218 196
219 Constant getConstantForMetadata(MetadataAnnotation metadata) { 197 /**
220 return metadata.value; 198 * Returns a list of constants topologically sorted so that dependencies
199 * appear before the dependent constant. [preSortCompare] is a comparator
200 * function that gives the constants a consistent order prior to the
201 * topological sort which gives the constants an ordering that is less
202 * sensitive to perturbations in the source code.
203 */
204 List<Constant> getConstantsForEmission([preSortCompare]) {
205 // We must emit dependencies before their uses.
206 Set<Constant> seenConstants = new Set<Constant>();
207 List<Constant> result = new List<Constant>();
208
209 void addConstant(Constant constant) {
210 if (!seenConstants.contains(constant)) {
211 constant.getDependencies().forEach(addConstant);
212 assert(!seenConstants.contains(constant));
213 result.add(constant);
214 seenConstants.add(constant);
215 }
216 }
217
218 List<Constant> sorted = compiledConstants.toList();
219 if (preSortCompare != null) {
220 sorted.sort(preSortCompare);
221 }
222 sorted.forEach(addConstant);
223 return result;
221 } 224 }
222 225
223 Constant compileNodeWithDefinitions(Node node, 226 Constant getInitialValueFor(VariableElement element) {
224 TreeElements definitions, 227 Constant initialValue = initialVariableValues[element.declaration];
225 {bool isConst: true}) { 228 if (initialValue == null) {
226 Constant constant = definitions.getConstant(node); 229 compiler.internalError(element, "No initial value for given element.");
227 if (constant != null) {
228 return constant;
229 } 230 }
230 constant = 231 return initialValue;
231 super.compileNodeWithDefinitions(node, definitions, isConst: isConst);
232 if (constant != null) {
233 definitions.setConstant(node, constant);
234 }
235 return constant;
236 } 232 }
237 } 233 }
238 234
239 class CompileTimeConstantEvaluator extends Visitor { 235 class CompileTimeConstantEvaluator extends Visitor {
240 bool isEvaluatingConstant; 236 bool isEvaluatingConstant;
241 final ConstantCompilerBase handler; 237 final ConstantHandler handler;
242 final TreeElements elements; 238 final TreeElements elements;
243 final Compiler compiler; 239 final Compiler compiler;
244 240
245 CompileTimeConstantEvaluator(this.handler, 241 CompileTimeConstantEvaluator(this.handler,
246 this.elements, 242 this.elements,
247 this.compiler, 243 this.compiler,
248 {bool isConst: false}) 244 {bool isConst: false})
249 : this.isEvaluatingConstant = isConst; 245 : this.isEvaluatingConstant = isConst;
250 246
251 ConstantSystem get constantSystem => handler.constantSystem; 247 ConstantSystem get constantSystem => handler.constantSystem;
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
437 if (prefixNode != null) { 433 if (prefixNode != null) {
438 Element maybePrefix = elements[prefixNode.asIdentifier()]; 434 Element maybePrefix = elements[prefixNode.asIdentifier()];
439 if (maybePrefix != null && maybePrefix.isPrefix() && 435 if (maybePrefix != null && maybePrefix.isPrefix() &&
440 (maybePrefix as PrefixElement).isDeferred) { 436 (maybePrefix as PrefixElement).isDeferred) {
441 return true; 437 return true;
442 } 438 }
443 } 439 }
444 return false; 440 return false;
445 } 441 }
446 442
447 Constant visitIdentifier(Identifier node) {
448 Element element = elements[node];
449 if (Elements.isClass(element) || Elements.isTypedef(element)) {
450 return makeTypeConstant(element);
451 }
452 return signalNotCompileTimeConstant(node);
453 }
454
455 // TODO(floitsch): provide better error-messages. 443 // TODO(floitsch): provide better error-messages.
456 Constant visitSend(Send send) { 444 Constant visitSend(Send send) {
457 Element element = elements[send]; 445 Element element = elements[send];
458 if (send.isPropertyAccess) { 446 if (send.isPropertyAccess) {
459 if (isDeferredUse(send)) { 447 if (isDeferredUse(send)) {
460 return signalNotCompileTimeConstant(send, 448 return signalNotCompileTimeConstant(send,
461 message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT); 449 message: MessageKind.DEFERRED_COMPILE_TIME_CONSTANT);
462 } 450 }
463 if (Elements.isStaticOrTopLevelFunction(element)) { 451 if (Elements.isStaticOrTopLevelFunction(element)) {
464 return new FunctionConstant(element); 452 return new FunctionConstant(element);
(...skipping 17 matching lines...) Expand all
482 if (result != null) return result; 470 if (result != null) return result;
483 } 471 }
484 return signalNotCompileTimeConstant(send); 472 return signalNotCompileTimeConstant(send);
485 } else if (send.isCall) { 473 } else if (send.isCall) {
486 if (identical(element, compiler.identicalFunction) 474 if (identical(element, compiler.identicalFunction)
487 && send.argumentCount() == 2) { 475 && send.argumentCount() == 2) {
488 Constant left = evaluate(send.argumentsNode.nodes.head); 476 Constant left = evaluate(send.argumentsNode.nodes.head);
489 Constant right = evaluate(send.argumentsNode.nodes.tail.head); 477 Constant right = evaluate(send.argumentsNode.nodes.tail.head);
490 Constant result = constantSystem.identity.fold(left, right); 478 Constant result = constantSystem.identity.fold(left, right);
491 if (result != null) return result; 479 if (result != null) return result;
480 } else if (Elements.isClass(element) || Elements.isTypedef(element)) {
481 // The node itself is not a constant but we register the selector (the
482 // identifier that refers to the class/typedef) as a constant.
483 Constant typeConstant = makeTypeConstant(element);
484 elements.setConstant(send.selector, typeConstant);
492 } 485 }
493 return signalNotCompileTimeConstant(send); 486 return signalNotCompileTimeConstant(send);
494 } else if (send.isPrefix) { 487 } else if (send.isPrefix) {
495 assert(send.isOperator); 488 assert(send.isOperator);
496 Constant receiverConstant = evaluate(send.receiver); 489 Constant receiverConstant = evaluate(send.receiver);
497 if (receiverConstant == null) return null; 490 if (receiverConstant == null) return null;
498 Operator op = send.selector; 491 Operator op = send.selector;
499 Constant folded; 492 Constant folded;
500 switch (op.source) { 493 switch (op.source) {
501 case "!": 494 case "!":
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
810 final FunctionElement constructor; 803 final FunctionElement constructor;
811 final Map<Element, Constant> definitions; 804 final Map<Element, Constant> definitions;
812 final Map<Element, Constant> fieldValues; 805 final Map<Element, Constant> fieldValues;
813 806
814 /** 807 /**
815 * Documentation wanted -- johnniwinther 808 * Documentation wanted -- johnniwinther
816 * 809 *
817 * Invariant: [constructor] must be an implementation element. 810 * Invariant: [constructor] must be an implementation element.
818 */ 811 */
819 ConstructorEvaluator(FunctionElement constructor, 812 ConstructorEvaluator(FunctionElement constructor,
820 ConstantCompiler handler, 813 ConstantHandler handler,
821 Compiler compiler) 814 Compiler compiler)
822 : this.constructor = constructor, 815 : this.constructor = constructor,
823 this.definitions = new Map<Element, Constant>(), 816 this.definitions = new Map<Element, Constant>(),
824 this.fieldValues = new Map<Element, Constant>(), 817 this.fieldValues = new Map<Element, Constant>(),
825 super(handler, 818 super(handler,
826 compiler.resolver.resolveMethodElement(constructor.declaration), 819 compiler.resolver.resolveMethodElement(constructor.declaration),
827 compiler, 820 compiler,
828 isConst: true) { 821 isConst: true) {
829 assert(invariant(constructor, constructor.isImplementation)); 822 assert(invariant(constructor, constructor.isImplementation));
830 } 823 }
(...skipping 12 matching lines...) Expand all
843 836
844 void potentiallyCheckType(Node node, 837 void potentiallyCheckType(Node node,
845 TypedElement element, 838 TypedElement element,
846 Constant constant) { 839 Constant constant) {
847 if (compiler.enableTypeAssertions) { 840 if (compiler.enableTypeAssertions) {
848 DartType elementType = element.type; 841 DartType elementType = element.type;
849 DartType constantType = constant.computeType(compiler); 842 DartType constantType = constant.computeType(compiler);
850 // TODO(ngeoffray): Handle type parameters. 843 // TODO(ngeoffray): Handle type parameters.
851 if (elementType.element.isTypeVariable()) return; 844 if (elementType.element.isTypeVariable()) return;
852 if (!constantSystem.isSubtype(compiler, constantType, elementType)) { 845 if (!constantSystem.isSubtype(compiler, constantType, elementType)) {
853 // TODO(johnniwinther): Provide better [node] values that point to the
854 // origin of the constant and not (just) the assignment.
855 compiler.reportFatalError( 846 compiler.reportFatalError(
856 node, MessageKind.NOT_ASSIGNABLE, 847 node, MessageKind.NOT_ASSIGNABLE,
857 {'fromType': elementType, 'toType': constantType}); 848 {'fromType': elementType, 'toType': constantType});
858 } 849 }
859 } 850 }
860 } 851 }
861 852
862 void updateFieldValue(Node node, TypedElement element, Constant constant) { 853 void updateFieldValue(Node node, TypedElement element, Constant constant) {
863 potentiallyCheckType(node, element, constant); 854 potentiallyCheckType(node, element, constant);
864 fieldValues[element] = constant; 855 fieldValues[element] = constant;
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
990 if (fieldValue == null) { 981 if (fieldValue == null) {
991 // Use the default value. 982 // Use the default value.
992 fieldValue = handler.compileConstant(field); 983 fieldValue = handler.compileConstant(field);
993 } 984 }
994 jsNewArguments.add(fieldValue); 985 jsNewArguments.add(fieldValue);
995 }, 986 },
996 includeSuperAndInjectedMembers: true); 987 includeSuperAndInjectedMembers: true);
997 return jsNewArguments; 988 return jsNewArguments;
998 } 989 }
999 } 990 }
OLDNEW
« no previous file with comments | « sdk/lib/_internal/compiler/implementation/common.dart ('k') | sdk/lib/_internal/compiler/implementation/compiler.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698