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

Side by Side Diff: packages/analyzer/lib/src/context/cache.dart

Issue 1400473008: Roll Observatory packages and add a roll script (Closed) Base URL: git@github.com:dart-lang/observatory_pub_packages.git@master
Patch Set: Created 5 years, 2 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) 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/generated/engine.dart' 10 import 'package:analyzer/src/generated/engine.dart'
11 show AnalysisEngine, CacheState, InternalAnalysisContext, RetentionPriority; 11 show AnalysisEngine, CacheState, InternalAnalysisContext, RetentionPriority;
12 import 'package:analyzer/src/generated/java_engine.dart'; 12 import 'package:analyzer/src/generated/java_engine.dart';
13 import 'package:analyzer/src/generated/source.dart'; 13 import 'package:analyzer/src/generated/source.dart';
14 import 'package:analyzer/src/generated/utilities_collection.dart'; 14 import 'package:analyzer/src/generated/utilities_collection.dart';
15 import 'package:analyzer/src/generated/utilities_general.dart';
16 import 'package:analyzer/src/task/model.dart'; 15 import 'package:analyzer/src/task/model.dart';
17 import 'package:analyzer/task/model.dart'; 16 import 'package:analyzer/task/model.dart';
18 17
19 /** 18 /**
20 * Return `true` if the given [target] is a priority one. 19 * Return `true` if the given [target] is a priority one.
21 */ 20 */
22 typedef bool IsPriorityAnalysisTarget(AnalysisTarget target); 21 typedef bool IsPriorityAnalysisTarget(AnalysisTarget target);
23 22
24 /** 23 /**
25 * An LRU cache of results produced by analysis. 24 * An LRU cache of results produced by analysis.
26 */ 25 */
27 class AnalysisCache { 26 class AnalysisCache {
28 /** 27 /**
29 * A flag used to control whether trace information should be produced when 28 * A flag used to control whether trace information should be produced when
30 * the content of the cache is modified. 29 * the content of the cache is modified.
31 */ 30 */
32 static bool _TRACE_CHANGES = false; 31 static bool _TRACE_CHANGES = false;
33 32
34 /** 33 /**
35 * An array containing the partitions of which this cache is comprised. 34 * An array containing the partitions of which this cache is comprised.
36 */ 35 */
37 final List<CachePartition> _partitions; 36 final List<CachePartition> _partitions;
38 37
39 /** 38 /**
40 * The [StreamController] reporting [InvalidatedResult]s. 39 * The [StreamController] reporting [InvalidatedResult]s.
41 */ 40 */
42 final StreamController<InvalidatedResult> _onResultInvalidated = 41 final ReentrantSynchronousStream<InvalidatedResult> onResultInvalidated =
43 new StreamController<InvalidatedResult>.broadcast(sync: true); 42 new ReentrantSynchronousStream<InvalidatedResult>();
44 43
45 /** 44 /**
46 * Initialize a newly created cache to have the given [partitions]. The 45 * Initialize a newly created cache to have the given [partitions]. The
47 * partitions will be searched in the order in which they appear in the array, 46 * partitions will be searched in the order in which they appear in the array,
48 * so the most specific partition (usually an [SdkCachePartition]) should be 47 * so the most specific partition (usually an [SdkCachePartition]) should be
49 * first and the most general (usually a [UniversalCachePartition]) last. 48 * first and the most general (usually a [UniversalCachePartition]) last.
50 */ 49 */
51 AnalysisCache(this._partitions) { 50 AnalysisCache(this._partitions) {
52 for (CachePartition partition in _partitions) { 51 for (CachePartition partition in _partitions) {
53 partition.onResultInvalidated.listen((InvalidatedResult event) { 52 partition.onResultInvalidated.listen((InvalidatedResult event) {
54 _onResultInvalidated.add(event); 53 onResultInvalidated.add(event);
55 }); 54 });
56 } 55 }
57 } 56 }
58 57
59 /**
60 * Return the stream that is notified when a value is invalidated.
61 */
62 Stream<InvalidatedResult> get onResultInvalidated =>
63 _onResultInvalidated.stream;
64
65 // TODO(brianwilkerson) Implement or delete this. 58 // TODO(brianwilkerson) Implement or delete this.
66 // /** 59 // /**
67 // * Return information about each of the partitions in this cache. 60 // * Return information about each of the partitions in this cache.
68 // */ 61 // */
69 // List<AnalysisContextStatistics_PartitionData> get partitionData { 62 // List<AnalysisContextStatistics_PartitionData> get partitionData {
70 // int count = _partitions.length; 63 // int count = _partitions.length;
71 // List<AnalysisContextStatistics_PartitionData> data = 64 // List<AnalysisContextStatistics_PartitionData> data =
72 // new List<AnalysisContextStatistics_PartitionData>(count); 65 // new List<AnalysisContextStatistics_PartitionData>(count);
73 // for (int i = 0; i < count; i++) { 66 // for (int i = 0; i < count; i++) {
74 // CachePartition partition = _partitions[i]; 67 // CachePartition partition = _partitions[i];
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after
166 Object getValue(AnalysisTarget target, ResultDescriptor result) { 159 Object getValue(AnalysisTarget target, ResultDescriptor result) {
167 CacheEntry entry = get(target); 160 CacheEntry entry = get(target);
168 if (entry == null) { 161 if (entry == null) {
169 return result.defaultValue; 162 return result.defaultValue;
170 } 163 }
171 return entry.getValue(result); 164 return entry.getValue(result);
172 } 165 }
173 166
174 /** 167 /**
175 * Return an iterator returning all of the map entries mapping targets to 168 * Return an iterator returning all of the map entries mapping targets to
176 * cache entries. 169 * cache entries. If the [context] is not `null`, then only entries that are
170 * owned by the given context will be returned.
177 */ 171 */
178 MapIterator<AnalysisTarget, CacheEntry> iterator() { 172 MapIterator<AnalysisTarget, CacheEntry> iterator(
179 int count = _partitions.length; 173 {InternalAnalysisContext context: null}) {
180 List<Map<AnalysisTarget, CacheEntry>> maps = 174 List<Map<AnalysisTarget, CacheEntry>> maps =
181 new List<Map<AnalysisTarget, CacheEntry>>(count); 175 <Map<AnalysisTarget, CacheEntry>>[];
182 for (int i = 0; i < count; i++) { 176 for (CachePartition partition in _partitions) {
183 maps[i] = _partitions[i].map; 177 if (context == null || partition.context == context) {
178 maps.add(partition.map);
179 }
184 } 180 }
185 return new MultipleMapIterator<AnalysisTarget, CacheEntry>(maps); 181 return new MultipleMapIterator<AnalysisTarget, CacheEntry>(maps);
186 } 182 }
187 183
188 /** 184 /**
189 * Puts the given [entry] into the cache. 185 * Puts the given [entry] into the cache.
190 */ 186 */
191 void put(CacheEntry entry) { 187 void put(CacheEntry entry) {
192 AnalysisTarget target = entry.target; 188 AnalysisTarget target = entry.target;
193 entry.fixExceptionState(); 189 entry.fixExceptionState();
(...skipping 15 matching lines...) Expand all
209 partition.put(entry); 205 partition.put(entry);
210 return; 206 return;
211 } 207 }
212 } 208 }
213 // TODO(brianwilkerson) Handle the case where no partition was found, 209 // TODO(brianwilkerson) Handle the case where no partition was found,
214 // possibly by throwing an exception. 210 // possibly by throwing an exception.
215 } 211 }
216 212
217 /** 213 /**
218 * Remove all information related to the given [target] from this cache. 214 * Remove all information related to the given [target] from this cache.
215 * Return the entry associated with the target, or `null` if there was cache
216 * entry for the target.
219 */ 217 */
220 void remove(AnalysisTarget target) { 218 CacheEntry remove(AnalysisTarget target) {
221 int count = _partitions.length; 219 int count = _partitions.length;
222 for (int i = 0; i < count; i++) { 220 for (int i = 0; i < count; i++) {
223 CachePartition partition = _partitions[i]; 221 CachePartition partition = _partitions[i];
224 if (partition.isResponsibleFor(target)) { 222 if (partition.isResponsibleFor(target)) {
225 if (_TRACE_CHANGES) { 223 if (_TRACE_CHANGES) {
226 AnalysisEngine.instance.logger 224 AnalysisEngine.instance.logger
227 .logInformation('Removed the cache entry for $target.'); 225 .logInformation('Removed the cache entry for $target.');
228 } 226 }
229 partition.remove(target); 227 return partition.remove(target);
230 return;
231 } 228 }
232 } 229 }
230 return null;
233 } 231 }
234 232
235 /** 233 /**
236 * Return the number of targets that are mapped to cache entries. 234 * Return the number of targets that are mapped to cache entries.
237 */ 235 */
238 int size() { 236 int size() {
239 int size = 0; 237 int size = 0;
240 int count = _partitions.length; 238 int count = _partitions.length;
241 for (int i = 0; i < count; i++) { 239 for (int i = 0; i < count; i++) {
242 size += _partitions[i].size(); 240 size += _partitions[i].size();
243 } 241 }
244 return size; 242 return size;
245 } 243 }
246 } 244 }
247 245
248 /** 246 /**
249 * The information cached by an analysis context about an individual target. 247 * The information cached by an analysis context about an individual target.
250 */ 248 */
251 class CacheEntry { 249 class CacheEntry {
252 /** 250 /**
253 * The index of the flag indicating whether the source was explicitly added to 251 * The index of the flag indicating whether the source was explicitly added to
254 * the context or whether the source was implicitly added because it was 252 * the context or whether the source was implicitly added because it was
255 * referenced by another source. 253 * referenced by another source.
256 */ 254 */
257 static int _EXPLICITLY_ADDED_FLAG = 0; 255 static int _EXPLICITLY_ADDED_FLAG = 0;
258 256
259 /** 257 /**
258 * The next invalidation process identifier.
259 */
260 static int nextInvalidateId = 0;
261
262 /**
260 * The target this entry is about. 263 * The target this entry is about.
261 */ 264 */
262 final AnalysisTarget target; 265 final AnalysisTarget target;
263 266
264 /** 267 /**
265 * The partition that is responsible for this entry. 268 * The partition that is responsible for this entry.
266 */ 269 */
267 CachePartition _partition; 270 CachePartition _partition;
268 271
269 /** 272 /**
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after
438 if (state == CacheState.ERROR) { 441 if (state == CacheState.ERROR) {
439 throw new ArgumentError('use setErrorState() to set the state to ERROR'); 442 throw new ArgumentError('use setErrorState() to set the state to ERROR');
440 } 443 }
441 if (state == CacheState.VALID) { 444 if (state == CacheState.VALID) {
442 throw new ArgumentError('use setValue() to set the state to VALID'); 445 throw new ArgumentError('use setValue() to set the state to VALID');
443 } 446 }
444 _validateStateChange(descriptor, state); 447 _validateStateChange(descriptor, state);
445 if (state == CacheState.INVALID) { 448 if (state == CacheState.INVALID) {
446 ResultData data = _resultMap[descriptor]; 449 ResultData data = _resultMap[descriptor];
447 if (data != null) { 450 if (data != null) {
448 _invalidate(descriptor, delta); 451 _invalidate(nextInvalidateId++, descriptor, delta, 0);
449 } 452 }
450 } else { 453 } else {
451 ResultData data = getResultData(descriptor); 454 ResultData data = getResultData(descriptor);
452 data.state = state; 455 data.state = state;
453 if (state != CacheState.IN_PROCESS) { 456 if (state != CacheState.IN_PROCESS) {
454 // 457 //
455 // If the state is in-process, we can leave the current value in the 458 // If the state is in-process, we can leave the current value in the
456 // cache for any 'get' methods to access. 459 // cache for any 'get' methods to access.
457 // 460 //
458 data.value = descriptor.defaultValue; 461 data.value = descriptor.defaultValue;
459 } 462 }
460 } 463 }
461 } 464 }
462 465
463 /** 466 /**
464 * Set the value of the result represented by the given [descriptor] to the 467 * Set the value of the result represented by the given [descriptor] to the
465 * given [value]. 468 * given [value].
466 */ 469 */
467 /*<V>*/ void setValue(ResultDescriptor /*<V>*/ descriptor, dynamic /*V*/ 470 /*<V>*/ void setValue(
468 value, List<TargetedResult> dependedOn) { 471 ResultDescriptor /*<V>*/ descriptor,
472 dynamic /*V*/
473 value,
474 List<TargetedResult> dependedOn) {
469 // { 475 // {
470 // String valueStr = '$value'; 476 // String valueStr = '$value';
471 // if (valueStr.length > 20) { 477 // if (valueStr.length > 20) {
472 // valueStr = valueStr.substring(0, 20) + '...'; 478 // valueStr = valueStr.substring(0, 20) + '...';
473 // } 479 // }
474 // valueStr = valueStr.replaceAll('\n', '\\n'); 480 // valueStr = valueStr.replaceAll('\n', '\\n');
475 // print( 481 // print(
476 // 'setValue $descriptor for $target value=$valueStr deps=$dependedOn') ; 482 // 'setValue $descriptor for $target value=$valueStr deps=$dependedOn') ;
477 // } 483 // }
478 _validateStateChange(descriptor, CacheState.VALID); 484 _validateStateChange(descriptor, CacheState.VALID);
479 TargetedResult thisResult = new TargetedResult(target, descriptor); 485 TargetedResult thisResult = new TargetedResult(target, descriptor);
480 if (_partition != null) { 486 if (_partition != null) {
481 _partition.resultStored(thisResult, value); 487 _partition.resultStored(thisResult, value);
482 } 488 }
483 ResultData data = getResultData(descriptor); 489 ResultData data = getResultData(descriptor);
484 _setDependedOnResults(data, thisResult, dependedOn); 490 _setDependedOnResults(data, thisResult, dependedOn);
485 data.state = CacheState.VALID; 491 data.state = CacheState.VALID;
486 data.value = value == null ? descriptor.defaultValue : value; 492 data.value = value == null ? descriptor.defaultValue : value;
487 } 493 }
488 494
489 /** 495 /**
490 * Set the value of the result represented by the given [descriptor] to the 496 * Set the value of the result represented by the given [descriptor] to the
491 * given [value], keep its dependency, invalidate all the dependent result. 497 * given [value], keep its dependency, invalidate all the dependent result.
492 */ 498 */
493 void setValueIncremental(ResultDescriptor descriptor, dynamic value) { 499 void setValueIncremental(
500 ResultDescriptor descriptor, dynamic value, bool invalidateDependent) {
494 ResultData data = getResultData(descriptor); 501 ResultData data = getResultData(descriptor);
495 List<TargetedResult> dependedOn = data.dependedOnResults; 502 data.state = CacheState.VALID;
496 _invalidate(descriptor, null); 503 data.value = value;
497 setValue(descriptor, value, dependedOn); 504 if (invalidateDependent) {
505 _invalidateDependentResults(nextInvalidateId++, data, null, 0);
506 }
498 } 507 }
499 508
500 @override 509 @override
501 String toString() { 510 String toString() {
502 StringBuffer buffer = new StringBuffer(); 511 StringBuffer buffer = new StringBuffer();
503 _writeOn(buffer); 512 _writeOn(buffer);
504 return buffer.toString(); 513 return buffer.toString();
505 } 514 }
506 515
507 /** 516 /**
508 * Return the value of the flag with the given [index]. 517 * Return the value of the flag with the given [index].
509 */ 518 */
510 bool _getFlag(int index) => BooleanArray.get(_flags, index); 519 bool _getFlag(int index) => BooleanArray.get(_flags, index);
511 520
512 /** 521 /**
513 * Invalidate the result represented by the given [descriptor] and propagate 522 * Invalidate the result represented by the given [descriptor] and propagate
514 * invalidation to other results that depend on it. 523 * invalidation to other results that depend on it.
515 */ 524 */
516 void _invalidate(ResultDescriptor descriptor, Delta delta) { 525 void _invalidate(
526 int id, ResultDescriptor descriptor, Delta delta, int level) {
527 ResultData thisData = _resultMap[descriptor];
528 if (thisData == null) {
529 return;
530 }
531 // Stop if already validated.
532 if (delta != null) {
533 if (thisData.invalidateId == id) {
534 return;
535 }
536 thisData.invalidateId = id;
537 }
538 // Ask the delta to validate.
517 DeltaResult deltaResult = null; 539 DeltaResult deltaResult = null;
518 if (delta != null) { 540 if (delta != null) {
519 deltaResult = delta.validate(_partition.context, target, descriptor); 541 deltaResult = delta.validate(_partition.context, target, descriptor);
520 if (deltaResult == DeltaResult.STOP) { 542 if (deltaResult == DeltaResult.STOP) {
521 // print('not-invalidate $descriptor for $target');
522 return; 543 return;
523 } 544 }
524 } 545 }
525 // print('invalidate $descriptor for $target'); 546 if (deltaResult == DeltaResult.INVALIDATE_NO_DELTA) {
526 ResultData thisData; 547 delta = null;
527 if (deltaResult == null || deltaResult == DeltaResult.INVALIDATE) {
528 thisData = _resultMap.remove(descriptor);
529 } 548 }
530 if (deltaResult == DeltaResult.KEEP_CONTINUE) { 549 if (deltaResult == null ||
531 thisData = _resultMap[descriptor]; 550 deltaResult == DeltaResult.INVALIDATE ||
532 } 551 deltaResult == DeltaResult.INVALIDATE_NO_DELTA) {
533 if (thisData == null) { 552 _resultMap.remove(descriptor);
534 return; 553 // {
554 // String indent = ' ' * level;
555 // print('[$id]$indent invalidate $descriptor for $target');
556 // }
535 } 557 }
536 // Stop depending on other results. 558 // Stop depending on other results.
537 TargetedResult thisResult = new TargetedResult(target, descriptor); 559 TargetedResult thisResult = new TargetedResult(target, descriptor);
538 for (TargetedResult dependedOnResult in thisData.dependedOnResults) { 560 for (TargetedResult dependedOnResult in thisData.dependedOnResults) {
539 ResultData data = _partition._getDataFor(dependedOnResult); 561 ResultData data = _partition._getDataFor(dependedOnResult);
540 if (data != null) { 562 if (data != null && deltaResult != DeltaResult.KEEP_CONTINUE) {
541 data.dependentResults.remove(thisResult); 563 data.dependentResults.remove(thisResult);
542 } 564 }
543 } 565 }
544 // Invalidate results that depend on this result. 566 // Invalidate results that depend on this result.
545 List<TargetedResult> dependentResults = thisData.dependentResults.toList(); 567 _invalidateDependentResults(id, thisData, delta, level + 1);
546 for (TargetedResult dependentResult in dependentResults) {
547 CacheEntry entry = _partition.get(dependentResult.target);
548 if (entry != null) {
549 entry._invalidate(dependentResult.result, delta);
550 }
551 }
552 // If empty, remove the entry altogether. 568 // If empty, remove the entry altogether.
553 if (_resultMap.isEmpty) { 569 if (_resultMap.isEmpty) {
554 _partition._targetMap.remove(target); 570 _partition._targetMap.remove(target);
555 _partition._removeIfSource(target); 571 _partition._removeIfSource(target);
556 } 572 }
557 // Notify controller. 573 // Notify controller.
558 _partition._onResultInvalidated 574 _partition.onResultInvalidated
559 .add(new InvalidatedResult(this, descriptor)); 575 .add(new InvalidatedResult(this, descriptor, thisData.value));
560 } 576 }
561 577
562 /** 578 /**
563 * Invalidates all the results of this entry, with propagation. 579 * Invalidates all the results of this entry, with propagation.
564 */ 580 */
565 void _invalidateAll() { 581 void _invalidateAll() {
566 List<ResultDescriptor> results = _resultMap.keys.toList(); 582 List<ResultDescriptor> results = _resultMap.keys.toList();
567 for (ResultDescriptor result in results) { 583 for (ResultDescriptor result in results) {
568 _invalidate(result, null); 584 _invalidate(nextInvalidateId++, result, null, 0);
569 } 585 }
570 } 586 }
571 587
588 /**
589 * Invalidate results that depend on [thisData].
590 */
591 void _invalidateDependentResults(
592 int id, ResultData thisData, Delta delta, int level) {
593 List<TargetedResult> dependentResults = thisData.dependentResults.toList();
594 for (TargetedResult dependentResult in dependentResults) {
595 CacheEntry entry = _partition.get(dependentResult.target);
596 if (entry != null) {
597 entry._invalidate(id, dependentResult.result, delta, level);
598 }
599 }
600 }
601
572 /** 602 /**
573 * Set the [dependedOn] on which this result depends. 603 * Set the [dependedOn] on which this result depends.
574 */ 604 */
575 void _setDependedOnResults(ResultData thisData, TargetedResult thisResult, 605 void _setDependedOnResults(ResultData thisData, TargetedResult thisResult,
576 List<TargetedResult> dependedOn) { 606 List<TargetedResult> dependedOn) {
577 thisData.dependedOnResults.forEach((TargetedResult dependedOnResult) { 607 thisData.dependedOnResults.forEach((TargetedResult dependedOnResult) {
578 ResultData data = _partition._getDataFor(dependedOnResult); 608 ResultData data = _partition._getDataFor(dependedOnResult);
579 if (data != null) { 609 if (data != null) {
580 data.dependentResults.remove(thisResult); 610 data.dependentResults.remove(thisResult);
581 } 611 }
(...skipping 214 matching lines...) Expand 10 before | Expand all | Expand 10 after
796 826
797 /** 827 /**
798 * A table mapping caching policies to the cache flush managers. 828 * A table mapping caching policies to the cache flush managers.
799 */ 829 */
800 final HashMap<ResultCachingPolicy, CacheFlushManager> _flushManagerMap = 830 final HashMap<ResultCachingPolicy, CacheFlushManager> _flushManagerMap =
801 new HashMap<ResultCachingPolicy, CacheFlushManager>(); 831 new HashMap<ResultCachingPolicy, CacheFlushManager>();
802 832
803 /** 833 /**
804 * The [StreamController] reporting [InvalidatedResult]s. 834 * The [StreamController] reporting [InvalidatedResult]s.
805 */ 835 */
806 final StreamController<InvalidatedResult> _onResultInvalidated = 836 final ReentrantSynchronousStream<InvalidatedResult> onResultInvalidated =
807 new StreamController<InvalidatedResult>.broadcast(sync: true); 837 new ReentrantSynchronousStream<InvalidatedResult>();
808 838
809 /** 839 /**
810 * A table mapping the targets belonging to this partition to the information 840 * A table mapping the targets belonging to this partition to the information
811 * known about those targets. 841 * known about those targets.
812 */ 842 */
813 HashMap<AnalysisTarget, CacheEntry> _targetMap = 843 HashMap<AnalysisTarget, CacheEntry> _targetMap =
814 new HashMap<AnalysisTarget, CacheEntry>(); 844 new HashMap<AnalysisTarget, CacheEntry>();
815 845
816 /** 846 /**
817 * A set of the [Source] targets. 847 * A set of the [Source] targets.
(...skipping 14 matching lines...) Expand all
832 /** 862 /**
833 * Return a table mapping the targets known to the context to the information 863 * Return a table mapping the targets known to the context to the information
834 * known about the target. 864 * known about the target.
835 * 865 *
836 * <b>Note:</b> This method is only visible for use by [AnalysisCache] and 866 * <b>Note:</b> This method is only visible for use by [AnalysisCache] and
837 * should not be used for any other purpose. 867 * should not be used for any other purpose.
838 */ 868 */
839 Map<AnalysisTarget, CacheEntry> get map => _targetMap; 869 Map<AnalysisTarget, CacheEntry> get map => _targetMap;
840 870
841 /** 871 /**
842 * Return the stream that is notified when a value is invalidated.
843 */
844 Stream<InvalidatedResult> get onResultInvalidated =>
845 _onResultInvalidated.stream;
846
847 /**
848 * Notifies the partition that the client is going to stop using it. 872 * Notifies the partition that the client is going to stop using it.
849 */ 873 */
850 void dispose() { 874 void dispose() {
851 for (CacheEntry entry in _targetMap.values) { 875 for (CacheEntry entry in _targetMap.values) {
852 entry.dispose(); 876 entry.dispose();
853 } 877 }
854 _targetMap.clear(); 878 _targetMap.clear();
855 } 879 }
856 880
857 /** 881 /**
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
889 throw new StateError( 913 throw new StateError(
890 'The entry for $target is already in ${entry._partition}'); 914 'The entry for $target is already in ${entry._partition}');
891 } 915 }
892 entry._partition = this; 916 entry._partition = this;
893 entry.fixExceptionState(); 917 entry.fixExceptionState();
894 _targetMap[target] = entry; 918 _targetMap[target] = entry;
895 _addIfSource(target); 919 _addIfSource(target);
896 } 920 }
897 921
898 /** 922 /**
899 * Remove all information related to the given [target] from this cache. 923 * Remove all information related to the given [target] from this partition.
924 * Return the entry associated with the target, or `null` if there was cache
925 * entry for the target.
900 */ 926 */
901 void remove(AnalysisTarget target) { 927 CacheEntry remove(AnalysisTarget target) {
902 for (CacheFlushManager flushManager in _flushManagerMap.values) { 928 for (CacheFlushManager flushManager in _flushManagerMap.values) {
903 flushManager.targetRemoved(target); 929 flushManager.targetRemoved(target);
904 } 930 }
905 CacheEntry entry = _targetMap.remove(target); 931 CacheEntry entry = _targetMap.remove(target);
906 if (entry != null) { 932 if (entry != null) {
907 entry._invalidateAll(); 933 entry._invalidateAll();
908 } 934 }
909 _removeIfSource(target); 935 _removeIfSource(target);
936 return entry;
910 } 937 }
911 938
912 /** 939 /**
913 * Records that a value of the result described by the given [descriptor] 940 * Records that a value of the result described by the given [descriptor]
914 * for the given [target] was just read from the cache. 941 * for the given [target] was just read from the cache.
915 */ 942 */
916 void resultAccessed(AnalysisTarget target, ResultDescriptor descriptor) { 943 void resultAccessed(AnalysisTarget target, ResultDescriptor descriptor) {
917 CacheFlushManager flushManager = _getFlushManager(descriptor); 944 CacheFlushManager flushManager = _getFlushManager(descriptor);
918 TargetedResult result = new TargetedResult(target, descriptor); 945 TargetedResult result = new TargetedResult(target, descriptor);
919 flushManager.resultAccessed(result); 946 flushManager.resultAccessed(result);
(...skipping 21 matching lines...) Expand all
941 * Return the number of targets that are mapped to cache entries. 968 * Return the number of targets that are mapped to cache entries.
942 */ 969 */
943 int size() => _targetMap.length; 970 int size() => _targetMap.length;
944 971
945 /** 972 /**
946 * If the given [target] is a [Source], adds it to [_sources]. 973 * If the given [target] is a [Source], adds it to [_sources].
947 */ 974 */
948 void _addIfSource(AnalysisTarget target) { 975 void _addIfSource(AnalysisTarget target) {
949 if (target is Source) { 976 if (target is Source) {
950 _sources.add(target); 977 _sources.add(target);
951 { 978 String fullName = target.fullName;
952 String fullName = target.fullName; 979 _pathToSources.putIfAbsent(fullName, () => <Source>[]).add(target);
953 _pathToSources.putIfAbsent(fullName, () => <Source>[]).add(target);
954 }
955 } 980 }
956 } 981 }
957 982
958 ResultData _getDataFor(TargetedResult result) { 983 ResultData _getDataFor(TargetedResult result) {
959 CacheEntry entry = context.analysisCache.get(result.target); 984 CacheEntry entry = context.analysisCache.get(result.target);
960 return entry != null ? entry._resultMap[result.result] : null; 985 return entry != null ? entry._resultMap[result.result] : null;
961 } 986 }
962 987
963 /** 988 /**
964 * Return the [CacheFlushManager] for the given [descriptor], not `null`. 989 * Return the [CacheFlushManager] for the given [descriptor], not `null`.
965 */ 990 */
966 CacheFlushManager _getFlushManager(ResultDescriptor descriptor) { 991 CacheFlushManager _getFlushManager(ResultDescriptor descriptor) {
967 ResultCachingPolicy policy = descriptor.cachingPolicy; 992 ResultCachingPolicy policy = descriptor.cachingPolicy;
968 if (identical(policy, DEFAULT_CACHING_POLICY)) { 993 if (identical(policy, DEFAULT_CACHING_POLICY)) {
969 return UnlimitedCacheFlushManager.INSTANCE; 994 return UnlimitedCacheFlushManager.INSTANCE;
970 } 995 }
971 CacheFlushManager manager = _flushManagerMap[policy]; 996 CacheFlushManager manager = _flushManagerMap[policy];
972 if (manager == null) { 997 if (manager == null) {
973 manager = new CacheFlushManager(policy, _isPriorityAnalysisTarget); 998 manager = new CacheFlushManager(policy, _isPriorityAnalysisTarget);
974 _flushManagerMap[policy] = manager; 999 _flushManagerMap[policy] = manager;
975 } 1000 }
976 return manager; 1001 return manager;
977 } 1002 }
978 1003
979 bool _isPriorityAnalysisTarget(AnalysisTarget target) { 1004 bool _isPriorityAnalysisTarget(AnalysisTarget target) {
980 return context.priorityTargets.contains(target); 1005 return context.priorityTargets.contains(target);
981 } 1006 }
982 1007
983 /** 1008 /**
984 * If the given [target] is a [Source], removes it from [_sources]. 1009 * If the given [target] is a [Source], remove it from the list of [_sources].
985 */ 1010 */
986 void _removeIfSource(AnalysisTarget target) { 1011 void _removeIfSource(AnalysisTarget target) {
987 if (target is Source) { 1012 if (target is Source) {
988 _sources.remove(target); 1013 _sources.remove(target);
989 { 1014 String fullName = target.fullName;
990 String fullName = target.fullName; 1015 List<Source> sources = _pathToSources[fullName];
991 List<Source> sources = _pathToSources[fullName]; 1016 if (sources != null) {
992 if (sources != null) { 1017 sources.remove(target);
993 sources.remove(target); 1018 if (sources.isEmpty) {
994 if (sources.isEmpty) { 1019 _pathToSources.remove(fullName);
995 _pathToSources.remove(fullName);
996 }
997 } 1020 }
998 } 1021 }
999 } 1022 }
1000 } 1023 }
1001 } 1024 }
1002 1025
1003 /** 1026 /**
1004 * The description for a change. 1027 * The description for a change.
1005 */ 1028 */
1006 class Delta { 1029 class Delta {
1007 final Source source; 1030 final Source source;
1008 1031
1009 Delta(this.source); 1032 Delta(this.source);
1010 1033
1011 /** 1034 /**
1012 * Check whether this delta affects the result described by the given 1035 * Check whether this delta affects the result described by the given
1013 * [descriptor] and [target]. 1036 * [descriptor] and [target].
1014 */ 1037 */
1015 DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target, 1038 DeltaResult validate(InternalAnalysisContext context, AnalysisTarget target,
1016 ResultDescriptor descriptor) { 1039 ResultDescriptor descriptor) {
1017 return DeltaResult.INVALIDATE; 1040 return DeltaResult.INVALIDATE;
1018 } 1041 }
1019 } 1042 }
1020 1043
1021 /** 1044 /**
1022 * The possible results of validating analysis results againt a [Delta]. 1045 * The possible results of validating analysis results againt a [Delta].
1023 */ 1046 */
1024 enum DeltaResult { INVALIDATE, KEEP_CONTINUE, STOP } 1047 enum DeltaResult {
1048 /**
1049 * Invalidate this result and continue visiting dependent results
1050 * with this [Delta].
1051 */
1052 INVALIDATE,
1053
1054 /**
1055 * Invalidate this result and stop using this [Delta], so unconditionally
1056 * invalidate all the dependent results.
1057 */
1058 INVALIDATE_NO_DELTA,
1059
1060 /**
1061 * Keep this result and continue validating dependent results
1062 * with this [Delta].
1063 */
1064 KEEP_CONTINUE,
1065
1066 /**
1067 * Keep this result and stop visiting results that depend on this one.
1068 */
1069 STOP
1070 }
1025 1071
1026 /** 1072 /**
1027 * [InvalidatedResult] describes an invalidated result. 1073 * [InvalidatedResult] describes an invalidated result.
1028 */ 1074 */
1029 class InvalidatedResult { 1075 class InvalidatedResult {
1030 /** 1076 /**
1031 * The target in which the result was invalidated. 1077 * The target in which the result was invalidated.
1032 */ 1078 */
1033 final CacheEntry entry; 1079 final CacheEntry entry;
1034 1080
1035 /** 1081 /**
1036 * The descriptor of the result which was invalidated. 1082 * The descriptor of the result which was invalidated.
1037 */ 1083 */
1038 final ResultDescriptor descriptor; 1084 final ResultDescriptor descriptor;
1039 1085
1040 InvalidatedResult(this.entry, this.descriptor); 1086 /**
1087 * The value of the result which was invalidated.
1088 */
1089 final Object value;
1090
1091 InvalidatedResult(this.entry, this.descriptor, this.value);
1041 1092
1042 @override 1093 @override
1043 String toString() => '$descriptor of ${entry.target}'; 1094 String toString() => '$descriptor of ${entry.target}';
1044 } 1095 }
1045 1096
1046 /** 1097 /**
1098 * A Stream-like interface, which broadcasts events synchronously.
1099 * If a second event is fired while delivering a first event, then the second
1100 * event will be delivered first, and then delivering of the first will be
1101 * continued.
1102 */
1103 class ReentrantSynchronousStream<T> {
1104 final List<Function> listeners = <Function>[];
1105
1106 /**
1107 * Send the given [event] to the stream.
1108 */
1109 void add(T event) {
1110 List<Function> listeners = this.listeners.toList();
1111 for (Function listener in listeners) {
1112 listener(event);
1113 }
1114 }
1115
1116 /**
1117 * Listen for the events in this stream.
1118 * Note that if the [listener] fires a new event, then the [listener] will be
1119 * invoked again before returning from the [add] invocation.
1120 */
1121 void listen(void listener(T event)) {
1122 listeners.add(listener);
1123 }
1124 }
1125
1126 /**
1047 * The data about a single analysis result that is stored in a [CacheEntry]. 1127 * The data about a single analysis result that is stored in a [CacheEntry].
1048 */ 1128 */
1049 // TODO(brianwilkerson) Consider making this a generic class so that the value 1129 // TODO(brianwilkerson) Consider making this a generic class so that the value
1050 // can be typed. 1130 // can be typed.
1051 class ResultData { 1131 class ResultData {
1052 /** 1132 /**
1053 * The [ResultDescriptor] this result is for. 1133 * The [ResultDescriptor] this result is for.
1054 */ 1134 */
1055 final ResultDescriptor descriptor; 1135 final ResultDescriptor descriptor;
1056 1136
1057 /** 1137 /**
1058 * The state of the cached value. 1138 * The state of the cached value.
1059 */ 1139 */
1060 CacheState state; 1140 CacheState state;
1061 1141
1062 /** 1142 /**
1063 * The value being cached, or the default value for the result if there is no 1143 * The value being cached, or the default value for the result if there is no
1064 * value (for example, when the [state] is [CacheState.INVALID]). 1144 * value (for example, when the [state] is [CacheState.INVALID]).
1065 */ 1145 */
1066 Object value; 1146 Object value;
1067 1147
1068 /** 1148 /**
1149 * The identifier of the invalidation process that most recently checked
1150 * this value. If it is the same as the current invalidation identifier,
1151 * then there is no reason to check it (and its subtree again).
1152 */
1153 int invalidateId = -1;
1154
1155 /**
1069 * A list of the results on which this result depends. 1156 * A list of the results on which this result depends.
1070 */ 1157 */
1071 List<TargetedResult> dependedOnResults = <TargetedResult>[]; 1158 List<TargetedResult> dependedOnResults = <TargetedResult>[];
1072 1159
1073 /** 1160 /**
1074 * A list of the results that depend on this result. 1161 * A list of the results that depend on this result.
1075 */ 1162 */
1076 Set<TargetedResult> dependentResults = new Set<TargetedResult>(); 1163 Set<TargetedResult> dependentResults = new Set<TargetedResult>();
1077 1164
1078 /** 1165 /**
(...skipping 28 matching lines...) Expand all
1107 bool isResponsibleFor(AnalysisTarget target) { 1194 bool isResponsibleFor(AnalysisTarget target) {
1108 if (target is AnalysisContextTarget) { 1195 if (target is AnalysisContextTarget) {
1109 return true; 1196 return true;
1110 } 1197 }
1111 Source source = target.source; 1198 Source source = target.source;
1112 return source != null && source.isInSystemLibrary; 1199 return source != null && source.isInSystemLibrary;
1113 } 1200 }
1114 } 1201 }
1115 1202
1116 /** 1203 /**
1117 * A specification of a specific result computed for a specific target.
1118 */
1119 class TargetedResult {
1120 /**
1121 * An empty list of results.
1122 */
1123 static final List<TargetedResult> EMPTY_LIST = const <TargetedResult>[];
1124
1125 /**
1126 * The target with which the result is associated.
1127 */
1128 final AnalysisTarget target;
1129
1130 /**
1131 * The result associated with the target.
1132 */
1133 final ResultDescriptor result;
1134
1135 /**
1136 * Initialize a new targeted result.
1137 */
1138 TargetedResult(this.target, this.result);
1139
1140 @override
1141 int get hashCode {
1142 return JenkinsSmiHash.combine(target.hashCode, result.hashCode);
1143 }
1144
1145 @override
1146 bool operator ==(other) {
1147 return other is TargetedResult &&
1148 other.target == target &&
1149 other.result == result;
1150 }
1151
1152 @override
1153 String toString() => '$result for $target';
1154 }
1155
1156 /**
1157 * A cache partition that contains all targets not contained in other partitions . 1204 * A cache partition that contains all targets not contained in other partitions .
1158 */ 1205 */
1159 class UniversalCachePartition extends CachePartition { 1206 class UniversalCachePartition extends CachePartition {
1160 /** 1207 /**
1161 * Initialize a newly created cache partition, belonging to the given 1208 * Initialize a newly created cache partition, belonging to the given
1162 * [context]. 1209 * [context].
1163 */ 1210 */
1164 UniversalCachePartition(InternalAnalysisContext context) : super(context); 1211 UniversalCachePartition(InternalAnalysisContext context) : super(context);
1165 1212
1166 @override 1213 @override
(...skipping 12 matching lines...) Expand all
1179 void resultAccessed(TargetedResult result) {} 1226 void resultAccessed(TargetedResult result) {}
1180 1227
1181 @override 1228 @override
1182 List<TargetedResult> resultStored(TargetedResult newResult, newValue) { 1229 List<TargetedResult> resultStored(TargetedResult newResult, newValue) {
1183 return TargetedResult.EMPTY_LIST; 1230 return TargetedResult.EMPTY_LIST;
1184 } 1231 }
1185 1232
1186 @override 1233 @override
1187 void targetRemoved(AnalysisTarget target) {} 1234 void targetRemoved(AnalysisTarget target) {}
1188 } 1235 }
OLDNEW
« no previous file with comments | « packages/analyzer/lib/src/cancelable_future.dart ('k') | packages/analyzer/lib/src/context/context.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698