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

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

Issue 2494093002: Refactor enqueuers (Closed)
Patch Set: Updated cf. comments. 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 for (ClassElement cls in classes) {
340 queue.add(() { 347 if (!unusedClasses.contains(cls)) {
341 processClass(classElement, cause); 348 // No need to add [classElement] to [impactBuilder]: it has already been
342 }); 349 // instantiated and we don't track origins of native instantiations
343 } 350 // precisely.
344 351 continue;
345 void flushQueue() { 352 }
346 if (flushing) return; 353 cls.ensureResolved(resolution);
347 flushing = true; 354 impactBuilder
348 while (!queue.isEmpty) { 355 .registerTypeUse(new TypeUse.nativeInstantiation(cls.rawType));
349 (queue.removeFirst())();
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 } 356 }
371 } 357 }
372 358
373 void handleFieldAnnotations(Element element) { 359 void handleFieldAnnotations(Element element) {
374 if (compiler.serialization.isDeserialized(element)) { 360 if (compiler.serialization.isDeserialized(element)) {
375 return; 361 return;
376 } 362 }
377 if (backend.isNative(element.enclosingElement)) { 363 if (backend.isNative(element.enclosingElement)) {
378 // Exclude non-instance (static) fields - they not really native and are 364 // Exclude non-instance (static) fields - they not really native and are
379 // compiled as isolate globals. Access of a property of a constructor 365 // 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); 428 Node node = element.parseNode(resolution.parsingContext);
443 if (node is! FunctionExpression) return false; 429 if (node is! FunctionExpression) return false;
444 FunctionExpression functionExpression = node; 430 FunctionExpression functionExpression = node;
445 node = functionExpression.body; 431 node = functionExpression.body;
446 Token token = node.getBeginToken(); 432 Token token = node.getBeginToken();
447 if (identical(token.stringValue, 'native')) return true; 433 if (identical(token.stringValue, 'native')) return true;
448 return false; 434 return false;
449 }); 435 });
450 } 436 }
451 437
452 void registerNativeBehavior(NativeBehavior nativeBehavior, cause) { 438 void registerNativeBehavior(
453 processNativeBehavior(nativeBehavior, cause); 439 WorldImpactBuilder impactBuilder, NativeBehavior nativeBehavior, cause) {
454 flushQueue(); 440 _processNativeBehavior(impactBuilder, nativeBehavior, cause);
455 } 441 }
456 442
457 processNativeBehavior(NativeBehavior behavior, cause) { 443 void _processNativeBehavior(
458 // TODO(ahe): Is this really a global dependency? 444 WorldImpactBuilder impactBuilder, NativeBehavior behavior, cause) {
459 Registry registry = compiler.globalDependencies; 445 void registerInstantiation(InterfaceType type) {
460 bool allUsedBefore = unusedClasses.isEmpty; 446 impactBuilder.registerTypeUse(new TypeUse.nativeInstantiation(type));
447 }
448
449 int unusedBefore = unusedClasses.length;
450 Set<ClassElement> matchingClasses = new Set<ClassElement>();
461 for (var type in behavior.typesInstantiated) { 451 for (var type in behavior.typesInstantiated) {
462 if (matchedTypeConstraints.contains(type)) continue; 452 if (matchedTypeConstraints.contains(type)) continue;
463 matchedTypeConstraints.add(type); 453 matchedTypeConstraints.add(type);
464 if (type is SpecialType) { 454 if (type is SpecialType) {
465 if (type == SpecialType.JsObject) { 455 if (type == SpecialType.JsObject) {
466 backend.registerInstantiatedType( 456 registerInstantiation(compiler.coreTypes.objectType);
467 compiler.coreTypes.objectType, world, registry);
468 } 457 }
469 continue; 458 continue;
470 } 459 }
471 if (type is InterfaceType) { 460 if (type is InterfaceType) {
472 if (type == coreTypes.intType) { 461 if (type == coreTypes.intType) {
473 backend.registerInstantiatedType(type, world, registry); 462 registerInstantiation(type);
474 } else if (type == coreTypes.doubleType) { 463 } else if (type == coreTypes.doubleType) {
475 backend.registerInstantiatedType(type, world, registry); 464 registerInstantiation(type);
476 } else if (type == coreTypes.numType) { 465 } else if (type == coreTypes.numType) {
477 backend.registerInstantiatedType( 466 registerInstantiation(coreTypes.doubleType);
478 coreTypes.doubleType, world, registry); 467 registerInstantiation(coreTypes.intType);
479 backend.registerInstantiatedType(coreTypes.intType, world, registry);
480 } else if (type == coreTypes.stringType) { 468 } else if (type == coreTypes.stringType) {
481 backend.registerInstantiatedType(type, world, registry); 469 registerInstantiation(type);
482 } else if (type == coreTypes.nullType) { 470 } else if (type == coreTypes.nullType) {
483 backend.registerInstantiatedType(type, world, registry); 471 registerInstantiation(type);
484 } else if (type == coreTypes.boolType) { 472 } else if (type == coreTypes.boolType) {
485 backend.registerInstantiatedType(type, world, registry); 473 registerInstantiation(type);
486 } else if (compiler.types.isSubtype( 474 } else if (compiler.types.isSubtype(
487 type, backend.backendClasses.listImplementation.rawType)) { 475 type, backend.backendClasses.listImplementation.rawType)) {
488 backend.registerInstantiatedType(type, world, registry); 476 registerInstantiation(type);
489 } 477 }
490 // TODO(johnniwinther): Improve spec string precision to handle type 478 // TODO(johnniwinther): Improve spec string precision to handle type
491 // arguments and implements relations that preserve generics. Currently 479 // arguments and implements relations that preserve generics. Currently
492 // we cannot distinguish between `List`, `List<dynamic>`, and 480 // we cannot distinguish between `List`, `List<dynamic>`, and
493 // `List<int>` and take all to mean `List<E>`; in effect not including 481 // `List<int>` and take all to mean `List<E>`; in effect not including
494 // any native subclasses of generic classes. 482 // any native subclasses of generic classes.
495 // TODO(johnniwinther,sra): Find and replace uses of `List` with the 483 // TODO(johnniwinther,sra): Find and replace uses of `List` with the
496 // actual implementation classes such as `JSArray` et al. 484 // actual implementation classes such as `JSArray` et al.
497 enqueueUnusedClassesMatching((ClassElement nativeClass) { 485 matchingClasses
486 .addAll(_findUnusedClassesMatching((ClassElement nativeClass) {
498 InterfaceType nativeType = nativeClass.thisType; 487 InterfaceType nativeType = nativeClass.thisType;
499 InterfaceType specType = type.element.thisType; 488 InterfaceType specType = type.element.thisType;
500 return compiler.types.isSubtype(nativeType, specType); 489 return compiler.types.isSubtype(nativeType, specType);
501 }, cause, 'subtypeof($type)'); 490 }));
502 } else if (type.isDynamic) { 491 } else if (type.isDynamic) {
503 enqueueUnusedClassesMatching((_) => true, cause, 'subtypeof($type)'); 492 matchingClasses.addAll(unusedClasses);
504 } else { 493 } else {
505 assert(type is VoidType); 494 assert(type is VoidType);
506 } 495 }
507 } 496 }
497 if (matchingClasses.isNotEmpty && registeredClasses.isEmpty) {
498 matchingClasses.addAll(_onFirstNativeClass(impactBuilder));
499 }
500 _registerTypeUses(impactBuilder, matchingClasses, cause);
508 501
509 // Give an info so that library developers can compile with -v to find why 502 // Give an info so that library developers can compile with -v to find why
510 // all the native classes are included. 503 // all the native classes are included.
511 if (unusedClasses.isEmpty && !allUsedBefore) { 504 if (unusedBefore == matchingClasses.length) {
512 reporter.log('All native types marked as used due to $cause.'); 505 reporter.log('All native types marked as used due to $cause.');
513 } 506 }
514 } 507 }
515 508
516 enqueueUnusedClassesMatching(bool predicate(classElement), cause, 509 Iterable<ClassElement> _findUnusedClassesMatching(
517 [String reason]) { 510 bool predicate(classElement)) {
518 Iterable matches = unusedClasses.where(predicate); 511 return unusedClasses.where(predicate);
519 matches.toList().forEach((c) => enqueueClass(c, cause));
520 } 512 }
521 513
522 onFirstNativeClass() { 514 Iterable<ClassElement> _onFirstNativeClass(WorldImpactBuilder impactBuilder) {
523 staticUse(name) { 515 void staticUse(name) {
524 backend.enqueue( 516 Element element = helpers.findHelper(name);
525 world, helpers.findHelper(name), compiler.globalDependencies); 517 impactBuilder.registerStaticUse(new StaticUse.foreignUse(element));
518 backend.registerBackendUse(element);
519 compiler.globalDependencies.registerDependency(element);
526 } 520 }
527 521
528 staticUse('defineProperty'); 522 staticUse('defineProperty');
529 staticUse('toStringForNativeObject'); 523 staticUse('toStringForNativeObject');
530 staticUse('hashCodeForNativeObject'); 524 staticUse('hashCodeForNativeObject');
531 staticUse('convertDartClosureToJS'); 525 staticUse('convertDartClosureToJS');
532 addNativeExceptions(); 526 return _findNativeExceptions();
533 } 527 }
534 528
535 addNativeExceptions() { 529 Iterable<ClassElement> _findNativeExceptions() {
536 enqueueUnusedClassesMatching((classElement) { 530 return _findUnusedClassesMatching((classElement) {
537 // TODO(sra): Annotate exception classes in dart:html. 531 // TODO(sra): Annotate exception classes in dart:html.
538 String name = classElement.name; 532 String name = classElement.name;
539 if (name.contains('Exception')) return true; 533 if (name.contains('Exception')) return true;
540 if (name.contains('Error')) return true; 534 if (name.contains('Error')) return true;
541 return false; 535 return false;
542 }, 'native exception'); 536 });
543 } 537 }
544 } 538 }
545 539
546 class NativeResolutionEnqueuer extends NativeEnqueuerBase { 540 class NativeResolutionEnqueuer extends NativeEnqueuerBase {
547 Map<String, ClassElement> tagOwner = new Map<String, ClassElement>(); 541 Map<String, ClassElement> tagOwner = new Map<String, ClassElement>();
548 542
549 NativeResolutionEnqueuer(Enqueuer world, Compiler compiler) 543 NativeResolutionEnqueuer(Compiler compiler)
550 : super(world, compiler, compiler.options.enableNativeLiveTypeAnalysis); 544 : super(compiler, compiler.options.enableNativeLiveTypeAnalysis);
551 545
552 void processNativeClass(ClassElement classElement) { 546 void processNativeClass(ClassElement classElement) {
553 super.processNativeClass(classElement); 547 super.processNativeClass(classElement);
554 548
555 // Js Interop interfaces do not have tags. 549 // Js Interop interfaces do not have tags.
556 if (backend.isJsInterop(classElement)) return; 550 if (backend.isJsInterop(classElement)) return;
557 // Since we map from dispatch tags to classes, a dispatch tag must be used 551 // Since we map from dispatch tags to classes, a dispatch tag must be used
558 // on only one native class. 552 // on only one native class.
559 for (String tag in backend.nativeData.getNativeTagsOfClass(classElement)) { 553 for (String tag in backend.nativeData.getNativeTagsOfClass(classElement)) {
560 ClassElement owner = tagOwner[tag]; 554 ClassElement owner = tagOwner[tag];
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after
616 return NativeBehavior.ofJsBuiltinCallSend( 610 return NativeBehavior.ofJsBuiltinCallSend(
617 node, reporter, compiler.coreTypes, resolver); 611 node, reporter, compiler.coreTypes, resolver);
618 } 612 }
619 } 613 }
620 614
621 class NativeCodegenEnqueuer extends NativeEnqueuerBase { 615 class NativeCodegenEnqueuer extends NativeEnqueuerBase {
622 final CodeEmitterTask emitter; 616 final CodeEmitterTask emitter;
623 617
624 final Set<ClassElement> doneAddSubtypes = new Set<ClassElement>(); 618 final Set<ClassElement> doneAddSubtypes = new Set<ClassElement>();
625 619
626 NativeCodegenEnqueuer(Enqueuer world, Compiler compiler, this.emitter) 620 NativeCodegenEnqueuer(Compiler compiler, this.emitter)
627 : super(world, compiler, compiler.options.enableNativeLiveTypeAnalysis); 621 : super(compiler, compiler.options.enableNativeLiveTypeAnalysis);
628 622
629 void processNativeClasses(Iterable<LibraryElement> libraries) { 623 void processNativeClasses(
630 super.processNativeClasses(libraries); 624 WorldImpactBuilder impactBuilder, Iterable<LibraryElement> libraries) {
625 super.processNativeClasses(impactBuilder, libraries);
631 626
632 // HACK HACK - add all the resolved classes. 627 // HACK HACK - add all the resolved classes.
633 NativeEnqueuerBase enqueuer = compiler.enqueuer.resolution.nativeEnqueuer; 628 NativeEnqueuerBase enqueuer = compiler.enqueuer.resolution.nativeEnqueuer;
629 Set<ClassElement> matchingClasses = new Set<ClassElement>();
634 for (final classElement in enqueuer.registeredClasses) { 630 for (final classElement in enqueuer.registeredClasses) {
635 if (unusedClasses.contains(classElement)) { 631 if (unusedClasses.contains(classElement)) {
636 enqueueClass(classElement, 'was resolved'); 632 matchingClasses.add(classElement);
637 } 633 }
638 } 634 }
639 flushQueue(); 635 if (matchingClasses.isNotEmpty && registeredClasses.isEmpty) {
636 matchingClasses.addAll(_onFirstNativeClass(impactBuilder));
637 }
638 _registerTypeUses(impactBuilder, matchingClasses, 'was resolved');
640 } 639 }
641 640
642 processClass(ClassElement classElement, cause) { 641 void _registerTypeUses(
643 super.processClass(classElement, cause); 642 WorldImpactBuilder impactBuilder, Set<ClassElement> classes, cause) {
644 // Add the information that this class is a subtype of its supertypes. The 643 super._registerTypeUses(impactBuilder, classes, cause);
645 // code emitter and the ssa builder use that information. 644
646 addSubtypes(classElement, emitter.nativeEmitter); 645 for (ClassElement classElement in classes) {
646 // Add the information that this class is a subtype of its supertypes. The
647 // code emitter and the ssa builder use that information.
648 _addSubtypes(classElement, emitter.nativeEmitter);
649 }
647 } 650 }
648 651
649 void addSubtypes(ClassElement cls, NativeEmitter emitter) { 652 void _addSubtypes(ClassElement cls, NativeEmitter emitter) {
650 if (!backend.isNative(cls)) return; 653 if (!backend.isNative(cls)) return;
651 if (doneAddSubtypes.contains(cls)) return; 654 if (doneAddSubtypes.contains(cls)) return;
652 doneAddSubtypes.add(cls); 655 doneAddSubtypes.add(cls);
653 656
654 // Walk the superclass chain since classes on the superclass chain might not 657 // Walk the superclass chain since classes on the superclass chain might not
655 // be instantiated (abstract or simply unused). 658 // be instantiated (abstract or simply unused).
656 addSubtypes(cls.superclass, emitter); 659 _addSubtypes(cls.superclass, emitter);
657 660
658 for (DartType type in cls.allSupertypes) { 661 for (DartType type in cls.allSupertypes) {
659 List<Element> subtypes = 662 List<Element> subtypes =
660 emitter.subtypes.putIfAbsent(type.element, () => <ClassElement>[]); 663 emitter.subtypes.putIfAbsent(type.element, () => <ClassElement>[]);
661 subtypes.add(cls); 664 subtypes.add(cls);
662 } 665 }
663 666
664 // Skip through all the mixin applications in the super class 667 // Skip through all the mixin applications in the super class
665 // chain. That way, the direct subtypes set only contain the 668 // chain. That way, the direct subtypes set only contain the
666 // natives classes. 669 // natives classes.
667 ClassElement superclass = cls.superclass; 670 ClassElement superclass = cls.superclass;
668 while (superclass != null && superclass.isMixinApplication) { 671 while (superclass != null && superclass.isMixinApplication) {
669 assert(!backend.isNative(superclass)); 672 assert(!backend.isNative(superclass));
670 superclass = superclass.superclass; 673 superclass = superclass.superclass;
671 } 674 }
672 675
673 List<Element> directSubtypes = 676 List<Element> directSubtypes =
674 emitter.directSubtypes.putIfAbsent(superclass, () => <ClassElement>[]); 677 emitter.directSubtypes.putIfAbsent(superclass, () => <ClassElement>[]);
675 directSubtypes.add(cls); 678 directSubtypes.add(cls);
676 } 679 }
677 680
678 void logSummary(log(message)) { 681 void logSummary(log(message)) {
679 log('Compiled ${registeredClasses.length} native classes, ' 682 log('Compiled ${registeredClasses.length} native classes, '
680 '${unusedClasses.length} native classes omitted.'); 683 '${unusedClasses.length} native classes omitted.');
681 } 684 }
682 } 685 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/type_variable_handler.dart ('k') | pkg/compiler/lib/src/ssa/builder.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698