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

Unified Diff: pkg/analyzer/lib/src/summary/bazel_summary.dart

Issue 2386743002: Cache linked bundles for Bazel packages in files.. (Closed)
Patch Set: Created 4 years, 3 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | pkg/analyzer/test/src/summary/bazel_summary_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/analyzer/lib/src/summary/bazel_summary.dart
diff --git a/pkg/analyzer/lib/src/summary/bazel_summary.dart b/pkg/analyzer/lib/src/summary/bazel_summary.dart
index 60a132077929311f88955ce13ba2892d1091d6f6..e3f4eee9b9ffe183db16e2d439a3d49926b0a10b 100644
--- a/pkg/analyzer/lib/src/summary/bazel_summary.dart
+++ b/pkg/analyzer/lib/src/summary/bazel_summary.dart
@@ -8,6 +8,7 @@ import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/source.dart';
import 'package:analyzer/src/generated/utilities_collection.dart';
+import 'package:analyzer/src/summary/api_signature.dart';
import 'package:analyzer/src/summary/format.dart';
import 'package:analyzer/src/summary/idl.dart';
import 'package:analyzer/src/summary/link.dart';
@@ -98,11 +99,24 @@ class Package {
*/
class SummaryProvider {
final ResourceProvider provider;
+ final String tempFileName;
final GetOutputFolder getOutputFolder;
+ final Folder linkedCacheFolder;
final AnalysisContext context;
final PackageBundle sdkBundle;
/**
+ * If `true` (by default), then linking new bundles is allowed.
+ * Otherwise only using existing cached bundles can be used.
+ */
+ final bool allowLinking;
+
+ /**
+ * See [PackageBundleAssembler.currentMajorVersion].
+ */
+ final int majorVersion;
+
+ /**
* Mapping from bundle paths to corresponding [Package]s. The packages in
* the map were consistent with their constituent sources at the moment when
* they were put into the map.
@@ -114,7 +128,16 @@ class SummaryProvider {
*/
final Map<Uri, _LinkNode> uriToNodeMap = {};
- SummaryProvider(this.provider, this.getOutputFolder, AnalysisContext context)
+ SummaryProvider(
+ this.provider,
+ this.tempFileName,
+ this.getOutputFolder,
+ this.linkedCacheFolder,
+ AnalysisContext context,
+ {@visibleForTesting
+ this.allowLinking: true,
+ @visibleForTesting
+ this.majorVersion: PackageBundleAssembler.currentMajorVersion})
: context = context,
sdkBundle = context.sourceFactory.dartSdk?.getLinkedBundle();
@@ -147,7 +170,15 @@ class SummaryProvider {
return null;
}
- _link(nodes);
+ // Read existing cached linked bundles.
+ for (_LinkNode node in nodes) {
+ _readLinked(node);
+ }
+
+ // Link new packages, if allowed.
+ if (allowLinking) {
+ _link(nodes);
+ }
// Create successfully linked packages.
return nodes
@@ -187,6 +218,17 @@ class SummaryProvider {
}
/**
+ * Return the name of the file for a linked bundle, in strong or spec mode.
+ */
+ String _getLinkedName(String hash) {
+ if (context.analysisOptions.strongMode) {
+ return 'linked_$hash.ds';
+ } else {
+ return 'linked_spec_$hash.ds';
+ }
+ }
+
+ /**
* Return the node for the given [uri], or `null` if there is no unlinked
* bundle that contains [uri].
*/
@@ -297,6 +339,27 @@ class SummaryProvider {
});
List<int> bytes = assembler.assemble().toBuffer();
node.package._linked = new PackageBundle.fromBuffer(bytes);
+ _writeLinked(node, bytes);
+ }
+ }
+ }
+
+ /**
+ * Attempt to read the linked bundle that corresponds to the given [node]
+ * with all its transitive dependencies.
+ */
+ void _readLinked(_LinkNode node) {
+ if (!node.isReady && node.linkedHash != null) {
+ String fileName = _getLinkedName(node.linkedHash);
+ File file = linkedCacheFolder.getChildAssumingFile(fileName);
+ // Try to read from the file system.
+ if (file.exists) {
+ try {
+ List<int> bytes = file.readAsBytesSync();
+ node.package._linked = new PackageBundle.fromBuffer(bytes);
+ } on FileSystemException {
+ // Ignore file system exceptions.
+ }
}
}
}
@@ -310,6 +373,10 @@ class SummaryProvider {
try {
List<int> bytes = file.readAsBytesSync();
PackageBundle bundle = new PackageBundle.fromBuffer(bytes);
+ // Check the major version.
+ if (bundle.majorVersion != majorVersion) {
+ return null;
+ }
// Check for consistency, and fail if it's not.
if (!_isUnlinkedBundleConsistent(bundle)) {
return null;
@@ -319,6 +386,30 @@ class SummaryProvider {
} on FileSystemException {}
return null;
}
+
+ /**
+ * Atomically write the given [bytes] into the file in the [folder].
+ */
+ void _writeAtomic(Folder folder, String fileName, List<int> bytes) {
+ String filePath = folder.getChildAssumingFile(fileName).path;
+ File tempFile = folder.getChildAssumingFile(tempFileName);
+ tempFile.writeAsBytesSync(bytes);
+ tempFile.renameSync(filePath);
+ }
+
+ /**
+ * If a new linked bundle was linked for the given [node], write the bundle
+ * into the memory cache and the file system.
+ */
+ void _writeLinked(_LinkNode node, List<int> bytes) {
+ String hash = node.linkedHash;
+ if (hash != null) {
+ String fileName = _getLinkedName(hash);
+// File file = linkedCacheFolder.getChildAssumingFile(fileName);
Paul Berry 2016/09/30 20:30:47 Remove commented out lines
scheglov 2016/09/30 20:38:28 Done.
+// manager.linkedBundleMap[file.path] = node.linked;
+ _writeAtomic(linkedCacheFolder, fileName, bytes);
+ }
+ }
}
/**
@@ -332,6 +423,7 @@ class _LinkNode {
Set<_LinkNode> transitiveDependencies;
List<_LinkNode> _dependencies;
+ String _linkedHash;
_LinkNode(this.linker, this.package);
@@ -385,6 +477,58 @@ class _LinkNode {
bool get isReady => package.linked != null || failed;
/**
+ * Return the hash string that corresponds to this linked bundle in the
+ * context of its SDK bundle and transitive dependencies. Return `null` if
+ * the hash computation fails, because for example the full transitive
+ * dependencies cannot computed.
+ */
+ String get linkedHash {
Paul Berry 2016/09/30 20:30:47 This method and the one below are copied almost ex
scheglov 2016/09/30 20:38:28 Yes, these two methods are similar to the ones we
+ if (_linkedHash == null && transitiveDependencies != null && !failed) {
+ ApiSignature signature = new ApiSignature();
+ // Add all unlinked API signatures.
+ List<String> signatures = <String>[];
+ signatures.add(linker.sdkBundle.apiSignature);
+ transitiveDependencies
+ .map((node) => node.package.unlinked.apiSignature)
+ .forEach(signatures.add);
+ signatures.sort();
+ signatures.forEach(signature.addString);
+ // Combine into a single hash.
+ appendDeclaredVariables(signature);
+ _linkedHash = signature.toHex();
+ }
+ return _linkedHash;
+ }
+
+ /**
+ * Append names and values of all referenced declared variables (even the
+ * ones without actually declared values) to the given [signature].
+ */
+ void appendDeclaredVariables(ApiSignature signature) {
+ Set<String> nameSet = new Set<String>();
+ for (_LinkNode node in transitiveDependencies) {
+ for (UnlinkedUnit unit in node.package.unlinked.unlinkedUnits) {
+ for (UnlinkedImport import in unit.imports) {
+ for (UnlinkedConfiguration configuration in import.configurations) {
+ nameSet.add(configuration.name);
+ }
+ }
+ for (UnlinkedExportPublic export in unit.publicNamespace.exports) {
+ for (UnlinkedConfiguration configuration in export.configurations) {
+ nameSet.add(configuration.name);
+ }
+ }
+ }
+ }
+ List<String> sortedNameList = nameSet.toList()..sort();
+ signature.addInt(sortedNameList.length);
+ for (String name in sortedNameList) {
+ signature.addString(name);
+ signature.addString(linker.context.declaredVariables.get(name) ?? '');
+ }
+ }
+
+ /**
* Compute the set of existing transitive dependencies for this node.
* If any dependency cannot be resolved, then set [failed] to `true`.
* Only unlinked bundle is used, so this method can be called before linking.
« no previous file with comments | « no previous file | pkg/analyzer/test/src/summary/bazel_summary_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698