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

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

Issue 594843003: Introduce LibraryUpdater. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Address Johnni's comments. Created 6 years, 2 months 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/site/try/poi/poi.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 library dart2js_incremental.library_updater;
6
7 import 'dart:async' show
8 Future;
9
10 import 'dart:convert' show
11 UTF8;
12
13 import 'package:compiler/compiler.dart' as api;
14
15 import 'package:compiler/implementation/dart2jslib.dart' show
16 Compiler,
17 Script;
18
19 import 'package:compiler/implementation/elements/elements.dart' show
20 LibraryElement;
21
22 import 'package:compiler/implementation/scanner/scannerlib.dart' show
23 EOF_TOKEN,
24 PartialElement,
25 PartialFunctionElement,
26 Token;
27
28 import 'package:compiler/implementation/source_file.dart' show
29 StringSourceFile;
30
31 import 'package:compiler/implementation/tree/tree.dart' show
32 FunctionExpression;
33
34 import 'diff.dart' show
35 Difference,
36 computeDifference;
37
38 typedef void Logger(message);
39
40 // TODO(ahe): Generalize this class. For now only works for Compiler.mainApp,
41 // and only if that library has exactly one compilation unit.
42 class LibraryUpdater {
43 final Compiler compiler;
44
45 final api.CompilerInputProvider inputProvider;
46
47 final Logger logTime;
48
49 final Logger logVerbose;
50
51 // TODO(ahe): Get rid of this field. It assumes that only one library has
52 // changed.
53 final Uri uri;
54
55 final List<Update> updates = <Update>[];
56
57 LibraryUpdater(
58 this.compiler,
59 this.inputProvider,
60 this.uri,
61 this.logTime,
62 this.logVerbose);
63
64 /// Used as tear-off passed to [LibraryLoaderTask.resetAsync].
65 Future<bool> reuseLibrary(LibraryElement library) {
66 assert(compiler != null);
67 if (library.isPlatformLibrary || library.isPackageLibrary) {
68 logTime('Reusing $library.');
69 return new Future.value(true);
70 } else if (library != compiler.mainApp) {
71 return new Future.value(false);
72 }
73 return inputProvider(uri).then((List<int> bytes) {
74 if (canReuseLibrary(library, bytes)) {
75 // TODO(ahe): Temporary. Since we don't yet apply the updates, the
76 // library cannot be reused if there are updates.
77 return updates.isEmpty;
78 } else {
79 return false;
80 }
81 });
82 }
83
84 /// Returns true if [library] can be reused.
85 ///
86 /// This methods also computes the [updates] (patches) needed to have
87 /// [library] reflect the modifications in [bytes].
88 bool canReuseLibrary(LibraryElement library, List<int> bytes) {
89 logTime('Attempting to reuse mainApp.');
90 String newSource = UTF8.decode(bytes);
91 logTime('Decoded UTF8');
92
93 // TODO(ahe): Can't use compiler.mainApp in general.
94 if (false && newSource == compiler.mainApp.compilationUnit.script.text) {
95 // TODO(ahe): Need to update the compilationUnit's source code when
96 // doing incremental analysis for this to work.
97 logTime("Source didn't change");
98 return true;
99 }
100
101 logTime("Source did change");
102 Script sourceScript = new Script(
103 uri, uri, new StringSourceFile('$uri', newSource));
104 var dartPrivacyIsBroken = compiler.libraryLoader;
105 LibraryElement newLibrary = dartPrivacyIsBroken.createLibrarySync(
106 null, sourceScript, uri);
107 logTime('New library synthesized.');
108 List<Difference> differences = computeDifference(library, newLibrary);
109 logTime('Differences computed.');
110 for (Difference difference in differences) {
111 logTime('Looking at difference: $difference');
112 if (difference.before == null || difference.after == null) {
113 logVerbose('Scope changed in $difference');
114 // Scope changed, don't reuse library.
115 return false;
116 }
117 Token diffToken = difference.token;
118 if (diffToken == null) {
119 logVerbose('No token stored in difference.');
120 return false;
121 }
122 if (difference.after is! PartialElement &&
123 difference.before is! PartialElement) {
124 logVerbose('Not a PartialElement: $difference');
125 // Don't know how to recompile element.
126 return false;
127 }
128 PartialElement before = difference.before;
129 PartialElement after = difference.after;
130
131 if (before is PartialFunctionElement && after is PartialFunctionElement) {
132 if (!canReuseFunction(diffToken, before, after)) {
133 return false;
134 }
135 } else {
136 // Unhandled kind of element.
137 return false;
138 }
139 }
140
141 return true;
142 }
143
144 /// Returns true if function [before] can be reused to reflect the changes in
145 /// [after].
146 ///
147 /// If [before] can be reused, an update (patch) is added to [updates].
148 bool canReuseFunction(
149 Token diffToken,
150 PartialFunctionElement before,
151 PartialFunctionElement after) {
152 FunctionExpression node =
153 after.parseNode(compiler).asFunctionExpression();
154 if (node == null) {
155 print('Not a function expression.');
156 return false;
157 }
158 Token last = after.endToken;
159 if (node.body != null) {
160 last = node.body.getBeginToken();
161 }
162 Token token = after.beginToken;
163 while (token != last && token.kind != EOF_TOKEN) {
164 if (token == diffToken) {
165 logVerbose('Signature changed');
166 return false;
167 }
168 token = token.next;
169 }
170 print('Simple modification of ${after} detected');
171 updates.add(new FunctionUpdate(compiler, before, after));
172 return true;
173 }
174 }
175
176 /// Represents an update (aka patch) of [before] to [after]. We use the word
177 /// "update" to avoid confusion with the compiler feature of "patch" methods.
178 abstract class Update {
179 final Compiler compiler;
180
181 PartialElement get before;
182
183 PartialElement get after;
184
185 Update(this.compiler);
186 }
187
188 /// Represents an update of a function element.
189 class FunctionUpdate extends Update {
190 final PartialFunctionElement before;
191
192 final PartialFunctionElement after;
193
194 FunctionUpdate(Compiler compiler, this.before, this.after)
195 : super(compiler);
196 }
OLDNEW
« no previous file with comments | « no previous file | dart/site/try/poi/poi.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698