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

Side by Side Diff: pkg/compiler/lib/src/deferred_load.dart

Issue 1859343004: dartfmt pkg/compiler (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 8 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
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 'common.dart'; 7 import 'common.dart';
8 import 'common/backend_api.dart' show 8 import 'common/backend_api.dart' show Backend;
9 Backend; 9 import 'common/tasks.dart' show CompilerTask;
10 import 'common/tasks.dart' show 10 import 'compiler.dart' show Compiler;
11 CompilerTask; 11 import 'constants/values.dart'
12 import 'compiler.dart' show 12 show
13 Compiler; 13 ConstantValue,
14 import 'constants/values.dart' show 14 ConstructedConstantValue,
15 ConstantValue, 15 DeferredConstantValue,
16 ConstructedConstantValue, 16 StringConstantValue;
17 DeferredConstantValue,
18 StringConstantValue;
19 import 'dart_types.dart'; 17 import 'dart_types.dart';
20 import 'elements/elements.dart' show 18 import 'elements/elements.dart'
21 AccessorElement, 19 show
22 AstElement, 20 AccessorElement,
23 ClassElement, 21 AstElement,
24 Element, 22 ClassElement,
25 ElementKind, 23 Element,
26 Elements, 24 ElementKind,
27 ExportElement, 25 Elements,
28 FunctionElement, 26 ExportElement,
29 ImportElement, 27 FunctionElement,
30 LibraryElement, 28 ImportElement,
31 LocalFunctionElement, 29 LibraryElement,
32 MetadataAnnotation, 30 LocalFunctionElement,
33 PrefixElement, 31 MetadataAnnotation,
34 ScopeContainerElement, 32 PrefixElement,
35 TypedefElement; 33 ScopeContainerElement,
36 import 'js_backend/js_backend.dart' show 34 TypedefElement;
37 JavaScriptBackend; 35 import 'js_backend/js_backend.dart' show JavaScriptBackend;
38 import 'resolution/resolution.dart' show 36 import 'resolution/resolution.dart' show AnalyzableElementX;
39 AnalyzableElementX; 37 import 'resolution/tree_elements.dart' show TreeElements;
40 import 'resolution/tree_elements.dart' show
41 TreeElements;
42 import 'tree/tree.dart' as ast; 38 import 'tree/tree.dart' as ast;
43 import 'tree/tree.dart' show 39 import 'tree/tree.dart'
44 Import, 40 show
45 LibraryTag, 41 Import,
46 LibraryDependency, 42 LibraryTag,
47 LiteralDartString, 43 LibraryDependency,
48 LiteralString, 44 LiteralDartString,
49 NewExpression, 45 LiteralString,
50 Node; 46 NewExpression,
51 import 'universe/use.dart' show 47 Node;
52 DynamicUse, 48 import 'universe/use.dart' show DynamicUse, StaticUse, TypeUse, TypeUseKind;
53 StaticUse, 49 import 'universe/world_impact.dart'
54 TypeUse, 50 show ImpactUseCase, WorldImpact, WorldImpactVisitorImpl;
55 TypeUseKind; 51 import 'util/setlet.dart' show Setlet;
56 import 'universe/world_impact.dart' show
57 ImpactUseCase,
58 WorldImpact,
59 WorldImpactVisitorImpl;
60 import 'util/setlet.dart' show
61 Setlet;
62 import 'util/uri_extras.dart' as uri_extras; 52 import 'util/uri_extras.dart' as uri_extras;
63 import 'util/util.dart' show 53 import 'util/util.dart' show Link, makeUnique;
64 Link, makeUnique;
65 54
66 /// A "hunk" of the program that will be loaded whenever one of its [imports] 55 /// A "hunk" of the program that will be loaded whenever one of its [imports]
67 /// are loaded. 56 /// are loaded.
68 /// 57 ///
69 /// Elements that are only used in one deferred import, is in an OutputUnit with 58 /// Elements that are only used in one deferred import, is in an OutputUnit with
70 /// the deferred import as single element in the [imports] set. 59 /// the deferred import as single element in the [imports] set.
71 /// 60 ///
72 /// Whenever a deferred Element is shared between several deferred imports it is 61 /// Whenever a deferred Element is shared between several deferred imports it is
73 /// in an output unit with those imports in the [imports] Set. 62 /// in an output unit with those imports in the [imports] Set.
74 /// 63 ///
75 /// OutputUnits are equal if their [imports] are equal. 64 /// OutputUnits are equal if their [imports] are equal.
76 class OutputUnit { 65 class OutputUnit {
77 /// The deferred imports that will load this output unit when one of them is 66 /// The deferred imports that will load this output unit when one of them is
78 /// loaded. 67 /// loaded.
79 final Setlet<_DeferredImport> imports = new Setlet<_DeferredImport>(); 68 final Setlet<_DeferredImport> imports = new Setlet<_DeferredImport>();
80 69
81 /// `true` if this output unit is for the main output file. 70 /// `true` if this output unit is for the main output file.
82 final bool isMainOutput; 71 final bool isMainOutput;
83 72
84 /// A unique name representing this [OutputUnit]. 73 /// A unique name representing this [OutputUnit].
85 String name; 74 String name;
86 75
87 OutputUnit({this.isMainOutput: false}); 76 OutputUnit({this.isMainOutput: false});
88 77
89 String toString() => "OutputUnit($name)"; 78 String toString() => "OutputUnit($name)";
90 79
91 bool operator==(OutputUnit other) { 80 bool operator ==(OutputUnit other) {
92 return imports.length == other.imports.length && 81 return imports.length == other.imports.length &&
93 imports.containsAll(other.imports); 82 imports.containsAll(other.imports);
94 } 83 }
95 84
96 int get hashCode { 85 int get hashCode {
97 int sum = 0; 86 int sum = 0;
98 for (_DeferredImport import in imports) { 87 for (_DeferredImport import in imports) {
99 sum = (sum + import.hashCode) & 0x3FFFFFFF; // Stay in 30 bit range. 88 sum = (sum + import.hashCode) & 0x3FFFFFFF; // Stay in 30 bit range.
100 } 89 }
101 return sum; 90 return sum;
102 } 91 }
103 } 92 }
104 93
105 /// For each deferred import, find elements and constants to be loaded when that 94 /// For each deferred import, find elements and constants to be loaded when that
106 /// import is loaded. Elements that are used by several deferred imports are in 95 /// import is loaded. Elements that are used by several deferred imports are in
107 /// shared OutputUnits. 96 /// shared OutputUnits.
108 class DeferredLoadTask extends CompilerTask { 97 class DeferredLoadTask extends CompilerTask {
109 /// The name of this task. 98 /// The name of this task.
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
222 /// 211 ///
223 /// For example, if we have two deferred libraries `A` and `B` that both 212 /// For example, if we have two deferred libraries `A` and `B` that both
224 /// import a library `C`, then even though elements from `A` and `C` end up in 213 /// import a library `C`, then even though elements from `A` and `C` end up in
225 /// different output units, there is a non-deferred path between `A` and `C`. 214 /// different output units, there is a non-deferred path between `A` and `C`.
226 bool hasOnlyNonDeferredImportPaths(Element from, Element to) { 215 bool hasOnlyNonDeferredImportPaths(Element from, Element to) {
227 OutputUnit outputUnitFrom = outputUnitForElement(from); 216 OutputUnit outputUnitFrom = outputUnitForElement(from);
228 OutputUnit outputUnitTo = outputUnitForElement(to); 217 OutputUnit outputUnitTo = outputUnitForElement(to);
229 return outputUnitTo.imports.containsAll(outputUnitFrom.imports); 218 return outputUnitTo.imports.containsAll(outputUnitFrom.imports);
230 } 219 }
231 220
232 void registerConstantDeferredUse(DeferredConstantValue constant, 221 void registerConstantDeferredUse(
233 PrefixElement prefix) { 222 DeferredConstantValue constant, PrefixElement prefix) {
234 OutputUnit outputUnit = new OutputUnit(); 223 OutputUnit outputUnit = new OutputUnit();
235 outputUnit.imports.add(new _DeclaredDeferredImport(prefix.deferredImport)); 224 outputUnit.imports.add(new _DeclaredDeferredImport(prefix.deferredImport));
236 _constantToOutputUnit[constant] = outputUnit; 225 _constantToOutputUnit[constant] = outputUnit;
237 } 226 }
238 227
239 /// Answers whether [element] is explicitly deferred when referred to from 228 /// Answers whether [element] is explicitly deferred when referred to from
240 /// [library]. 229 /// [library].
241 bool _isExplicitlyDeferred(Element element, LibraryElement library) { 230 bool _isExplicitlyDeferred(Element element, LibraryElement library) {
242 Iterable<ImportElement> imports = _getImports(element, library); 231 Iterable<ImportElement> imports = _getImports(element, library);
243 // If the element is not imported explicitly, it is implicitly imported 232 // If the element is not imported explicitly, it is implicitly imported
(...skipping 14 matching lines...) Expand all
258 if (element.isAccessor) { 247 if (element.isAccessor) {
259 element = (element as AccessorElement).abstractField; 248 element = (element as AccessorElement).abstractField;
260 } 249 }
261 return library.getImportsFor(element); 250 return library.getImportsFor(element);
262 } 251 }
263 252
264 /// Finds all elements and constants that [element] depends directly on. 253 /// Finds all elements and constants that [element] depends directly on.
265 /// (not the transitive closure.) 254 /// (not the transitive closure.)
266 /// 255 ///
267 /// Adds the results to [elements] and [constants]. 256 /// Adds the results to [elements] and [constants].
268 void _collectAllElementsAndConstantsResolvedFrom( 257 void _collectAllElementsAndConstantsResolvedFrom(Element element,
269 Element element, 258 Set<Element> elements, Set<ConstantValue> constants, isMirrorUsage) {
270 Set<Element> elements,
271 Set<ConstantValue> constants,
272 isMirrorUsage) {
273
274 if (element.isMalformed) { 259 if (element.isMalformed) {
275 // Malformed elements are ignored. 260 // Malformed elements are ignored.
276 return; 261 return;
277 } 262 }
278 263
279 /// Recursively collects all the dependencies of [type]. 264 /// Recursively collects all the dependencies of [type].
280 void collectTypeDependencies(DartType type) { 265 void collectTypeDependencies(DartType type) {
281 // TODO(het): we would like to separate out types that are only needed for 266 // TODO(het): we would like to separate out types that are only needed for
282 // rti from types that are needed for their members. 267 // rti from types that are needed for their members.
283 if (type is GenericType) { 268 if (type is GenericType) {
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 AstElement analyzableElement = element.analyzableElement.declaration; 305 AstElement analyzableElement = element.analyzableElement.declaration;
321 if (!compiler.enqueuer.resolution.hasBeenProcessed(analyzableElement)) { 306 if (!compiler.enqueuer.resolution.hasBeenProcessed(analyzableElement)) {
322 return; 307 return;
323 } 308 }
324 309
325 WorldImpact worldImpact = 310 WorldImpact worldImpact =
326 compiler.resolution.getWorldImpact(analyzableElement); 311 compiler.resolution.getWorldImpact(analyzableElement);
327 compiler.impactStrategy.visitImpact( 312 compiler.impactStrategy.visitImpact(
328 analyzableElement, 313 analyzableElement,
329 worldImpact, 314 worldImpact,
330 new WorldImpactVisitorImpl( 315 new WorldImpactVisitorImpl(visitStaticUse: (StaticUse staticUse) {
331 visitStaticUse: (StaticUse staticUse) { 316 elements.add(staticUse.element);
332 elements.add(staticUse.element); 317 }, visitTypeUse: (TypeUse typeUse) {
333 }, 318 DartType type = typeUse.type;
334 visitTypeUse: (TypeUse typeUse) { 319 switch (typeUse.kind) {
335 DartType type = typeUse.type; 320 case TypeUseKind.TYPE_LITERAL:
336 switch (typeUse.kind) { 321 if (type.isTypedef || type.isInterfaceType) {
337 case TypeUseKind.TYPE_LITERAL: 322 elements.add(type.element);
338 if (type.isTypedef || type.isInterfaceType) {
339 elements.add(type.element);
340 }
341 break;
342 case TypeUseKind.INSTANTIATION:
343 case TypeUseKind.IS_CHECK:
344 case TypeUseKind.AS_CAST:
345 case TypeUseKind.CATCH_TYPE:
346 collectTypeDependencies(type);
347 break;
348 case TypeUseKind.CHECKED_MODE_CHECK:
349 if (compiler.options.enableTypeAssertions) {
350 collectTypeDependencies(type);
351 }
352 break;
353 } 323 }
354 }), 324 break;
355 IMPACT_USE); 325 case TypeUseKind.INSTANTIATION:
326 case TypeUseKind.IS_CHECK:
327 case TypeUseKind.AS_CAST:
328 case TypeUseKind.CATCH_TYPE:
329 collectTypeDependencies(type);
330 break;
331 case TypeUseKind.CHECKED_MODE_CHECK:
332 if (compiler.options.enableTypeAssertions) {
333 collectTypeDependencies(type);
334 }
335 break;
336 }
337 }),
338 IMPACT_USE);
356 339
357 TreeElements treeElements = analyzableElement.resolvedAst.elements; 340 TreeElements treeElements = analyzableElement.resolvedAst.elements;
358 assert(treeElements != null); 341 assert(treeElements != null);
359 342
360 treeElements.forEachConstantNode((Node node, _) { 343 treeElements.forEachConstantNode((Node node, _) {
361 // Explicitly depend on the backend constants. 344 // Explicitly depend on the backend constants.
362 ConstantValue value = 345 ConstantValue value =
363 backend.constants.getConstantValueForNode(node, treeElements); 346 backend.constants.getConstantValueForNode(node, treeElements);
364 if (value != null) { 347 if (value != null) {
365 // TODO(johnniwinther): Assert that all constants have values when 348 // TODO(johnniwinther): Assert that all constants have values when
(...skipping 30 matching lines...) Expand all
396 ClassElement cls = element.declaration; 379 ClassElement cls = element.declaration;
397 cls.forEachLocalMember(addLiveInstanceMember); 380 cls.forEachLocalMember(addLiveInstanceMember);
398 if (cls.implementation != cls) { 381 if (cls.implementation != cls) {
399 // TODO(ahe): Why doesn't ClassElement.forEachLocalMember do this? 382 // TODO(ahe): Why doesn't ClassElement.forEachLocalMember do this?
400 cls.implementation.forEachLocalMember(addLiveInstanceMember); 383 cls.implementation.forEachLocalMember(addLiveInstanceMember);
401 } 384 }
402 for (var type in cls.implementation.allSupertypes) { 385 for (var type in cls.implementation.allSupertypes) {
403 elements.add(type.element.implementation); 386 elements.add(type.element.implementation);
404 } 387 }
405 elements.add(cls.implementation); 388 elements.add(cls.implementation);
406 } else if (Elements.isStaticOrTopLevel(element) || 389 } else if (Elements.isStaticOrTopLevel(element) || element.isConstructor) {
407 element.isConstructor) {
408 elements.add(element); 390 elements.add(element);
409 collectDependencies(element); 391 collectDependencies(element);
410 } 392 }
411 if (element.isGenerativeConstructor) { 393 if (element.isGenerativeConstructor) {
412 // When instantiating a class, we record a reference to the 394 // When instantiating a class, we record a reference to the
413 // constructor, not the class itself. We must add all the 395 // constructor, not the class itself. We must add all the
414 // instance members of the constructor's class. 396 // instance members of the constructor's class.
415 ClassElement implementation = 397 ClassElement implementation = element.enclosingClass.implementation;
416 element.enclosingClass.implementation;
417 _collectAllElementsAndConstantsResolvedFrom( 398 _collectAllElementsAndConstantsResolvedFrom(
418 implementation, elements, constants, isMirrorUsage); 399 implementation, elements, constants, isMirrorUsage);
419 } 400 }
420 401
421 // Other elements, in particular instance members, are ignored as 402 // Other elements, in particular instance members, are ignored as
422 // they are processed as part of the class. 403 // they are processed as part of the class.
423 } 404 }
424 405
425 /// Returns the transitive closure of all libraries that are imported 406 /// Returns the transitive closure of all libraries that are imported
426 /// from root without DeferredLibrary annotations. 407 /// from root without DeferredLibrary annotations.
(...skipping 23 matching lines...) Expand all
450 if (library.isPatched) { 431 if (library.isPatched) {
451 iterateTags(library.implementation); 432 iterateTags(library.implementation);
452 } 433 }
453 } 434 }
454 traverseLibrary(root); 435 traverseLibrary(root);
455 result.add(compiler.coreLibrary); 436 result.add(compiler.coreLibrary);
456 return result; 437 return result;
457 } 438 }
458 439
459 /// Add all dependencies of [constant] to the mapping of [import]. 440 /// Add all dependencies of [constant] to the mapping of [import].
460 void _mapConstantDependencies(ConstantValue constant, 441 void _mapConstantDependencies(
461 _DeferredImport import) { 442 ConstantValue constant, _DeferredImport import) {
462 Set<ConstantValue> constants = _constantsDeferredBy.putIfAbsent(import, 443 Set<ConstantValue> constants = _constantsDeferredBy.putIfAbsent(
463 () => new Set<ConstantValue>()); 444 import, () => new Set<ConstantValue>());
464 if (constants.contains(constant)) return; 445 if (constants.contains(constant)) return;
465 constants.add(constant); 446 constants.add(constant);
466 if (constant is ConstructedConstantValue) { 447 if (constant is ConstructedConstantValue) {
467 _mapDependencies(element: constant.type.element, import: import); 448 _mapDependencies(element: constant.type.element, import: import);
468 } 449 }
469 constant.getDependencies().forEach((ConstantValue dependency) { 450 constant.getDependencies().forEach((ConstantValue dependency) {
470 _mapConstantDependencies(dependency, import); 451 _mapConstantDependencies(dependency, import);
471 }); 452 });
472 } 453 }
473 454
474 /// Recursively traverses the graph of dependencies from one of [element] 455 /// Recursively traverses the graph of dependencies from one of [element]
475 /// or [constant], mapping deferred imports to each dependency it needs in the 456 /// or [constant], mapping deferred imports to each dependency it needs in the
476 /// sets [_importedDeferredBy] and [_constantsDeferredBy]. 457 /// sets [_importedDeferredBy] and [_constantsDeferredBy].
477 /// Only one of [element] and [constant] should be given. 458 /// Only one of [element] and [constant] should be given.
478 void _mapDependencies({Element element, 459 void _mapDependencies(
479 _DeferredImport import, 460 {Element element, _DeferredImport import, isMirrorUsage: false}) {
480 isMirrorUsage: false}) { 461 Set<Element> elements =
481 462 _importedDeferredBy.putIfAbsent(import, () => new Set<Element>());
482 Set<Element> elements = _importedDeferredBy.putIfAbsent(import,
483 () => new Set<Element>());
484
485 463
486 Set<Element> dependentElements = new Set<Element>(); 464 Set<Element> dependentElements = new Set<Element>();
487 Set<ConstantValue> dependentConstants = new Set<ConstantValue>(); 465 Set<ConstantValue> dependentConstants = new Set<ConstantValue>();
488 466
489 LibraryElement library; 467 LibraryElement library;
490 468
491 if (element != null) { 469 if (element != null) {
492 // Only process elements once, unless we are doing dependencies due to 470 // Only process elements once, unless we are doing dependencies due to
493 // mirrors, which are added in additional traversals. 471 // mirrors, which are added in additional traversals.
494 if (!isMirrorUsage && elements.contains(element)) return; 472 if (!isMirrorUsage && elements.contains(element)) return;
495 // Anything used directly by main will be loaded from the start 473 // Anything used directly by main will be loaded from the start
496 // We do not need to traverse it again. 474 // We do not need to traverse it again.
497 if (import != _fakeMainImport && _mainElements.contains(element)) return; 475 if (import != _fakeMainImport && _mainElements.contains(element)) return;
498 elements.add(element); 476 elements.add(element);
499 477
500
501 // This call can modify [dependentElements] and [dependentConstants]. 478 // This call can modify [dependentElements] and [dependentConstants].
502 _collectAllElementsAndConstantsResolvedFrom( 479 _collectAllElementsAndConstantsResolvedFrom(
503 element, dependentElements, dependentConstants, isMirrorUsage); 480 element, dependentElements, dependentConstants, isMirrorUsage);
504 481
505 library = element.library; 482 library = element.library;
506 } 483 }
507 484
508 for (Element dependency in dependentElements) { 485 for (Element dependency in dependentElements) {
509 if (_isExplicitlyDeferred(dependency, library)) { 486 if (_isExplicitlyDeferred(dependency, library)) {
510 for (ImportElement deferredImport in _getImports(dependency, library)) { 487 for (ImportElement deferredImport in _getImports(dependency, library)) {
511 _mapDependencies(element: dependency, 488 _mapDependencies(
489 element: dependency,
512 import: new _DeclaredDeferredImport(deferredImport)); 490 import: new _DeclaredDeferredImport(deferredImport));
513 } 491 }
514 } else { 492 } else {
515 _mapDependencies(element: dependency, import: import); 493 _mapDependencies(element: dependency, import: import);
516 } 494 }
517 } 495 }
518 496
519 for (ConstantValue dependency in dependentConstants) { 497 for (ConstantValue dependency in dependentConstants) {
520 if (dependency is DeferredConstantValue) { 498 if (dependency is DeferredConstantValue) {
521 _mapConstantDependencies(dependency, 499 _mapConstantDependencies(dependency,
522 new _DeclaredDeferredImport(dependency.prefix.deferredImport)); 500 new _DeclaredDeferredImport(dependency.prefix.deferredImport));
523 } else { 501 } else {
524 _mapConstantDependencies(dependency, import); 502 _mapConstantDependencies(dependency, import);
525 } 503 }
526 } 504 }
527 } 505 }
528 506
529 /// Adds extra dependencies coming from mirror usage. 507 /// Adds extra dependencies coming from mirror usage.
530 /// 508 ///
531 /// The elements are added with [_mapDependencies]. 509 /// The elements are added with [_mapDependencies].
532 void _addMirrorElements() { 510 void _addMirrorElements() {
533 void mapDependenciesIfResolved(Element element, 511 void mapDependenciesIfResolved(
534 _DeferredImport deferredImport) { 512 Element element, _DeferredImport deferredImport) {
535 // If an element is the target of a MirrorsUsed annotation but never used 513 // If an element is the target of a MirrorsUsed annotation but never used
536 // It will not be resolved, and we should not call isNeededForReflection. 514 // It will not be resolved, and we should not call isNeededForReflection.
537 // TODO(sigurdm): Unresolved elements should just answer false when 515 // TODO(sigurdm): Unresolved elements should just answer false when
538 // asked isNeededForReflection. Instead an internal error is triggered. 516 // asked isNeededForReflection. Instead an internal error is triggered.
539 // So we have to filter them out here. 517 // So we have to filter them out here.
540 if (element is AnalyzableElementX && !element.hasTreeElements) return; 518 if (element is AnalyzableElementX && !element.hasTreeElements) return;
541 if (compiler.backend.isAccessibleByReflection(element)) { 519 if (compiler.backend.isAccessibleByReflection(element)) {
542 _mapDependencies( 520 _mapDependencies(
543 element: element, import: deferredImport, isMirrorUsage: true); 521 element: element, import: deferredImport, isMirrorUsage: true);
544 } 522 }
(...skipping 16 matching lines...) Expand all
561 } 539 }
562 } 540 }
563 541
564 processMetadata(library); 542 processMetadata(library);
565 library.imports.forEach(processMetadata); 543 library.imports.forEach(processMetadata);
566 library.exports.forEach(processMetadata); 544 library.exports.forEach(processMetadata);
567 } 545 }
568 546
569 for (_DeferredImport deferredImport in _allDeferredImports.keys) { 547 for (_DeferredImport deferredImport in _allDeferredImports.keys) {
570 LibraryElement deferredLibrary = _allDeferredImports[deferredImport]; 548 LibraryElement deferredLibrary = _allDeferredImports[deferredImport];
571 for (LibraryElement library in 549 for (LibraryElement library
572 _nonDeferredReachableLibraries(deferredLibrary)) { 550 in _nonDeferredReachableLibraries(deferredLibrary)) {
573 handleLibrary(library, deferredImport); 551 handleLibrary(library, deferredImport);
574 } 552 }
575 } 553 }
576 } 554 }
577 555
578 /// Computes a unique string for the name field for each outputUnit. 556 /// Computes a unique string for the name field for each outputUnit.
579 /// 557 ///
580 /// Also sets up the [hunksToLoad] mapping. 558 /// Also sets up the [hunksToLoad] mapping.
581 void _assignNamesToOutputUnits(Set<OutputUnit> allOutputUnits) { 559 void _assignNamesToOutputUnits(Set<OutputUnit> allOutputUnits) {
582 Set<String> usedImportNames = new Set<String>(); 560 Set<String> usedImportNames = new Set<String>();
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
635 allOutputUnits.add(mainOutputUnit); 613 allOutputUnits.add(mainOutputUnit);
636 return; 614 return;
637 } 615 }
638 if (main == null) return; 616 if (main == null) return;
639 LibraryElement mainLibrary = main.library; 617 LibraryElement mainLibrary = main.library;
640 _importedDeferredBy = new Map<_DeferredImport, Set<Element>>(); 618 _importedDeferredBy = new Map<_DeferredImport, Set<Element>>();
641 _constantsDeferredBy = new Map<_DeferredImport, Set<ConstantValue>>(); 619 _constantsDeferredBy = new Map<_DeferredImport, Set<ConstantValue>>();
642 _importedDeferredBy[_fakeMainImport] = _mainElements; 620 _importedDeferredBy[_fakeMainImport] = _mainElements;
643 621
644 measureElement(mainLibrary, () { 622 measureElement(mainLibrary, () {
645
646 // Starting from main, traverse the program and find all dependencies. 623 // Starting from main, traverse the program and find all dependencies.
647 _mapDependencies(element: compiler.mainFunction, import: _fakeMainImport); 624 _mapDependencies(element: compiler.mainFunction, import: _fakeMainImport);
648 625
649 // Also add "global" dependencies to the main OutputUnit. These are 626 // Also add "global" dependencies to the main OutputUnit. These are
650 // things that the backend needs but cannot associate with a particular 627 // things that the backend needs but cannot associate with a particular
651 // element, for example, startRootIsolate. This set also contains 628 // element, for example, startRootIsolate. This set also contains
652 // elements for which we lack precise information. 629 // elements for which we lack precise information.
653 for (Element element in compiler.globalDependencies.otherDependencies) { 630 for (Element element in compiler.globalDependencies.otherDependencies) {
654 _mapDependencies(element: element, import: _fakeMainImport); 631 _mapDependencies(element: element, import: _fakeMainImport);
655 } 632 }
(...skipping 13 matching lines...) Expand all
669 // all deferred imports mapped to this element. Same for constants. 646 // all deferred imports mapped to this element. Same for constants.
670 for (_DeferredImport import in _importedDeferredBy.keys) { 647 for (_DeferredImport import in _importedDeferredBy.keys) {
671 for (Element element in _importedDeferredBy[import]) { 648 for (Element element in _importedDeferredBy[import]) {
672 // Only one file should be loaded when the program starts, so make 649 // Only one file should be loaded when the program starts, so make
673 // sure that only one OutputUnit is created for [fakeMainImport]. 650 // sure that only one OutputUnit is created for [fakeMainImport].
674 if (import == _fakeMainImport) { 651 if (import == _fakeMainImport) {
675 elementToOutputUnitBuilder[element] = mainOutputUnit; 652 elementToOutputUnitBuilder[element] = mainOutputUnit;
676 } else { 653 } else {
677 elementToOutputUnitBuilder 654 elementToOutputUnitBuilder
678 .putIfAbsent(element, () => new OutputUnit()) 655 .putIfAbsent(element, () => new OutputUnit())
679 .imports.add(import); 656 .imports
657 .add(import);
680 } 658 }
681 } 659 }
682 } 660 }
683 for (_DeferredImport import in _constantsDeferredBy.keys) { 661 for (_DeferredImport import in _constantsDeferredBy.keys) {
684 for (ConstantValue constant in _constantsDeferredBy[import]) { 662 for (ConstantValue constant in _constantsDeferredBy[import]) {
685 // Only one file should be loaded when the program starts, so make 663 // Only one file should be loaded when the program starts, so make
686 // sure that only one OutputUnit is created for [fakeMainImport]. 664 // sure that only one OutputUnit is created for [fakeMainImport].
687 if (import == _fakeMainImport) { 665 if (import == _fakeMainImport) {
688 constantToOutputUnitBuilder[constant] = mainOutputUnit; 666 constantToOutputUnitBuilder[constant] = mainOutputUnit;
689 } else { 667 } else {
690 constantToOutputUnitBuilder 668 constantToOutputUnitBuilder
691 .putIfAbsent(constant, () => new OutputUnit()) 669 .putIfAbsent(constant, () => new OutputUnit())
692 .imports.add(import); 670 .imports
671 .add(import);
693 } 672 }
694 } 673 }
695 } 674 }
696 675
697 // Release maps; 676 // Release maps;
698 _importedDeferredBy = null; 677 _importedDeferredBy = null;
699 _constantsDeferredBy = null; 678 _constantsDeferredBy = null;
700 679
701 // Find all the output units elements/constants have been mapped to, and 680 // Find all the output units elements/constants have been mapped to, and
702 // canonicalize them. 681 // canonicalize them.
703 elementToOutputUnitBuilder.forEach( 682 elementToOutputUnitBuilder
704 (Element element, OutputUnit outputUnit) { 683 .forEach((Element element, OutputUnit outputUnit) {
705 OutputUnit representative = allOutputUnits.lookup(outputUnit); 684 OutputUnit representative = allOutputUnits.lookup(outputUnit);
706 if (representative == null) { 685 if (representative == null) {
707 representative = outputUnit; 686 representative = outputUnit;
708 allOutputUnits.add(representative); 687 allOutputUnits.add(representative);
709 } 688 }
710 _elementToOutputUnit[element] = representative; 689 _elementToOutputUnit[element] = representative;
711 }); 690 });
712 constantToOutputUnitBuilder.forEach( 691 constantToOutputUnitBuilder
713 (ConstantValue constant, OutputUnit outputUnit) { 692 .forEach((ConstantValue constant, OutputUnit outputUnit) {
714 OutputUnit representative = allOutputUnits.lookup(outputUnit); 693 OutputUnit representative = allOutputUnits.lookup(outputUnit);
715 if (representative == null) { 694 if (representative == null) {
716 representative = outputUnit; 695 representative = outputUnit;
717 allOutputUnits.add(representative); 696 allOutputUnits.add(representative);
718 } 697 }
719 _constantToOutputUnit[constant] = representative; 698 _constantToOutputUnit[constant] = representative;
720 }); 699 });
721 700
722 // Generate a unique name for each OutputUnit. 701 // Generate a unique name for each OutputUnit.
723 _assignNamesToOutputUnits(allOutputUnits); 702 _assignNamesToOutputUnits(allOutputUnits);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
761 for (ImportElement import in library.imports) { 740 for (ImportElement import in library.imports) {
762 /// Give an error if the old annotation-based syntax has been used. 741 /// Give an error if the old annotation-based syntax has been used.
763 List<MetadataAnnotation> metadataList = import.metadata; 742 List<MetadataAnnotation> metadataList = import.metadata;
764 if (metadataList != null) { 743 if (metadataList != null) {
765 for (MetadataAnnotation metadata in metadataList) { 744 for (MetadataAnnotation metadata in metadataList) {
766 metadata.ensureResolved(compiler.resolution); 745 metadata.ensureResolved(compiler.resolution);
767 ConstantValue value = 746 ConstantValue value =
768 compiler.constants.getConstantValue(metadata.constant); 747 compiler.constants.getConstantValue(metadata.constant);
769 Element element = value.getType(compiler.coreTypes).element; 748 Element element = value.getType(compiler.coreTypes).element;
770 if (element == deferredLibraryClass) { 749 if (element == deferredLibraryClass) {
771 reporter.reportErrorMessage( 750 reporter.reportErrorMessage(
772 import, MessageKind.DEFERRED_OLD_SYNTAX); 751 import, MessageKind.DEFERRED_OLD_SYNTAX);
773 } 752 }
774 } 753 }
775 } 754 }
776 755
777 String prefix = (import.prefix != null) 756 String prefix = (import.prefix != null) ? import.prefix.name : null;
778 ? import.prefix.name
779 : null;
780 // The last import we saw with the same prefix. 757 // The last import we saw with the same prefix.
781 ImportElement previousDeferredImport = prefixDeferredImport[prefix]; 758 ImportElement previousDeferredImport = prefixDeferredImport[prefix];
782 if (import.isDeferred) { 759 if (import.isDeferred) {
783 _DeferredImport key = new _DeclaredDeferredImport(import); 760 _DeferredImport key = new _DeclaredDeferredImport(import);
784 LibraryElement importedLibrary = import.importedLibrary; 761 LibraryElement importedLibrary = import.importedLibrary;
785 _allDeferredImports[key] = importedLibrary; 762 _allDeferredImports[key] = importedLibrary;
786 763
787 if (prefix == null) { 764 if (prefix == null) {
788 reporter.reportErrorMessage( 765 reporter.reportErrorMessage(
789 import, 766 import, MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX);
790 MessageKind.DEFERRED_LIBRARY_WITHOUT_PREFIX);
791 } else { 767 } else {
792 prefixDeferredImport[prefix] = import; 768 prefixDeferredImport[prefix] = import;
793 _deferredImportDescriptions[key] = 769 _deferredImportDescriptions[key] =
794 new ImportDescription(import, library, compiler); 770 new ImportDescription(import, library, compiler);
795 } 771 }
796 isProgramSplit = true; 772 isProgramSplit = true;
797 lastDeferred = import; 773 lastDeferred = import;
798 } 774 }
799 if (prefix != null) { 775 if (prefix != null) {
800 if (previousDeferredImport != null || 776 if (previousDeferredImport != null ||
801 (import.isDeferred && usedPrefixes.contains(prefix))) { 777 (import.isDeferred && usedPrefixes.contains(prefix))) {
802 ImportElement failingImport = (previousDeferredImport != null) 778 ImportElement failingImport = (previousDeferredImport != null)
803 ? previousDeferredImport 779 ? previousDeferredImport
804 : import; 780 : import;
805 reporter.reportErrorMessage( 781 reporter.reportErrorMessage(failingImport.prefix,
806 failingImport.prefix,
807 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX); 782 MessageKind.DEFERRED_LIBRARY_DUPLICATE_PREFIX);
808 } 783 }
809 usedPrefixes.add(prefix); 784 usedPrefixes.add(prefix);
810 } 785 }
811 } 786 }
812 }); 787 });
813 } 788 }
814 if (isProgramSplit) { 789 if (isProgramSplit) {
815 isProgramSplit = compiler.backend.enableDeferredLoadingIfSupported( 790 isProgramSplit = compiler.backend.enableDeferredLoadingIfSupported(
816 lastDeferred, compiler.globalDependencies); 791 lastDeferred, compiler.globalDependencies);
817 } 792 }
818 } 793 }
819 794
820 /// If [send] is a static send with a deferred element, returns the 795 /// If [send] is a static send with a deferred element, returns the
821 /// [PrefixElement] that the first prefix of the send resolves to. 796 /// [PrefixElement] that the first prefix of the send resolves to.
822 /// Otherwise returns null. 797 /// Otherwise returns null.
823 /// 798 ///
824 /// Precondition: send must be static. 799 /// Precondition: send must be static.
825 /// 800 ///
826 /// Example: 801 /// Example:
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
886 /// - <prefix> is the `as` prefix used for a given deferred import. 861 /// - <prefix> is the `as` prefix used for a given deferred import.
887 /// - <list of files> is a list of the filenames the must be loaded when that 862 /// - <list of files> is a list of the filenames the must be loaded when that
888 /// import is loaded. 863 /// import is loaded.
889 Map<String, Map<String, dynamic>> computeDeferredMap() { 864 Map<String, Map<String, dynamic>> computeDeferredMap() {
890 JavaScriptBackend backend = compiler.backend; 865 JavaScriptBackend backend = compiler.backend;
891 Map<String, Map<String, dynamic>> mapping = 866 Map<String, Map<String, dynamic>> mapping =
892 new Map<String, Map<String, dynamic>>(); 867 new Map<String, Map<String, dynamic>>();
893 _deferredImportDescriptions.keys.forEach((_DeferredImport import) { 868 _deferredImportDescriptions.keys.forEach((_DeferredImport import) {
894 List<OutputUnit> outputUnits = hunksToLoad[importDeferName[import]]; 869 List<OutputUnit> outputUnits = hunksToLoad[importDeferName[import]];
895 ImportDescription description = _deferredImportDescriptions[import]; 870 ImportDescription description = _deferredImportDescriptions[import];
896 Map<String, dynamic> libraryMap = 871 Map<String, dynamic> libraryMap = mapping.putIfAbsent(
897 mapping.putIfAbsent(description.importingUri, 872 description.importingUri,
898 () => <String, dynamic>{"name": description.importingLibraryName, 873 () => <String, dynamic>{
899 "imports": <String, List<String>>{}}); 874 "name": description.importingLibraryName,
875 "imports": <String, List<String>>{}
876 });
900 877
901 libraryMap["imports"][importDeferName[import]] = outputUnits.map( 878 libraryMap["imports"][importDeferName[import]] =
902 (OutputUnit outputUnit) { 879 outputUnits.map((OutputUnit outputUnit) {
903 return backend.deferredPartFileName(outputUnit.name); 880 return backend.deferredPartFileName(outputUnit.name);
904 }).toList(); 881 }).toList();
905 }); 882 });
906 return mapping; 883 return mapping;
907 } 884 }
908 885
909 /// Creates a textual representation of the output unit content. 886 /// Creates a textual representation of the output unit content.
910 String dump() { 887 String dump() {
911 Map<OutputUnit, List<String>> elementMap = <OutputUnit, List<String>>{}; 888 Map<OutputUnit, List<String>> elementMap = <OutputUnit, List<String>>{};
912 Map<OutputUnit, List<String>> constantMap = 889 Map<OutputUnit, List<String>> constantMap = <OutputUnit, List<String>>{};
913 <OutputUnit, List<String>>{};
914 _elementToOutputUnit.forEach((Element element, OutputUnit output) { 890 _elementToOutputUnit.forEach((Element element, OutputUnit output) {
915 elementMap.putIfAbsent(output, () => <String>[]).add('$element'); 891 elementMap.putIfAbsent(output, () => <String>[]).add('$element');
916 }); 892 });
917 _constantToOutputUnit.forEach((ConstantValue value, OutputUnit output) { 893 _constantToOutputUnit.forEach((ConstantValue value, OutputUnit output) {
918 constantMap.putIfAbsent(output, () => <String>[]) 894 constantMap
895 .putIfAbsent(output, () => <String>[])
919 .add(value.toStructuredString()); 896 .add(value.toStructuredString());
920 }); 897 });
921 898
922 StringBuffer sb = new StringBuffer(); 899 StringBuffer sb = new StringBuffer();
923 for (OutputUnit outputUnit in allOutputUnits) { 900 for (OutputUnit outputUnit in allOutputUnits) {
924 sb.write(outputUnit.name); 901 sb.write(outputUnit.name);
925 List<String> elements = elementMap[outputUnit]; 902 List<String> elements = elementMap[outputUnit];
926 if (elements != null) { 903 if (elements != null) {
927 sb.write('\n elements:'); 904 sb.write('\n elements:');
928 for (String element in elements..sort()) { 905 for (String element in elements..sort()) {
929 sb.write('\n $element'); 906 sb.write('\n $element');
930 } 907 }
931 } 908 }
932 List<String> constants = constantMap[outputUnit]; 909 List<String> constants = constantMap[outputUnit];
933 if (constants != null) { 910 if (constants != null) {
934 sb.write('\n constants:'); 911 sb.write('\n constants:');
935 for (String value in constants..sort()) { 912 for (String value in constants..sort()) {
936 sb.write('\n $value'); 913 sb.write('\n $value');
937 } 914 }
938 } 915 }
939 } 916 }
940 return sb.toString(); 917 return sb.toString();
941 } 918 }
942
943 } 919 }
944 920
945 class ImportDescription { 921 class ImportDescription {
946 /// Relative uri to the importing library. 922 /// Relative uri to the importing library.
947 final String importingUri; 923 final String importingUri;
924
948 /// The prefix this import is imported as. 925 /// The prefix this import is imported as.
949 final String prefix; 926 final String prefix;
950 final LibraryElement _importingLibrary; 927 final LibraryElement _importingLibrary;
951 928
952 ImportDescription(ImportElement import, 929 ImportDescription(
953 LibraryElement importingLibrary, 930 ImportElement import, LibraryElement importingLibrary, Compiler compiler)
954 Compiler compiler) 931 : importingUri = uri_extras.relativize(compiler.mainApp.canonicalUri,
955 : importingUri = uri_extras.relativize( 932 importingLibrary.canonicalUri, false),
956 compiler.mainApp.canonicalUri,
957 importingLibrary.canonicalUri, false),
958 prefix = import.prefix.name, 933 prefix = import.prefix.name,
959 _importingLibrary = importingLibrary; 934 _importingLibrary = importingLibrary;
960 935
961 String get importingLibraryName { 936 String get importingLibraryName {
962 return _importingLibrary.hasLibraryName 937 return _importingLibrary.hasLibraryName
963 ? _importingLibrary.libraryName : "<unnamed>"; 938 ? _importingLibrary.libraryName
939 : "<unnamed>";
964 } 940 }
965 } 941 }
966 942
967 /// A node in the deferred import graph. 943 /// A node in the deferred import graph.
968 /// 944 ///
969 /// This class serves as the root node; the 'import' of the main library. 945 /// This class serves as the root node; the 'import' of the main library.
970 class _DeferredImport { 946 class _DeferredImport {
971 const _DeferredImport(); 947 const _DeferredImport();
972 948
973 /// Computes a suggestive name for this import. 949 /// Computes a suggestive name for this import.
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after
1012 return result; 988 return result;
1013 } 989 }
1014 990
1015 bool operator ==(other) { 991 bool operator ==(other) {
1016 if (other is! _DeclaredDeferredImport) return false; 992 if (other is! _DeclaredDeferredImport) return false;
1017 return declaration == other.declaration; 993 return declaration == other.declaration;
1018 } 994 }
1019 995
1020 int get hashCode => declaration.hashCode * 17; 996 int get hashCode => declaration.hashCode * 17;
1021 } 997 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/dart_types.dart ('k') | pkg/compiler/lib/src/diagnostics/diagnostic_listener.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698