| OLD | NEW |
| 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, |
| (...skipping 276 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 return library.getImportsFor(element); | 287 return library.getImportsFor(element); |
| 288 } | 288 } |
| 289 | 289 |
| 290 /// Finds all elements and constants that [element] depends directly on. | 290 /// Finds all elements and constants that [element] depends directly on. |
| 291 /// (not the transitive closure.) | 291 /// (not the transitive closure.) |
| 292 /// | 292 /// |
| 293 /// Adds the results to [elements] and [constants]. | 293 /// Adds the results to [elements] and [constants]. |
| 294 void _collectAllElementsAndConstantsResolvedFrom( | 294 void _collectAllElementsAndConstantsResolvedFrom( |
| 295 Element element, | 295 Element element, |
| 296 Set<Element> elements, | 296 Set<Element> elements, |
| 297 Set<Constant> constants) { | 297 Set<Constant> constants, |
| 298 isMirrorUsage) { |
| 298 | 299 |
| 299 /// Recursively add the constant and its dependencies to [constants]. | 300 /// Recursively add the constant and its dependencies to [constants]. |
| 300 void addConstants(Constant constant) { | 301 void addConstants(Constant constant) { |
| 301 if (constants.contains(constant)) return; | 302 if (constants.contains(constant)) return; |
| 302 constants.add(constant); | 303 constants.add(constant); |
| 303 if (constant is ConstructedConstant) { | 304 if (constant is ConstructedConstant) { |
| 304 elements.add(constant.type.element); | 305 elements.add(constant.type.element); |
| 305 } | 306 } |
| 306 constant.getDependencies().forEach(addConstants); | 307 constant.getDependencies().forEach(addConstants); |
| 307 } | 308 } |
| (...skipping 29 matching lines...) Expand all Loading... |
| 337 | 338 |
| 338 // TODO(sigurdm): How is metadata on a patch-class handled? | 339 // TODO(sigurdm): How is metadata on a patch-class handled? |
| 339 for (MetadataAnnotation metadata in element.metadata) { | 340 for (MetadataAnnotation metadata in element.metadata) { |
| 340 Constant constant = backend.constants.getConstantForMetadata(metadata); | 341 Constant constant = backend.constants.getConstantForMetadata(metadata); |
| 341 if (constant != null) { | 342 if (constant != null) { |
| 342 addConstants(constant); | 343 addConstants(constant); |
| 343 } | 344 } |
| 344 } | 345 } |
| 345 if (element.isClass) { | 346 if (element.isClass) { |
| 346 // If we see a class, add everything its live instance members refer | 347 // If we see a class, add everything its live instance members refer |
| 347 // to. Static members are not relevant. | 348 // to. Static members are not relevant, unless we are processing |
| 349 // extra dependencies due to mirrors. |
| 348 void addLiveInstanceMember(Element element) { | 350 void addLiveInstanceMember(Element element) { |
| 349 if (!compiler.enqueuer.resolution.isLive(element)) return; | 351 if (!compiler.enqueuer.resolution.isLive(element)) return; |
| 350 if (!element.isInstanceMember) return; | 352 if (!isMirrorUsage && !element.isInstanceMember) return; |
| 351 collectDependencies(element.implementation); | 353 collectDependencies(element.implementation); |
| 352 } | 354 } |
| 353 ClassElement cls = element.declaration; | 355 ClassElement cls = element.declaration; |
| 354 cls.forEachLocalMember(addLiveInstanceMember); | 356 cls.forEachLocalMember(addLiveInstanceMember); |
| 355 if (cls.implementation != cls) { | 357 if (cls.implementation != cls) { |
| 356 // TODO(ahe): Why doesn't ClassElement.forEachLocalMember do this? | 358 // TODO(ahe): Why doesn't ClassElement.forEachLocalMember do this? |
| 357 cls.implementation.forEachLocalMember(addLiveInstanceMember); | 359 cls.implementation.forEachLocalMember(addLiveInstanceMember); |
| 358 } | 360 } |
| 359 for (var type in cls.implementation.allSupertypes) { | 361 for (var type in cls.implementation.allSupertypes) { |
| 360 elements.add(type.element.implementation); | 362 elements.add(type.element.implementation); |
| 361 } | 363 } |
| 362 elements.add(cls.implementation); | 364 elements.add(cls.implementation); |
| 363 } else if (Elements.isStaticOrTopLevel(element) || | 365 } else if (Elements.isStaticOrTopLevel(element) || |
| 364 element.isConstructor) { | 366 element.isConstructor) { |
| 365 collectDependencies(element); | 367 collectDependencies(element); |
| 366 } | 368 } |
| 367 if (element.isGenerativeConstructor) { | 369 if (element.isGenerativeConstructor) { |
| 368 // When instantiating a class, we record a reference to the | 370 // When instantiating a class, we record a reference to the |
| 369 // constructor, not the class itself. We must add all the | 371 // constructor, not the class itself. We must add all the |
| 370 // instance members of the constructor's class. | 372 // instance members of the constructor's class. |
| 371 ClassElement implementation = | 373 ClassElement implementation = |
| 372 element.enclosingClass.implementation; | 374 element.enclosingClass.implementation; |
| 373 _collectAllElementsAndConstantsResolvedFrom( | 375 _collectAllElementsAndConstantsResolvedFrom( |
| 374 implementation, elements, constants); | 376 implementation, elements, constants, isMirrorUsage); |
| 375 } | 377 } |
| 376 | 378 |
| 377 // Other elements, in particular instance members, are ignored as | 379 // Other elements, in particular instance members, are ignored as |
| 378 // they are processed as part of the class. | 380 // they are processed as part of the class. |
| 379 } | 381 } |
| 380 | 382 |
| 381 /// Returns the transitive closure of all libraries that are imported | 383 /// Returns the transitive closure of all libraries that are imported |
| 382 /// from root without DeferredLibrary annotations. | 384 /// from root without DeferredLibrary annotations. |
| 383 Set<LibraryElement> _nonDeferredReachableLibraries(LibraryElement root) { | 385 Set<LibraryElement> _nonDeferredReachableLibraries(LibraryElement root) { |
| 384 Set<LibraryElement> result = new Set<LibraryElement>(); | 386 Set<LibraryElement> result = new Set<LibraryElement>(); |
| (...skipping 22 matching lines...) Expand all Loading... |
| 407 } | 409 } |
| 408 } | 410 } |
| 409 traverseLibrary(root); | 411 traverseLibrary(root); |
| 410 result.add(compiler.coreLibrary); | 412 result.add(compiler.coreLibrary); |
| 411 return result; | 413 return result; |
| 412 } | 414 } |
| 413 | 415 |
| 414 /// Recursively traverses the graph of dependencies from [element], mapping | 416 /// Recursively traverses the graph of dependencies from [element], mapping |
| 415 /// deferred imports to each dependency it needs in the sets | 417 /// deferred imports to each dependency it needs in the sets |
| 416 /// [_importedDeferredBy] and [_constantsDeferredBy]. | 418 /// [_importedDeferredBy] and [_constantsDeferredBy]. |
| 417 void _mapDependencies(Element element, Import import) { | 419 void _mapDependencies(Element element, Import import, |
| 420 {isMirrorUsage: false}) { |
| 418 Set<Element> elements = _importedDeferredBy.putIfAbsent(import, | 421 Set<Element> elements = _importedDeferredBy.putIfAbsent(import, |
| 419 () => new Set<Element>()); | 422 () => new Set<Element>()); |
| 420 Set<Constant> constants = _constantsDeferredBy.putIfAbsent(import, | 423 Set<Constant> constants = _constantsDeferredBy.putIfAbsent(import, |
| 421 () => new Set<Constant>()); | 424 () => new Set<Constant>()); |
| 422 | 425 |
| 423 if (elements.contains(element)) return; | 426 // Only process elements once, unless we are doing dependencies due to |
| 427 // mirrors, which are added in additional traversals. |
| 428 if (!isMirrorUsage && elements.contains(element)) return; |
| 424 // Anything used directly by main will be loaded from the start | 429 // Anything used directly by main will be loaded from the start |
| 425 // We do not need to traverse it again. | 430 // We do not need to traverse it again. |
| 426 if (import != _fakeMainImport && _mainElements.contains(element)) return; | 431 if (import != _fakeMainImport && _mainElements.contains(element)) return; |
| 427 | 432 |
| 428 // Here we modify [_importedDeferredBy]. | 433 // Here we modify [_importedDeferredBy]. |
| 429 elements.add(element); | 434 elements.add(element); |
| 430 | 435 |
| 431 Set<Element> dependentElements = new Set<Element>(); | 436 Set<Element> dependentElements = new Set<Element>(); |
| 432 | 437 |
| 433 // This call can modify [_importedDeferredBy] and [_constantsDeferredBy]. | 438 // This call can modify [_importedDeferredBy] and [_constantsDeferredBy]. |
| 434 _collectAllElementsAndConstantsResolvedFrom( | 439 _collectAllElementsAndConstantsResolvedFrom( |
| 435 element, dependentElements, constants); | 440 element, dependentElements, constants, isMirrorUsage); |
| 436 | 441 |
| 437 LibraryElement library = element.library; | 442 LibraryElement library = element.library; |
| 438 for (Element dependency in dependentElements) { | 443 for (Element dependency in dependentElements) { |
| 439 if (_isExplicitlyDeferred(dependency, library)) { | 444 if (_isExplicitlyDeferred(dependency, library)) { |
| 440 for (Import deferredImport in _getImports(dependency, library)) { | 445 for (Import deferredImport in _getImports(dependency, library)) { |
| 441 _mapDependencies(dependency, deferredImport); | 446 _mapDependencies(dependency, deferredImport); |
| 442 }; | 447 }; |
| 443 } else { | 448 } else { |
| 444 _mapDependencies(dependency, import); | 449 _mapDependencies(dependency, import); |
| 445 } | 450 } |
| 446 } | 451 } |
| 447 } | 452 } |
| 448 | 453 |
| 449 /// Adds extra dependencies coming from mirror usage. | 454 /// Adds extra dependencies coming from mirror usage. |
| 450 /// | 455 /// |
| 451 /// The elements are added with [_mapDependencies]. | 456 /// The elements are added with [_mapDependencies]. |
| 452 void _addMirrorElements() { | 457 void _addMirrorElements() { |
| 453 void mapDependenciesIfResolved(Element element, Import deferredImport) { | 458 void mapDependenciesIfResolved(Element element, Import deferredImport) { |
| 454 // If an element is the target of a MirrorsUsed annotation but never used | 459 // If an element is the target of a MirrorsUsed annotation but never used |
| 455 // It will not be resolved, and we should not call isNeededForReflection. | 460 // It will not be resolved, and we should not call isNeededForReflection. |
| 456 // TODO(sigurdm): Unresolved elements should just answer false when | 461 // TODO(sigurdm): Unresolved elements should just answer false when |
| 457 // asked isNeededForReflection. Instead an internal error is triggered. | 462 // asked isNeededForReflection. Instead an internal error is triggered. |
| 458 // So we have to filter them out here. | 463 // So we have to filter them out here. |
| 459 if (element is AnalyzableElementX && !element.hasTreeElements) return; | 464 if (element is AnalyzableElementX && !element.hasTreeElements) return; |
| 460 if (compiler.backend.isNeededForReflection(element)) { | 465 if (compiler.backend.isNeededForReflection(element)) { |
| 461 _mapDependencies(element, deferredImport); | 466 _mapDependencies(element, deferredImport, isMirrorUsage: true); |
| 462 } | 467 } |
| 463 } | 468 } |
| 464 | 469 |
| 465 // For each deferred import we analyze all elements reachable from the | 470 // For each deferred import we analyze all elements reachable from the |
| 466 // imported library through non-deferred imports. | 471 // imported library through non-deferred imports. |
| 467 handleLibrary(LibraryElement library, Import deferredImport) { | 472 handleLibrary(LibraryElement library, Import deferredImport) { |
| 468 library.implementation.forEachLocalMember((Element element) { | 473 library.implementation.forEachLocalMember((Element element) { |
| 469 mapDependenciesIfResolved(element, deferredImport); | 474 mapDependenciesIfResolved(element, deferredImport); |
| 470 }); | 475 }); |
| 471 | 476 |
| (...skipping 311 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 783 Element maybePrefix = elements[identifier]; | 788 Element maybePrefix = elements[identifier]; |
| 784 if (maybePrefix != null && maybePrefix.isPrefix) { | 789 if (maybePrefix != null && maybePrefix.isPrefix) { |
| 785 PrefixElement prefixElement = maybePrefix; | 790 PrefixElement prefixElement = maybePrefix; |
| 786 if (prefixElement.isDeferred) { | 791 if (prefixElement.isDeferred) { |
| 787 return prefixElement; | 792 return prefixElement; |
| 788 } | 793 } |
| 789 } | 794 } |
| 790 return null; | 795 return null; |
| 791 } | 796 } |
| 792 } | 797 } |
| OLD | NEW |