| 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;
|
| }
|
|
|