| OLD | NEW |
| 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 js_backend; | 5 part of js_backend; |
| 6 | 6 |
| 7 const VERBOSE_OPTIMIZER_HINTS = false; | 7 const VERBOSE_OPTIMIZER_HINTS = false; |
| 8 | 8 |
| 9 class JavaScriptItemCompilationContext extends ItemCompilationContext { | 9 class JavaScriptItemCompilationContext extends ItemCompilationContext { |
| 10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); | 10 final Set<HInstruction> boundsChecked = new Set<HInstruction>(); |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 157 * generated. | 157 * generated. |
| 158 */ | 158 */ |
| 159 final Map<String, Selector> oneShotInterceptors; | 159 final Map<String, Selector> oneShotInterceptors; |
| 160 | 160 |
| 161 /** | 161 /** |
| 162 * The members of instantiated interceptor classes: maps a member name to the | 162 * The members of instantiated interceptor classes: maps a member name to the |
| 163 * list of members that have that name. This map is used by the codegen to | 163 * list of members that have that name. This map is used by the codegen to |
| 164 * know whether a send must be intercepted or not. | 164 * know whether a send must be intercepted or not. |
| 165 */ | 165 */ |
| 166 final Map<String, Set<Element>> interceptedElements; | 166 final Map<String, Set<Element>> interceptedElements; |
| 167 // TODO(sra): Not all methods in the Set always require an interceptor. A | 167 |
| 168 // method may be mixed into a true interceptor *and* a plain class. For the | 168 /** |
| 169 // method to work on the interceptor class it needs to use the explicit | 169 * The members of mixin classes that are mixed into an instantiated |
| 170 // receiver. This constrains the call on a known plain receiver to pass the | 170 * interceptor class. This is a cached subset of [interceptedElements]. |
| 171 // explicit receiver. https://code.google.com/p/dart/issues/detail?id=8942 | 171 * These members must be invoked with a correct explicit receiver even when |
| 172 * the receiver is not an intercepted class because the function uses the |
| 173 * explicit interceptor parameter since it may be called on an intercepted |
| 174 * class. |
| 175 */ |
| 176 final Map<String, Set<Element>> interceptedMixinElements = |
| 177 new Map<String, Set<Element>>(); |
| 172 | 178 |
| 173 /** | 179 /** |
| 174 * A map of specialized versions of the [getInterceptorMethod]. | 180 * A map of specialized versions of the [getInterceptorMethod]. |
| 175 * Since [getInterceptorMethod] is a hot method at runtime, we're | 181 * Since [getInterceptorMethod] is a hot method at runtime, we're |
| 176 * always specializing it based on the incoming type. The keys in | 182 * always specializing it based on the incoming type. The keys in |
| 177 * the map are the names of these specialized versions. Note that | 183 * the map are the names of these specialized versions. Note that |
| 178 * the generic version that contains all possible type checks is | 184 * the generic version that contains all possible type checks is |
| 179 * also stored in this map. | 185 * also stored in this map. |
| 180 */ | 186 */ |
| 181 final Map<String, Set<ClassElement>> specializedGetInterceptors; | 187 final Map<String, Set<ClassElement>> specializedGetInterceptors; |
| (...skipping 178 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 360 } | 366 } |
| 361 | 367 |
| 362 bool isInterceptedName(String name) { | 368 bool isInterceptedName(String name) { |
| 363 return interceptedElements[name] != null; | 369 return interceptedElements[name] != null; |
| 364 } | 370 } |
| 365 | 371 |
| 366 bool isInterceptedSelector(Selector selector) { | 372 bool isInterceptedSelector(Selector selector) { |
| 367 return interceptedElements[selector.name] != null; | 373 return interceptedElements[selector.name] != null; |
| 368 } | 374 } |
| 369 | 375 |
| 376 /** |
| 377 * Returns `true` iff [selector] matches an element defined in a class mixed |
| 378 * into an intercepted class. These selectors are not eligible for the 'dummy |
| 379 * explicit receiver' optimization. |
| 380 */ |
| 381 bool isInterceptedMixinSelector(Selector selector) { |
| 382 Set<Element> elements = interceptedMixinElements.putIfAbsent( |
| 383 selector.name, |
| 384 () { |
| 385 Set<Element> elements = interceptedElements[selector.name]; |
| 386 if (elements == null) return null; |
| 387 return elements |
| 388 .where((element) => |
| 389 classesMixedIntoNativeClasses.contains( |
| 390 element.getEnclosingClass())) |
| 391 .toSet(); |
| 392 }); |
| 393 |
| 394 if (elements == null) return false; |
| 395 if (elements.isEmpty) return false; |
| 396 return elements.any((element) => selector.applies(element, compiler)); |
| 397 } |
| 398 |
| 370 final Map<String, Set<ClassElement>> interceptedClassesCache = | 399 final Map<String, Set<ClassElement>> interceptedClassesCache = |
| 371 new Map<String, Set<ClassElement>>(); | 400 new Map<String, Set<ClassElement>>(); |
| 372 | 401 |
| 373 /** | 402 /** |
| 374 * Returns a set of interceptor classes that contain a member named | 403 * Returns a set of interceptor classes that contain a member named |
| 375 * [name]. Returns [:null:] if there is no class. | 404 * [name]. Returns [:null:] if there is no class. |
| 376 */ | 405 */ |
| 377 Set<ClassElement> getInterceptedClassesOn(String name) { | 406 Set<ClassElement> getInterceptedClassesOn(String name) { |
| 378 Set<Element> intercepted = interceptedElements[name]; | 407 Set<Element> intercepted = interceptedElements[name]; |
| 379 if (intercepted == null) return null; | 408 if (intercepted == null) return null; |
| (...skipping 1466 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1846 void visitTrue(TrueConstant constant) => copy(constant); | 1875 void visitTrue(TrueConstant constant) => copy(constant); |
| 1847 | 1876 |
| 1848 void visitFalse(FalseConstant constant) => copy(constant); | 1877 void visitFalse(FalseConstant constant) => copy(constant); |
| 1849 | 1878 |
| 1850 void visitString(StringConstant constant) => copy(constant); | 1879 void visitString(StringConstant constant) => copy(constant); |
| 1851 | 1880 |
| 1852 void visitType(TypeConstant constant) => copy(constant); | 1881 void visitType(TypeConstant constant) => copy(constant); |
| 1853 | 1882 |
| 1854 void visitInterceptor(InterceptorConstant constant) => copy(constant); | 1883 void visitInterceptor(InterceptorConstant constant) => copy(constant); |
| 1855 | 1884 |
| 1885 void visitDummyReceiver(DummyReceiverConstant constant) => copy(constant); |
| 1886 |
| 1856 void visitList(ListConstant constant) { | 1887 void visitList(ListConstant constant) { |
| 1857 copy(constant.entries); | 1888 copy(constant.entries); |
| 1858 copy(constant); | 1889 copy(constant); |
| 1859 } | 1890 } |
| 1860 void visitMap(MapConstant constant) { | 1891 void visitMap(MapConstant constant) { |
| 1861 copy(constant.keys); | 1892 copy(constant.keys); |
| 1862 copy(constant.values); | 1893 copy(constant.values); |
| 1863 copy(constant.protoValue); | 1894 copy(constant.protoValue); |
| 1864 copy(constant); | 1895 copy(constant); |
| 1865 } | 1896 } |
| 1866 | 1897 |
| 1867 void visitConstructed(ConstructedConstant constant) { | 1898 void visitConstructed(ConstructedConstant constant) { |
| 1868 copy(constant.fields); | 1899 copy(constant.fields); |
| 1869 copy(constant); | 1900 copy(constant); |
| 1870 } | 1901 } |
| 1871 } | 1902 } |
| OLD | NEW |