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

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

Issue 1133833002: Automatically remove empty entries from the cache. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | pkg/analyzer/test/src/context/cache_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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: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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analyzer/test/src/context/cache_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698