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

Side by Side Diff: sdk/lib/_internal/compiler/implementation/deferred_load.dart

Issue 278733003: When mirrors are used with deferred loading we now go through all (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Handle patch libraries + Adress Karl's comments. Created 6 years, 7 months 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | tests/compiler/dart2js/deferred_mirrors_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 library deferred_load; 5 library deferred_load;
6 6
7 import 'dart2jslib.dart' show 7 import 'dart2jslib.dart' show
8 Backend, 8 Backend,
9 Compiler, 9 Compiler,
10 CompilerTask, 10 CompilerTask,
11 Constant, 11 Constant,
12 ConstructedConstant, 12 ConstructedConstant,
13 LibraryLoaderTask,
13 MessageKind, 14 MessageKind,
14 StringConstant, 15 StringConstant,
15 invariant, 16 invariant;
16 Backend;
17 17
18 import 'dart_backend/dart_backend.dart' show 18 import 'dart_backend/dart_backend.dart' show
19 DartBackend; 19 DartBackend;
20 20
21 import 'js_backend/js_backend.dart' show 21 import 'js_backend/js_backend.dart' show
22 JavaScriptBackend; 22 JavaScriptBackend;
23 23
24 import 'elements/elements.dart' show 24 import 'elements/elements.dart' show
25 Element, 25 Element,
26 ClassElement, 26 ClassElement,
27 ElementKind, 27 ElementKind,
28 Elements, 28 Elements,
29 FunctionElement, 29 FunctionElement,
30 LibraryElement, 30 LibraryElement,
31 MetadataAnnotation, 31 MetadataAnnotation,
32 ScopeContainerElement, 32 ScopeContainerElement,
33 PrefixElement, 33 PrefixElement,
34 ClosureContainer, 34 ClosureContainer,
35 VoidElement; 35 VoidElement,
36 TypedefElement;
36 37
37 import 'util/util.dart' show 38 import 'util/util.dart' show
38 Link; 39 Link;
39 40
40 import 'util/setlet.dart' show 41 import 'util/setlet.dart' show
41 Setlet; 42 Setlet;
42 43
43 import 'tree/tree.dart' show 44 import 'tree/tree.dart' show
44 LibraryTag, 45 LibraryTag,
45 Node, 46 Node,
46 NewExpression, 47 NewExpression,
47 Import, 48 Import,
48 LiteralString, 49 LiteralString,
49 LiteralDartString; 50 LiteralDartString;
50 51
51 import 'tree/tree.dart' as ast; 52 import 'tree/tree.dart' as ast;
52 53
53 import 'resolution/resolution.dart' show 54 import 'resolution/resolution.dart' show
54 TreeElements; 55 TreeElements,
55 56 AnalyzableElement;
56 import 'mirrors_used.dart' show
57 MirrorUsageAnalyzer,
58 MirrorUsageAnalyzerTask,
59 MirrorUsage;
60 57
61 /// A "hunk" of the program that will be loaded whenever one of its [imports] 58 /// A "hunk" of the program that will be loaded whenever one of its [imports]
62 /// are loaded. 59 /// are loaded.
63 /// 60 ///
64 /// Elements that are only used in one deferred import, is in an OutputUnit with 61 /// Elements that are only used in one deferred import, is in an OutputUnit with
65 /// the deferred import as single element in the [imports] set. 62 /// the deferred import as single element in the [imports] set.
66 /// 63 ///
67 /// Whenever a deferred Element is shared between several deferred imports it is 64 /// Whenever a deferred Element is shared between several deferred imports it is
68 /// in an output unit with those imports in the [imports] Set. 65 /// in an output unit with those imports in the [imports] Set.
69 /// 66 ///
(...skipping 225 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 elements.add(constant.type.element); 292 elements.add(constant.type.element);
296 } 293 }
297 constant.getDependencies().forEach(addConstants); 294 constant.getDependencies().forEach(addConstants);
298 } 295 }
299 296
300 /// Collects all direct dependencies of [element]. 297 /// Collects all direct dependencies of [element].
301 /// 298 ///
302 /// The collected dependent elements and constants are are added to 299 /// The collected dependent elements and constants are are added to
303 /// [elements] and [constants] respectively. 300 /// [elements] and [constants] respectively.
304 void collectDependencies(Element element) { 301 void collectDependencies(Element element) {
305 TreeElements treeElements = element.isTypedef 302 TreeElements treeElements = element is TypedefElement
306 ? element.treeElements 303 ? element.treeElements
307 : compiler.enqueuer.resolution.getCachedElements(element); 304 : compiler.enqueuer.resolution.getCachedElements(element);
308 305
309 // TODO(sigurdm): We want to be more specific about this - need a better 306 // TODO(sigurdm): We want to be more specific about this - need a better
310 // way to query "liveness". 307 // way to query "liveness".
311 if (treeElements == null) return; 308 if (treeElements == null) return;
312 309
313 for (Element dependency in treeElements.allElements) { 310 for (Element dependency in treeElements.allElements) {
314 if (Elements.isLocal(dependency) && !dependency.isFunction) continue; 311 if (Elements.isLocal(dependency) && !dependency.isFunction) continue;
315 if (dependency.isErroneous) continue; 312 if (dependency.isErroneous) continue;
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
425 } else { 422 } else {
426 _mapDependencies(dependency, import); 423 _mapDependencies(dependency, import);
427 } 424 }
428 } 425 }
429 } 426 }
430 427
431 /// Adds extra dependencies coming from mirror usage. 428 /// Adds extra dependencies coming from mirror usage.
432 /// 429 ///
433 /// The elements are added with [_mapDependencies]. 430 /// The elements are added with [_mapDependencies].
434 void _addMirrorElements() { 431 void _addMirrorElements() {
435 MirrorUsageAnalyzerTask mirrorTask = compiler.mirrorUsageAnalyzerTask; 432 void mapDependenciesIfResolved(Element element, Import deferredImport) {
436 // For each import we record all mirrors-used elements from all the 433 // If an element is the target of a MirrorsUsed annotation but never used
437 // libraries reached directly from that import. 434 // It will not be resolved, and we should not call isNeededForReflection.
435 // TODO(sigurdm): Unresolved elements should just answer false when
436 // asked isNeededForReflection. Instead an internal error is triggered.
437 // So we have to filter them out here.
438 if (element is AnalyzableElement && !element.hasTreeElements) return;
439 if (compiler.backend.isNeededForReflection(element)) {
440 _mapDependencies(element, deferredImport);
441 }
442 }
443
444 Set<LibraryElement> seenLibraries = new Set<LibraryElement>();
445
446 // For each deferred import we analyze all elements reachable from the
447 // imported library through non-deferred imports.
448 handleLibrary(LibraryElement library, Import deferredImport) {
449 seenLibraries.add(library);
450
451 library.forEachLocalMember((Element element) {
452 mapDependenciesIfResolved(element, deferredImport);
453 });
454 if (library.isPatched) {
455 library.implementation.forEachLocalMember((Element element) {
456 mapDependenciesIfResolved(element, deferredImport);
457 });
458 }
459
460 for (MetadataAnnotation metadata in library.metadata) {
461 Constant constant =
462 backend.constants.getConstantForMetadata(metadata);
463 if (constant != null) {
464 _mapDependencies(constant.computeType(compiler).element,
465 deferredImport);
466 }
467 }
468 for (LibraryTag tag in library.tags) {
469 for (MetadataAnnotation metadata in tag.metadata) {
470 Constant constant =
471 backend.constants.getConstantForMetadata(metadata);
472 if (constant != null) {
473 _mapDependencies(constant.computeType(compiler).element,
474 deferredImport);
475 }
476 }
477 }
478 }
479
438 for (Import deferredImport in _allDeferredImports.keys) { 480 for (Import deferredImport in _allDeferredImports.keys) {
439 LibraryElement deferredLibrary = _allDeferredImports[deferredImport]; 481 LibraryElement deferredLibrary = _allDeferredImports[deferredImport];
440 for (LibraryElement library in 482 for (LibraryElement library in
441 _nonDeferredReachableLibraries(deferredLibrary)) { 483 _nonDeferredReachableLibraries(deferredLibrary)) {
442 // TODO(sigurdm): The metadata should go to the right output unit. 484 handleLibrary(library, deferredImport);
443 // For now they all go to the main output unit. 485 }
444 for (MetadataAnnotation metadata in library.metadata) { 486 }
445 Constant constant =
446 backend.constants.getConstantForMetadata(metadata);
447 if (constant != null) {
448 _mapDependencies(constant.computeType(compiler).element,
449 _fakeMainImport);
450 }
451 }
452 for (LibraryTag tag in library.tags) {
453 for (MetadataAnnotation metadata in tag.metadata) {
454 Constant constant =
455 backend.constants.getConstantForMetadata(metadata);
456 if (constant != null) {
457 _mapDependencies(constant.computeType(compiler).element,
458 _fakeMainImport);
459 }
460 }
461 }
462 487
463 if (mirrorTask.librariesWithUsage.contains(library)) { 488 // A number of libraries are never imported explicitly - they belong to the
464 489 // main output unit.
465 Map<LibraryElement, List<MirrorUsage>> mirrorsResult = 490 LibraryLoaderTask loader = compiler.libraryLoader;
466 mirrorTask.analyzer.collectMirrorsUsedAnnotation(); 491 for (LibraryElement library in loader.libraryNames.values) {
467 492 if (!seenLibraries.contains(library)) {
468 // If there is a MirrorsUsed annotation we add only the needed 493 handleLibrary(library, _fakeMainImport);
469 // things to the output units for the library.
470 List<MirrorUsage> mirrorUsages = mirrorsResult[library];
471 if (mirrorUsages == null) continue;
472
473 void mapDependenciesIfResolved(Element element) {
474 // If there is a target for this class, but no use of mirrors the
475 // class will not be resolved. We just skip it.
476 if (element is ClassElement &&!element.isResolved) {
477 return;
478 }
479 _mapDependencies(element, deferredImport);
480 }
481
482 for (MirrorUsage usage in mirrorUsages) {
483 if (usage.targets != null) {
484 for (Element dependency in usage.targets) {
485 if (dependency.isLibrary) {
486 LibraryElement library = dependency;
487 library.forEachLocalMember(mapDependenciesIfResolved);
488 } else {
489 mapDependenciesIfResolved(dependency);
490 }
491 }
492 }
493 if (usage.metaTargets != null) {
494 for (Element dependency in usage.metaTargets) {
495 _mapDependencies(dependency, deferredImport);
496 }
497 }
498 }
499 } else {
500 // If there is no MirrorsUsed annotation we add _everything_ to
501 // the output units for the library.
502
503 // TODO(sigurdm): This is too expensive.
504 // Plan: If mirrors are used without MirrorsUsed, create an
505 // "EverythingElse" library that contains all elements that are
506 // not referred by main or deferred libraries that don't contain
507 // mirrors (without MirrorsUsed).
508 //
509 // So basically we want:
510 // mainImport
511 // deferredA
512 // deferredB
513 // deferredCwithMirrorsUsed
514 // deferredEverythingElse
515 //
516 // Where deferredEverythingElse will be loaded for *all* libraries
517 // that contain a mirror usage without MirrorsUsed.
518 // When loading the deferredEverythingElse also load all other
519 // deferred libraries at the same time.
520 bool usesMirrors = false;
521 for (LibraryTag tag in library.tags) {
522 if (tag is! Import) continue;
523 if (library.getLibraryFromTag(tag) == compiler.mirrorsLibrary) {
524 usesMirrors = true;
525 break;
526 }
527 }
528 if (usesMirrors) {
529 // Add all resolved elements to the output unit.
530 for (Element element in
531 compiler.enqueuer.resolution.resolvedElements.keys) {
532 _mapDependencies(element, deferredImport);
533 }
534 for (Element element in
535 compiler.mirrorDependencies.otherDependencies) {
536 _mapDependencies(element, deferredImport);
537 }
538 }
539 }
540 } 494 }
541 } 495 }
542 } 496 }
543 497
544 /// Computes a unique string for the name field for each outputUnit. 498 /// Computes a unique string for the name field for each outputUnit.
545 /// 499 ///
546 /// Also sets up the [hunksToLoad] mapping. 500 /// Also sets up the [hunksToLoad] mapping.
547 void _assignNamesToOutputUnits(Set<OutputUnit> allOutputUnits) { 501 void _assignNamesToOutputUnits(Set<OutputUnit> allOutputUnits) {
548 Set<String> usedImportNames = new Set<String>(); 502 Set<String> usedImportNames = new Set<String>();
549 503
(...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after
826 Element maybePrefix = elements[identifier]; 780 Element maybePrefix = elements[identifier];
827 if (maybePrefix != null && maybePrefix.isPrefix) { 781 if (maybePrefix != null && maybePrefix.isPrefix) {
828 PrefixElement prefixElement = maybePrefix; 782 PrefixElement prefixElement = maybePrefix;
829 if (prefixElement.isDeferred) { 783 if (prefixElement.isDeferred) {
830 return prefixElement; 784 return prefixElement;
831 } 785 }
832 } 786 }
833 return null; 787 return null;
834 } 788 }
835 } 789 }
OLDNEW
« no previous file with comments | « no previous file | tests/compiler/dart2js/deferred_mirrors_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698