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/ast.dart'; | |
10 import 'package:analyzer/src/generated/engine.dart' | 9 import 'package:analyzer/src/generated/engine.dart' |
11 show AnalysisEngine, CacheState, InternalAnalysisContext, RetentionPriority; | 10 show AnalysisEngine, CacheState, InternalAnalysisContext, RetentionPriority; |
12 import 'package:analyzer/src/generated/html.dart'; | |
13 import 'package:analyzer/src/generated/java_engine.dart'; | 11 import 'package:analyzer/src/generated/java_engine.dart'; |
14 import 'package:analyzer/src/generated/source.dart'; | 12 import 'package:analyzer/src/generated/source.dart'; |
15 import 'package:analyzer/src/generated/utilities_collection.dart'; | 13 import 'package:analyzer/src/generated/utilities_collection.dart'; |
16 import 'package:analyzer/src/generated/utilities_general.dart'; | 14 import 'package:analyzer/src/generated/utilities_general.dart'; |
17 import 'package:analyzer/task/model.dart'; | 15 import 'package:analyzer/task/model.dart'; |
18 | 16 |
19 /** | 17 /** |
18 * Return `true` if the given [target] is a priority one. | |
19 */ | |
20 typedef bool IsPriorityAnalysisTarget(AnalysisTarget target); | |
21 | |
22 /** | |
20 * An LRU cache of results produced by analysis. | 23 * An LRU cache of results produced by analysis. |
21 */ | 24 */ |
22 class AnalysisCache { | 25 class AnalysisCache { |
23 /** | 26 /** |
24 * A flag used to control whether trace information should be produced when | 27 * A flag used to control whether trace information should be produced when |
25 * the content of the cache is modified. | 28 * the content of the cache is modified. |
26 */ | 29 */ |
27 static bool _TRACE_CHANGES = false; | 30 static bool _TRACE_CHANGES = false; |
28 | 31 |
29 /** | 32 /** |
30 * An array containing the partitions of which this cache is comprised. | 33 * An array containing the partitions of which this cache is comprised. |
31 */ | 34 */ |
32 final List<CachePartition> _partitions; | 35 final List<CachePartition> _partitions; |
33 | 36 |
34 /** | 37 /** |
35 * Initialize a newly created cache to have the given [partitions]. The | 38 * Initialize a newly created cache to have the given [partitions]. The |
36 * partitions will be searched in the order in which they appear in the array, | 39 * partitions will be searched in the order in which they appear in the array, |
37 * so the most specific partition (usually an [SdkCachePartition]) should be | 40 * so the most specific partition (usually an [SdkCachePartition]) should be |
38 * first and the most general (usually a [UniversalCachePartition]) last. | 41 * first and the most general (usually a [UniversalCachePartition]) last. |
39 */ | 42 */ |
40 AnalysisCache(this._partitions); | 43 AnalysisCache(this._partitions) { |
41 | 44 for (CachePartition partition in _partitions) { |
42 /** | 45 partition._cache = this; |
43 * Return the number of entries in this cache that have an AST associated with | 46 } |
44 * them. | 47 } |
45 */ | |
46 int get astSize => _partitions[_partitions.length - 1].astSize; | |
47 | 48 |
48 // TODO(brianwilkerson) Implement or delete this. | 49 // TODO(brianwilkerson) Implement or delete this. |
49 // /** | 50 // /** |
50 // * Return information about each of the partitions in this cache. | 51 // * Return information about each of the partitions in this cache. |
51 // */ | 52 // */ |
52 // List<AnalysisContextStatistics_PartitionData> get partitionData { | 53 // List<AnalysisContextStatistics_PartitionData> get partitionData { |
53 // int count = _partitions.length; | 54 // int count = _partitions.length; |
54 // List<AnalysisContextStatistics_PartitionData> data = | 55 // List<AnalysisContextStatistics_PartitionData> data = |
55 // new List<AnalysisContextStatistics_PartitionData>(count); | 56 // new List<AnalysisContextStatistics_PartitionData>(count); |
56 // for (int i = 0; i < count; i++) { | 57 // for (int i = 0; i < count; i++) { |
57 // CachePartition partition = _partitions[i]; | 58 // CachePartition partition = _partitions[i]; |
58 // data[i] = new AnalysisContextStatisticsImpl_PartitionDataImpl( | 59 // data[i] = new AnalysisContextStatisticsImpl_PartitionDataImpl( |
59 // partition.astSize, | 60 // partition.astSize, |
60 // partition.map.length); | 61 // partition.map.length); |
61 // } | 62 // } |
62 // return data; | 63 // return data; |
63 // } | 64 // } |
64 | 65 |
65 /** | 66 /** |
66 * Record that the AST associated with the given [target] was just read from | |
67 * the cache. | |
68 */ | |
69 void accessedAst(AnalysisTarget target) { | |
70 // TODO(brianwilkerson) Extract this logic to a helper method (here and | |
71 // elsewhere) | |
72 int count = _partitions.length; | |
73 for (int i = 0; i < count; i++) { | |
74 if (_partitions[i].contains(target)) { | |
75 _partitions[i].accessedAst(target); | |
76 return; | |
77 } | |
78 } | |
79 } | |
80 | |
81 /** | |
82 * Return the entry associated with the given [target]. | 67 * Return the entry associated with the given [target]. |
83 */ | 68 */ |
84 CacheEntry get(AnalysisTarget target) { | 69 CacheEntry get(AnalysisTarget target) { |
85 int count = _partitions.length; | 70 int count = _partitions.length; |
86 for (int i = 0; i < count; i++) { | 71 for (int i = 0; i < count; i++) { |
87 if (_partitions[i].contains(target)) { | 72 if (_partitions[i].contains(target)) { |
88 return _partitions[i].get(target); | 73 return _partitions[i].get(target); |
89 } | 74 } |
90 } | 75 } |
91 // | 76 // |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
128 for (int i = 0; i < count; i++) { | 113 for (int i = 0; i < count; i++) { |
129 maps[i] = _partitions[i].map; | 114 maps[i] = _partitions[i].map; |
130 } | 115 } |
131 return new MultipleMapIterator<AnalysisTarget, CacheEntry>(maps); | 116 return new MultipleMapIterator<AnalysisTarget, CacheEntry>(maps); |
132 } | 117 } |
133 | 118 |
134 /** | 119 /** |
135 * Associate the given [entry] with the given [target]. | 120 * Associate the given [entry] with the given [target]. |
136 */ | 121 */ |
137 void put(AnalysisTarget target, CacheEntry entry) { | 122 void put(AnalysisTarget target, CacheEntry entry) { |
138 entry._cache = this; | |
139 entry._target = target; | |
140 entry.fixExceptionState(); | 123 entry.fixExceptionState(); |
141 int count = _partitions.length; | 124 int count = _partitions.length; |
142 for (int i = 0; i < count; i++) { | 125 for (int i = 0; i < count; i++) { |
143 if (_partitions[i].contains(target)) { | 126 if (_partitions[i].contains(target)) { |
144 if (_TRACE_CHANGES) { | 127 if (_TRACE_CHANGES) { |
145 CacheEntry oldEntry = _partitions[i].get(target); | 128 CacheEntry oldEntry = _partitions[i].get(target); |
146 if (oldEntry == null) { | 129 if (oldEntry == null) { |
147 AnalysisEngine.instance.logger | 130 AnalysisEngine.instance.logger |
148 .logInformation('Added a cache entry for $target.'); | 131 .logInformation('Added a cache entry for $target.'); |
149 } else { | 132 } else { |
(...skipping 21 matching lines...) Expand all Loading... | |
171 AnalysisEngine.instance.logger | 154 AnalysisEngine.instance.logger |
172 .logInformation('Removed the cache entry for $target.'); | 155 .logInformation('Removed the cache entry for $target.'); |
173 } | 156 } |
174 _partitions[i].remove(target); | 157 _partitions[i].remove(target); |
175 return; | 158 return; |
176 } | 159 } |
177 } | 160 } |
178 } | 161 } |
179 | 162 |
180 /** | 163 /** |
181 * Record that the AST associated with the given [target] was just removed | |
182 * from the cache. | |
183 */ | |
184 void removedAst(AnalysisTarget target) { | |
185 int count = _partitions.length; | |
186 for (int i = 0; i < count; i++) { | |
187 if (_partitions[i].contains(target)) { | |
188 _partitions[i].removedAst(target); | |
189 return; | |
190 } | |
191 } | |
192 } | |
193 | |
194 /** | |
195 * Return the number of targets that are mapped to cache entries. | 164 * Return the number of targets that are mapped to cache entries. |
196 */ | 165 */ |
197 int size() { | 166 int size() { |
198 int size = 0; | 167 int size = 0; |
199 int count = _partitions.length; | 168 int count = _partitions.length; |
200 for (int i = 0; i < count; i++) { | 169 for (int i = 0; i < count; i++) { |
201 size += _partitions[i].size(); | 170 size += _partitions[i].size(); |
202 } | 171 } |
203 return size; | 172 return size; |
204 } | 173 } |
205 | 174 |
206 /** | |
207 * Record that the AST associated with the given [target] was just stored to | |
208 * the cache. | |
209 */ | |
210 void storedAst(AnalysisTarget target) { | |
211 int count = _partitions.length; | |
212 for (int i = 0; i < count; i++) { | |
213 if (_partitions[i].contains(target)) { | |
214 _partitions[i].storedAst(target); | |
215 return; | |
216 } | |
217 } | |
218 } | |
219 | |
220 ResultData _getDataFor(TargetedResult result) { | 175 ResultData _getDataFor(TargetedResult result) { |
221 AnalysisTarget target = result.target; | 176 AnalysisTarget target = result.target; |
222 int count = _partitions.length; | 177 int count = _partitions.length; |
223 for (int i = 0; i < count; i++) { | 178 for (int i = 0; i < count; i++) { |
224 if (_partitions[i].contains(target)) { | 179 if (_partitions[i].contains(target)) { |
225 CacheEntry entry = _partitions[i].get(target); | 180 CacheEntry entry = _partitions[i].get(target); |
226 return entry._getResultData(result.result); | 181 return entry._getResultData(result.result); |
227 } | 182 } |
228 } | 183 } |
229 return null; | 184 return null; |
230 } | 185 } |
231 } | 186 } |
232 | 187 |
233 /** | 188 /** |
234 * The information cached by an analysis context about an individual target. | 189 * The information cached by an analysis context about an individual target. |
235 */ | 190 */ |
236 class CacheEntry { | 191 class CacheEntry { |
237 /** | 192 /** |
238 * The index of the flag indicating whether the source was explicitly added to | 193 * The index of the flag indicating whether the source was explicitly added to |
239 * the context or whether the source was implicitly added because it was | 194 * the context or whether the source was implicitly added because it was |
240 * referenced by another source. | 195 * referenced by another source. |
241 */ | 196 */ |
242 static int _EXPLICITLY_ADDED_FLAG = 0; | 197 static int _EXPLICITLY_ADDED_FLAG = 0; |
243 | 198 |
244 /** | 199 /** |
245 * The cache that contains this entry. | 200 * The partition that is responsible for this entry. |
246 */ | 201 */ |
247 AnalysisCache _cache; | 202 CachePartition _partition; |
248 | 203 |
249 /** | 204 /** |
250 * The target this entry is about. | 205 * The target this entry is about. |
251 */ | 206 */ |
252 AnalysisTarget _target; | 207 AnalysisTarget _target; |
253 | 208 |
254 /** | 209 /** |
255 * The most recent time at which the state of the target matched the state | 210 * The most recent time at which the state of the target matched the state |
256 * represented by this entry. | 211 * represented by this entry. |
257 */ | 212 */ |
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
289 | 244 |
290 /** | 245 /** |
291 * Set whether the source was explicitly added to the context to match the | 246 * Set whether the source was explicitly added to the context to match the |
292 * [explicitlyAdded] flag. | 247 * [explicitlyAdded] flag. |
293 */ | 248 */ |
294 void set explicitlyAdded(bool explicitlyAdded) { | 249 void set explicitlyAdded(bool explicitlyAdded) { |
295 _setFlag(_EXPLICITLY_ADDED_FLAG, explicitlyAdded); | 250 _setFlag(_EXPLICITLY_ADDED_FLAG, explicitlyAdded); |
296 } | 251 } |
297 | 252 |
298 /** | 253 /** |
299 * Return `true` if this entry contains at least one result whose value is an | |
300 * AST structure. | |
301 */ | |
302 bool get hasAstStructure { | |
303 for (ResultData data in _resultMap.values) { | |
304 if (data.value is AstNode || data.value is XmlNode) { | |
305 return true; | |
306 } | |
307 } | |
308 return false; | |
309 } | |
310 | |
311 /** | |
312 * Fix the state of the [exception] to match the current state of the entry. | 254 * Fix the state of the [exception] to match the current state of the entry. |
313 */ | 255 */ |
314 void fixExceptionState() { | 256 void fixExceptionState() { |
315 if (!hasErrorState()) { | 257 if (!hasErrorState()) { |
316 _exception = null; | 258 _exception = null; |
317 } | 259 } |
318 } | 260 } |
319 | 261 |
320 /** | 262 /** |
321 * Mark any AST structures associated with this cache entry as being flushed. | |
322 */ | |
323 void flushAstStructures() { | |
324 _resultMap.forEach((ResultDescriptor descriptor, ResultData data) { | |
325 if (data.value is AstNode || data.value is XmlNode) { | |
326 _validateStateChange(descriptor, CacheState.FLUSHED); | |
327 data.state = CacheState.FLUSHED; | |
328 data.value = descriptor.defaultValue; | |
329 } | |
330 }); | |
331 } | |
332 | |
333 /** | |
334 * Return the memento of the result represented by the given [descriptor]. | 263 * Return the memento of the result represented by the given [descriptor]. |
335 */ | 264 */ |
336 Object getMemento(ResultDescriptor descriptor) { | 265 Object getMemento(ResultDescriptor descriptor) { |
337 ResultData data = _resultMap[descriptor]; | 266 ResultData data = _resultMap[descriptor]; |
338 if (data == null) { | 267 if (data == null) { |
339 return null; | 268 return null; |
340 } | 269 } |
341 return data.memento; | 270 return data.memento; |
342 } | 271 } |
343 | 272 |
(...skipping 10 matching lines...) Expand all Loading... | |
354 | 283 |
355 /** | 284 /** |
356 * Return the value of the result represented by the given [descriptor], or | 285 * Return the value of the result represented by the given [descriptor], or |
357 * the default value for the result if this entry does not have a valid value. | 286 * the default value for the result if this entry does not have a valid value. |
358 */ | 287 */ |
359 /*<V>*/ dynamic /*V*/ getValue(ResultDescriptor /*<V>*/ descriptor) { | 288 /*<V>*/ dynamic /*V*/ getValue(ResultDescriptor /*<V>*/ descriptor) { |
360 ResultData data = _resultMap[descriptor]; | 289 ResultData data = _resultMap[descriptor]; |
361 if (data == null) { | 290 if (data == null) { |
362 return descriptor.defaultValue; | 291 return descriptor.defaultValue; |
363 } | 292 } |
293 if (_partition != null) { | |
294 _partition.resultAccessed(_target, descriptor); | |
295 } | |
364 return data.value; | 296 return data.value; |
365 } | 297 } |
366 | 298 |
367 /** | 299 /** |
368 * Return `true` if the state of any data value is [CacheState.ERROR]. | 300 * Return `true` if the state of any data value is [CacheState.ERROR]. |
369 */ | 301 */ |
370 bool hasErrorState() { | 302 bool hasErrorState() { |
371 for (ResultData data in _resultMap.values) { | 303 for (ResultData data in _resultMap.values) { |
372 if (data.state == CacheState.ERROR) { | 304 if (data.state == CacheState.ERROR) { |
373 return true; | 305 return true; |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
408 if (descriptors == null || descriptors.isEmpty) { | 340 if (descriptors == null || descriptors.isEmpty) { |
409 throw new ArgumentError('at least one descriptor is expected'); | 341 throw new ArgumentError('at least one descriptor is expected'); |
410 } | 342 } |
411 if (exception == null) { | 343 if (exception == null) { |
412 throw new ArgumentError('an exception is expected'); | 344 throw new ArgumentError('an exception is expected'); |
413 } | 345 } |
414 this._exception = exception; | 346 this._exception = exception; |
415 for (ResultDescriptor descriptor in descriptors) { | 347 for (ResultDescriptor descriptor in descriptors) { |
416 ResultData data = _getResultData(descriptor); | 348 ResultData data = _getResultData(descriptor); |
417 TargetedResult thisResult = new TargetedResult(_target, descriptor); | 349 TargetedResult thisResult = new TargetedResult(_target, descriptor); |
418 data.invalidate(_cache, thisResult, CacheState.ERROR); | 350 data.invalidate(_partition, thisResult, CacheState.ERROR); |
419 } | 351 } |
420 } | 352 } |
421 | 353 |
422 /** | 354 /** |
423 * Set the state of the result represented by the given [descriptor] to the | 355 * Set the state of the result represented by the given [descriptor] to the |
424 * given [state]. | 356 * given [state]. |
425 */ | 357 */ |
426 void setState(ResultDescriptor descriptor, CacheState state) { | 358 void setState(ResultDescriptor descriptor, CacheState state) { |
427 if (state == CacheState.ERROR) { | 359 if (state == CacheState.ERROR) { |
428 throw new ArgumentError('use setErrorState() to set the state to ERROR'); | 360 throw new ArgumentError('use setErrorState() to set the state to ERROR'); |
429 } | 361 } |
430 if (state == CacheState.VALID) { | 362 if (state == CacheState.VALID) { |
431 throw new ArgumentError('use setValue() to set the state to VALID'); | 363 throw new ArgumentError('use setValue() to set the state to VALID'); |
432 } | 364 } |
433 _validateStateChange(descriptor, state); | 365 _validateStateChange(descriptor, state); |
434 if (state == CacheState.INVALID) { | 366 if (state == CacheState.INVALID) { |
435 ResultData data = _resultMap[descriptor]; | 367 ResultData data = _resultMap[descriptor]; |
436 if (data != null) { | 368 if (data != null) { |
437 TargetedResult thisResult = new TargetedResult(_target, descriptor); | 369 TargetedResult thisResult = new TargetedResult(_target, descriptor); |
438 data.invalidate(_cache, thisResult, CacheState.INVALID); | 370 data.invalidate(_partition, thisResult, CacheState.INVALID); |
439 } | 371 } |
440 } else { | 372 } else { |
441 ResultData data = _getResultData(descriptor); | 373 ResultData data = _getResultData(descriptor); |
442 data.state = state; | 374 data.state = state; |
443 if (state != CacheState.IN_PROCESS) { | 375 if (state != CacheState.IN_PROCESS) { |
444 // | 376 // |
445 // If the state is in-process, we can leave the current value in the | 377 // If the state is in-process, we can leave the current value in the |
446 // cache for any 'get' methods to access. | 378 // cache for any 'get' methods to access. |
447 // | 379 // |
448 data.value = descriptor.defaultValue; | 380 data.value = descriptor.defaultValue; |
449 } | 381 } |
450 } | 382 } |
451 } | 383 } |
452 | 384 |
453 /** | 385 /** |
454 * Set the value of the result represented by the given [descriptor] to the | 386 * Set the value of the result represented by the given [descriptor] to the |
455 * given [value]. The optional [memento] may help to recompute [value] more | 387 * given [value]. The optional [memento] may help to recompute [value] more |
456 * efficiently after invalidation. | 388 * efficiently after invalidation. |
457 */ | 389 */ |
458 /*<V>*/ void setValue(ResultDescriptor /*<V>*/ descriptor, dynamic /*V*/ | 390 /*<V>*/ void setValue(ResultDescriptor /*<V>*/ descriptor, dynamic /*V*/ |
459 value, List<TargetedResult> dependedOn, Object memento) { | 391 value, List<TargetedResult> dependedOn, Object memento) { |
460 _validateStateChange(descriptor, CacheState.VALID); | 392 _validateStateChange(descriptor, CacheState.VALID); |
393 TargetedResult thisResult = new TargetedResult(_target, descriptor); | |
394 if (_partition != null) { | |
395 _partition.resultStored(thisResult, value); | |
396 } | |
461 ResultData data = _getResultData(descriptor); | 397 ResultData data = _getResultData(descriptor); |
462 { | 398 data.invalidate(_partition, thisResult, CacheState.INVALID); |
463 TargetedResult thisResult = new TargetedResult(_target, descriptor); | 399 data.setDependedOnResults(_partition, thisResult, dependedOn); |
464 data.invalidate(_cache, thisResult, CacheState.INVALID); | |
465 data.setDependedOnResults(_cache, thisResult, dependedOn); | |
466 } | |
467 data.state = CacheState.VALID; | 400 data.state = CacheState.VALID; |
468 data.value = value == null ? descriptor.defaultValue : value; | 401 data.value = value == null ? descriptor.defaultValue : value; |
469 data.memento = memento; | 402 data.memento = memento; |
470 } | 403 } |
471 | 404 |
472 @override | 405 @override |
473 String toString() { | 406 String toString() { |
474 StringBuffer buffer = new StringBuffer(); | 407 StringBuffer buffer = new StringBuffer(); |
475 _writeOn(buffer); | 408 _writeOn(buffer); |
476 return buffer.toString(); | 409 return buffer.toString(); |
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
533 ResultData data = _resultMap[result]; | 466 ResultData data = _resultMap[result]; |
534 buffer.write('; '); | 467 buffer.write('; '); |
535 buffer.write(result.toString()); | 468 buffer.write(result.toString()); |
536 buffer.write(' = '); | 469 buffer.write(' = '); |
537 buffer.write(data.state); | 470 buffer.write(data.state); |
538 } | 471 } |
539 } | 472 } |
540 } | 473 } |
541 | 474 |
542 /** | 475 /** |
476 * An object that controls flushing of analysis results from the cache. | |
477 */ | |
478 class CacheFlushManager<T> { | |
479 final IsPriorityAnalysisTarget isPriorityAnalysisTarget; | |
480 final ResultCachingPolicy<T> policy; | |
481 final int maxActiveSize; | |
482 final int maxIdleSize; | |
483 | |
484 /** | |
485 * A map of the stored [TargetedResult] to their sizes. | |
486 */ | |
487 final HashMap<TargetedResult, int> resultSizeMap = | |
488 new HashMap<TargetedResult, int>(); | |
489 | |
490 /** | |
491 * A linked set containing the most recently accessed results with the most | |
492 * recently used at the end of the list. When more results are added than the | |
493 * maximum size allowed then the least recently used results will be flushed | |
494 * from the cache. | |
495 */ | |
496 final LinkedHashSet<TargetedResult> recentlyUsed = | |
497 new LinkedHashSet<TargetedResult>(); | |
498 | |
499 /** | |
500 * The current size of stored results. | |
501 */ | |
502 int currentSize = 0; | |
503 | |
504 /** | |
505 * The current maximum cache size. | |
506 */ | |
507 int maxSize; | |
508 | |
509 CacheFlushManager( | |
510 ResultCachingPolicy<T> policy, this.isPriorityAnalysisTarget) | |
511 : policy = policy, | |
512 maxActiveSize = policy.maxActiveSize, | |
513 maxIdleSize = policy.maxIdleSize, | |
514 maxSize = policy.maxIdleSize; | |
515 | |
516 /** | |
517 * If [currentSize] is already less than [maxSize], returns an empty list. | |
518 * Otherwise returns [TargetedResult]s to flush from the cache to make | |
519 * [currentSize] lass then [maxSize]. | |
Brian Wilkerson
2015/05/07 14:19:19
"lass then" --> "less than"
If it's intentional t
scheglov
2015/05/07 15:49:27
Done.
| |
520 */ | |
521 List<TargetedResult> flushToSize() { | |
522 // If still under the cap, done. | |
523 if (maxSize == -1 || currentSize <= maxSize) { | |
524 return TargetedResult.EMPTY_LIST; | |
525 } | |
526 // Flush results until we are under the cap. | |
527 List<TargetedResult> resultsToFlush = <TargetedResult>[]; | |
528 for (TargetedResult result in recentlyUsed) { | |
529 if (isPriorityAnalysisTarget(result.target)) { | |
530 continue; | |
531 } | |
532 resultsToFlush.add(result); | |
533 int size = resultSizeMap.remove(result); | |
534 assert(size != null); | |
535 currentSize -= size; | |
536 if (currentSize <= maxSize) { | |
537 break; | |
538 } | |
539 } | |
540 recentlyUsed.removeAll(resultsToFlush); | |
541 return resultsToFlush; | |
542 } | |
543 | |
544 /** | |
545 * Notifies this manager that the corresponding analysis context is acive. | |
Brian Wilkerson
2015/05/07 14:19:19
"acive" --> "active"
scheglov
2015/05/07 15:49:27
Done.
| |
546 */ | |
547 void madeActive() { | |
548 maxSize = maxActiveSize; | |
549 } | |
550 | |
551 /** | |
552 * Notifies this manager that the corresponding analysis context is idle. | |
553 * Returns [TargetedResult]s that should be flushed from the cache. | |
554 */ | |
555 List<TargetedResult> madeIdle() { | |
556 maxSize = maxIdleSize; | |
557 return flushToSize(); | |
558 } | |
559 | |
560 /** | |
561 * Records that the given [result] was just read from the cache. | |
562 */ | |
563 void resultAccessed(TargetedResult result) { | |
564 if (recentlyUsed.remove(result)) { | |
565 recentlyUsed.add(result); | |
Brian Wilkerson
2015/05/07 14:19:19
Given that an access is a use, shouldn't the resul
scheglov
2015/05/07 15:49:27
Yes, access is a use, but only if the result was a
| |
566 } | |
567 } | |
568 | |
569 /** | |
570 * Records that the given [newResult] and [newValue] were stored to the cache. | |
571 * Returns [TargetedResult]s that should be flushed from the cache. | |
572 */ | |
573 List<TargetedResult> resultStored(TargetedResult newResult, T newValue) { | |
574 if (!recentlyUsed.remove(newResult)) { | |
575 int size = policy.measure(newValue); | |
576 resultSizeMap[newResult] = size; | |
577 currentSize += size; | |
578 } | |
579 recentlyUsed.add(newResult); | |
580 return flushToSize(); | |
581 } | |
582 | |
583 /** | |
584 * Records that the given [target] was just removed from to the cache. | |
585 */ | |
586 void targetRemoved(AnalysisTarget target) { | |
587 List<TargetedResult> resultsToRemove = <TargetedResult>[]; | |
588 for (TargetedResult result in recentlyUsed) { | |
589 if (result.target == target) { | |
590 resultsToRemove.add(result); | |
591 int size = resultSizeMap.remove(result); | |
592 assert(size != null); | |
593 currentSize -= size; | |
594 } | |
595 } | |
596 recentlyUsed.removeAll(resultsToRemove); | |
597 } | |
598 } | |
599 | |
600 /** | |
543 * A single partition in an LRU cache of information related to analysis. | 601 * A single partition in an LRU cache of information related to analysis. |
544 */ | 602 */ |
545 abstract class CachePartition { | 603 abstract class CachePartition { |
546 /** | 604 /** |
605 * The [AnalysisCache] that owns this partition. | |
606 * | |
607 * TODO(scheglov) It seems wrong. Partitions may be shared between caches. | |
608 * But we need a way to go from every "enclosing" partition into "enclosed" | |
609 * ones. | |
Brian Wilkerson
2015/05/07 14:19:19
I'm guessing that this is effectively the same as
scheglov
2015/05/07 15:49:27
There are some problems with it in tests.
I will d
| |
610 */ | |
611 AnalysisCache _cache; | |
612 | |
613 /** | |
547 * The context that owns this partition. Multiple contexts can reference a | 614 * The context that owns this partition. Multiple contexts can reference a |
548 * partition, but only one context can own it. | 615 * partition, but only one context can own it. |
549 */ | 616 */ |
550 final InternalAnalysisContext context; | 617 final InternalAnalysisContext context; |
551 | 618 |
552 /** | 619 /** |
553 * The maximum number of sources for which AST structures should be kept in | 620 * A table mapping caching policies to the cache flush managers. |
554 * the cache. | |
555 */ | 621 */ |
556 int _maxCacheSize = 0; | 622 final HashMap<ResultCachingPolicy, CacheFlushManager> _flushManagerMap = |
557 | 623 new HashMap<ResultCachingPolicy, CacheFlushManager>(); |
558 /** | |
559 * The policy used to determine which results to remove from the cache. | |
560 */ | |
561 final CacheRetentionPolicy _retentionPolicy; | |
562 | 624 |
563 /** | 625 /** |
564 * A table mapping the targets belonging to this partition to the information | 626 * A table mapping the targets belonging to this partition to the information |
565 * known about those targets. | 627 * known about those targets. |
566 */ | 628 */ |
567 HashMap<AnalysisTarget, CacheEntry> _targetMap = | 629 HashMap<AnalysisTarget, CacheEntry> _targetMap = |
568 new HashMap<AnalysisTarget, CacheEntry>(); | 630 new HashMap<AnalysisTarget, CacheEntry>(); |
569 | 631 |
570 /** | 632 /** |
571 * A list containing the most recently accessed targets with the most recently | 633 * Initialize a newly created cache partition, belonging to the given |
572 * used at the end of the list. When more targets are added than the maximum | 634 * [context]. |
573 * allowed then the least recently used target will be removed and will have | |
574 * it's cached AST structure flushed. | |
575 */ | 635 */ |
576 List<AnalysisTarget> _recentlyUsed = <AnalysisTarget>[]; | 636 CachePartition(this.context); |
577 | |
578 /** | |
579 * Initialize a newly created cache partition, belonging to the given | |
580 * [context]. The partition will maintain at most [_maxCacheSize] AST | |
581 * structures in the cache, using the [_retentionPolicy] to determine which | |
582 * AST structures to flush. | |
583 */ | |
584 CachePartition(this.context, this._maxCacheSize, this._retentionPolicy); | |
585 | |
586 /** | |
587 * Return the number of entries in this partition that have an AST associated | |
588 * with them. | |
589 */ | |
590 int get astSize { | |
591 int astSize = 0; | |
592 int count = _recentlyUsed.length; | |
593 for (int i = 0; i < count; i++) { | |
594 AnalysisTarget target = _recentlyUsed[i]; | |
595 CacheEntry entry = _targetMap[target]; | |
596 if (entry.hasAstStructure) { | |
597 astSize++; | |
598 } | |
599 } | |
600 return astSize; | |
601 } | |
602 | 637 |
603 /** | 638 /** |
604 * Return a table mapping the targets known to the context to the information | 639 * Return a table mapping the targets known to the context to the information |
605 * known about the target. | 640 * known about the target. |
606 * | 641 * |
607 * <b>Note:</b> This method is only visible for use by [AnalysisCache] and | 642 * <b>Note:</b> This method is only visible for use by [AnalysisCache] and |
608 * should not be used for any other purpose. | 643 * should not be used for any other purpose. |
609 */ | 644 */ |
610 Map<AnalysisTarget, CacheEntry> get map => _targetMap; | 645 Map<AnalysisTarget, CacheEntry> get map => _targetMap; |
611 | 646 |
612 /** | 647 /** |
613 * Return the maximum size of the cache. | |
614 */ | |
615 int get maxCacheSize => _maxCacheSize; | |
616 | |
617 /** | |
618 * Set the maximum size of the cache to the given [size]. | |
619 */ | |
620 void set maxCacheSize(int size) { | |
621 _maxCacheSize = size; | |
622 while (_recentlyUsed.length > _maxCacheSize) { | |
623 if (!_flushAstFromCache()) { | |
624 break; | |
625 } | |
626 } | |
627 } | |
628 | |
629 /** | |
630 * Record that the AST associated with the given [target] was just read from | |
631 * the cache. | |
632 */ | |
633 void accessedAst(AnalysisTarget target) { | |
634 if (_recentlyUsed.remove(target)) { | |
635 _recentlyUsed.add(target); | |
636 return; | |
637 } | |
638 while (_recentlyUsed.length >= _maxCacheSize) { | |
639 if (!_flushAstFromCache()) { | |
640 break; | |
641 } | |
642 } | |
643 _recentlyUsed.add(target); | |
644 } | |
645 | |
646 /** | |
647 * Return `true` if the given [target] is contained in this partition. | 648 * Return `true` if the given [target] is contained in this partition. |
648 */ | 649 */ |
649 // TODO(brianwilkerson) Rename this to something more meaningful, such as | 650 // TODO(brianwilkerson) Rename this to something more meaningful, such as |
650 // isResponsibleFor. | 651 // isResponsibleFor. |
651 bool contains(AnalysisTarget target); | 652 bool contains(AnalysisTarget target); |
652 | 653 |
653 /** | 654 /** |
654 * Return the entry associated with the given [target]. | 655 * Return the entry associated with the given [target]. |
655 */ | 656 */ |
656 CacheEntry get(AnalysisTarget target) => _targetMap[target]; | 657 CacheEntry get(AnalysisTarget target) => _targetMap[target]; |
657 | 658 |
658 /** | 659 /** |
659 * Return an iterator returning all of the map entries mapping targets to | 660 * Return an iterator returning all of the map entries mapping targets to |
660 * cache entries. | 661 * cache entries. |
661 */ | 662 */ |
662 MapIterator<AnalysisTarget, CacheEntry> iterator() => | 663 MapIterator<AnalysisTarget, CacheEntry> iterator() => |
663 new SingleMapIterator<AnalysisTarget, CacheEntry>(_targetMap); | 664 new SingleMapIterator<AnalysisTarget, CacheEntry>(_targetMap); |
664 | 665 |
665 /** | 666 /** |
666 * Associate the given [entry] with the given [target]. | 667 * Associate the given [entry] with the given [target]. |
667 */ | 668 */ |
668 void put(AnalysisTarget target, CacheEntry entry) { | 669 void put(AnalysisTarget target, CacheEntry entry) { |
670 entry._partition = this; | |
Brian Wilkerson
2015/05/07 14:19:19
It would be good to ensure that "entry._partition"
scheglov
2015/05/07 15:49:27
Done.
| |
671 entry._target = target; | |
Brian Wilkerson
2015/05/07 14:19:19
It seems strange to assign the target here. It wou
scheglov
2015/05/07 15:49:27
Yes.
Probably more natural would be to make target
| |
669 entry.fixExceptionState(); | 672 entry.fixExceptionState(); |
670 _targetMap[target] = entry; | 673 _targetMap[target] = entry; |
671 } | 674 } |
672 | 675 |
673 /** | 676 /** |
674 * Remove all information related to the given [target] from this cache. | 677 * Remove all information related to the given [target] from this cache. |
675 */ | 678 */ |
676 void remove(AnalysisTarget target) { | 679 void remove(AnalysisTarget target) { |
677 _recentlyUsed.remove(target); | 680 for (CacheFlushManager flushManager in _flushManagerMap.values) { |
681 flushManager.targetRemoved(target); | |
682 } | |
678 _targetMap.remove(target); | 683 _targetMap.remove(target); |
679 } | 684 } |
680 | 685 |
681 /** | 686 /** |
682 * Record that the AST associated with the given [target] was just removed | 687 * Records that a value of the result described by the given [descriptor] |
683 * from the cache. | 688 * for the given [target] was just read from the cache. |
684 */ | 689 */ |
685 void removedAst(AnalysisTarget target) { | 690 void resultAccessed(AnalysisTarget target, ResultDescriptor descriptor) { |
686 _recentlyUsed.remove(target); | 691 CacheFlushManager flushManager = _getFlushManager(descriptor); |
692 TargetedResult result = new TargetedResult(target, descriptor); | |
693 flushManager.resultAccessed(result); | |
694 } | |
695 | |
696 /** | |
697 * Records that the given [result] was just stored into the cache. | |
698 */ | |
699 void resultStored(TargetedResult result, Object value) { | |
700 CacheFlushManager flushManager = _getFlushManager(result.result); | |
701 List<TargetedResult> resultsToFlush = | |
702 flushManager.resultStored(result, value); | |
703 for (TargetedResult result in resultsToFlush) { | |
704 CacheEntry entry = get(result.target); | |
705 ResultData data = entry._resultMap[result.result]; | |
706 data.flush(); | |
707 } | |
687 } | 708 } |
688 | 709 |
689 /** | 710 /** |
690 * Return the number of targets that are mapped to cache entries. | 711 * Return the number of targets that are mapped to cache entries. |
691 */ | 712 */ |
692 int size() => _targetMap.length; | 713 int size() => _targetMap.length; |
693 | 714 |
694 /** | 715 ResultData _getDataFor(TargetedResult result) { |
695 * Record that the AST associated with the given [target] was just stored to | 716 return _cache._getDataFor(result); |
696 * the cache. | |
697 */ | |
698 void storedAst(AnalysisTarget target) { | |
699 if (_recentlyUsed.contains(target)) { | |
700 return; | |
701 } | |
702 while (_recentlyUsed.length >= _maxCacheSize) { | |
703 if (!_flushAstFromCache()) { | |
704 break; | |
705 } | |
706 } | |
707 _recentlyUsed.add(target); | |
708 } | 717 } |
709 | 718 |
710 /** | 719 /** |
711 * Attempt to flush one AST structure from the cache. Return `true` if a | 720 * Return the [CacheFlushManager] for the given [descriptor], not `null`. |
712 * structure was flushed. | |
713 */ | 721 */ |
714 bool _flushAstFromCache() { | 722 CacheFlushManager _getFlushManager(ResultDescriptor descriptor) { |
715 AnalysisTarget removedTarget = _removeAstToFlush(); | 723 ResultCachingPolicy policy = descriptor.cachingPolicy; |
716 if (removedTarget == null) { | 724 return _flushManagerMap.putIfAbsent( |
717 return false; | 725 policy, () => new CacheFlushManager(policy, _isPriorityAnalysisTarget)); |
718 } | |
719 CacheEntry entry = _targetMap[removedTarget]; | |
720 entry.flushAstStructures(); | |
721 return true; | |
722 } | 726 } |
723 | 727 |
724 /** | 728 bool _isPriorityAnalysisTarget(AnalysisTarget target) { |
725 * Remove and return one target from the list of recently used targets whose | 729 return context.priorityTargets.contains(target); |
726 * AST structure can be flushed from the cache, or `null` if none of the | |
727 * targets can be removed. The target that will be returned will be the target | |
728 * that has been unreferenced for the longest period of time but that is not a | |
729 * priority for analysis. | |
730 */ | |
731 AnalysisTarget _removeAstToFlush() { | |
732 int targetToRemove = -1; | |
733 for (int i = 0; i < _recentlyUsed.length; i++) { | |
734 AnalysisTarget target = _recentlyUsed[i]; | |
735 RetentionPriority priority = | |
736 _retentionPolicy.getAstPriority(target, _targetMap[target]); | |
737 if (priority == RetentionPriority.LOW) { | |
738 return _recentlyUsed.removeAt(i); | |
739 } else if (priority == RetentionPriority.MEDIUM && targetToRemove < 0) { | |
740 targetToRemove = i; | |
741 } | |
742 } | |
743 if (targetToRemove < 0) { | |
744 // This happens if the retention policy returns a priority of HIGH for all | |
745 // of the targets that have been recently used. This is the case, for | |
746 // example, when the list of priority sources is bigger than the current | |
747 // cache size. | |
748 return null; | |
749 } | |
750 return _recentlyUsed.removeAt(targetToRemove); | |
751 } | 730 } |
752 } | 731 } |
753 | 732 |
754 /** | |
755 * A policy objecy that determines how important it is for data to be retained | |
756 * in the analysis cache. | |
757 */ | |
758 abstract class CacheRetentionPolicy { | |
759 /** | |
760 * Return the priority of retaining the AST structure for the given [target] | |
761 * in the given [entry]. | |
762 */ | |
763 // TODO(brianwilkerson) Find a more general mechanism, probably based on task | |
764 // descriptors, to determine which data is still needed for analysis and which | |
765 // can be removed from the cache. Ideally we could (a) remove the need for | |
766 // this class and (b) be able to flush all result data (not just AST's). | |
767 RetentionPriority getAstPriority(AnalysisTarget target, CacheEntry entry); | |
768 } | |
769 | |
770 /** | |
771 * A retention policy that will keep AST's in the cache if there is analysis | |
772 * information that needs to be computed for a source, where the computation is | |
773 * dependent on having the AST. | |
774 */ | |
775 class DefaultRetentionPolicy implements CacheRetentionPolicy { | |
776 /** | |
777 * An instance of this class that can be shared. | |
778 */ | |
779 static const DefaultRetentionPolicy POLICY = const DefaultRetentionPolicy(); | |
780 | |
781 /** | |
782 * Initialize a newly created instance of this class. | |
783 */ | |
784 const DefaultRetentionPolicy(); | |
785 | |
786 // TODO(brianwilkerson) Implement or delete this. | |
787 // /** | |
788 // * Return `true` if there is analysis information in the given entry that ne eds to be | |
789 // * computed, where the computation is dependent on having the AST. | |
790 // * | |
791 // * @param dartEntry the entry being tested | |
792 // * @return `true` if there is analysis information that needs to be computed from the AST | |
793 // */ | |
794 // bool astIsNeeded(DartEntry dartEntry) => | |
795 // dartEntry.hasInvalidData(DartEntry.HINTS) || | |
796 // dartEntry.hasInvalidData(DartEntry.LINTS) || | |
797 // dartEntry.hasInvalidData(DartEntry.VERIFICATION_ERRORS) || | |
798 // dartEntry.hasInvalidData(DartEntry.RESOLUTION_ERRORS); | |
799 | |
800 @override | |
801 RetentionPriority getAstPriority(AnalysisTarget target, CacheEntry entry) { | |
802 // TODO(brianwilkerson) Implement or replace this. | |
803 // if (sourceEntry is DartEntry) { | |
804 // DartEntry dartEntry = sourceEntry; | |
805 // if (astIsNeeded(dartEntry)) { | |
806 // return RetentionPriority.MEDIUM; | |
807 // } | |
808 // } | |
809 // return RetentionPriority.LOW; | |
810 return RetentionPriority.MEDIUM; | |
811 } | |
812 } | |
813 | |
814 /** | 733 /** |
815 * The data about a single analysis result that is stored in a [CacheEntry]. | 734 * The data about a single analysis result that is stored in a [CacheEntry]. |
816 */ | 735 */ |
817 // TODO(brianwilkerson) Consider making this a generic class so that the value | 736 // TODO(brianwilkerson) Consider making this a generic class so that the value |
818 // can be typed. | 737 // can be typed. |
819 class ResultData { | 738 class ResultData { |
820 /** | 739 /** |
821 * The [ResultDescriptor] this result is for. | 740 * The [ResultDescriptor] this result is for. |
822 */ | 741 */ |
823 final ResultDescriptor descriptor; | 742 final ResultDescriptor descriptor; |
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
859 } | 778 } |
860 | 779 |
861 /** | 780 /** |
862 * Add the given [result] to the list of dependent results. | 781 * Add the given [result] to the list of dependent results. |
863 */ | 782 */ |
864 void addDependentResult(TargetedResult result) { | 783 void addDependentResult(TargetedResult result) { |
865 dependentResults.add(result); | 784 dependentResults.add(result); |
866 } | 785 } |
867 | 786 |
868 /** | 787 /** |
788 * Flush this value. | |
789 */ | |
790 void flush() { | |
791 state = CacheState.FLUSHED; | |
792 value = descriptor.defaultValue; | |
793 } | |
794 | |
795 /** | |
869 * Invalidate this [ResultData] that corresponds to [thisResult] and | 796 * Invalidate this [ResultData] that corresponds to [thisResult] and |
870 * propagate invalidation to the results that depend on this one. | 797 * propagate invalidation to the results that depend on this one. |
871 */ | 798 */ |
872 void invalidate( | 799 void invalidate(CachePartition partition, TargetedResult thisResult, |
873 AnalysisCache cache, TargetedResult thisResult, CacheState newState) { | 800 CacheState newState) { |
874 // Invalidate this result. | 801 // Invalidate this result. |
875 state = newState; | 802 state = newState; |
876 value = descriptor.defaultValue; | 803 value = descriptor.defaultValue; |
877 // Stop depending on other results. | 804 // Stop depending on other results. |
878 List<TargetedResult> dependedOnResults = this.dependedOnResults; | 805 List<TargetedResult> dependedOnResults = this.dependedOnResults; |
879 this.dependedOnResults = <TargetedResult>[]; | 806 this.dependedOnResults = <TargetedResult>[]; |
880 dependedOnResults.forEach((TargetedResult dependedOnResult) { | 807 dependedOnResults.forEach((TargetedResult dependedOnResult) { |
881 ResultData data = cache._getDataFor(dependedOnResult); | 808 ResultData data = partition._getDataFor(dependedOnResult); |
882 data.removeDependentResult(thisResult); | 809 data.removeDependentResult(thisResult); |
883 }); | 810 }); |
884 // Invalidate results that depend on this result. | 811 // Invalidate results that depend on this result. |
885 List<TargetedResult> dependentResults = this.dependentResults; | 812 List<TargetedResult> dependentResults = this.dependentResults; |
886 this.dependentResults = <TargetedResult>[]; | 813 this.dependentResults = <TargetedResult>[]; |
887 dependentResults.forEach((TargetedResult dependentResult) { | 814 dependentResults.forEach((TargetedResult dependentResult) { |
888 ResultData data = cache._getDataFor(dependentResult); | 815 ResultData data = partition._getDataFor(dependentResult); |
889 data.invalidate(cache, dependentResult, newState); | 816 data.invalidate(partition, dependentResult, newState); |
890 }); | 817 }); |
891 } | 818 } |
892 | 819 |
893 /** | 820 /** |
894 * Remove the given [result] from the list of dependent results. | 821 * Remove the given [result] from the list of dependent results. |
895 */ | 822 */ |
896 void removeDependentResult(TargetedResult result) { | 823 void removeDependentResult(TargetedResult result) { |
897 dependentResults.remove(result); | 824 dependentResults.remove(result); |
898 } | 825 } |
899 | 826 |
900 /** | 827 /** |
901 * Set the [dependedOn] on which this result depends. | 828 * Set the [dependedOn] on which this result depends. |
902 */ | 829 */ |
903 void setDependedOnResults(AnalysisCache cache, TargetedResult thisResult, | 830 void setDependedOnResults(CachePartition partition, TargetedResult thisResult, |
904 List<TargetedResult> dependedOn) { | 831 List<TargetedResult> dependedOn) { |
905 dependedOnResults.forEach((TargetedResult dependedOnResult) { | 832 dependedOnResults.forEach((TargetedResult dependedOnResult) { |
906 ResultData data = cache._getDataFor(dependedOnResult); | 833 ResultData data = partition._getDataFor(dependedOnResult); |
907 data.removeDependentResult(thisResult); | 834 data.removeDependentResult(thisResult); |
908 }); | 835 }); |
909 dependedOnResults = dependedOn; | 836 dependedOnResults = dependedOn; |
910 dependedOnResults.forEach((TargetedResult dependentResult) { | 837 dependedOnResults.forEach((TargetedResult dependentResult) { |
911 ResultData data = cache._getDataFor(dependentResult); | 838 ResultData data = partition._getDataFor(dependentResult); |
912 data.addDependentResult(thisResult); | 839 data.addDependentResult(thisResult); |
913 }); | 840 }); |
914 } | 841 } |
915 } | 842 } |
916 | 843 |
917 /** | 844 /** |
918 * A cache partition that contains all of the targets in the SDK. | 845 * A cache partition that contains all of the targets in the SDK. |
919 */ | 846 */ |
920 class SdkCachePartition extends CachePartition { | 847 class SdkCachePartition extends CachePartition { |
921 /** | 848 /** |
922 * Initialize a newly created cache partition, belonging to the given | 849 * Initialize a newly created cache partition, belonging to the given |
923 * [context]. The partition will maintain at most [maxCacheSize] AST | 850 * [context]. |
924 * structures in the cache. | |
925 */ | 851 */ |
926 SdkCachePartition(InternalAnalysisContext context, int maxCacheSize) | 852 SdkCachePartition(InternalAnalysisContext context) : super(context); |
927 : super(context, maxCacheSize, DefaultRetentionPolicy.POLICY); | |
928 | 853 |
929 @override | 854 @override |
930 bool contains(AnalysisTarget target) { | 855 bool contains(AnalysisTarget target) { |
931 Source source = target.source; | 856 Source source = target.source; |
932 return source != null && source.isInSystemLibrary; | 857 return source != null && source.isInSystemLibrary; |
933 } | 858 } |
934 } | 859 } |
935 | 860 |
936 /** | 861 /** |
937 * A specification of a specific result computed for a specific target. | 862 * A specification of a specific result computed for a specific target. |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
972 @override | 897 @override |
973 String toString() => '$result for $target'; | 898 String toString() => '$result for $target'; |
974 } | 899 } |
975 | 900 |
976 /** | 901 /** |
977 * A cache partition that contains all targets not contained in other partitions . | 902 * A cache partition that contains all targets not contained in other partitions . |
978 */ | 903 */ |
979 class UniversalCachePartition extends CachePartition { | 904 class UniversalCachePartition extends CachePartition { |
980 /** | 905 /** |
981 * Initialize a newly created cache partition, belonging to the given | 906 * Initialize a newly created cache partition, belonging to the given |
982 * [context]. The partition will maintain at most [maxCacheSize] AST | 907 * [context]. |
983 * structures in the cache, using the [retentionPolicy] to determine which | |
984 * AST structures to flush. | |
985 */ | 908 */ |
986 UniversalCachePartition(InternalAnalysisContext context, int maxCacheSize, | 909 UniversalCachePartition(InternalAnalysisContext context) : super(context); |
987 CacheRetentionPolicy retentionPolicy) | |
988 : super(context, maxCacheSize, retentionPolicy); | |
989 | 910 |
990 @override | 911 @override |
991 bool contains(AnalysisTarget target) => true; | 912 bool contains(AnalysisTarget target) => true; |
992 } | 913 } |
OLD | NEW |