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

Side by Side Diff: pkg/compiler/lib/src/native/enqueue.dart

Issue 2494093002: Refactor enqueuers (Closed)
Patch Set: Refactor enqueuers Created 4 years, 1 month 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
OLDNEW
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/registry.dart' show Registry; 9 import '../common/registry.dart' show Registry;
10 import '../common/resolution.dart' show Resolution; 10 import '../common/resolution.dart' show Resolution;
11 import '../compiler.dart' show Compiler; 11 import '../compiler.dart' show Compiler;
12 import '../constants/values.dart'; 12 import '../constants/values.dart';
13 import '../core_types.dart' show CoreTypes; 13 import '../core_types.dart' show CoreTypes;
14 import '../dart_types.dart'; 14 import '../dart_types.dart';
15 import '../elements/elements.dart'; 15 import '../elements/elements.dart';
16 import '../elements/modelx.dart' show FunctionElementX; 16 import '../elements/modelx.dart' show FunctionElementX;
17 import '../enqueue.dart' show Enqueuer; 17 import '../enqueue.dart' show Enqueuer;
18 import '../js_backend/backend_helpers.dart' show BackendHelpers; 18 import '../js_backend/backend_helpers.dart' show BackendHelpers;
19 import '../js_backend/js_backend.dart'; 19 import '../js_backend/js_backend.dart';
20 import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter; 20 import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter;
21 import '../tokens/token.dart' show BeginGroupToken, Token; 21 import '../tokens/token.dart' show BeginGroupToken, Token;
22 import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN; 22 import '../tokens/token_constants.dart' as Tokens show EOF_TOKEN;
23 import '../tree/tree.dart'; 23 import '../tree/tree.dart';
24 import '../universe/use.dart' show StaticUse, TypeUse;
25 import '../universe/world_impact.dart' show WorldImpactBuilder;
24 import 'behavior.dart'; 26 import 'behavior.dart';
25 27
26 /** 28 /**
27 * This could be an abstract class but we use it as a stub for the dart_backend. 29 * This could be an abstract class but we use it as a stub for the dart_backend.
28 */ 30 */
29 class NativeEnqueuer { 31 class NativeEnqueuer {
32 /// Called when a [type] has been instantiated natively.
33 void onInstantiatedType(InterfaceType type) {}
34
30 /// Initial entry point to native enqueuer. 35 /// Initial entry point to native enqueuer.
31 void processNativeClasses(Iterable<LibraryElement> libraries) {} 36 void processNativeClasses(
37 WorldImpactBuilder impactBuilder, Iterable<LibraryElement> libraries) {}
32 38
33 /// Registers the [nativeBehavior]. Adds the liveness of its instantiated 39 /// Registers the [nativeBehavior]. Adds the liveness of its instantiated
34 /// types to the world. 40 /// types to the world.
35 void registerNativeBehavior(NativeBehavior nativeBehavior, cause) {} 41 void registerNativeBehavior(
42 WorldImpactBuilder impactBuilder, NativeBehavior nativeBehavior, cause) {}
36 43
37 // TODO(johnniwinther): Move [handleFieldAnnotations] and 44 // TODO(johnniwinther): Move [handleFieldAnnotations] and
38 // [handleMethodAnnotations] to [JavaScriptBackend] or [NativeData]. 45 // [handleMethodAnnotations] to [JavaScriptBackend] or [NativeData].
39 // TODO(johnniwinther): Change the return type to 'bool' and rename them to 46 // TODO(johnniwinther): Change the return type to 'bool' and rename them to
40 // something like `computeNativeField`. 47 // something like `computeNativeField`.
41 /// Process the potentially native [field]. Adds information from metadata 48 /// Process the potentially native [field]. Adds information from metadata
42 /// attributes. 49 /// attributes.
43 void handleFieldAnnotations(Element field) {} 50 void handleFieldAnnotations(Element field) {}
44 51
45 /// Process the potentially native [method]. Adds information from metadata 52 /// Process the potentially native [method]. Adds information from metadata
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
79 86
80 final Map<ClassElement, Set<ClassElement>> nonNativeSubclasses = 87 final Map<ClassElement, Set<ClassElement>> nonNativeSubclasses =
81 new Map<ClassElement, Set<ClassElement>>(); 88 new Map<ClassElement, Set<ClassElement>>();
82 89
83 /** 90 /**
84 * Records matched constraints ([SpecialType] or [DartType]). Once a type 91 * Records matched constraints ([SpecialType] or [DartType]). Once a type
85 * constraint has been matched, there is no need to match it again. 92 * constraint has been matched, there is no need to match it again.
86 */ 93 */
87 final Set matchedTypeConstraints = new Set(); 94 final Set matchedTypeConstraints = new Set();
88 95
89 /// Pending actions. Classes in [pendingClasses] have action thunks in
90 /// [queue] to register the class.
91 final queue = new Queue();
92 bool flushing = false;
93
94 final Enqueuer world;
95 final Compiler compiler; 96 final Compiler compiler;
96 final bool enableLiveTypeAnalysis; 97 final bool enableLiveTypeAnalysis;
97 98
98 ClassElement _annotationCreatesClass; 99 ClassElement _annotationCreatesClass;
99 ClassElement _annotationReturnsClass; 100 ClassElement _annotationReturnsClass;
100 ClassElement _annotationJsNameClass; 101 ClassElement _annotationJsNameClass;
101 102
102 /// Subclasses of [NativeEnqueuerBase] are constructed by the backend. 103 /// Subclasses of [NativeEnqueuerBase] are constructed by the backend.
103 NativeEnqueuerBase(this.world, Compiler compiler, this.enableLiveTypeAnalysis) 104 NativeEnqueuerBase(Compiler compiler, this.enableLiveTypeAnalysis)
104 : this.compiler = compiler, 105 : this.compiler = compiler,
105 processedLibraries = compiler.cacheStrategy.newSet(); 106 processedLibraries = compiler.cacheStrategy.newSet();
106 107
107 JavaScriptBackend get backend => compiler.backend; 108 JavaScriptBackend get backend => compiler.backend;
108 BackendHelpers get helpers => backend.helpers; 109 BackendHelpers get helpers => backend.helpers;
109 Resolution get resolution => compiler.resolution; 110 Resolution get resolution => compiler.resolution;
110 111
111 DiagnosticReporter get reporter => compiler.reporter; 112 DiagnosticReporter get reporter => compiler.reporter;
112 CoreTypes get coreTypes => compiler.coreTypes; 113 CoreTypes get coreTypes => compiler.coreTypes;
113 114
114 void processNativeClasses(Iterable<LibraryElement> libraries) { 115 void onInstantiatedType(InterfaceType type) {
116 if (unusedClasses.remove(type.element)) {
117 registeredClasses.add(type.element);
118 }
119 }
120
121 void processNativeClasses(
122 WorldImpactBuilder impactBuilder, Iterable<LibraryElement> libraries) {
115 if (compiler.options.hasIncrementalSupport) { 123 if (compiler.options.hasIncrementalSupport) {
116 // Since [Set.add] returns bool if an element was added, this restricts 124 // Since [Set.add] returns bool if an element was added, this restricts
117 // [libraries] to ones that haven't already been processed. This saves 125 // [libraries] to ones that haven't already been processed. This saves
118 // time during incremental compiles. 126 // time during incremental compiles.
119 libraries = libraries.where(processedLibraries.add); 127 libraries = libraries.where(processedLibraries.add);
120 } 128 }
121 libraries.forEach(processNativeClassesInLibrary); 129 libraries.forEach(processNativeClassesInLibrary);
122 if (helpers.isolateHelperLibrary != null) { 130 if (helpers.isolateHelperLibrary != null) {
123 processNativeClassesInLibrary(helpers.isolateHelperLibrary); 131 processNativeClassesInLibrary(helpers.isolateHelperLibrary);
124 } 132 }
125 processSubclassesOfNativeClasses(libraries); 133 processSubclassesOfNativeClasses(libraries);
126 if (!enableLiveTypeAnalysis) { 134 if (!enableLiveTypeAnalysis) {
127 nativeClasses.forEach((c) => enqueueClass(c, 'forced')); 135 _registerTypeUses(impactBuilder, nativeClasses, 'forced');
128 flushQueue();
129 } 136 }
130 } 137 }
131 138
132 void processNativeClassesInLibrary(LibraryElement library) { 139 void processNativeClassesInLibrary(LibraryElement library) {
133 // Use implementation to ensure the inclusion of injected members. 140 // Use implementation to ensure the inclusion of injected members.
134 library.implementation.forEachLocalMember((Element element) { 141 library.implementation.forEachLocalMember((Element element) {
135 if (element.isClass && backend.isNative(element)) { 142 if (element.isClass && backend.isNative(element)) {
136 processNativeClass(element); 143 processNativeClass(element);
137 } 144 }
138 }); 145 });
(...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after
326 if (name == null) { 333 if (name == null) {
327 name = specString; 334 name = specString;
328 } else { 335 } else {
329 reporter.internalError( 336 reporter.internalError(
330 annotation, 'Too many JSName annotations: ${annotation}'); 337 annotation, 'Too many JSName annotations: ${annotation}');
331 } 338 }
332 } 339 }
333 return name; 340 return name;
334 } 341 }
335 342
336 enqueueClass(ClassElement classElement, cause) { 343 /// Register [classes] as natively instantiated in [impactBuilder].
337 assert(unusedClasses.contains(classElement)); 344 void _registerTypeUses(
338 unusedClasses.remove(classElement); 345 WorldImpactBuilder impactBuilder, Set<ClassElement> classes, cause) {
339 pendingClasses.add(classElement); 346 bool maybeFirstTime = registeredClasses.isEmpty;
Harry Terkelsen 2016/11/11 21:24:27 is this used anywhere?
Johnni Winther 2016/11/14 09:08:36 No.
340 queue.add(() { 347 for (ClassElement cls in classes) {
341 processClass(classElement, cause); 348 if (!unusedClasses.contains(cls)) {
342 }); 349 // No need to add [classElement] to [impactBuilder]: it has already been
343 } 350 // instantiated and we don't track origins of native instantiations
344 351 // precisely.
345 void flushQueue() { 352 continue;
346 if (flushing) return; 353 }
347 flushing = true; 354 cls.ensureResolved(resolution);
348 while (!queue.isEmpty) { 355 impactBuilder
349 (queue.removeFirst())(); 356 .registerTypeUse(new TypeUse.nativeInstantiation(cls.rawType));
350 }
351 flushing = false;
352 }
353
354 processClass(ClassElement classElement, cause) {
355 // TODO(ahe): Fix this assertion to work in incremental compilation.
356 assert(compiler.options.hasIncrementalSupport ||
357 !registeredClasses.contains(classElement));
358
359 bool firstTime = registeredClasses.isEmpty;
360 pendingClasses.remove(classElement);
361 registeredClasses.add(classElement);
362
363 // TODO(ahe): Is this really a global dependency?
364 classElement.ensureResolved(resolution);
365 compiler.backend.registerInstantiatedType(
366 classElement.rawType, world, compiler.globalDependencies);
367
368 if (firstTime) {
369 queue.add(onFirstNativeClass);
370 } 357 }
371 } 358 }
372 359
373 void handleFieldAnnotations(Element element) { 360 void handleFieldAnnotations(Element element) {
374 if (compiler.serialization.isDeserialized(element)) { 361 if (compiler.serialization.isDeserialized(element)) {
375 return; 362 return;
376 } 363 }
377 if (backend.isNative(element.enclosingElement)) { 364 if (backend.isNative(element.enclosingElement)) {
378 // Exclude non-instance (static) fields - they not really native and are 365 // Exclude non-instance (static) fields - they not really native and are
379 // compiled as isolate globals. Access of a property of a constructor 366 // compiled as isolate globals. Access of a property of a constructor
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
442 Node node = element.parseNode(resolution.parsingContext); 429 Node node = element.parseNode(resolution.parsingContext);
443 if (node is! FunctionExpression) return false; 430 if (node is! FunctionExpression) return false;
444 FunctionExpression functionExpression = node; 431 FunctionExpression functionExpression = node;
445 node = functionExpression.body; 432 node = functionExpression.body;
446 Token token = node.getBeginToken(); 433 Token token = node.getBeginToken();
447 if (identical(token.stringValue, 'native')) return true; 434 if (identical(token.stringValue, 'native')) return true;
448 return false; 435 return false;
449 }); 436 });
450 } 437 }
451 438
452 void registerNativeBehavior(NativeBehavior nativeBehavior, cause) { 439 void registerNativeBehavior(
453 processNativeBehavior(nativeBehavior, cause); 440 WorldImpactBuilder impactBuilder, NativeBehavior nativeBehavior, cause) {
454 flushQueue(); 441 _processNativeBehavior(impactBuilder, nativeBehavior, cause);
455 } 442 }
456 443
457 processNativeBehavior(NativeBehavior behavior, cause) { 444 void _processNativeBehavior(
458 // TODO(ahe): Is this really a global dependency? 445 WorldImpactBuilder impactBuilder, NativeBehavior behavior, cause) {
459 Registry registry = compiler.globalDependencies; 446 void instantiated(InterfaceType type) {
460 bool allUsedBefore = unusedClasses.isEmpty; 447 impactBuilder.registerTypeUse(new TypeUse.nativeInstantiation(type));
448 }
449
450 int unusedBefore = unusedClasses.length;
451 Set<ClassElement> matchingClasses = new Set<ClassElement>();
461 for (var type in behavior.typesInstantiated) { 452 for (var type in behavior.typesInstantiated) {
462 if (matchedTypeConstraints.contains(type)) continue; 453 if (matchedTypeConstraints.contains(type)) continue;
463 matchedTypeConstraints.add(type); 454 matchedTypeConstraints.add(type);
464 if (type is SpecialType) { 455 if (type is SpecialType) {
465 if (type == SpecialType.JsObject) { 456 if (type == SpecialType.JsObject) {
466 backend.registerInstantiatedType( 457 instantiated(compiler.coreTypes.objectType);
467 compiler.coreTypes.objectType, world, registry);
468 } 458 }
469 continue; 459 continue;
470 } 460 }
471 if (type is InterfaceType) { 461 if (type is InterfaceType) {
472 if (type == coreTypes.intType) { 462 if (type == coreTypes.intType) {
473 backend.registerInstantiatedType(type, world, registry); 463 instantiated(type);
474 } else if (type == coreTypes.doubleType) { 464 } else if (type == coreTypes.doubleType) {
475 backend.registerInstantiatedType(type, world, registry); 465 instantiated(type);
476 } else if (type == coreTypes.numType) { 466 } else if (type == coreTypes.numType) {
477 backend.registerInstantiatedType( 467 instantiated(coreTypes.doubleType);
478 coreTypes.doubleType, world, registry); 468 instantiated(coreTypes.doubleType);
Harry Terkelsen 2016/11/11 21:24:27 doubleType -> intType
Johnni Winther 2016/11/14 09:08:36 Good catch!
479 backend.registerInstantiatedType(coreTypes.intType, world, registry);
480 } else if (type == coreTypes.stringType) { 469 } else if (type == coreTypes.stringType) {
481 backend.registerInstantiatedType(type, world, registry); 470 instantiated(type);
482 } else if (type == coreTypes.nullType) { 471 } else if (type == coreTypes.nullType) {
483 backend.registerInstantiatedType(type, world, registry); 472 instantiated(type);
484 } else if (type == coreTypes.boolType) { 473 } else if (type == coreTypes.boolType) {
485 backend.registerInstantiatedType(type, world, registry); 474 instantiated(type);
486 } else if (compiler.types.isSubtype( 475 } else if (compiler.types.isSubtype(
487 type, backend.backendClasses.listImplementation.rawType)) { 476 type, backend.backendClasses.listImplementation.rawType)) {
488 backend.registerInstantiatedType(type, world, registry); 477 instantiated(type);
489 } 478 }
490 // TODO(johnniwinther): Improve spec string precision to handle type 479 // TODO(johnniwinther): Improve spec string precision to handle type
491 // arguments and implements relations that preserve generics. Currently 480 // arguments and implements relations that preserve generics. Currently
492 // we cannot distinguish between `List`, `List<dynamic>`, and 481 // we cannot distinguish between `List`, `List<dynamic>`, and
493 // `List<int>` and take all to mean `List<E>`; in effect not including 482 // `List<int>` and take all to mean `List<E>`; in effect not including
494 // any native subclasses of generic classes. 483 // any native subclasses of generic classes.
495 // TODO(johnniwinther,sra): Find and replace uses of `List` with the 484 // TODO(johnniwinther,sra): Find and replace uses of `List` with the
496 // actual implementation classes such as `JSArray` et al. 485 // actual implementation classes such as `JSArray` et al.
497 enqueueUnusedClassesMatching((ClassElement nativeClass) { 486 matchingClasses
487 .addAll(_findUnusedClassesMatching((ClassElement nativeClass) {
498 InterfaceType nativeType = nativeClass.thisType; 488 InterfaceType nativeType = nativeClass.thisType;
499 InterfaceType specType = type.element.thisType; 489 InterfaceType specType = type.element.thisType;
500 return compiler.types.isSubtype(nativeType, specType); 490 return compiler.types.isSubtype(nativeType, specType);
501 }, cause, 'subtypeof($type)'); 491 }));
502 } else if (type.isDynamic) { 492 } else if (type.isDynamic) {
503 enqueueUnusedClassesMatching((_) => true, cause, 'subtypeof($type)'); 493 matchingClasses.addAll(unusedClasses);
504 } else { 494 } else {
505 assert(type is VoidType); 495 assert(type is VoidType);
506 } 496 }
507 } 497 }
498 if (matchingClasses.isNotEmpty && registeredClasses.isEmpty) {
499 matchingClasses.addAll(_onFirstNativeClass(impactBuilder));
500 }
501 _registerTypeUses(impactBuilder, matchingClasses, cause);
508 502
509 // Give an info so that library developers can compile with -v to find why 503 // Give an info so that library developers can compile with -v to find why
510 // all the native classes are included. 504 // all the native classes are included.
511 if (unusedClasses.isEmpty && !allUsedBefore) { 505 if (unusedBefore == matchingClasses.length) {
512 reporter.log('All native types marked as used due to $cause.'); 506 reporter.log('All native types marked as used due to $cause.');
513 } 507 }
514 } 508 }
515 509
516 enqueueUnusedClassesMatching(bool predicate(classElement), cause, 510 Iterable<ClassElement> _findUnusedClassesMatching(
517 [String reason]) { 511 bool predicate(classElement)) {
518 Iterable matches = unusedClasses.where(predicate); 512 return unusedClasses.where(predicate);
519 matches.toList().forEach((c) => enqueueClass(c, cause));
520 } 513 }
521 514
522 onFirstNativeClass() { 515 Iterable<ClassElement> _onFirstNativeClass(WorldImpactBuilder impactBuilder) {
523 staticUse(name) { 516 void staticUse(name) {
524 backend.enqueue( 517 Element element = helpers.findHelper(name);
525 world, helpers.findHelper(name), compiler.globalDependencies); 518 impactBuilder.registerStaticUse(new StaticUse.foreignUse(element));
519 backend.registerBackendUse(element);
520 compiler.globalDependencies.registerDependency(element);
526 } 521 }
527 522
528 staticUse('defineProperty'); 523 staticUse('defineProperty');
529 staticUse('toStringForNativeObject'); 524 staticUse('toStringForNativeObject');
530 staticUse('hashCodeForNativeObject'); 525 staticUse('hashCodeForNativeObject');
531 staticUse('convertDartClosureToJS'); 526 staticUse('convertDartClosureToJS');
532 addNativeExceptions(); 527 return _findNativeExceptions();
533 } 528 }
534 529
535 addNativeExceptions() { 530 Iterable<ClassElement> _findNativeExceptions() {
536 enqueueUnusedClassesMatching((classElement) { 531 return _findUnusedClassesMatching((classElement) {
537 // TODO(sra): Annotate exception classes in dart:html. 532 // TODO(sra): Annotate exception classes in dart:html.
538 String name = classElement.name; 533 String name = classElement.name;
539 if (name.contains('Exception')) return true; 534 if (name.contains('Exception')) return true;
540 if (name.contains('Error')) return true; 535 if (name.contains('Error')) return true;
541 return false; 536 return false;
542 }, 'native exception'); 537 });
543 } 538 }
544 } 539 }
545 540
546 class NativeResolutionEnqueuer extends NativeEnqueuerBase { 541 class NativeResolutionEnqueuer extends NativeEnqueuerBase {
547 Map<String, ClassElement> tagOwner = new Map<String, ClassElement>(); 542 Map<String, ClassElement> tagOwner = new Map<String, ClassElement>();
548 543
549 NativeResolutionEnqueuer(Enqueuer world, Compiler compiler) 544 NativeResolutionEnqueuer(Compiler compiler)
550 : super(world, compiler, compiler.options.enableNativeLiveTypeAnalysis); 545 : super(compiler, compiler.options.enableNativeLiveTypeAnalysis);
551 546
552 void processNativeClass(ClassElement classElement) { 547 void processNativeClass(ClassElement classElement) {
553 super.processNativeClass(classElement); 548 super.processNativeClass(classElement);
554 549
555 // Js Interop interfaces do not have tags. 550 // Js Interop interfaces do not have tags.
556 if (backend.isJsInterop(classElement)) return; 551 if (backend.isJsInterop(classElement)) return;
557 // Since we map from dispatch tags to classes, a dispatch tag must be used 552 // Since we map from dispatch tags to classes, a dispatch tag must be used
558 // on only one native class. 553 // on only one native class.
559 for (String tag in backend.nativeData.getNativeTagsOfClass(classElement)) { 554 for (String tag in backend.nativeData.getNativeTagsOfClass(classElement)) {
560 ClassElement owner = tagOwner[tag]; 555 ClassElement owner = tagOwner[tag];
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 return NativeBehavior.ofJsBuiltinCallSend( 611 return NativeBehavior.ofJsBuiltinCallSend(
617 node, reporter, compiler.coreTypes, resolver); 612 node, reporter, compiler.coreTypes, resolver);
618 } 613 }
619 } 614 }
620 615
621 class NativeCodegenEnqueuer extends NativeEnqueuerBase { 616 class NativeCodegenEnqueuer extends NativeEnqueuerBase {
622 final CodeEmitterTask emitter; 617 final CodeEmitterTask emitter;
623 618
624 final Set<ClassElement> doneAddSubtypes = new Set<ClassElement>(); 619 final Set<ClassElement> doneAddSubtypes = new Set<ClassElement>();
625 620
626 NativeCodegenEnqueuer(Enqueuer world, Compiler compiler, this.emitter) 621 NativeCodegenEnqueuer(Compiler compiler, this.emitter)
627 : super(world, compiler, compiler.options.enableNativeLiveTypeAnalysis); 622 : super(compiler, compiler.options.enableNativeLiveTypeAnalysis);
628 623
629 void processNativeClasses(Iterable<LibraryElement> libraries) { 624 void processNativeClasses(
630 super.processNativeClasses(libraries); 625 WorldImpactBuilder impactBuilder, Iterable<LibraryElement> libraries) {
626 super.processNativeClasses(impactBuilder, libraries);
631 627
632 // HACK HACK - add all the resolved classes. 628 // HACK HACK - add all the resolved classes.
633 NativeEnqueuerBase enqueuer = compiler.enqueuer.resolution.nativeEnqueuer; 629 NativeEnqueuerBase enqueuer = compiler.enqueuer.resolution.nativeEnqueuer;
630 Set<ClassElement> matchingClasses = new Set<ClassElement>();
634 for (final classElement in enqueuer.registeredClasses) { 631 for (final classElement in enqueuer.registeredClasses) {
635 if (unusedClasses.contains(classElement)) { 632 if (unusedClasses.contains(classElement)) {
636 enqueueClass(classElement, 'was resolved'); 633 matchingClasses.add(classElement);
637 } 634 }
638 } 635 }
639 flushQueue(); 636 if (matchingClasses.isNotEmpty && registeredClasses.isEmpty) {
637 matchingClasses.addAll(_onFirstNativeClass(impactBuilder));
638 }
639 _registerTypeUses(impactBuilder, matchingClasses, 'was resolved');
640 } 640 }
641 641
642 processClass(ClassElement classElement, cause) { 642 void _registerTypeUses(
643 super.processClass(classElement, cause); 643 WorldImpactBuilder impactBuilder, Set<ClassElement> classes, cause) {
644 // Add the information that this class is a subtype of its supertypes. The 644 super._registerTypeUses(impactBuilder, classes, cause);
645 // code emitter and the ssa builder use that information. 645
646 addSubtypes(classElement, emitter.nativeEmitter); 646 for (ClassElement classElement in classes) {
647 // Add the information that this class is a subtype of its supertypes. Th e
Harry Terkelsen 2016/11/11 21:24:27 long line
Johnni Winther 2016/11/14 09:08:36 Done.
648 // code emitter and the ssa builder use that information.
649 _addSubtypes(classElement, emitter.nativeEmitter);
650 }
647 } 651 }
648 652
649 void addSubtypes(ClassElement cls, NativeEmitter emitter) { 653 void _addSubtypes(ClassElement cls, NativeEmitter emitter) {
650 if (!backend.isNative(cls)) return; 654 if (!backend.isNative(cls)) return;
651 if (doneAddSubtypes.contains(cls)) return; 655 if (doneAddSubtypes.contains(cls)) return;
652 doneAddSubtypes.add(cls); 656 doneAddSubtypes.add(cls);
653 657
654 // Walk the superclass chain since classes on the superclass chain might not 658 // Walk the superclass chain since classes on the superclass chain might not
655 // be instantiated (abstract or simply unused). 659 // be instantiated (abstract or simply unused).
656 addSubtypes(cls.superclass, emitter); 660 _addSubtypes(cls.superclass, emitter);
657 661
658 for (DartType type in cls.allSupertypes) { 662 for (DartType type in cls.allSupertypes) {
659 List<Element> subtypes = 663 List<Element> subtypes =
660 emitter.subtypes.putIfAbsent(type.element, () => <ClassElement>[]); 664 emitter.subtypes.putIfAbsent(type.element, () => <ClassElement>[]);
661 subtypes.add(cls); 665 subtypes.add(cls);
662 } 666 }
663 667
664 // Skip through all the mixin applications in the super class 668 // Skip through all the mixin applications in the super class
665 // chain. That way, the direct subtypes set only contain the 669 // chain. That way, the direct subtypes set only contain the
666 // natives classes. 670 // natives classes.
667 ClassElement superclass = cls.superclass; 671 ClassElement superclass = cls.superclass;
668 while (superclass != null && superclass.isMixinApplication) { 672 while (superclass != null && superclass.isMixinApplication) {
669 assert(!backend.isNative(superclass)); 673 assert(!backend.isNative(superclass));
670 superclass = superclass.superclass; 674 superclass = superclass.superclass;
671 } 675 }
672 676
673 List<Element> directSubtypes = 677 List<Element> directSubtypes =
674 emitter.directSubtypes.putIfAbsent(superclass, () => <ClassElement>[]); 678 emitter.directSubtypes.putIfAbsent(superclass, () => <ClassElement>[]);
675 directSubtypes.add(cls); 679 directSubtypes.add(cls);
676 } 680 }
677 681
678 void logSummary(log(message)) { 682 void logSummary(log(message)) {
679 log('Compiled ${registeredClasses.length} native classes, ' 683 log('Compiled ${registeredClasses.length} native classes, '
680 '${unusedClasses.length} native classes omitted.'); 684 '${unusedClasses.length} native classes omitted.');
681 } 685 }
682 } 686 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698