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

Unified Diff: lib/compiler/implementation/universe.dart

Issue 10191016: Introduce typed selectors for getters and setters also for better tree shaking. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « lib/compiler/implementation/ssa/codegen.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/compiler/implementation/universe.dart
===================================================================
--- lib/compiler/implementation/universe.dart (revision 6933)
+++ lib/compiler/implementation/universe.dart (working copy)
@@ -9,8 +9,8 @@
final Set<SourceString> instantiatedClassInstanceFields;
final Set<FunctionElement> staticFunctionsNeedingGetter;
final Map<SourceString, Set<Selector>> invokedNames;
- final Set<SourceString> invokedGetters;
- final Set<SourceString> invokedSetters;
+ final Map<SourceString, Set<Selector>> invokedGetters;
+ final Map<SourceString, Set<Selector>> invokedSetters;
final Map<String, LibraryElement> libraries;
// TODO(ngeoffray): This should be a Set<Type>.
final Set<Element> isChecks;
@@ -22,8 +22,8 @@
instantiatedClassInstanceFields = new Set<SourceString>(),
staticFunctionsNeedingGetter = new Set<FunctionElement>(),
invokedNames = new Map<SourceString, Set<Selector>>(),
- invokedGetters = new Set<SourceString>(),
- invokedSetters = new Set<SourceString>(),
+ invokedGetters = new Map<SourceString, Set<Selector>>(),
+ invokedSetters = new Map<SourceString, Set<Selector>>(),
isChecks = new Set<Element>();
void addGeneratedCode(WorkItem work, String code) {
@@ -33,6 +33,31 @@
void addBailoutCode(WorkItem work, String code) {
generatedBailoutCode[work.element] = code;
}
+
+ bool hasMatchingSelector(Set<Selector> selectors,
+ Element member,
+ Compiler compiler) {
+ if (selectors === null) return false;
+ for (Selector selector in selectors) {
+ if (selector.applies(member, compiler)) return true;
+ }
+ return false;
+ }
+
+ bool hasInvocation(Element member, Compiler compiler) {
+ return hasMatchingSelector(
+ compiler.universe.invokedNames[member.name], member, compiler);
+ }
+
+ bool hasGetter(Element member, Compiler compiler) {
+ return hasMatchingSelector(
+ compiler.universe.invokedGetters[member.name], member, compiler);
+ }
+
+ bool hasSetter(Element member, Compiler compiler) {
+ return hasMatchingSelector(
+ compiler.universe.invokedSetters[member.name], member, compiler);
+ }
}
class SelectorKind {
@@ -52,34 +77,67 @@
// The numbers of arguments of the selector. Includes named arguments.
final int argumentCount;
final SelectorKind kind;
- const Selector(this.kind, this.argumentCount);
+ final List<SourceString> namedArguments = const <SourceString>[];
+ final List<SourceString> orderedNamedArguments = const <SourceString>[];
+ // The const constructor.
+ const Selector.constant(this.kind, this.argumentCount);
+
+ Selector(
+ this.kind,
+ this.argumentCount,
+ [List<SourceString> namedArguments = const <SourceString>[]])
+ : this.namedArguments = namedArguments,
+ this.orderedNamedArguments = namedArguments.isEmpty()
+ ? namedArguments
+ : <SourceString>[];
+
+ Selector.invocation(
+ int argumentCount,
+ [List<SourceString> namedArguments = const <SourceString>[]])
+ : this(SelectorKind.INVOCATION, argumentCount, namedArguments);
+
int hashCode() => argumentCount + 1000 * namedArguments.length;
- List<SourceString> get namedArguments() => const <SourceString>[];
- int get namedArgumentCount() => 0;
- int get positionalArgumentCount() => argumentCount;
+ int get namedArgumentCount() => namedArguments.length;
+ int get positionalArgumentCount() => argumentCount - namedArgumentCount;
- static final Selector GETTER = const Selector(SelectorKind.GETTER, 0);
- static final Selector SETTER = const Selector(SelectorKind.SETTER, 1);
+ static final Selector GETTER =
+ const Selector.constant(SelectorKind.GETTER, 0);
+ static final Selector SETTER =
+ const Selector.constant(SelectorKind.SETTER, 1);
static final Selector UNARY_OPERATOR =
- const Selector(SelectorKind.OPERATOR, 0);
+ const Selector.constant(SelectorKind.OPERATOR, 0);
static final Selector BINARY_OPERATOR =
- const Selector(SelectorKind.OPERATOR, 1);
- static final Selector INDEX = const Selector(SelectorKind.INDEX, 1);
- static final Selector INDEX_SET = const Selector(SelectorKind.INDEX, 2);
+ const Selector.constant(SelectorKind.OPERATOR, 1);
+ static final Selector INDEX =
+ const Selector.constant(SelectorKind.INDEX, 1);
+ static final Selector INDEX_SET =
+ const Selector.constant(SelectorKind.INDEX, 2);
static final Selector INDEX_AND_INDEX_SET =
- const Selector(SelectorKind.INDEX, 2);
+ const Selector.constant(SelectorKind.INDEX, 2);
static final Selector GETTER_AND_SETTER =
- const Selector(SelectorKind.SETTER, 1);
+ const Selector.constant(SelectorKind.SETTER, 1);
static final Selector INVOCATION_0 =
- const Selector(SelectorKind.INVOCATION, 0);
+ const Selector.constant(SelectorKind.INVOCATION, 0);
static final Selector INVOCATION_1 =
- const Selector(SelectorKind.INVOCATION, 1);
+ const Selector.constant(SelectorKind.INVOCATION, 1);
static final Selector INVOCATION_2 =
- const Selector(SelectorKind.INVOCATION, 2);
+ const Selector.constant(SelectorKind.INVOCATION, 2);
- bool applies(FunctionElement element, Compiler compiler) {
- FunctionParameters parameters = element.computeParameters(compiler);
+ bool applies(Element element, Compiler compiler) {
+ if (element.isSetter()) return kind === SelectorKind.SETTER;
+ if (element.isGetter()) {
+ return kind === SelectorKind.GETTER || kind === SelectorKind.INVOCATION;
+ }
+ if (element.isField()) {
+ return kind === SelectorKind.GETTER
+ || kind === SelectorKind.INVOCATION
+ || kind === SelectorKind.SETTER;
+ }
+ if (kind === SelectorKind.GETTER) return true;
+
+ FunctionElement function = element;
+ FunctionParameters parameters = function.computeParameters(compiler);
if (argumentCount > parameters.parameterCount) return false;
int requiredParameterCount = parameters.requiredParameterCount;
int optionalParameterCount = parameters.optionalParameterCount;
@@ -203,63 +261,75 @@
&& sameNames(namedArguments, other.namedArguments);
}
- List<SourceString> getOrderedNamedArguments() => namedArguments;
-
- toString() => '$kind $argumentCount';
-}
-
-class Invocation extends Selector {
- final List<SourceString> namedArguments;
- List<SourceString> orderedNamedArguments;
- int get namedArgumentCount() => namedArguments.length;
- int get positionalArgumentCount() => argumentCount - namedArgumentCount;
-
- Invocation(int argumentCount,
- [List<SourceString> names = const <SourceString>[]])
- : super(SelectorKind.INVOCATION, argumentCount),
- namedArguments = names,
- orderedNamedArguments = const <SourceString>[];
-
List<SourceString> getOrderedNamedArguments() {
if (namedArguments.isEmpty()) return namedArguments;
- // We use the empty const List as a sentinel.
if (!orderedNamedArguments.isEmpty()) return orderedNamedArguments;
- List<SourceString> list = new List<SourceString>.from(namedArguments);
- list.sort((SourceString first, SourceString second) {
+ orderedNamedArguments.addAll(namedArguments);
+ orderedNamedArguments.sort((SourceString first, SourceString second) {
return first.slowToString().compareTo(second.slowToString());
});
- orderedNamedArguments = list;
return orderedNamedArguments;
}
+
+ toString() => '$kind $argumentCount';
}
-/**
- * A [TypedInvocation] is an invocation where we have information on
- * the type of the receiver.
- */
-class TypedInvocation extends Invocation {
+class TypedSelector extends Selector {
/**
* The type of the receiver. Any subtype of that type can be the
* target of the invocation.
*/
final Type receiverType;
- TypedInvocation(this.receiverType, Selector selector)
- : super(selector.argumentCount, selector.namedArguments);
+ TypedSelector(this.receiverType, Selector selector)
+ : super(selector.kind,
+ selector.argumentCount,
+ selector.namedArguments);
- bool applies(FunctionElement element, Compiler compiler) {
+ bool applies(Element element, Compiler compiler) {
if (!element.enclosingElement.isClass()) return false;
+ // A closure can be called through any typed selector:
+ // class A {
+ // get foo() => () => 42;
+ // bar() => foo(); // The call to 'foo' is a typed selector.
+ // }
+ if (element.enclosingElement.superclass === compiler.closureClass) {
+ return super.applies(element, compiler);
+ }
+
ClassElement other = element.enclosingElement;
ClassElement self = receiverType.element;
- if (!other.isSubclassOf(self)) return false;
- return super.applies(element, compiler);
+
+ // If the class of the element is a subclass of this selector's
+ // class, it is a candidate.
+ if (other.isSubclassOf(self)) {
+ return super.applies(element, compiler);
+ }
+
+ if (self.isSubclassOf(other)) {
+ // Resolve an invocation of [element.name] on [self]. If the
+ // found element is [element], or is an abstract field whose
+ // getter or setter is [element], this selector is a candidate.
+ Element resolved = self.lookupMember(element.name);
+ if (resolved === element) {
+ return super.applies(element, compiler);
+ }
+
+ if (resolved !== null && resolved.kind === ElementKind.ABSTRACT_FIELD) {
+ AbstractFieldElement field = resolved;
+ if (element === field.getter || element === field.setter) {
+ return super.applies(element, compiler);
+ }
+ }
+ }
+
return false;
}
bool operator ==(other) {
- if (other is !TypedInvocation) return false;
+ if (other is !TypedSelector) return false;
if (other.receiverType !== receiverType) return false;
return super == other;
}
« no previous file with comments | « lib/compiler/implementation/ssa/codegen.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698