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