OLD | NEW |
1 // Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2015, 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 analyzer.src.context.cache; | 5 library analyzer.src.context.cache; |
6 | 6 |
7 import 'dart:async'; | 7 import 'dart:async'; |
8 import 'dart:collection'; | 8 import 'dart:collection'; |
9 | 9 |
10 import 'package:analyzer/src/dart/element/element.dart' | 10 import 'package:analyzer/src/dart/element/element.dart' |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
47 <ReentrantSynchronousStreamSubscription>[]; | 47 <ReentrantSynchronousStreamSubscription>[]; |
48 | 48 |
49 /** | 49 /** |
50 * Initialize a newly created cache to have the given [_partitions]. The | 50 * Initialize a newly created cache to have the given [_partitions]. The |
51 * partitions will be searched in the order in which they appear in the array, | 51 * partitions will be searched in the order in which they appear in the array, |
52 * so the most specific partition (usually an [SdkCachePartition]) should be | 52 * so the most specific partition (usually an [SdkCachePartition]) should be |
53 * first and the most general (usually a [UniversalCachePartition]) last. | 53 * first and the most general (usually a [UniversalCachePartition]) last. |
54 */ | 54 */ |
55 AnalysisCache(this._partitions) { | 55 AnalysisCache(this._partitions) { |
56 for (CachePartition partition in _partitions) { | 56 for (CachePartition partition in _partitions) { |
| 57 partition.containingCaches.add(this); |
57 ReentrantSynchronousStreamSubscription<InvalidatedResult> subscription = | 58 ReentrantSynchronousStreamSubscription<InvalidatedResult> subscription = |
58 partition.onResultInvalidated.listen((InvalidatedResult event) { | 59 partition.onResultInvalidated.listen((InvalidatedResult event) { |
59 onResultInvalidated.add(event); | 60 onResultInvalidated.add(event); |
60 }); | 61 }); |
61 onResultInvalidatedPartitionSubscriptions.add(subscription); | 62 onResultInvalidatedPartitionSubscriptions.add(subscription); |
62 } | 63 } |
63 } | 64 } |
64 | 65 |
65 /** | 66 /** |
66 * Return an iterator returning all of the [Source] targets. | 67 * Return an iterator returning all of the [Source] targets. |
(...skipping 22 matching lines...) Expand all Loading... |
89 // } | 90 // } |
90 | 91 |
91 /** | 92 /** |
92 * Free any allocated resources and references. | 93 * Free any allocated resources and references. |
93 */ | 94 */ |
94 void dispose() { | 95 void dispose() { |
95 for (ReentrantSynchronousStreamSubscription subscription | 96 for (ReentrantSynchronousStreamSubscription subscription |
96 in onResultInvalidatedPartitionSubscriptions) { | 97 in onResultInvalidatedPartitionSubscriptions) { |
97 subscription.cancel(); | 98 subscription.cancel(); |
98 } | 99 } |
| 100 for (CachePartition partition in _partitions) { |
| 101 partition.containingCaches.remove(this); |
| 102 } |
99 } | 103 } |
100 | 104 |
101 /** | 105 /** |
102 * Return the entry associated with the given [target]. | 106 * Return the entry associated with the given [target]. |
103 */ | 107 */ |
104 CacheEntry get(AnalysisTarget target) { | 108 CacheEntry get(AnalysisTarget target) { |
105 int count = _partitions.length; | 109 int count = _partitions.length; |
106 for (int i = 0; i < count; i++) { | 110 for (int i = 0; i < count; i++) { |
107 CachePartition partition = _partitions[i]; | 111 CachePartition partition = _partitions[i]; |
108 if (partition.isResponsibleFor(target)) { | 112 if (partition.isResponsibleFor(target)) { |
(...skipping 233 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 /** | 346 /** |
343 * Return a list of result descriptors for results whose state is not | 347 * Return a list of result descriptors for results whose state is not |
344 * [CacheState.INVALID]. | 348 * [CacheState.INVALID]. |
345 */ | 349 */ |
346 List<ResultDescriptor> get nonInvalidResults => _resultMap.keys.toList(); | 350 List<ResultDescriptor> get nonInvalidResults => _resultMap.keys.toList(); |
347 | 351 |
348 /** | 352 /** |
349 * Notifies the entry that the client is going to stop using it. | 353 * Notifies the entry that the client is going to stop using it. |
350 */ | 354 */ |
351 void dispose() { | 355 void dispose() { |
352 _resultMap.forEach((descriptor, data) { | 356 _resultMap.forEach((ResultDescriptor descriptor, ResultData data) { |
353 TargetedResult result = new TargetedResult(target, descriptor); | 357 TargetedResult result = new TargetedResult(target, descriptor); |
354 for (TargetedResult dependedOnResult in data.dependedOnResults) { | 358 for (TargetedResult dependedOnResult in data.dependedOnResults) { |
355 ResultData dependedOnData = _partition._getDataFor(dependedOnResult); | 359 for (AnalysisCache cache in _partition.containingCaches) { |
356 if (dependedOnData != null) { | 360 CacheEntry entry = cache.get(dependedOnResult.target); |
357 dependedOnData.dependentResults.remove(result); | 361 if (entry != null) { |
| 362 ResultData data = |
| 363 entry.getResultDataOrNull(dependedOnResult.result); |
| 364 if (data != null) { |
| 365 data.dependentResults.remove(result); |
| 366 } |
| 367 } |
358 } | 368 } |
359 } | 369 } |
360 }); | 370 }); |
361 _resultMap.clear(); | 371 _resultMap.clear(); |
362 AnalysisTarget oldTarget = target; | 372 AnalysisTarget oldTarget = target; |
363 if (oldTarget is ElementImpl) { | 373 if (oldTarget is ElementImpl) { |
364 oldTarget.setModifier(Modifier.CACHE_KEY, false); | 374 oldTarget.setModifier(Modifier.CACHE_KEY, false); |
365 } | 375 } |
366 } | 376 } |
367 | 377 |
368 /** | 378 /** |
369 * Fix the state of the [exception] to match the current state of the entry. | 379 * Fix the state of the [exception] to match the current state of the entry. |
370 */ | 380 */ |
371 void fixExceptionState() { | 381 void fixExceptionState() { |
372 if (!hasErrorState()) { | 382 if (!hasErrorState()) { |
373 _exception = null; | 383 _exception = null; |
374 } | 384 } |
375 } | 385 } |
376 | 386 |
377 /** | 387 /** |
378 * Look up the [ResultData] of [descriptor], or add a new one if it isn't | 388 * Return the result data associated with the [descriptor], creating one if it |
379 * there. | 389 * isn't there. |
380 */ | 390 */ |
381 ResultData getResultData(ResultDescriptor descriptor) { | 391 ResultData getResultData(ResultDescriptor descriptor) { |
382 return _resultMap.putIfAbsent(descriptor, () => new ResultData(descriptor)); | 392 return _resultMap.putIfAbsent(descriptor, () => new ResultData(descriptor)); |
383 } | 393 } |
384 | 394 |
385 /** | 395 /** |
| 396 * Return the result data associated with the [descriptor], or `null` if there |
| 397 * is no data currently associated with the descriptor. |
| 398 */ |
| 399 ResultData getResultDataOrNull(ResultDescriptor descriptor) => |
| 400 _resultMap[descriptor]; |
| 401 |
| 402 /** |
386 * Return the state of the result represented by the given [descriptor]. | 403 * Return the state of the result represented by the given [descriptor]. |
387 */ | 404 */ |
388 CacheState getState(ResultDescriptor descriptor) { | 405 CacheState getState(ResultDescriptor descriptor) { |
389 ResultData data = _resultMap[descriptor]; | 406 ResultData data = _resultMap[descriptor]; |
390 if (data == null) { | 407 if (data == null) { |
391 return CacheState.INVALID; | 408 return CacheState.INVALID; |
392 } | 409 } |
393 return data.state; | 410 return data.state; |
394 } | 411 } |
395 | 412 |
(...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
577 if (deltaResult == null || | 594 if (deltaResult == null || |
578 deltaResult == DeltaResult.INVALIDATE || | 595 deltaResult == DeltaResult.INVALIDATE || |
579 deltaResult == DeltaResult.INVALIDATE_NO_DELTA) { | 596 deltaResult == DeltaResult.INVALIDATE_NO_DELTA) { |
580 _resultMap.remove(descriptor); | 597 _resultMap.remove(descriptor); |
581 // { | 598 // { |
582 // String indent = ' ' * level; | 599 // String indent = ' ' * level; |
583 // print('[$id]$indent invalidate $descriptor for $target'); | 600 // print('[$id]$indent invalidate $descriptor for $target'); |
584 // } | 601 // } |
585 } | 602 } |
586 // Stop depending on other results. | 603 // Stop depending on other results. |
587 TargetedResult thisResult = new TargetedResult(target, descriptor); | 604 if (deltaResult != DeltaResult.KEEP_CONTINUE) { |
588 for (TargetedResult dependedOnResult in thisData.dependedOnResults) { | 605 TargetedResult thisResult = new TargetedResult(target, descriptor); |
589 ResultData data = _partition._getDataFor(dependedOnResult); | 606 for (TargetedResult dependedOnResult in thisData.dependedOnResults) { |
590 if (data != null && deltaResult != DeltaResult.KEEP_CONTINUE) { | 607 for (AnalysisCache cache in _partition.containingCaches) { |
591 data.dependentResults.remove(thisResult); | 608 CacheEntry entry = cache.get(dependedOnResult.target); |
| 609 if (entry != null) { |
| 610 ResultData data = |
| 611 entry.getResultDataOrNull(dependedOnResult.result); |
| 612 if (data != null) { |
| 613 data.dependentResults.remove(thisResult); |
| 614 } |
| 615 } |
| 616 } |
592 } | 617 } |
593 } | 618 } |
594 // Invalidate results that depend on this result. | 619 // Invalidate results that depend on this result. |
595 _invalidateDependentResults(id, thisData, delta, level + 1); | 620 _invalidateDependentResults(id, thisData, delta, level + 1); |
596 // If empty and not explicitly added, remove the entry altogether. | 621 // If empty and not explicitly added, remove the entry altogether. |
597 if (_resultMap.isEmpty && !explicitlyAdded) { | 622 if (_resultMap.isEmpty && !explicitlyAdded) { |
598 CacheEntry entry = _partition.entryMap.remove(target); | 623 CacheEntry entry = _partition.entryMap.remove(target); |
599 if (entry != null) { | 624 if (entry != null) { |
600 entry.dispose(); | 625 entry.dispose(); |
601 } | 626 } |
(...skipping 12 matching lines...) Expand all Loading... |
614 for (ResultDescriptor result in results) { | 639 for (ResultDescriptor result in results) { |
615 _invalidate(nextInvalidateId++, result, null, 0); | 640 _invalidate(nextInvalidateId++, result, null, 0); |
616 } | 641 } |
617 } | 642 } |
618 | 643 |
619 /** | 644 /** |
620 * Invalidate results that depend on [thisData]. | 645 * Invalidate results that depend on [thisData]. |
621 */ | 646 */ |
622 void _invalidateDependentResults( | 647 void _invalidateDependentResults( |
623 int id, ResultData thisData, Delta delta, int level) { | 648 int id, ResultData thisData, Delta delta, int level) { |
| 649 // It is necessary to copy the results to a list to avoid a concurrent |
| 650 // modification of the set of dependent results. |
624 List<TargetedResult> dependentResults = thisData.dependentResults.toList(); | 651 List<TargetedResult> dependentResults = thisData.dependentResults.toList(); |
625 for (TargetedResult dependentResult in dependentResults) { | 652 for (TargetedResult dependentResult in dependentResults) { |
626 CacheEntry entry = _partition.get(dependentResult.target); | 653 for (AnalysisCache cache in _partition.containingCaches) { |
627 if (entry != null) { | 654 CacheEntry entry = cache.get(dependentResult.target); |
628 entry._invalidate(id, dependentResult.result, delta, level); | 655 if (entry != null) { |
| 656 entry._invalidate(id, dependentResult.result, delta, level); |
| 657 } |
629 } | 658 } |
630 } | 659 } |
631 } | 660 } |
632 | 661 |
633 /** | 662 /** |
634 * If the given `target` is an element, mark it as being a cache key. | 663 * If the given `target` is an element, mark it as being a cache key. |
635 */ | 664 */ |
636 void _markAsCacheKey(AnalysisTarget target) { | 665 void _markAsCacheKey(AnalysisTarget target) { |
637 if (target is ElementImpl) { | 666 if (target is ElementImpl) { |
638 target.setModifier(Modifier.CACHE_KEY, true); | 667 target.setModifier(Modifier.CACHE_KEY, true); |
639 } | 668 } |
640 } | 669 } |
641 | 670 |
642 /** | 671 /** |
643 * Set the [dependedOn] on which this result depends. | 672 * Set the [dependedOn] on which this result depends. |
644 */ | 673 */ |
645 void _setDependedOnResults(ResultData thisData, TargetedResult thisResult, | 674 void _setDependedOnResults(ResultData thisData, TargetedResult thisResult, |
646 List<TargetedResult> dependedOn) { | 675 List<TargetedResult> dependedOn) { |
647 thisData.dependedOnResults.forEach((TargetedResult dependedOnResult) { | 676 thisData.dependedOnResults.forEach((TargetedResult dependedOnResult) { |
648 ResultData data = _partition._getDataFor(dependedOnResult); | 677 for (AnalysisCache cache in _partition.containingCaches) { |
649 if (data != null) { | 678 CacheEntry entry = cache.get(dependedOnResult.target); |
650 data.dependentResults.remove(thisResult); | 679 if (entry != null) { |
| 680 ResultData data = entry.getResultDataOrNull(dependedOnResult.result); |
| 681 if (data != null) { |
| 682 data.dependentResults.remove(thisResult); |
| 683 } |
| 684 } |
651 } | 685 } |
652 }); | 686 }); |
653 thisData.dependedOnResults = dependedOn; | 687 thisData.dependedOnResults = dependedOn; |
654 thisData.dependedOnResults.forEach((TargetedResult dependedOnResult) { | 688 thisData.dependedOnResults.forEach((TargetedResult dependedOnResult) { |
655 ResultData data = _partition._getDataFor(dependedOnResult); | 689 for (AnalysisCache cache in _partition.containingCaches) { |
656 if (data != null) { | 690 CacheEntry entry = cache.get(dependedOnResult.target); |
657 data.dependentResults.add(thisResult); | 691 if (entry != null) { |
| 692 ResultData data = entry.getResultDataOrNull(dependedOnResult.result); |
| 693 if (data != null) { |
| 694 data.dependentResults.add(thisResult); |
| 695 } |
| 696 } |
658 } | 697 } |
659 }); | 698 }); |
660 } | 699 } |
661 | 700 |
662 /** | 701 /** |
663 * Set states of the given and dependent results to [CacheState.ERROR] and | 702 * Set states of the given and dependent results to [CacheState.ERROR] and |
664 * their values to the corresponding default values | 703 * their values to the corresponding default values |
665 */ | 704 */ |
666 void _setErrorState(ResultDescriptor descriptor, CaughtException exception) { | 705 void _setErrorState(ResultDescriptor descriptor, CaughtException exception) { |
667 ResultData thisData = getResultData(descriptor); | 706 ResultData thisData = getResultData(descriptor); |
668 // Set the error state. | 707 // Set the error state. |
669 _exception = exception; | 708 _exception = exception; |
670 thisData.state = CacheState.ERROR; | 709 thisData.state = CacheState.ERROR; |
671 thisData.value = descriptor.defaultValue; | 710 thisData.value = descriptor.defaultValue; |
672 // Propagate the error state. | 711 // Propagate the error state. |
673 thisData.dependentResults.forEach((TargetedResult dependentResult) { | 712 thisData.dependentResults.forEach((TargetedResult dependentResult) { |
674 CacheEntry entry = _partition.get(dependentResult.target); | 713 for (AnalysisCache cache in _partition.containingCaches) { |
675 entry._setErrorState(dependentResult.result, exception); | 714 CacheEntry entry = cache.get(dependentResult.target); |
| 715 if (entry != null) { |
| 716 entry._setErrorState(dependentResult.result, exception); |
| 717 } |
| 718 } |
676 }); | 719 }); |
677 } | 720 } |
678 | 721 |
679 /** | 722 /** |
680 * Set the value of the flag with the given [index] to the given [value]. | 723 * Set the value of the flag with the given [index] to the given [value]. |
681 */ | 724 */ |
682 void _setFlag(int index, bool value) { | 725 void _setFlag(int index, bool value) { |
683 _flags = BooleanArray.set(_flags, index, value); | 726 _flags = BooleanArray.set(_flags, index, value); |
684 } | 727 } |
685 | 728 |
(...skipping 172 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
858 * A single partition in an LRU cache of information related to analysis. | 901 * A single partition in an LRU cache of information related to analysis. |
859 */ | 902 */ |
860 abstract class CachePartition { | 903 abstract class CachePartition { |
861 /** | 904 /** |
862 * The context that owns this partition. Multiple contexts can reference a | 905 * The context that owns this partition. Multiple contexts can reference a |
863 * partition, but only one context can own it. | 906 * partition, but only one context can own it. |
864 */ | 907 */ |
865 final InternalAnalysisContext context; | 908 final InternalAnalysisContext context; |
866 | 909 |
867 /** | 910 /** |
| 911 * A list of the caches that contain this partition. This includes the cache |
| 912 * associated with the context that owns this partition. |
| 913 */ |
| 914 final List<AnalysisCache> containingCaches = <AnalysisCache>[]; |
| 915 |
| 916 /** |
868 * A table mapping caching policies to the cache flush managers. | 917 * A table mapping caching policies to the cache flush managers. |
869 */ | 918 */ |
870 final HashMap<ResultCachingPolicy, CacheFlushManager> _flushManagerMap = | 919 final HashMap<ResultCachingPolicy, CacheFlushManager> _flushManagerMap = |
871 new HashMap<ResultCachingPolicy, CacheFlushManager>(); | 920 new HashMap<ResultCachingPolicy, CacheFlushManager>(); |
872 | 921 |
873 /** | 922 /** |
874 * The [StreamController] reporting [InvalidatedResult]s. | 923 * The [StreamController] reporting [InvalidatedResult]s. |
875 */ | 924 */ |
876 final ReentrantSynchronousStream<InvalidatedResult> onResultInvalidated = | 925 final ReentrantSynchronousStream<InvalidatedResult> onResultInvalidated = |
877 new ReentrantSynchronousStream<InvalidatedResult>(); | 926 new ReentrantSynchronousStream<InvalidatedResult>(); |
(...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1006 * If the given [target] is a [Source], adds it to [sources]. | 1055 * If the given [target] is a [Source], adds it to [sources]. |
1007 */ | 1056 */ |
1008 void _addIfSource(AnalysisTarget target) { | 1057 void _addIfSource(AnalysisTarget target) { |
1009 if (target is Source) { | 1058 if (target is Source) { |
1010 sources.add(target); | 1059 sources.add(target); |
1011 String fullName = target.fullName; | 1060 String fullName = target.fullName; |
1012 pathToSource.putIfAbsent(fullName, () => <Source>[]).add(target); | 1061 pathToSource.putIfAbsent(fullName, () => <Source>[]).add(target); |
1013 } | 1062 } |
1014 } | 1063 } |
1015 | 1064 |
1016 ResultData _getDataFor(TargetedResult result) { | |
1017 CacheEntry entry = context.analysisCache.get(result.target); | |
1018 return entry != null ? entry._resultMap[result.result] : null; | |
1019 } | |
1020 | |
1021 /** | 1065 /** |
1022 * Return the [CacheFlushManager] for the given [descriptor], not `null`. | 1066 * Return the [CacheFlushManager] for the given [descriptor], not `null`. |
1023 */ | 1067 */ |
1024 CacheFlushManager _getFlushManager(ResultDescriptor descriptor) { | 1068 CacheFlushManager _getFlushManager(ResultDescriptor descriptor) { |
1025 ResultCachingPolicy policy = descriptor.cachingPolicy; | 1069 ResultCachingPolicy policy = descriptor.cachingPolicy; |
1026 if (identical(policy, DEFAULT_CACHING_POLICY)) { | 1070 if (identical(policy, DEFAULT_CACHING_POLICY)) { |
1027 return UnlimitedCacheFlushManager.INSTANCE; | 1071 return UnlimitedCacheFlushManager.INSTANCE; |
1028 } | 1072 } |
1029 CacheFlushManager manager = _flushManagerMap[policy]; | 1073 CacheFlushManager manager = _flushManagerMap[policy]; |
1030 if (manager == null) { | 1074 if (manager == null) { |
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1279 void resultAccessed(TargetedResult result) {} | 1323 void resultAccessed(TargetedResult result) {} |
1280 | 1324 |
1281 @override | 1325 @override |
1282 List<TargetedResult> resultStored(TargetedResult newResult, newValue) { | 1326 List<TargetedResult> resultStored(TargetedResult newResult, newValue) { |
1283 return TargetedResult.EMPTY_LIST; | 1327 return TargetedResult.EMPTY_LIST; |
1284 } | 1328 } |
1285 | 1329 |
1286 @override | 1330 @override |
1287 void targetRemoved(AnalysisTarget target) {} | 1331 void targetRemoved(AnalysisTarget target) {} |
1288 } | 1332 } |
OLD | NEW |