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

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

Issue 659813002: Apply updates to static methods. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Fix types. 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
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/implementation/dart2jslib.dart' show 15 import 'package:compiler/implementation/dart2jslib.dart' show
16 Compiler, 16 Compiler,
17 Script; 17 Script;
18 18
19 import 'package:compiler/implementation/elements/elements.dart' show 19 import 'package:compiler/implementation/elements/elements.dart' show
20 Element, 20 Element,
21 FunctionElement, 21 FunctionElement,
22 LibraryElement; 22 LibraryElement,
23 ScopeContainerElement;
23 24
24 import 'package:compiler/implementation/scanner/scannerlib.dart' show 25 import 'package:compiler/implementation/scanner/scannerlib.dart' show
25 EOF_TOKEN, 26 EOF_TOKEN,
27 PartialClassElement,
26 PartialElement, 28 PartialElement,
27 PartialFunctionElement, 29 PartialFunctionElement,
28 Token; 30 Token;
29 31
30 import 'package:compiler/implementation/source_file.dart' show 32 import 'package:compiler/implementation/source_file.dart' show
31 StringSourceFile; 33 StringSourceFile;
32 34
33 import 'package:compiler/implementation/tree/tree.dart' show 35 import 'package:compiler/implementation/tree/tree.dart' show
34 FunctionExpression; 36 ClassNode,
37 FunctionExpression,
38 NodeList;
35 39
36 import 'package:compiler/implementation/js/js.dart' show 40 import 'package:compiler/implementation/js/js.dart' show
37 js; 41 js;
38 42
39 import 'package:compiler/implementation/js/js.dart' as jsAst; 43 import 'package:compiler/implementation/js/js.dart' as jsAst;
40 44
41 import 'package:compiler/implementation/js_emitter/js_emitter.dart' show 45 import 'package:compiler/implementation/js_emitter/js_emitter.dart' show
42 CodeEmitterTask, 46 CodeEmitterTask,
43 MemberInfo; 47 MemberInfo;
44 48
45 import 'package:compiler/js_lib/shared/embedded_names.dart' as embeddedNames; 49 import 'package:compiler/js_lib/shared/embedded_names.dart' as embeddedNames;
46 50
47 import 'package:compiler/implementation/js_backend/js_backend.dart' show 51 import 'package:compiler/implementation/js_backend/js_backend.dart' show
48 JavaScriptBackend, 52 JavaScriptBackend,
49 Namer; 53 Namer;
50 54
51 import 'diff.dart' show 55 import 'diff.dart' show
52 Difference, 56 Difference,
53 computeDifference; 57 computeDifference;
54 58
55 typedef void Logger(message); 59 typedef void Logger(message);
56 60
61 typedef bool Reuser(
62 Token diffToken,
63 PartialElement before,
64 PartialElement after);
65
57 // TODO(ahe): Generalize this class. For now only works for Compiler.mainApp, 66 // TODO(ahe): Generalize this class. For now only works for Compiler.mainApp,
58 // and only if that library has exactly one compilation unit. 67 // and only if that library has exactly one compilation unit.
59 class LibraryUpdater { 68 class LibraryUpdater {
60 final Compiler compiler; 69 final Compiler compiler;
61 70
62 final api.CompilerInputProvider inputProvider; 71 final api.CompilerInputProvider inputProvider;
63 72
64 final Logger logTime; 73 final Logger logTime;
65 74
66 final Logger logVerbose; 75 final Logger logVerbose;
67 76
68 // TODO(ahe): Get rid of this field. It assumes that only one library has 77 // TODO(ahe): Get rid of this field. It assumes that only one library has
69 // changed. 78 // changed.
70 final Uri uri; 79 final Uri uri;
71 80
72 // When [true], updates must be applied (using [applyUpdates]) before the 81 // When [true], updates must be applied (using [applyUpdates]) before the
73 // [compiler]'s state correctly reflects the updated program. 82 // [compiler]'s state correctly reflects the updated program.
74 bool hasPendingUpdates = false; 83 bool hasPendingUpdates = false;
75 84
85 bool onlySimpleUpdates = true;
86
76 final List<Update> updates = <Update>[]; 87 final List<Update> updates = <Update>[];
77 88
78 LibraryUpdater( 89 LibraryUpdater(
79 this.compiler, 90 this.compiler,
80 this.inputProvider, 91 this.inputProvider,
81 this.uri, 92 this.uri,
82 this.logTime, 93 this.logTime,
83 this.logVerbose); 94 this.logVerbose);
84 95
85 JavaScriptBackend get backend => compiler.backend; 96 JavaScriptBackend get backend => compiler.backend;
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after
119 return true; 130 return true;
120 } 131 }
121 132
122 logTime("Source did change"); 133 logTime("Source did change");
123 Script sourceScript = new Script( 134 Script sourceScript = new Script(
124 uri, uri, new StringSourceFile('$uri', newSource)); 135 uri, uri, new StringSourceFile('$uri', newSource));
125 var dartPrivacyIsBroken = compiler.libraryLoader; 136 var dartPrivacyIsBroken = compiler.libraryLoader;
126 LibraryElement newLibrary = dartPrivacyIsBroken.createLibrarySync( 137 LibraryElement newLibrary = dartPrivacyIsBroken.createLibrarySync(
127 null, sourceScript, uri); 138 null, sourceScript, uri);
128 logTime('New library synthesized.'); 139 logTime('New library synthesized.');
129 List<Difference> differences = computeDifference(library, newLibrary); 140 return canReuseScopeContainerElement(library, newLibrary);
141 }
142
143 bool canReuseScopeContainerElement(
144 ScopeContainerElement element,
145 ScopeContainerElement newElement) {
146 List<Difference> differences = computeDifference(element, newElement);
130 logTime('Differences computed.'); 147 logTime('Differences computed.');
131 for (Difference difference in differences) { 148 for (Difference difference in differences) {
132 logTime('Looking at difference: $difference'); 149 logTime('Looking at difference: $difference');
133 if (difference.before == null || difference.after == null) { 150 if (difference.before == null || difference.after == null) {
134 logVerbose('Scope changed in $difference'); 151 logVerbose('Scope changed in $difference');
135 // Scope changed, don't reuse library. 152 // Scope changed, don't reuse library.
153 onlySimpleUpdates = false;
136 return false; 154 return false;
137 } 155 }
138 Token diffToken = difference.token; 156 Token diffToken = difference.token;
139 if (diffToken == null) { 157 if (diffToken == null) {
140 logVerbose('No token stored in difference.'); 158 logVerbose('No token stored in difference.');
159 onlySimpleUpdates = false;
141 return false; 160 return false;
142 } 161 }
143 if (difference.after is! PartialElement && 162 if (difference.after is! PartialElement &&
144 difference.before is! PartialElement) { 163 difference.before is! PartialElement) {
145 logVerbose('Not a PartialElement: $difference'); 164 logVerbose('Not a PartialElement: $difference');
146 // Don't know how to recompile element. 165 // Don't know how to recompile element.
166 onlySimpleUpdates = false;
147 return false; 167 return false;
148 } 168 }
149 PartialElement before = difference.before; 169 PartialElement before = difference.before;
150 PartialElement after = difference.after; 170 PartialElement after = difference.after;
151 171
172 Reuser reuser;
173
152 if (before is PartialFunctionElement && after is PartialFunctionElement) { 174 if (before is PartialFunctionElement && after is PartialFunctionElement) {
153 if (!canReuseFunction(diffToken, before, after)) { 175 reuser = canReuseFunction;
154 return false; 176 } else if (before is PartialClassElement &&
155 } 177 after is PartialClassElement) {
178 reuser = canReuseClass;
156 } else { 179 } else {
157 // Unhandled kind of element. 180 reuser = cannotReuse;
181 }
182 if (!reuser(diffToken, before, after)) {
183 onlySimpleUpdates = false;
158 return false; 184 return false;
159 } 185 }
160 } 186 }
161 hasPendingUpdates = true; 187 hasPendingUpdates = true;
162 188
163 return true; 189 return true;
164 } 190 }
165 191
166 /// Returns true if function [before] can be reused to reflect the changes in 192 /// Returns true if function [before] can be reused to reflect the changes in
167 /// [after]. 193 /// [after].
168 /// 194 ///
169 /// If [before] can be reused, an update (patch) is added to [updates]. 195 /// If [before] can be reused, an update (patch) is added to [updates].
170 bool canReuseFunction( 196 bool canReuseFunction(
171 Token diffToken, 197 Token diffToken,
172 PartialFunctionElement before, 198 PartialFunctionElement before,
173 PartialFunctionElement after) { 199 PartialFunctionElement after) {
174 FunctionExpression node = 200 FunctionExpression node =
175 after.parseNode(compiler).asFunctionExpression(); 201 after.parseNode(compiler).asFunctionExpression();
176 if (node == null) { 202 if (node == null) {
177 print('Not a function expression.'); 203 logVerbose('Not a function expression.');
178 return false; 204 return false;
179 } 205 }
180 Token last = after.endToken; 206 Token last = after.endToken;
181 if (node.body != null) { 207 if (node.body != null) {
182 last = node.body.getBeginToken(); 208 last = node.body.getBeginToken();
183 } 209 }
184 Token token = after.beginToken; 210 if (isTokenBetween(diffToken, after.beginToken, last)) {
185 while (token != last && token.kind != EOF_TOKEN) { 211 logVerbose('Signature changed.');
186 if (token == diffToken) { 212 return false;
187 logVerbose('Signature changed');
188 return false;
189 }
190 token = token.next;
191 } 213 }
192 print('Simple modification of ${after} detected'); 214 logVerbose('Simple modification of ${after} detected');
193 updates.add(new FunctionUpdate(compiler, before, after)); 215 updates.add(new FunctionUpdate(compiler, before, after));
194 return true; 216 return true;
195 } 217 }
196 218
219 bool canReuseClass(
220 Token diffToken,
221 PartialClassElement before,
222 PartialClassElement after) {
223 ClassNode node = after.parseNode(compiler).asClassNode();
224 if (node == null) {
225 logVerbose('Not a ClassNode.');
226 return false;
227 }
228 NodeList body = node.body;
229 if (body == null) {
230 logVerbose('Class has no body.');
231 return false;
232 }
233 if (isTokenBetween(diffToken, node.beginToken, body.beginToken)) {
234 logVerbose('Class header changed.');
235 return false;
236 }
237 logVerbose('Simple modification of ${after} detected');
238 return canReuseScopeContainerElement(before, after);
239 }
240
241 bool isTokenBetween(Token token, Token first, Token last) {
242 Token current = first;
243 while (current != last && current.kind != EOF_TOKEN) {
244 if (current == token) {
245 return true;
246 }
247 current = current.next;
248 }
249 return false;
250 }
251
252 bool cannotReuse(
253 Token diffToken,
254 PartialElement before,
255 PartialElement after) {
256 logVerbose(
257 'Unhandled change:'
258 ' ${before} (${before.runtimeType} -> ${after.runtimeType}).');
259 return false;
260 }
261
197 List<Element> applyUpdates() { 262 List<Element> applyUpdates() {
263 if (!onlySimpleUpdates) {
264 throw new StateError("Can't compute update.");
265 }
198 return updates.map((Update update) => update.apply()).toList(); 266 return updates.map((Update update) => update.apply()).toList();
199 } 267 }
200 268
201 String computeUpdateJs() { 269 String computeUpdateJs() {
202 List<Element> updatedElements = applyUpdates(); 270 List<Element> updatedElements = applyUpdates();
203 if (compiler.progress != null) { 271 if (compiler.progress != null) {
204 compiler.progress.reset(); 272 compiler.progress.reset();
205 } 273 }
206 for (Element element in updatedElements) { 274 for (Element element in updatedElements) {
207 compiler.enqueuer.resolution.addToWorkList(element); 275 compiler.enqueuer.resolution.addToWorkList(element);
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after
310 before.getOrSet = after.getOrSet; 378 before.getOrSet = after.getOrSet;
311 } 379 }
312 380
313 /// Reset various caches and remove this element from the compiler's internal 381 /// Reset various caches and remove this element from the compiler's internal
314 /// state. 382 /// state.
315 void reuseElement() { 383 void reuseElement() {
316 compiler.forgetElement(before); 384 compiler.forgetElement(before);
317 before.reuseElement(); 385 before.reuseElement();
318 } 386 }
319 } 387 }
OLDNEW
« no previous file with comments | « dart/pkg/dart2js_incremental/lib/diff.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