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 Script; | 18 Script; |
18 | 19 |
19 import 'package:compiler/src/elements/elements.dart' show | 20 import 'package:compiler/src/elements/elements.dart' show |
20 ClassElement, | 21 ClassElement, |
21 Element, | 22 Element, |
22 FunctionElement, | 23 FunctionElement, |
23 LibraryElement, | 24 LibraryElement, |
24 STATE_NOT_STARTED, | 25 STATE_NOT_STARTED, |
25 ScopeContainerElement; | 26 ScopeContainerElement; |
26 | 27 |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
65 LinkBuilder; | 66 LinkBuilder; |
66 | 67 |
67 import 'package:compiler/src/elements/modelx.dart' show | 68 import 'package:compiler/src/elements/modelx.dart' show |
68 ClassElementX, | 69 ClassElementX, |
69 CompilationUnitElementX, | 70 CompilationUnitElementX, |
70 DeclarationSite, | 71 DeclarationSite, |
71 ElementX, | 72 ElementX, |
72 FieldElementX, | 73 FieldElementX, |
73 LibraryElementX; | 74 LibraryElementX; |
74 | 75 |
| 76 import 'package:compiler/src/universe/universe.dart' show |
| 77 Selector; |
| 78 |
75 import 'diff.dart' show | 79 import 'diff.dart' show |
76 Difference, | 80 Difference, |
77 computeDifference; | 81 computeDifference; |
78 | 82 |
79 typedef void Logger(message); | 83 typedef void Logger(message); |
80 | 84 |
81 typedef bool Reuser( | 85 typedef bool Reuser( |
82 Token diffToken, | 86 Token diffToken, |
83 PartialElement before, | 87 PartialElement before, |
84 PartialElement after); | 88 PartialElement after); |
(...skipping 455 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
540 } | 544 } |
541 | 545 |
542 String computeUpdateJs() { | 546 String computeUpdateJs() { |
543 List<Update> removals = <Update>[]; | 547 List<Update> removals = <Update>[]; |
544 List<Element> updatedElements = applyUpdates(removals); | 548 List<Element> updatedElements = applyUpdates(removals); |
545 if (compiler.progress != null) { | 549 if (compiler.progress != null) { |
546 compiler.progress.reset(); | 550 compiler.progress.reset(); |
547 } | 551 } |
548 for (Element element in updatedElements) { | 552 for (Element element in updatedElements) { |
549 if (!element.isClass) { | 553 if (!element.isClass) { |
550 compiler.enqueuer.resolution.addToWorkList(element); | 554 enqueuer.resolution.addToWorkList(element); |
551 } else { | 555 } else { |
552 NO_WARN(element).ensureResolved(compiler); | 556 NO_WARN(element).ensureResolved(compiler); |
553 } | 557 } |
554 } | 558 } |
555 compiler.processQueue(compiler.enqueuer.resolution, null); | 559 compiler.processQueue(enqueuer.resolution, null); |
556 | 560 |
557 compiler.phase = Compiler.PHASE_DONE_RESOLVING; | 561 compiler.phase = Compiler.PHASE_DONE_RESOLVING; |
558 | 562 |
559 // TODO(ahe): Clean this up. Don't call this method in analyze-only mode. | 563 // TODO(ahe): Clean this up. Don't call this method in analyze-only mode. |
560 if (compiler.analyzeOnly) return "/* analyze only */"; | 564 if (compiler.analyzeOnly) return "/* analyze only */"; |
561 | 565 |
562 Set<ClassElementX> changedClasses = | 566 Set<ClassElementX> changedClasses = |
563 new Set<ClassElementX>.from(_classesWithSchemaChanges); | 567 new Set<ClassElementX>.from(_classesWithSchemaChanges); |
564 for (Element element in updatedElements) { | 568 for (Element element in updatedElements) { |
565 if (!element.isClass) { | 569 if (!element.isClass) { |
566 compiler.enqueuer.codegen.addToWorkList(element); | 570 enqueuer.codegen.addToWorkList(element); |
567 } else { | 571 } else { |
568 changedClasses.add(element); | 572 changedClasses.add(element); |
569 } | 573 } |
570 } | 574 } |
571 compiler.processQueue(compiler.enqueuer.codegen, null); | 575 compiler.processQueue(enqueuer.codegen, null); |
| 576 |
| 577 // Run through all compiled methods and see if they may apply to |
| 578 // newlySeenSelectors. |
| 579 for (Element e in enqueuer.codegen.generatedCode.keys) { |
| 580 if (e.isFunction && !e.isConstructor && |
| 581 e.functionSignature.hasOptionalParameters) { |
| 582 for (Selector selector in enqueuer.codegen.newlySeenSelectors) { |
| 583 // TODO(ahe): Group selectors by name at this point for improved |
| 584 // performance. |
| 585 if (e.isInstanceMember && selector.applies(e, compiler.world)) { |
| 586 // TODO(ahe): Don't use |
| 587 // enqueuer.codegen.newlyEnqueuedElements directly like |
| 588 // this, make a copy. |
| 589 enqueuer.codegen.newlyEnqueuedElements.add(e); |
| 590 } |
| 591 if (selector.name == namer.closureInvocationSelectorName) { |
| 592 selector = new Selector.call( |
| 593 e.name, e.library, |
| 594 selector.argumentCount, selector.namedArguments); |
| 595 if (selector.appliesUnnamed(e, compiler.world)) { |
| 596 // TODO(ahe): Also make a copy here. |
| 597 enqueuer.codegen.newlyEnqueuedElements.add(e); |
| 598 } |
| 599 } |
| 600 } |
| 601 } |
| 602 } |
572 | 603 |
573 List<jsAst.Statement> updates = <jsAst.Statement>[]; | 604 List<jsAst.Statement> updates = <jsAst.Statement>[]; |
574 | 605 |
575 Set newClasses = new Set.from( | 606 // TODO(ahe): allInstantiatedClasses seem to include interfaces that aren't |
| 607 // needed. |
| 608 Set<ClassElementX> newClasses = new Set.from( |
576 compiler.codegenWorld.allInstantiatedClasses.where( | 609 compiler.codegenWorld.allInstantiatedClasses.where( |
577 emitter.computeClassFilter())); | 610 emitter.computeClassFilter())); |
578 newClasses.removeAll(_existingClasses); | 611 newClasses.removeAll(_existingClasses); |
579 | 612 |
| 613 // TODO(ahe): When more than one updated is computed, we need to make sure |
| 614 // that existing classes aren't overwritten. No test except the one test |
| 615 // that tests more than one update is affected by this problem, and only |
| 616 // because main is closurized because we always enable tear-off. Is that |
| 617 // really necessary? Also, add a test which tests directly that what |
| 618 // happens when tear-off is introduced in second update. |
| 619 emitter.neededClasses.addAll(newClasses); |
| 620 |
580 List<jsAst.Statement> inherits = <jsAst.Statement>[]; | 621 List<jsAst.Statement> inherits = <jsAst.Statement>[]; |
581 | 622 |
582 for (ClassElementX cls in newClasses) { | 623 for (ClassElementX cls in newClasses) { |
583 jsAst.Node classAccess = emitter.classAccess(cls); | 624 jsAst.Node classAccess = emitter.classAccess(cls); |
584 String name = namer.getNameOfClass(cls); | 625 String name = namer.getNameOfClass(cls); |
585 | 626 |
586 updates.add( | 627 updates.add( |
587 js.statement( | 628 js.statement( |
588 r'# = #', [classAccess, invokeDefineClass(cls)])); | 629 r'# = #', [classAccess, invokeDefineClass(cls)])); |
589 | 630 |
(...skipping 20 matching lines...) Expand all Loading... |
610 jsAst.Node classAccess = emitter.classAccess(cls); | 651 jsAst.Node classAccess = emitter.classAccess(cls); |
611 updates.add( | 652 updates.add( |
612 js.statement( | 653 js.statement( |
613 r'# = self.$dart_unsafe_eval.schemaChange(#, #, #)', | 654 r'# = self.$dart_unsafe_eval.schemaChange(#, #, #)', |
614 [classAccess, invokeDefineClass(cls), classAccess, superAccess])); | 655 [classAccess, invokeDefineClass(cls), classAccess, superAccess])); |
615 } | 656 } |
616 | 657 |
617 for (RemovalUpdate update in removals) { | 658 for (RemovalUpdate update in removals) { |
618 update.writeUpdateJsOn(updates); | 659 update.writeUpdateJsOn(updates); |
619 } | 660 } |
620 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { | 661 for (Element element in enqueuer.codegen.newlyEnqueuedElements) { |
621 if (!element.isField) { | 662 if (!element.isField) { |
622 updates.add(computeMemberUpdateJs(element)); | 663 updates.add(computeMemberUpdateJs(element)); |
| 664 } else { |
| 665 if (backend.constants.lazyStatics.contains(element)) { |
| 666 throw new StateError("$element requires lazy initializer."); |
| 667 } |
623 } | 668 } |
624 } | 669 } |
625 | 670 |
| 671 updates.add(js.statement(r''' |
| 672 if (self.$dart_unsafe_eval.pendingStubs) { |
| 673 self.$dart_unsafe_eval.pendingStubs.map(function(e) { return e(); }); |
| 674 self.$dart_unsafe_eval.pendingStubs = void 0; |
| 675 } |
| 676 ''')); |
| 677 |
626 if (updates.length == 1) { | 678 if (updates.length == 1) { |
627 return prettyPrintJs(updates.single); | 679 return prettyPrintJs(updates.single); |
628 } else { | 680 } else { |
629 return prettyPrintJs(js.statement('{#}', [updates])); | 681 return prettyPrintJs(js.statement('{#}', [updates])); |
630 } | 682 } |
631 } | 683 } |
632 | 684 |
633 jsAst.Expression invokeDefineClass(ClassElementX cls) { | 685 jsAst.Expression invokeDefineClass(ClassElementX cls) { |
634 String name = namer.getNameOfClass(cls); | 686 String name = namer.getNameOfClass(cls); |
635 var descriptor = js('Object.create(null)'); | 687 var descriptor = js('Object.create(null)'); |
(...skipping 494 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1130 abstract class JsFeatures { | 1182 abstract class JsFeatures { |
1131 Compiler get compiler; | 1183 Compiler get compiler; |
1132 | 1184 |
1133 JavaScriptBackend get backend => compiler.backend; | 1185 JavaScriptBackend get backend => compiler.backend; |
1134 | 1186 |
1135 Namer get namer => backend.namer; | 1187 Namer get namer => backend.namer; |
1136 | 1188 |
1137 CodeEmitterTask get emitter => backend.emitter; | 1189 CodeEmitterTask get emitter => backend.emitter; |
1138 | 1190 |
1139 ContainerBuilder get containerBuilder => emitter.oldEmitter.containerBuilder; | 1191 ContainerBuilder get containerBuilder => emitter.oldEmitter.containerBuilder; |
| 1192 |
| 1193 EnqueueTask get enqueuer => compiler.enqueuer; |
1140 } | 1194 } |
1141 | 1195 |
1142 class EmitterHelper extends JsFeatures { | 1196 class EmitterHelper extends JsFeatures { |
1143 final Compiler compiler; | 1197 final Compiler compiler; |
1144 | 1198 |
1145 EmitterHelper(this.compiler); | 1199 EmitterHelper(this.compiler); |
1146 | 1200 |
1147 ClassEmitter get classEmitter => backend.emitter.oldEmitter.classEmitter; | 1201 ClassEmitter get classEmitter => backend.emitter.oldEmitter.classEmitter; |
1148 | 1202 |
1149 List<String> computeFields(ClassElement cls) { | 1203 List<String> computeFields(ClassElement cls) { |
1150 // TODO(ahe): Rewrite for new emitter. | 1204 // TODO(ahe): Rewrite for new emitter. |
1151 ClassBuilder builder = new ClassBuilder(cls, namer); | 1205 ClassBuilder builder = new ClassBuilder(cls, namer); |
1152 classEmitter.emitFields(cls, builder, ""); | 1206 classEmitter.emitFields(cls, builder, ""); |
1153 return builder.fields; | 1207 return builder.fields; |
1154 } | 1208 } |
1155 } | 1209 } |
1156 | 1210 |
1157 // TODO(ahe): Remove this method. | 1211 // TODO(ahe): Remove this method. |
1158 NO_WARN(x) => x; | 1212 NO_WARN(x) => x; |
OLD | NEW |