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

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

Issue 2162053004: Separate gathering Delta changes and validation. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 5 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/task/dart.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 fd65089cc2e791a7760b8a1f4131caf1b9e70bf2..8e9ca2bd3d3d668b77ce673efad3413c744da90c 100644
--- a/pkg/analyzer/lib/src/context/cache.dart
+++ b/pkg/analyzer/lib/src/context/cache.dart
@@ -18,6 +18,11 @@ import 'package:analyzer/src/task/model.dart';
import 'package:analyzer/task/model.dart';
/**
+ * The cache results visiting function type.
+ */
+typedef void CacheResultVisitor(AnalysisTarget target, ResultData data);
+
+/**
* Return `true` if the [result] of the [target] should be flushed.
*/
typedef bool FlushResultFilter<V>(
@@ -297,9 +302,9 @@ class CacheEntry {
static int _EXPLICITLY_ADDED_FLAG = 0;
/**
- * The next invalidation process identifier.
+ * The next visit process identifier.
*/
- static int nextInvalidateId = 0;
+ static int nextVisitId = 0;
/**
* A table containing the number of times the value of a result descriptor was
@@ -527,7 +532,12 @@ class CacheEntry {
if (state == CacheState.INVALID) {
ResultData data = _resultMap[descriptor];
if (data != null) {
- _invalidate(nextInvalidateId++, descriptor, delta, 0);
+ bool canUseDelta =
+ _gatherResultsInvalidatedByDelta(descriptor, delta, 0);
+ if (!canUseDelta) {
+ delta = null;
+ }
+ _invalidate(nextVisitId++, descriptor, delta, 0);
}
} else {
ResultData data = getResultData(descriptor);
@@ -584,7 +594,7 @@ class CacheEntry {
data.value = value;
}
if (invalidateDependent) {
- _invalidateDependentResults(nextInvalidateId++, data, null, 0);
+ _invalidateDependentResults(nextVisitId++, data, null, 0);
}
}
@@ -596,6 +606,35 @@ class CacheEntry {
}
/**
+ * Visit the given [result] and all results that depend on it, and
+ * ask [delta] to gather changes. Return `true` if the [delta] can be used
+ * to perform limited invalidation, or `false` if the changes collection
+ * process does not stop (should not happen).
+ */
+ bool _gatherResultsInvalidatedByDelta(
+ ResultDescriptor result, Delta delta, int level) {
+ if (delta == null) {
+ return false;
+ }
+ for (int i = 0; i < 64; i++) {
+ bool hasVisitChanges = false;
+ _visitResults(nextVisitId++, result,
+ (AnalysisTarget target, ResultData data) {
+ bool hasDeltaChanges = delta.gatherChanges(
+ _partition.context, target, data.descriptor, data.value);
+ if (hasDeltaChanges) {
+ hasVisitChanges = true;
+ }
+ });
+ delta.gatherEnd();
+ if (!hasVisitChanges) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Return the value of the flag with the given [index].
*/
bool _getFlag(int index) => BooleanArray.get(_flags, index);
@@ -612,10 +651,10 @@ class CacheEntry {
}
// Stop if already validated.
if (delta != null) {
- if (thisData.invalidateId == id) {
+ if (thisData.visitId == id) {
return;
}
- thisData.invalidateId = id;
+ thisData.visitId = id;
}
// Ask the delta to validate.
DeltaResult deltaResult = null;
@@ -688,7 +727,7 @@ class CacheEntry {
int length = results.length;
for (int i = 0; i < length; i++) {
ResultDescriptor result = results[i];
- _invalidate(nextInvalidateId++, result, null, 0);
+ _invalidate(nextVisitId++, result, null, 0);
}
}
@@ -819,6 +858,41 @@ class CacheEntry {
}
/**
+ * Call [visitor] for the result described by the given [descriptor] and all
+ * results that depend on directly or indirectly. Each result is visited
+ * only once.
+ */
+ void _visitResults(
+ int id, ResultDescriptor descriptor, CacheResultVisitor visitor) {
+ ResultData thisData = _resultMap[descriptor];
+ if (thisData == null) {
+ return;
+ }
+ // Stop if already visited.
+ if (thisData.visitId == id) {
+ return;
+ }
+ thisData.visitId = id;
+ // Visit this result.
+ visitor(target, thisData);
+ // Visit results that depend on this result.
+ List<AnalysisCache> caches = _partition.containingCaches;
+ int cacheLength = caches.length;
+ List<TargetedResult> dependentResults = thisData.dependentResults.toList();
+ int resultLength = dependentResults.length;
+ for (int i = 0; i < resultLength; i++) {
+ TargetedResult dependentResult = dependentResults[i];
+ for (int j = 0; j < cacheLength; j++) {
+ AnalysisCache cache = caches[j];
+ CacheEntry entry = cache.get(dependentResult.target);
+ if (entry != null) {
+ entry._visitResults(id, dependentResult.result, visitor);
+ }
+ }
+ }
+ }
+
+ /**
* Write a textual representation of this entry to the given [buffer]. The
* result should only be used for debugging purposes.
*/
@@ -1186,6 +1260,16 @@ class Delta {
Delta(this.source);
+ bool gatherChanges(InternalAnalysisContext context, AnalysisTarget target,
+ ResultDescriptor descriptor, Object value) {
+ return false;
+ }
+
+ /**
+ * The current cache results visit is done.
+ */
+ void gatherEnd() {}
+
/**
* Check whether this delta affects the result described by the given
* [descriptor] and [target]. The current [value] of the result is provided.
@@ -1344,11 +1428,10 @@ class ResultData {
Object value;
/**
- * The identifier of the invalidation process that most recently checked
- * this value. If it is the same as the current invalidation identifier,
- * then there is no reason to check it (and its subtree again).
+ * The identifier of the most recent visiting process. We use it to visit
+ * every result only once.
*/
- int invalidateId = -1;
+ int visitId = -1;
/**
* A list of the results on which this result depends.
« no previous file with comments | « no previous file | pkg/analyzer/lib/src/task/dart.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698