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

Side by Side 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 unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library dart2js_incremental.library_updater; 5 library dart2js_incremental.library_updater;
6 6
7 import 'dart:async' show 7 import 'dart:async' show
8 Future; 8 Future;
9 9
10 import 'dart:convert' show 10 import 'dart:convert' show
11 UTF8; 11 UTF8;
12 12
13 import 'package:compiler/compiler.dart' as api; 13 import 'package:compiler/compiler.dart' as api;
14 14
15 import 'package:compiler/src/dart2jslib.dart' show 15 import 'package:compiler/src/dart2jslib.dart' show
16 Compiler, 16 Compiler,
17 EnqueueTask, 17 EnqueueTask,
18 Script; 18 Script;
19 19
20 import 'package:compiler/src/elements/elements.dart' show 20 import 'package:compiler/src/elements/elements.dart' show
21 ClassElement, 21 ClassElement,
22 CompilationUnitElement,
22 Element, 23 Element,
23 FunctionElement, 24 FunctionElement,
24 LibraryElement, 25 LibraryElement,
25 STATE_NOT_STARTED, 26 STATE_NOT_STARTED,
26 ScopeContainerElement; 27 ScopeContainerElement;
27 28
28 import 'package:compiler/src/scanner/scannerlib.dart' show 29 import 'package:compiler/src/scanner/scannerlib.dart' show
29 EOF_TOKEN, 30 EOF_TOKEN,
30 Listener, 31 Listener,
31 NodeListener, 32 NodeListener,
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
82 ElementX, 83 ElementX,
83 FieldElementX, 84 FieldElementX,
84 LibraryElementX; 85 LibraryElementX;
85 86
86 import 'package:compiler/src/universe/universe.dart' show 87 import 'package:compiler/src/universe/universe.dart' show
87 Selector; 88 Selector;
88 89
89 import 'package:compiler/src/constants/values.dart' show 90 import 'package:compiler/src/constants/values.dart' show
90 ConstantValue; 91 ConstantValue;
91 92
93 import 'package:compiler/src/library_loader.dart' show
94 TagState;
95
92 import 'diff.dart' show 96 import 'diff.dart' show
93 Difference, 97 Difference,
94 computeDifference; 98 computeDifference;
95 99
96 import 'dart2js_incremental.dart' show 100 import 'dart2js_incremental.dart' show
97 IncrementalCompilationFailed, 101 IncrementalCompilationFailed,
98 IncrementalCompiler; 102 IncrementalCompiler;
99 103
100 typedef void Logger(message); 104 typedef void Logger(message);
101 105
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 178
175 final Set<ElementX> _removedElements = new Set<ElementX>(); 179 final Set<ElementX> _removedElements = new Set<ElementX>();
176 180
177 final Set<ClassElementX> _classesWithSchemaChanges = 181 final Set<ClassElementX> _classesWithSchemaChanges =
178 new Set<ClassElementX>(); 182 new Set<ClassElementX>();
179 183
180 final IncrementalCompilerContext _context; 184 final IncrementalCompilerContext _context;
181 185
182 final Map<Uri, Future> _sources = <Uri, Future>{}; 186 final Map<Uri, Future> _sources = <Uri, Future>{};
183 187
188 /// Cached tokens of entry compilation units.
189 final Map<LibraryElementX, Token> _entryUnitTokens =
190 <LibraryElementX, Token>{};
191
192 /// Cached source files for entry compilation units.
193 final Map<LibraryElementX, SourceFile> _entrySourceFiles =
194 <LibraryElementX, SourceFile>{};
195
184 bool _hasComputedNeeds = false; 196 bool _hasComputedNeeds = false;
185 197
186 bool _hasCapturedCompilerState = false; 198 bool _hasCapturedCompilerState = false;
187 199
188 LibraryUpdater( 200 LibraryUpdater(
189 this.compiler, 201 this.compiler,
190 this.inputProvider, 202 this.inputProvider,
191 this.logTime, 203 this.logTime,
192 this.logVerbose, 204 this.logVerbose,
193 this._context) { 205 this._context) {
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
226 return new Future.value(true); 238 return new Future.value(true);
227 } 239 }
228 return _haveTagsChanged(library).then((bool haveTagsChanged) { 240 return _haveTagsChanged(library).then((bool haveTagsChanged) {
229 if (haveTagsChanged) { 241 if (haveTagsChanged) {
230 cannotReuse( 242 cannotReuse(
231 library, 243 library,
232 "Changes to library, import, export, or part declarations not" 244 "Changes to library, import, export, or part declarations not"
233 " supported."); 245 " supported.");
234 return true; 246 return true;
235 } 247 }
248
249 bool isChanged = false;
250 List<Future<Script>> futureScripts = <Future<Script>>[];
251
236 for (CompilationUnitElementX unit in library.compilationUnits) { 252 for (CompilationUnitElementX unit in library.compilationUnits) {
237 Uri uri = unit.script.resourceUri; 253 Uri uri = unit.script.resourceUri;
238 if (_context._uriHasUpdate(uri)) { 254 if (_context._uriHasUpdate(uri)) {
239 if (!library.compilationUnits.tail.isEmpty) { 255 isChanged = true;
240 // TODO(ahe): Remove this restriction. 256 futureScripts.add(_updatedScript(unit.script, library));
241 cannotReuse( 257 } else {
242 library, 258 futureScripts.add(new Future.value(unit.script));
243 "Multiple compilation units not supported"
244 " (${library.compilationUnits}).");
245 return true;
246 }
247 return _readUri(uri).then((bytes) {
248 return canReuseLibrary(library, bytes);
249 });
250 } 259 }
251 } 260 }
252 261
253 logTime("Reusing $library, source didn't change."); 262 if (!isChanged) {
254 // Source code of [library] wasn't changed. 263 logTime("Reusing $library, source didn't change.");
255 return true; 264 return true;
265 }
266
267 return Future.wait(futureScripts).then(
268 (List<Script> scripts) => canReuseLibrary(library, scripts));
269 }).whenComplete(() => _cleanUp(library));
270 }
271
272 void _cleanUp(LibraryElementX library) {
273 _entryUnitTokens.remove(library);
274 _entrySourceFiles.remove(library);
275 }
276
277 Future<Script> _updatedScript(Script before, LibraryElementX library) {
278 if (before == library.entryCompilationUnit.script &&
279 _entrySourceFiles.containsKey(library)) {
280 return new Future.value(before.copyWithFile(_entrySourceFiles[library]));
281 }
282
283 return _readUri(before.resourceUri).then((bytes) {
284 String filename = before.file.filename;
285 SourceFile sourceFile = bytes is String
286 ? new StringSourceFile(filename, bytes)
287 : new CachingUtf8BytesSourceFile(filename, bytes);
288 return before.copyWithFile(sourceFile);
256 }); 289 });
257 } 290 }
258 291
259 Future<bool> _haveTagsChanged(LibraryElement library) { 292 Future<bool> _haveTagsChanged(LibraryElement library) {
260 Uri uri = library.entryCompilationUnit.script.resourceUri; 293 Script before = library.entryCompilationUnit.script;
261 if (!_context._uriHasUpdate(uri)) { 294 if (!_context._uriHasUpdate(before.resourceUri)) {
262 // The entry compilation unit hasn't been updated. So the tags aren't 295 // The entry compilation unit hasn't been updated. So the tags aren't
263 // changed. 296 // changed.
264 return new Future<bool>.value(false); 297 return new Future<bool>.value(false);
265 } 298 }
266 299
267 return _readUri(uri).then((bytes) { 300 return _updatedScript(before, library).then((Script script) {
268 String filename = '$uri'; 301 _entrySourceFiles[library] = script.file;
269 SourceFile sourceFile = bytes is String 302 Token token = new Scanner(_entrySourceFiles[library]).tokenize();
270 ? new StringSourceFile(filename, bytes) 303 _entryUnitTokens[library] = token;
271 : new CachingUtf8BytesSourceFile(filename, bytes);
272 Token token = new Scanner(sourceFile).tokenize();
273 // Using two parsers to only create the nodes we want ([LibraryTag]). 304 // Using two parsers to only create the nodes we want ([LibraryTag]).
274 Parser parser = new Parser(new Listener()); 305 Parser parser = new Parser(new Listener());
275 NodeListener listener = new NodeListener( 306 NodeListener listener = new NodeListener(
276 compiler, library.entryCompilationUnit); 307 compiler, library.entryCompilationUnit);
277 Parser nodeParser = new Parser(listener); 308 Parser nodeParser = new Parser(listener);
278 Iterator<LibraryTag> tags = library.tags.iterator; 309 Iterator<LibraryTag> tags = library.tags.iterator;
279 while (token.kind != EOF_TOKEN) { 310 while (token.kind != EOF_TOKEN) {
280 token = parser.parseMetadataStar(token); 311 token = parser.parseMetadataStar(token);
281 if (parser.optional('library', token) || 312 if (parser.optional('library', token) ||
282 parser.optional('import', token) || 313 parser.optional('import', token) ||
(...skipping 23 matching lines...) Expand all
306 if (compiler == null) return; 337 if (compiler == null) return;
307 338
308 if (_hasCapturedCompilerState) return; 339 if (_hasCapturedCompilerState) return;
309 _context._captureState(compiler); 340 _context._captureState(compiler);
310 _hasCapturedCompilerState = true; 341 _hasCapturedCompilerState = true;
311 } 342 }
312 343
313 /// Returns true if [library] can be reused. 344 /// Returns true if [library] can be reused.
314 /// 345 ///
315 /// This methods also computes the [updates] (patches) needed to have 346 /// This methods also computes the [updates] (patches) needed to have
316 /// [library] reflect the modifications in [bytes]. 347 /// [library] reflect the modifications in [scripts].
317 bool canReuseLibrary(LibraryElement library, bytes) { 348 bool canReuseLibrary(LibraryElement library, List<Script> scripts) {
318 logTime('Attempting to reuse ${library}.'); 349 logTime('Attempting to reuse ${library}.');
319 String newSource = bytes is String ? bytes : UTF8.decode(bytes);
320 logTime('Decoded UTF8');
321 350
322 Uri uri = library.entryCompilationUnit.script.resourceUri; 351 Uri entryUri = library.entryCompilationUnit.script.resourceUri;
323 Script sourceScript = new Script( 352 Script entryScript =
324 uri, uri, new StringSourceFile('$uri', newSource)); 353 scripts.singleWhere((Script script) => script.resourceUri == entryUri);
325 var dartPrivacyIsBroken = compiler.libraryLoader; 354 LibraryElement newLibrary =
326 LibraryElement newLibrary = dartPrivacyIsBroken.createLibrarySync( 355 new LibraryElementX(entryScript, library.canonicalUri);
327 null, sourceScript, uri); 356 if (_entryUnitTokens.containsKey(library)) {
357 compiler.dietParser.dietParse(
358 newLibrary.entryCompilationUnit, _entryUnitTokens[library]);
359 } else {
360 compiler.scanner.scanLibrary(newLibrary);
361 }
362
363 TagState tagState = new TagState();
364 for (LibraryTag tag in newLibrary.tags) {
365 if (tag.isImport) {
366 tagState.checkTag(TagState.IMPORT_OR_EXPORT, tag, compiler);
367 } else if (tag.isExport) {
368 tagState.checkTag(TagState.IMPORT_OR_EXPORT, tag, compiler);
369 } else if (tag.isLibraryName) {
370 tagState.checkTag(TagState.LIBRARY, tag, compiler);
371 if (newLibrary.libraryTag == null) {
372 // Use the first if there are multiple (which is reported as an
373 // error in [TagState.checkTag]).
374 newLibrary.libraryTag = tag;
375 }
376 } else if (tag.isPart) {
377 tagState.checkTag(TagState.PART, tag, compiler);
378 }
379 }
380
381 // TODO(ahe): Process tags using TagState, not
382 // LibraryLoaderTask.processLibraryTags.
383 Link<CompilationUnitElement> units = library.compilationUnits;
384 for (Script script in scripts) {
385 CompilationUnitElementX unit = units.head;
386 units = units.tail;
387 if (script != entryScript) {
388 // TODO(ahe): Copied from library_loader.
389 CompilationUnitElement newUnit =
390 new CompilationUnitElementX(script, newLibrary);
391 compiler.withCurrentElement(newUnit, () {
392 compiler.scanner.scan(newUnit);
393 if (unit.partTag == null) {
394 compiler.reportError(unit, MessageKind.MISSING_PART_OF_TAG);
395 }
396 });
397 }
398 }
399
328 logTime('New library synthesized.'); 400 logTime('New library synthesized.');
329 return canReuseScopeContainerElement(library, newLibrary); 401 return canReuseScopeContainerElement(library, newLibrary);
330 } 402 }
331 403
332 bool cannotReuse(context, String message) { 404 bool cannotReuse(context, String message) {
333 _failedUpdates.add(new FailedUpdate(context, message)); 405 _failedUpdates.add(new FailedUpdate(context, message));
334 logVerbose(message); 406 logVerbose(message);
335 return false; 407 return false;
336 } 408 }
337 409
(...skipping 1064 matching lines...) Expand 10 before | Expand all | Expand 10 after
1402 List<String> computeFields(ClassElement cls) { 1474 List<String> computeFields(ClassElement cls) {
1403 // TODO(ahe): Rewrite for new emitter. 1475 // TODO(ahe): Rewrite for new emitter.
1404 ClassBuilder builder = new ClassBuilder(cls, namer); 1476 ClassBuilder builder = new ClassBuilder(cls, namer);
1405 classEmitter.emitFields(cls, builder); 1477 classEmitter.emitFields(cls, builder);
1406 return builder.fields; 1478 return builder.fields;
1407 } 1479 }
1408 } 1480 }
1409 1481
1410 // TODO(ahe): Remove this method. 1482 // TODO(ahe): Remove this method.
1411 NO_WARN(x) => x; 1483 NO_WARN(x) => x;
OLDNEW
« 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