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 804903004: Refactor LibraryUpdater to prepare for parts. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: 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
« no previous file with comments | « dart/pkg/dart2js_incremental/lib/dart2js_incremental.dart ('k') | 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
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 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
76 import 'package:compiler/src/universe/universe.dart' show 76 import 'package:compiler/src/universe/universe.dart' show
77 Selector; 77 Selector;
78 78
79 import 'package:compiler/src/constants/values.dart' show 79 import 'package:compiler/src/constants/values.dart' show
80 ConstantValue; 80 ConstantValue;
81 81
82 import 'diff.dart' show 82 import 'diff.dart' show
83 Difference, 83 Difference,
84 computeDifference; 84 computeDifference;
85 85
86 import 'dart2js_incremental.dart' show
87 IncrementalCompiler;
88
86 typedef void Logger(message); 89 typedef void Logger(message);
87 90
88 typedef bool Reuser( 91 typedef bool Reuser(
89 Token diffToken, 92 Token diffToken,
90 PartialElement before, 93 PartialElement before,
91 PartialElement after); 94 PartialElement after);
92 95
93 class FailedUpdate { 96 class FailedUpdate {
94 /// Either an [Element] or a [Difference]. 97 /// Either an [Element] or a [Difference].
95 final context; 98 final context;
96 final String message; 99 final String message;
97 100
98 FailedUpdate(this.context, this.message); 101 FailedUpdate(this.context, this.message);
99 102
100 String toString() { 103 String toString() {
101 if (context == null) return '$message'; 104 if (context == null) return '$message';
102 return 'In $context:\n $message'; 105 return 'In $context:\n $message';
103 } 106 }
104 } 107 }
105 108
106 // TODO(ahe): Generalize this class. For now only works for Compiler.mainApp, 109 abstract class _IncrementalCompilerContext {
107 // and only if that library has exactly one compilation unit. 110 IncrementalCompiler incrementalCompiler;
111
112 Set<ClassElementX> _emittedClasses;
113
114 Set<ClassElementX> _directlyInstantiatedClasses;
115
116 Set<ConstantValue> _compiledConstants;
117 }
118
119 class IncrementalCompilerContext extends _IncrementalCompilerContext {
120 final Set<Uri> _uriWithUpdates = new Set<Uri>();
121
122 void set incrementalCompiler(IncrementalCompiler value) {
123 if (super.incrementalCompiler != null) {
124 throw new StateError("Can't set [incrementalCompiler] more than once.");
125 }
Johnni Winther 2014/12/16 11:22:52 You need to do super.incrementalCompiler = value
ahe 2014/12/16 12:04:31 Done.
126 }
127
128 void registerUriWithUpdates(Iterable<Uri> uris) {
129 _uriWithUpdates.addAll(uris);
130 }
131
132 void _captureState(Compiler compiler) {
133 _emittedClasses = new Set.from(compiler.backend.emitter.neededClasses);
134
135 _directlyInstantiatedClasses =
136 new Set.from(compiler.codegenWorld.directlyInstantiatedClasses);
137
138 List<ConstantValue> constants =
139 compiler.backend.emitter.outputConstantLists[
140 compiler.deferredLoadTask.mainOutputUnit];
141 if (constants == null) constants = <ConstantValue>[];
142 _compiledConstants = new Set<ConstantValue>.identity()..addAll(constants);
143 }
144
145 bool _uriHasUpdate(Uri uri) => _uriWithUpdates.contains(uri);
146 }
147
108 class LibraryUpdater extends JsFeatures { 148 class LibraryUpdater extends JsFeatures {
109 final Compiler compiler; 149 final Compiler compiler;
110 150
111 final api.CompilerInputProvider inputProvider; 151 final api.CompilerInputProvider inputProvider;
112 152
113 final Logger logTime; 153 final Logger logTime;
114 154
115 final Logger logVerbose; 155 final Logger logVerbose;
116 156
117 // TODO(ahe): Get rid of this field. It assumes that only one library has
118 // changed.
119 final Uri uri;
120
121 final List<Update> updates = <Update>[]; 157 final List<Update> updates = <Update>[];
122 158
123 final List<FailedUpdate> _failedUpdates = <FailedUpdate>[]; 159 final List<FailedUpdate> _failedUpdates = <FailedUpdate>[];
124 160
125 final Set<ElementX> _elementsToInvalidate = new Set<ElementX>(); 161 final Set<ElementX> _elementsToInvalidate = new Set<ElementX>();
126 162
127 final Set<ElementX> _removedElements = new Set<ElementX>(); 163 final Set<ElementX> _removedElements = new Set<ElementX>();
128 164
129 final Set<ClassElementX> _classesWithSchemaChanges = 165 final Set<ClassElementX> _classesWithSchemaChanges =
130 new Set<ClassElementX>(); 166 new Set<ClassElementX>();
131 167
132 final Set<ClassElementX> _emittedClasses; 168 final IncrementalCompilerContext _context;
133
134 final Set<ClassElementX> _directlyInstantiatedClasses;
135
136 final Set<ConstantValue> _compiledConstants;
137 169
138 bool _hasComputedNeeds = false; 170 bool _hasComputedNeeds = false;
139 171
172 bool _hasCapturedCompilerState = false;
173
140 LibraryUpdater( 174 LibraryUpdater(
141 Compiler compiler, 175 this.compiler,
142 this.inputProvider, 176 this.inputProvider,
143 this.uri,
144 this.logTime, 177 this.logTime,
145 this.logVerbose) 178 this.logVerbose,
146 : this.compiler = compiler, 179 this._context) {
147 _emittedClasses = _getEmittedClasses(compiler), 180 // TODO(ahe): Would like to remove this from the constructor. However, the
148 _directlyInstantiatedClasses = 181 // state must be captured before calling [reuseCompiler].
149 _getDirectlyInstantiatedClasses(compiler), 182 // Proper solution might be: [reuseCompiler] should not clear the sets that
150 _compiledConstants = _getEmittedConstants(compiler); 183 // are captured in [IncrementalCompilerContext._captureState].
184 _ensureCompilerStateCaptured();
185 }
151 186
152 /// Returns the classes emitted by [compiler]. 187 /// Returns the classes emitted by [compiler].
153 static Set<ClassElementX> _getEmittedClasses(Compiler compiler) { 188 Set<ClassElementX> get _emittedClasses => _context._emittedClasses;
154 if (compiler == null) return null;
155 return new Set.from(compiler.backend.emitter.neededClasses);
156 }
157 189
158 /// Returns the directly instantantiated classes seen by [compiler]. 190 /// Returns the directly instantantiated classes seen by [compiler] (this
159 static Set<ClassElementX> _getDirectlyInstantiatedClasses(Compiler compiler) { 191 /// includes interfaces and may be different from [_emittedClasses] that only
160 if (compiler == null) return null; 192 /// includes interfaces used in type tests).
161 return new Set.from(compiler.codegenWorld.directlyInstantiatedClasses); 193 Set<ClassElementX> get _directlyInstantiatedClasses {
194 return _context._directlyInstantiatedClasses;
162 } 195 }
163 196
164 /// Returns the constants emitted by [compiler]. 197 /// Returns the constants emitted by [compiler].
165 static Set<ConstantValue> _getEmittedConstants(Compiler compiler) { 198 Set<ConstantValue> get _compiledConstants => _context._compiledConstants;
166 if (compiler != null) {
167 List<ConstantValue> constants =
168 compiler.backend.emitter.outputConstantLists[
169 compiler.deferredLoadTask.mainOutputUnit];
170 if (constants != null) {
171 return new Set<ConstantValue>.identity()..addAll(constants);
172 }
173 }
174 return null;
175 }
176 199
177 /// When [true], updates must be applied (using [applyUpdates]) before the 200 /// When [true], updates must be applied (using [applyUpdates]) before the
178 /// [compiler]'s state correctly reflects the updated program. 201 /// [compiler]'s state correctly reflects the updated program.
179 bool get hasPendingUpdates => !updates.isEmpty; 202 bool get hasPendingUpdates => !updates.isEmpty;
180 203
181 bool get failed => !_failedUpdates.isEmpty; 204 bool get failed => !_failedUpdates.isEmpty;
182 205
183 /// Used as tear-off passed to [LibraryLoaderTask.resetAsync]. 206 /// Used as tear-off passed to [LibraryLoaderTask.resetAsync].
184 Future<bool> reuseLibrary(LibraryElement library) { 207 Future<bool> reuseLibrary(LibraryElement library) {
208 _ensureCompilerStateCaptured();
185 assert(compiler != null); 209 assert(compiler != null);
186 if (library.isPlatformLibrary || library.isPackageLibrary) { 210 if (library.isPlatformLibrary) {
187 logTime('Reusing $library.'); 211 logTime('Reusing $library (assumed read-only).');
188 return new Future.value(true); 212 return new Future.value(true);
189 } else if (library != compiler.mainApp) {
190 return new Future.value(false);
191 } 213 }
192 return inputProvider(uri).then((bytes) { 214 for (CompilationUnitElementX unit in library.compilationUnits) {
193 return canReuseLibrary(library, bytes); 215 Uri uri = unit.script.resourceUri;
194 }); 216 if (_context._uriHasUpdate(uri)) {
217 if (!library.compilationUnits.tail.isEmpty) {
218 // TODO(ahe): Remove this restriction.
219 cannotReuse(library, "Multiple compilation units not supported.");
220 return new Future.value(true);
221 }
222 return inputProvider(uri).then((bytes) {
223 return canReuseLibrary(library, bytes);
224 });
225 }
226 }
227
228 logTime("Reusing $library, source didn't change.");
229 // Source code of [library] wasn't changed.
230 return new Future.value(true);
231 }
232
233 void _ensureCompilerStateCaptured() {
234 // TODO(ahe): [compiler] shouldn't be null, remove the following line.
235 if (compiler == null) return;
236
237 if (_hasCapturedCompilerState) return;
238 _context._captureState(compiler);
239 _hasCapturedCompilerState = true;
195 } 240 }
196 241
197 /// Returns true if [library] can be reused. 242 /// Returns true if [library] can be reused.
198 /// 243 ///
199 /// This methods also computes the [updates] (patches) needed to have 244 /// This methods also computes the [updates] (patches) needed to have
200 /// [library] reflect the modifications in [bytes]. 245 /// [library] reflect the modifications in [bytes].
201 bool canReuseLibrary(LibraryElement library, bytes) { 246 bool canReuseLibrary(LibraryElement library, bytes) {
202 logTime('Attempting to reuse mainApp.'); 247 logTime('Attempting to reuse ${library}.');
203 String newSource = bytes is String ? bytes : UTF8.decode(bytes); 248 String newSource = bytes is String ? bytes : UTF8.decode(bytes);
204 logTime('Decoded UTF8'); 249 logTime('Decoded UTF8');
205 250
206 // TODO(ahe): Can't use compiler.mainApp in general. 251 Uri uri = library.entryCompilationUnit.script.resourceUri;
207 if (false && newSource == compiler.mainApp.compilationUnit.script.text) {
208 // TODO(ahe): Need to update the compilationUnit's source code when
209 // doing incremental analysis for this to work.
210 logTime("Source didn't change");
211 return true;
212 }
213
214 logTime("Source did change");
215 Script sourceScript = new Script( 252 Script sourceScript = new Script(
216 uri, uri, new StringSourceFile('$uri', newSource)); 253 uri, uri, new StringSourceFile('$uri', newSource));
217 var dartPrivacyIsBroken = compiler.libraryLoader; 254 var dartPrivacyIsBroken = compiler.libraryLoader;
218 LibraryElement newLibrary = dartPrivacyIsBroken.createLibrarySync( 255 LibraryElement newLibrary = dartPrivacyIsBroken.createLibrarySync(
219 null, sourceScript, uri); 256 null, sourceScript, uri);
220 logTime('New library synthesized.'); 257 logTime('New library synthesized.');
221 return canReuseScopeContainerElement(library, newLibrary); 258 return canReuseScopeContainerElement(library, newLibrary);
222 } 259 }
223 260
224 bool cannotReuse(context, String message) { 261 bool cannotReuse(context, String message) {
(...skipping 1070 matching lines...) Expand 10 before | Expand all | Expand 10 after
1295 List<String> computeFields(ClassElement cls) { 1332 List<String> computeFields(ClassElement cls) {
1296 // TODO(ahe): Rewrite for new emitter. 1333 // TODO(ahe): Rewrite for new emitter.
1297 ClassBuilder builder = new ClassBuilder(cls, namer); 1334 ClassBuilder builder = new ClassBuilder(cls, namer);
1298 classEmitter.emitFields(cls, builder); 1335 classEmitter.emitFields(cls, builder);
1299 return builder.fields; 1336 return builder.fields;
1300 } 1337 }
1301 } 1338 }
1302 1339
1303 // TODO(ahe): Remove this method. 1340 // TODO(ahe): Remove this method.
1304 NO_WARN(x) => x; 1341 NO_WARN(x) => x;
OLDNEW
« no previous file with comments | « dart/pkg/dart2js_incremental/lib/dart2js_incremental.dart ('k') | dart/site/try/poi/poi.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698