Chromium Code Reviews| 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 dart2js.js_emitter; | 5 part of dart2js.js_emitter; |
| 6 | 6 |
| 7 class NativeEmitter { | 7 class NativeEmitter { |
| 8 | 8 |
| 9 final Map<Element, ClassBuilder> cachedBuilders; | 9 final Map<Element, ClassBuilder> cachedBuilders; |
| 10 | 10 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 36 | 36 |
| 37 Compiler get compiler => emitterTask.compiler; | 37 Compiler get compiler => emitterTask.compiler; |
| 38 JavaScriptBackend get backend => compiler.backend; | 38 JavaScriptBackend get backend => compiler.backend; |
| 39 | 39 |
| 40 jsAst.Expression get defPropFunction { | 40 jsAst.Expression get defPropFunction { |
| 41 Element element = backend.findHelper('defineProperty'); | 41 Element element = backend.findHelper('defineProperty'); |
| 42 return emitterTask.staticFunctionAccess(element); | 42 return emitterTask.staticFunctionAccess(element); |
| 43 } | 43 } |
| 44 | 44 |
| 45 /** | 45 /** |
| 46 * Prepares native classes for emission. Returns the reduced list of classes. | 46 * Prepares native classes for emission. Returns the unneeded classes. |
|
herhut
2015/01/26 14:58:08
Why is this better? Do you expect that this set is
floitsch
2015/01/26 17:57:50
I think it's smaller, but more importantly it's a
| |
| 47 * | 47 * |
| 48 * Removes trivial classes (that can be represented by a super type) and | 48 * Removes trivial classes (that can be represented by a super type) and |
| 49 * generates properties that have to be added to classes (native or not). | 49 * generates properties that have to be added to classes (native or not). |
| 50 * | 50 * |
| 51 * The interceptors are filtered to avoid emitting trivial interceptors. For | 51 * The interceptors are filtered to avoid emitting trivial interceptors. For |
| 52 * example, if the program contains no code that can distinguish between the | 52 * example, if the program contains no code that can distinguish between the |
| 53 * numerous subclasses of `Element` then we can pretend that `Element` is a | 53 * numerous subclasses of `Element` then we can pretend that `Element` is a |
| 54 * leaf class, and all instances of subclasses of `Element` are instances of | 54 * leaf class, and all instances of subclasses of `Element` are instances of |
| 55 * `Element`. | 55 * `Element`. |
| 56 * | 56 * |
| 57 * There is also a performance benefit (in addition to the obvious code size | 57 * There is also a performance benefit (in addition to the obvious code size |
| 58 * benefit), due to how [getNativeInterceptor] works. Finding the interceptor | 58 * benefit), due to how [getNativeInterceptor] works. Finding the interceptor |
| 59 * of a leaf class in the hierarchy is more efficient that a non-leaf, so it | 59 * of a leaf class in the hierarchy is more efficient that a non-leaf, so it |
| 60 * improves performance when more classes can be treated as leaves. | 60 * improves performance when more classes can be treated as leaves. |
| 61 * | 61 * |
| 62 * [classes] contains native classes, mixin applications, and user subclasses | 62 * [classes] contains native classes, mixin applications, and user subclasses |
| 63 * of native classes. *Only* the native classes are returned. The order of | 63 * of native classes. |
| 64 * the returned classes is unchanged. (That is, the returned output might | |
| 65 * just have classes removed). | |
| 66 * | 64 * |
| 67 * [allAdditionalProperties] is used to collect properties that are pushed up | 65 * [allAdditionalProperties] is used to collect properties that are pushed up |
| 68 * from the above optimizations onto a non-native class, e.g, `Interceptor`. | 66 * from the above optimizations onto a non-native class, e.g, `Interceptor`. |
| 69 */ | 67 */ |
| 70 List<Class> prepareNativeClasses( | 68 Set<Class> prepareNativeClasses( |
| 71 List<Class> classes, | 69 List<Class> classes, |
| 72 Map<Class, Map<String, jsAst.Expression>> allAdditionalProperties) { | 70 Map<Class, Map<String, jsAst.Expression>> allAdditionalProperties) { |
| 71 assert(classes.every((Class cls) => cls != null)); | |
|
herhut
2015/01/26 14:58:08
Why is this needed?
floitsch
2015/01/26 17:57:50
If the mapping from classElement to Class fails in
herhut
2015/01/27 09:50:29
I was just curious how this could happen.
| |
| 72 | |
| 73 hasNativeClasses = classes.isNotEmpty; | |
| 74 | |
| 73 // Compute a pre-order traversal of the subclass forest. We actually want a | 75 // Compute a pre-order traversal of the subclass forest. We actually want a |
| 74 // post-order traversal but it is easier to compute the pre-order and use it | 76 // post-order traversal but it is easier to compute the pre-order and use it |
| 75 // in reverse. | 77 // in reverse. |
| 76 | |
| 77 hasNativeClasses = classes.isNotEmpty; | |
| 78 | |
| 79 List<Class> preOrder = <Class>[]; | 78 List<Class> preOrder = <Class>[]; |
| 80 Set<Class> seen = new Set<Class>(); | 79 Set<Class> seen = new Set<Class>(); |
| 81 | 80 |
| 82 Class objectClass = null; | 81 Class objectClass = null; |
| 83 Class jsInterceptorClass = null; | 82 Class jsInterceptorClass = null; |
| 84 void walk(Class cls) { | 83 void walk(Class cls) { |
| 85 if (cls.element == compiler.objectClass) { | 84 if (cls.element == compiler.objectClass) { |
| 86 objectClass = cls; | 85 objectClass = cls; |
| 87 return; | 86 return; |
| 88 } | 87 } |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 222 } | 221 } |
| 223 } | 222 } |
| 224 } | 223 } |
| 225 | 224 |
| 226 // TODO(sra): Issue #13731- this is commented out as part of custom | 225 // TODO(sra): Issue #13731- this is commented out as part of custom |
| 227 // element constructor work. | 226 // element constructor work. |
| 228 // (floitsch: was run on every native class.) | 227 // (floitsch: was run on every native class.) |
| 229 //assert(!classElement.hasBackendMembers); | 228 //assert(!classElement.hasBackendMembers); |
| 230 | 229 |
| 231 return classes | 230 return classes |
| 232 .where((Class cls) => cls.isNative && neededClasses.contains(cls)) | 231 .where((Class cls) => cls.isNative && !neededClasses.contains(cls)) |
| 233 .toList(); | 232 .toSet(); |
| 234 } | 233 } |
| 235 | 234 |
| 236 /** | 235 /** |
| 237 * Computes the native classes that are extended (subclassed) by non-native | 236 * Computes the native classes that are extended (subclassed) by non-native |
| 238 * classes and the set non-mative classes that extend them. (A List is used | 237 * classes and the set non-mative classes that extend them. (A List is used |
| 239 * instead of a Set for out stability). | 238 * instead of a Set for out stability). |
| 240 */ | 239 */ |
| 241 Map<Class, List<Class>> computeExtensionPoints(List<Class> classes) { | 240 Map<Class, List<Class>> computeExtensionPoints(List<Class> classes) { |
| 242 Class nativeSuperclassOf(Class cls) { | 241 Class nativeSuperclassOf(Class cls) { |
| 243 if (cls == null) return null; | 242 if (cls == null) return null; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 271 } | 270 } |
| 272 | 271 |
| 273 return | 272 return |
| 274 cls.methods.isEmpty && | 273 cls.methods.isEmpty && |
| 275 cls.isChecks.isEmpty && | 274 cls.isChecks.isEmpty && |
| 276 cls.callStubs.isEmpty && | 275 cls.callStubs.isEmpty && |
| 277 !cls.superclass.isMixinApplication && | 276 !cls.superclass.isMixinApplication && |
| 278 !cls.fields.any(needsAccessor); | 277 !cls.fields.any(needsAccessor); |
| 279 } | 278 } |
| 280 | 279 |
| 281 void finishGenerateNativeClasses() { | |
| 282 // TODO(sra): Put specialized version of getNativeMethods on | |
| 283 // `Object.prototype` to avoid checking in `getInterceptor` and | |
| 284 // specializations. | |
| 285 } | |
| 286 | |
| 287 void potentiallyConvertDartClosuresToJs( | 280 void potentiallyConvertDartClosuresToJs( |
| 288 List<jsAst.Statement> statements, | 281 List<jsAst.Statement> statements, |
| 289 FunctionElement member, | 282 FunctionElement member, |
| 290 List<jsAst.Parameter> stubParameters) { | 283 List<jsAst.Parameter> stubParameters) { |
| 291 FunctionSignature parameters = member.functionSignature; | 284 FunctionSignature parameters = member.functionSignature; |
| 292 Element converter = backend.findHelper('convertDartClosureToJS'); | 285 Element converter = backend.findHelper('convertDartClosureToJS'); |
| 293 jsAst.Expression closureConverter = | 286 jsAst.Expression closureConverter = |
| 294 emitterTask.staticFunctionAccess(converter); | 287 emitterTask.staticFunctionAccess(converter); |
| 295 parameters.forEachParameter((ParameterElement parameter) { | 288 parameters.forEachParameter((ParameterElement parameter) { |
| 296 String name = parameter.name; | 289 String name = parameter.name; |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 427 targetOutput.add(';'); | 420 targetOutput.add(';'); |
| 428 } | 421 } |
| 429 targetOutput.addBuffer(jsAst.prettyPrint( | 422 targetOutput.addBuffer(jsAst.prettyPrint( |
| 430 new jsAst.ExpressionStatement(init), compiler)); | 423 new jsAst.ExpressionStatement(init), compiler)); |
| 431 targetOutput.add('\n'); | 424 targetOutput.add('\n'); |
| 432 } | 425 } |
| 433 | 426 |
| 434 targetOutput.add('\n'); | 427 targetOutput.add('\n'); |
| 435 } | 428 } |
| 436 } | 429 } |
| OLD | NEW |