Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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 Loading... | |
| 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; |
| OLD | NEW |