Read linked bundles from ByteStore.
R=brianwilkerson@google.com
Change-Id: I5be61a2d03c57d1b6bd7a765e50b235ef3f8af5b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/100983
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index e330665..c67f47a 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -587,7 +587,7 @@
}
@override
- String toString() => path;
+ String toString() => path ?? '<unresolved>';
/**
* Compute the full or partial map of exported declarations for this library.
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index daeaedc..421a8df 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -9,6 +9,7 @@
import 'package:analyzer/src/dart/analysis/byte_store.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/analysis/file_state.dart';
+import 'package:analyzer/src/dart/analysis/library_graph.dart';
import 'package:analyzer/src/dart/analysis/performance_logger.dart';
import 'package:analyzer/src/dart/analysis/restricted_analysis_context.dart';
import 'package:analyzer/src/dart/element/element.dart';
@@ -219,9 +220,72 @@
}
/// Load data required to access elements of the given [targetLibrary].
- ///
- /// TODO(scheglov) Implement loading cached linked bundles.
void load2(FileState targetLibrary) {
+ var loadedBundles = Set<LibraryCycle>.identity();
+ var inputBundles = <LinkedNodeBundle>[];
+
+ void loadBundle(LibraryCycle cycle) {
+ if (!loadedBundles.add(cycle)) return;
+
+ logger.run('Prepare linked bundle', () {
+ logger.writeln('Libraries: ${cycle.libraries}');
+ cycle.directDependencies.forEach(loadBundle);
+
+ var key = cycle.transitiveSignature + '.linked_bundle';
+ var bytes = byteStore.get(key);
+
+ if (bytes == null) {
+ var inputLibraries = <link2.LinkInputLibrary>[];
+ logger.run('Prepare input libraries', () {
+ for (var libraryFile in cycle.libraries) {
+ var librarySource = libraryFile.source;
+ if (librarySource == null) continue;
+
+ var inputUnits = <link2.LinkInputUnit>[];
+ for (var file in libraryFile.libraryFiles) {
+ var isSynthetic = !file.exists;
+ inputUnits.add(
+ link2.LinkInputUnit(file.source, isSynthetic, file.parse()),
+ );
+ }
+
+ inputLibraries.add(
+ link2.LinkInputLibrary(librarySource, inputUnits),
+ );
+ }
+ logger.writeln('Prepared ${inputLibraries.length} libraries.');
+ });
+
+ link2.LinkResult linkResult;
+ logger.run('Link libraries', () {
+ linkResult = link2.link(
+ analysisContext.analysisOptions,
+ analysisContext.sourceFactory,
+ analysisContext.declaredVariables,
+ inputBundles,
+ inputLibraries,
+ );
+ logger.writeln('Linked ${inputLibraries.length} libraries.');
+ });
+
+ bytes = linkResult.bundle.toBuffer();
+ byteStore.put(key, bytes);
+ logger.writeln('Stored ${bytes.length} bytes.');
+ } else {
+ logger.writeln('Loaded ${bytes.length} bytes.');
+ }
+
+ inputBundles.add(
+ LinkedNodeBundle.fromBuffer(bytes),
+ );
+ });
+ }
+
+ logger.run('Prepare linked bundles', () {
+ var libraryCycle = targetLibrary.libraryCycle;
+ loadBundle(libraryCycle);
+ });
+
var rootReference = Reference.root();
rootReference.getChild('dart:core').getChild('dynamic').element =
DynamicElementImpl.instance;
@@ -232,39 +296,11 @@
rootReference,
);
- var inputLibraries = <link2.LinkInputLibrary>[];
- var transitiveFiles = targetLibrary.transitiveFiles;
- for (var libraryFile in transitiveFiles) {
- if (libraryFile.isPart) {
- elementFactory.partUriSet.add(libraryFile.uriStr);
- }
-
- // TODO(scheglov) Why do we even we such invalid files in transitive?
- var librarySource = libraryFile.source;
- if (librarySource == null) continue;
-
- var inputUnits = <link2.LinkInputUnit>[];
- for (var file in libraryFile.libraryFiles) {
- var isSynthetic = !file.exists;
- inputUnits.add(
- link2.LinkInputUnit(file.source, isSynthetic, file.parse()),
- );
- }
- inputLibraries.add(
- link2.LinkInputLibrary(librarySource, inputUnits),
+ for (var bundle in inputBundles) {
+ elementFactory.addBundle(
+ LinkedBundleContext(elementFactory, bundle),
);
}
- var linkResult = link2.link(
- analysisContext.analysisOptions,
- analysisContext.sourceFactory,
- analysisContext.declaredVariables,
- [],
- inputLibraries,
- );
-
- elementFactory.addBundle(
- LinkedBundleContext(elementFactory, linkResult.bundle),
- );
var dartCore = elementFactory.libraryOfUri('dart:core');
var dartAsync = elementFactory.libraryOfUri('dart:async');
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_graph.dart b/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
index 7b0bcaf..3e79078 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_graph.dart
@@ -8,7 +8,6 @@
import 'package:analyzer/src/summary/api_signature.dart';
import 'package:analyzer/src/summary/link.dart' as graph
show DependencyWalker, Node;
-import 'package:meta/meta.dart';
/// Ensure that the [FileState.libraryCycle] for the [file] and anything it
/// depends on is computed.
@@ -23,7 +22,6 @@
final List<FileState> libraries = [];
/// The library cycles that this cycle references directly.
- @visibleForTesting
final Set<LibraryCycle> directDependencies = new Set<LibraryCycle>();
/// The cycles that use this cycle, used to [invalidate] transitively.
@@ -35,11 +33,11 @@
/// transitive signatures of the cycles that the [libraries] reference
/// directly. So, indirectly it is based on the transitive closure of all
/// files that [libraries] reference (but we don't compute these files).
- String _transitiveSignature;
+ String transitiveSignature;
/// The map from a library in [libraries] to its transitive signature.
///
- /// It is almost the same as [_transitiveSignature], but is also based on
+ /// It is almost the same as [transitiveSignature], but is also based on
/// the URI of this specific library. Currently we store each linked library
/// with its own key, so we need unique keys. However practically we never
/// can use just *one* library of a cycle, we always use the whole cycle.
@@ -49,7 +47,7 @@
LibraryCycle();
- LibraryCycle.external() : _transitiveSignature = '<external>';
+ LibraryCycle.external() : transitiveSignature = '<external>';
/// Invalidate this cycle and any cycles that directly or indirectly use it.
///
@@ -125,6 +123,8 @@
for (var node in scc) {
cycle.libraries.add(node.file);
+ signature.addString(node.file.uriStr);
+
signature.addInt(node.file.libraryFiles.length);
for (var file in node.file.libraryFiles) {
signature.addBytes(file.apiSignature);
@@ -132,13 +132,13 @@
}
// Compute the general library cycle signature.
- cycle._transitiveSignature = signature.toHex();
+ cycle.transitiveSignature = signature.toHex();
// Compute library specific signatures.
for (var node in scc) {
var librarySignatureBuilder = new ApiSignature()
..addString(node.file.uriStr)
- ..addString(cycle._transitiveSignature);
+ ..addString(cycle.transitiveSignature);
var librarySignature = librarySignatureBuilder.toHex();
node.file.internal_setLibraryCycle(
@@ -166,7 +166,7 @@
if (cycle.directDependencies.add(referencedCycle)) {
referencedCycle._directUsers.add(cycle);
- signature.addString(referencedCycle._transitiveSignature);
+ signature.addString(referencedCycle.transitiveSignature);
}
}
}
diff --git a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
index 414d97a..64cb319 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -19,7 +19,6 @@
final AnalysisSession analysisSession;
final Reference rootReference;
final Map<String, LinkedLibraryContext> libraryMap = {};
- final Set<String> partUriSet = Set<String>();
CoreTypes _coreTypes;
@@ -72,7 +71,8 @@
}
bool isLibraryUri(String uriStr) {
- return !partUriSet.contains(uriStr);
+ var libraryContext = libraryMap[uriStr];
+ return !libraryContext.definingUnit.hasPartOfDirective;
}
LibraryElementImpl libraryOfUri(String uriStr) {
diff --git a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
index 09a4027..dabace1 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -71,6 +71,15 @@
this.data,
this.tokensContext);
+ bool get hasPartOfDirective {
+ for (var directive in unit_withDirectives.directives) {
+ if (directive is PartOfDirective) {
+ return true;
+ }
+ }
+ return false;
+ }
+
CompilationUnit get unit => _unit;
CompilationUnit get unit_withDeclarations {