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 |
| (...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 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 108 final Uri uri; | 109 final Uri uri; |
| 109 | 110 |
| 110 final List<Update> updates = <Update>[]; | 111 final List<Update> updates = <Update>[]; |
| 111 | 112 |
| 112 final List<FailedUpdate> _failedUpdates = <FailedUpdate>[]; | 113 final List<FailedUpdate> _failedUpdates = <FailedUpdate>[]; |
| 113 | 114 |
| 114 final Set<ElementX> _elementsToInvalidate = new Set<ElementX>(); | 115 final Set<ElementX> _elementsToInvalidate = new Set<ElementX>(); |
| 115 | 116 |
| 116 final Set<ElementX> _removedElements = new Set<ElementX>(); | 117 final Set<ElementX> _removedElements = new Set<ElementX>(); |
| 117 | 118 |
| 119 final Set<ClassElementX> _classesWithSchemaChanges = | |
| 120 new Set<ClassElementX>(); | |
| 121 | |
| 118 LibraryUpdater( | 122 LibraryUpdater( |
| 119 this.compiler, | 123 this.compiler, |
| 120 this.inputProvider, | 124 this.inputProvider, |
| 121 this.uri, | 125 this.uri, |
| 122 this.logTime, | 126 this.logTime, |
| 123 this.logVerbose); | 127 this.logVerbose); |
| 124 | 128 |
| 125 /// When [true], updates must be applied (using [applyUpdates]) before the | 129 /// When [true], updates must be applied (using [applyUpdates]) before the |
| 126 /// [compiler]'s state correctly reflects the updated program. | 130 /// [compiler]'s state correctly reflects the updated program. |
| 127 bool get hasPendingUpdates => !updates.isEmpty; | 131 bool get hasPendingUpdates => !updates.isEmpty; |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 177 | 181 |
| 178 bool canReuseScopeContainerElement( | 182 bool canReuseScopeContainerElement( |
| 179 ScopeContainerElement element, | 183 ScopeContainerElement element, |
| 180 ScopeContainerElement newElement) { | 184 ScopeContainerElement newElement) { |
| 181 List<Difference> differences = computeDifference(element, newElement); | 185 List<Difference> differences = computeDifference(element, newElement); |
| 182 logTime('Differences computed.'); | 186 logTime('Differences computed.'); |
| 183 for (Difference difference in differences) { | 187 for (Difference difference in differences) { |
| 184 logTime('Looking at difference: $difference'); | 188 logTime('Looking at difference: $difference'); |
| 185 | 189 |
| 186 if (difference.before == null && difference.after is PartialElement) { | 190 if (difference.before == null && difference.after is PartialElement) { |
| 187 canReuseAddedElement(difference.after, element); | 191 canReuseAddedElement(difference.after, element, newElement); |
| 188 continue; | 192 continue; |
| 189 } | 193 } |
| 190 if (difference.after == null && difference.before is PartialElement) { | 194 if (difference.after == null && difference.before is PartialElement) { |
| 191 canReuseRemovedElement(difference.before); | 195 canReuseRemovedElement(difference.before); |
| 192 continue; | 196 continue; |
| 193 } | 197 } |
| 194 Token diffToken = difference.token; | 198 Token diffToken = difference.token; |
| 195 if (diffToken == null) { | 199 if (diffToken == null) { |
| 196 cannotReuse(difference, "No difference token."); | 200 cannotReuse(difference, "No difference token."); |
| 197 continue; | 201 continue; |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 218 assert(!_failedUpdates.isEmpty); | 222 assert(!_failedUpdates.isEmpty); |
| 219 continue; | 223 continue; |
| 220 } | 224 } |
| 221 } | 225 } |
| 222 | 226 |
| 223 return _failedUpdates.isEmpty; | 227 return _failedUpdates.isEmpty; |
| 224 } | 228 } |
| 225 | 229 |
| 226 bool canReuseAddedElement( | 230 bool canReuseAddedElement( |
| 227 PartialElement element, | 231 PartialElement element, |
| 228 ScopeContainerElement container) { | 232 ScopeContainerElement container, |
| 233 ScopeContainerElement syntheticContainer) { | |
| 229 if (element is PartialFunctionElement) { | 234 if (element is PartialFunctionElement) { |
| 230 addFunction(element, container); | 235 addFunction(element, container); |
| 231 return true; | 236 return true; |
| 232 } else if (element is PartialClassElement) { | 237 } else if (element is PartialClassElement) { |
| 233 addClass(element, container); | 238 addClass(element, container); |
| 234 return true; | 239 return true; |
| 240 } else if (element is PartialFieldList) { | |
| 241 addFields(element, container, syntheticContainer); | |
| 242 return true; | |
| 235 } | 243 } |
| 236 return cannotReuse(element, "Added element that isn't a function."); | 244 return cannotReuse(element, "Adding ${element.runtimeType} not supported."); |
| 237 } | 245 } |
| 238 | 246 |
| 239 void addFunction( | 247 void addFunction( |
| 240 PartialFunctionElement element, | 248 PartialFunctionElement element, |
| 241 ScopeContainerElement container) { | 249 ScopeContainerElement container) { |
| 242 invalidateScopesAffectedBy(element, container); | 250 invalidateScopesAffectedBy(element, container); |
| 243 | 251 |
| 244 updates.add(new AddedFunctionUpdate(compiler, element, container)); | 252 updates.add(new AddedFunctionUpdate(compiler, element, container)); |
| 245 } | 253 } |
| 246 | 254 |
| 247 void addClass( | 255 void addClass( |
| 248 PartialClassElement element, | 256 PartialClassElement element, |
| 249 LibraryElementX library) { | 257 LibraryElementX library) { |
| 250 invalidateScopesAffectedBy(element, library); | 258 invalidateScopesAffectedBy(element, library); |
| 251 | 259 |
| 252 updates.add(new AddedClassUpdate(compiler, element, library)); | 260 updates.add(new AddedClassUpdate(compiler, element, library)); |
| 253 } | 261 } |
| 254 | 262 |
| 263 void addFields( | |
|
Johnni Winther
2014/11/21 14:23:05
Add documentation, especially for [syntheticContai
ahe
2014/11/21 15:48:47
Done, added:
/// Called when a field in [defini
| |
| 264 PartialFieldList definition, | |
| 265 ScopeContainerElement container, | |
| 266 ScopeContainerElement syntheticContainer) { | |
| 267 List<FieldElementX> fields = <FieldElementX>[]; | |
| 268 syntheticContainer.forEachLocalMember((ElementX member) { | |
| 269 if (member.declarationSite == definition) { | |
| 270 fields.add(member); | |
| 271 } | |
| 272 }); | |
| 273 for (FieldElementX field in fields) { | |
| 274 addField(field, container); | |
| 275 } | |
| 276 } | |
| 277 | |
| 278 void addField(FieldElementX element, ScopeContainerElement container) { | |
| 279 invalidateScopesAffectedBy(element, container); | |
| 280 if (!element.isInstanceMember) { | |
| 281 cannotReuse(element, "Not an instance field."); | |
| 282 } else { | |
| 283 addInstanceField(element, container); | |
| 284 } | |
| 285 } | |
| 286 | |
| 287 void addInstanceField(FieldElementX element, ClassElementX cls) { | |
| 288 _classesWithSchemaChanges.add(cls); | |
| 289 | |
| 290 updates.add(new AddedFieldUpdate(compiler, element, cls)); | |
| 291 } | |
| 292 | |
| 255 bool canReuseRemovedElement(PartialElement element) { | 293 bool canReuseRemovedElement(PartialElement element) { |
| 256 if (element is PartialFunctionElement) { | 294 if (element is PartialFunctionElement) { |
| 257 removeFunction(element); | 295 removeFunction(element); |
| 258 return true; | 296 return true; |
| 259 } else if (element is PartialClassElement) { | 297 } else if (element is PartialClassElement) { |
| 260 removeClass(element); | 298 removeClass(element); |
| 261 return true; | 299 return true; |
| 262 } | 300 } |
| 263 return cannotReuse(element, "Removed element that isn't a function."); | 301 return cannotReuse(element, "Removed element that isn't a function."); |
| 264 } | 302 } |
| (...skipping 187 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 452 if (!element.isClass) { | 490 if (!element.isClass) { |
| 453 compiler.enqueuer.resolution.addToWorkList(element); | 491 compiler.enqueuer.resolution.addToWorkList(element); |
| 454 } else { | 492 } else { |
| 455 element.ensureResolved(compiler); | 493 element.ensureResolved(compiler); |
| 456 } | 494 } |
| 457 } | 495 } |
| 458 compiler.processQueue(compiler.enqueuer.resolution, null); | 496 compiler.processQueue(compiler.enqueuer.resolution, null); |
| 459 | 497 |
| 460 compiler.phase = Compiler.PHASE_DONE_RESOLVING; | 498 compiler.phase = Compiler.PHASE_DONE_RESOLVING; |
| 461 | 499 |
| 462 Set<PartialClassElement> changedClasses = new Set<PartialClassElement>(); | 500 Set<PartialClassElement> changedClasses = |
| 501 new Set<PartialClassElement>.from(_classesWithSchemaChanges); | |
| 463 for (Element element in updatedElements) { | 502 for (Element element in updatedElements) { |
| 464 if (!element.isClass) { | 503 if (!element.isClass) { |
| 465 compiler.enqueuer.codegen.addToWorkList(element); | 504 compiler.enqueuer.codegen.addToWorkList(element); |
| 466 } else { | 505 } else { |
| 467 changedClasses.add(element); | 506 changedClasses.add(element); |
| 468 } | 507 } |
| 469 } | 508 } |
| 470 compiler.processQueue(compiler.enqueuer.codegen, null); | 509 compiler.processQueue(compiler.enqueuer.codegen, null); |
| 471 | 510 |
| 472 List<jsAst.Statement> updates = <jsAst.Statement>[]; | 511 List<jsAst.Statement> updates = <jsAst.Statement>[]; |
| (...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 876 | 915 |
| 877 PartialFunctionElement apply() { | 916 PartialFunctionElement apply() { |
| 878 // TODO(ahe): Reuse compilation unit of element instead? | 917 // TODO(ahe): Reuse compilation unit of element instead? |
| 879 CompilationUnitElementX compilationUnit = library.compilationUnit; | 918 CompilationUnitElementX compilationUnit = library.compilationUnit; |
| 880 PartialClassElement copy = element.copyWithEnclosing(compilationUnit); | 919 PartialClassElement copy = element.copyWithEnclosing(compilationUnit); |
| 881 compilationUnit.addMember(copy, compiler); | 920 compilationUnit.addMember(copy, compiler); |
| 882 return copy; | 921 return copy; |
| 883 } | 922 } |
| 884 } | 923 } |
| 885 | 924 |
| 925 class AddedFieldUpdate extends Update with JsFeatures { | |
| 926 final FieldElementX element; | |
| 927 | |
| 928 final ScopeContainerElement container; | |
| 929 | |
| 930 AddedFieldUpdate(Compiler compiler, this.element, this.container) | |
| 931 : super(compiler); | |
| 932 | |
| 933 PartialFieldList get before => null; | |
| 934 | |
| 935 PartialFieldList get after => element.declarationSite; | |
| 936 | |
| 937 FieldElementX apply() { | |
| 938 FieldElementX copy = element.copyWithEnclosing(container); | |
| 939 container.addMember(copy, compiler); | |
| 940 return copy; | |
| 941 } | |
| 942 } | |
| 943 | |
| 944 | |
| 886 class ClassUpdate extends Update with JsFeatures { | 945 class ClassUpdate extends Update with JsFeatures { |
| 887 final PartialClassElement before; | 946 final PartialClassElement before; |
| 888 | 947 |
| 889 final PartialClassElement after; | 948 final PartialClassElement after; |
| 890 | 949 |
| 891 ClassUpdate(Compiler compiler, this.before, this.after) | 950 ClassUpdate(Compiler compiler, this.before, this.after) |
| 892 : super(compiler); | 951 : super(compiler); |
| 893 | 952 |
| 894 PartialFunctionElement apply() { | 953 PartialFunctionElement apply() { |
| 895 patchElement(); | 954 patchElement(); |
| (...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1010 | 1069 |
| 1011 ClassEmitter get classEmitter => backend.emitter.oldEmitter.classEmitter; | 1070 ClassEmitter get classEmitter => backend.emitter.oldEmitter.classEmitter; |
| 1012 | 1071 |
| 1013 List<String> computeFields(ClassElement cls) { | 1072 List<String> computeFields(ClassElement cls) { |
| 1014 // TODO(ahe): Rewrite for new emitter. | 1073 // TODO(ahe): Rewrite for new emitter. |
| 1015 ClassBuilder builder = new ClassBuilder(cls, namer); | 1074 ClassBuilder builder = new ClassBuilder(cls, namer); |
| 1016 classEmitter.emitFields(cls, builder, ""); | 1075 classEmitter.emitFields(cls, builder, ""); |
| 1017 return builder.fields; | 1076 return builder.fields; |
| 1018 } | 1077 } |
| 1019 } | 1078 } |
| OLD | NEW |