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

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: 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 76 matching lines...) Expand 10 before | Expand all | Expand 10 after
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
184 bool _hasComputedNeeds = false; 188 bool _hasComputedNeeds = false;
185 189
186 bool _hasCapturedCompilerState = false; 190 bool _hasCapturedCompilerState = false;
187 191
192 Token _entryUnitTokens;
193
194 SourceFile _entrySourceFile;
Johnni Winther 2014/12/19 12:17:33 What is the semantics of this?
ahe 2014/12/19 13:35:45 Done.
195
188 LibraryUpdater( 196 LibraryUpdater(
189 this.compiler, 197 this.compiler,
190 this.inputProvider, 198 this.inputProvider,
191 this.logTime, 199 this.logTime,
192 this.logVerbose, 200 this.logVerbose,
193 this._context) { 201 this._context) {
194 // TODO(ahe): Would like to remove this from the constructor. However, the 202 // TODO(ahe): Would like to remove this from the constructor. However, the
195 // state must be captured before calling [reuseCompiler]. 203 // state must be captured before calling [reuseCompiler].
196 // Proper solution might be: [reuseCompiler] should not clear the sets that 204 // Proper solution might be: [reuseCompiler] should not clear the sets that
197 // are captured in [IncrementalCompilerContext._captureState]. 205 // are captured in [IncrementalCompilerContext._captureState].
(...skipping 28 matching lines...) Expand all
226 return new Future.value(true); 234 return new Future.value(true);
227 } 235 }
228 return _haveTagsChanged(library).then((bool haveTagsChanged) { 236 return _haveTagsChanged(library).then((bool haveTagsChanged) {
229 if (haveTagsChanged) { 237 if (haveTagsChanged) {
230 cannotReuse( 238 cannotReuse(
231 library, 239 library,
232 "Changes to library, import, export, or part declarations not" 240 "Changes to library, import, export, or part declarations not"
233 " supported."); 241 " supported.");
234 return true; 242 return true;
235 } 243 }
244
245 bool isChanged = false;
246 List<Future<Script>> futureScripts = <Future<Script>>[];
247
236 for (CompilationUnitElementX unit in library.compilationUnits) { 248 for (CompilationUnitElementX unit in library.compilationUnits) {
237 Uri uri = unit.script.resourceUri; 249 Uri uri = unit.script.resourceUri;
238 if (_context._uriHasUpdate(uri)) { 250 if (_context._uriHasUpdate(uri)) {
239 if (!library.compilationUnits.tail.isEmpty) { 251 isChanged = true;
240 // TODO(ahe): Remove this restriction. 252 futureScripts.add(_updatedScript(unit.script, library));
241 cannotReuse( 253 } else {
242 library, 254 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 } 255 }
251 } 256 }
252 257
253 logTime("Reusing $library, source didn't change."); 258 if (!isChanged) {
254 // Source code of [library] wasn't changed. 259 logTime("Reusing $library, source didn't change.");
255 return true; 260 return true;
261 }
262
263 return Future.wait(futureScripts).then(
264 (List<Script> scripts) => canReuseLibrary(library, scripts));
265 });
266 }
267
268 Future<Script> _updatedScript(Script before, LibraryElementX library) {
269 if (before == library.entryCompilationUnit.script &&
270 _entrySourceFile != null) {
271 return new Future.value(before.copyWithFile(_entrySourceFile));
272 }
273
274 return _readUri(before.resourceUri).then((bytes) {
275 String filename = before.file.filename;
276 SourceFile sourceFile = bytes is String
277 ? new StringSourceFile(filename, bytes)
278 : new CachingUtf8BytesSourceFile(filename, bytes);
279 return before.copyWithFile(sourceFile);
256 }); 280 });
257 } 281 }
258 282
259 Future<bool> _haveTagsChanged(LibraryElement library) { 283 Future<bool> _haveTagsChanged(LibraryElement library) {
260 Uri uri = library.entryCompilationUnit.script.resourceUri; 284 Script before = library.entryCompilationUnit.script;
261 if (!_context._uriHasUpdate(uri)) { 285 if (!_context._uriHasUpdate(before.resourceUri)) {
262 // The entry compilation unit hasn't been updated. So the tags aren't 286 // The entry compilation unit hasn't been updated. So the tags aren't
263 // changed. 287 // changed.
264 return new Future<bool>.value(false); 288 return new Future<bool>.value(false);
265 } 289 }
266 290
267 return _readUri(uri).then((bytes) { 291 return _updatedScript(before, library).then((Script script) {
268 String filename = '$uri'; 292 _entrySourceFile = script.file;
269 SourceFile sourceFile = bytes is String 293 Token token = new Scanner(_entrySourceFile).tokenize();
270 ? new StringSourceFile(filename, bytes) 294 _entryUnitTokens = 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]). 295 // Using two parsers to only create the nodes we want ([LibraryTag]).
274 Parser parser = new Parser(new Listener()); 296 Parser parser = new Parser(new Listener());
275 NodeListener listener = new NodeListener( 297 NodeListener listener = new NodeListener(
276 compiler, library.entryCompilationUnit); 298 compiler, library.entryCompilationUnit);
277 Parser nodeParser = new Parser(listener); 299 Parser nodeParser = new Parser(listener);
278 Iterator<LibraryTag> tags = library.tags.iterator; 300 Iterator<LibraryTag> tags = library.tags.iterator;
279 while (token.kind != EOF_TOKEN) { 301 while (token.kind != EOF_TOKEN) {
280 token = parser.parseMetadataStar(token); 302 token = parser.parseMetadataStar(token);
281 if (parser.optional('library', token) || 303 if (parser.optional('library', token) ||
282 parser.optional('import', token) || 304 parser.optional('import', token) ||
(...skipping 23 matching lines...) Expand all
306 if (compiler == null) return; 328 if (compiler == null) return;
307 329
308 if (_hasCapturedCompilerState) return; 330 if (_hasCapturedCompilerState) return;
309 _context._captureState(compiler); 331 _context._captureState(compiler);
310 _hasCapturedCompilerState = true; 332 _hasCapturedCompilerState = true;
311 } 333 }
312 334
313 /// Returns true if [library] can be reused. 335 /// Returns true if [library] can be reused.
314 /// 336 ///
315 /// This methods also computes the [updates] (patches) needed to have 337 /// This methods also computes the [updates] (patches) needed to have
316 /// [library] reflect the modifications in [bytes]. 338 /// [library] reflect the modifications in [scripts].
317 bool canReuseLibrary(LibraryElement library, bytes) { 339 bool canReuseLibrary(LibraryElement library, List<Script> scripts) {
318 logTime('Attempting to reuse ${library}.'); 340 logTime('Attempting to reuse ${library}.');
319 String newSource = bytes is String ? bytes : UTF8.decode(bytes);
320 logTime('Decoded UTF8');
321 341
322 Uri uri = library.entryCompilationUnit.script.resourceUri; 342 Uri entryUri = library.entryCompilationUnit.script.resourceUri;
323 Script sourceScript = new Script( 343 Script entryScript =
324 uri, uri, new StringSourceFile('$uri', newSource)); 344 scripts.singleWhere((Script script) => script.resourceUri == entryUri);
325 var dartPrivacyIsBroken = compiler.libraryLoader; 345 LibraryElement newLibrary =
326 LibraryElement newLibrary = dartPrivacyIsBroken.createLibrarySync( 346 new LibraryElementX(entryScript, library.canonicalUri);
327 null, sourceScript, uri); 347 if (_entryUnitTokens != null) {
348 compiler.dietParser.dietParse(
349 newLibrary.entryCompilationUnit, _entryUnitTokens);
350 } else {
351 compiler.scanner.scanLibrary(newLibrary);
352 }
353
354 TagState tagState = new TagState();
355 for (LibraryTag tag in newLibrary.tags) {
356 if (tag.isImport) {
357 tagState.checkTag(TagState.IMPORT_OR_EXPORT, tag, compiler);
358 } else if (tag.isExport) {
359 tagState.checkTag(TagState.IMPORT_OR_EXPORT, tag, compiler);
360 } else if (tag.isLibraryName) {
361 tagState.checkTag(TagState.LIBRARY, tag, compiler);
362 if (newLibrary.libraryTag == null) {
363 // Use the first if there are multiple (which is reported as an
364 // error in [TagState.checkTag]).
365 newLibrary.libraryTag = tag;
366 }
367 } else if (tag.isPart) {
368 tagState.checkTag(TagState.PART, tag, compiler);
369 }
370 }
371
372 // TODO(ahe): Process tags using TagState, not
373 // LibraryLoaderTask.processLibraryTags.
374 Link<CompilationUnitElement> units = library.compilationUnits;
375 for (Script script in scripts) {
376 CompilationUnitElementX unit = units.head;
377 units = units.tail;
378 if (script != entryScript) {
379 // TODO(ahe): Copied form library_loader.
Johnni Winther 2014/12/19 12:17:33 'form' -> 'from'
ahe 2014/12/19 13:35:45 Done.
380 CompilationUnitElement newUnit =
381 new CompilationUnitElementX(script, newLibrary);
382 compiler.withCurrentElement(newUnit, () {
383 compiler.scanner.scan(newUnit);
384 if (unit.partTag == null) {
385 compiler.reportError(unit, MessageKind.MISSING_PART_OF_TAG);
386 }
387 });
388 }
389 }
390
328 logTime('New library synthesized.'); 391 logTime('New library synthesized.');
329 return canReuseScopeContainerElement(library, newLibrary); 392 return canReuseScopeContainerElement(library, newLibrary);
330 } 393 }
331 394
332 bool cannotReuse(context, String message) { 395 bool cannotReuse(context, String message) {
333 _failedUpdates.add(new FailedUpdate(context, message)); 396 _failedUpdates.add(new FailedUpdate(context, message));
334 logVerbose(message); 397 logVerbose(message);
335 return false; 398 return false;
336 } 399 }
337 400
(...skipping 1064 matching lines...) Expand 10 before | Expand all | Expand 10 after
1402 List<String> computeFields(ClassElement cls) { 1465 List<String> computeFields(ClassElement cls) {
1403 // TODO(ahe): Rewrite for new emitter. 1466 // TODO(ahe): Rewrite for new emitter.
1404 ClassBuilder builder = new ClassBuilder(cls, namer); 1467 ClassBuilder builder = new ClassBuilder(cls, namer);
1405 classEmitter.emitFields(cls, builder); 1468 classEmitter.emitFields(cls, builder);
1406 return builder.fields; 1469 return builder.fields;
1407 } 1470 }
1408 } 1471 }
1409 1472
1410 // TODO(ahe): Remove this method. 1473 // TODO(ahe): Remove this method.
1411 NO_WARN(x) => x; 1474 NO_WARN(x) => x;
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698