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

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

Issue 730423002: Incremental compilation of superclass change. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Add type arguments. Created 6 years, 1 month 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
« no previous file with comments | « no previous file | dart/tests/try/web/incremental_compilation_update_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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
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 Script; 17 Script;
18 18
19 import 'package:compiler/src/elements/elements.dart' show 19 import 'package:compiler/src/elements/elements.dart' show
20 ClassElement, 20 ClassElement,
21 Element, 21 Element,
22 FunctionElement, 22 FunctionElement,
23 LibraryElement, 23 LibraryElement,
24 STATE_NOT_STARTED,
24 ScopeContainerElement; 25 ScopeContainerElement;
25 26
26 import 'package:compiler/src/scanner/scannerlib.dart' show 27 import 'package:compiler/src/scanner/scannerlib.dart' show
27 EOF_TOKEN, 28 EOF_TOKEN,
28 PartialClassElement, 29 PartialClassElement,
29 PartialElement, 30 PartialElement,
30 PartialFunctionElement, 31 PartialFunctionElement,
31 Token; 32 Token;
32 33
33 import 'package:compiler/src/source_file.dart' show 34 import 'package:compiler/src/source_file.dart' show
(...skipping 332 matching lines...) Expand 10 before | Expand all | Expand 10 after
366 PartialClassElement after) { 367 PartialClassElement after) {
367 ClassNode node = after.parseNode(compiler).asClassNode(); 368 ClassNode node = after.parseNode(compiler).asClassNode();
368 if (node == null) { 369 if (node == null) {
369 return cannotReuse(after, "Not a ClassNode: '$node'"); 370 return cannotReuse(after, "Not a ClassNode: '$node'");
370 } 371 }
371 NodeList body = node.body; 372 NodeList body = node.body;
372 if (body == null) { 373 if (body == null) {
373 return cannotReuse(after, "Class has no body."); 374 return cannotReuse(after, "Class has no body.");
374 } 375 }
375 if (isTokenBetween(diffToken, node.beginToken, body.beginToken)) { 376 if (isTokenBetween(diffToken, node.beginToken, body.beginToken)) {
376 return cannotReuse(after, "Class header changed."); 377 logVerbose('Class header modified in ${after}');
378 updates.add(new ClassUpdate(compiler, before, after));
379 before.forEachLocalMember((ElementX member) {
380 // TODO(ahe): Quadratic.
381 invalidateScopesAffectedBy(member, before);
382 });
377 } 383 }
378 logVerbose('Simple modification of ${after} detected');
379 return canReuseScopeContainerElement(before, after); 384 return canReuseScopeContainerElement(before, after);
380 } 385 }
381 386
382 bool isTokenBetween(Token token, Token first, Token last) { 387 bool isTokenBetween(Token token, Token first, Token last) {
383 Token current = first; 388 Token current = first;
384 while (current != last && current.kind != EOF_TOKEN) { 389 while (current != last && current.kind != EOF_TOKEN) {
385 if (current == token) { 390 if (current == token) {
386 return true; 391 return true;
387 } 392 }
388 current = current.next; 393 current = current.next;
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
439 new Set.from(compiler.codegenWorld.directlyInstantiatedClasses); 444 new Set.from(compiler.codegenWorld.directlyInstantiatedClasses);
440 445
441 List<Update> removals = <Update>[]; 446 List<Update> removals = <Update>[];
442 List<Element> updatedElements = applyUpdates(removals); 447 List<Element> updatedElements = applyUpdates(removals);
443 if (compiler.progress != null) { 448 if (compiler.progress != null) {
444 compiler.progress.reset(); 449 compiler.progress.reset();
445 } 450 }
446 for (Element element in updatedElements) { 451 for (Element element in updatedElements) {
447 if (!element.isClass) { 452 if (!element.isClass) {
448 compiler.enqueuer.resolution.addToWorkList(element); 453 compiler.enqueuer.resolution.addToWorkList(element);
454 } else {
455 element.ensureResolved(compiler);
449 } 456 }
450 } 457 }
451 compiler.processQueue(compiler.enqueuer.resolution, null); 458 compiler.processQueue(compiler.enqueuer.resolution, null);
452 459
453 compiler.phase = Compiler.PHASE_DONE_RESOLVING; 460 compiler.phase = Compiler.PHASE_DONE_RESOLVING;
454 461
462 Set<PartialClassElement> changedClasses = new Set<PartialClassElement>();
455 for (Element element in updatedElements) { 463 for (Element element in updatedElements) {
456 if (!element.isClass) { 464 if (!element.isClass) {
457 compiler.enqueuer.codegen.addToWorkList(element); 465 compiler.enqueuer.codegen.addToWorkList(element);
466 } else {
467 changedClasses.add(element);
458 } 468 }
459 } 469 }
460 compiler.processQueue(compiler.enqueuer.codegen, null); 470 compiler.processQueue(compiler.enqueuer.codegen, null);
461 471
462 List<jsAst.Statement> updates = <jsAst.Statement>[]; 472 List<jsAst.Statement> updates = <jsAst.Statement>[];
463 473
464 Set newClasses = 474 Set newClasses =
465 new Set.from(compiler.codegenWorld.directlyInstantiatedClasses); 475 new Set.from(compiler.codegenWorld.directlyInstantiatedClasses);
466 newClasses.removeAll(existingClasses); 476 newClasses.removeAll(existingClasses);
467 477
(...skipping 23 matching lines...) Expand all
491 jsAst.Node superAccess = namer.elementAccess(superclass); 501 jsAst.Node superAccess = namer.elementAccess(superclass);
492 inherits.add( 502 inherits.add(
493 js.statement( 503 js.statement(
494 r'self.$dart_unsafe_eval.inheritFrom(#, #)', 504 r'self.$dart_unsafe_eval.inheritFrom(#, #)',
495 [classAccess, superAccess])); 505 [classAccess, superAccess]));
496 } 506 }
497 } 507 }
498 508
499 updates.addAll(inherits); 509 updates.addAll(inherits);
500 510
511 for (ClassElementX cls in changedClasses) {
512 ClassElement superclass = cls.superclass;
513 if (superclass != null) {
514 jsAst.Node classAccess = namer.elementAccess(cls);
515 jsAst.Node superAccess = namer.elementAccess(superclass);
516 updates.add(
517 js.statement(
518 r'#.prototype.__proto__ = #.prototype',
519 [classAccess, superAccess]));
520 updates.add(
521 js.statement(
522 r'#.prototype.constructor = #',
523 [classAccess, classAccess]));
524 }
525 }
526
501 for (RemovedFunctionUpdate update in removals) { 527 for (RemovedFunctionUpdate update in removals) {
502 update.writeUpdateJsOn(updates); 528 update.writeUpdateJsOn(updates);
503 } 529 }
504 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) { 530 for (Element element in compiler.enqueuer.codegen.newlyEnqueuedElements) {
505 if (!element.isField) { 531 if (!element.isField) {
506 updates.add(computeMemberUpdateJs(element)); 532 updates.add(computeMemberUpdateJs(element));
507 } 533 }
508 } 534 }
509 535
510 if (updates.length == 1) { 536 if (updates.length == 1) {
(...skipping 339 matching lines...) Expand 10 before | Expand all | Expand 10 after
850 876
851 PartialFunctionElement apply() { 877 PartialFunctionElement apply() {
852 // TODO(ahe): Reuse compilation unit of element instead? 878 // TODO(ahe): Reuse compilation unit of element instead?
853 CompilationUnitElementX compilationUnit = library.compilationUnit; 879 CompilationUnitElementX compilationUnit = library.compilationUnit;
854 PartialClassElement copy = element.copyWithEnclosing(compilationUnit); 880 PartialClassElement copy = element.copyWithEnclosing(compilationUnit);
855 compilationUnit.addMember(copy, compiler); 881 compilationUnit.addMember(copy, compiler);
856 return copy; 882 return copy;
857 } 883 }
858 } 884 }
859 885
886 class ClassUpdate extends Update with JsFeatures {
887 final PartialClassElement before;
888
889 final PartialClassElement after;
890
891 ClassUpdate(Compiler compiler, this.before, this.after)
892 : super(compiler);
893
894 PartialFunctionElement apply() {
895 patchElement();
896 reuseElement();
897 return before;
898 }
899
900 /// Destructively change the tokens in [before] to match those of [after].
901 void patchElement() {
902 before.cachedNode = after.cachedNode;
903 before.beginToken = after.beginToken;
904 before.endToken = after.endToken;
905 }
906
907 void reuseElement() {
908 before.supertype = null;
909 before.interfaces = null;
910 before.nativeTagInfo = null;
911 before.supertypeLoadState = STATE_NOT_STARTED;
912 before.resolutionState = STATE_NOT_STARTED;
913 before.isProxy = false;
914 before.hasIncompleteHierarchy = false;
915 before.backendMembers = const Link<Element>();
916 before.allSupertypesAndSelf = null;
917 }
918 }
919
860 /// Returns all qualified names in [element] with less than four identifiers. A 920 /// Returns all qualified names in [element] with less than four identifiers. A
861 /// qualified name is an identifier followed by a sequence of dots and 921 /// qualified name is an identifier followed by a sequence of dots and
862 /// identifiers, for example, "x", and "x.y.z". But not "x.y.z.w" ("w" is the 922 /// identifiers, for example, "x", and "x.y.z". But not "x.y.z.w" ("w" is the
863 /// fourth identifier). 923 /// fourth identifier).
864 /// 924 ///
865 /// The longest possible name that can be resolved is three identifiers, for 925 /// The longest possible name that can be resolved is three identifiers, for
866 /// example, "prefix.MyClass.staticMethod". Since four or more identifiers 926 /// example, "prefix.MyClass.staticMethod". Since four or more identifiers
867 /// cannot resolve to anything statically, they're not included in the returned 927 /// cannot resolve to anything statically, they're not included in the returned
868 /// value of this method. 928 /// value of this method.
869 Set<String> qualifiedNamesIn(PartialElement element) { 929 Set<String> qualifiedNamesIn(PartialElement element) {
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after
950 1010
951 ClassEmitter get classEmitter => backend.emitter.oldEmitter.classEmitter; 1011 ClassEmitter get classEmitter => backend.emitter.oldEmitter.classEmitter;
952 1012
953 List<String> computeFields(ClassElement cls) { 1013 List<String> computeFields(ClassElement cls) {
954 // TODO(ahe): Rewrite for new emitter. 1014 // TODO(ahe): Rewrite for new emitter.
955 ClassBuilder builder = new ClassBuilder(cls, namer); 1015 ClassBuilder builder = new ClassBuilder(cls, namer);
956 classEmitter.emitFields(cls, builder, ""); 1016 classEmitter.emitFields(cls, builder, "");
957 return builder.fields; 1017 return builder.fields;
958 } 1018 }
959 } 1019 }
OLDNEW
« no previous file with comments | « no previous file | dart/tests/try/web/incremental_compilation_update_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698