Index: sdk/lib/_internal/compiler/implementation/js_backend/backend.dart |
=================================================================== |
--- sdk/lib/_internal/compiler/implementation/js_backend/backend.dart (revision 19306) |
+++ sdk/lib/_internal/compiler/implementation/js_backend/backend.dart (working copy) |
@@ -642,7 +642,6 @@ |
ClassElement jsFunctionClass; |
ClassElement jsNullClass; |
ClassElement jsBoolClass; |
- ClassElement objectInterceptorClass; |
Element jsArrayLength; |
Element jsStringLength; |
Element jsArrayRemoveLast; |
@@ -651,6 +650,7 @@ |
Element jsStringConcat; |
Element jsStringToString; |
Element getInterceptorMethod; |
+ Element interceptedNames; |
Element fixedLengthListConstructor; |
bool seenAnyClass = false; |
@@ -705,11 +705,9 @@ |
final Map<String, Collection<ClassElement>> specializedGetInterceptors; |
/** |
- * Set of classes whose instances are intercepted. Implemented as a |
- * [LinkedHashMap] to preserve the insertion order. |
- * TODO(ngeoffray): No need to preserve order anymore. |
+ * Set of classes whose methods are intercepted. |
*/ |
- final Map<ClassElement, ClassElement> interceptedClasses; |
+ final Set<ClassElement> interceptedClasses; |
/** |
* Set of selectors that are used from within loops. Used by the |
@@ -735,7 +733,7 @@ |
rti = new RuntimeTypeInformation(compiler), |
specializedGetInterceptors = |
new Map<String, Collection<ClassElement>>(), |
- interceptedClasses = new LinkedHashMap<ClassElement, ClassElement>(), |
+ interceptedClasses = new Set<ClassElement>(), |
super(compiler, JAVA_SCRIPT_CONSTANT_SYSTEM) { |
emitter = disableEval |
? new CodeEmitterNoEvalTask(compiler, namer, generateSourceMap) |
@@ -755,7 +753,7 @@ |
bool isInterceptorClass(Element element) { |
if (element == null) return false; |
- return interceptedClasses.containsKey(element); |
+ return interceptedClasses.contains(element); |
} |
void addInterceptedSelector(Selector selector) { |
@@ -763,7 +761,7 @@ |
} |
String registerOneShotInterceptor(Selector selector) { |
- Set<ClassElement> classes = getInterceptedClassesOn(selector); |
+ Set<ClassElement> classes = getInterceptedClassesOn(selector.name); |
String name = namer.getOneShotInterceptorName(selector, classes); |
if (!oneShotInterceptors.containsKey(name)) { |
registerSpecializedGetInterceptor(classes); |
@@ -772,50 +770,44 @@ |
return name; |
} |
- final Map<Selector, Set<ClassElement>> interceptedClassesCache = |
- new Map<Selector, Set<ClassElement>>(); |
- final Map<Selector, Set<ClassElement>> interceptedClassesNonNullCache = |
- new Map<Selector, Set<ClassElement>>(); |
+ bool isInterceptedMethod(Element element) { |
+ return element.isInstanceMember() |
+ && interceptedElements[element.name] != null; |
+ } |
+ bool isInterceptedName(SourceString name) { |
+ return interceptedElements[name] != null; |
+ } |
+ |
+ final Map<SourceString, Set<ClassElement>> interceptedClassesCache = |
+ new Map<SourceString, Set<ClassElement>>(); |
+ |
/** |
- * Returns a set of interceptor classes that contain a member whose |
- * signature matches the given [selector]. Returns [:null:] if there |
- * is no class. |
+ * Returns a set of interceptor classes that contain a member named |
+ * [name]. Returns [:null:] if there is no class. |
*/ |
- Set<ClassElement> getInterceptedClassesOn(Selector selector, |
- {bool canBeNull: true}) { |
- Set<Element> intercepted = interceptedElements[selector.name]; |
+ Set<ClassElement> getInterceptedClassesOn(SourceString name) { |
+ Set<Element> intercepted = interceptedElements[name]; |
if (intercepted == null) return null; |
- // Pick the right cache and query it. |
- Map<Selector, Set<ClassElement>> cache = canBeNull |
- ? interceptedClassesCache |
- : interceptedClassesNonNullCache; |
- if (cache.containsKey(selector)) return cache[selector]; |
- // Populate the cache by running through all the elements and |
- // determine if the given selector applies to them. |
- Set<ClassElement> result = new Set<ClassElement>(); |
- for (Element element in intercepted) { |
- ClassElement enclosing = element.getEnclosingClass(); |
- // We have to treat null as a bottom type, so we use the untyped |
- // applies method for those elements that are implemented on the |
- // null class. |
- bool applies = (enclosing == jsNullClass) |
- ? canBeNull && selector.appliesUntyped(element, compiler) |
- : selector.applies(element, compiler); |
- if (applies) result.add(enclosing); |
- } |
- if (result.isEmpty) result = null; |
- cache[selector] = result; |
- assert(cache.containsKey(selector)); |
+ Set<Element> result = interceptedClassesCache.putIfAbsent(name, () { |
+ // Populate the cache by running through all the elements and |
+ // determine if the given selector applies to them. |
+ Set<ClassElement> result = new Set<ClassElement>(); |
+ for (Element element in intercepted) { |
+ result.add(element.getEnclosingClass()); |
+ } |
+ return result; |
+ }); |
return result; |
} |
void initializeHelperClasses() { |
- objectInterceptorClass = |
- compiler.findInterceptor(const SourceString('ObjectInterceptor')); |
getInterceptorMethod = |
compiler.findInterceptor(const SourceString('getInterceptor')); |
+ interceptedNames = |
+ compiler.findInterceptor(const SourceString('interceptedNames')); |
List<ClassElement> classes = [ |
+ compiler.objectClass, |
jsStringClass = compiler.findInterceptor(const SourceString('JSString')), |
jsArrayClass = compiler.findInterceptor(const SourceString('JSArray')), |
// The int class must be before the double class, because the |
@@ -847,7 +839,7 @@ |
jsStringClass, const SourceString('toString')); |
for (ClassElement cls in classes) { |
- if (cls != null) interceptedClasses[cls] = null; |
+ if (cls != null) interceptedClasses.add(cls); |
} |
} |
@@ -865,23 +857,11 @@ |
} |
void registerSpecializedGetInterceptor(Set<ClassElement> classes) { |
- compiler.enqueuer.codegen.registerInstantiatedClass(objectInterceptorClass); |
String name = namer.getInterceptorName(getInterceptorMethod, classes); |
if (classes.contains(compiler.objectClass)) { |
// We can't use a specialized [getInterceptorMethod], so we make |
// sure we emit the one with all checks. |
- specializedGetInterceptors.putIfAbsent(name, () { |
- // It is important to take the order provided by the map, |
- // because we want the int type check to happen before the |
- // double type check: the double type check covers the int |
- // type check. Also we don't need to do a number type check |
- // because that is covered by the double type check. |
- List<ClassElement> keys = <ClassElement>[]; |
- interceptedClasses.forEach((ClassElement cls, _) { |
- if (cls != jsNumberClass) keys.add(cls); |
- }); |
- return keys; |
- }); |
+ specializedGetInterceptors[name] = interceptedClasses; |
} else { |
specializedGetInterceptors[name] = classes; |
} |