mirror of
https://github.com/dart-lang/sdk
synced 2024-09-18 21:11:19 +00:00
Implement GC for FileState(s).
Also fix for invoking watch(). R=ahe@google.com, paulberry@google.com, sigmund@google.com BUG= Review-Url: https://codereview.chromium.org/2929363002 .
This commit is contained in:
parent
10a5bfaa08
commit
5e8ceb60ab
|
@ -54,6 +54,10 @@ class FileState {
|
|||
Set<FileState> _directReferencedFiles = new Set<FileState>();
|
||||
List<FileState> _directReferencedLibraries = <FileState>[];
|
||||
|
||||
/// This flag is set to `true` during the mark phase of garbage collection
|
||||
/// and set back to `false` for survived instances.
|
||||
bool _gcMarked = false;
|
||||
|
||||
FileState._(this._fsState, this.uri, this.fileUri);
|
||||
|
||||
/// The MD5 signature of the file API as a byte array.
|
||||
|
@ -309,6 +313,35 @@ class FileSystemState {
|
|||
/// The `file:` URI of all files currently tracked by this instance.
|
||||
Iterable<Uri> get fileUris => _fileUriToFile.keys;
|
||||
|
||||
/// Perform mark and sweep garbage collection of [FileState]s.
|
||||
void gc(Uri entryPoint) {
|
||||
void mark(FileState file) {
|
||||
if (!file._gcMarked) {
|
||||
file._gcMarked = true;
|
||||
file._directReferencedFiles.forEach(mark);
|
||||
}
|
||||
}
|
||||
|
||||
var file = _uriToFile[entryPoint];
|
||||
if (file == null) return;
|
||||
|
||||
mark(file);
|
||||
|
||||
var urisToRemove = new Set<Uri>();
|
||||
var fileUrisToRemove = new Set<Uri>();
|
||||
for (var file in _uriToFile.values) {
|
||||
if (file._gcMarked) {
|
||||
file._gcMarked = false;
|
||||
} else {
|
||||
urisToRemove.add(file.uri);
|
||||
fileUrisToRemove.add(file.fileUri);
|
||||
}
|
||||
}
|
||||
|
||||
urisToRemove.forEach(_uriToFile.remove);
|
||||
fileUrisToRemove.forEach(_fileUriToFile.remove);
|
||||
}
|
||||
|
||||
/// Return the [FileState] for the given [absoluteUri], or `null` if the
|
||||
/// [absoluteUri] cannot be resolved into a file URI.
|
||||
///
|
||||
|
|
|
@ -79,8 +79,16 @@ class IncrementalKernelGeneratorImpl implements IncrementalKernelGenerator {
|
|||
: _logger = _options.logger,
|
||||
_byteStore = _options.byteStore {
|
||||
_computeSalt();
|
||||
|
||||
Future<Null> onFileAdded(Uri uri) {
|
||||
if (watch != null) {
|
||||
return watch(uri, true);
|
||||
}
|
||||
return new Future.value();
|
||||
}
|
||||
|
||||
_fsState = new FileSystemState(
|
||||
_options.fileSystem, _uriTranslator, _salt, (uri) => watch(uri, true));
|
||||
_options.fileSystem, _uriTranslator, _salt, onFileAdded);
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -304,6 +312,9 @@ class IncrementalKernelGeneratorImpl implements IncrementalKernelGenerator {
|
|||
await file.refresh();
|
||||
}
|
||||
}
|
||||
|
||||
// The file graph might have changed, perform GC.
|
||||
_fsState.gc(_entryPoint);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -141,6 +141,51 @@ baz() => 44;
|
|||
''');
|
||||
}
|
||||
|
||||
test_gc() async {
|
||||
var a = writeFile('/a.dart', '');
|
||||
var b = writeFile('/b.dart', '');
|
||||
var c = writeFile('/c.dart', 'import "a.dart";');
|
||||
var d = writeFile('/d.dart', 'import "b.dart";');
|
||||
var e = writeFile(
|
||||
'/e.dart',
|
||||
r'''
|
||||
import "c.dart";
|
||||
import "d.dart";
|
||||
''');
|
||||
|
||||
var eFile = await fsState.getFile(e);
|
||||
|
||||
// The root and four files.
|
||||
expect(fsState.fileUris, contains(e));
|
||||
expect(fsState.fileUris, contains(a));
|
||||
expect(fsState.fileUris, contains(b));
|
||||
expect(fsState.fileUris, contains(c));
|
||||
expect(fsState.fileUris, contains(d));
|
||||
|
||||
// No changes after GC.
|
||||
fsState.gc(e);
|
||||
expect(fsState.fileUris, contains(e));
|
||||
expect(fsState.fileUris, contains(a));
|
||||
expect(fsState.fileUris, contains(b));
|
||||
expect(fsState.fileUris, contains(c));
|
||||
expect(fsState.fileUris, contains(d));
|
||||
|
||||
// Update e.dart so that it does not reference c.dart anymore.
|
||||
// Then GC removes both c.dart and a.dart it references.
|
||||
writeFile(
|
||||
'/e.dart',
|
||||
r'''
|
||||
import "d.dart";
|
||||
''');
|
||||
await eFile.refresh();
|
||||
fsState.gc(e);
|
||||
expect(fsState.fileUris, contains(e));
|
||||
expect(fsState.fileUris, isNot(contains(a)));
|
||||
expect(fsState.fileUris, contains(b));
|
||||
expect(fsState.fileUris, isNot(contains(c)));
|
||||
expect(fsState.fileUris, contains(d));
|
||||
}
|
||||
|
||||
test_getFile() async {
|
||||
var a = writeFile('/a.dart', '');
|
||||
var b = writeFile('/b.dart', '');
|
||||
|
|
Loading…
Reference in a new issue