Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1080)

Side by Side Diff: pkg/compiler/lib/src/js_emitter/native_emitter.dart

Issue 872403002: Don't create builders to determine if a native class is trivial or not. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_emitter/old_emitter/class_builder.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
53 * 53 *
54 * There is also a performance benefit (in addition to the obvious code size 54 * There is also a performance benefit (in addition to the obvious code size
55 * benefit), due to how [getNativeInterceptor] works. Finding the interceptor 55 * benefit), due to how [getNativeInterceptor] works. Finding the interceptor
56 * of a leaf class in the hierarchy is more efficient that a non-leaf, so it 56 * of a leaf class in the hierarchy is more efficient that a non-leaf, so it
57 * improves performance when more classes can be treated as leaves. 57 * improves performance when more classes can be treated as leaves.
58 * 58 *
59 * [classes] contains native classes, mixin applications, and user subclasses 59 * [classes] contains native classes, mixin applications, and user subclasses
60 * of native classes. ONLY the native classes are generated here. [classes] 60 * of native classes. ONLY the native classes are generated here. [classes]
61 * is sorted in desired output order. 61 * is sorted in desired output order.
62 * 62 *
63 * [additionalProperties] is used to collect properties that are pushed up 63 * [allAdditionalProperties] is used to collect properties that are pushed up
64 * from the above optimizations onto a non-native class, e.g, `Interceptor`. 64 * from the above optimizations onto a non-native class, e.g, `Interceptor`.
65 */ 65 */
66 void generateNativeClasses( 66 void generateNativeClasses(
67 List<Class> classes, 67 List<Class> classes,
68 Map<ClassElement, Map<String, jsAst.Expression>> additionalProperties) { 68 Map<Class, Map<String, jsAst.Expression>> allAdditionalProperties) {
69 // Compute a pre-order traversal of the subclass forest. We actually want a 69 // Compute a pre-order traversal of the subclass forest. We actually want a
70 // post-order traversal but it is easier to compute the pre-order and use it 70 // post-order traversal but it is easier to compute the pre-order and use it
71 // in reverse. 71 // in reverse.
72 72
73 if (classes.isNotEmpty) {
74 hasNativeClasses = true;
75 }
76
73 List<Class> preOrder = <Class>[]; 77 List<Class> preOrder = <Class>[];
74 Set<Class> seen = new Set<Class>(); 78 Set<Class> seen = new Set<Class>();
75 79
76 Class objectClass = null; 80 Class objectClass = null;
77 Class jsInterceptorClass = null; 81 Class jsInterceptorClass = null;
78 void walk(Class cls) { 82 void walk(Class cls) {
79 if (cls.element == compiler.objectClass) { 83 if (cls.element == compiler.objectClass) {
80 objectClass = cls; 84 objectClass = cls;
81 return; 85 return;
82 } 86 }
83 if (cls.element == backend.jsInterceptorClass) { 87 if (cls.element == backend.jsInterceptorClass) {
84 jsInterceptorClass = cls; 88 jsInterceptorClass = cls;
85 return; 89 return;
86 } 90 }
87 if (seen.contains(cls)) return; 91 if (seen.contains(cls)) return;
88 seen.add(cls); 92 seen.add(cls);
89 walk(cls.superclass); 93 walk(cls.superclass);
90 preOrder.add(cls); 94 preOrder.add(cls);
91 } 95 }
92 classes.forEach(walk); 96 classes.forEach(walk);
93 97
94 // Generate code for each native class into [ClassBuilder]s.
95
96 Map<Class, ClassBuilder> builders = new Map<Class, ClassBuilder>();
97 for (Class cls in classes) {
98 if (cls.isNative) {
99 ClassBuilder builder = createBuilderAndSetIsTrivial(cls);
100 builders[cls] = builder;
101 }
102 }
103
104 // Find which classes are needed and which are non-leaf classes. Any class 98 // Find which classes are needed and which are non-leaf classes. Any class
105 // that is not needed can be treated as a leaf class equivalent to some 99 // that is not needed can be treated as a leaf class equivalent to some
106 // needed class. 100 // needed class.
107 101
108 Set<Class> neededClasses = new Set<Class>(); 102 Set<Class> neededClasses = new Set<Class>();
109 Set<Class> nonleafClasses = new Set<Class>(); 103 Set<Class> nonleafClasses = new Set<Class>();
110 104
111 Map<Class, List<Class>> extensionPoints = computeExtensionPoints(preOrder); 105 Map<Class, List<Class>> extensionPoints = computeExtensionPoints(preOrder);
112 106
113 neededClasses.add(objectClass); 107 neededClasses.add(objectClass);
114 108
115 Set<ClassElement> neededByConstant = emitterTask 109 Set<ClassElement> neededByConstant = emitterTask
116 .computeInterceptorsReferencedFromConstants(); 110 .computeInterceptorsReferencedFromConstants();
117 Set<ClassElement> modifiedClasses = emitterTask.typeTestRegistry 111 Set<ClassElement> modifiedClasses = emitterTask.typeTestRegistry
118 .computeClassesModifiedByEmitRuntimeTypeSupport(); 112 .computeClassesModifiedByEmitRuntimeTypeSupport();
119 113
120 for (Class cls in preOrder.reversed) { 114 for (Class cls in preOrder.reversed) {
121 ClassElement classElement = cls.element; 115 ClassElement classElement = cls.element;
122 // Post-order traversal ensures we visit the subclasses before their 116 // Post-order traversal ensures we visit the subclasses before their
123 // superclass. This makes it easy to tell if a class is needed because a 117 // superclass. This makes it easy to tell if a class is needed because a
124 // subclass is needed. 118 // subclass is needed.
125 ClassBuilder builder = builders[cls];
126 bool needed = false; 119 bool needed = false;
127 if (builder == null) { 120 if (!cls.isNative) {
128 assert(!cls.isNative);
129 // Mixin applications (native+mixin) are non-native, so [classElement] 121 // Mixin applications (native+mixin) are non-native, so [classElement]
130 // has already been emitted as a regular class. Mark [classElement] as 122 // has already been emitted as a regular class. Mark [classElement] as
131 // 'needed' to ensure the native superclass is needed. 123 // 'needed' to ensure the native superclass is needed.
132 needed = true; 124 needed = true;
133 } else if (!builder.isTrivial) { 125 } else if (!isTrivialClass(cls)) {
134 needed = true; 126 needed = true;
135 } else if (neededByConstant.contains(classElement)) { 127 } else if (neededByConstant.contains(classElement)) {
136 needed = true; 128 needed = true;
137 } else if (modifiedClasses.contains(classElement)) { 129 } else if (modifiedClasses.contains(classElement)) {
138 // TODO(9556): Remove this test when [emitRuntimeTypeSupport] no longer 130 // TODO(9556): Remove this test when [emitRuntimeTypeSupport] no longer
139 // adds information to a class prototype or constructor. 131 // adds information to a class prototype or constructor.
140 needed = true; 132 needed = true;
141 } else if (extensionPoints.containsKey(cls)) { 133 } else if (extensionPoints.containsKey(cls)) {
142 needed = true; 134 needed = true;
143 } 135 }
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
207 StringBuffer sb = new StringBuffer(leafStr); 199 StringBuffer sb = new StringBuffer(leafStr);
208 if (nonleafStr != '') { 200 if (nonleafStr != '') {
209 sb..write(';')..write(nonleafStr); 201 sb..write(';')..write(nonleafStr);
210 } 202 }
211 if (extensions != null) { 203 if (extensions != null) {
212 sb..write(';') 204 sb..write(';')
213 ..writeAll(extensions.map((Class cls) => cls.name), '|'); 205 ..writeAll(extensions.map((Class cls) => cls.name), '|');
214 } 206 }
215 String encoding = sb.toString(); 207 String encoding = sb.toString();
216 208
217 ClassBuilder builder = builders[cls]; 209 if (cls.isNative || encoding != '') {
218 if (builder == null) { 210 Map<String, jsAst.Expression> properties =
219 // No builder because this is an intermediate mixin application or 211 allAdditionalProperties.putIfAbsent(cls,
220 // Interceptor - these are not direct native classes. 212 () => new Map<String, jsAst.Expression>());
221 if (encoding != '') { 213 properties[backend.namer.nativeSpecProperty] = js.string(encoding);
222 Map<String, jsAst.Expression> properties =
223 additionalProperties.putIfAbsent(cls.element,
224 () => new Map<String, jsAst.Expression>());
225 properties[backend.namer.nativeSpecProperty] = js.string(encoding);
226 }
227 } else {
228 builder.addProperty(
229 backend.namer.nativeSpecProperty, js.string(encoding));
230 } 214 }
231 } 215 }
232 generateClassInfo(jsInterceptorClass); 216 generateClassInfo(jsInterceptorClass);
233 for (Class cls in classes) { 217 for (Class cls in classes) {
234 if (!cls.isNative || neededClasses.contains(cls)) { 218 if (!cls.isNative || neededClasses.contains(cls)) {
235 generateClassInfo(cls); 219 generateClassInfo(cls);
236 } 220 }
237 } 221 }
238 } 222 }
239 223
240 // Emit the native class interceptors that were actually used. 224 // Emit the native class interceptors that were actually used.
241 for (Class cls in classes) { 225 for (Class cls in classes) {
242 assert(!cls.onlyForRti); 226 assert(!cls.onlyForRti);
243 ClassElement classElement = cls.element; 227 ClassElement classElement = cls.element;
244 if (!cls.isNative) continue; 228 if (!cls.isNative) continue;
245 if (neededClasses.contains(cls)) { 229 if (neededClasses.contains(cls)) {
246 ClassBuilder builder = builders[cls]; 230 // TODO(sra): Issue #13731- this is commented out as part of custom
247 assert(builder != null); 231 // element constructor work.
232 //assert(!classElement.hasBackendMembers);
248 233
249 emitterTask.oldEmitter.classEmitter.emitConstructorsForCSP(cls); 234 ClassBuilder enclosingBuilder =
250 emitterTask.oldEmitter.classEmitter.emitFields( 235 emitterTask.oldEmitter.getElementDescriptor(classElement);
251 cls, builder, classIsNative: true); 236 emitterTask.oldEmitter.emitClass(cls, enclosingBuilder);
252 emitterTask.oldEmitter.classEmitter.emitCheckedClassSetters(
253 cls, builder);
254 emitterTask.oldEmitter.classEmitter.emitClassGettersSettersForCSP(
255 cls, builder);
256 emitterTask.oldEmitter.classEmitter.emitInstanceMembers(
257 cls, builder);
258 emitterTask.oldEmitter.classEmitter.emitCallStubs(cls, builder);
259 emitterTask.oldEmitter.classEmitter
260 .emitRuntimeTypeInformation(cls, builder);
261
262 // Define interceptor class for [classElement].
263 emitterTask.oldEmitter.classEmitter.emitClassBuilderWithReflectionData(
264 cls,
265 builders[cls],
266 emitterTask.oldEmitter.getElementDescriptor(classElement));
267 emitterTask.oldEmitter.needsClassSupport = true;
268 } 237 }
269 } 238 }
270 } 239 }
271 240
272 /** 241 /**
273 * Computes the native classes that are extended (subclassed) by non-native 242 * Computes the native classes that are extended (subclassed) by non-native
274 * classes and the set non-mative classes that extend them. (A List is used 243 * classes and the set non-mative classes that extend them. (A List is used
275 * instead of a Set for out stability). 244 * instead of a Set for out stability).
276 */ 245 */
277 Map<Class, List<Class>> computeExtensionPoints(List<Class> classes) { 246 Map<Class, List<Class>> computeExtensionPoints(List<Class> classes) {
(...skipping 14 matching lines...) Expand all
292 Class nativeAncestor = nativeAncestorOf(cls); 261 Class nativeAncestor = nativeAncestorOf(cls);
293 if (nativeAncestor != null) { 262 if (nativeAncestor != null) {
294 map 263 map
295 .putIfAbsent(nativeAncestor, () => <Class>[]) 264 .putIfAbsent(nativeAncestor, () => <Class>[])
296 .add(cls); 265 .add(cls);
297 } 266 }
298 } 267 }
299 return map; 268 return map;
300 } 269 }
301 270
302 ClassBuilder createBuilderAndSetIsTrivial(Class cls) { 271 bool isTrivialClass(Class cls) {
303 ClassElement classElement = cls.element;
304
305 // TODO(sra): Issue #13731- this is commented out as part of custom element
306 // constructor work.
307 //assert(!classElement.hasBackendMembers);
308 hasNativeClasses = true;
309
310 Class superclass = cls.superclass;
311 assert(superclass != null);
312 assert(superclass.element != compiler.objectClass);
313
314 ClassBuilder builder;
315 if (compiler.hasIncrementalSupport) {
316 builder = cachedBuilders[classElement];
317 if (builder != null) return builder;
318 builder = new ClassBuilder(classElement, backend.namer);
319 cachedBuilders[classElement] = builder;
320 } else {
321 builder = new ClassBuilder(classElement, backend.namer);
322 }
323 builder.superName = superclass.name;
324
325 bool needsAccessor(Field field) { 272 bool needsAccessor(Field field) {
326 return field.needsGetter || 273 return field.needsGetter ||
327 field.needsUncheckedSetter || 274 field.needsUncheckedSetter ||
328 field.needsCheckedSetter; 275 field.needsCheckedSetter;
329 } 276 }
330 277
331 builder.isTrivial = 278 return
332 cls.methods.isEmpty && 279 cls.methods.isEmpty &&
333 cls.isChecks.isEmpty && 280 cls.isChecks.isEmpty &&
334 cls.callStubs.isEmpty && 281 cls.callStubs.isEmpty &&
335 !superclass.isMixinApplication && 282 !cls.superclass.isMixinApplication &&
336 !cls.fields.any(needsAccessor); 283 !cls.fields.any(needsAccessor);
337
338 return builder;
339 } 284 }
340 285
341 void finishGenerateNativeClasses() { 286 void finishGenerateNativeClasses() {
342 // TODO(sra): Put specialized version of getNativeMethods on 287 // TODO(sra): Put specialized version of getNativeMethods on
343 // `Object.prototype` to avoid checking in `getInterceptor` and 288 // `Object.prototype` to avoid checking in `getInterceptor` and
344 // specializations. 289 // specializations.
345 } 290 }
346 291
347 void potentiallyConvertDartClosuresToJs( 292 void potentiallyConvertDartClosuresToJs(
348 List<jsAst.Statement> statements, 293 List<jsAst.Statement> statements,
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
487 targetOutput.add(';'); 432 targetOutput.add(';');
488 } 433 }
489 targetOutput.addBuffer(jsAst.prettyPrint( 434 targetOutput.addBuffer(jsAst.prettyPrint(
490 new jsAst.ExpressionStatement(init), compiler)); 435 new jsAst.ExpressionStatement(init), compiler));
491 targetOutput.add('\n'); 436 targetOutput.add('\n');
492 } 437 }
493 438
494 targetOutput.add('\n'); 439 targetOutput.add('\n');
495 } 440 }
496 } 441 }
OLDNEW
« no previous file with comments | « no previous file | pkg/compiler/lib/src/js_emitter/old_emitter/class_builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698