| 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:collection'; | 7 import 'dart:collection'; |
| 8 | 8 |
| 9 import 'package:analyzer/src/generated/engine.dart' | 9 import 'package:analyzer/src/generated/engine.dart' |
| 10 show AnalysisEngine, CacheState, InternalAnalysisContext, RetentionPriority; | 10 show AnalysisEngine, CacheState, InternalAnalysisContext, RetentionPriority; |
| (...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 165 * Return the number of targets that are mapped to cache entries. | 165 * Return the number of targets that are mapped to cache entries. |
| 166 */ | 166 */ |
| 167 int size() { | 167 int size() { |
| 168 int size = 0; | 168 int size = 0; |
| 169 int count = _partitions.length; | 169 int count = _partitions.length; |
| 170 for (int i = 0; i < count; i++) { | 170 for (int i = 0; i < count; i++) { |
| 171 size += _partitions[i].size(); | 171 size += _partitions[i].size(); |
| 172 } | 172 } |
| 173 return size; | 173 return size; |
| 174 } | 174 } |
| 175 | |
| 176 ResultData _getDataFor(TargetedResult result) { | |
| 177 CacheEntry entry = get(result.target); | |
| 178 if (entry != null) { | |
| 179 return entry._getResultData(result.result); | |
| 180 } | |
| 181 return null; | |
| 182 } | |
| 183 } | 175 } |
| 184 | 176 |
| 185 /** | 177 /** |
| 186 * The information cached by an analysis context about an individual target. | 178 * The information cached by an analysis context about an individual target. |
| 187 */ | 179 */ |
| 188 class CacheEntry { | 180 class CacheEntry { |
| 189 /** | 181 /** |
| 190 * The index of the flag indicating whether the source was explicitly added to | 182 * The index of the flag indicating whether the source was explicitly added to |
| 191 * the context or whether the source was implicitly added because it was | 183 * the context or whether the source was implicitly added because it was |
| 192 * referenced by another source. | 184 * referenced by another source. |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 326 void setErrorState( | 318 void setErrorState( |
| 327 CaughtException exception, List<ResultDescriptor> descriptors) { | 319 CaughtException exception, List<ResultDescriptor> descriptors) { |
| 328 if (descriptors == null || descriptors.isEmpty) { | 320 if (descriptors == null || descriptors.isEmpty) { |
| 329 throw new ArgumentError('at least one descriptor is expected'); | 321 throw new ArgumentError('at least one descriptor is expected'); |
| 330 } | 322 } |
| 331 if (exception == null) { | 323 if (exception == null) { |
| 332 throw new ArgumentError('an exception is expected'); | 324 throw new ArgumentError('an exception is expected'); |
| 333 } | 325 } |
| 334 this._exception = exception; | 326 this._exception = exception; |
| 335 for (ResultDescriptor descriptor in descriptors) { | 327 for (ResultDescriptor descriptor in descriptors) { |
| 336 _invalidate(descriptor, exception); | 328 _setErrorState(descriptor, exception); |
| 337 } | 329 } |
| 338 } | 330 } |
| 339 | 331 |
| 340 /** | 332 /** |
| 341 * Set the state of the result represented by the given [descriptor] to the | 333 * Set the state of the result represented by the given [descriptor] to the |
| 342 * given [state]. | 334 * given [state]. |
| 343 */ | 335 */ |
| 344 void setState(ResultDescriptor descriptor, CacheState state) { | 336 void setState(ResultDescriptor descriptor, CacheState state) { |
| 345 if (state == CacheState.ERROR) { | 337 if (state == CacheState.ERROR) { |
| 346 throw new ArgumentError('use setErrorState() to set the state to ERROR'); | 338 throw new ArgumentError('use setErrorState() to set the state to ERROR'); |
| 347 } | 339 } |
| 348 if (state == CacheState.VALID) { | 340 if (state == CacheState.VALID) { |
| 349 throw new ArgumentError('use setValue() to set the state to VALID'); | 341 throw new ArgumentError('use setValue() to set the state to VALID'); |
| 350 } | 342 } |
| 351 _validateStateChange(descriptor, state); | 343 _validateStateChange(descriptor, state); |
| 352 if (state == CacheState.INVALID) { | 344 if (state == CacheState.INVALID) { |
| 353 ResultData data = _resultMap[descriptor]; | 345 ResultData data = _resultMap[descriptor]; |
| 354 if (data != null) { | 346 if (data != null) { |
| 355 _invalidate(descriptor, null); | 347 _invalidate(descriptor, true); |
| 356 } | 348 } |
| 357 } else { | 349 } else { |
| 358 ResultData data = _getResultData(descriptor); | 350 ResultData data = _getResultData(descriptor); |
| 359 data.state = state; | 351 data.state = state; |
| 360 if (state != CacheState.IN_PROCESS) { | 352 if (state != CacheState.IN_PROCESS) { |
| 361 // | 353 // |
| 362 // If the state is in-process, we can leave the current value in the | 354 // If the state is in-process, we can leave the current value in the |
| 363 // cache for any 'get' methods to access. | 355 // cache for any 'get' methods to access. |
| 364 // | 356 // |
| 365 data.value = descriptor.defaultValue; | 357 data.value = descriptor.defaultValue; |
| 366 } | 358 } |
| 367 } | 359 } |
| 368 } | 360 } |
| 369 | 361 |
| 370 /** | 362 /** |
| 371 * Set the value of the result represented by the given [descriptor] to the | 363 * Set the value of the result represented by the given [descriptor] to the |
| 372 * given [value]. | 364 * given [value]. |
| 373 */ | 365 */ |
| 374 /*<V>*/ void setValue(ResultDescriptor /*<V>*/ descriptor, dynamic /*V*/ | 366 /*<V>*/ void setValue(ResultDescriptor /*<V>*/ descriptor, dynamic /*V*/ |
| 375 value, List<TargetedResult> dependedOn) { | 367 value, List<TargetedResult> dependedOn) { |
| 376 _validateStateChange(descriptor, CacheState.VALID); | 368 _validateStateChange(descriptor, CacheState.VALID); |
| 377 TargetedResult thisResult = new TargetedResult(target, descriptor); | 369 TargetedResult thisResult = new TargetedResult(target, descriptor); |
| 378 if (_partition != null) { | 370 if (_partition != null) { |
| 379 _partition.resultStored(thisResult, value); | 371 _partition.resultStored(thisResult, value); |
| 380 } | 372 } |
| 381 _invalidate(descriptor, null); | 373 _invalidate(descriptor, false); |
| 382 ResultData data = _getResultData(descriptor); | 374 ResultData data = _getResultData(descriptor); |
| 383 _setDependedOnResults(data, thisResult, dependedOn); | 375 _setDependedOnResults(data, thisResult, dependedOn); |
| 384 data.state = CacheState.VALID; | 376 data.state = CacheState.VALID; |
| 385 data.value = value == null ? descriptor.defaultValue : value; | 377 data.value = value == null ? descriptor.defaultValue : value; |
| 386 } | 378 } |
| 387 | 379 |
| 388 @override | 380 @override |
| 389 String toString() { | 381 String toString() { |
| 390 StringBuffer buffer = new StringBuffer(); | 382 StringBuffer buffer = new StringBuffer(); |
| 391 _writeOn(buffer); | 383 _writeOn(buffer); |
| 392 return buffer.toString(); | 384 return buffer.toString(); |
| 393 } | 385 } |
| 394 | 386 |
| 395 /** | 387 /** |
| 396 * Return the value of the flag with the given [index]. | 388 * Return the value of the flag with the given [index]. |
| 397 */ | 389 */ |
| 398 bool _getFlag(int index) => BooleanArray.get(_flags, index); | 390 bool _getFlag(int index) => BooleanArray.get(_flags, index); |
| 399 | 391 |
| 400 /** | 392 /** |
| 401 * Look up the [ResultData] of [descriptor], or add a new one if it isn't | 393 * Look up the [ResultData] of [descriptor], or add a new one if it isn't |
| 402 * there. | 394 * there. |
| 403 */ | 395 */ |
| 404 ResultData _getResultData(ResultDescriptor descriptor) { | 396 ResultData _getResultData(ResultDescriptor descriptor) { |
| 405 return _resultMap.putIfAbsent(descriptor, () => new ResultData(descriptor)); | 397 return _resultMap.putIfAbsent(descriptor, () => new ResultData(descriptor)); |
| 406 } | 398 } |
| 407 | 399 |
| 408 /** | 400 /** |
| 409 * Invalidate the result represented by the given [descriptor]. | 401 * Invalidate the result represented by the given [descriptor] if |
| 410 * Propagate invalidation to other results that depend on it. | 402 * [includeThis] is true. Propagate invalidation to other results that |
| 403 * depend on it. |
| 411 */ | 404 */ |
| 412 void _invalidate(ResultDescriptor descriptor, CaughtException exception) { | 405 void _invalidate(ResultDescriptor descriptor, bool includeThis) { |
| 413 ResultData thisData = _getResultData(descriptor); | 406 ResultData thisData; |
| 414 // Invalidate this result. | 407 if (includeThis) { |
| 415 if (exception == null) { | 408 thisData = _resultMap.remove(descriptor); |
| 416 thisData.state = CacheState.INVALID; | |
| 417 } else { | 409 } else { |
| 418 thisData.state = CacheState.ERROR; | 410 thisData = _resultMap[descriptor]; |
| 419 _exception = exception; | |
| 420 } | 411 } |
| 421 thisData.value = descriptor.defaultValue; | 412 if (thisData == null) { |
| 413 return; |
| 414 } |
| 422 // Stop depending on other results. | 415 // Stop depending on other results. |
| 423 TargetedResult thisResult = new TargetedResult(target, descriptor); | 416 TargetedResult thisResult = new TargetedResult(target, descriptor); |
| 424 List<TargetedResult> dependedOnResults = thisData.dependedOnResults; | 417 thisData.dependedOnResults.forEach((TargetedResult dependedOnResult) { |
| 425 thisData.dependedOnResults = <TargetedResult>[]; | 418 ResultData data = _partition._getDataFor(dependedOnResult, orNull: true); |
| 426 dependedOnResults.forEach((TargetedResult dependedOnResult) { | 419 if (data != null) { |
| 427 ResultData data = _partition._getDataFor(dependedOnResult); | 420 data.dependentResults.remove(thisResult); |
| 428 data.dependentResults.remove(thisResult); | 421 } |
| 429 }); | 422 }); |
| 430 // Invalidate results that depend on this result. | 423 // Invalidate results that depend on this result. |
| 431 List<TargetedResult> dependentResults = thisData.dependentResults; | 424 List<TargetedResult> dependentResults = thisData.dependentResults; |
| 432 thisData.dependentResults = <TargetedResult>[]; | 425 thisData.dependentResults = <TargetedResult>[]; |
| 433 dependentResults.forEach((TargetedResult dependentResult) { | 426 dependentResults.forEach((TargetedResult dependentResult) { |
| 434 CacheEntry entry = _partition.get(dependentResult.target); | 427 CacheEntry entry = _partition.get(dependentResult.target); |
| 435 entry._invalidate(dependentResult.result, exception); | 428 entry._invalidate(dependentResult.result, true); |
| 436 }); | 429 }); |
| 430 // If empty, remove the entry altogether. |
| 431 if (_resultMap.isEmpty) { |
| 432 _partition._targetMap.remove(target); |
| 433 } |
| 437 } | 434 } |
| 438 | 435 |
| 439 /** | 436 /** |
| 440 * Set the [dependedOn] on which this result depends. | 437 * Set the [dependedOn] on which this result depends. |
| 441 */ | 438 */ |
| 442 void _setDependedOnResults(ResultData thisData, TargetedResult thisResult, | 439 void _setDependedOnResults(ResultData thisData, TargetedResult thisResult, |
| 443 List<TargetedResult> dependedOn) { | 440 List<TargetedResult> dependedOn) { |
| 444 thisData.dependedOnResults = dependedOn; | 441 thisData.dependedOnResults = dependedOn; |
| 445 thisData.dependedOnResults.forEach((TargetedResult dependentResult) { | 442 thisData.dependedOnResults.forEach((TargetedResult dependentResult) { |
| 446 ResultData data = _partition._getDataFor(dependentResult); | 443 ResultData data = _partition._getDataFor(dependentResult); |
| 447 data.dependentResults.add(thisResult); | 444 data.dependentResults.add(thisResult); |
| 448 }); | 445 }); |
| 449 } | 446 } |
| 450 | 447 |
| 451 /** | 448 /** |
| 449 * Set states of the given and dependent results to [CacheState.ERROR] and |
| 450 * their values to the corresponding default values |
| 451 */ |
| 452 void _setErrorState(ResultDescriptor descriptor, CaughtException exception) { |
| 453 ResultData thisData = _getResultData(descriptor); |
| 454 // Set the error state. |
| 455 _exception = exception; |
| 456 thisData.state = CacheState.ERROR; |
| 457 thisData.value = descriptor.defaultValue; |
| 458 // Propagate the error state. |
| 459 thisData.dependentResults.forEach((TargetedResult dependentResult) { |
| 460 CacheEntry entry = _partition.get(dependentResult.target); |
| 461 entry._setErrorState(dependentResult.result, exception); |
| 462 }); |
| 463 } |
| 464 |
| 465 /** |
| 452 * Set the value of the flag with the given [index] to the given [value]. | 466 * Set the value of the flag with the given [index] to the given [value]. |
| 453 */ | 467 */ |
| 454 void _setFlag(int index, bool value) { | 468 void _setFlag(int index, bool value) { |
| 455 _flags = BooleanArray.set(_flags, index, value); | 469 _flags = BooleanArray.set(_flags, index, value); |
| 456 } | 470 } |
| 457 | 471 |
| 458 /** | 472 /** |
| 459 * If the state of the value described by the given [descriptor] is changing | 473 * If the state of the value described by the given [descriptor] is changing |
| 460 * from ERROR to anything else, capture the information. This is an attempt to | 474 * from ERROR to anything else, capture the information. This is an attempt to |
| 461 * discover the underlying cause of a long-standing bug. | 475 * discover the underlying cause of a long-standing bug. |
| (...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 658 /** | 672 /** |
| 659 * Return a table mapping the targets known to the context to the information | 673 * Return a table mapping the targets known to the context to the information |
| 660 * known about the target. | 674 * known about the target. |
| 661 * | 675 * |
| 662 * <b>Note:</b> This method is only visible for use by [AnalysisCache] and | 676 * <b>Note:</b> This method is only visible for use by [AnalysisCache] and |
| 663 * should not be used for any other purpose. | 677 * should not be used for any other purpose. |
| 664 */ | 678 */ |
| 665 Map<AnalysisTarget, CacheEntry> get map => _targetMap; | 679 Map<AnalysisTarget, CacheEntry> get map => _targetMap; |
| 666 | 680 |
| 667 /** | 681 /** |
| 682 * Return the entry associated with the given [target]. |
| 683 */ |
| 684 CacheEntry get(AnalysisTarget target) => _targetMap[target]; |
| 685 |
| 686 /** |
| 668 * Return `true` if this partition is responsible for the given [target]. | 687 * Return `true` if this partition is responsible for the given [target]. |
| 669 */ | 688 */ |
| 670 bool isResponsibleFor(AnalysisTarget target); | 689 bool isResponsibleFor(AnalysisTarget target); |
| 671 | 690 |
| 672 /** | 691 /** |
| 673 * Return the entry associated with the given [target]. | |
| 674 */ | |
| 675 CacheEntry get(AnalysisTarget target) => _targetMap[target]; | |
| 676 | |
| 677 /** | |
| 678 * Return an iterator returning all of the map entries mapping targets to | 692 * Return an iterator returning all of the map entries mapping targets to |
| 679 * cache entries. | 693 * cache entries. |
| 680 */ | 694 */ |
| 681 MapIterator<AnalysisTarget, CacheEntry> iterator() => | 695 MapIterator<AnalysisTarget, CacheEntry> iterator() => |
| 682 new SingleMapIterator<AnalysisTarget, CacheEntry>(_targetMap); | 696 new SingleMapIterator<AnalysisTarget, CacheEntry>(_targetMap); |
| 683 | 697 |
| 684 /** | 698 /** |
| 685 * Puts the given [entry] into the partition. | 699 * Puts the given [entry] into the partition. |
| 686 */ | 700 */ |
| 687 void put(CacheEntry entry) { | 701 void put(CacheEntry entry) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 717 | 731 |
| 718 /** | 732 /** |
| 719 * Records that the given [result] was just stored into the cache. | 733 * Records that the given [result] was just stored into the cache. |
| 720 */ | 734 */ |
| 721 void resultStored(TargetedResult result, Object value) { | 735 void resultStored(TargetedResult result, Object value) { |
| 722 CacheFlushManager flushManager = _getFlushManager(result.result); | 736 CacheFlushManager flushManager = _getFlushManager(result.result); |
| 723 List<TargetedResult> resultsToFlush = | 737 List<TargetedResult> resultsToFlush = |
| 724 flushManager.resultStored(result, value); | 738 flushManager.resultStored(result, value); |
| 725 for (TargetedResult result in resultsToFlush) { | 739 for (TargetedResult result in resultsToFlush) { |
| 726 CacheEntry entry = get(result.target); | 740 CacheEntry entry = get(result.target); |
| 727 ResultData data = entry._resultMap[result.result]; | 741 if (entry != null) { |
| 728 data.flush(); | 742 ResultData data = entry._resultMap[result.result]; |
| 743 if (data != null) { |
| 744 data.flush(); |
| 745 } |
| 746 } |
| 729 } | 747 } |
| 730 } | 748 } |
| 731 | 749 |
| 732 /** | 750 /** |
| 733 * Return the number of targets that are mapped to cache entries. | 751 * Return the number of targets that are mapped to cache entries. |
| 734 */ | 752 */ |
| 735 int size() => _targetMap.length; | 753 int size() => _targetMap.length; |
| 736 | 754 |
| 737 ResultData _getDataFor(TargetedResult result) { | 755 ResultData _getDataFor(TargetedResult result, {bool orNull: false}) { |
| 738 return context.analysisCache._getDataFor(result); | 756 CacheEntry entry = context.analysisCache.get(result.target); |
| 757 if (orNull) { |
| 758 return entry != null ? entry._resultMap[result.result] : null; |
| 759 } else { |
| 760 return entry._getResultData(result.result); |
| 761 } |
| 739 } | 762 } |
| 740 | 763 |
| 741 /** | 764 /** |
| 742 * Return the [CacheFlushManager] for the given [descriptor], not `null`. | 765 * Return the [CacheFlushManager] for the given [descriptor], not `null`. |
| 743 */ | 766 */ |
| 744 CacheFlushManager _getFlushManager(ResultDescriptor descriptor) { | 767 CacheFlushManager _getFlushManager(ResultDescriptor descriptor) { |
| 745 ResultCachingPolicy policy = descriptor.cachingPolicy; | 768 ResultCachingPolicy policy = descriptor.cachingPolicy; |
| 746 return _flushManagerMap.putIfAbsent( | 769 return _flushManagerMap.putIfAbsent( |
| 747 policy, () => new CacheFlushManager(policy, _isPriorityAnalysisTarget)); | 770 policy, () => new CacheFlushManager(policy, _isPriorityAnalysisTarget)); |
| 748 } | 771 } |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 868 class UniversalCachePartition extends CachePartition { | 891 class UniversalCachePartition extends CachePartition { |
| 869 /** | 892 /** |
| 870 * Initialize a newly created cache partition, belonging to the given | 893 * Initialize a newly created cache partition, belonging to the given |
| 871 * [context]. | 894 * [context]. |
| 872 */ | 895 */ |
| 873 UniversalCachePartition(InternalAnalysisContext context) : super(context); | 896 UniversalCachePartition(InternalAnalysisContext context) : super(context); |
| 874 | 897 |
| 875 @override | 898 @override |
| 876 bool isResponsibleFor(AnalysisTarget target) => true; | 899 bool isResponsibleFor(AnalysisTarget target) => true; |
| 877 } | 900 } |
| OLD | NEW |