| 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 30 matching lines...) Expand all Loading... |
| 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 unneeded classes. | 46 * Prepares native classes for emission. Returns the unneeded classes. |
| 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 * Updates the `nativeInfo` field of the given classes. This data |
| 52 * must be emitted with the corresponding classes. |
| 53 * |
| 51 * The interceptors are filtered to avoid emitting trivial interceptors. For | 54 * The interceptors are filtered to avoid emitting trivial interceptors. For |
| 52 * example, if the program contains no code that can distinguish between the | 55 * 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 | 56 * 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 | 57 * leaf class, and all instances of subclasses of `Element` are instances of |
| 55 * `Element`. | 58 * `Element`. |
| 56 * | 59 * |
| 57 * There is also a performance benefit (in addition to the obvious code size | 60 * There is also a performance benefit (in addition to the obvious code size |
| 58 * benefit), due to how [getNativeInterceptor] works. Finding the interceptor | 61 * 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 | 62 * 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. | 63 * improves performance when more classes can be treated as leaves. |
| 61 * | 64 * |
| 62 * [classes] contains native classes, mixin applications, and user subclasses | 65 * [classes] contains native classes, mixin applications, and user subclasses |
| 63 * of native classes. | 66 * of native classes. |
| 64 * | |
| 65 * [allAdditionalProperties] is used to collect properties that are pushed up | |
| 66 * from the above optimizations onto a non-native class, e.g, `Interceptor`. | |
| 67 */ | 67 */ |
| 68 Set<Class> prepareNativeClasses( | 68 Set<Class> prepareNativeClasses(List<Class> classes) { |
| 69 List<Class> classes, | |
| 70 Map<Class, Map<String, jsAst.Expression>> allAdditionalProperties) { | |
| 71 assert(classes.every((Class cls) => cls != null)); | 69 assert(classes.every((Class cls) => cls != null)); |
| 72 | 70 |
| 73 hasNativeClasses = classes.isNotEmpty; | 71 hasNativeClasses = classes.isNotEmpty; |
| 74 | 72 |
| 75 // Compute a pre-order traversal of the subclass forest. We actually want a | 73 // Compute a pre-order traversal of the subclass forest. We actually want a |
| 76 // post-order traversal but it is easier to compute the pre-order and use it | 74 // post-order traversal but it is easier to compute the pre-order and use it |
| 77 // in reverse. | 75 // in reverse. |
| 78 List<Class> preOrder = <Class>[]; | 76 List<Class> preOrder = <Class>[]; |
| 79 Set<Class> seen = new Set<Class>(); | 77 Set<Class> seen = new Set<Class>(); |
| 80 | 78 |
| (...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 201 if (nonleafStr != '') { | 199 if (nonleafStr != '') { |
| 202 sb..write(';')..write(nonleafStr); | 200 sb..write(';')..write(nonleafStr); |
| 203 } | 201 } |
| 204 if (extensions != null) { | 202 if (extensions != null) { |
| 205 sb..write(';') | 203 sb..write(';') |
| 206 ..writeAll(extensions.map((Class cls) => cls.name), '|'); | 204 ..writeAll(extensions.map((Class cls) => cls.name), '|'); |
| 207 } | 205 } |
| 208 String encoding = sb.toString(); | 206 String encoding = sb.toString(); |
| 209 | 207 |
| 210 if (cls.isNative || encoding != '') { | 208 if (cls.isNative || encoding != '') { |
| 211 Map<String, jsAst.Expression> properties = | 209 assert(cls.nativeInfo == null); |
| 212 allAdditionalProperties.putIfAbsent(cls, | 210 cls.nativeInfo = encoding; |
| 213 () => new Map<String, jsAst.Expression>()); | |
| 214 properties[backend.namer.nativeSpecProperty] = js.string(encoding); | |
| 215 } | 211 } |
| 216 } | 212 } |
| 217 generateClassInfo(jsInterceptorClass); | 213 generateClassInfo(jsInterceptorClass); |
| 218 for (Class cls in classes) { | 214 for (Class cls in classes) { |
| 219 if (!cls.isNative || neededClasses.contains(cls)) { | 215 if (!cls.isNative || neededClasses.contains(cls)) { |
| 220 generateClassInfo(cls); | 216 generateClassInfo(cls); |
| 221 } | 217 } |
| 222 } | 218 } |
| 223 } | 219 } |
| 224 | 220 |
| (...skipping 195 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 420 targetOutput.add(';'); | 416 targetOutput.add(';'); |
| 421 } | 417 } |
| 422 targetOutput.addBuffer(jsAst.prettyPrint( | 418 targetOutput.addBuffer(jsAst.prettyPrint( |
| 423 new jsAst.ExpressionStatement(init), compiler)); | 419 new jsAst.ExpressionStatement(init), compiler)); |
| 424 targetOutput.add('\n'); | 420 targetOutput.add('\n'); |
| 425 } | 421 } |
| 426 | 422 |
| 427 targetOutput.add('\n'); | 423 targetOutput.add('\n'); |
| 428 } | 424 } |
| 429 } | 425 } |
| OLD | NEW |