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

Side by Side Diff: dart/pkg/dart2js_incremental/lib/library_updater.dart

Issue 732083002: Implement adding methods. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Merged with r41885 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
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
55 55
56 import 'package:compiler/src/js_backend/js_backend.dart' show 56 import 'package:compiler/src/js_backend/js_backend.dart' show
57 JavaScriptBackend, 57 JavaScriptBackend,
58 Namer; 58 Namer;
59 59
60 import 'package:compiler/src/util/util.dart' show 60 import 'package:compiler/src/util/util.dart' show
61 Link, 61 Link,
62 LinkBuilder; 62 LinkBuilder;
63 63
64 import 'package:compiler/src/elements/modelx.dart' show 64 import 'package:compiler/src/elements/modelx.dart' show
65 ClassElementX,
65 DeclarationSite, 66 DeclarationSite,
66 ElementX; 67 ElementX,
68 LibraryElementX;
67 69
68 import 'diff.dart' show 70 import 'diff.dart' show
69 Difference, 71 Difference,
70 computeDifference; 72 computeDifference;
71 73
72 typedef void Logger(message); 74 typedef void Logger(message);
73 75
74 typedef bool Reuser( 76 typedef bool Reuser(
75 Token diffToken, 77 Token diffToken,
76 PartialElement before, 78 PartialElement before,
(...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after
174 176
175 bool canReuseScopeContainerElement( 177 bool canReuseScopeContainerElement(
176 ScopeContainerElement element, 178 ScopeContainerElement element,
177 ScopeContainerElement newElement) { 179 ScopeContainerElement newElement) {
178 List<Difference> differences = computeDifference(element, newElement); 180 List<Difference> differences = computeDifference(element, newElement);
179 logTime('Differences computed.'); 181 logTime('Differences computed.');
180 for (Difference difference in differences) { 182 for (Difference difference in differences) {
181 logTime('Looking at difference: $difference'); 183 logTime('Looking at difference: $difference');
182 184
183 if (difference.before == null && difference.after is PartialElement) { 185 if (difference.before == null && difference.after is PartialElement) {
184 canReuseAddedElement(difference.after); 186 canReuseAddedElement(difference.after, element);
185 continue; 187 continue;
186 } 188 }
187 if (difference.after == null && difference.before is PartialElement) { 189 if (difference.after == null && difference.before is PartialElement) {
188 canReuseRemovedElement(difference.before); 190 canReuseRemovedElement(difference.before);
189 continue; 191 continue;
190 } 192 }
191 Token diffToken = difference.token; 193 Token diffToken = difference.token;
192 if (diffToken == null) { 194 if (diffToken == null) {
193 cannotReuse(difference, "No difference token."); 195 cannotReuse(difference, "No difference token.");
194 continue; 196 continue;
(...skipping 18 matching lines...) Expand all
213 } 215 }
214 if (!reuser(diffToken, before, after)) { 216 if (!reuser(diffToken, before, after)) {
215 assert(!_failedUpdates.isEmpty); 217 assert(!_failedUpdates.isEmpty);
216 continue; 218 continue;
217 } 219 }
218 } 220 }
219 221
220 return _failedUpdates.isEmpty; 222 return _failedUpdates.isEmpty;
221 } 223 }
222 224
223 bool canReuseAddedElement(PartialElement element) { 225 bool canReuseAddedElement(
224 return cannotReuse(element, "Scope changed, element added."); 226 PartialElement element,
227 ScopeContainerElement container) {
228 if (element is PartialFunctionElement) {
229 addFunction(element, container);
230 return true;
231 }
232 return cannotReuse(element, "Added element that isn't a function.");
233 }
234
235 void addFunction(
236 PartialFunctionElement element,
237 ScopeContainerElement container) {
238 invalidateScopesAffectedBy(element, container);
239
240 updates.add(new AddedFunctionUpdate(compiler, element, container));
225 } 241 }
226 242
227 bool canReuseRemovedElement(PartialElement element) { 243 bool canReuseRemovedElement(PartialElement element) {
228 if (element is PartialFunctionElement) { 244 if (element is PartialFunctionElement) {
229 return canReuseRemovedFunction(element); 245 removeFunction(element);
246 return true;
230 } 247 }
231 return cannotReuse( 248 return cannotReuse(element, "Removed element that isn't a function.");
232 element, "Removed element that isn't a method.");
233 } 249 }
234 250
235 bool canReuseRemovedFunction(PartialFunctionElement element) { 251 void removeFunction(PartialFunctionElement element) {
236 logVerbose("Removed method $element."); 252 logVerbose("Removed method $element.");
237 253
238 ScopeContainerElement container = element.enclosingElement; 254 invalidateScopesAffectedBy(element, element.enclosingElement);
255
256 _removedElements.add(element);
257
258 updates.add(new RemovedFunctionUpdate(compiler, element));
259 }
260
261 void invalidateScopesAffectedBy(
262 ElementX element,
263 ScopeContainerElement container) {
239 for (ScopeContainerElement scope in scopesAffectedBy(element, container)) { 264 for (ScopeContainerElement scope in scopesAffectedBy(element, container)) {
240 scanSites(scope, (Element member, DeclarationSite site) { 265 scanSites(scope, (Element member, DeclarationSite site) {
241 // TODO(ahe): Cache qualifiedNamesIn to avoid quadratic behavior. 266 // TODO(ahe): Cache qualifiedNamesIn to avoid quadratic behavior.
242 Map<String, List<String>> names = qualifiedNamesIn(site); 267 Map<String, List<String>> names = qualifiedNamesIn(site);
243 if (canNamesResolveStaticallyTo(names, element, container)) { 268 if (canNamesResolveStaticallyTo(names, element, container)) {
244 _elementsToInvalidate.add(member); 269 _elementsToInvalidate.add(member);
245 } 270 }
246 }); 271 });
247 } 272 }
248
249 _removedElements.add(element);
250
251 updates.add(new RemovedFunctionUpdate(compiler, element));
252
253 return true;
254 } 273 }
255 274
256 /// Invoke [f] on each [DeclarationSite] in [element]. If [element] is a 275 /// Invoke [f] on each [DeclarationSite] in [element]. If [element] is a
257 /// [ScopeContainerElement], invoke f on all local members as well. 276 /// [ScopeContainerElement], invoke f on all local members as well.
258 void scanSites( 277 void scanSites(
259 Element element, 278 Element element,
260 void f(ElementX element, DeclarationSite site)) { 279 void f(ElementX element, DeclarationSite site)) {
261 DeclarationSite site = declarationSite(element); 280 DeclarationSite site = declarationSite(element);
262 if (site != null) { 281 if (site != null) {
263 f(element, site); 282 f(element, site);
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
298 FunctionExpression node = 317 FunctionExpression node =
299 after.parseNode(compiler).asFunctionExpression(); 318 after.parseNode(compiler).asFunctionExpression();
300 if (node == null) { 319 if (node == null) {
301 return cannotReuse(after, "Not a function expression: '$node'"); 320 return cannotReuse(after, "Not a function expression: '$node'");
302 } 321 }
303 Token last = after.endToken; 322 Token last = after.endToken;
304 if (node.body != null) { 323 if (node.body != null) {
305 last = node.body.getBeginToken(); 324 last = node.body.getBeginToken();
306 } 325 }
307 if (isTokenBetween(diffToken, after.beginToken, last)) { 326 if (isTokenBetween(diffToken, after.beginToken, last)) {
308 return cannotReuse(after, 'Signature changed.'); 327 removeFunction(before);
328 addFunction(after, before.enclosingElement);
329 return true;
309 } 330 }
310 logVerbose('Simple modification of ${after} detected'); 331 logVerbose('Simple modification of ${after} detected');
311 updates.add(new FunctionUpdate(compiler, before, after)); 332 updates.add(new FunctionUpdate(compiler, before, after));
312 return true; 333 return true;
313 } 334 }
314 335
315 bool canReuseClass( 336 bool canReuseClass(
316 Token diffToken, 337 Token diffToken,
317 PartialClassElement before, 338 PartialClassElement before,
318 PartialClassElement after) { 339 PartialClassElement after) {
(...skipping 120 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 jsAst.Node superAccess = namer.elementAccess(superclass); 460 jsAst.Node superAccess = namer.elementAccess(superclass);
440 inherits.add( 461 inherits.add(
441 js.statement( 462 js.statement(
442 r'self.$dart_unsafe_eval.inheritFrom(#, #)', 463 r'self.$dart_unsafe_eval.inheritFrom(#, #)',
443 [classAccess, superAccess])); 464 [classAccess, superAccess]));
444 } 465 }
445 } 466 }
446 467
447 updates.addAll(inherits); 468 updates.addAll(inherits);
448 469
470 for (RemovedFunctionUpdate update in removals) {
471 update.writeUpdateJsOn(updates);
472 }
449 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { 473 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) {
450 if (!element.isField) { 474 if (!element.isField) {
451 updates.add(computeMemberUpdateJs(element)); 475 updates.add(computeMemberUpdateJs(element));
452 } 476 }
453 } 477 }
454 for (RemovedFunctionUpdate update in removals) {
455 update.writeUpdateJsOn(updates);
456 }
457 478
458 if (updates.length == 1) { 479 if (updates.length == 1) {
459 return prettyPrintJs(updates.single); 480 return prettyPrintJs(updates.single);
460 } else { 481 } else {
461 return prettyPrintJs(js.statement('{#}', [updates])); 482 return prettyPrintJs(js.statement('{#}', [updates]));
462 } 483 }
463 } 484 }
464 485
465 jsAst.Node computeMemberUpdateJs(Element element) { 486 jsAst.Node computeMemberUpdateJs(Element element) {
466 MemberInfo info = emitter.oldEmitter.containerBuilder 487 MemberInfo info = emitter.oldEmitter.containerBuilder
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after
527 abstract class Update { 548 abstract class Update {
528 final Compiler compiler; 549 final Compiler compiler;
529 550
530 PartialElement get before; 551 PartialElement get before;
531 552
532 PartialElement get after; 553 PartialElement get after;
533 554
534 Update(this.compiler); 555 Update(this.compiler);
535 556
536 /// Applies the update to [before] and returns that element. 557 /// Applies the update to [before] and returns that element.
537 PartialElement apply(); 558 Element apply();
538 559
539 bool get isRemoval => false; 560 bool get isRemoval => false;
540 561
541 /// Called before any patches are applied to capture any state that is needed 562 /// Called before any patches are applied to capture any state that is needed
542 /// later. 563 /// later.
543 void captureState() { 564 void captureState() {
544 } 565 }
545 } 566 }
546 567
547 /// Represents an update of a function element. 568 /// Represents an update of a function element.
(...skipping 13 matching lines...) Expand all
561 582
562 /// Destructively change the tokens in [before] to match those of [after]. 583 /// Destructively change the tokens in [before] to match those of [after].
563 void patchElement() { 584 void patchElement() {
564 before.beginToken = after.beginToken; 585 before.beginToken = after.beginToken;
565 before.endToken = after.endToken; 586 before.endToken = after.endToken;
566 before.getOrSet = after.getOrSet; 587 before.getOrSet = after.getOrSet;
567 } 588 }
568 } 589 }
569 590
570 abstract class ReuseFunction { 591 abstract class ReuseFunction {
592 Compiler get compiler;
593
571 PartialFunctionElement get before; 594 PartialFunctionElement get before;
572 595
573 /// Reset various caches and remove this element from the compiler's internal 596 /// Reset various caches and remove this element from the compiler's internal
574 /// state. 597 /// state.
575 void reuseElement() { 598 void reuseElement() {
576 compiler.forgetElement(before); 599 compiler.forgetElement(before);
577 before.reuseElement(); 600 before.reuseElement();
578 } 601 }
579 } 602 }
580 603
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
613 if (backend.isAliasedSuperMember(element)) { 636 if (backend.isAliasedSuperMember(element)) {
614 superName = namer.getNameOfAliasedSuperMember(element); 637 superName = namer.getNameOfAliasedSuperMember(element);
615 } 638 }
616 } else { 639 } else {
617 elementAccess = namer.elementAccess(element); 640 elementAccess = namer.elementAccess(element);
618 } 641 }
619 642
620 wasStateCaptured = true; 643 wasStateCaptured = true;
621 } 644 }
622 645
623 PartialElement apply() { 646 PartialFunctionElement apply() {
624 if (!wasStateCaptured) throw "captureState must be called before apply."; 647 if (!wasStateCaptured) throw "captureState must be called before apply.";
625 removeFromEnclosing(); 648 removeFromEnclosing();
626 reuseElement(); 649 reuseElement();
627 return null; 650 return null;
628 } 651 }
629 652
630 void removeFromEnclosing() { 653 void removeFromEnclosing() {
631 PartialClassElement cls = element.enclosingClass; 654 PartialClassElement cls = element.enclosingClass;
632 if (cls == null) { 655 if (cls == null) {
633 removeFromLibrary(element.library); 656 removeFromLibrary(element.library);
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
676 if (superName != null) { 699 if (superName != null) {
677 updates.add( 700 updates.add(
678 js.statement('delete #.prototype.#', [elementAccess, superName])); 701 js.statement('delete #.prototype.#', [elementAccess, superName]));
679 } 702 }
680 } else { 703 } else {
681 updates.add(js.statement('delete #', [elementAccess])); 704 updates.add(js.statement('delete #', [elementAccess]));
682 } 705 }
683 } 706 }
684 } 707 }
685 708
709 class AddedFunctionUpdate extends Update with JsFeatures {
710 final PartialFunctionElement element;
711
712 final ScopeContainerElement container;
713
714 AddedFunctionUpdate(Compiler compiler, this.element, this.container)
715 : super(compiler) {
716 if (container == null) {
717 throw "container is null";
718 }
719 }
720
721 PartialFunctionElement get before => null;
722
723 PartialElement get after => element;
724
725 PartialFunctionElement apply() {
726 Element enclosing = container;
727 if (enclosing.isLibrary) {
728 // TODO(ahe): Reuse compilation unit instead?
729 enclosing = enclosing.compilationUnit;
730 }
731 PartialFunctionElement copy = element.copyWithEnclosing(enclosing);
732 container.addMember(copy, compiler);
733 return copy;
734 }
735 }
736
686 /// Returns all qualified names in [element] with less than four identifiers. A 737 /// Returns all qualified names in [element] with less than four identifiers. A
687 /// qualified name is an identifier followed by a sequence of dots and 738 /// qualified name is an identifier followed by a sequence of dots and
688 /// identifiers, for example, "x", and "x.y.z". But not "x.y.z.w" ("w" is the 739 /// identifiers, for example, "x", and "x.y.z". But not "x.y.z.w" ("w" is the
689 /// fourth identifier). 740 /// fourth identifier).
690 /// 741 ///
691 /// The longest possible name that can be resolved is three identifiers, for 742 /// The longest possible name that can be resolved is three identifiers, for
692 /// example, "prefix.MyClass.staticMethod". Since four or more identifiers 743 /// example, "prefix.MyClass.staticMethod". Since four or more identifiers
693 /// cannot resolve to anything statically, they're not included in the returned 744 /// cannot resolve to anything statically, they're not included in the returned
694 /// value of this method. 745 /// value of this method.
695 Set<String> qualifiedNamesIn(PartialElement element) { 746 Set<String> qualifiedNamesIn(PartialElement element) {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
776 827
777 ClassEmitter get classEmitter => backend.emitter.oldEmitter.classEmitter; 828 ClassEmitter get classEmitter => backend.emitter.oldEmitter.classEmitter;
778 829
779 List<String> computeFields(ClassElement cls) { 830 List<String> computeFields(ClassElement cls) {
780 // TODO(ahe): Rewrite for new emitter. 831 // TODO(ahe): Rewrite for new emitter.
781 ClassBuilder builder = new ClassBuilder(cls, namer); 832 ClassBuilder builder = new ClassBuilder(cls, namer);
782 classEmitter.emitFields(cls, builder, ""); 833 classEmitter.emitFields(cls, builder, "");
783 return builder.fields; 834 return builder.fields;
784 } 835 }
785 } 836 }
OLDNEW
« no previous file with comments | « dart/pkg/compiler/lib/src/scanner/listener.dart ('k') | dart/tests/try/web/incremental_compilation_update_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698