| 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 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 walk(cls.superclass); | 89 walk(cls.superclass); |
| 90 preOrder.add(cls); | 90 preOrder.add(cls); |
| 91 } | 91 } |
| 92 classes.forEach(walk); | 92 classes.forEach(walk); |
| 93 | 93 |
| 94 // Generate code for each native class into [ClassBuilder]s. | 94 // Generate code for each native class into [ClassBuilder]s. |
| 95 | 95 |
| 96 Map<Class, ClassBuilder> builders = new Map<Class, ClassBuilder>(); | 96 Map<Class, ClassBuilder> builders = new Map<Class, ClassBuilder>(); |
| 97 for (Class cls in classes) { | 97 for (Class cls in classes) { |
| 98 if (cls.isNative) { | 98 if (cls.isNative) { |
| 99 ClassBuilder builder = generateNativeClass(cls); | 99 ClassBuilder builder = createBuilderAndSetIsTrivial(cls); |
| 100 builders[cls] = builder; | 100 builders[cls] = builder; |
| 101 } | 101 } |
| 102 } | 102 } |
| 103 | 103 |
| 104 // Find which classes are needed and which are non-leaf classes. Any class | 104 // 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 | 105 // that is not needed can be treated as a leaf class equivalent to some |
| 106 // needed class. | 106 // needed class. |
| 107 | 107 |
| 108 Set<Class> neededClasses = new Set<Class>(); | 108 Set<Class> neededClasses = new Set<Class>(); |
| 109 Set<Class> nonleafClasses = new Set<Class>(); | 109 Set<Class> nonleafClasses = new Set<Class>(); |
| (...skipping 127 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 237 } | 237 } |
| 238 } | 238 } |
| 239 | 239 |
| 240 // Emit the native class interceptors that were actually used. | 240 // Emit the native class interceptors that were actually used. |
| 241 for (Class cls in classes) { | 241 for (Class cls in classes) { |
| 242 assert(!cls.onlyForRti); | 242 assert(!cls.onlyForRti); |
| 243 ClassElement classElement = cls.element; | 243 ClassElement classElement = cls.element; |
| 244 if (!cls.isNative) continue; | 244 if (!cls.isNative) continue; |
| 245 if (neededClasses.contains(cls)) { | 245 if (neededClasses.contains(cls)) { |
| 246 ClassBuilder builder = builders[cls]; | 246 ClassBuilder builder = builders[cls]; |
| 247 | 247 assert(builder != null); |
| 248 // In CSP mode [emitClassConstructor] and [emitClassGettersSetters] have | |
| 249 // a side-effect on "precompiled" functions in [OldEmitter]. For this | |
| 250 // reason, it is important that we don't call these methods before we | |
| 251 // are certain that a class is needed. | |
| 252 | 248 |
| 253 emitterTask.oldEmitter.classEmitter.emitConstructorsForCSP(cls); | 249 emitterTask.oldEmitter.classEmitter.emitConstructorsForCSP(cls); |
| 254 | 250 emitterTask.oldEmitter.classEmitter.emitFields( |
| 255 // [emitClassGettersSettersForCSP] does not affect whether or not a | 251 cls, builder, classIsNative: true); |
| 256 // class is needed. If getters/setters are emitted, the class has fields | 252 emitterTask.oldEmitter.classEmitter.emitCheckedClassSetters( |
| 257 // and is therefore non-trivial. | 253 cls, builder); |
| 258 emitterTask.oldEmitter.classEmitter.emitClassGettersSettersForCSP( | 254 emitterTask.oldEmitter.classEmitter.emitClassGettersSettersForCSP( |
| 259 cls, builder); | 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); |
| 260 | 261 |
| 261 // Define interceptor class for [classElement]. | 262 // Define interceptor class for [classElement]. |
| 262 emitterTask.oldEmitter.classEmitter.emitClassBuilderWithReflectionData( | 263 emitterTask.oldEmitter.classEmitter.emitClassBuilderWithReflectionData( |
| 263 cls, | 264 cls, |
| 264 builders[cls], | 265 builders[cls], |
| 265 emitterTask.oldEmitter.getElementDescriptor(classElement)); | 266 emitterTask.oldEmitter.getElementDescriptor(classElement)); |
| 266 emitterTask.oldEmitter.needsClassSupport = true; | 267 emitterTask.oldEmitter.needsClassSupport = true; |
| 267 } | 268 } |
| 268 } | 269 } |
| 269 } | 270 } |
| (...skipping 21 matching lines...) Expand all Loading... |
| 291 Class nativeAncestor = nativeAncestorOf(cls); | 292 Class nativeAncestor = nativeAncestorOf(cls); |
| 292 if (nativeAncestor != null) { | 293 if (nativeAncestor != null) { |
| 293 map | 294 map |
| 294 .putIfAbsent(nativeAncestor, () => <Class>[]) | 295 .putIfAbsent(nativeAncestor, () => <Class>[]) |
| 295 .add(cls); | 296 .add(cls); |
| 296 } | 297 } |
| 297 } | 298 } |
| 298 return map; | 299 return map; |
| 299 } | 300 } |
| 300 | 301 |
| 301 ClassBuilder generateNativeClass(Class cls) { | 302 ClassBuilder createBuilderAndSetIsTrivial(Class cls) { |
| 302 ClassElement classElement = cls.element; | 303 ClassElement classElement = cls.element; |
| 303 | 304 |
| 304 // TODO(sra): Issue #13731- this is commented out as part of custom element | 305 // TODO(sra): Issue #13731- this is commented out as part of custom element |
| 305 // constructor work. | 306 // constructor work. |
| 306 //assert(!classElement.hasBackendMembers); | 307 //assert(!classElement.hasBackendMembers); |
| 307 hasNativeClasses = true; | 308 hasNativeClasses = true; |
| 308 | 309 |
| 309 Class superclass = cls.superclass; | 310 Class superclass = cls.superclass; |
| 310 assert(superclass != null); | 311 assert(superclass != null); |
| 311 assert(superclass.element != compiler.objectClass); | 312 assert(superclass.element != compiler.objectClass); |
| 312 | 313 |
| 313 ClassBuilder builder; | 314 ClassBuilder builder; |
| 314 if (compiler.hasIncrementalSupport) { | 315 if (compiler.hasIncrementalSupport) { |
| 315 builder = cachedBuilders[classElement]; | 316 builder = cachedBuilders[classElement]; |
| 316 if (builder != null) return builder; | 317 if (builder != null) return builder; |
| 317 builder = new ClassBuilder(classElement, backend.namer); | 318 builder = new ClassBuilder(classElement, backend.namer); |
| 318 cachedBuilders[classElement] = builder; | 319 cachedBuilders[classElement] = builder; |
| 319 } else { | 320 } else { |
| 320 builder = new ClassBuilder(classElement, backend.namer); | 321 builder = new ClassBuilder(classElement, backend.namer); |
| 321 } | 322 } |
| 322 builder.superName = superclass.name; | 323 builder.superName = superclass.name; |
| 323 | 324 |
| 324 bool hasFields = emitterTask.oldEmitter.classEmitter.emitFields( | 325 bool needsAccessor(Field field) { |
| 325 cls, builder, classIsNative: true); | 326 return field.needsGetter || |
| 326 int propertyCount = builder.properties.length; | 327 field.needsUncheckedSetter || |
| 327 emitterTask.oldEmitter.classEmitter.emitCheckedClassSetters(cls, builder); | 328 field.needsCheckedSetter; |
| 328 emitterTask.oldEmitter.classEmitter.emitInstanceMembers( | 329 } |
| 329 classElement, builder); | |
| 330 emitterTask.oldEmitter.classEmitter.emitCallStubs(cls, builder); | |
| 331 emitterTask.oldEmitter.classEmitter | |
| 332 .emitRuntimeTypeInformation(cls, builder); | |
| 333 | 330 |
| 334 if (!hasFields && | 331 builder.isTrivial = |
| 335 builder.properties.length == propertyCount && | 332 cls.methods.isEmpty && |
| 336 superclass is! MixinApplicationElement) { | 333 cls.isChecks.isEmpty && |
| 337 builder.isTrivial = true; | 334 cls.callStubs.isEmpty && |
| 338 } | 335 superclass is! MixinApplicationElement && |
| 336 !cls.fields.any(needsAccessor); |
| 339 | 337 |
| 340 return builder; | 338 return builder; |
| 341 } | 339 } |
| 342 | 340 |
| 343 void finishGenerateNativeClasses() { | 341 void finishGenerateNativeClasses() { |
| 344 // TODO(sra): Put specialized version of getNativeMethods on | 342 // TODO(sra): Put specialized version of getNativeMethods on |
| 345 // `Object.prototype` to avoid checking in `getInterceptor` and | 343 // `Object.prototype` to avoid checking in `getInterceptor` and |
| 346 // specializations. | 344 // specializations. |
| 347 } | 345 } |
| 348 | 346 |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 489 targetOutput.add(';'); | 487 targetOutput.add(';'); |
| 490 } | 488 } |
| 491 targetOutput.addBuffer(jsAst.prettyPrint( | 489 targetOutput.addBuffer(jsAst.prettyPrint( |
| 492 new jsAst.ExpressionStatement(init), compiler)); | 490 new jsAst.ExpressionStatement(init), compiler)); |
| 493 targetOutput.add('\n'); | 491 targetOutput.add('\n'); |
| 494 } | 492 } |
| 495 | 493 |
| 496 targetOutput.add('\n'); | 494 targetOutput.add('\n'); |
| 497 } | 495 } |
| 498 } | 496 } |
| OLD | NEW |