| 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] less or equal to [maxSize]. |
| 520 * |
| 521 * Results for priority files are never flushed, so this method might leave |
| 522 * [currentSize] greater than [maxSize]. |
| 523 */ |
| 524 List<TargetedResult> flushToSize() { |
| 525 // If still under the cap, done. |
| 526 if (maxSize == -1 || currentSize <= maxSize) { |
| 527 return TargetedResult.EMPTY_LIST; |
| 528 } |
| 529 // Flush results until we are under the cap. |
| 530 List<TargetedResult> resultsToFlush = <TargetedResult>[]; |
| 531 for (TargetedResult result in recentlyUsed) { |
| 532 if (isPriorityAnalysisTarget(result.target)) { |
| 533 continue; |
| 534 } |
| 535 resultsToFlush.add(result); |
| 536 int size = resultSizeMap.remove(result); |
| 537 assert(size != null); |
| 538 currentSize -= size; |
| 539 if (currentSize <= maxSize) { |
| 540 break; |
| 541 } |
| 542 } |
| 543 recentlyUsed.removeAll(resultsToFlush); |
| 544 return resultsToFlush; |
| 545 } |
| 546 |
| 547 /** |
| 548 * Notifies this manager that the corresponding analysis context is active. |
| 549 */ |
| 550 void madeActive() { |
| 551 maxSize = maxActiveSize; |
| 552 } |
| 553 |
| 554 /** |
| 555 * Notifies this manager that the corresponding analysis context is idle. |
| 556 * Returns [TargetedResult]s that should be flushed from the cache. |
| 557 */ |
| 558 List<TargetedResult> madeIdle() { |
| 559 maxSize = maxIdleSize; |
| 560 return flushToSize(); |
| 561 } |
| 562 |
| 563 /** |
| 564 * Records that the given [result] was just read from the cache. |
| 565 */ |
| 566 void resultAccessed(TargetedResult result) { |
| 567 if (recentlyUsed.remove(result)) { |
| 568 recentlyUsed.add(result); |
| 569 } |
| 570 } |
| 571 |
| 572 /** |
| 573 * Records that the given [newResult] and [newValue] were stored to the cache. |
| 574 * Returns [TargetedResult]s that should be flushed from the cache. |
| 575 */ |
| 576 List<TargetedResult> resultStored(TargetedResult newResult, T newValue) { |
| 577 if (!recentlyUsed.remove(newResult)) { |
| 578 int size = policy.measure(newValue); |
| 579 resultSizeMap[newResult] = size; |
| 580 currentSize += size; |
| 581 } |
| 582 recentlyUsed.add(newResult); |
| 583 return flushToSize(); |
| 584 } |
| 585 |
| 586 /** |
| 587 * Records that the given [target] was just removed from to the cache. |
| 588 */ |
| 589 void targetRemoved(AnalysisTarget target) { |
| 590 List<TargetedResult> resultsToRemove = <TargetedResult>[]; |
| 591 for (TargetedResult result in recentlyUsed) { |
| 592 if (result.target == target) { |
| 593 resultsToRemove.add(result); |
| 594 int size = resultSizeMap.remove(result); |
| 595 assert(size != null); |
| 596 currentSize -= size; |
| 597 } |
| 598 } |
| 599 recentlyUsed.removeAll(resultsToRemove); |
| 600 } |
| 601 } |
| 602 |
| 603 /** |
| 543 * A single partition in an LRU cache of information related to analysis. | 604 * A single partition in an LRU cache of information related to analysis. |
| 544 */ | 605 */ |
| 545 abstract class CachePartition { | 606 abstract class CachePartition { |
| 546 /** | 607 /** |
| 608 * The [AnalysisCache] that owns this partition. |
| 609 * |
| 610 * TODO(scheglov) It seems wrong. Partitions may be shared between caches. |
| 611 * But we need a way to go from every "enclosing" partition into "enclosed" |
| 612 * ones. |
| 613 */ |
| 614 AnalysisCache _cache; |
| 615 |
| 616 /** |
| 547 * The context that owns this partition. Multiple contexts can reference a | 617 * The context that owns this partition. Multiple contexts can reference a |
| 548 * partition, but only one context can own it. | 618 * partition, but only one context can own it. |
| 549 */ | 619 */ |
| 550 final InternalAnalysisContext context; | 620 final InternalAnalysisContext context; |
| 551 | 621 |
| 552 /** | 622 /** |
| 553 * The maximum number of sources for which AST structures should be kept in | 623 * A table mapping caching policies to the cache flush managers. |
| 554 * the cache. | |
| 555 */ | 624 */ |
| 556 int _maxCacheSize = 0; | 625 final HashMap<ResultCachingPolicy, CacheFlushManager> _flushManagerMap = |
| 557 | 626 new HashMap<ResultCachingPolicy, CacheFlushManager>(); |
| 558 /** | |
| 559 * The policy used to determine which results to remove from the cache. | |
| 560 */ | |
| 561 final CacheRetentionPolicy _retentionPolicy; | |
| 562 | 627 |
| 563 /** | 628 /** |
| 564 * A table mapping the targets belonging to this partition to the information | 629 * A table mapping the targets belonging to this partition to the information |
| 565 * known about those targets. | 630 * known about those targets. |
| 566 */ | 631 */ |
| 567 HashMap<AnalysisTarget, CacheEntry> _targetMap = | 632 HashMap<AnalysisTarget, CacheEntry> _targetMap = |
| 568 new HashMap<AnalysisTarget, CacheEntry>(); | 633 new HashMap<AnalysisTarget, CacheEntry>(); |
| 569 | 634 |
| 570 /** | 635 /** |
| 571 * A list containing the most recently accessed targets with the most recently | 636 * 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 | 637 * [context]. |
| 573 * allowed then the least recently used target will be removed and will have | |
| 574 * it's cached AST structure flushed. | |
| 575 */ | 638 */ |
| 576 List<AnalysisTarget> _recentlyUsed = <AnalysisTarget>[]; | 639 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 | 640 |
| 603 /** | 641 /** |
| 604 * Return a table mapping the targets known to the context to the information | 642 * Return a table mapping the targets known to the context to the information |
| 605 * known about the target. | 643 * known about the target. |
| 606 * | 644 * |
| 607 * <b>Note:</b> This method is only visible for use by [AnalysisCache] and | 645 * <b>Note:</b> This method is only visible for use by [AnalysisCache] and |
| 608 * should not be used for any other purpose. | 646 * should not be used for any other purpose. |
| 609 */ | 647 */ |
| 610 Map<AnalysisTarget, CacheEntry> get map => _targetMap; | 648 Map<AnalysisTarget, CacheEntry> get map => _targetMap; |
| 611 | 649 |
| 612 /** | 650 /** |
| 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. | 651 * Return `true` if the given [target] is contained in this partition. |
| 648 */ | 652 */ |
| 649 // TODO(brianwilkerson) Rename this to something more meaningful, such as | 653 // TODO(brianwilkerson) Rename this to something more meaningful, such as |
| 650 // isResponsibleFor. | 654 // isResponsibleFor. |
| 651 bool contains(AnalysisTarget target); | 655 bool contains(AnalysisTarget target); |
| 652 | 656 |
| 653 /** | 657 /** |
| 654 * Return the entry associated with the given [target]. | 658 * Return the entry associated with the given [target]. |
| 655 */ | 659 */ |
| 656 CacheEntry get(AnalysisTarget target) => _targetMap[target]; | 660 CacheEntry get(AnalysisTarget target) => _targetMap[target]; |
| 657 | 661 |
| 658 /** | 662 /** |
| 659 * Return an iterator returning all of the map entries mapping targets to | 663 * Return an iterator returning all of the map entries mapping targets to |
| 660 * cache entries. | 664 * cache entries. |
| 661 */ | 665 */ |
| 662 MapIterator<AnalysisTarget, CacheEntry> iterator() => | 666 MapIterator<AnalysisTarget, CacheEntry> iterator() => |
| 663 new SingleMapIterator<AnalysisTarget, CacheEntry>(_targetMap); | 667 new SingleMapIterator<AnalysisTarget, CacheEntry>(_targetMap); |
| 664 | 668 |
| 665 /** | 669 /** |
| 666 * Associate the given [entry] with the given [target]. | 670 * Associate the given [entry] with the given [target]. |
| 667 */ | 671 */ |
| 668 void put(AnalysisTarget target, CacheEntry entry) { | 672 void put(AnalysisTarget target, CacheEntry entry) { |
| 673 if (entry._partition != null) { |
| 674 throw new StateError( |
| 675 'The entry for $target is already in ${entry._partition}'); |
| 676 } |
| 677 entry._partition = this; |
| 678 entry._target = target; |
| 669 entry.fixExceptionState(); | 679 entry.fixExceptionState(); |
| 670 _targetMap[target] = entry; | 680 _targetMap[target] = entry; |
| 671 } | 681 } |
| 672 | 682 |
| 673 /** | 683 /** |
| 674 * Remove all information related to the given [target] from this cache. | 684 * Remove all information related to the given [target] from this cache. |
| 675 */ | 685 */ |
| 676 void remove(AnalysisTarget target) { | 686 void remove(AnalysisTarget target) { |
| 677 _recentlyUsed.remove(target); | 687 for (CacheFlushManager flushManager in _flushManagerMap.values) { |
| 688 flushManager.targetRemoved(target); |
| 689 } |
| 678 _targetMap.remove(target); | 690 _targetMap.remove(target); |
| 679 } | 691 } |
| 680 | 692 |
| 681 /** | 693 /** |
| 682 * Record that the AST associated with the given [target] was just removed | 694 * Records that a value of the result described by the given [descriptor] |
| 683 * from the cache. | 695 * for the given [target] was just read from the cache. |
| 684 */ | 696 */ |
| 685 void removedAst(AnalysisTarget target) { | 697 void resultAccessed(AnalysisTarget target, ResultDescriptor descriptor) { |
| 686 _recentlyUsed.remove(target); | 698 CacheFlushManager flushManager = _getFlushManager(descriptor); |
| 699 TargetedResult result = new TargetedResult(target, descriptor); |
| 700 flushManager.resultAccessed(result); |
| 701 } |
| 702 |
| 703 /** |
| 704 * Records that the given [result] was just stored into the cache. |
| 705 */ |
| 706 void resultStored(TargetedResult result, Object value) { |
| 707 CacheFlushManager flushManager = _getFlushManager(result.result); |
| 708 List<TargetedResult> resultsToFlush = |
| 709 flushManager.resultStored(result, value); |
| 710 for (TargetedResult result in resultsToFlush) { |
| 711 CacheEntry entry = get(result.target); |
| 712 ResultData data = entry._resultMap[result.result]; |
| 713 data.flush(); |
| 714 } |
| 687 } | 715 } |
| 688 | 716 |
| 689 /** | 717 /** |
| 690 * Return the number of targets that are mapped to cache entries. | 718 * Return the number of targets that are mapped to cache entries. |
| 691 */ | 719 */ |
| 692 int size() => _targetMap.length; | 720 int size() => _targetMap.length; |
| 693 | 721 |
| 694 /** | 722 ResultData _getDataFor(TargetedResult result) { |
| 695 * Record that the AST associated with the given [target] was just stored to | 723 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 } | 724 } |
| 709 | 725 |
| 710 /** | 726 /** |
| 711 * Attempt to flush one AST structure from the cache. Return `true` if a | 727 * Return the [CacheFlushManager] for the given [descriptor], not `null`. |
| 712 * structure was flushed. | |
| 713 */ | 728 */ |
| 714 bool _flushAstFromCache() { | 729 CacheFlushManager _getFlushManager(ResultDescriptor descriptor) { |
| 715 AnalysisTarget removedTarget = _removeAstToFlush(); | 730 ResultCachingPolicy policy = descriptor.cachingPolicy; |
| 716 if (removedTarget == null) { | 731 return _flushManagerMap.putIfAbsent( |
| 717 return false; | 732 policy, () => new CacheFlushManager(policy, _isPriorityAnalysisTarget)); |
| 718 } | |
| 719 CacheEntry entry = _targetMap[removedTarget]; | |
| 720 entry.flushAstStructures(); | |
| 721 return true; | |
| 722 } | 733 } |
| 723 | 734 |
| 724 /** | 735 bool _isPriorityAnalysisTarget(AnalysisTarget target) { |
| 725 * Remove and return one target from the list of recently used targets whose | 736 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 } | 737 } |
| 752 } | 738 } |
| 753 | 739 |
| 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 /** | 740 /** |
| 815 * The data about a single analysis result that is stored in a [CacheEntry]. | 741 * The data about a single analysis result that is stored in a [CacheEntry]. |
| 816 */ | 742 */ |
| 817 // TODO(brianwilkerson) Consider making this a generic class so that the value | 743 // TODO(brianwilkerson) Consider making this a generic class so that the value |
| 818 // can be typed. | 744 // can be typed. |
| 819 class ResultData { | 745 class ResultData { |
| 820 /** | 746 /** |
| 821 * The [ResultDescriptor] this result is for. | 747 * The [ResultDescriptor] this result is for. |
| 822 */ | 748 */ |
| 823 final ResultDescriptor descriptor; | 749 final ResultDescriptor descriptor; |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 859 } | 785 } |
| 860 | 786 |
| 861 /** | 787 /** |
| 862 * Add the given [result] to the list of dependent results. | 788 * Add the given [result] to the list of dependent results. |
| 863 */ | 789 */ |
| 864 void addDependentResult(TargetedResult result) { | 790 void addDependentResult(TargetedResult result) { |
| 865 dependentResults.add(result); | 791 dependentResults.add(result); |
| 866 } | 792 } |
| 867 | 793 |
| 868 /** | 794 /** |
| 795 * Flush this value. |
| 796 */ |
| 797 void flush() { |
| 798 state = CacheState.FLUSHED; |
| 799 value = descriptor.defaultValue; |
| 800 } |
| 801 |
| 802 /** |
| 869 * Invalidate this [ResultData] that corresponds to [thisResult] and | 803 * Invalidate this [ResultData] that corresponds to [thisResult] and |
| 870 * propagate invalidation to the results that depend on this one. | 804 * propagate invalidation to the results that depend on this one. |
| 871 */ | 805 */ |
| 872 void invalidate( | 806 void invalidate(CachePartition partition, TargetedResult thisResult, |
| 873 AnalysisCache cache, TargetedResult thisResult, CacheState newState) { | 807 CacheState newState) { |
| 874 // Invalidate this result. | 808 // Invalidate this result. |
| 875 state = newState; | 809 state = newState; |
| 876 value = descriptor.defaultValue; | 810 value = descriptor.defaultValue; |
| 877 // Stop depending on other results. | 811 // Stop depending on other results. |
| 878 List<TargetedResult> dependedOnResults = this.dependedOnResults; | 812 List<TargetedResult> dependedOnResults = this.dependedOnResults; |
| 879 this.dependedOnResults = <TargetedResult>[]; | 813 this.dependedOnResults = <TargetedResult>[]; |
| 880 dependedOnResults.forEach((TargetedResult dependedOnResult) { | 814 dependedOnResults.forEach((TargetedResult dependedOnResult) { |
| 881 ResultData data = cache._getDataFor(dependedOnResult); | 815 ResultData data = partition._getDataFor(dependedOnResult); |
| 882 data.removeDependentResult(thisResult); | 816 data.removeDependentResult(thisResult); |
| 883 }); | 817 }); |
| 884 // Invalidate results that depend on this result. | 818 // Invalidate results that depend on this result. |
| 885 List<TargetedResult> dependentResults = this.dependentResults; | 819 List<TargetedResult> dependentResults = this.dependentResults; |
| 886 this.dependentResults = <TargetedResult>[]; | 820 this.dependentResults = <TargetedResult>[]; |
| 887 dependentResults.forEach((TargetedResult dependentResult) { | 821 dependentResults.forEach((TargetedResult dependentResult) { |
| 888 ResultData data = cache._getDataFor(dependentResult); | 822 ResultData data = partition._getDataFor(dependentResult); |
| 889 data.invalidate(cache, dependentResult, newState); | 823 data.invalidate(partition, dependentResult, newState); |
| 890 }); | 824 }); |
| 891 } | 825 } |
| 892 | 826 |
| 893 /** | 827 /** |
| 894 * Remove the given [result] from the list of dependent results. | 828 * Remove the given [result] from the list of dependent results. |
| 895 */ | 829 */ |
| 896 void removeDependentResult(TargetedResult result) { | 830 void removeDependentResult(TargetedResult result) { |
| 897 dependentResults.remove(result); | 831 dependentResults.remove(result); |
| 898 } | 832 } |
| 899 | 833 |
| 900 /** | 834 /** |
| 901 * Set the [dependedOn] on which this result depends. | 835 * Set the [dependedOn] on which this result depends. |
| 902 */ | 836 */ |
| 903 void setDependedOnResults(AnalysisCache cache, TargetedResult thisResult, | 837 void setDependedOnResults(CachePartition partition, TargetedResult thisResult, |
| 904 List<TargetedResult> dependedOn) { | 838 List<TargetedResult> dependedOn) { |
| 905 dependedOnResults.forEach((TargetedResult dependedOnResult) { | 839 dependedOnResults.forEach((TargetedResult dependedOnResult) { |
| 906 ResultData data = cache._getDataFor(dependedOnResult); | 840 ResultData data = partition._getDataFor(dependedOnResult); |
| 907 data.removeDependentResult(thisResult); | 841 data.removeDependentResult(thisResult); |
| 908 }); | 842 }); |
| 909 dependedOnResults = dependedOn; | 843 dependedOnResults = dependedOn; |
| 910 dependedOnResults.forEach((TargetedResult dependentResult) { | 844 dependedOnResults.forEach((TargetedResult dependentResult) { |
| 911 ResultData data = cache._getDataFor(dependentResult); | 845 ResultData data = partition._getDataFor(dependentResult); |
| 912 data.addDependentResult(thisResult); | 846 data.addDependentResult(thisResult); |
| 913 }); | 847 }); |
| 914 } | 848 } |
| 915 } | 849 } |
| 916 | 850 |
| 917 /** | 851 /** |
| 918 * A cache partition that contains all of the targets in the SDK. | 852 * A cache partition that contains all of the targets in the SDK. |
| 919 */ | 853 */ |
| 920 class SdkCachePartition extends CachePartition { | 854 class SdkCachePartition extends CachePartition { |
| 921 /** | 855 /** |
| 922 * Initialize a newly created cache partition, belonging to the given | 856 * Initialize a newly created cache partition, belonging to the given |
| 923 * [context]. The partition will maintain at most [maxCacheSize] AST | 857 * [context]. |
| 924 * structures in the cache. | |
| 925 */ | 858 */ |
| 926 SdkCachePartition(InternalAnalysisContext context, int maxCacheSize) | 859 SdkCachePartition(InternalAnalysisContext context) : super(context); |
| 927 : super(context, maxCacheSize, DefaultRetentionPolicy.POLICY); | |
| 928 | 860 |
| 929 @override | 861 @override |
| 930 bool contains(AnalysisTarget target) { | 862 bool contains(AnalysisTarget target) { |
| 931 Source source = target.source; | 863 Source source = target.source; |
| 932 return source != null && source.isInSystemLibrary; | 864 return source != null && source.isInSystemLibrary; |
| 933 } | 865 } |
| 934 } | 866 } |
| 935 | 867 |
| 936 /** | 868 /** |
| 937 * A specification of a specific result computed for a specific target. | 869 * 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 | 904 @override |
| 973 String toString() => '$result for $target'; | 905 String toString() => '$result for $target'; |
| 974 } | 906 } |
| 975 | 907 |
| 976 /** | 908 /** |
| 977 * A cache partition that contains all targets not contained in other partitions
. | 909 * A cache partition that contains all targets not contained in other partitions
. |
| 978 */ | 910 */ |
| 979 class UniversalCachePartition extends CachePartition { | 911 class UniversalCachePartition extends CachePartition { |
| 980 /** | 912 /** |
| 981 * Initialize a newly created cache partition, belonging to the given | 913 * Initialize a newly created cache partition, belonging to the given |
| 982 * [context]. The partition will maintain at most [maxCacheSize] AST | 914 * [context]. |
| 983 * structures in the cache, using the [retentionPolicy] to determine which | |
| 984 * AST structures to flush. | |
| 985 */ | 915 */ |
| 986 UniversalCachePartition(InternalAnalysisContext context, int maxCacheSize, | 916 UniversalCachePartition(InternalAnalysisContext context) : super(context); |
| 987 CacheRetentionPolicy retentionPolicy) | |
| 988 : super(context, maxCacheSize, retentionPolicy); | |
| 989 | 917 |
| 990 @override | 918 @override |
| 991 bool contains(AnalysisTarget target) => true; | 919 bool contains(AnalysisTarget target) => true; |
| 992 } | 920 } |
| OLD | NEW |