| 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 |
| (...skipping 10 matching lines...) Expand all Loading... |
| 21 Element, | 21 Element, |
| 22 FunctionElement, | 22 FunctionElement, |
| 23 LibraryElement, | 23 LibraryElement, |
| 24 STATE_NOT_STARTED, | 24 STATE_NOT_STARTED, |
| 25 ScopeContainerElement; | 25 ScopeContainerElement; |
| 26 | 26 |
| 27 import 'package:compiler/src/scanner/scannerlib.dart' show | 27 import 'package:compiler/src/scanner/scannerlib.dart' show |
| 28 EOF_TOKEN, | 28 EOF_TOKEN, |
| 29 PartialClassElement, | 29 PartialClassElement, |
| 30 PartialElement, | 30 PartialElement, |
| 31 PartialFieldList, |
| 31 PartialFunctionElement, | 32 PartialFunctionElement, |
| 32 Token; | 33 Token; |
| 33 | 34 |
| 34 import 'package:compiler/src/source_file.dart' show | 35 import 'package:compiler/src/source_file.dart' show |
| 35 StringSourceFile; | 36 StringSourceFile; |
| 36 | 37 |
| 37 import 'package:compiler/src/tree/tree.dart' show | 38 import 'package:compiler/src/tree/tree.dart' show |
| 38 ClassNode, | 39 ClassNode, |
| 39 FunctionExpression, | 40 FunctionExpression, |
| 40 NodeList; | 41 NodeList; |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 109 final Uri uri; | 110 final Uri uri; |
| 110 | 111 |
| 111 final List<Update> updates = <Update>[]; | 112 final List<Update> updates = <Update>[]; |
| 112 | 113 |
| 113 final List<FailedUpdate> _failedUpdates = <FailedUpdate>[]; | 114 final List<FailedUpdate> _failedUpdates = <FailedUpdate>[]; |
| 114 | 115 |
| 115 final Set<ElementX> _elementsToInvalidate = new Set<ElementX>(); | 116 final Set<ElementX> _elementsToInvalidate = new Set<ElementX>(); |
| 116 | 117 |
| 117 final Set<ElementX> _removedElements = new Set<ElementX>(); | 118 final Set<ElementX> _removedElements = new Set<ElementX>(); |
| 118 | 119 |
| 120 final Set<ClassElementX> _classesWithSchemaChanges = |
| 121 new Set<ClassElementX>(); |
| 122 |
| 119 LibraryUpdater( | 123 LibraryUpdater( |
| 120 this.compiler, | 124 this.compiler, |
| 121 this.inputProvider, | 125 this.inputProvider, |
| 122 this.uri, | 126 this.uri, |
| 123 this.logTime, | 127 this.logTime, |
| 124 this.logVerbose); | 128 this.logVerbose); |
| 125 | 129 |
| 126 /// When [true], updates must be applied (using [applyUpdates]) before the | 130 /// When [true], updates must be applied (using [applyUpdates]) before the |
| 127 /// [compiler]'s state correctly reflects the updated program. | 131 /// [compiler]'s state correctly reflects the updated program. |
| 128 bool get hasPendingUpdates => !updates.isEmpty; | 132 bool get hasPendingUpdates => !updates.isEmpty; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 178 | 182 |
| 179 bool canReuseScopeContainerElement( | 183 bool canReuseScopeContainerElement( |
| 180 ScopeContainerElement element, | 184 ScopeContainerElement element, |
| 181 ScopeContainerElement newElement) { | 185 ScopeContainerElement newElement) { |
| 182 List<Difference> differences = computeDifference(element, newElement); | 186 List<Difference> differences = computeDifference(element, newElement); |
| 183 logTime('Differences computed.'); | 187 logTime('Differences computed.'); |
| 184 for (Difference difference in differences) { | 188 for (Difference difference in differences) { |
| 185 logTime('Looking at difference: $difference'); | 189 logTime('Looking at difference: $difference'); |
| 186 | 190 |
| 187 if (difference.before == null && difference.after is PartialElement) { | 191 if (difference.before == null && difference.after is PartialElement) { |
| 188 canReuseAddedElement(difference.after, element); | 192 canReuseAddedElement(difference.after, element, newElement); |
| 189 continue; | 193 continue; |
| 190 } | 194 } |
| 191 if (difference.after == null && difference.before is PartialElement) { | 195 if (difference.after == null && difference.before is PartialElement) { |
| 192 canReuseRemovedElement(difference.before); | 196 canReuseRemovedElement(difference.before); |
| 193 continue; | 197 continue; |
| 194 } | 198 } |
| 195 Token diffToken = difference.token; | 199 Token diffToken = difference.token; |
| 196 if (diffToken == null) { | 200 if (diffToken == null) { |
| 197 cannotReuse(difference, "No difference token."); | 201 cannotReuse(difference, "No difference token."); |
| 198 continue; | 202 continue; |
| (...skipping 20 matching lines...) Expand all Loading... |
| 219 assert(!_failedUpdates.isEmpty); | 223 assert(!_failedUpdates.isEmpty); |
| 220 continue; | 224 continue; |
| 221 } | 225 } |
| 222 } | 226 } |
| 223 | 227 |
| 224 return _failedUpdates.isEmpty; | 228 return _failedUpdates.isEmpty; |
| 225 } | 229 } |
| 226 | 230 |
| 227 bool canReuseAddedElement( | 231 bool canReuseAddedElement( |
| 228 PartialElement element, | 232 PartialElement element, |
| 229 ScopeContainerElement container) { | 233 ScopeContainerElement container, |
| 234 ScopeContainerElement syntheticContainer) { |
| 230 if (element is PartialFunctionElement) { | 235 if (element is PartialFunctionElement) { |
| 231 addFunction(element, container); | 236 addFunction(element, container); |
| 232 return true; | 237 return true; |
| 233 } else if (element is PartialClassElement) { | 238 } else if (element is PartialClassElement) { |
| 234 addClass(element, container); | 239 addClass(element, container); |
| 235 return true; | 240 return true; |
| 241 } else if (element is PartialFieldList) { |
| 242 addFields(element, container, syntheticContainer); |
| 243 return true; |
| 236 } | 244 } |
| 237 return cannotReuse(element, "Added element that isn't a function."); | 245 return cannotReuse(element, "Adding ${element.runtimeType} not supported."); |
| 238 } | 246 } |
| 239 | 247 |
| 240 void addFunction( | 248 void addFunction( |
| 241 PartialFunctionElement element, | 249 PartialFunctionElement element, |
| 242 /* ScopeContainerElement */ container) { | 250 /* ScopeContainerElement */ container) { |
| 243 invalidateScopesAffectedBy(element, container); | 251 invalidateScopesAffectedBy(element, container); |
| 244 | 252 |
| 245 updates.add(new AddedFunctionUpdate(compiler, element, container)); | 253 updates.add(new AddedFunctionUpdate(compiler, element, container)); |
| 246 } | 254 } |
| 247 | 255 |
| 248 void addClass( | 256 void addClass( |
| 249 PartialClassElement element, | 257 PartialClassElement element, |
| 250 LibraryElementX library) { | 258 LibraryElementX library) { |
| 251 invalidateScopesAffectedBy(element, library); | 259 invalidateScopesAffectedBy(element, library); |
| 252 | 260 |
| 253 updates.add(new AddedClassUpdate(compiler, element, library)); | 261 updates.add(new AddedClassUpdate(compiler, element, library)); |
| 254 } | 262 } |
| 255 | 263 |
| 264 /// Called when a field in [definition] has changed. |
| 265 /// |
| 266 /// There's no direct link from a [PartialFieldList] to its implied |
| 267 /// [FieldElementX], so instead we use [syntheticContainer], the (synthetic) |
| 268 /// container created by [canReuseLibrary], or [canReuseClass] (through |
| 269 /// [PartialClassElement.parseNode]). This container is scanned looking for |
| 270 /// fields whose declaration site is [definition]. |
| 271 // TODO(ahe): It would be nice if [computeDifference] returned this |
| 272 // information directly. |
| 273 void addFields( |
| 274 PartialFieldList definition, |
| 275 ScopeContainerElement container, |
| 276 ScopeContainerElement syntheticContainer) { |
| 277 List<FieldElementX> fields = <FieldElementX>[]; |
| 278 syntheticContainer.forEachLocalMember((ElementX member) { |
| 279 if (member.declarationSite == definition) { |
| 280 fields.add(member); |
| 281 } |
| 282 }); |
| 283 for (FieldElementX field in fields) { |
| 284 addField(field, container); |
| 285 } |
| 286 } |
| 287 |
| 288 void addField(FieldElementX element, ScopeContainerElement container) { |
| 289 invalidateScopesAffectedBy(element, container); |
| 290 if (!element.isInstanceMember) { |
| 291 cannotReuse(element, "Not an instance field."); |
| 292 } else { |
| 293 addInstanceField(element, container); |
| 294 } |
| 295 } |
| 296 |
| 297 void addInstanceField(FieldElementX element, ClassElementX cls) { |
| 298 _classesWithSchemaChanges.add(cls); |
| 299 |
| 300 updates.add(new AddedFieldUpdate(compiler, element, cls)); |
| 301 } |
| 302 |
| 256 bool canReuseRemovedElement(PartialElement element) { | 303 bool canReuseRemovedElement(PartialElement element) { |
| 257 if (element is PartialFunctionElement) { | 304 if (element is PartialFunctionElement) { |
| 258 removeFunction(element); | 305 removeFunction(element); |
| 259 return true; | 306 return true; |
| 260 } else if (element is PartialClassElement) { | 307 } else if (element is PartialClassElement) { |
| 261 removeClass(element); | 308 removeClass(element); |
| 262 return true; | 309 return true; |
| 263 } | 310 } |
| 264 return cannotReuse(element, "Removed element that isn't a function."); | 311 return cannotReuse(element, "Removed element that isn't a function."); |
| 265 } | 312 } |
| (...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 456 element.ensureResolved(compiler); | 503 element.ensureResolved(compiler); |
| 457 } | 504 } |
| 458 } | 505 } |
| 459 compiler.processQueue(compiler.enqueuer.resolution, null); | 506 compiler.processQueue(compiler.enqueuer.resolution, null); |
| 460 | 507 |
| 461 compiler.phase = Compiler.PHASE_DONE_RESOLVING; | 508 compiler.phase = Compiler.PHASE_DONE_RESOLVING; |
| 462 | 509 |
| 463 // TODO(ahe): Clean this up. Don't call this method in analyze-only mode. | 510 // TODO(ahe): Clean this up. Don't call this method in analyze-only mode. |
| 464 if (compiler.analyzeOnly) return "/* analyze only */"; | 511 if (compiler.analyzeOnly) return "/* analyze only */"; |
| 465 | 512 |
| 466 Set<PartialClassElement> changedClasses = new Set<PartialClassElement>(); | 513 Set<PartialClassElement> changedClasses = |
| 514 new Set<PartialClassElement>.from(_classesWithSchemaChanges); |
| 467 for (Element element in updatedElements) { | 515 for (Element element in updatedElements) { |
| 468 if (!element.isClass) { | 516 if (!element.isClass) { |
| 469 compiler.enqueuer.codegen.addToWorkList(element); | 517 compiler.enqueuer.codegen.addToWorkList(element); |
| 470 } else { | 518 } else { |
| 471 changedClasses.add(element); | 519 changedClasses.add(element); |
| 472 } | 520 } |
| 473 } | 521 } |
| 474 compiler.processQueue(compiler.enqueuer.codegen, null); | 522 compiler.processQueue(compiler.enqueuer.codegen, null); |
| 475 | 523 |
| 476 List<jsAst.Statement> updates = <jsAst.Statement>[]; | 524 List<jsAst.Statement> updates = <jsAst.Statement>[]; |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 880 | 928 |
| 881 PartialClassElement apply() { | 929 PartialClassElement apply() { |
| 882 // TODO(ahe): Reuse compilation unit of element instead? | 930 // TODO(ahe): Reuse compilation unit of element instead? |
| 883 CompilationUnitElementX compilationUnit = library.compilationUnit; | 931 CompilationUnitElementX compilationUnit = library.compilationUnit; |
| 884 PartialClassElement copy = element.copyWithEnclosing(compilationUnit); | 932 PartialClassElement copy = element.copyWithEnclosing(compilationUnit); |
| 885 compilationUnit.addMember(copy, compiler); | 933 compilationUnit.addMember(copy, compiler); |
| 886 return copy; | 934 return copy; |
| 887 } | 935 } |
| 888 } | 936 } |
| 889 | 937 |
| 938 class AddedFieldUpdate extends Update with JsFeatures { |
| 939 final FieldElementX element; |
| 940 |
| 941 final ScopeContainerElement container; |
| 942 |
| 943 AddedFieldUpdate(Compiler compiler, this.element, this.container) |
| 944 : super(compiler); |
| 945 |
| 946 PartialFieldList get before => null; |
| 947 |
| 948 PartialFieldList get after => element.declarationSite; |
| 949 |
| 950 FieldElementX apply() { |
| 951 FieldElementX copy = element.copyWithEnclosing(container); |
| 952 container.addMember(copy, compiler); |
| 953 return copy; |
| 954 } |
| 955 } |
| 956 |
| 957 |
| 890 class ClassUpdate extends Update with JsFeatures { | 958 class ClassUpdate extends Update with JsFeatures { |
| 891 final PartialClassElement before; | 959 final PartialClassElement before; |
| 892 | 960 |
| 893 final PartialClassElement after; | 961 final PartialClassElement after; |
| 894 | 962 |
| 895 ClassUpdate(Compiler compiler, this.before, this.after) | 963 ClassUpdate(Compiler compiler, this.before, this.after) |
| 896 : super(compiler); | 964 : super(compiler); |
| 897 | 965 |
| 898 PartialFunctionElement apply() { | 966 PartialFunctionElement apply() { |
| 899 patchElement(); | 967 patchElement(); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1014 | 1082 |
| 1015 ClassEmitter get classEmitter => backend.emitter.oldEmitter.classEmitter; | 1083 ClassEmitter get classEmitter => backend.emitter.oldEmitter.classEmitter; |
| 1016 | 1084 |
| 1017 List<String> computeFields(ClassElement cls) { | 1085 List<String> computeFields(ClassElement cls) { |
| 1018 // TODO(ahe): Rewrite for new emitter. | 1086 // TODO(ahe): Rewrite for new emitter. |
| 1019 ClassBuilder builder = new ClassBuilder(cls, namer); | 1087 ClassBuilder builder = new ClassBuilder(cls, namer); |
| 1020 classEmitter.emitFields(cls, builder, ""); | 1088 classEmitter.emitFields(cls, builder, ""); |
| 1021 return builder.fields; | 1089 return builder.fields; |
| 1022 } | 1090 } |
| 1023 } | 1091 } |
| OLD | NEW |