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

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

Issue 221873002: Compute frontend/backend specific constants. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fixes 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 resolution; 5 part of resolution;
6 6
7 abstract class TreeElements { 7 abstract class TreeElements {
8 Element get currentElement; 8 Element get currentElement;
9 Setlet<Node> get superUses; 9 Setlet<Node> get superUses;
10 10
11 /// Iterables of the dependencies that this [TreeElement] records of 11 /// Iterables of the dependencies that this [TreeElement] records of
12 /// [currentElement]. 12 /// [currentElement].
13 Iterable<Element> get allElements; 13 Iterable<Element> get allElements;
14 Iterable<Constant> get allConstants; 14 void forEachConstantNode(f(Node n, Constant c));
15 15
16 /// A set of additional dependencies. See [registerDependency] below. 16 /// A set of additional dependencies. See [registerDependency] below.
17 Setlet<Element> get otherDependencies; 17 Setlet<Element> get otherDependencies;
18 18
19 Element operator[](Node node); 19 Element operator[](Node node);
20 Selector getSelector(Send send); 20 Selector getSelector(Send send);
21 Selector getGetterSelectorInComplexSendSet(SendSet node); 21 Selector getGetterSelectorInComplexSendSet(SendSet node);
22 Selector getOperatorSelectorInComplexSendSet(SendSet node); 22 Selector getOperatorSelectorInComplexSendSet(SendSet node);
23 DartType getType(Node node); 23 DartType getType(Node node);
24 void setSelector(Node node, Selector selector); 24 void setSelector(Node node, Selector selector);
(...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after
238 Map<VariableElement, List<Node>> accessMap = 238 Map<VariableElement, List<Node>> accessMap =
239 accessedByClosureIn.putIfAbsent(contextNode, 239 accessedByClosureIn.putIfAbsent(contextNode,
240 () => new Map<VariableElement, List<Node>>()); 240 () => new Map<VariableElement, List<Node>>());
241 accessMap.putIfAbsent(element, () => <Node>[]).add(accessNode); 241 accessMap.putIfAbsent(element, () => <Node>[]).add(accessNode);
242 } 242 }
243 243
244 String toString() => 'TreeElementMapping($currentElement)'; 244 String toString() => 'TreeElementMapping($currentElement)';
245 245
246 Iterable<Element> get allElements => elements; 246 Iterable<Element> get allElements => elements;
247 247
248 Iterable<Constant> get allConstants => constants.values; 248 void forEachConstantNode(f(Node n, Constant c)) => constants.forEach(f);
249 } 249 }
250 250
251 class ResolverTask extends CompilerTask { 251 class ResolverTask extends CompilerTask {
252 ResolverTask(Compiler compiler) : super(compiler); 252 final ConstantCompiler constantCompiler;
253
254 ResolverTask(Compiler compiler, this.constantCompiler) : super(compiler);
253 255
254 String get name => 'Resolver'; 256 String get name => 'Resolver';
255 257
256 TreeElements resolve(Element element) { 258 TreeElements resolve(Element element) {
257 return measure(() { 259 return measure(() {
258 if (Elements.isErroneousElement(element)) return null; 260 if (Elements.isErroneousElement(element)) return null;
259 261
260 for (MetadataAnnotation metadata in element.metadata) { 262 for (MetadataAnnotation metadata in element.metadata) {
261 metadata.ensureResolved(compiler); 263 metadata.ensureResolved(compiler);
262 } 264 }
(...skipping 313 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 compiler.reportError(element, MessageKind.CONST_WITHOUT_INITIALIZER); 578 compiler.reportError(element, MessageKind.CONST_WITHOUT_INITIALIZER);
577 } else if (modifiers.isFinal() && !element.isInstanceMember()) { 579 } else if (modifiers.isFinal() && !element.isInstanceMember()) {
578 compiler.reportError(element, MessageKind.FINAL_WITHOUT_INITIALIZER); 580 compiler.reportError(element, MessageKind.FINAL_WITHOUT_INITIALIZER);
579 } else { 581 } else {
580 compiler.enqueuer.resolution.registerInstantiatedClass( 582 compiler.enqueuer.resolution.registerInstantiatedClass(
581 compiler.nullClass, visitor.mapping); 583 compiler.nullClass, visitor.mapping);
582 } 584 }
583 585
584 if (Elements.isStaticOrTopLevelField(element)) { 586 if (Elements.isStaticOrTopLevelField(element)) {
585 visitor.addDeferredAction(element, () { 587 visitor.addDeferredAction(element, () {
586 compiler.constantHandler.compileVariable( 588 if (element.modifiers.isConst()) {
587 element, isConst: element.modifiers.isConst()); 589 constantCompiler.compileConstant(element);
590 } else {
591 constantCompiler.compileVariable(element);
592 }
588 }); 593 });
589 if (initializer != null) { 594 if (initializer != null) {
590 if (!element.modifiers.isConst()) { 595 if (!element.modifiers.isConst()) {
591 // TODO(johnniwinther): Determine the const-ness eagerly to avoid 596 // TODO(johnniwinther): Determine the const-ness eagerly to avoid
592 // unnecessary registrations. 597 // unnecessary registrations.
593 compiler.backend.registerLazyField(visitor.mapping); 598 compiler.backend.registerLazyField(visitor.mapping);
594 } 599 }
595 } 600 }
596 } 601 }
597 602
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 } 655 }
651 656
652 // [target] is now the actual target of the redirections. Run through 657 // [target] is now the actual target of the redirections. Run through
653 // the constructors again and set their [redirectionTarget], so that we 658 // the constructors again and set their [redirectionTarget], so that we
654 // do not have to run the loop for these constructors again. Furthermore, 659 // do not have to run the loop for these constructors again. Furthermore,
655 // compute [redirectionTargetType] for each factory by computing the 660 // compute [redirectionTargetType] for each factory by computing the
656 // substitution of the target type with respect to the factory type. 661 // substitution of the target type with respect to the factory type.
657 while (!seen.isEmpty) { 662 while (!seen.isEmpty) {
658 FunctionElementX factory = seen.removeLast(); 663 FunctionElementX factory = seen.removeLast();
659 664
660 TreeElements treeElements = 665 // [factory] must already be analyzed but the [TreeElements] might not
661 compiler.enqueuer.resolution.getCachedElements(factory); 666 // have been stored in the enqueuer cache yet.
667 // TODO(johnniwinther): Store [TreeElements] in the cache before
668 // resolution of the element.
669 TreeElements treeElements = factory.treeElements;
670 assert(invariant(node, treeElements != null,
671 message: 'No TreeElements cached for $factory.'));
662 FunctionExpression functionNode = factory.parseNode(compiler); 672 FunctionExpression functionNode = factory.parseNode(compiler);
663 Return redirectionNode = functionNode.body; 673 Return redirectionNode = functionNode.body;
664 InterfaceType factoryType = 674 InterfaceType factoryType =
665 treeElements.getType(redirectionNode.expression); 675 treeElements.getType(redirectionNode.expression);
666 676
667 targetType = targetType.substByContext(factoryType); 677 targetType = targetType.substByContext(factoryType);
668 factory.redirectionTarget = target; 678 factory.redirectionTarget = target;
669 factory.redirectionTargetType = targetType; 679 factory.redirectionTargetType = targetType;
670 } 680 }
671 } 681 }
(...skipping 500 matching lines...) Expand 10 before | Expand all | Expand 10 after
1172 Node node = annotation.parseNode(compiler); 1182 Node node = annotation.parseNode(compiler);
1173 // TODO(johnniwinther): Find the right analyzable element to hold the 1183 // TODO(johnniwinther): Find the right analyzable element to hold the
1174 // [TreeElements] for the annotation. 1184 // [TreeElements] for the annotation.
1175 Element annotatedElement = annotation.annotatedElement; 1185 Element annotatedElement = annotation.annotatedElement;
1176 Element context = annotatedElement.enclosingElement; 1186 Element context = annotatedElement.enclosingElement;
1177 if (context == null) { 1187 if (context == null) {
1178 context = annotatedElement; 1188 context = annotatedElement;
1179 } 1189 }
1180 ResolverVisitor visitor = visitorFor(context); 1190 ResolverVisitor visitor = visitorFor(context);
1181 node.accept(visitor); 1191 node.accept(visitor);
1182 annotation.value = compiler.constantHandler.compileNodeWithDefinitions( 1192 annotation.value =
1183 node, visitor.mapping, isConst: true); 1193 constantCompiler.compileMetadata(annotation, node, visitor.mapping);
1184 compiler.backend.registerMetadataConstant(annotation.value, 1194 // TODO(johnniwinther): Register the relation between the annotation
1185 visitor.mapping); 1195 // and the annotated element instead. This will allow the backed to
1186 1196 // retrieve the backend constant and only registered metadata on the
1197 // elements for which it is needed. (Issue 17732).
1198 compiler.backend.registerMetadataConstant(
1199 annotation.value, visitor.mapping);
1187 annotation.resolutionState = STATE_DONE; 1200 annotation.resolutionState = STATE_DONE;
1188 })); 1201 }));
1189 } 1202 }
1190 1203
1191 error(Spannable node, MessageKind kind, [arguments = const {}]) { 1204 error(Spannable node, MessageKind kind, [arguments = const {}]) {
1192 // TODO(ahe): Make non-fatal. 1205 // TODO(ahe): Make non-fatal.
1193 compiler.reportFatalError(node, kind, arguments); 1206 compiler.reportFatalError(node, kind, arguments);
1194 } 1207 }
1195 1208
1196 Link<MetadataAnnotation> resolveMetadata(Element element, 1209 Link<MetadataAnnotation> resolveMetadata(Element element,
1197 VariableDefinitions node) { 1210 VariableDefinitions node) {
1198 LinkBuilder<MetadataAnnotation> metadata = 1211 LinkBuilder<MetadataAnnotation> metadata =
1199 new LinkBuilder<MetadataAnnotation>(); 1212 new LinkBuilder<MetadataAnnotation>();
1200 for (Metadata annotation in node.metadata.nodes) { 1213 for (Metadata annotation in node.metadata.nodes) {
1201 ParameterMetadataAnnotation metadataAnnotation = 1214 ParameterMetadataAnnotation metadataAnnotation =
1202 new ParameterMetadataAnnotation(annotation); 1215 new ParameterMetadataAnnotation(annotation);
1203 metadataAnnotation.annotatedElement = element; 1216 metadataAnnotation.annotatedElement = element;
1204 metadata.addLast(metadataAnnotation.ensureResolved(compiler)); 1217 metadata.addLast(metadataAnnotation.ensureResolved(compiler));
1205 } 1218 }
1206 return metadata.toLink(); 1219 return metadata.toLink();
1207 } 1220 }
1208 } 1221 }
1209 1222
1210 class ConstantMapper extends Visitor {
1211 final Map<Constant, Node> constantToNodeMap = new Map<Constant, Node>();
1212 final CompileTimeConstantEvaluator evaluator;
1213
1214 ConstantMapper(ConstantHandler handler,
1215 TreeElements elements,
1216 Compiler compiler)
1217 : evaluator = new CompileTimeConstantEvaluator(
1218 handler, elements, compiler, isConst: false);
1219
1220 visitNode(Node node) {
1221 Constant constant = evaluator.evaluate(node);
1222 if (constant != null) constantToNodeMap[constant] = node;
1223 node.visitChildren(this);
1224 }
1225 }
1226
1227 class InitializerResolver { 1223 class InitializerResolver {
1228 final ResolverVisitor visitor; 1224 final ResolverVisitor visitor;
1229 final Map<Element, Node> initialized; 1225 final Map<Element, Node> initialized;
1230 Link<Node> initializers; 1226 Link<Node> initializers;
1231 bool hasSuper; 1227 bool hasSuper;
1232 1228
1233 InitializerResolver(this.visitor) 1229 InitializerResolver(this.visitor)
1234 : initialized = new Map<Element, Node>(), hasSuper = false; 1230 : initialized = new Map<Element, Node>(), hasSuper = false;
1235 1231
1236 error(Node node, MessageKind kind, [arguments = const {}]) { 1232 error(Node node, MessageKind kind, [arguments = const {}]) {
(...skipping 964 matching lines...) Expand 10 before | Expand all | Expand 10 after
2201 // fields they reference are visible, but must be resolved independently. 2197 // fields they reference are visible, but must be resolved independently.
2202 if (element.kind == ElementKind.FIELD_PARAMETER) { 2198 if (element.kind == ElementKind.FIELD_PARAMETER) {
2203 useElement(parameterNode, element); 2199 useElement(parameterNode, element);
2204 } else { 2200 } else {
2205 defineElement(parameterNode, element); 2201 defineElement(parameterNode, element);
2206 } 2202 }
2207 parameterNodes = parameterNodes.tail; 2203 parameterNodes = parameterNodes.tail;
2208 }); 2204 });
2209 addDeferredAction(enclosingElement, () { 2205 addDeferredAction(enclosingElement, () {
2210 functionParameters.forEachOptionalParameter((Element parameter) { 2206 functionParameters.forEachOptionalParameter((Element parameter) {
2211 compiler.constantHandler.compileConstant(parameter); 2207 compiler.resolver.constantCompiler.compileConstant(parameter);
2212 }); 2208 });
2213 }); 2209 });
2214 if (inCheckContext) { 2210 if (inCheckContext) {
2215 functionParameters.forEachParameter((Element element) { 2211 functionParameters.forEachParameter((Element element) {
2216 compiler.enqueuer.resolution.registerIsCheck( 2212 compiler.enqueuer.resolution.registerIsCheck(
2217 element.computeType(compiler), mapping); 2213 element.computeType(compiler), mapping);
2218 }); 2214 });
2219 } 2215 }
2220 } 2216 }
2221 2217
(...skipping 359 matching lines...) Expand 10 before | Expand all | Expand 10 after
2581 // type variable expression. 2577 // type variable expression.
2582 mapping.setType(node, compiler.typeClass.computeType(compiler)); 2578 mapping.setType(node, compiler.typeClass.computeType(compiler));
2583 world.registerTypeLiteral(target, mapping); 2579 world.registerTypeLiteral(target, mapping);
2584 } else if (target.impliesType() && (!sendIsMemberAccess || node.isCall)) { 2580 } else if (target.impliesType() && (!sendIsMemberAccess || node.isCall)) {
2585 // Set the type of the node to [Type] to mark this send as a 2581 // Set the type of the node to [Type] to mark this send as a
2586 // type literal. 2582 // type literal.
2587 mapping.setType(node, compiler.typeClass.computeType(compiler)); 2583 mapping.setType(node, compiler.typeClass.computeType(compiler));
2588 world.registerTypeLiteral(target, mapping); 2584 world.registerTypeLiteral(target, mapping);
2589 2585
2590 // Don't try to make constants of calls to type literals. 2586 // Don't try to make constants of calls to type literals.
2591 analyzeConstant(node, isConst: !node.isCall); 2587 if (!node.isCall) {
2588 analyzeConstant(node);
2589 } else {
2590 // The node itself is not a constant but we register the selector (the
2591 // identifier that refers to the class/typedef) as a constant.
2592 analyzeConstant(node.selector);
2593 }
2592 } 2594 }
2593 if (isPotentiallyMutableTarget(target)) { 2595 if (isPotentiallyMutableTarget(target)) {
2594 if (enclosingElement != target.enclosingElement) { 2596 if (enclosingElement != target.enclosingElement) {
2595 for (Node scope in promotionScope) { 2597 for (Node scope in promotionScope) {
2596 mapping.setAccessedByClosureIn(scope, target, node); 2598 mapping.setAccessedByClosureIn(scope, target, node);
2597 } 2599 }
2598 } 2600 }
2599 } 2601 }
2600 } 2602 }
2601 2603
(...skipping 449 matching lines...) Expand 10 before | Expand all | Expand 10 after
3051 world.registerFactoryWithTypeArguments(mapping); 3053 world.registerFactoryWithTypeArguments(mapping);
3052 } 3054 }
3053 if (constructor.isGenerativeConstructor() && cls.isAbstract) { 3055 if (constructor.isGenerativeConstructor() && cls.isAbstract) {
3054 warning(node, MessageKind.ABSTRACT_CLASS_INSTANTIATION); 3056 warning(node, MessageKind.ABSTRACT_CLASS_INSTANTIATION);
3055 compiler.backend.registerAbstractClassInstantiation(mapping); 3057 compiler.backend.registerAbstractClassInstantiation(mapping);
3056 } 3058 }
3057 3059
3058 if (isSymbolConstructor) { 3060 if (isSymbolConstructor) {
3059 if (node.isConst()) { 3061 if (node.isConst()) {
3060 Node argumentNode = node.send.arguments.head; 3062 Node argumentNode = node.send.arguments.head;
3061 Constant name = compiler.constantHandler.compileNodeWithDefinitions( 3063 Constant name = compiler.resolver.constantCompiler.compileNode(
3062 argumentNode, mapping, isConst: true); 3064 argumentNode, mapping);
3063 if (!name.isString) { 3065 if (!name.isString) {
3064 DartType type = name.computeType(compiler); 3066 DartType type = name.computeType(compiler);
3065 compiler.reportError(argumentNode, MessageKind.STRING_EXPECTED, 3067 compiler.reportError(argumentNode, MessageKind.STRING_EXPECTED,
3066 {'type': type}); 3068 {'type': type});
3067 } else { 3069 } else {
3068 StringConstant stringConstant = name; 3070 StringConstant stringConstant = name;
3069 String nameString = stringConstant.toDartString().slowToString(); 3071 String nameString = stringConstant.toDartString().slowToString();
3070 if (validateSymbol(argumentNode, nameString)) { 3072 if (validateSymbol(argumentNode, nameString)) {
3071 world.registerConstSymbol(nameString, mapping); 3073 world.registerConstSymbol(nameString, mapping);
3072 } 3074 }
(...skipping 27 matching lines...) Expand all
3100 if (cls == compiler.stringClass) continue; 3102 if (cls == compiler.stringClass) continue;
3101 Element equals = cls.lookupMember('=='); 3103 Element equals = cls.lookupMember('==');
3102 if (equals.getEnclosingClass() != compiler.objectClass) { 3104 if (equals.getEnclosingClass() != compiler.objectClass) {
3103 compiler.reportError(spannable, 3105 compiler.reportError(spannable,
3104 MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS, 3106 MessageKind.CONST_MAP_KEY_OVERRIDES_EQUALS,
3105 {'type': keyType}); 3107 {'type': keyType});
3106 } 3108 }
3107 } 3109 }
3108 } 3110 }
3109 3111
3110 void analyzeConstant(Node node, {bool isConst: true}) { 3112 void analyzeConstant(Node node) {
3111 addDeferredAction(enclosingElement, () { 3113 addDeferredAction(enclosingElement, () {
3112 Constant constant = compiler.constantHandler.compileNodeWithDefinitions( 3114 Constant constant =
3113 node, mapping, isConst: isConst); 3115 compiler.resolver.constantCompiler.compileNode(node, mapping);
3114 3116
3115 if (isConst && constant != null && constant.isMap) { 3117 if (constant.isMap) {
3116 checkConstMapKeysDontOverrideEquals(node, constant); 3118 checkConstMapKeysDontOverrideEquals(node, constant);
3117 } 3119 }
3118 3120
3119 // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names 3121 // The type constant that is an argument to JS_INTERCEPTOR_CONSTANT names
3120 // a class that will be instantiated outside the program by attaching a 3122 // a class that will be instantiated outside the program by attaching a
3121 // native class dispatch record referencing the interceptor. 3123 // native class dispatch record referencing the interceptor.
3122 if (argumentsToJsInterceptorConstant != null && 3124 if (argumentsToJsInterceptorConstant != null &&
3123 argumentsToJsInterceptorConstant.contains(node)) { 3125 argumentsToJsInterceptorConstant.contains(node)) {
3124 if (constant.isType) { 3126 if (constant.isType) {
3125 TypeConstant typeConstant = constant; 3127 TypeConstant typeConstant = constant;
(...skipping 1329 matching lines...) Expand 10 before | Expand all | Expand 10 after
4455 4457
4456 visitNodeList(NodeList node) { 4458 visitNodeList(NodeList node) {
4457 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) { 4459 for (Link<Node> link = node.nodes; !link.isEmpty; link = link.tail) {
4458 Identifier name = visit(link.head); 4460 Identifier name = visit(link.head);
4459 VariableElement element = new VariableElementX( 4461 VariableElement element = new VariableElementX(
4460 name.source, kind, resolver.enclosingElement, 4462 name.source, kind, resolver.enclosingElement,
4461 variables, name.token); 4463 variables, name.token);
4462 resolver.defineElement(link.head, element); 4464 resolver.defineElement(link.head, element);
4463 if (definitions.modifiers.isConst()) { 4465 if (definitions.modifiers.isConst()) {
4464 compiler.enqueuer.resolution.addDeferredAction(element, () { 4466 compiler.enqueuer.resolution.addDeferredAction(element, () {
4465 compiler.constantHandler.compileVariable(element, isConst: true); 4467 compiler.resolver.constantCompiler.compileConstant(element);
4466 }); 4468 });
4467 } 4469 }
4468 } 4470 }
4469 } 4471 }
4470 } 4472 }
4471 4473
4472 class ConstructorResolver extends CommonResolverVisitor<Element> { 4474 class ConstructorResolver extends CommonResolverVisitor<Element> {
4473 final ResolverVisitor resolver; 4475 final ResolverVisitor resolver;
4474 bool inConstContext; 4476 bool inConstContext;
4475 DartType type; 4477 DartType type;
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after
4662 TreeElements _treeElements; 4664 TreeElements _treeElements;
4663 4665
4664 bool get hasTreeElements => _treeElements != null; 4666 bool get hasTreeElements => _treeElements != null;
4665 4667
4666 TreeElements get treeElements { 4668 TreeElements get treeElements {
4667 assert(invariant(this, _treeElements !=null, 4669 assert(invariant(this, _treeElements !=null,
4668 message: "TreeElements have not been computed for $this.")); 4670 message: "TreeElements have not been computed for $this."));
4669 return _treeElements; 4671 return _treeElements;
4670 } 4672 }
4671 } 4673 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698