| Index: pkg/compiler/lib/src/native/enqueue.dart
|
| diff --git a/pkg/compiler/lib/src/native/enqueue.dart b/pkg/compiler/lib/src/native/enqueue.dart
|
| index 444eb6f7dad286f2dfc8828ef9ef492981d873f5..adb79f734192f2ec6a09d220a73d095e2211682d 100644
|
| --- a/pkg/compiler/lib/src/native/enqueue.dart
|
| +++ b/pkg/compiler/lib/src/native/enqueue.dart
|
| @@ -2,9 +2,6 @@
|
| // for details. All rights reserved. Use of this source code is governed by a
|
| // BSD-style license that can be found in the LICENSE file.
|
|
|
| -import 'package:front_end/src/fasta/scanner.dart' show BeginGroupToken, Token;
|
| -import 'package:front_end/src/fasta/scanner.dart' as Tokens show EOF_TOKEN;
|
| -
|
| import '../common.dart';
|
| import '../common/backend_api.dart';
|
| import '../common/resolution.dart' show Resolution;
|
| @@ -23,6 +20,7 @@ import '../universe/use.dart' show StaticUse, TypeUse;
|
| import '../universe/world_impact.dart'
|
| show WorldImpact, WorldImpactBuilder, WorldImpactBuilderImpl;
|
| import 'behavior.dart';
|
| +import 'resolver.dart' show NativeClassResolver;
|
|
|
| /**
|
| * This could be an abstract class but we use it as a stub for the dart_backend.
|
| @@ -66,8 +64,6 @@ abstract class NativeEnqueuerBase implements NativeEnqueuer {
|
| DiagnosticReporter get _reporter => _compiler.reporter;
|
| CommonElements get _commonElements => _compiler.commonElements;
|
|
|
| - NativeBasicData get _nativeBasicData => _backend.nativeBasicData;
|
| -
|
| BackendClasses get _backendClasses => _backend.backendClasses;
|
|
|
| void onInstantiatedType(InterfaceType type) {
|
| @@ -187,13 +183,13 @@ abstract class NativeEnqueuerBase implements NativeEnqueuer {
|
| }
|
|
|
| class NativeResolutionEnqueuer extends NativeEnqueuerBase {
|
| + final NativeClassResolver _nativeClassResolver;
|
| +
|
| /// The set of all native classes. Each native class is in [nativeClasses]
|
| /// and exactly one of [unusedClasses] and [registeredClasses].
|
| final Set<ClassElement> _nativeClasses = new Set<ClassElement>();
|
|
|
| - Map<String, ClassElement> tagOwner = new Map<String, ClassElement>();
|
| -
|
| - NativeResolutionEnqueuer(Compiler compiler)
|
| + NativeResolutionEnqueuer(Compiler compiler, this._nativeClassResolver)
|
| : super(compiler, compiler.options.enableNativeLiveTypeAnalysis);
|
|
|
| BackendUsageBuilder get _backendUsageBuilder => _backend.backendUsageBuilder;
|
| @@ -205,13 +201,8 @@ class NativeResolutionEnqueuer extends NativeEnqueuerBase {
|
|
|
| WorldImpact processNativeClasses(Iterable<LibraryElement> libraries) {
|
| WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
|
| - Set<ClassElement> nativeClasses = new Set<ClassElement>();
|
| - libraries.forEach((l) => _processNativeClassesInLibrary(l, nativeClasses));
|
| - if (_helpers.isolateHelperLibrary != null) {
|
| - _processNativeClassesInLibrary(
|
| - _helpers.isolateHelperLibrary, nativeClasses);
|
| - }
|
| - _processSubclassesOfNativeClasses(libraries, nativeClasses);
|
| + Set<ClassElement> nativeClasses =
|
| + _nativeClassResolver.computeNativeClasses(libraries);
|
| _nativeClasses.addAll(nativeClasses);
|
| _unusedClasses.addAll(nativeClasses);
|
| if (!enableLiveTypeAnalysis) {
|
| @@ -220,162 +211,6 @@ class NativeResolutionEnqueuer extends NativeEnqueuerBase {
|
| return impactBuilder;
|
| }
|
|
|
| - void _processNativeClassesInLibrary(
|
| - LibraryElement library, Set<ClassElement> nativeClasses) {
|
| - // Use implementation to ensure the inclusion of injected members.
|
| - library.implementation.forEachLocalMember((Element element) {
|
| - if (element.isClass) {
|
| - ClassElement cls = element;
|
| - if (_nativeBasicData.isNativeClass(cls)) {
|
| - _processNativeClass(element, nativeClasses);
|
| - }
|
| - }
|
| - });
|
| - }
|
| -
|
| - void _processNativeClass(
|
| - ClassElement classElement, Set<ClassElement> nativeClasses) {
|
| - nativeClasses.add(classElement);
|
| - // Resolve class to ensure the class has valid inheritance info.
|
| - classElement.ensureResolved(_resolution);
|
| - // Js Interop interfaces do not have tags.
|
| - if (_nativeBasicData.isJsInteropClass(classElement)) return;
|
| - // Since we map from dispatch tags to classes, a dispatch tag must be used
|
| - // on only one native class.
|
| - for (String tag in _nativeBasicData.getNativeTagsOfClass(classElement)) {
|
| - ClassElement owner = tagOwner[tag];
|
| - if (owner != null) {
|
| - if (owner != classElement) {
|
| - _reporter.internalError(
|
| - classElement, "Tag '$tag' already in use by '${owner.name}'");
|
| - }
|
| - } else {
|
| - tagOwner[tag] = classElement;
|
| - }
|
| - }
|
| - }
|
| -
|
| - void _processSubclassesOfNativeClasses(
|
| - Iterable<LibraryElement> libraries, Set<ClassElement> nativeClasses) {
|
| - Set<ClassElement> nativeClassesAndSubclasses = new Set<ClassElement>();
|
| - // Collect potential subclasses, e.g.
|
| - //
|
| - // class B extends foo.A {}
|
| - //
|
| - // String "A" has a potential subclass B.
|
| -
|
| - var potentialExtends = new Map<String, Set<ClassElement>>();
|
| -
|
| - libraries.forEach((library) {
|
| - library.implementation.forEachLocalMember((element) {
|
| - if (element.isClass) {
|
| - String extendsName = _findExtendsNameOfClass(element);
|
| - if (extendsName != null) {
|
| - Set<ClassElement> potentialSubclasses = potentialExtends
|
| - .putIfAbsent(extendsName, () => new Set<ClassElement>());
|
| - potentialSubclasses.add(element);
|
| - }
|
| - }
|
| - });
|
| - });
|
| -
|
| - // Resolve all the native classes and any classes that might extend them in
|
| - // [potentialExtends], and then check that the properly resolved class is in
|
| - // fact a subclass of a native class.
|
| -
|
| - ClassElement nativeSuperclassOf(ClassElement classElement) {
|
| - if (_nativeBasicData.isNativeClass(classElement)) return classElement;
|
| - if (classElement.superclass == null) return null;
|
| - return nativeSuperclassOf(classElement.superclass);
|
| - }
|
| -
|
| - void walkPotentialSubclasses(ClassElement element) {
|
| - if (nativeClassesAndSubclasses.contains(element)) return;
|
| - element.ensureResolved(_resolution);
|
| - ClassElement nativeSuperclass = nativeSuperclassOf(element);
|
| - if (nativeSuperclass != null) {
|
| - nativeClassesAndSubclasses.add(element);
|
| - Set<ClassElement> potentialSubclasses = potentialExtends[element.name];
|
| - if (potentialSubclasses != null) {
|
| - potentialSubclasses.forEach(walkPotentialSubclasses);
|
| - }
|
| - }
|
| - }
|
| -
|
| - nativeClasses.forEach(walkPotentialSubclasses);
|
| - nativeClasses.addAll(nativeClassesAndSubclasses);
|
| - }
|
| -
|
| - /**
|
| - * Returns the source string of the class named in the extends clause, or
|
| - * `null` if there is no extends clause.
|
| - */
|
| - String _findExtendsNameOfClass(ClassElement classElement) {
|
| - if (classElement.isResolved) {
|
| - ClassElement superClass = classElement.superclass;
|
| - while (superClass != null) {
|
| - if (!superClass.isUnnamedMixinApplication) {
|
| - return superClass.name;
|
| - }
|
| - superClass = superClass.superclass;
|
| - }
|
| - return null;
|
| - }
|
| -
|
| - // "class B extends A ... {}" --> "A"
|
| - // "class B extends foo.A ... {}" --> "A"
|
| - // "class B<T> extends foo.A<T,T> with M1, M2 ... {}" --> "A"
|
| -
|
| - // We want to avoid calling classElement.parseNode on every class. Doing so
|
| - // will slightly increase parse time and size and cause compiler errors and
|
| - // warnings to me emitted in more unused code.
|
| -
|
| - // An alternative to this code is to extend the API of ClassElement to
|
| - // expose the name of the extended element.
|
| -
|
| - // Pattern match the above cases in the token stream.
|
| - // [abstract] class X extends [id.]* id
|
| -
|
| - Token skipTypeParameters(Token token) {
|
| - BeginGroupToken beginGroupToken = token;
|
| - Token endToken = beginGroupToken.endGroup;
|
| - return endToken.next;
|
| - //for (;;) {
|
| - // token = token.next;
|
| - // if (token.stringValue == '>') return token.next;
|
| - // if (token.stringValue == '<') return skipTypeParameters(token);
|
| - //}
|
| - }
|
| -
|
| - String scanForExtendsName(Token token) {
|
| - if (token.stringValue == 'abstract') token = token.next;
|
| - if (token.stringValue != 'class') return null;
|
| - token = token.next;
|
| - if (!token.isIdentifier()) return null;
|
| - token = token.next;
|
| - // class F<X extends B<X>> extends ...
|
| - if (token.stringValue == '<') {
|
| - token = skipTypeParameters(token);
|
| - }
|
| - if (token.stringValue != 'extends') return null;
|
| - token = token.next;
|
| - Token id = token;
|
| - while (token.kind != Tokens.EOF_TOKEN) {
|
| - token = token.next;
|
| - if (token.stringValue != '.') break;
|
| - token = token.next;
|
| - if (!token.isIdentifier()) return null;
|
| - id = token;
|
| - }
|
| - // Should be at '{', 'with', 'implements', '<' or 'native'.
|
| - return id.lexeme;
|
| - }
|
| -
|
| - return _reporter.withCurrentElement(classElement, () {
|
| - return scanForExtendsName(classElement.position);
|
| - });
|
| - }
|
| -
|
| void logSummary(log(message)) {
|
| log('Resolved ${_registeredClasses.length} native elements used, '
|
| '${_unusedClasses.length} native elements dead.');
|
| @@ -383,14 +218,14 @@ class NativeResolutionEnqueuer extends NativeEnqueuerBase {
|
| }
|
|
|
| class NativeCodegenEnqueuer extends NativeEnqueuerBase {
|
| - final CodeEmitterTask emitter;
|
| + final CodeEmitterTask _emitter;
|
|
|
| - final Set<ClassElement> doneAddSubtypes = new Set<ClassElement>();
|
| + final Set<ClassElement> _doneAddSubtypes = new Set<ClassElement>();
|
|
|
| final NativeResolutionEnqueuer _resolutionEnqueuer;
|
|
|
| NativeCodegenEnqueuer(
|
| - Compiler compiler, this.emitter, this._resolutionEnqueuer)
|
| + Compiler compiler, this._emitter, this._resolutionEnqueuer)
|
| : super(compiler, compiler.options.enableNativeLiveTypeAnalysis) {}
|
|
|
| NativeData get _nativeData => _backend.nativeData;
|
| @@ -425,14 +260,14 @@ class NativeCodegenEnqueuer extends NativeEnqueuerBase {
|
| for (ClassElement classElement in classes) {
|
| // Add the information that this class is a subtype of its supertypes. The
|
| // code emitter and the ssa builder use that information.
|
| - _addSubtypes(classElement, emitter.nativeEmitter);
|
| + _addSubtypes(classElement, _emitter.nativeEmitter);
|
| }
|
| }
|
|
|
| void _addSubtypes(ClassElement cls, NativeEmitter emitter) {
|
| if (!_nativeData.isNativeClass(cls)) return;
|
| - if (doneAddSubtypes.contains(cls)) return;
|
| - doneAddSubtypes.add(cls);
|
| + if (_doneAddSubtypes.contains(cls)) return;
|
| + _doneAddSubtypes.add(cls);
|
|
|
| // Walk the superclass chain since classes on the superclass chain might not
|
| // be instantiated (abstract or simply unused).
|
|
|