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

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

Issue 796353003: Incremental compiler detects when library graph changes. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Merged with r42504. 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 09cb6f4bd463fa1767e438752a1f833ef26c49a5..14034c6ddfe50679935c8651c0ed0e6255226a61 100644
--- a/dart/pkg/dart2js_incremental/lib/library_updater.dart
+++ b/dart/pkg/dart2js_incremental/lib/library_updater.dart
@@ -27,19 +27,29 @@ import 'package:compiler/src/elements/elements.dart' show
import 'package:compiler/src/scanner/scannerlib.dart' show
EOF_TOKEN,
+ Listener,
+ NodeListener,
+ Parser,
PartialClassElement,
PartialElement,
PartialFieldList,
PartialFunctionElement,
+ Scanner,
Token;
import 'package:compiler/src/source_file.dart' show
+ CachingUtf8BytesSourceFile,
+ SourceFile,
StringSourceFile;
import 'package:compiler/src/tree/tree.dart' show
ClassNode,
FunctionExpression,
- NodeList;
+ LibraryTag,
+ NodeList,
+ Part,
+ StringNode,
+ unparse;
import 'package:compiler/src/js/js.dart' show
js;
@@ -84,6 +94,7 @@ import 'diff.dart' show
computeDifference;
import 'dart2js_incremental.dart' show
+ IncrementalCompilationFailed,
IncrementalCompiler;
typedef void Logger(message);
@@ -168,6 +179,8 @@ class LibraryUpdater extends JsFeatures {
final IncrementalCompilerContext _context;
+ final Map<Uri, Future> _sources = <Uri, Future>{};
+
bool _hasComputedNeeds = false;
bool _hasCapturedCompilerState = false;
@@ -212,23 +225,80 @@ class LibraryUpdater extends JsFeatures {
logTime('Reusing $library (assumed read-only).');
return new Future.value(true);
}
- 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.");
- return new Future.value(true);
+ return _haveTagsChanged(library).then((bool haveTagsChanged) {
+ if (haveTagsChanged) {
+ cannotReuse(
+ library,
+ "Changes to library, import, export, or part declarations not"
+ " supported.");
+ return true;
+ }
+ 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);
+ });
}
- return inputProvider(uri).then((bytes) {
- return canReuseLibrary(library, bytes);
- });
}
+
+ logTime("Reusing $library, source didn't change.");
+ // Source code of [library] wasn't changed.
+ return true;
+ });
+ }
+
+ Future<bool> _haveTagsChanged(LibraryElement library) {
+ Uri uri = library.entryCompilationUnit.script.resourceUri;
+ if (!_context._uriHasUpdate(uri)) {
+ // The entry compilation unit hasn't been updated. So the tags aren't
+ // changed.
+ return new Future<bool>.value(false);
}
- logTime("Reusing $library, source didn't change.");
- // Source code of [library] wasn't changed.
- return new Future.value(true);
+ 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();
+ // Using two parsers to only create the nodes we want ([LibraryTag]).
+ Parser parser = new Parser(new Listener());
+ NodeListener listener = new NodeListener(
+ compiler, library.entryCompilationUnit);
+ Parser nodeParser = new Parser(listener);
+ Iterator<LibraryTag> tags = library.tags.iterator;
+ while (token.kind != EOF_TOKEN) {
+ token = parser.parseMetadataStar(token);
+ if (parser.optional('library', token) ||
+ parser.optional('import', token) ||
+ parser.optional('export', token) ||
+ parser.optional('part', token)) {
+ if (!tags.moveNext()) return true;
+ token = nodeParser.parseTopLevelDeclaration(token);
+ LibraryTag tag = listener.popNode();
+ assert(listener.nodes.isEmpty);
+ if (unparse(tags.current) != unparse(tag)) {
+ return true;
+ }
+ } else {
+ break;
+ }
+ }
+ return tags.moveNext();
+ });
+ }
+
+ Future _readUri(Uri uri) {
+ return _sources.putIfAbsent(uri, () => inputProvider(uri));
}
void _ensureCompilerStateCaptured() {
@@ -583,8 +653,7 @@ class LibraryUpdater extends JsFeatures {
update.captureState();
}
if (!_failedUpdates.isEmpty) {
- throw new StateError(
- "Can't compute update.\n\n${_failedUpdates.join('\n\n')}");
+ throw new IncrementalCompilationFailed(_failedUpdates.join('\n\n'));
}
for (ElementX element in _elementsToInvalidate) {
compiler.forgetElement(element);
« no previous file with comments | « dart/pkg/dart2js_incremental/lib/dart2js_incremental.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