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

Unified Diff: dart/pkg/dart2js_incremental/lib/library_updater.dart

Issue 815123002: Incremental compilation of libraries with multiple parts. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Address comments. Created 6 years 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 | « dart/pkg/compiler/lib/src/script.dart ('k') | dart/tests/try/web/incremental_compilation_update_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: dart/pkg/dart2js_incremental/lib/library_updater.dart
diff --git a/dart/pkg/dart2js_incremental/lib/library_updater.dart b/dart/pkg/dart2js_incremental/lib/library_updater.dart
index 14034c6ddfe50679935c8651c0ed0e6255226a61..6ea459f02e10b12f99cf138025d0e44732a078e1 100644
--- a/dart/pkg/dart2js_incremental/lib/library_updater.dart
+++ b/dart/pkg/dart2js_incremental/lib/library_updater.dart
@@ -19,6 +19,7 @@ import 'package:compiler/src/dart2jslib.dart' show
import 'package:compiler/src/elements/elements.dart' show
ClassElement,
+ CompilationUnitElement,
Element,
FunctionElement,
LibraryElement,
@@ -89,6 +90,9 @@ import 'package:compiler/src/universe/universe.dart' show
import 'package:compiler/src/constants/values.dart' show
ConstantValue;
+import 'package:compiler/src/library_loader.dart' show
+ TagState;
+
import 'diff.dart' show
Difference,
computeDifference;
@@ -181,6 +185,14 @@ class LibraryUpdater extends JsFeatures {
final Map<Uri, Future> _sources = <Uri, Future>{};
+ /// Cached tokens of entry compilation units.
+ final Map<LibraryElementX, Token> _entryUnitTokens =
+ <LibraryElementX, Token>{};
+
+ /// Cached source files for entry compilation units.
+ final Map<LibraryElementX, SourceFile> _entrySourceFiles =
+ <LibraryElementX, SourceFile>{};
+
bool _hasComputedNeeds = false;
bool _hasCapturedCompilerState = false;
@@ -233,43 +245,62 @@ class LibraryUpdater extends JsFeatures {
" supported.");
return true;
}
+
+ bool isChanged = false;
+ List<Future<Script>> futureScripts = <Future<Script>>[];
+
for (CompilationUnitElementX unit in library.compilationUnits) {
Uri uri = unit.script.resourceUri;
if (_context._uriHasUpdate(uri)) {
- if (!library.compilationUnits.tail.isEmpty) {
- // TODO(ahe): Remove this restriction.
- cannotReuse(
- library,
- "Multiple compilation units not supported"
- " (${library.compilationUnits}).");
- return true;
- }
- return _readUri(uri).then((bytes) {
- return canReuseLibrary(library, bytes);
- });
+ isChanged = true;
+ futureScripts.add(_updatedScript(unit.script, library));
+ } else {
+ futureScripts.add(new Future.value(unit.script));
}
}
- logTime("Reusing $library, source didn't change.");
- // Source code of [library] wasn't changed.
- return true;
+ if (!isChanged) {
+ logTime("Reusing $library, source didn't change.");
+ return true;
+ }
+
+ return Future.wait(futureScripts).then(
+ (List<Script> scripts) => canReuseLibrary(library, scripts));
+ }).whenComplete(() => _cleanUp(library));
+ }
+
+ void _cleanUp(LibraryElementX library) {
+ _entryUnitTokens.remove(library);
+ _entrySourceFiles.remove(library);
+ }
+
+ Future<Script> _updatedScript(Script before, LibraryElementX library) {
+ if (before == library.entryCompilationUnit.script &&
+ _entrySourceFiles.containsKey(library)) {
+ return new Future.value(before.copyWithFile(_entrySourceFiles[library]));
+ }
+
+ return _readUri(before.resourceUri).then((bytes) {
+ String filename = before.file.filename;
+ SourceFile sourceFile = bytes is String
+ ? new StringSourceFile(filename, bytes)
+ : new CachingUtf8BytesSourceFile(filename, bytes);
+ return before.copyWithFile(sourceFile);
});
}
Future<bool> _haveTagsChanged(LibraryElement library) {
- Uri uri = library.entryCompilationUnit.script.resourceUri;
- if (!_context._uriHasUpdate(uri)) {
+ Script before = library.entryCompilationUnit.script;
+ if (!_context._uriHasUpdate(before.resourceUri)) {
// The entry compilation unit hasn't been updated. So the tags aren't
// changed.
return new Future<bool>.value(false);
}
- return _readUri(uri).then((bytes) {
- String filename = '$uri';
- SourceFile sourceFile = bytes is String
- ? new StringSourceFile(filename, bytes)
- : new CachingUtf8BytesSourceFile(filename, bytes);
- Token token = new Scanner(sourceFile).tokenize();
+ return _updatedScript(before, library).then((Script script) {
+ _entrySourceFiles[library] = script.file;
+ Token token = new Scanner(_entrySourceFiles[library]).tokenize();
+ _entryUnitTokens[library] = token;
// Using two parsers to only create the nodes we want ([LibraryTag]).
Parser parser = new Parser(new Listener());
NodeListener listener = new NodeListener(
@@ -313,18 +344,59 @@ class LibraryUpdater extends JsFeatures {
/// Returns true if [library] can be reused.
///
/// This methods also computes the [updates] (patches) needed to have
- /// [library] reflect the modifications in [bytes].
- bool canReuseLibrary(LibraryElement library, bytes) {
+ /// [library] reflect the modifications in [scripts].
+ bool canReuseLibrary(LibraryElement library, List<Script> scripts) {
logTime('Attempting to reuse ${library}.');
- String newSource = bytes is String ? bytes : UTF8.decode(bytes);
- logTime('Decoded UTF8');
-
- Uri uri = library.entryCompilationUnit.script.resourceUri;
- Script sourceScript = new Script(
- uri, uri, new StringSourceFile('$uri', newSource));
- var dartPrivacyIsBroken = compiler.libraryLoader;
- LibraryElement newLibrary = dartPrivacyIsBroken.createLibrarySync(
- null, sourceScript, uri);
+
+ Uri entryUri = library.entryCompilationUnit.script.resourceUri;
+ Script entryScript =
+ scripts.singleWhere((Script script) => script.resourceUri == entryUri);
+ LibraryElement newLibrary =
+ new LibraryElementX(entryScript, library.canonicalUri);
+ if (_entryUnitTokens.containsKey(library)) {
+ compiler.dietParser.dietParse(
+ newLibrary.entryCompilationUnit, _entryUnitTokens[library]);
+ } else {
+ compiler.scanner.scanLibrary(newLibrary);
+ }
+
+ TagState tagState = new TagState();
+ for (LibraryTag tag in newLibrary.tags) {
+ if (tag.isImport) {
+ tagState.checkTag(TagState.IMPORT_OR_EXPORT, tag, compiler);
+ } else if (tag.isExport) {
+ tagState.checkTag(TagState.IMPORT_OR_EXPORT, tag, compiler);
+ } else if (tag.isLibraryName) {
+ tagState.checkTag(TagState.LIBRARY, tag, compiler);
+ if (newLibrary.libraryTag == null) {
+ // Use the first if there are multiple (which is reported as an
+ // error in [TagState.checkTag]).
+ newLibrary.libraryTag = tag;
+ }
+ } else if (tag.isPart) {
+ tagState.checkTag(TagState.PART, tag, compiler);
+ }
+ }
+
+ // TODO(ahe): Process tags using TagState, not
+ // LibraryLoaderTask.processLibraryTags.
+ Link<CompilationUnitElement> units = library.compilationUnits;
+ for (Script script in scripts) {
+ CompilationUnitElementX unit = units.head;
+ units = units.tail;
+ if (script != entryScript) {
+ // TODO(ahe): Copied from library_loader.
+ CompilationUnitElement newUnit =
+ new CompilationUnitElementX(script, newLibrary);
+ compiler.withCurrentElement(newUnit, () {
+ compiler.scanner.scan(newUnit);
+ if (unit.partTag == null) {
+ compiler.reportError(unit, MessageKind.MISSING_PART_OF_TAG);
+ }
+ });
+ }
+ }
+
logTime('New library synthesized.');
return canReuseScopeContainerElement(library, newLibrary);
}
« no previous file with comments | « dart/pkg/compiler/lib/src/script.dart ('k') | dart/tests/try/web/incremental_compilation_update_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698