| 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 | 
|---|