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

Unified Diff: pkg/analyzer/lib/src/context/cache.dart

Issue 1121963002: Record dependencies and invalidate results. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Merge and fixes for review comments. Created 5 years, 8 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/context/context.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/context/cache.dart
diff --git a/pkg/analyzer/lib/src/context/cache.dart b/pkg/analyzer/lib/src/context/cache.dart
index 08c7c58978773e10eab5c931099aa68f855c6af3..4ef2814a792dabf89efce162db140f8391556782 100644
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ b/pkg/analyzer/lib/src/context/cache.dart
@@ -13,6 +13,7 @@ import 'package:analyzer/src/generated/html.dart';
import 'package:analyzer/src/generated/java_engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_collection.dart';
+import 'package:analyzer/src/generated/utilities_general.dart';
import 'package:analyzer/task/model.dart';
/**
@@ -134,6 +135,8 @@ class AnalysisCache {
* Associate the given [entry] with the given [target].
*/
void put(AnalysisTarget target, CacheEntry entry) {
+ entry._cache = this;
+ entry._target = target;
entry.fixExceptionState();
int count = _partitions.length;
for (int i = 0; i < count; i++) {
@@ -213,6 +216,18 @@ class AnalysisCache {
}
}
}
+
+ ResultData _getDataFor(TargetedResult result) {
+ AnalysisTarget target = result.target;
+ int count = _partitions.length;
+ for (int i = 0; i < count; i++) {
+ if (_partitions[i].contains(target)) {
+ CacheEntry entry = _partitions[i].get(target);
+ return entry._getResultData(result.result);
+ }
+ }
+ return null;
+ }
}
/**
@@ -227,6 +242,16 @@ class CacheEntry {
static int _EXPLICITLY_ADDED_FLAG = 0;
/**
+ * The cache that contains this entry.
+ */
+ AnalysisCache _cache;
+
+ /**
+ * The target this entry is about.
+ */
+ AnalysisTarget _target;
+
+ /**
* The most recent time at which the state of the target matched the state
* represented by this entry.
*/
@@ -363,9 +388,9 @@ class CacheEntry {
getState(descriptor) == CacheState.VALID;
/**
- * Set the [CacheState.ERROR] state for given [descriptors], their values to
- * the corresponding default values, and remember the [exception] that caused
- * this state.
+ * For each of the given [descriptors], set their states to
+ * [CacheState.ERROR], their values to the corresponding default values, and
+ * remember the [exception] that caused this state.
*/
void setErrorState(
CaughtException exception, List<ResultDescriptor> descriptors) {
@@ -378,8 +403,8 @@ class CacheEntry {
this._exception = exception;
for (ResultDescriptor descriptor in descriptors) {
ResultData data = _getResultData(descriptor);
- data.state = CacheState.ERROR;
- data.value = descriptor.defaultValue;
+ TargetedResult thisResult = new TargetedResult(_target, descriptor);
+ data.invalidate(_cache, thisResult, CacheState.ERROR);
}
}
@@ -396,7 +421,11 @@ class CacheEntry {
}
_validateStateChange(descriptor, state);
if (state == CacheState.INVALID) {
- _resultMap.remove(descriptor);
+ ResultData data = _resultMap[descriptor];
+ if (data != null) {
+ TargetedResult thisResult = new TargetedResult(_target, descriptor);
+ data.invalidate(_cache, thisResult, CacheState.INVALID);
+ }
} else {
ResultData data = _getResultData(descriptor);
data.state = state;
@@ -415,9 +444,14 @@ class CacheEntry {
* given [value].
*/
/*<V>*/ void setValue(ResultDescriptor /*<V>*/ descriptor, dynamic /*V*/
- value) {
+ value, List<TargetedResult> dependedOn) {
_validateStateChange(descriptor, CacheState.VALID);
ResultData data = _getResultData(descriptor);
+ {
+ TargetedResult thisResult = new TargetedResult(_target, descriptor);
+ data.invalidate(_cache, thisResult, CacheState.INVALID);
+ data.setDependedOnResults(_cache, thisResult, dependedOn);
+ }
data.state = CacheState.VALID;
data.value = value == null ? descriptor.defaultValue : value;
}
@@ -771,6 +805,11 @@ class DefaultRetentionPolicy implements CacheRetentionPolicy {
// can be typed.
class ResultData {
/**
+ * The [ResultDescriptor] this result is for.
+ */
+ final ResultDescriptor descriptor;
+
+ /**
* The state of the cached value.
*/
CacheState state;
@@ -782,13 +821,78 @@ class ResultData {
Object value;
/**
+ * A list of the results on which this result depends.
+ */
+ List<TargetedResult> dependedOnResults = <TargetedResult>[];
+
+ /**
+ * A list of the results that depend on this result.
+ */
+ List<TargetedResult> dependentResults = <TargetedResult>[];
+
+ /**
* Initialize a newly created result holder to represent the value of data
* described by the given [descriptor].
*/
- ResultData(ResultDescriptor descriptor) {
+ ResultData(this.descriptor) {
state = CacheState.INVALID;
value = descriptor.defaultValue;
}
+
+ /**
+ * Add the given [result] to the list of dependent results.
+ */
+ void addDependentResult(TargetedResult result) {
+ dependentResults.add(result);
+ }
+
+ /**
+ * Invalidate this [ResultData] that corresponds to [thisResult] and
+ * propagate invalidation to the results that depend on this one.
+ */
+ void invalidate(
+ AnalysisCache cache, TargetedResult thisResult, CacheState newState) {
+ // Invalidate this result.
+ state = newState;
+ value = descriptor.defaultValue;
+ // Stop depending on other results.
+ List<TargetedResult> dependedOnResults = this.dependedOnResults;
+ this.dependedOnResults = <TargetedResult>[];
+ dependedOnResults.forEach((TargetedResult dependedOnResult) {
+ ResultData data = cache._getDataFor(dependedOnResult);
+ data.removeDependentResult(thisResult);
+ });
+ // Invalidate results that depend on this result.
+ List<TargetedResult> dependentResults = this.dependentResults;
+ this.dependentResults = <TargetedResult>[];
+ dependentResults.forEach((TargetedResult dependentResult) {
+ ResultData data = cache._getDataFor(dependentResult);
+ data.invalidate(cache, dependentResult, newState);
+ });
+ }
+
+ /**
+ * Remove the given [result] from the list of dependent results.
+ */
+ void removeDependentResult(TargetedResult result) {
+ dependentResults.remove(result);
+ }
+
+ /**
+ * Set the [dependedOn] on which this result depends.
+ */
+ void setDependedOnResults(AnalysisCache cache, TargetedResult thisResult,
+ List<TargetedResult> dependedOn) {
+ dependedOnResults.forEach((TargetedResult dependedOnResult) {
+ ResultData data = cache._getDataFor(dependedOnResult);
+ data.removeDependentResult(thisResult);
+ });
+ dependedOnResults = dependedOn;
+ dependedOnResults.forEach((TargetedResult dependentResult) {
+ ResultData data = cache._getDataFor(dependentResult);
+ data.addDependentResult(thisResult);
+ });
+ }
}
/**
@@ -811,6 +915,46 @@ class SdkCachePartition extends CachePartition {
}
/**
+ * A specification of a specific result computed for a specific target.
+ */
+class TargetedResult {
+ /**
+ * An empty list of results.
+ */
+ static final List<TargetedResult> EMPTY_LIST = const <TargetedResult>[];
+
+ /**
+ * The target with which the result is associated.
+ */
+ final AnalysisTarget target;
+
+ /**
+ * The result associated with the target.
+ */
+ final ResultDescriptor result;
+
+ /**
+ * Initialize a new targeted result.
+ */
+ TargetedResult(this.target, this.result);
+
+ @override
+ int get hashCode {
+ return JenkinsSmiHash.combine(target.hashCode, result.hashCode);
+ }
+
+ @override
+ bool operator ==(other) {
+ return other is TargetedResult &&
+ other.target == target &&
+ other.result == result;
+ }
+
+ @override
+ String toString() => '$result for $target';
+}
+
+/**
* A cache partition that contains all targets not contained in other partitions.
*/
class UniversalCachePartition extends CachePartition {
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/context/context.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698