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

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

Issue 1109393012: Allow use of deferred type-literals in non-constant contexts. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Address review Created 5 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
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 'constants/expressions.dart'; 7 import 'constants/expressions.dart';
8 import 'constants/values.dart' show 8 import 'constants/values.dart' show
9 ConstantValue, 9 ConstantValue,
10 ConstructedConstantValue, 10 ConstructedConstantValue,
(...skipping 176 matching lines...) Expand 10 before | Expand all | Expand 10 after
187 break; 187 break;
188 } 188 }
189 element = element.enclosingElement.implementation; 189 element = element.enclosingElement.implementation;
190 } 190 }
191 return _elementToOutputUnit[element]; 191 return _elementToOutputUnit[element];
192 } 192 }
193 193
194 /// Returns the [OutputUnit] where [constant] belongs. 194 /// Returns the [OutputUnit] where [constant] belongs.
195 OutputUnit outputUnitForConstant(ConstantValue constant) { 195 OutputUnit outputUnitForConstant(ConstantValue constant) {
196 if (!isProgramSplit) return mainOutputUnit; 196 if (!isProgramSplit) return mainOutputUnit;
197
198 return _constantToOutputUnit[constant]; 197 return _constantToOutputUnit[constant];
199 } 198 }
200 199
201 bool isDeferred(Element element) { 200 bool isDeferred(Element element) {
202 return outputUnitForElement(element) != mainOutputUnit; 201 return outputUnitForElement(element) != mainOutputUnit;
203 } 202 }
204 203
205 /// Returns true if e1 and e2 are in the same output unit. 204 /// Returns true if e1 and e2 are in the same output unit.
206 bool inSameOutputUnit(Element e1, Element e2) { 205 bool inSameOutputUnit(Element e1, Element e2) {
207 return outputUnitForElement(e1) == outputUnitForElement(e2); 206 return outputUnitForElement(e1) == outputUnitForElement(e2);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
242 /// Finds all elements and constants that [element] depends directly on. 241 /// Finds all elements and constants that [element] depends directly on.
243 /// (not the transitive closure.) 242 /// (not the transitive closure.)
244 /// 243 ///
245 /// Adds the results to [elements] and [constants]. 244 /// Adds the results to [elements] and [constants].
246 void _collectAllElementsAndConstantsResolvedFrom( 245 void _collectAllElementsAndConstantsResolvedFrom(
247 Element element, 246 Element element,
248 Set<Element> elements, 247 Set<Element> elements,
249 Set<ConstantValue> constants, 248 Set<ConstantValue> constants,
250 isMirrorUsage) { 249 isMirrorUsage) {
251 250
252 /// Recursively add the constant and its dependencies to [constants].
253 void addConstants(ConstantValue constant) {
254 if (constants.contains(constant)) return;
255 constants.add(constant);
256 if (constant is ConstructedConstantValue) {
257 elements.add(constant.type.element);
258 }
259 constant.getDependencies().forEach(addConstants);
260 }
261
262 /// Collects all direct dependencies of [element]. 251 /// Collects all direct dependencies of [element].
263 /// 252 ///
264 /// The collected dependent elements and constants are are added to 253 /// The collected dependent elements and constants are are added to
265 /// [elements] and [constants] respectively. 254 /// [elements] and [constants] respectively.
266 void collectDependencies(Element element) { 255 void collectDependencies(Element element) {
267 // TODO(johnniwinther): Remove this when [AbstractFieldElement] has been 256 // TODO(johnniwinther): Remove this when [AbstractFieldElement] has been
268 // removed. 257 // removed.
269 if (element is! AstElement) return; 258 if (element is! AstElement) return;
270 AstElement astElement = element; 259 AstElement astElement = element;
271 260
(...skipping 10 matching lines...) Expand all
282 271
283 for (Element dependency in treeElements.allElements) { 272 for (Element dependency in treeElements.allElements) {
284 if (dependency.isLocal && !dependency.isFunction) continue; 273 if (dependency.isLocal && !dependency.isFunction) continue;
285 if (dependency.isErroneous) continue; 274 if (dependency.isErroneous) continue;
286 if (dependency.isTypeVariable) continue; 275 if (dependency.isTypeVariable) continue;
287 276
288 elements.add(dependency); 277 elements.add(dependency);
289 } 278 }
290 treeElements.forEachConstantNode((Node node, _) { 279 treeElements.forEachConstantNode((Node node, _) {
291 // Explicitly depend on the backend constants. 280 // Explicitly depend on the backend constants.
292 addConstants( 281 constants.add(
293 backend.constants.getConstantForNode(node, treeElements).value); 282 backend.constants.getConstantForNode(node, treeElements).value);
294 }); 283 });
295 elements.addAll(treeElements.otherDependencies); 284 elements.addAll(treeElements.otherDependencies);
296 } 285 }
297 286
298 // TODO(sigurdm): How is metadata on a patch-class handled? 287 // TODO(sigurdm): How is metadata on a patch-class handled?
299 for (MetadataAnnotation metadata in element.metadata) { 288 for (MetadataAnnotation metadata in element.metadata) {
300 ConstantExpression constant = 289 ConstantExpression constant =
301 backend.constants.getConstantForMetadata(metadata); 290 backend.constants.getConstantForMetadata(metadata);
302 if (constant != null) { 291 if (constant != null) {
303 addConstants(constant.value); 292 constants.add(constant.value);
304 } 293 }
305 } 294 }
306 295
307 collectTypeDependencies(DartType type) { 296 collectTypeDependencies(DartType type) {
308 if (type is FunctionType) { 297 if (type is FunctionType) {
309 for (DartType argumentType in type.parameterTypes) { 298 for (DartType argumentType in type.parameterTypes) {
310 collectTypeDependencies(argumentType); 299 collectTypeDependencies(argumentType);
311 } 300 }
312 for (DartType argumentType in type.optionalParameterTypes) { 301 for (DartType argumentType in type.optionalParameterTypes) {
313 collectTypeDependencies(argumentType); 302 collectTypeDependencies(argumentType);
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 iterateTags(library); 383 iterateTags(library);
395 if (library.isPatched) { 384 if (library.isPatched) {
396 iterateTags(library.implementation); 385 iterateTags(library.implementation);
397 } 386 }
398 } 387 }
399 traverseLibrary(root); 388 traverseLibrary(root);
400 result.add(compiler.coreLibrary); 389 result.add(compiler.coreLibrary);
401 return result; 390 return result;
402 } 391 }
403 392
404 /// Recursively traverses the graph of dependencies from [element], mapping 393 /// Add all dependencies of [constant] to the mapping of [import].
405 /// deferred imports to each dependency it needs in the sets 394 void _mapConstantDependencies(ConstantValue constant, Import import) {
406 /// [_importedDeferredBy] and [_constantsDeferredBy]. 395 Set<ConstantValue> constants = _constantsDeferredBy.putIfAbsent(import,
407 void _mapDependencies(Element element, Import import, 396 () => new Set<ConstantValue>());
408 {isMirrorUsage: false}) { 397 if (constants.contains(constant)) return;
398 constants.add(constant);
399 if (constant is ConstructedConstantValue) {
400 _mapDependencies(element: constant.type.element, import: import);
401 }
402 constant.getDependencies().forEach((ConstantValue dependency) {
403 _mapConstantDependencies(dependency, import);
404 });
405 }
406
407 /// Recursively traverses the graph of dependencies from one of [element]
408 /// or [constant], mapping deferred imports to each dependency it needs in the
409 /// sets [_importedDeferredBy] and [_constantsDeferredBy].
410 /// Only one of [element] and [constant] should be given.
411 void _mapDependencies({Element element,
412 Import import,
413 isMirrorUsage: false}) {
414
409 Set<Element> elements = _importedDeferredBy.putIfAbsent(import, 415 Set<Element> elements = _importedDeferredBy.putIfAbsent(import,
410 () => new Set<Element>()); 416 () => new Set<Element>());
411 Set<ConstantValue> constants = _constantsDeferredBy.putIfAbsent(import,
412 () => new Set<ConstantValue>());
413 417
414 // Only process elements once, unless we are doing dependencies due to
415 // mirrors, which are added in additional traversals.
416 if (!isMirrorUsage && elements.contains(element)) return;
417 // Anything used directly by main will be loaded from the start
418 // We do not need to traverse it again.
419 if (import != _fakeMainImport && _mainElements.contains(element)) return;
420
421 // Here we modify [_importedDeferredBy].
422 elements.add(element);
423 418
424 Set<Element> dependentElements = new Set<Element>(); 419 Set<Element> dependentElements = new Set<Element>();
420 Set<ConstantValue> dependentConstants = new Set<ConstantValue>();
425 421
426 // This call can modify [_importedDeferredBy] and [_constantsDeferredBy]. 422 LibraryElement library;
427 _collectAllElementsAndConstantsResolvedFrom(
428 element, dependentElements, constants, isMirrorUsage);
429 423
430 LibraryElement library = element.library; 424 if (element != null) {
425 // Only process elements once, unless we are doing dependencies due to
426 // mirrors, which are added in additional traversals.
427 if (!isMirrorUsage && elements.contains(element)) return;
428 // Anything used directly by main will be loaded from the start
429 // We do not need to traverse it again.
430 if (import != _fakeMainImport && _mainElements.contains(element)) return;
431 elements.add(element);
432
433
434 // This call can modify [dependentElements] and [dependentConstants].
435 _collectAllElementsAndConstantsResolvedFrom(
436 element, dependentElements, dependentConstants, isMirrorUsage);
437
438 library = element.library;
439 }
440
431 for (Element dependency in dependentElements) { 441 for (Element dependency in dependentElements) {
432 if (_isExplicitlyDeferred(dependency, library)) { 442 if (_isExplicitlyDeferred(dependency, library)) {
433 for (Import deferredImport in _getImports(dependency, library)) { 443 for (Import deferredImport in _getImports(dependency, library)) {
434 _mapDependencies(dependency, deferredImport); 444 _mapDependencies(element: dependency, import: deferredImport);
435 }; 445 }
436 } else { 446 } else {
437 _mapDependencies(dependency, import); 447 _mapDependencies(element: dependency, import: import);
448 }
449 }
450
451 for (ConstantValue dependency in dependentConstants) {
452 if (dependency is DeferredConstantValue) {
453 _mapConstantDependencies(dependency,
454 dependency.prefix.deferredImport);
455 } else {
456 _mapConstantDependencies(dependency, import);
438 } 457 }
439 } 458 }
440 } 459 }
441 460
442 /// Adds extra dependencies coming from mirror usage. 461 /// Adds extra dependencies coming from mirror usage.
443 /// 462 ///
444 /// The elements are added with [_mapDependencies]. 463 /// The elements are added with [_mapDependencies].
445 void _addMirrorElements() { 464 void _addMirrorElements() {
446 void mapDependenciesIfResolved(Element element, Import deferredImport) { 465 void mapDependenciesIfResolved(Element element, Import deferredImport) {
447 // If an element is the target of a MirrorsUsed annotation but never used 466 // If an element is the target of a MirrorsUsed annotation but never used
448 // It will not be resolved, and we should not call isNeededForReflection. 467 // It will not be resolved, and we should not call isNeededForReflection.
449 // TODO(sigurdm): Unresolved elements should just answer false when 468 // TODO(sigurdm): Unresolved elements should just answer false when
450 // asked isNeededForReflection. Instead an internal error is triggered. 469 // asked isNeededForReflection. Instead an internal error is triggered.
451 // So we have to filter them out here. 470 // So we have to filter them out here.
452 if (element is AnalyzableElementX && !element.hasTreeElements) return; 471 if (element is AnalyzableElementX && !element.hasTreeElements) return;
453 if (compiler.backend.isAccessibleByReflection(element)) { 472 if (compiler.backend.isAccessibleByReflection(element)) {
454 _mapDependencies(element, deferredImport, isMirrorUsage: true); 473 _mapDependencies(element: element, import: deferredImport,
474 isMirrorUsage: true);
455 } 475 }
456 } 476 }
457 477
458 // For each deferred import we analyze all elements reachable from the 478 // For each deferred import we analyze all elements reachable from the
459 // imported library through non-deferred imports. 479 // imported library through non-deferred imports.
460 handleLibrary(LibraryElement library, Import deferredImport) { 480 handleLibrary(LibraryElement library, Import deferredImport) {
461 library.implementation.forEachLocalMember((Element element) { 481 library.implementation.forEachLocalMember((Element element) {
462 mapDependenciesIfResolved(element, deferredImport); 482 mapDependenciesIfResolved(element, deferredImport);
463 }); 483 });
464 484
465 for (MetadataAnnotation metadata in library.metadata) { 485 for (MetadataAnnotation metadata in library.metadata) {
466 ConstantExpression constant = 486 ConstantExpression constant =
467 backend.constants.getConstantForMetadata(metadata); 487 backend.constants.getConstantForMetadata(metadata);
468 if (constant != null) { 488 if (constant != null) {
469 _mapDependencies(constant.value.getType(compiler.coreTypes).element, 489 _mapConstantDependencies(constant.value,
470 deferredImport); 490 deferredImport);
471 } 491 }
472 } 492 }
473 for (LibraryTag tag in library.tags) { 493 for (LibraryTag tag in library.tags) {
474 for (MetadataAnnotation metadata in tag.metadata) { 494 for (MetadataAnnotation metadata in tag.metadata) {
475 ConstantExpression constant = 495 ConstantExpression constant =
476 backend.constants.getConstantForMetadata(metadata); 496 backend.constants.getConstantForMetadata(metadata);
477 if (constant != null) { 497 if (constant != null) {
478 _mapDependencies(constant.value.getType(compiler.coreTypes).element, 498 _mapConstantDependencies(constant.value,
479 deferredImport); 499 deferredImport);
480 } 500 }
481 } 501 }
482 } 502 }
483 } 503 }
484 504
485 for (Import deferredImport in _allDeferredImports.keys) { 505 for (Import deferredImport in _allDeferredImports.keys) {
486 LibraryElement deferredLibrary = _allDeferredImports[deferredImport]; 506 LibraryElement deferredLibrary = _allDeferredImports[deferredImport];
487 for (LibraryElement library in 507 for (LibraryElement library in
488 _nonDeferredReachableLibraries(deferredLibrary)) { 508 _nonDeferredReachableLibraries(deferredLibrary)) {
489 handleLibrary(library, deferredImport); 509 handleLibrary(library, deferredImport);
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after
573 } 593 }
574 if (main == null) return; 594 if (main == null) return;
575 LibraryElement mainLibrary = main.library; 595 LibraryElement mainLibrary = main.library;
576 _importedDeferredBy = new Map<Import, Set<Element>>(); 596 _importedDeferredBy = new Map<Import, Set<Element>>();
577 _constantsDeferredBy = new Map<Import, Set<ConstantValue>>(); 597 _constantsDeferredBy = new Map<Import, Set<ConstantValue>>();
578 _importedDeferredBy[_fakeMainImport] = _mainElements; 598 _importedDeferredBy[_fakeMainImport] = _mainElements;
579 599
580 measureElement(mainLibrary, () { 600 measureElement(mainLibrary, () {
581 601
582 // Starting from main, traverse the program and find all dependencies. 602 // Starting from main, traverse the program and find all dependencies.
583 _mapDependencies(compiler.mainFunction, _fakeMainImport); 603 _mapDependencies(element: compiler.mainFunction, import: _fakeMainImport);
584 604
585 // Also add "global" dependencies to the main OutputUnit. These are 605 // Also add "global" dependencies to the main OutputUnit. These are
586 // things that the backend need but cannot associate with a particular 606 // things that the backend need but cannot associate with a particular
587 // element, for example, startRootIsolate. This set also contains 607 // element, for example, startRootIsolate. This set also contains
588 // elements for which we lack precise information. 608 // elements for which we lack precise information.
589 for (Element element in compiler.globalDependencies.otherDependencies) { 609 for (Element element in compiler.globalDependencies.otherDependencies) {
590 _mapDependencies(element, _fakeMainImport); 610 _mapDependencies(element: element, import: _fakeMainImport);
591 } 611 }
592 612
593 // Now check to see if we have to add more elements due to mirrors. 613 // Now check to see if we have to add more elements due to mirrors.
594 if (compiler.mirrorsLibrary != null) { 614 if (compiler.mirrorsLibrary != null) {
595 _addMirrorElements(); 615 _addMirrorElements();
596 } 616 }
597 617
598 // Build the OutputUnits using these two maps. 618 // Build the OutputUnits using these two maps.
599 Map<Element, OutputUnit> elementToOutputUnitBuilder = 619 Map<Element, OutputUnit> elementToOutputUnitBuilder =
600 new Map<Element, OutputUnit>(); 620 new Map<Element, OutputUnit>();
601 Map<ConstantValue, OutputUnit> constantToOutputUnitBuilder = 621 Map<ConstantValue, OutputUnit> constantToOutputUnitBuilder =
602 new Map<ConstantValue, OutputUnit>(); 622 new Map<ConstantValue, OutputUnit>();
603 623
604 // Reverse the mappings. For each element record an OutputUnit collecting 624 // Reverse the mappings. For each element record an OutputUnit collecting
605 // all deferred imports mapped to this element. Same for constants. 625 // all deferred imports mapped to this element. Same for constants.
606 for (Import import in _importedDeferredBy.keys) { 626 for (Import import in _importedDeferredBy.keys) {
607 for (Element element in _importedDeferredBy[import]) { 627 for (Element element in _importedDeferredBy[import]) {
608 // Only one file should be loaded when the program starts, so make 628 // Only one file should be loaded when the program starts, so make
609 // sure that only one OutputUnit is created for [fakeMainImport]. 629 // sure that only one OutputUnit is created for [fakeMainImport].
610 if (import == _fakeMainImport) { 630 if (import == _fakeMainImport) {
611 elementToOutputUnitBuilder[element] = mainOutputUnit; 631 elementToOutputUnitBuilder[element] = mainOutputUnit;
612 } else { 632 } else {
613 elementToOutputUnitBuilder 633 elementToOutputUnitBuilder
614 .putIfAbsent(element, () => new OutputUnit()) 634 .putIfAbsent(element, () => new OutputUnit())
615 .imports.add(import); 635 .imports.add(import);
616 } 636 }
617 } 637 }
638 }
639 for (Import import in _constantsDeferredBy.keys) {
618 for (ConstantValue constant in _constantsDeferredBy[import]) { 640 for (ConstantValue constant in _constantsDeferredBy[import]) {
619 // Only one file should be loaded when the program starts, so make 641 // Only one file should be loaded when the program starts, so make
620 // sure that only one OutputUnit is created for [fakeMainImport]. 642 // sure that only one OutputUnit is created for [fakeMainImport].
621 if (import == _fakeMainImport) { 643 if (import == _fakeMainImport) {
622 constantToOutputUnitBuilder[constant] = mainOutputUnit; 644 constantToOutputUnitBuilder[constant] = mainOutputUnit;
623 } else { 645 } else {
624 constantToOutputUnitBuilder 646 constantToOutputUnitBuilder
625 .putIfAbsent(constant, () => new OutputUnit()) 647 .putIfAbsent(constant, () => new OutputUnit())
626 .imports.add(import); 648 .imports.add(import);
627 } 649 }
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after
860 _importingLibrary = importingLibrary; 882 _importingLibrary = importingLibrary;
861 883
862 String get importingLibraryName { 884 String get importingLibraryName {
863 String libraryName = _importingLibrary.getLibraryName(); 885 String libraryName = _importingLibrary.getLibraryName();
864 return libraryName == "" 886 return libraryName == ""
865 ? "<unnamed>" 887 ? "<unnamed>"
866 : libraryName; 888 : libraryName;
867 } 889 }
868 890
869 } 891 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698