| OLD | NEW |
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 import 'dart:collection' show Queue; | 5 import 'dart:collection' show Queue; |
| 6 | 6 |
| 7 import '../common.dart'; | 7 import '../common.dart'; |
| 8 import '../common/backend_api.dart' show ForeignResolver; | 8 import '../common/backend_api.dart' show ForeignResolver; |
| 9 import '../common/resolution.dart' show Resolution; | 9 import '../common/resolution.dart' show Resolution; |
| 10 import '../compiler.dart' show Compiler; | 10 import '../compiler.dart' show Compiler; |
| (...skipping 11 matching lines...) Expand all Loading... |
| 22 import '../universe/use.dart' show StaticUse, TypeUse; | 22 import '../universe/use.dart' show StaticUse, TypeUse; |
| 23 import '../universe/world_impact.dart' | 23 import '../universe/world_impact.dart' |
| 24 show WorldImpact, WorldImpactBuilder, WorldImpactBuilderImpl; | 24 show WorldImpact, WorldImpactBuilder, WorldImpactBuilderImpl; |
| 25 import 'behavior.dart'; | 25 import 'behavior.dart'; |
| 26 | 26 |
| 27 /** | 27 /** |
| 28 * This could be an abstract class but we use it as a stub for the dart_backend. | 28 * This could be an abstract class but we use it as a stub for the dart_backend. |
| 29 */ | 29 */ |
| 30 class NativeEnqueuer { | 30 class NativeEnqueuer { |
| 31 /// Called when a [type] has been instantiated natively. | 31 /// Called when a [type] has been instantiated natively. |
| 32 void onInstantiatedType(InterfaceType type) {} | 32 void onInstantiatedType(ResolutionInterfaceType type) {} |
| 33 | 33 |
| 34 /// Initial entry point to native enqueuer. | 34 /// Initial entry point to native enqueuer. |
| 35 WorldImpact processNativeClasses(Iterable<LibraryElement> libraries) => | 35 WorldImpact processNativeClasses(Iterable<LibraryElement> libraries) => |
| 36 const WorldImpact(); | 36 const WorldImpact(); |
| 37 | 37 |
| 38 /// Registers the [nativeBehavior]. Adds the liveness of its instantiated | 38 /// Registers the [nativeBehavior]. Adds the liveness of its instantiated |
| 39 /// types to the world. | 39 /// types to the world. |
| 40 void registerNativeBehavior( | 40 void registerNativeBehavior( |
| 41 WorldImpactBuilder impactBuilder, NativeBehavior nativeBehavior, cause) {} | 41 WorldImpactBuilder impactBuilder, NativeBehavior nativeBehavior, cause) {} |
| 42 | 42 |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 92 : this.compiler = compiler, | 92 : this.compiler = compiler, |
| 93 processedLibraries = compiler.cacheStrategy.newSet(); | 93 processedLibraries = compiler.cacheStrategy.newSet(); |
| 94 | 94 |
| 95 JavaScriptBackend get backend => compiler.backend; | 95 JavaScriptBackend get backend => compiler.backend; |
| 96 BackendHelpers get helpers => backend.helpers; | 96 BackendHelpers get helpers => backend.helpers; |
| 97 Resolution get resolution => compiler.resolution; | 97 Resolution get resolution => compiler.resolution; |
| 98 | 98 |
| 99 DiagnosticReporter get reporter => compiler.reporter; | 99 DiagnosticReporter get reporter => compiler.reporter; |
| 100 CommonElements get commonElements => compiler.commonElements; | 100 CommonElements get commonElements => compiler.commonElements; |
| 101 | 101 |
| 102 void onInstantiatedType(InterfaceType type) { | 102 void onInstantiatedType(ResolutionInterfaceType type) { |
| 103 if (_unusedClasses.remove(type.element)) { | 103 if (_unusedClasses.remove(type.element)) { |
| 104 _registeredClasses.add(type.element); | 104 _registeredClasses.add(type.element); |
| 105 } | 105 } |
| 106 } | 106 } |
| 107 | 107 |
| 108 WorldImpact processNativeClasses(Iterable<LibraryElement> libraries) { | 108 WorldImpact processNativeClasses(Iterable<LibraryElement> libraries) { |
| 109 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); | 109 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); |
| 110 _processNativeClasses(impactBuilder, libraries); | 110 _processNativeClasses(impactBuilder, libraries); |
| 111 return impactBuilder; | 111 return impactBuilder; |
| 112 } | 112 } |
| (...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 415 }); | 415 }); |
| 416 } | 416 } |
| 417 | 417 |
| 418 void registerNativeBehavior( | 418 void registerNativeBehavior( |
| 419 WorldImpactBuilder impactBuilder, NativeBehavior nativeBehavior, cause) { | 419 WorldImpactBuilder impactBuilder, NativeBehavior nativeBehavior, cause) { |
| 420 _processNativeBehavior(impactBuilder, nativeBehavior, cause); | 420 _processNativeBehavior(impactBuilder, nativeBehavior, cause); |
| 421 } | 421 } |
| 422 | 422 |
| 423 void _processNativeBehavior( | 423 void _processNativeBehavior( |
| 424 WorldImpactBuilder impactBuilder, NativeBehavior behavior, cause) { | 424 WorldImpactBuilder impactBuilder, NativeBehavior behavior, cause) { |
| 425 void registerInstantiation(InterfaceType type) { | 425 void registerInstantiation(ResolutionInterfaceType type) { |
| 426 impactBuilder.registerTypeUse(new TypeUse.nativeInstantiation(type)); | 426 impactBuilder.registerTypeUse(new TypeUse.nativeInstantiation(type)); |
| 427 } | 427 } |
| 428 | 428 |
| 429 int unusedBefore = _unusedClasses.length; | 429 int unusedBefore = _unusedClasses.length; |
| 430 Set<ClassElement> matchingClasses = new Set<ClassElement>(); | 430 Set<ClassElement> matchingClasses = new Set<ClassElement>(); |
| 431 for (var type in behavior.typesInstantiated) { | 431 for (var type in behavior.typesInstantiated) { |
| 432 if (type is SpecialType) { | 432 if (type is SpecialType) { |
| 433 if (type == SpecialType.JsObject) { | 433 if (type == SpecialType.JsObject) { |
| 434 registerInstantiation(compiler.commonElements.objectType); | 434 registerInstantiation(compiler.commonElements.objectType); |
| 435 } | 435 } |
| 436 continue; | 436 continue; |
| 437 } | 437 } |
| 438 if (type is InterfaceType) { | 438 if (type is ResolutionInterfaceType) { |
| 439 if (type == commonElements.intType) { | 439 if (type == commonElements.intType) { |
| 440 registerInstantiation(type); | 440 registerInstantiation(type); |
| 441 } else if (type == commonElements.doubleType) { | 441 } else if (type == commonElements.doubleType) { |
| 442 registerInstantiation(type); | 442 registerInstantiation(type); |
| 443 } else if (type == commonElements.numType) { | 443 } else if (type == commonElements.numType) { |
| 444 registerInstantiation(commonElements.doubleType); | 444 registerInstantiation(commonElements.doubleType); |
| 445 registerInstantiation(commonElements.intType); | 445 registerInstantiation(commonElements.intType); |
| 446 } else if (type == commonElements.stringType) { | 446 } else if (type == commonElements.stringType) { |
| 447 registerInstantiation(type); | 447 registerInstantiation(type); |
| 448 } else if (type == commonElements.nullType) { | 448 } else if (type == commonElements.nullType) { |
| 449 registerInstantiation(type); | 449 registerInstantiation(type); |
| 450 } else if (type == commonElements.boolType) { | 450 } else if (type == commonElements.boolType) { |
| 451 registerInstantiation(type); | 451 registerInstantiation(type); |
| 452 } else if (compiler.types.isSubtype( | 452 } else if (compiler.types.isSubtype( |
| 453 type, backend.backendClasses.listImplementation.rawType)) { | 453 type, backend.backendClasses.listImplementation.rawType)) { |
| 454 registerInstantiation(type); | 454 registerInstantiation(type); |
| 455 } | 455 } |
| 456 // TODO(johnniwinther): Improve spec string precision to handle type | 456 // TODO(johnniwinther): Improve spec string precision to handle type |
| 457 // arguments and implements relations that preserve generics. Currently | 457 // arguments and implements relations that preserve generics. Currently |
| 458 // we cannot distinguish between `List`, `List<dynamic>`, and | 458 // we cannot distinguish between `List`, `List<dynamic>`, and |
| 459 // `List<int>` and take all to mean `List<E>`; in effect not including | 459 // `List<int>` and take all to mean `List<E>`; in effect not including |
| 460 // any native subclasses of generic classes. | 460 // any native subclasses of generic classes. |
| 461 // TODO(johnniwinther,sra): Find and replace uses of `List` with the | 461 // TODO(johnniwinther,sra): Find and replace uses of `List` with the |
| 462 // actual implementation classes such as `JSArray` et al. | 462 // actual implementation classes such as `JSArray` et al. |
| 463 matchingClasses | 463 matchingClasses |
| 464 .addAll(_findUnusedClassesMatching((ClassElement nativeClass) { | 464 .addAll(_findUnusedClassesMatching((ClassElement nativeClass) { |
| 465 InterfaceType nativeType = nativeClass.thisType; | 465 ResolutionInterfaceType nativeType = nativeClass.thisType; |
| 466 InterfaceType specType = type.element.thisType; | 466 ResolutionInterfaceType specType = type.element.thisType; |
| 467 return compiler.types.isSubtype(nativeType, specType); | 467 return compiler.types.isSubtype(nativeType, specType); |
| 468 })); | 468 })); |
| 469 } else if (type.isDynamic) { | 469 } else if (type.isDynamic) { |
| 470 matchingClasses.addAll(_unusedClasses); | 470 matchingClasses.addAll(_unusedClasses); |
| 471 } else { | 471 } else { |
| 472 assert(type is VoidType); | 472 assert(type is ResolutionVoidType); |
| 473 } | 473 } |
| 474 } | 474 } |
| 475 if (matchingClasses.isNotEmpty && _registeredClasses.isEmpty) { | 475 if (matchingClasses.isNotEmpty && _registeredClasses.isEmpty) { |
| 476 matchingClasses.addAll(_onFirstNativeClass(impactBuilder)); | 476 matchingClasses.addAll(_onFirstNativeClass(impactBuilder)); |
| 477 } | 477 } |
| 478 _registerTypeUses(impactBuilder, matchingClasses, cause); | 478 _registerTypeUses(impactBuilder, matchingClasses, cause); |
| 479 | 479 |
| 480 // Give an info so that library developers can compile with -v to find why | 480 // Give an info so that library developers can compile with -v to find why |
| 481 // all the native classes are included. | 481 // all the native classes are included. |
| 482 if (unusedBefore > 0 && unusedBefore == matchingClasses.length) { | 482 if (unusedBefore > 0 && unusedBefore == matchingClasses.length) { |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 628 | 628 |
| 629 void _addSubtypes(ClassElement cls, NativeEmitter emitter) { | 629 void _addSubtypes(ClassElement cls, NativeEmitter emitter) { |
| 630 if (!backend.isNative(cls)) return; | 630 if (!backend.isNative(cls)) return; |
| 631 if (doneAddSubtypes.contains(cls)) return; | 631 if (doneAddSubtypes.contains(cls)) return; |
| 632 doneAddSubtypes.add(cls); | 632 doneAddSubtypes.add(cls); |
| 633 | 633 |
| 634 // Walk the superclass chain since classes on the superclass chain might not | 634 // Walk the superclass chain since classes on the superclass chain might not |
| 635 // be instantiated (abstract or simply unused). | 635 // be instantiated (abstract or simply unused). |
| 636 _addSubtypes(cls.superclass, emitter); | 636 _addSubtypes(cls.superclass, emitter); |
| 637 | 637 |
| 638 for (DartType type in cls.allSupertypes) { | 638 for (ResolutionDartType type in cls.allSupertypes) { |
| 639 List<Element> subtypes = | 639 List<Element> subtypes = |
| 640 emitter.subtypes.putIfAbsent(type.element, () => <ClassElement>[]); | 640 emitter.subtypes.putIfAbsent(type.element, () => <ClassElement>[]); |
| 641 subtypes.add(cls); | 641 subtypes.add(cls); |
| 642 } | 642 } |
| 643 | 643 |
| 644 // Skip through all the mixin applications in the super class | 644 // Skip through all the mixin applications in the super class |
| 645 // chain. That way, the direct subtypes set only contain the | 645 // chain. That way, the direct subtypes set only contain the |
| 646 // natives classes. | 646 // natives classes. |
| 647 ClassElement superclass = cls.superclass; | 647 ClassElement superclass = cls.superclass; |
| 648 while (superclass != null && superclass.isMixinApplication) { | 648 while (superclass != null && superclass.isMixinApplication) { |
| 649 assert(!backend.isNative(superclass)); | 649 assert(!backend.isNative(superclass)); |
| 650 superclass = superclass.superclass; | 650 superclass = superclass.superclass; |
| 651 } | 651 } |
| 652 | 652 |
| 653 List<Element> directSubtypes = | 653 List<Element> directSubtypes = |
| 654 emitter.directSubtypes.putIfAbsent(superclass, () => <ClassElement>[]); | 654 emitter.directSubtypes.putIfAbsent(superclass, () => <ClassElement>[]); |
| 655 directSubtypes.add(cls); | 655 directSubtypes.add(cls); |
| 656 } | 656 } |
| 657 | 657 |
| 658 void logSummary(log(message)) { | 658 void logSummary(log(message)) { |
| 659 log('Compiled ${_registeredClasses.length} native classes, ' | 659 log('Compiled ${_registeredClasses.length} native classes, ' |
| 660 '${_unusedClasses.length} native classes omitted.'); | 660 '${_unusedClasses.length} native classes omitted.'); |
| 661 } | 661 } |
| 662 } | 662 } |
| OLD | NEW |