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

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: 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
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..7478f76f7a5d4a45a57e6c637c8b8f50231cfcbe 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;
@@ -185,6 +189,10 @@ class LibraryUpdater extends JsFeatures {
bool _hasCapturedCompilerState = false;
+ Token _entryUnitTokens;
+
+ SourceFile _entrySourceFile;
Johnni Winther 2014/12/19 12:17:33 What is the semantics of this?
ahe 2014/12/19 13:35:45 Done.
+
LibraryUpdater(
this.compiler,
this.inputProvider,
@@ -233,43 +241,57 @@ 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));
+ });
+ }
+
+ Future<Script> _updatedScript(Script before, LibraryElementX library) {
+ if (before == library.entryCompilationUnit.script &&
+ _entrySourceFile != null) {
+ return new Future.value(before.copyWithFile(_entrySourceFile));
+ }
+
+ 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) {
+ _entrySourceFile = script.file;
+ Token token = new Scanner(_entrySourceFile).tokenize();
+ _entryUnitTokens = token;
// Using two parsers to only create the nodes we want ([LibraryTag]).
Parser parser = new Parser(new Listener());
NodeListener listener = new NodeListener(
@@ -313,18 +335,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 != null) {
+ compiler.dietParser.dietParse(
+ newLibrary.entryCompilationUnit, _entryUnitTokens);
+ } 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 form library_loader.
Johnni Winther 2014/12/19 12:17:33 'form' -> 'from'
ahe 2014/12/19 13:35:45 Done.
+ 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);
}

Powered by Google App Engine
This is Rietveld 408576698