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

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

Issue 12207081: Add a type kind to TypedSelector. A typed selector can either be (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 10 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 library universe; 5 library universe;
6 6
7 import '../closure.dart'; 7 import '../closure.dart';
8 import '../elements/elements.dart'; 8 import '../elements/elements.dart';
9 import '../dart2jslib.dart'; 9 import '../dart2jslib.dart';
10 import '../dart_types.dart'; 10 import '../dart_types.dart';
(...skipping 23 matching lines...) Expand all
34 final Set<FunctionElement> staticFunctionsNeedingGetter; 34 final Set<FunctionElement> staticFunctionsNeedingGetter;
35 final Map<SourceString, Set<Selector>> invokedNames; 35 final Map<SourceString, Set<Selector>> invokedNames;
36 final Map<SourceString, Set<Selector>> invokedGetters; 36 final Map<SourceString, Set<Selector>> invokedGetters;
37 final Map<SourceString, Set<Selector>> invokedSetters; 37 final Map<SourceString, Set<Selector>> invokedSetters;
38 38
39 /** 39 /**
40 * Fields accessed. Currently only the codegen knows this 40 * Fields accessed. Currently only the codegen knows this
41 * information. The resolver is too conservative when seeing a 41 * information. The resolver is too conservative when seeing a
42 * getter and only registers an invoked getter. 42 * getter and only registers an invoked getter.
43 */ 43 */
44 final Map<SourceString, Set<Selector>> fieldGetters; 44 final Set<Element> fieldGetters;
45 45
46 /** 46 /**
47 * Fields set. See comment in [fieldGetters]. 47 * Fields set. See comment in [fieldGetters].
48 */ 48 */
49 final Map<SourceString, Set<Selector>> fieldSetters; 49 final Set<Element> fieldSetters;
50 final Set<DartType> isChecks; 50 final Set<DartType> isChecks;
51 51
52 Universe() : instantiatedClasses = new Set<ClassElement>(), 52 Universe() : instantiatedClasses = new Set<ClassElement>(),
53 instantiatedTypes = new Set<DartType>(), 53 instantiatedTypes = new Set<DartType>(),
54 staticFunctionsNeedingGetter = new Set<FunctionElement>(), 54 staticFunctionsNeedingGetter = new Set<FunctionElement>(),
55 invokedNames = new Map<SourceString, Set<Selector>>(), 55 invokedNames = new Map<SourceString, Set<Selector>>(),
56 invokedGetters = new Map<SourceString, Set<Selector>>(), 56 invokedGetters = new Map<SourceString, Set<Selector>>(),
57 fieldGetters = new Map<SourceString, Set<Selector>>(),
58 fieldSetters = new Map<SourceString, Set<Selector>>(),
59 invokedSetters = new Map<SourceString, Set<Selector>>(), 57 invokedSetters = new Map<SourceString, Set<Selector>>(),
58 fieldGetters = new Set<Element>(),
59 fieldSetters = new Set<Element>(),
60 isChecks = new Set<DartType>(); 60 isChecks = new Set<DartType>();
61 61
62 bool hasMatchingSelector(Set<Selector> selectors, 62 bool hasMatchingSelector(Set<Selector> selectors,
63 Element member, 63 Element member,
64 Compiler compiler) { 64 Compiler compiler) {
65 if (selectors == null) return false; 65 if (selectors == null) return false;
66 for (Selector selector in selectors) { 66 for (Selector selector in selectors) {
67 if (selector.appliesUnnamed(member, compiler)) return true; 67 if (selector.appliesUnnamed(member, compiler)) return true;
68 } 68 }
69 return false; 69 return false;
70 } 70 }
71 71
72 bool hasInvocation(Element member, Compiler compiler) { 72 bool hasInvocation(Element member, Compiler compiler) {
73 return hasMatchingSelector(invokedNames[member.name], member, compiler); 73 return hasMatchingSelector(invokedNames[member.name], member, compiler);
74 } 74 }
75 75
76 bool hasInvokedGetter(Element member, Compiler compiler) { 76 bool hasInvokedGetter(Element member, Compiler compiler) {
77 return hasMatchingSelector(invokedGetters[member.name], member, compiler); 77 return hasMatchingSelector(invokedGetters[member.name], member, compiler);
78 } 78 }
79 79
80 bool hasInvokedSetter(Element member, Compiler compiler) { 80 bool hasInvokedSetter(Element member, Compiler compiler) {
81 return hasMatchingSelector(invokedSetters[member.name], member, compiler); 81 return hasMatchingSelector(invokedSetters[member.name], member, compiler);
82 } 82 }
83 83
84 bool hasFieldGetter(Element member, Compiler compiler) { 84 bool hasFieldGetter(Element member, Compiler compiler) {
85 return hasMatchingSelector(fieldGetters[member.name], member, compiler); 85 return fieldGetters.contains(member);
86 } 86 }
87 87
88 bool hasFieldSetter(Element member, Compiler compiler) { 88 bool hasFieldSetter(Element member, Compiler compiler) {
89 return hasMatchingSelector(fieldSetters[member.name], member, compiler); 89 return fieldSetters.contains(member);
90 } 90 }
91 } 91 }
92 92
93 class SelectorKind { 93 class SelectorKind {
94 final String name; 94 final String name;
95 const SelectorKind(this.name); 95 const SelectorKind(this.name);
96 96
97 static const SelectorKind GETTER = const SelectorKind('getter'); 97 static const SelectorKind GETTER = const SelectorKind('getter');
98 static const SelectorKind SETTER = const SelectorKind('setter'); 98 static const SelectorKind SETTER = const SelectorKind('setter');
99 static const SelectorKind CALL = const SelectorKind('call'); 99 static const SelectorKind CALL = const SelectorKind('call');
100 static const SelectorKind OPERATOR = const SelectorKind('operator'); 100 static const SelectorKind OPERATOR = const SelectorKind('operator');
101 static const SelectorKind INDEX = const SelectorKind('index'); 101 static const SelectorKind INDEX = const SelectorKind('index');
102 102
103 toString() => name; 103 String toString() => name;
104 }
105
106 class TypedSelectorKind {
107 final String name;
108 const TypedSelectorKind(this.name);
109
110 /// Unknown type: used for untyped selector.
111 static const TypedSelectorKind UNKNOWN = const TypedSelectorKind('unknown');
112
113 // Exact type: the selector knows the exact type of the receiver.
114 // For example [:new Map():].
115 static const TypedSelectorKind EXACT = const TypedSelectorKind('exact');
116
117 // Subclass type: the receiver type is in a subclass hierarchy.
118 // For example [:this:].
119 static const TypedSelectorKind SUBCLASS = const TypedSelectorKind('subclass');
120
121 // Interface type: any type that implements the receiver type.
122 // For example [(foo as Foo).bar()], or any type annotation in
123 // checked mode.
124 static const TypedSelectorKind INTERFACE =
125 const TypedSelectorKind('interface');
126
127 String toString() => name;
104 } 128 }
105 129
106 class Selector { 130 class Selector {
107 final SelectorKind kind; 131 final SelectorKind kind;
108 final SourceString name; 132 final SourceString name;
109 final LibraryElement library; // Library is null for non-private selectors. 133 final LibraryElement library; // Library is null for non-private selectors.
110 134
111 // The numbers of arguments of the selector. Includes named arguments. 135 // The numbers of arguments of the selector. Includes named arguments.
112 final int argumentCount; 136 final int argumentCount;
113 final List<SourceString> namedArguments; 137 final List<SourceString> namedArguments;
114 final List<SourceString> orderedNamedArguments; 138 final List<SourceString> orderedNamedArguments;
139 TypedSelectorKind get typeKind => TypedSelectorKind.UNKNOWN;
115 140
116 Selector( 141 Selector(
117 this.kind, 142 this.kind,
118 SourceString name, 143 SourceString name,
119 LibraryElement library, 144 LibraryElement library,
120 this.argumentCount, 145 this.argumentCount,
121 [List<SourceString> namedArguments = const <SourceString>[]]) 146 [List<SourceString> namedArguments = const <SourceString>[]])
122 : this.name = name, 147 : this.name = name,
123 this.library = name.isPrivate() ? library : null, 148 this.library = name.isPrivate() ? library : null,
124 this.namedArguments = namedArguments, 149 this.namedArguments = namedArguments,
(...skipping 236 matching lines...) Expand 10 before | Expand all | Expand 10 after
361 386
362 bool operator ==(other) { 387 bool operator ==(other) {
363 if (other is !Selector) return false; 388 if (other is !Selector) return false;
364 return identical(receiverType, other.receiverType) 389 return identical(receiverType, other.receiverType)
365 && equalsUntyped(other); 390 && equalsUntyped(other);
366 } 391 }
367 392
368 bool equalsUntyped(Selector other) { 393 bool equalsUntyped(Selector other) {
369 return name == other.name 394 return name == other.name
370 && kind == other.kind 395 && kind == other.kind
396 && typeKind == other.typeKind
371 && identical(library, other.library) 397 && identical(library, other.library)
372 && argumentCount == other.argumentCount 398 && argumentCount == other.argumentCount
373 && namedArguments.length == other.namedArguments.length 399 && namedArguments.length == other.namedArguments.length
374 && sameNames(namedArguments, other.namedArguments); 400 && sameNames(namedArguments, other.namedArguments);
375 } 401 }
376 402
377 List<SourceString> getOrderedNamedArguments() { 403 List<SourceString> getOrderedNamedArguments() {
378 if (namedArguments.isEmpty) return namedArguments; 404 if (namedArguments.isEmpty) return namedArguments;
379 if (!orderedNamedArguments.isEmpty) return orderedNamedArguments; 405 if (!orderedNamedArguments.isEmpty) return orderedNamedArguments;
380 406
(...skipping 13 matching lines...) Expand all
394 } 420 }
395 return "[$result]"; 421 return "[$result]";
396 } 422 }
397 return ''; 423 return '';
398 } 424 }
399 425
400 String toString() { 426 String toString() {
401 String named = ''; 427 String named = '';
402 String type = ''; 428 String type = '';
403 if (namedArgumentCount > 0) named = ', named=${namedArgumentsToString()}'; 429 if (namedArgumentCount > 0) named = ', named=${namedArgumentsToString()}';
404 if (receiverType != null) type = ', type=$receiverType'; 430 if (receiverType != null) type = ', type=$typeKind $receiverType';
405 return 'Selector($kind, ${name.slowToString()}, ' 431 return 'Selector($kind, ${name.slowToString()}, '
406 'arity=$argumentCount$named$type)'; 432 'arity=$argumentCount$named$type)';
407 } 433 }
408 } 434 }
409 435
410 class TypedSelector extends Selector { 436 class TypedSelector extends Selector {
411 /** 437 /**
412 * The type of the receiver. Any subtype of that type can be the 438 * The type of the receiver.
413 * target of the invocation.
414 */ 439 */
415 final DartType receiverType; 440 final DartType receiverType;
441 final TypedSelectorKind typeKind;
416 442
417 final Selector asUntyped; 443 final Selector asUntyped;
418 444
419 TypedSelector(DartType this.receiverType, Selector selector) 445 TypedSelector(DartType this.receiverType, this.typeKind, Selector selector)
420 : asUntyped = selector.asUntyped, 446 : asUntyped = selector.asUntyped,
421 super(selector.kind, 447 super(selector.kind,
422 selector.name, 448 selector.name,
423 selector.library, 449 selector.library,
424 selector.argumentCount, 450 selector.argumentCount,
425 selector.namedArguments) { 451 selector.namedArguments) {
426 // Invariant: Typed selector can not be based on a malformed type. 452 // Invariant: Typed selector can not be based on a malformed type.
427 assert(!identical(receiverType.kind, TypeKind.MALFORMED_TYPE)); 453 assert(!identical(receiverType.kind, TypeKind.MALFORMED_TYPE));
428 assert(asUntyped.receiverType == null); 454 assert(asUntyped.receiverType == null);
455 assert(typeKind != TypedSelectorKind.UNKNOWN);
429 } 456 }
430 457
458 TypedSelector.subclass(DartType receiverType, Selector selector)
459 : this(receiverType, TypedSelectorKind.SUBCLASS, selector);
460
461 TypedSelector.exact(DartType receiverType, Selector selector)
462 : this(receiverType, TypedSelectorKind.EXACT, selector);
463
464 TypedSelector.subtype(DartType receiverType, Selector selector)
465 : this(receiverType, TypedSelectorKind.INTERFACE, selector);
466
431 /** 467 /**
432 * Check if [element] will be the one used at runtime when being 468 * Check if [element] will be the one used at runtime when being
433 * invoked on an instance of [cls]. 469 * invoked on an instance of [cls].
434 */ 470 */
435 bool hasElementIn(ClassElement cls, Element element) { 471 bool hasElementIn(ClassElement cls, Element element) {
436 // Use the selector for the lookup instead of [:element.name:] 472 // Use the selector for the lookup instead of [:element.name:]
437 // because the selector has the right privacy information. 473 // because the selector has the right privacy information.
438 Element resolved = cls.lookupSelector(this); 474 Element resolved = cls.lookupSelector(this);
439 if (resolved == element) return true; 475 if (resolved == element) return true;
440 if (resolved == null) return false; 476 if (resolved == null) return false;
441 if (resolved.isAbstractField()) { 477 if (resolved.isAbstractField()) {
442 AbstractFieldElement field = resolved; 478 AbstractFieldElement field = resolved;
443 if (element == field.getter || element == field.setter) { 479 if (element == field.getter || element == field.setter) {
444 return true; 480 return true;
445 } else { 481 } else {
446 ClassElement otherCls = field.getEnclosingClass();
447 // We have not found a match, but another class higher in the 482 // We have not found a match, but another class higher in the
448 // hierarchy may define the getter or the setter. 483 // hierarchy may define the getter or the setter.
449 return hasElementIn(otherCls.superclass, element); 484 ClassElement otherCls = field.getEnclosingClass().superclass;
485 if (otherCls == null) return false;
486 return hasElementIn(otherCls, element);
450 } 487 }
451 } 488 }
452 return false; 489 return false;
453 } 490 }
454 491
455 bool appliesUnnamed(Element element, Compiler compiler) { 492 bool appliesUnnamed(Element element, Compiler compiler) {
456 assert(sameNameHack(element, compiler)); 493 assert(sameNameHack(element, compiler));
457 // [TypedSelector] are only used when compiling. 494 // [TypedSelector] are only used when compiling.
458 assert(compiler.phase == Compiler.PHASE_COMPILING); 495 assert(compiler.phase == Compiler.PHASE_COMPILING);
459 if (!element.isMember()) return false; 496 if (!element.isMember()) return false;
460 497
461 // A closure can be called through any typed selector: 498 // A closure can be called through any typed selector:
462 // class A { 499 // class A {
463 // get foo => () => 42; 500 // get foo => () => 42;
464 // bar() => foo(); // The call to 'foo' is a typed selector. 501 // bar() => foo(); // The call to 'foo' is a typed selector.
465 // } 502 // }
466 ClassElement other = element.getEnclosingClass(); 503 ClassElement other = element.getEnclosingClass();
467 if (identical(other.superclass, compiler.closureClass)) { 504 if (identical(other.superclass, compiler.closureClass)) {
468 return appliesUntyped(element, compiler); 505 return appliesUntyped(element, compiler);
469 } 506 }
470 507
471 Element self = receiverType.element; 508 Element self = receiverType.element;
472 if (self.isTypedef()) { 509 if (self.isTypedef()) {
473 // A typedef is a function type that doesn't have any 510 // A typedef is a function type that doesn't have any
474 // user-defined members. 511 // user-defined members.
475 return false; 512 return false;
476 } 513 }
477 514
478 if (other.implementsInterface(self) 515 if (typeKind == TypedSelectorKind.EXACT) {
479 || other.isSubclassOf(self) 516 return hasElementIn(self, element) && appliesUntyped(element, compiler);
480 || compiler.world.hasAnySubclassThatImplements(other, receiverType)) { 517 } else if (typeKind == TypedSelectorKind.SUBCLASS) {
481 return appliesUntyped(element, compiler); 518 return (hasElementIn(self, element) || other.isSubclassOf(self))
482 } 519 && appliesUntyped(element, compiler);
520 } else {
521 assert(typeKind == TypedSelectorKind.INTERFACE);
522 if (other.implementsInterface(self)
523 || other.isSubclassOf(self)
524 || compiler.world.hasAnySubclassThatImplements(other, receiverType)) {
525 return appliesUntyped(element, compiler);
526 }
483 527
484 // If [self] is a subclass of [other], it inherits the 528 // If [self] is a subclass of [other], it inherits the
485 // implementation of [element]. 529 // implementation of [element].
486 ClassElement cls = self; 530 ClassElement cls = self;
487 if (cls.isSubclassOf(other)) { 531 if (cls.isSubclassOf(other)) {
488 // Resolve an invocation of [element.name] on [self]. If it 532 // Resolve an invocation of [element.name] on [self]. If it
489 // is found, this selector is a candidate. 533 // is found, this selector is a candidate.
490 return hasElementIn(self, element) && appliesUntyped(element, compiler); 534 return hasElementIn(self, element) && appliesUntyped(element, compiler);
535 }
491 } 536 }
492 537
493 return false; 538 return false;
494 } 539 }
495 } 540 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698