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

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

Powered by Google App Engine
This is Rietveld 408576698