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

Side by Side Diff: pkg/analyzer/lib/src/generated/incremental_resolver.dart

Issue 1650873002: Fix memory leak in incremental resolver (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 4 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, 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.generated.incremental_resolver; 5 library analyzer.src.generated.incremental_resolver;
6 6
7 import 'dart:collection'; 7 import 'dart:collection';
8 import 'dart:math' as math; 8 import 'dart:math' as math;
9 9
10 import 'package:analyzer/dart/ast/ast.dart'; 10 import 'package:analyzer/dart/ast/ast.dart';
(...skipping 934 matching lines...) Expand 10 before | Expand all | Expand 10 after
945 */ 945 */
946 class IncrementalResolver { 946 class IncrementalResolver {
947 /** 947 /**
948 * The element of the compilation unit being resolved. 948 * The element of the compilation unit being resolved.
949 */ 949 */
950 final CompilationUnitElementImpl _definingUnit; 950 final CompilationUnitElementImpl _definingUnit;
951 951
952 /** 952 /**
953 * The context the compilation unit being resolved in. 953 * The context the compilation unit being resolved in.
954 */ 954 */
955 AnalysisContext _context; 955 final AnalysisContext _context;
956 956
957 /** 957 /**
958 * The object used to access the types from the core library. 958 * The object used to access the types from the core library.
959 */ 959 */
960 TypeProvider _typeProvider; 960 final TypeProvider _typeProvider;
961 961
962 /** 962 /**
963 * The type system primitives. 963 * The type system primitives.
964 */ 964 */
965 TypeSystem _typeSystem; 965 final TypeSystem _typeSystem;
966 966
967 /** 967 /**
968 * The element for the library containing the compilation unit being resolved. 968 * The element for the library containing the compilation unit being resolved.
969 */ 969 */
970 LibraryElementImpl _definingLibrary; 970 final LibraryElementImpl _definingLibrary;
971
972 final AnalysisCache _cache;
971 973
972 /** 974 /**
973 * The [CacheEntry] corresponding to the source being resolved. 975 * The [CacheEntry] corresponding to the source being resolved.
974 */ 976 */
975 CacheEntry newSourceEntry; 977 final CacheEntry newSourceEntry;
976 978
977 /** 979 /**
978 * The [CacheEntry] corresponding to the [LibrarySpecificUnit] being resolved. 980 * The [CacheEntry] corresponding to the [LibrarySpecificUnit] being resolved.
979 */ 981 */
980 CacheEntry newUnitEntry; 982 final CacheEntry newUnitEntry;
981 983
982 /** 984 /**
983 * The source representing the compilation unit being visited. 985 * The source representing the compilation unit being visited.
984 */ 986 */
985 Source _source; 987 final Source _source;
986 988
987 /** 989 /**
988 * The source representing the library of the compilation unit being visited. 990 * The source representing the library of the compilation unit being visited.
989 */ 991 */
990 Source _librarySource; 992 final Source _librarySource;
991 993
992 /** 994 /**
993 * The offset of the changed contents. 995 * The offset of the changed contents.
994 */ 996 */
995 final int _updateOffset; 997 final int _updateOffset;
996 998
997 /** 999 /**
998 * The end of the changed contents in the old unit. 1000 * The end of the changed contents in the old unit.
999 */ 1001 */
1000 final int _updateEndOld; 1002 final int _updateEndOld;
1001 1003
1002 /** 1004 /**
1003 * The end of the changed contents in the new unit. 1005 * The end of the changed contents in the new unit.
1004 */ 1006 */
1005 final int _updateEndNew; 1007 final int _updateEndNew;
1006 1008
1007 /** 1009 /**
1008 * The delta between [_updateEndNew] and [_updateEndOld]. 1010 * The delta between [_updateEndNew] and [_updateEndOld].
1009 */ 1011 */
1010 int _updateDelta; 1012 final int _updateDelta;
1011 1013
1012 /** 1014 /**
1013 * The set of [AnalysisError]s that have been already shifted. 1015 * The set of [AnalysisError]s that have been already shifted.
1014 */ 1016 */
1015 Set<AnalysisError> _alreadyShiftedErrors = new HashSet.identity(); 1017 final Set<AnalysisError> _alreadyShiftedErrors = new HashSet.identity();
1016 1018
1017 RecordingErrorListener errorListener = new RecordingErrorListener(); 1019 final RecordingErrorListener errorListener = new RecordingErrorListener();
1018 ResolutionContext _resolutionContext; 1020 ResolutionContext _resolutionContext;
1019 1021
1020 List<AnalysisError> _resolveErrors = AnalysisError.NO_ERRORS; 1022 List<AnalysisError> _resolveErrors = AnalysisError.NO_ERRORS;
1021 List<AnalysisError> _verifyErrors = AnalysisError.NO_ERRORS; 1023 List<AnalysisError> _verifyErrors = AnalysisError.NO_ERRORS;
1022 1024
1023 /** 1025 /**
1024 * Initialize a newly created incremental resolver to resolve a node in the 1026 * Initialize a newly created incremental resolver to resolve a node in the
1025 * given source in the given library. 1027 * given source in the given library.
1026 */ 1028 */
1027 IncrementalResolver( 1029 IncrementalResolver(
1030 this._cache,
1028 this.newSourceEntry, 1031 this.newSourceEntry,
1029 this.newUnitEntry, 1032 this.newUnitEntry,
1030 this._definingUnit, 1033 CompilationUnitElementImpl definingUnit,
1031 this._updateOffset, 1034 this._updateOffset,
1032 this._updateEndOld, 1035 int updateEndOld,
1033 this._updateEndNew) { 1036 int updateEndNew)
1034 _updateDelta = _updateEndNew - _updateEndOld; 1037 : _definingUnit = definingUnit,
1035 _definingLibrary = _definingUnit.library; 1038 _context = definingUnit.context,
1036 _librarySource = _definingLibrary.source; 1039 _typeProvider = definingUnit.context.typeProvider,
1037 _source = _definingUnit.source; 1040 _typeSystem = definingUnit.context.typeSystem,
Brian Wilkerson 2016/02/01 14:58:16 No need to duplicate "definingUnit.context" in eit
skybrian 2016/02/02 01:16:54 If I change it to _context I get this error: Only
Brian Wilkerson 2016/02/02 16:32:06 Ah, right. I'd forgotten that.
skybrian 2016/02/02 22:42:11 Okay, assuming by "leave it as is" you didn't mean
Brian Wilkerson 2016/02/02 22:51:14 Correct. I meant "leave the code the way I saw it
1038 _context = _definingUnit.context; 1041 _definingLibrary = definingUnit.library,
1039 _typeProvider = _context.typeProvider; 1042 _source = definingUnit.source,
1040 _typeSystem = _context.typeSystem; 1043 _librarySource = definingUnit.library.source,
1041 } 1044 _updateEndOld = updateEndOld,
1045 _updateEndNew = updateEndNew,
1046 _updateDelta = updateEndNew - updateEndOld;
1042 1047
1043 /** 1048 /**
1044 * Resolve [node], reporting any errors or warnings to the given listener. 1049 * Resolve [node], reporting any errors or warnings to the given listener.
1045 * 1050 *
1046 * [node] - the root of the AST structure to be resolved. 1051 * [node] - the root of the AST structure to be resolved.
1047 * 1052 *
1048 * Returns `true` if resolution was successful. 1053 * Returns `true` if resolution was successful.
1049 */ 1054 */
1050 bool resolve(AstNode node) { 1055 bool resolve(AstNode node) {
1051 logger.enter('resolve: $_definingUnit'); 1056 logger.enter('resolve: $_definingUnit');
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
1272 _updateEndOld, _updateEndNew, _updateDelta)); 1277 _updateEndOld, _updateEndNew, _updateDelta));
1273 } finally { 1278 } finally {
1274 timer.stop('invalidate cache with delta'); 1279 timer.stop('invalidate cache with delta');
1275 } 1280 }
1276 } 1281 }
1277 } 1282 }
1278 1283
1279 void _updateElementNameOffsets() { 1284 void _updateElementNameOffsets() {
1280 LoggingTimer timer = logger.startTimer(); 1285 LoggingTimer timer = logger.startTimer();
1281 try { 1286 try {
1282 _definingUnit 1287 _definingUnit.accept(
1283 .accept(new _ElementOffsetUpdater(_updateOffset, _updateDelta)); 1288 new _ElementOffsetUpdater(_updateOffset, _updateDelta, _cache));
1284 _definingUnit.afterIncrementalResolution(); 1289 _definingUnit.afterIncrementalResolution();
1285 } finally { 1290 } finally {
1286 timer.stop('update element offsets'); 1291 timer.stop('update element offsets');
1287 } 1292 }
1288 } 1293 }
1289 1294
1290 void _updateEntry() { 1295 void _updateEntry() {
1291 _updateErrors_NEW(RESOLVE_TYPE_NAMES_ERRORS, []); 1296 _updateErrors_NEW(RESOLVE_TYPE_NAMES_ERRORS, []);
1292 _updateErrors_NEW(RESOLVE_UNIT_ERRORS, _resolveErrors); 1297 _updateErrors_NEW(RESOLVE_UNIT_ERRORS, _resolveErrors);
1293 _updateErrors_NEW(VARIABLE_REFERENCE_ERRORS, []); 1298 _updateErrors_NEW(VARIABLE_REFERENCE_ERRORS, []);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1351 _verifyErrors = errorListener.getErrorsForSource(_source); 1356 _verifyErrors = errorListener.getErrorsForSource(_source);
1352 } finally { 1357 } finally {
1353 timer.stop('verify'); 1358 timer.stop('verify');
1354 } 1359 }
1355 } 1360 }
1356 } 1361 }
1357 1362
1358 class PoorMansIncrementalResolver { 1363 class PoorMansIncrementalResolver {
1359 final TypeProvider _typeProvider; 1364 final TypeProvider _typeProvider;
1360 final Source _unitSource; 1365 final Source _unitSource;
1366 final AnalysisCache _cache;
1361 1367
1362 /** 1368 /**
1363 * The [CacheEntry] corresponding to the source being resolved. 1369 * The [CacheEntry] corresponding to the source being resolved.
1364 */ 1370 */
1365 CacheEntry _sourceEntry; 1371 final CacheEntry _sourceEntry;
1366 1372
1367 /** 1373 /**
1368 * The [CacheEntry] corresponding to the [LibrarySpecificUnit] being resolved. 1374 * The [CacheEntry] corresponding to the [LibrarySpecificUnit] being resolved.
1369 */ 1375 */
1370 CacheEntry _unitEntry; 1376 final CacheEntry _unitEntry;
1371 1377
1372 final CompilationUnit _oldUnit; 1378 final CompilationUnit _oldUnit;
1373 CompilationUnitElement _unitElement; 1379 CompilationUnitElement _unitElement;
1374 1380
1375 int _updateOffset; 1381 int _updateOffset;
1376 int _updateDelta; 1382 int _updateDelta;
1377 int _updateEndOld; 1383 int _updateEndOld;
1378 int _updateEndNew; 1384 int _updateEndNew;
1379 1385
1380 LineInfo _newLineInfo; 1386 LineInfo _newLineInfo;
1381 List<AnalysisError> _newScanErrors = <AnalysisError>[]; 1387 List<AnalysisError> _newScanErrors = <AnalysisError>[];
1382 List<AnalysisError> _newParseErrors = <AnalysisError>[]; 1388 List<AnalysisError> _newParseErrors = <AnalysisError>[];
1383 1389
1384 PoorMansIncrementalResolver( 1390 PoorMansIncrementalResolver(
1385 this._typeProvider, 1391 this._typeProvider,
1386 this._unitSource, 1392 this._unitSource,
1393 this._cache,
1387 this._sourceEntry, 1394 this._sourceEntry,
1388 this._unitEntry, 1395 this._unitEntry,
1389 this._oldUnit, 1396 this._oldUnit,
1390 bool resolveApiChanges) { 1397 bool resolveApiChanges) {
1391 _resolveApiChanges = resolveApiChanges; 1398 _resolveApiChanges = resolveApiChanges;
1392 } 1399 }
1393 1400
1394 /** 1401 /**
1395 * Attempts to update [_oldUnit] to the state corresponding to [newCode]. 1402 * Attempts to update [_oldUnit] to the state corresponding to [newCode].
1396 * Returns `true` if success, or `false` otherwise. 1403 * Returns `true` if success, or `false` otherwise.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1437 bool success = _resolveCommentDoc(newUnit, firstPair); 1444 bool success = _resolveCommentDoc(newUnit, firstPair);
1438 logger.log('Documentation comment resolved: $success'); 1445 logger.log('Documentation comment resolved: $success');
1439 return success; 1446 return success;
1440 } 1447 }
1441 // A pure whitespace change. 1448 // A pure whitespace change.
1442 if (firstPair.kind == _TokenDifferenceKind.OFFSET) { 1449 if (firstPair.kind == _TokenDifferenceKind.OFFSET) {
1443 logger.log('Whitespace change.'); 1450 logger.log('Whitespace change.');
1444 _shiftTokens(firstPair.oldToken); 1451 _shiftTokens(firstPair.oldToken);
1445 { 1452 {
1446 IncrementalResolver incrementalResolver = new IncrementalResolver( 1453 IncrementalResolver incrementalResolver = new IncrementalResolver(
1454 _cache,
1447 _sourceEntry, 1455 _sourceEntry,
1448 _unitEntry, 1456 _unitEntry,
1449 _unitElement, 1457 _unitElement,
1450 _updateOffset, 1458 _updateOffset,
1451 _updateEndOld, 1459 _updateEndOld,
1452 _updateEndNew); 1460 _updateEndNew);
1453 incrementalResolver._updateCache(); 1461 incrementalResolver._updateCache();
1454 incrementalResolver._updateElementNameOffsets(); 1462 incrementalResolver._updateElementNameOffsets();
1455 incrementalResolver._shiftEntryErrors(); 1463 incrementalResolver._shiftEntryErrors();
1456 } 1464 }
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1563 if (oldBeginToken.previous.type == TokenType.EOF) { 1571 if (oldBeginToken.previous.type == TokenType.EOF) {
1564 _oldUnit.beginToken = newBeginToken; 1572 _oldUnit.beginToken = newBeginToken;
1565 } else { 1573 } else {
1566 oldBeginToken.previous.setNext(newBeginToken); 1574 oldBeginToken.previous.setNext(newBeginToken);
1567 } 1575 }
1568 newNode.endToken.setNext(oldNode.endToken.next); 1576 newNode.endToken.setNext(oldNode.endToken.next);
1569 _shiftTokens(oldNode.endToken.next); 1577 _shiftTokens(oldNode.endToken.next);
1570 } 1578 }
1571 // perform incremental resolution 1579 // perform incremental resolution
1572 IncrementalResolver incrementalResolver = new IncrementalResolver( 1580 IncrementalResolver incrementalResolver = new IncrementalResolver(
1581 _cache,
1573 _sourceEntry, 1582 _sourceEntry,
1574 _unitEntry, 1583 _unitEntry,
1575 _unitElement, 1584 _unitElement,
1576 _updateOffset, 1585 _updateOffset,
1577 _updateEndOld, 1586 _updateEndOld,
1578 _updateEndNew); 1587 _updateEndNew);
1579 bool success = incrementalResolver.resolve(newNode); 1588 bool success = incrementalResolver.resolve(newNode);
1580 // check if success 1589 // check if success
1581 if (!success) { 1590 if (!success) {
1582 logger.log('Failure: element model changed.'); 1591 logger.log('Failure: element model changed.');
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1641 logger.log('oldComment.beginToken: ${oldComment.beginToken}'); 1650 logger.log('oldComment.beginToken: ${oldComment.beginToken}');
1642 logger.log('newComment.beginToken: ${newComment.beginToken}'); 1651 logger.log('newComment.beginToken: ${newComment.beginToken}');
1643 _updateOffset = oldToken.offset - 1; 1652 _updateOffset = oldToken.offset - 1;
1644 // update token references 1653 // update token references
1645 _shiftTokens(firstPair.oldToken); 1654 _shiftTokens(firstPair.oldToken);
1646 _setPrecedingComments(oldToken, newComment.tokens.first); 1655 _setPrecedingComments(oldToken, newComment.tokens.first);
1647 // replace node 1656 // replace node
1648 NodeReplacer.replace(oldComment, newComment); 1657 NodeReplacer.replace(oldComment, newComment);
1649 // update elements 1658 // update elements
1650 IncrementalResolver incrementalResolver = new IncrementalResolver( 1659 IncrementalResolver incrementalResolver = new IncrementalResolver(
1660 _cache,
1651 _sourceEntry, 1661 _sourceEntry,
1652 _unitEntry, 1662 _unitEntry,
1653 _unitElement, 1663 _unitElement,
1654 _updateOffset, 1664 _updateOffset,
1655 _updateEndOld, 1665 _updateEndOld,
1656 _updateEndNew); 1666 _updateEndNew);
1657 incrementalResolver._updateCache(); 1667 incrementalResolver._updateCache();
1658 incrementalResolver._updateElementNameOffsets(); 1668 incrementalResolver._updateElementNameOffsets();
1659 incrementalResolver._shiftEntryErrors(); 1669 incrementalResolver._shiftEntryErrors();
1660 _updateEntry(); 1670 _updateEntry();
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
2029 } 2039 }
2030 } 2040 }
2031 2041
2032 /** 2042 /**
2033 * Instances of the class [_DeclarationMismatchException] represent an exception 2043 * Instances of the class [_DeclarationMismatchException] represent an exception
2034 * that is thrown when the element model defined by a given AST structure does 2044 * that is thrown when the element model defined by a given AST structure does
2035 * not match an existing element model. 2045 * not match an existing element model.
2036 */ 2046 */
2037 class _DeclarationMismatchException {} 2047 class _DeclarationMismatchException {}
2038 2048
2049 /**
2050 * Adjusts the location of each Element that moved.
2051 *
2052 * Since operator== and hashCode of an Element are based
2053 * on the element location, we also need to remove each
2054 * moved element from the cache to avoid a memory leak.
2055 */
2039 class _ElementOffsetUpdater extends GeneralizingElementVisitor { 2056 class _ElementOffsetUpdater extends GeneralizingElementVisitor {
2040 final int updateOffset; 2057 final int updateOffset;
2041 final int updateDelta; 2058 final int updateDelta;
2059 final AnalysisCache cache;
2042 2060
2043 _ElementOffsetUpdater(this.updateOffset, this.updateDelta); 2061 _ElementOffsetUpdater(this.updateOffset, this.updateDelta, this.cache);
2044 2062
2045 @override 2063 @override
2046 visitElement(Element element) { 2064 visitElement(Element element) {
2047 // name offset 2065 // name offset
2048 int nameOffset = element.nameOffset; 2066 int nameOffset = element.nameOffset;
2049 if (nameOffset > updateOffset) { 2067 if (nameOffset > updateOffset) {
2068 cache.remove(element);
Brian Wilkerson 2016/02/01 14:58:16 This causes us to loose all analysis information a
skybrian 2016/02/01 22:26:32 It's unfortunate, but I'm not sure it's a performa
Brian Wilkerson 2016/02/02 16:32:06 As long as we only remove elements when their hash
2050 (element as ElementImpl).nameOffset = nameOffset + updateDelta; 2069 (element as ElementImpl).nameOffset = nameOffset + updateDelta;
2051 } 2070 }
2052 // visible range 2071 // visible range
2053 if (element is LocalElement) { 2072 if (element is LocalElement) {
2054 SourceRange visibleRange = element.visibleRange; 2073 SourceRange visibleRange = element.visibleRange;
2055 if (visibleRange != null && visibleRange.offset > updateOffset) { 2074 if (visibleRange != null && visibleRange.offset > updateOffset) {
2056 int newOffset = visibleRange.offset + updateDelta; 2075 int newOffset = visibleRange.offset + updateDelta;
2057 int length = visibleRange.length; 2076 int length = visibleRange.length;
2058 if (element is FunctionElementImpl) { 2077 if (element is FunctionElementImpl) {
2078 cache.remove(element);
2059 element.setVisibleRange(newOffset, length); 2079 element.setVisibleRange(newOffset, length);
2060 } else if (element is LocalVariableElementImpl) { 2080 } else if (element is LocalVariableElementImpl) {
2081 cache.remove(element);
2061 element.setVisibleRange(newOffset, length); 2082 element.setVisibleRange(newOffset, length);
2062 } else if (element is ParameterElementImpl) { 2083 } else if (element is ParameterElementImpl) {
2084 cache.remove(element);
2063 element.setVisibleRange(newOffset, length); 2085 element.setVisibleRange(newOffset, length);
2064 } 2086 }
2065 } 2087 }
2066 } 2088 }
2067 super.visitElement(element); 2089 super.visitElement(element);
2068 } 2090 }
2069 } 2091 }
2070 2092
2071 class _ElementsGatherer extends GeneralizingElementVisitor { 2093 class _ElementsGatherer extends GeneralizingElementVisitor {
2072 final DeclarationMatcher matcher; 2094 final DeclarationMatcher matcher;
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
2138 @override 2160 @override
2139 String toString() => name; 2161 String toString() => name;
2140 } 2162 }
2141 2163
2142 class _TokenPair { 2164 class _TokenPair {
2143 final _TokenDifferenceKind kind; 2165 final _TokenDifferenceKind kind;
2144 final Token oldToken; 2166 final Token oldToken;
2145 final Token newToken; 2167 final Token newToken;
2146 _TokenPair(this.kind, this.oldToken, this.newToken); 2168 _TokenPair(this.kind, this.oldToken, this.newToken);
2147 } 2169 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698