mirror of
https://github.com/dart-lang/sdk
synced 2024-09-05 16:41:07 +00:00
Try to load the existing unlinked bundle by the content hash.
So that we don't create _File.forResolution() when we could use only the content hash and the existing unlinked bundle. This makes loading cached analysis results cheaper - no need to parse the unit. TBR R=brianwilkerson@google.com, paulberry@google.com BUG= Review URL: https://codereview.chromium.org/2450283003 .
This commit is contained in:
parent
bd594d453f
commit
6be23afcf2
|
@ -235,9 +235,8 @@ class AnalysisDriver {
|
||||||
bool analyzed = false;
|
bool analyzed = false;
|
||||||
for (String path in _priorityFiles) {
|
for (String path in _priorityFiles) {
|
||||||
if (_filesToAnalyze.remove(path)) {
|
if (_filesToAnalyze.remove(path)) {
|
||||||
_File file = _fileForPath(path);
|
|
||||||
AnalysisResult result =
|
AnalysisResult result =
|
||||||
_computeAnalysisResult(file, withUnit: true);
|
_computeAnalysisResult(path, withUnit: true);
|
||||||
yield result;
|
yield result;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -252,8 +251,7 @@ class AnalysisDriver {
|
||||||
// Analyze a general file.
|
// Analyze a general file.
|
||||||
if (_filesToAnalyze.isNotEmpty) {
|
if (_filesToAnalyze.isNotEmpty) {
|
||||||
String path = _removeFirst(_filesToAnalyze);
|
String path = _removeFirst(_filesToAnalyze);
|
||||||
_File file = _fileForPath(path);
|
AnalysisResult result = _computeAnalysisResult(path, withUnit: false);
|
||||||
AnalysisResult result = _computeAnalysisResult(file, withUnit: false);
|
|
||||||
yield result;
|
yield result;
|
||||||
// Repeat the processing loop.
|
// Repeat the processing loop.
|
||||||
_hasWork.notify();
|
_hasWork.notify();
|
||||||
|
@ -366,33 +364,38 @@ class AnalysisDriver {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Compute the [AnalysisResult] for the [file].
|
* Return the cached or newly computed analysis result of the file with the
|
||||||
|
* given [path].
|
||||||
*
|
*
|
||||||
* The result will have the fully resolved unit only if [withUnit] is `true`.
|
* The result will have the fully resolved unit and will always be newly
|
||||||
|
* compute only if [withUnit] is `true`.
|
||||||
*/
|
*/
|
||||||
AnalysisResult _computeAnalysisResult(_File file, {bool withUnit: false}) {
|
AnalysisResult _computeAnalysisResult(String path, {bool withUnit: false}) {
|
||||||
// If we don't need to the fully resolved unit, check for a cached result.
|
Source source = _sourceForPath(path);
|
||||||
|
|
||||||
|
// If we don't need the fully resolved unit, check for the cached result.
|
||||||
if (!withUnit) {
|
if (!withUnit) {
|
||||||
AnalysisResult result = _getCachedAnalysisResult(file);
|
_File file = new _File.forLinking(this, source);
|
||||||
|
// Prepare the key for the cached result.
|
||||||
|
String key = _getResolvedUnitKey(file);
|
||||||
|
if (key == null) {
|
||||||
|
_logger.run('Compute the dependency hash for $source', () {
|
||||||
|
_createLibraryContext(file);
|
||||||
|
key = _getResolvedUnitKey(file);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
// Check for the cached result.
|
||||||
|
AnalysisResult result = _getCachedAnalysisResult(file, key);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We need the fully resolved unit, or the result is not cached.
|
// We need the fully resolved unit, or the result is not cached.
|
||||||
return _logger.run('Compute analysis result for $file', () {
|
return _logger.run('Compute analysis result for $source', () {
|
||||||
_LibraryContext libraryContext = _createLibraryContext(file);
|
|
||||||
|
|
||||||
// We recomputed the dependency hash, and we might have a cached result.
|
|
||||||
if (!withUnit) {
|
|
||||||
AnalysisResult result = _getCachedAnalysisResult(file);
|
|
||||||
if (result != null) {
|
|
||||||
_logger.writeln('Return the cached analysis result.');
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Still no result, compute and store it.
|
// Still no result, compute and store it.
|
||||||
|
_File file = new _File.forResolution(this, source);
|
||||||
|
_LibraryContext libraryContext = _createLibraryContext(file);
|
||||||
AnalysisContext analysisContext = _createAnalysisContext(libraryContext);
|
AnalysisContext analysisContext = _createAnalysisContext(libraryContext);
|
||||||
try {
|
try {
|
||||||
analysisContext.setContents(file.source, file.content);
|
analysisContext.setContents(file.source, file.content);
|
||||||
|
@ -559,37 +562,24 @@ class AnalysisDriver {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the [_File] for the given [path] in [_sourceFactory].
|
* If we know the result [key] for the [file], try to load the analysis
|
||||||
|
* result from the cache. Return `null` if not found.
|
||||||
*/
|
*/
|
||||||
_File _fileForPath(String path) {
|
AnalysisResult _getCachedAnalysisResult(_File file, String key) {
|
||||||
Source fileSource = _resourceProvider.getFile(path).createSource();
|
List<int> bytes = _byteStore.get(key);
|
||||||
Uri uri = _sourceFactory.restoreUri(fileSource);
|
if (bytes != null) {
|
||||||
Source source = _resourceProvider.getFile(path).createSource(uri);
|
var unit = new AnalysisDriverResolvedUnit.fromBuffer(bytes);
|
||||||
return new _File.forResolution(this, source);
|
List<AnalysisError> errors = unit.errors
|
||||||
}
|
.map((error) => new AnalysisError.forValues(
|
||||||
|
file.source,
|
||||||
/**
|
error.offset,
|
||||||
* If we know the dependency signature for the [file], try to load the
|
error.length,
|
||||||
* analysis result from the cache. Return `null` if not found.
|
ErrorCode.byUniqueName(error.uniqueName),
|
||||||
*/
|
error.message,
|
||||||
AnalysisResult _getCachedAnalysisResult(_File file) {
|
error.correction))
|
||||||
String key = _getResolvedUnitKey(file);
|
.toList();
|
||||||
if (key != null) {
|
return new AnalysisResult(
|
||||||
List<int> bytes = _byteStore.get(key);
|
file.path, file.uri, null, file.contentHash, null, errors);
|
||||||
if (bytes != null) {
|
|
||||||
var unit = new AnalysisDriverResolvedUnit.fromBuffer(bytes);
|
|
||||||
List<AnalysisError> errors = unit.errors
|
|
||||||
.map((error) => new AnalysisError.forValues(
|
|
||||||
file.source,
|
|
||||||
error.offset,
|
|
||||||
error.length,
|
|
||||||
ErrorCode.byUniqueName(error.uniqueName),
|
|
||||||
error.message,
|
|
||||||
error.correction))
|
|
||||||
.toList();
|
|
||||||
return new AnalysisResult(
|
|
||||||
file.path, file.uri, null, file.contentHash, null, errors);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
@ -609,6 +599,15 @@ class AnalysisDriver {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the [Source] for the given [path] in [_sourceFactory].
|
||||||
|
*/
|
||||||
|
Source _sourceForPath(String path) {
|
||||||
|
Source fileSource = _resourceProvider.getFile(path).createSource();
|
||||||
|
Uri uri = _sourceFactory.restoreUri(fileSource);
|
||||||
|
return _resourceProvider.getFile(path).createSource(uri);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verify the API signature for the file with the given [path], and decide
|
* Verify the API signature for the file with the given [path], and decide
|
||||||
* which linked libraries should be invalidated, and files reanalyzed.
|
* which linked libraries should be invalidated, and files reanalyzed.
|
||||||
|
@ -620,7 +619,8 @@ class AnalysisDriver {
|
||||||
String oldSignature = _fileApiSignatureMap[path];
|
String oldSignature = _fileApiSignatureMap[path];
|
||||||
// Compute the new API signature.
|
// Compute the new API signature.
|
||||||
// _File.forResolution() also updates the content hash in the cache.
|
// _File.forResolution() also updates the content hash in the cache.
|
||||||
_File newFile = _fileForPath(path);
|
Source source = _sourceForPath(path);
|
||||||
|
_File newFile = new _File.forResolution(this, source);
|
||||||
String newSignature = newFile.unlinked.apiSignature;
|
String newSignature = newFile.unlinked.apiSignature;
|
||||||
// If the old API signature is not null, then the file was used to
|
// If the old API signature is not null, then the file was used to
|
||||||
// compute at least one dependency signature. If the new API signature
|
// compute at least one dependency signature. If the new API signature
|
||||||
|
@ -816,22 +816,10 @@ class _File {
|
||||||
*/
|
*/
|
||||||
final CompilationUnit unit;
|
final CompilationUnit unit;
|
||||||
|
|
||||||
factory _File.forLinking(AnalysisDriver driver, Source source) {
|
/**
|
||||||
// If we have enough cached information, use it.
|
* Return the file with consistent [content] and [contentHash].
|
||||||
String contentHash = driver._fileContentHashMap[source.fullName];
|
*/
|
||||||
if (contentHash != null) {
|
factory _File.forContent(AnalysisDriver driver, Source source) {
|
||||||
String key = '$contentHash.unlinked';
|
|
||||||
List<int> bytes = driver._byteStore.get(key);
|
|
||||||
if (bytes != null) {
|
|
||||||
PackageBundle unlinked = new PackageBundle.fromBuffer(bytes);
|
|
||||||
return new _File._(driver, source, null, contentHash, unlinked, null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Otherwise, read the source, parse and build a new unlinked bundle.
|
|
||||||
return new _File.forResolution(driver, source);
|
|
||||||
}
|
|
||||||
|
|
||||||
factory _File.forResolution(AnalysisDriver driver, Source source) {
|
|
||||||
String path = source.fullName;
|
String path = source.fullName;
|
||||||
// Read the content.
|
// Read the content.
|
||||||
String content;
|
String content;
|
||||||
|
@ -853,6 +841,37 @@ class _File {
|
||||||
List<int> hashBytes = md5.convert(textBytes).bytes;
|
List<int> hashBytes = md5.convert(textBytes).bytes;
|
||||||
String contentHash = hex.encode(hashBytes);
|
String contentHash = hex.encode(hashBytes);
|
||||||
driver._fileContentHashMap[path] = contentHash;
|
driver._fileContentHashMap[path] = contentHash;
|
||||||
|
// Return information about the file content.
|
||||||
|
return new _File._(driver, source, content, contentHash, null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory _File.forLinking(AnalysisDriver driver, Source source) {
|
||||||
|
String path = source.fullName;
|
||||||
|
String contentHash = driver._fileContentHashMap[path];
|
||||||
|
// If we don't have the file content hash, compute it.
|
||||||
|
if (contentHash == null) {
|
||||||
|
_File file = new _File.forContent(driver, source);
|
||||||
|
contentHash = file.contentHash;
|
||||||
|
}
|
||||||
|
// If we have the cached unlinked bundle, use it.
|
||||||
|
{
|
||||||
|
String key = '$contentHash.unlinked';
|
||||||
|
List<int> bytes = driver._byteStore.get(key);
|
||||||
|
if (bytes != null) {
|
||||||
|
PackageBundle unlinked = new PackageBundle.fromBuffer(bytes);
|
||||||
|
driver._fileApiSignatureMap[path] = unlinked.apiSignature;
|
||||||
|
return new _File._(driver, source, null, contentHash, unlinked, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Otherwise, read the source, parse and build a new unlinked bundle.
|
||||||
|
return new _File.forResolution(driver, source);
|
||||||
|
}
|
||||||
|
|
||||||
|
factory _File.forResolution(AnalysisDriver driver, Source source) {
|
||||||
|
_File file = new _File.forContent(driver, source);
|
||||||
|
String path = file.path;
|
||||||
|
String content = file.content;
|
||||||
|
String contentHash = file.contentHash;
|
||||||
// Parse the unit.
|
// Parse the unit.
|
||||||
CompilationUnit unit = _parse(driver, source, content);
|
CompilationUnit unit = _parse(driver, source, content);
|
||||||
// Prepare the unlinked bundle.
|
// Prepare the unlinked bundle.
|
||||||
|
@ -873,7 +892,7 @@ class _File {
|
||||||
unlinked = new PackageBundle.fromBuffer(bytes);
|
unlinked = new PackageBundle.fromBuffer(bytes);
|
||||||
driver._fileApiSignatureMap[path] = unlinked.apiSignature;
|
driver._fileApiSignatureMap[path] = unlinked.apiSignature;
|
||||||
}
|
}
|
||||||
// Update the current file state.
|
// Return the full file.
|
||||||
return new _File._(driver, source, content, contentHash, unlinked, unit);
|
return new _File._(driver, source, content, contentHash, unlinked, unit);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue