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

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: simplify and improve tests 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 935 matching lines...) Expand 10 before | Expand all | Expand 10 after
946 */ 946 */
947 class IncrementalResolver { 947 class IncrementalResolver {
948 /** 948 /**
949 * The element of the compilation unit being resolved. 949 * The element of the compilation unit being resolved.
950 */ 950 */
951 final CompilationUnitElementImpl _definingUnit; 951 final CompilationUnitElementImpl _definingUnit;
952 952
953 /** 953 /**
954 * The context the compilation unit being resolved in. 954 * The context the compilation unit being resolved in.
955 */ 955 */
956 AnalysisContext _context; 956 final AnalysisContext _context;
957 957
958 /** 958 /**
959 * The object used to access the types from the core library. 959 * The object used to access the types from the core library.
960 */ 960 */
961 TypeProvider _typeProvider; 961 final TypeProvider _typeProvider;
962 962
963 /** 963 /**
964 * The type system primitives. 964 * The type system primitives.
965 */ 965 */
966 TypeSystem _typeSystem; 966 final TypeSystem _typeSystem;
967 967
968 /** 968 /**
969 * The element for the library containing the compilation unit being resolved. 969 * The element for the library containing the compilation unit being resolved.
970 */ 970 */
971 LibraryElementImpl _definingLibrary; 971 final LibraryElementImpl _definingLibrary;
972
973 final AnalysisCache _cache;
972 974
973 /** 975 /**
974 * The [CacheEntry] corresponding to the source being resolved. 976 * The [CacheEntry] corresponding to the source being resolved.
975 */ 977 */
976 CacheEntry newSourceEntry; 978 final CacheEntry newSourceEntry;
977 979
978 /** 980 /**
979 * The [CacheEntry] corresponding to the [LibrarySpecificUnit] being resolved. 981 * The [CacheEntry] corresponding to the [LibrarySpecificUnit] being resolved.
980 */ 982 */
981 CacheEntry newUnitEntry; 983 final CacheEntry newUnitEntry;
982 984
983 /** 985 /**
984 * The source representing the compilation unit being visited. 986 * The source representing the compilation unit being visited.
985 */ 987 */
986 Source _source; 988 final Source _source;
987 989
988 /** 990 /**
989 * The source representing the library of the compilation unit being visited. 991 * The source representing the library of the compilation unit being visited.
990 */ 992 */
991 Source _librarySource; 993 final Source _librarySource;
992 994
993 /** 995 /**
994 * The offset of the changed contents. 996 * The offset of the changed contents.
995 */ 997 */
996 final int _updateOffset; 998 final int _updateOffset;
997 999
998 /** 1000 /**
999 * The end of the changed contents in the old unit. 1001 * The end of the changed contents in the old unit.
1000 */ 1002 */
1001 final int _updateEndOld; 1003 final int _updateEndOld;
1002 1004
1003 /** 1005 /**
1004 * The end of the changed contents in the new unit. 1006 * The end of the changed contents in the new unit.
1005 */ 1007 */
1006 final int _updateEndNew; 1008 final int _updateEndNew;
1007 1009
1008 /** 1010 /**
1009 * The delta between [_updateEndNew] and [_updateEndOld]. 1011 * The delta between [_updateEndNew] and [_updateEndOld].
1010 */ 1012 */
1011 int _updateDelta; 1013 final int _updateDelta;
1012 1014
1013 /** 1015 /**
1014 * The set of [AnalysisError]s that have been already shifted. 1016 * The set of [AnalysisError]s that have been already shifted.
1015 */ 1017 */
1016 Set<AnalysisError> _alreadyShiftedErrors = new HashSet.identity(); 1018 final Set<AnalysisError> _alreadyShiftedErrors = new HashSet.identity();
1017 1019
1018 RecordingErrorListener errorListener = new RecordingErrorListener(); 1020 final RecordingErrorListener errorListener = new RecordingErrorListener();
1019 ResolutionContext _resolutionContext; 1021 ResolutionContext _resolutionContext;
1020 1022
1021 List<AnalysisError> _resolveErrors = AnalysisError.NO_ERRORS; 1023 List<AnalysisError> _resolveErrors = AnalysisError.NO_ERRORS;
1022 List<AnalysisError> _verifyErrors = AnalysisError.NO_ERRORS; 1024 List<AnalysisError> _verifyErrors = AnalysisError.NO_ERRORS;
1023 1025
1024 /** 1026 /**
1025 * Initialize a newly created incremental resolver to resolve a node in the 1027 * Initialize a newly created incremental resolver to resolve a node in the
1026 * given source in the given library. 1028 * given source in the given library.
1027 */ 1029 */
1028 IncrementalResolver( 1030 IncrementalResolver(
1031 this._cache,
1029 this.newSourceEntry, 1032 this.newSourceEntry,
1030 this.newUnitEntry, 1033 this.newUnitEntry,
1031 this._definingUnit, 1034 CompilationUnitElementImpl definingUnit,
1032 this._updateOffset, 1035 this._updateOffset,
1033 this._updateEndOld, 1036 int updateEndOld,
1034 this._updateEndNew) { 1037 int updateEndNew)
1035 _updateDelta = _updateEndNew - _updateEndOld; 1038 : _definingUnit = definingUnit,
1036 _definingLibrary = _definingUnit.library; 1039 _context = definingUnit.context,
1037 _librarySource = _definingLibrary.source; 1040 _typeProvider = definingUnit.context.typeProvider,
1038 _source = _definingUnit.source; 1041 _typeSystem = definingUnit.context.typeSystem,
1039 _context = _definingUnit.context; 1042 _definingLibrary = definingUnit.library,
1040 _typeProvider = _context.typeProvider; 1043 _source = definingUnit.source,
1041 _typeSystem = _context.typeSystem; 1044 _librarySource = definingUnit.library.source,
1042 } 1045 _updateEndOld = updateEndOld,
1046 _updateEndNew = updateEndNew,
1047 _updateDelta = updateEndNew - updateEndOld;
1043 1048
1044 /** 1049 /**
1045 * Resolve [node], reporting any errors or warnings to the given listener. 1050 * Resolve [node], reporting any errors or warnings to the given listener.
1046 * 1051 *
1047 * [node] - the root of the AST structure to be resolved. 1052 * [node] - the root of the AST structure to be resolved.
1048 * 1053 *
1049 * Returns `true` if resolution was successful. 1054 * Returns `true` if resolution was successful.
1050 */ 1055 */
1051 bool resolve(AstNode node) { 1056 bool resolve(AstNode node) {
1052 logger.enter('resolve: $_definingUnit'); 1057 logger.enter('resolve: $_definingUnit');
(...skipping 220 matching lines...) Expand 10 before | Expand all | Expand 10 after
1273 _updateEndOld, _updateEndNew, _updateDelta)); 1278 _updateEndOld, _updateEndNew, _updateDelta));
1274 } finally { 1279 } finally {
1275 timer.stop('invalidate cache with delta'); 1280 timer.stop('invalidate cache with delta');
1276 } 1281 }
1277 } 1282 }
1278 } 1283 }
1279 1284
1280 void _updateElementNameOffsets() { 1285 void _updateElementNameOffsets() {
1281 LoggingTimer timer = logger.startTimer(); 1286 LoggingTimer timer = logger.startTimer();
1282 try { 1287 try {
1283 _definingUnit 1288 _definingUnit.accept(
1284 .accept(new _ElementOffsetUpdater(_updateOffset, _updateDelta)); 1289 new _ElementOffsetUpdater(_updateOffset, _updateDelta, _cache));
1285 _definingUnit.afterIncrementalResolution(); 1290 _definingUnit.afterIncrementalResolution();
1286 } finally { 1291 } finally {
1287 timer.stop('update element offsets'); 1292 timer.stop('update element offsets');
1288 } 1293 }
1289 } 1294 }
1290 1295
1291 void _updateEntry() { 1296 void _updateEntry() {
1292 _updateErrors_NEW(RESOLVE_TYPE_NAMES_ERRORS, []); 1297 _updateErrors_NEW(RESOLVE_TYPE_NAMES_ERRORS, []);
1293 _updateErrors_NEW(RESOLVE_UNIT_ERRORS, _resolveErrors); 1298 _updateErrors_NEW(RESOLVE_UNIT_ERRORS, _resolveErrors);
1294 _updateErrors_NEW(VARIABLE_REFERENCE_ERRORS, []); 1299 _updateErrors_NEW(VARIABLE_REFERENCE_ERRORS, []);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1352 _verifyErrors = errorListener.getErrorsForSource(_source); 1357 _verifyErrors = errorListener.getErrorsForSource(_source);
1353 } finally { 1358 } finally {
1354 timer.stop('verify'); 1359 timer.stop('verify');
1355 } 1360 }
1356 } 1361 }
1357 } 1362 }
1358 1363
1359 class PoorMansIncrementalResolver { 1364 class PoorMansIncrementalResolver {
1360 final TypeProvider _typeProvider; 1365 final TypeProvider _typeProvider;
1361 final Source _unitSource; 1366 final Source _unitSource;
1367 final AnalysisCache _cache;
1362 1368
1363 /** 1369 /**
1364 * The [CacheEntry] corresponding to the source being resolved. 1370 * The [CacheEntry] corresponding to the source being resolved.
1365 */ 1371 */
1366 CacheEntry _sourceEntry; 1372 final CacheEntry _sourceEntry;
1367 1373
1368 /** 1374 /**
1369 * The [CacheEntry] corresponding to the [LibrarySpecificUnit] being resolved. 1375 * The [CacheEntry] corresponding to the [LibrarySpecificUnit] being resolved.
1370 */ 1376 */
1371 CacheEntry _unitEntry; 1377 final CacheEntry _unitEntry;
1372 1378
1373 final CompilationUnit _oldUnit; 1379 final CompilationUnit _oldUnit;
1374 CompilationUnitElement _unitElement; 1380 CompilationUnitElement _unitElement;
1375 1381
1376 int _updateOffset; 1382 int _updateOffset;
1377 int _updateDelta; 1383 int _updateDelta;
1378 int _updateEndOld; 1384 int _updateEndOld;
1379 int _updateEndNew; 1385 int _updateEndNew;
1380 1386
1381 LineInfo _newLineInfo; 1387 LineInfo _newLineInfo;
1382 List<AnalysisError> _newScanErrors = <AnalysisError>[]; 1388 List<AnalysisError> _newScanErrors = <AnalysisError>[];
1383 List<AnalysisError> _newParseErrors = <AnalysisError>[]; 1389 List<AnalysisError> _newParseErrors = <AnalysisError>[];
1384 1390
1385 PoorMansIncrementalResolver( 1391 PoorMansIncrementalResolver(
1386 this._typeProvider, 1392 this._typeProvider,
1387 this._unitSource, 1393 this._unitSource,
1394 this._cache,
1388 this._sourceEntry, 1395 this._sourceEntry,
1389 this._unitEntry, 1396 this._unitEntry,
1390 this._oldUnit, 1397 this._oldUnit,
1391 bool resolveApiChanges) { 1398 bool resolveApiChanges) {
1392 _resolveApiChanges = resolveApiChanges; 1399 _resolveApiChanges = resolveApiChanges;
1393 } 1400 }
1394 1401
1395 /** 1402 /**
1396 * Attempts to update [_oldUnit] to the state corresponding to [newCode]. 1403 * Attempts to update [_oldUnit] to the state corresponding to [newCode].
1397 * Returns `true` if success, or `false` otherwise. 1404 * Returns `true` if success, or `false` otherwise.
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
1438 bool success = _resolveCommentDoc(newUnit, firstPair); 1445 bool success = _resolveCommentDoc(newUnit, firstPair);
1439 logger.log('Documentation comment resolved: $success'); 1446 logger.log('Documentation comment resolved: $success');
1440 return success; 1447 return success;
1441 } 1448 }
1442 // A pure whitespace change. 1449 // A pure whitespace change.
1443 if (firstPair.kind == _TokenDifferenceKind.OFFSET) { 1450 if (firstPair.kind == _TokenDifferenceKind.OFFSET) {
1444 logger.log('Whitespace change.'); 1451 logger.log('Whitespace change.');
1445 _shiftTokens(firstPair.oldToken); 1452 _shiftTokens(firstPair.oldToken);
1446 { 1453 {
1447 IncrementalResolver incrementalResolver = new IncrementalResolver( 1454 IncrementalResolver incrementalResolver = new IncrementalResolver(
1455 _cache,
1448 _sourceEntry, 1456 _sourceEntry,
1449 _unitEntry, 1457 _unitEntry,
1450 _unitElement, 1458 _unitElement,
1451 _updateOffset, 1459 _updateOffset,
1452 _updateEndOld, 1460 _updateEndOld,
1453 _updateEndNew); 1461 _updateEndNew);
1454 incrementalResolver._updateCache(); 1462 incrementalResolver._updateCache();
1455 incrementalResolver._updateElementNameOffsets(); 1463 incrementalResolver._updateElementNameOffsets();
1456 incrementalResolver._shiftEntryErrors(); 1464 incrementalResolver._shiftEntryErrors();
1457 } 1465 }
(...skipping 106 matching lines...) Expand 10 before | Expand all | Expand 10 after
1564 if (oldBeginToken.previous.type == TokenType.EOF) { 1572 if (oldBeginToken.previous.type == TokenType.EOF) {
1565 _oldUnit.beginToken = newBeginToken; 1573 _oldUnit.beginToken = newBeginToken;
1566 } else { 1574 } else {
1567 oldBeginToken.previous.setNext(newBeginToken); 1575 oldBeginToken.previous.setNext(newBeginToken);
1568 } 1576 }
1569 newNode.endToken.setNext(oldNode.endToken.next); 1577 newNode.endToken.setNext(oldNode.endToken.next);
1570 _shiftTokens(oldNode.endToken.next); 1578 _shiftTokens(oldNode.endToken.next);
1571 } 1579 }
1572 // perform incremental resolution 1580 // perform incremental resolution
1573 IncrementalResolver incrementalResolver = new IncrementalResolver( 1581 IncrementalResolver incrementalResolver = new IncrementalResolver(
1582 _cache,
1574 _sourceEntry, 1583 _sourceEntry,
1575 _unitEntry, 1584 _unitEntry,
1576 _unitElement, 1585 _unitElement,
1577 _updateOffset, 1586 _updateOffset,
1578 _updateEndOld, 1587 _updateEndOld,
1579 _updateEndNew); 1588 _updateEndNew);
1580 bool success = incrementalResolver.resolve(newNode); 1589 bool success = incrementalResolver.resolve(newNode);
1581 // check if success 1590 // check if success
1582 if (!success) { 1591 if (!success) {
1583 logger.log('Failure: element model changed.'); 1592 logger.log('Failure: element model changed.');
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after
1642 logger.log('oldComment.beginToken: ${oldComment.beginToken}'); 1651 logger.log('oldComment.beginToken: ${oldComment.beginToken}');
1643 logger.log('newComment.beginToken: ${newComment.beginToken}'); 1652 logger.log('newComment.beginToken: ${newComment.beginToken}');
1644 _updateOffset = oldToken.offset - 1; 1653 _updateOffset = oldToken.offset - 1;
1645 // update token references 1654 // update token references
1646 _shiftTokens(firstPair.oldToken); 1655 _shiftTokens(firstPair.oldToken);
1647 _setPrecedingComments(oldToken, newComment.tokens.first); 1656 _setPrecedingComments(oldToken, newComment.tokens.first);
1648 // replace node 1657 // replace node
1649 NodeReplacer.replace(oldComment, newComment); 1658 NodeReplacer.replace(oldComment, newComment);
1650 // update elements 1659 // update elements
1651 IncrementalResolver incrementalResolver = new IncrementalResolver( 1660 IncrementalResolver incrementalResolver = new IncrementalResolver(
1661 _cache,
1652 _sourceEntry, 1662 _sourceEntry,
1653 _unitEntry, 1663 _unitEntry,
1654 _unitElement, 1664 _unitElement,
1655 _updateOffset, 1665 _updateOffset,
1656 _updateEndOld, 1666 _updateEndOld,
1657 _updateEndNew); 1667 _updateEndNew);
1658 incrementalResolver._updateCache(); 1668 incrementalResolver._updateCache();
1659 incrementalResolver._updateElementNameOffsets(); 1669 incrementalResolver._updateElementNameOffsets();
1660 incrementalResolver._shiftEntryErrors(); 1670 incrementalResolver._shiftEntryErrors();
1661 _updateEntry(); 1671 _updateEntry();
(...skipping 368 matching lines...) Expand 10 before | Expand all | Expand 10 after
2030 } 2040 }
2031 } 2041 }
2032 2042
2033 /** 2043 /**
2034 * Instances of the class [_DeclarationMismatchException] represent an exception 2044 * Instances of the class [_DeclarationMismatchException] represent an exception
2035 * that is thrown when the element model defined by a given AST structure does 2045 * that is thrown when the element model defined by a given AST structure does
2036 * not match an existing element model. 2046 * not match an existing element model.
2037 */ 2047 */
2038 class _DeclarationMismatchException {} 2048 class _DeclarationMismatchException {}
2039 2049
2050 /**
2051 * Adjusts the location of each Element that moved.
2052 *
2053 * Since operator== and hashCode of an Element are based
2054 * on the element location, we also need to remove each
2055 * moved element from the cache to avoid a memory leak.
2056 */
2040 class _ElementOffsetUpdater extends GeneralizingElementVisitor { 2057 class _ElementOffsetUpdater extends GeneralizingElementVisitor {
2041 final int updateOffset; 2058 final int updateOffset;
2042 final int updateDelta; 2059 final int updateDelta;
2060 final AnalysisCache cache;
2043 2061
2044 _ElementOffsetUpdater(this.updateOffset, this.updateDelta); 2062 _ElementOffsetUpdater(this.updateOffset, this.updateDelta, this.cache);
2045 2063
2046 @override 2064 @override
2047 visitElement(Element element) { 2065 visitElement(Element element) {
2048 // name offset 2066 // name offset
2049 int nameOffset = element.nameOffset; 2067 int nameOffset = element.nameOffset;
2050 if (nameOffset > updateOffset) { 2068 if (nameOffset > updateOffset) {
2069 cache.remove(element);
2051 (element as ElementImpl).nameOffset = nameOffset + updateDelta; 2070 (element as ElementImpl).nameOffset = nameOffset + updateDelta;
2052 } 2071 }
2053 // visible range 2072 // visible range
2054 if (element is LocalElement) { 2073 if (element is LocalElement) {
2055 SourceRange visibleRange = element.visibleRange; 2074 SourceRange visibleRange = element.visibleRange;
2056 if (visibleRange != null && visibleRange.offset > updateOffset) { 2075 if (visibleRange != null && visibleRange.offset > updateOffset) {
2057 int newOffset = visibleRange.offset + updateDelta; 2076 int newOffset = visibleRange.offset + updateDelta;
2058 int length = visibleRange.length; 2077 int length = visibleRange.length;
2059 if (element is FunctionElementImpl) { 2078 if (element is FunctionElementImpl) {
2060 element.setVisibleRange(newOffset, length); 2079 element.setVisibleRange(newOffset, length);
(...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after
2139 @override 2158 @override
2140 String toString() => name; 2159 String toString() => name;
2141 } 2160 }
2142 2161
2143 class _TokenPair { 2162 class _TokenPair {
2144 final _TokenDifferenceKind kind; 2163 final _TokenDifferenceKind kind;
2145 final Token oldToken; 2164 final Token oldToken;
2146 final Token newToken; 2165 final Token newToken;
2147 _TokenPair(this.kind, this.oldToken, this.newToken); 2166 _TokenPair(this.kind, this.oldToken, this.newToken);
2148 } 2167 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698