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

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

Issue 201613006: Introduces the new syntax for deferred loading (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 6 years, 9 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
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 Compiler, 8 Compiler,
9 CompilerTask, 9 CompilerTask,
10 Constant, 10 Constant,
(...skipping 96 matching lines...) Expand 10 before | Expand all | Expand 10 after
107 /// program. 107 /// program.
108 final Set<OutputUnit> allOutputUnits = new Set<OutputUnit>(); 108 final Set<OutputUnit> allOutputUnits = new Set<OutputUnit>();
109 109
110 /// Will be `true` if the program contains deferred libraries. 110 /// Will be `true` if the program contains deferred libraries.
111 bool splitProgram = false; 111 bool splitProgram = false;
112 112
113 /// A mapping from the name of a [DeferredLibrary] annotation to all dependent 113 /// A mapping from the name of a [DeferredLibrary] annotation to all dependent
114 /// output units. 114 /// output units.
115 final Map<String, Set<OutputUnit>> hunksToLoad = 115 final Map<String, Set<OutputUnit>> hunksToLoad =
116 new Map<String, Set<OutputUnit>>(); 116 new Map<String, Set<OutputUnit>>();
117 final Map<Import, String> importDeferName = new Map<Import, String>();
117 118
118 /// A mapping from elements and constants to their output unit. Query this via 119 /// A mapping from elements and constants to their output unit. Query this via
119 /// [outputUnitForElement] 120 /// [outputUnitForElement]
120 final Map<Element, OutputUnit> _elementToOutputUnit = 121 final Map<Element, OutputUnit> _elementToOutputUnit =
121 new Map<Element, OutputUnit>(); 122 new Map<Element, OutputUnit>();
122 123
123 /// A mapping from constants to their output unit. Query this via 124 /// A mapping from constants to their output unit. Query this via
124 /// [outputUnitForConstant] 125 /// [outputUnitForConstant]
125 final Map<Constant, OutputUnit> _constantToOutputUnit = 126 final Map<Constant, OutputUnit> _constantToOutputUnit =
126 new Map<Constant, OutputUnit>(); 127 new Map<Constant, OutputUnit>();
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after
190 191
191 /// Answers whether the [import] has a [DeferredLibrary] annotation. 192 /// Answers whether the [import] has a [DeferredLibrary] annotation.
192 bool _isImportDeferred(Import import) { 193 bool _isImportDeferred(Import import) {
193 return _allDeferredImports.containsKey(import); 194 return _allDeferredImports.containsKey(import);
194 } 195 }
195 196
196 /// Checks whether the [import] has a [DeferredLibrary] annotation and stores 197 /// Checks whether the [import] has a [DeferredLibrary] annotation and stores
197 /// the information in [_allDeferredImports] and on the corresponding 198 /// the information in [_allDeferredImports] and on the corresponding
198 /// prefixElement. 199 /// prefixElement.
199 void _markIfDeferred(Import import, LibraryElement library) { 200 void _markIfDeferred(Import import, LibraryElement library) {
201 // Check if the import is deferred by a keyword.
202 if (import.isDeferred) {
203 _allDeferredImports[import] = library.getLibraryFromTag(import);
204 return;
205 }
206 // Check if the import is deferred by a metadata annotation.
200 Link<MetadataAnnotation> metadataList = import.metadata; 207 Link<MetadataAnnotation> metadataList = import.metadata;
201 if (metadataList == null) return; 208 if (metadataList == null) return;
202 for (MetadataAnnotation metadata in metadataList) { 209 for (MetadataAnnotation metadata in metadataList) {
203 metadata.ensureResolved(compiler); 210 metadata.ensureResolved(compiler);
204 Element element = metadata.value.computeType(compiler).element; 211 Element element = metadata.value.computeType(compiler).element;
205 if (element == deferredLibraryClass) { 212 if (element == deferredLibraryClass) {
206 _allDeferredImports[import] = library.getLibraryFromTag(import); 213 _allDeferredImports[import] = library.getLibraryFromTag(import);
207 // On encountering a deferred library without a prefix we report an 214 // On encountering a deferred library without a prefix we report an
208 // error, but continue the compilation to possibly give more 215 // error, but continue the compilation to possibly give more
209 // information. Therefore it is neccessary to check if there is a prefix 216 // information. Therefore it is neccessary to check if there is a prefix
210 // here. 217 // here.
211 Element maybePrefix = library.find(import.prefix.toString()); 218 Element maybePrefix = library.find(import.prefix.toString());
212 if (maybePrefix != null && maybePrefix.isPrefix()) { 219 if (maybePrefix != null && maybePrefix.isPrefix()) {
213 PrefixElement prefix = maybePrefix; 220 PrefixElement prefix = maybePrefix;
214 prefix.markAsDeferred(); 221 prefix.markAsDeferred(import);
215 } 222 }
216 } 223 }
217 } 224 }
218 } 225 }
219 226
220 /// Answers whether [element] is explicitly deferred when referred to from 227 /// Answers whether [element] is explicitly deferred when referred to from
221 /// [library]. 228 /// [library].
222 bool _isExplicitlyDeferred(Element element, LibraryElement library) { 229 bool _isExplicitlyDeferred(Element element, LibraryElement library) {
223 Link<Import> imports = _getImports(element, library); 230 Link<Import> imports = _getImports(element, library);
224 // If the element is not imported explicitly, it is implicitly imported 231 // If the element is not imported explicitly, it is implicitly imported
(...skipping 297 matching lines...) Expand 10 before | Expand all | Expand 10 after
522 // unit of the constant, but we prefer separate instances. 529 // unit of the constant, but we prefer separate instances.
523 // Replace the imports of the constant to match the ones of the class. 530 // Replace the imports of the constant to match the ones of the class.
524 _replaceOutputUnitImports(constant, constantUnit, classImports); 531 _replaceOutputUnitImports(constant, constantUnit, classImports);
525 } 532 }
526 } 533 }
527 534
528 /// Computes a unique string for the name field for each outputUnit. 535 /// Computes a unique string for the name field for each outputUnit.
529 /// 536 ///
530 /// Also sets up the [hunksToLoad] mapping. 537 /// Also sets up the [hunksToLoad] mapping.
531 void _assignNamesToOutputUnits(Set<OutputUnit> allOutputUnits) { 538 void _assignNamesToOutputUnits(Set<OutputUnit> allOutputUnits) {
532 Map<Import, String> deferNameCache = new Map<Import, String>(); 539 Set<String> usedImportNames = new Set<String>();
540
541 // Returns suggestedName if it is not in usedNames. Otherwise concatenate
floitsch 2014/03/17 14:15:41 concatenates
sigurdm 2014/03/19 12:46:30 Done.
542 // the smallest number that makes it not appear in usedNames.
543 // Adds the result to usedNames.
544 String makeUnique(String suggestedName, Set<String> usedNames) {
545 String result = suggestedName;
546 if (usedNames.contains(suggestedName)) {
547 int counter = 0;
548 while (usedNames.contains(result)) {
549 counter++;
550 result = "$suggestedName$counter";
551 }
552 }
553 usedNames.add(result);
554 return result;
555 }
556
533 // Finds the first argument to the [DeferredLibrary] annotation 557 // Finds the first argument to the [DeferredLibrary] annotation
534 String importDeferName(Import import) { 558 void computeImportDeferName(Import import) {
535 if (deferNameCache.containsKey(import)) return deferNameCache[import];
536 if (import == _fakeMainImport) return "main";
537 Link<MetadataAnnotation> metadatas = import.metadata;
538 assert(metadatas != null);
539 String result; 559 String result;
540 for (MetadataAnnotation metadata in metadatas) { 560 if (import == _fakeMainImport) {
541 metadata.ensureResolved(compiler); 561 result = "main";
542 Element element = metadata.value.computeType(compiler).element; 562 } else if (import.isDeferred) {
543 if (metadata.value.computeType(compiler).element == 563 result = import.prefix.toString();
544 deferredLibraryClass) { 564 } else {
545 ConstructedConstant constant = metadata.value; 565 Link<MetadataAnnotation> metadatas = import.metadata;
546 StringConstant s = constant.fields[0]; 566 assert(metadatas != null);
547 result = s.value.slowToString(); 567 for (MetadataAnnotation metadata in metadatas) {
548 break; 568 metadata.ensureResolved(compiler);
569 Element element = metadata.value.computeType(compiler).element;
570 if (metadata.value.computeType(compiler).element ==
571 deferredLibraryClass) {
572 ConstructedConstant constant = metadata.value;
573 StringConstant s = constant.fields[0];
574 result = s.value.slowToString();
575 break;
576 }
549 } 577 }
550 } 578 }
551 assert(result != null); 579 assert(result != null);
552 deferNameCache[import] = result; 580 importDeferName[import] = makeUnique(result, usedImportNames);;
553 return result;
554 } 581 }
555 582
556 Set<String> usedNames = new Set<String>(); 583 Set<String> usedOutputUnitNames = new Set<String>();
557 Map<OutputUnit, String> generatedNames = new Map<OutputUnit, String>(); 584 Map<OutputUnit, String> generatedNames = new Map<OutputUnit, String>();
558 585
559 void computeOutputUnitName(OutputUnit outputUnit) { 586 void computeOutputUnitName(OutputUnit outputUnit) {
560 if (generatedNames[outputUnit] != null) return; 587 if (generatedNames[outputUnit] != null) return;
561 String suggestedName = outputUnit.imports.map((import) { 588 String suggestedName = outputUnit.imports.map((import) {
562 return importDeferName(import); 589 return importDeferName[import];
563 }).join('_'); 590 }).join('_');
564 if (!usedNames.contains(suggestedName)) { 591 outputUnit.name = makeUnique(suggestedName, usedOutputUnitNames);
565 outputUnit.name = suggestedName;
566 } else {
567 int counter = 0;
568 while (usedNames.contains("$suggestedName$counter")) {
569 counter++;
570 }
571 outputUnit.name = "$suggestedName$counter";
572 }
573 generatedNames[outputUnit] = outputUnit.name; 592 generatedNames[outputUnit] = outputUnit.name;
574 } 593 }
575 594
595 for (Import import in _allDeferredImports.keys) {
596 computeImportDeferName(import);
597 }
598
576 for (OutputUnit outputUnit in allOutputUnits) { 599 for (OutputUnit outputUnit in allOutputUnits) {
577 computeOutputUnitName(outputUnit); 600 computeOutputUnitName(outputUnit);
578 } 601 }
579 602
580 // For each deferred import we find out which outputUnits to load. 603 // For each deferred import we find out which outputUnits to load.
581 for (Import import in _allDeferredImports.keys) { 604 for (Import import in _allDeferredImports.keys) {
582 if (import == _fakeMainImport) continue; 605 if (import == _fakeMainImport) continue;
583 hunksToLoad[importDeferName(import)] = new Set<OutputUnit>(); 606 hunksToLoad[importDeferName[import]] = new Set<OutputUnit>();
584 for (OutputUnit outputUnit in allOutputUnits) { 607 for (OutputUnit outputUnit in allOutputUnits) {
585 if (outputUnit == mainOutputUnit) continue; 608 if (outputUnit == mainOutputUnit) continue;
586 if (outputUnit.imports.contains(import)) { 609 if (outputUnit.imports.contains(import)) {
587 hunksToLoad[importDeferName(import)].add(outputUnit); 610 hunksToLoad[importDeferName[import]].add(outputUnit);
588 } 611 }
589 } 612 }
590 } 613 }
591 } 614 }
592 615
593 void onResolutionComplete(FunctionElement main) { 616 void onResolutionComplete(FunctionElement main) {
594 if (!splitProgram) { 617 if (!splitProgram) {
595 allOutputUnits.add(mainOutputUnit); 618 allOutputUnits.add(mainOutputUnit);
596 return; 619 return;
597 } 620 }
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
650 _assignNamesToOutputUnits(allOutputUnits); 673 _assignNamesToOutputUnits(allOutputUnits);
651 }); 674 });
652 } 675 }
653 676
654 void ensureMetadataResolved(Compiler compiler) { 677 void ensureMetadataResolved(Compiler compiler) {
655 _allDeferredImports[_fakeMainImport] = compiler.mainApp; 678 _allDeferredImports[_fakeMainImport] = compiler.mainApp;
656 var lastDeferred; 679 var lastDeferred;
657 // When detecting duplicate prefixes of deferred libraries there are 4 680 // When detecting duplicate prefixes of deferred libraries there are 4
658 // cases of duplicate prefixes: 681 // cases of duplicate prefixes:
659 // 1. 682 // 1.
660 // @DeferredLibrary("a") import "lib.dart" as a; 683 // import "lib.dart" deferred as a;
661 // @DeferredLibrary("b") import "lib2.dart" as a; 684 // import "lib2.dart" deferred as a;
662 // 2. 685 // 2.
663 // @DeferredLibrary("a") import "lib.dart" as a; 686 // import "lib.dart" deferred as a;
664 // import "lib2.dart" as a; 687 // import "lib2.dart" as a;
665 // 3. 688 // 3.
666 // import "lib.dart" as a; 689 // import "lib.dart" as a;
667 // @DeferredLibrary("a") import "lib2.dart" as a; 690 // import "lib2.dart" deferred as a;
668 // 4. 691 // 4.
669 // import "lib.dart" as a; 692 // import "lib.dart" as a;
670 // import "lib2.dart" as a; 693 // import "lib2.dart" as a;
671 // We must be able to signal error for case 1, 2, 3, but accept case 4. 694 // We must be able to signal error for case 1, 2, 3, but accept case 4.
672 695
673 // The prefixes that have been used by any imports in this library. 696 // The prefixes that have been used by any imports in this library.
674 Setlet<String> usedPrefixes = new Setlet<String>(); 697 Setlet<String> usedPrefixes = new Setlet<String>();
675 // The last deferred import we saw with a given prefix (if any). 698 // The last deferred import we saw with a given prefix (if any).
676 Map<String, Import> prefixDeferredImport = new Map<String, Import>(); 699 Map<String, Import> prefixDeferredImport = new Map<String, Import>();
677 for (LibraryElement library in compiler.libraries.values) { 700 for (LibraryElement library in compiler.libraries.values) {
(...skipping 13 matching lines...) Expand all
691 Import previousDeferredImport = prefixDeferredImport[prefix]; 714 Import previousDeferredImport = prefixDeferredImport[prefix];
692 bool isDeferred = _isImportDeferred(import); 715 bool isDeferred = _isImportDeferred(import);
693 if (isDeferred) { 716 if (isDeferred) {
694 if (prefix == null) { 717 if (prefix == null) {
695 compiler.reportError(import, 718 compiler.reportError(import,
696 MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX); 719 MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX);
697 } else { 720 } else {
698 prefixDeferredImport[prefix] = import; 721 prefixDeferredImport[prefix] = import;
699 } 722 }
700 splitProgram = true; 723 splitProgram = true;
701 lastDeferred = import.metadata.first; 724 lastDeferred = import;
702 } 725 }
703 if (prefix != null) { 726 if (prefix != null) {
704 if (previousDeferredImport != null || 727 if (previousDeferredImport != null ||
705 (isDeferred && usedPrefixes.contains(prefix))) { 728 (isDeferred && usedPrefixes.contains(prefix))) {
706 Import failingImport = (previousDeferredImport != null) 729 Import failingImport = (previousDeferredImport != null)
707 ? previousDeferredImport 730 ? previousDeferredImport
708 : import; 731 : import;
709 compiler.reportError(failingImport.prefix, 732 compiler.reportError(failingImport.prefix,
710 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX); 733 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX);
711 } 734 }
712 usedPrefixes.add(prefix); 735 usedPrefixes.add(prefix);
713 } 736 }
714 } 737 }
715 }); 738 });
716 } 739 }
717 if (splitProgram && compiler.backend is DartBackend) { 740 if (splitProgram && compiler.backend is DartBackend) {
718 // TODO(sigurdm): Implement deferred loading for dart2dart. 741 // TODO(sigurdm): Implement deferred loading for dart2dart.
719 splitProgram = false; 742 splitProgram = false;
720 compiler.reportInfo( 743 compiler.reportInfo(
721 lastDeferred, 744 lastDeferred,
722 MessageKind.DEFERRED_LIBRARY_DART_2_DART); 745 MessageKind.DEFERRED_LIBRARY_DART_2_DART);
723 } 746 }
724 } 747 }
725 } 748 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698