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

Side by Side Diff: pkg/compiler/lib/src/native/enqueue.dart

Issue 2782503003: Extract NativeClassResolver from NativeResolutionEnqueuer (Closed)
Patch Set: Remove unused getter. Created 3 years, 8 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
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend.dart ('k') | pkg/compiler/lib/src/native/resolver.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 import 'package:front_end/src/fasta/scanner.dart' show BeginGroupToken, Token;
6 import 'package:front_end/src/fasta/scanner.dart' as Tokens show EOF_TOKEN;
7
8 import '../common.dart'; 5 import '../common.dart';
9 import '../common/backend_api.dart'; 6 import '../common/backend_api.dart';
10 import '../common/resolution.dart' show Resolution; 7 import '../common/resolution.dart' show Resolution;
11 import '../compiler.dart' show Compiler; 8 import '../compiler.dart' show Compiler;
12 import '../common_elements.dart' show CommonElements; 9 import '../common_elements.dart' show CommonElements;
13 import '../elements/elements.dart'; 10 import '../elements/elements.dart';
14 import '../elements/entities.dart'; 11 import '../elements/entities.dart';
15 import '../elements/resolution_types.dart'; 12 import '../elements/resolution_types.dart';
16 import '../elements/types.dart'; 13 import '../elements/types.dart';
17 import '../js_backend/backend_helpers.dart' show BackendHelpers; 14 import '../js_backend/backend_helpers.dart' show BackendHelpers;
18 import '../js_backend/backend_usage.dart' show BackendUsageBuilder; 15 import '../js_backend/backend_usage.dart' show BackendUsageBuilder;
19 import '../js_backend/js_backend.dart'; 16 import '../js_backend/js_backend.dart';
20 import '../js_backend/native_data.dart' show NativeBasicData, NativeData; 17 import '../js_backend/native_data.dart' show NativeBasicData, NativeData;
21 import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter; 18 import '../js_emitter/js_emitter.dart' show CodeEmitterTask, NativeEmitter;
22 import '../universe/use.dart' show StaticUse, TypeUse; 19 import '../universe/use.dart' show StaticUse, TypeUse;
23 import '../universe/world_impact.dart' 20 import '../universe/world_impact.dart'
24 show WorldImpact, WorldImpactBuilder, WorldImpactBuilderImpl; 21 show WorldImpact, WorldImpactBuilder, WorldImpactBuilderImpl;
25 import 'behavior.dart'; 22 import 'behavior.dart';
23 import 'resolver.dart' show NativeClassResolver;
26 24
27 /** 25 /**
28 * This could be an abstract class but we use it as a stub for the dart_backend. 26 * This could be an abstract class but we use it as a stub for the dart_backend.
29 */ 27 */
30 class NativeEnqueuer { 28 class NativeEnqueuer {
31 /// Called when a [type] has been instantiated natively. 29 /// Called when a [type] has been instantiated natively.
32 void onInstantiatedType(InterfaceType type) {} 30 void onInstantiatedType(InterfaceType type) {}
33 31
34 /// Initial entry point to native enqueuer. 32 /// Initial entry point to native enqueuer.
35 WorldImpact processNativeClasses(Iterable<LibraryElement> libraries) => 33 WorldImpact processNativeClasses(Iterable<LibraryElement> libraries) =>
(...skipping 23 matching lines...) Expand all
59 /// Subclasses of [NativeEnqueuerBase] are constructed by the backend. 57 /// Subclasses of [NativeEnqueuerBase] are constructed by the backend.
60 NativeEnqueuerBase(this._compiler, this.enableLiveTypeAnalysis); 58 NativeEnqueuerBase(this._compiler, this.enableLiveTypeAnalysis);
61 59
62 JavaScriptBackend get _backend => _compiler.backend; 60 JavaScriptBackend get _backend => _compiler.backend;
63 BackendHelpers get _helpers => _backend.helpers; 61 BackendHelpers get _helpers => _backend.helpers;
64 Resolution get _resolution => _compiler.resolution; 62 Resolution get _resolution => _compiler.resolution;
65 63
66 DiagnosticReporter get _reporter => _compiler.reporter; 64 DiagnosticReporter get _reporter => _compiler.reporter;
67 CommonElements get _commonElements => _compiler.commonElements; 65 CommonElements get _commonElements => _compiler.commonElements;
68 66
69 NativeBasicData get _nativeBasicData => _backend.nativeBasicData;
70
71 BackendClasses get _backendClasses => _backend.backendClasses; 67 BackendClasses get _backendClasses => _backend.backendClasses;
72 68
73 void onInstantiatedType(InterfaceType type) { 69 void onInstantiatedType(InterfaceType type) {
74 if (_unusedClasses.remove(type.element)) { 70 if (_unusedClasses.remove(type.element)) {
75 _registeredClasses.add(type.element); 71 _registeredClasses.add(type.element);
76 } 72 }
77 } 73 }
78 74
79 /// Register [classes] as natively instantiated in [impactBuilder]. 75 /// Register [classes] as natively instantiated in [impactBuilder].
80 void _registerTypeUses( 76 void _registerTypeUses(
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
180 // TODO(sra): Annotate exception classes in dart:html. 176 // TODO(sra): Annotate exception classes in dart:html.
181 String name = classElement.name; 177 String name = classElement.name;
182 if (name.contains('Exception')) return true; 178 if (name.contains('Exception')) return true;
183 if (name.contains('Error')) return true; 179 if (name.contains('Error')) return true;
184 return false; 180 return false;
185 }); 181 });
186 } 182 }
187 } 183 }
188 184
189 class NativeResolutionEnqueuer extends NativeEnqueuerBase { 185 class NativeResolutionEnqueuer extends NativeEnqueuerBase {
186 final NativeClassResolver _nativeClassResolver;
187
190 /// The set of all native classes. Each native class is in [nativeClasses] 188 /// The set of all native classes. Each native class is in [nativeClasses]
191 /// and exactly one of [unusedClasses] and [registeredClasses]. 189 /// and exactly one of [unusedClasses] and [registeredClasses].
192 final Set<ClassElement> _nativeClasses = new Set<ClassElement>(); 190 final Set<ClassElement> _nativeClasses = new Set<ClassElement>();
193 191
194 Map<String, ClassElement> tagOwner = new Map<String, ClassElement>(); 192 NativeResolutionEnqueuer(Compiler compiler, this._nativeClassResolver)
195
196 NativeResolutionEnqueuer(Compiler compiler)
197 : super(compiler, compiler.options.enableNativeLiveTypeAnalysis); 193 : super(compiler, compiler.options.enableNativeLiveTypeAnalysis);
198 194
199 BackendUsageBuilder get _backendUsageBuilder => _backend.backendUsageBuilder; 195 BackendUsageBuilder get _backendUsageBuilder => _backend.backendUsageBuilder;
200 196
201 void _registerBackendUse(FunctionEntity element) { 197 void _registerBackendUse(FunctionEntity element) {
202 _backendUsageBuilder.registerBackendFunctionUse(element); 198 _backendUsageBuilder.registerBackendFunctionUse(element);
203 _backendUsageBuilder.registerGlobalFunctionDependency(element); 199 _backendUsageBuilder.registerGlobalFunctionDependency(element);
204 } 200 }
205 201
206 WorldImpact processNativeClasses(Iterable<LibraryElement> libraries) { 202 WorldImpact processNativeClasses(Iterable<LibraryElement> libraries) {
207 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); 203 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
208 Set<ClassElement> nativeClasses = new Set<ClassElement>(); 204 Set<ClassElement> nativeClasses =
209 libraries.forEach((l) => _processNativeClassesInLibrary(l, nativeClasses)); 205 _nativeClassResolver.computeNativeClasses(libraries);
210 if (_helpers.isolateHelperLibrary != null) {
211 _processNativeClassesInLibrary(
212 _helpers.isolateHelperLibrary, nativeClasses);
213 }
214 _processSubclassesOfNativeClasses(libraries, nativeClasses);
215 _nativeClasses.addAll(nativeClasses); 206 _nativeClasses.addAll(nativeClasses);
216 _unusedClasses.addAll(nativeClasses); 207 _unusedClasses.addAll(nativeClasses);
217 if (!enableLiveTypeAnalysis) { 208 if (!enableLiveTypeAnalysis) {
218 _registerTypeUses(impactBuilder, _nativeClasses, 'forced'); 209 _registerTypeUses(impactBuilder, _nativeClasses, 'forced');
219 } 210 }
220 return impactBuilder; 211 return impactBuilder;
221 } 212 }
222 213
223 void _processNativeClassesInLibrary(
224 LibraryElement library, Set<ClassElement> nativeClasses) {
225 // Use implementation to ensure the inclusion of injected members.
226 library.implementation.forEachLocalMember((Element element) {
227 if (element.isClass) {
228 ClassElement cls = element;
229 if (_nativeBasicData.isNativeClass(cls)) {
230 _processNativeClass(element, nativeClasses);
231 }
232 }
233 });
234 }
235
236 void _processNativeClass(
237 ClassElement classElement, Set<ClassElement> nativeClasses) {
238 nativeClasses.add(classElement);
239 // Resolve class to ensure the class has valid inheritance info.
240 classElement.ensureResolved(_resolution);
241 // Js Interop interfaces do not have tags.
242 if (_nativeBasicData.isJsInteropClass(classElement)) return;
243 // Since we map from dispatch tags to classes, a dispatch tag must be used
244 // on only one native class.
245 for (String tag in _nativeBasicData.getNativeTagsOfClass(classElement)) {
246 ClassElement owner = tagOwner[tag];
247 if (owner != null) {
248 if (owner != classElement) {
249 _reporter.internalError(
250 classElement, "Tag '$tag' already in use by '${owner.name}'");
251 }
252 } else {
253 tagOwner[tag] = classElement;
254 }
255 }
256 }
257
258 void _processSubclassesOfNativeClasses(
259 Iterable<LibraryElement> libraries, Set<ClassElement> nativeClasses) {
260 Set<ClassElement> nativeClassesAndSubclasses = new Set<ClassElement>();
261 // Collect potential subclasses, e.g.
262 //
263 // class B extends foo.A {}
264 //
265 // String "A" has a potential subclass B.
266
267 var potentialExtends = new Map<String, Set<ClassElement>>();
268
269 libraries.forEach((library) {
270 library.implementation.forEachLocalMember((element) {
271 if (element.isClass) {
272 String extendsName = _findExtendsNameOfClass(element);
273 if (extendsName != null) {
274 Set<ClassElement> potentialSubclasses = potentialExtends
275 .putIfAbsent(extendsName, () => new Set<ClassElement>());
276 potentialSubclasses.add(element);
277 }
278 }
279 });
280 });
281
282 // Resolve all the native classes and any classes that might extend them in
283 // [potentialExtends], and then check that the properly resolved class is in
284 // fact a subclass of a native class.
285
286 ClassElement nativeSuperclassOf(ClassElement classElement) {
287 if (_nativeBasicData.isNativeClass(classElement)) return classElement;
288 if (classElement.superclass == null) return null;
289 return nativeSuperclassOf(classElement.superclass);
290 }
291
292 void walkPotentialSubclasses(ClassElement element) {
293 if (nativeClassesAndSubclasses.contains(element)) return;
294 element.ensureResolved(_resolution);
295 ClassElement nativeSuperclass = nativeSuperclassOf(element);
296 if (nativeSuperclass != null) {
297 nativeClassesAndSubclasses.add(element);
298 Set<ClassElement> potentialSubclasses = potentialExtends[element.name];
299 if (potentialSubclasses != null) {
300 potentialSubclasses.forEach(walkPotentialSubclasses);
301 }
302 }
303 }
304
305 nativeClasses.forEach(walkPotentialSubclasses);
306 nativeClasses.addAll(nativeClassesAndSubclasses);
307 }
308
309 /**
310 * Returns the source string of the class named in the extends clause, or
311 * `null` if there is no extends clause.
312 */
313 String _findExtendsNameOfClass(ClassElement classElement) {
314 if (classElement.isResolved) {
315 ClassElement superClass = classElement.superclass;
316 while (superClass != null) {
317 if (!superClass.isUnnamedMixinApplication) {
318 return superClass.name;
319 }
320 superClass = superClass.superclass;
321 }
322 return null;
323 }
324
325 // "class B extends A ... {}" --> "A"
326 // "class B extends foo.A ... {}" --> "A"
327 // "class B<T> extends foo.A<T,T> with M1, M2 ... {}" --> "A"
328
329 // We want to avoid calling classElement.parseNode on every class. Doing so
330 // will slightly increase parse time and size and cause compiler errors and
331 // warnings to me emitted in more unused code.
332
333 // An alternative to this code is to extend the API of ClassElement to
334 // expose the name of the extended element.
335
336 // Pattern match the above cases in the token stream.
337 // [abstract] class X extends [id.]* id
338
339 Token skipTypeParameters(Token token) {
340 BeginGroupToken beginGroupToken = token;
341 Token endToken = beginGroupToken.endGroup;
342 return endToken.next;
343 //for (;;) {
344 // token = token.next;
345 // if (token.stringValue == '>') return token.next;
346 // if (token.stringValue == '<') return skipTypeParameters(token);
347 //}
348 }
349
350 String scanForExtendsName(Token token) {
351 if (token.stringValue == 'abstract') token = token.next;
352 if (token.stringValue != 'class') return null;
353 token = token.next;
354 if (!token.isIdentifier()) return null;
355 token = token.next;
356 // class F<X extends B<X>> extends ...
357 if (token.stringValue == '<') {
358 token = skipTypeParameters(token);
359 }
360 if (token.stringValue != 'extends') return null;
361 token = token.next;
362 Token id = token;
363 while (token.kind != Tokens.EOF_TOKEN) {
364 token = token.next;
365 if (token.stringValue != '.') break;
366 token = token.next;
367 if (!token.isIdentifier()) return null;
368 id = token;
369 }
370 // Should be at '{', 'with', 'implements', '<' or 'native'.
371 return id.lexeme;
372 }
373
374 return _reporter.withCurrentElement(classElement, () {
375 return scanForExtendsName(classElement.position);
376 });
377 }
378
379 void logSummary(log(message)) { 214 void logSummary(log(message)) {
380 log('Resolved ${_registeredClasses.length} native elements used, ' 215 log('Resolved ${_registeredClasses.length} native elements used, '
381 '${_unusedClasses.length} native elements dead.'); 216 '${_unusedClasses.length} native elements dead.');
382 } 217 }
383 } 218 }
384 219
385 class NativeCodegenEnqueuer extends NativeEnqueuerBase { 220 class NativeCodegenEnqueuer extends NativeEnqueuerBase {
386 final CodeEmitterTask emitter; 221 final CodeEmitterTask _emitter;
387 222
388 final Set<ClassElement> doneAddSubtypes = new Set<ClassElement>(); 223 final Set<ClassElement> _doneAddSubtypes = new Set<ClassElement>();
389 224
390 final NativeResolutionEnqueuer _resolutionEnqueuer; 225 final NativeResolutionEnqueuer _resolutionEnqueuer;
391 226
392 NativeCodegenEnqueuer( 227 NativeCodegenEnqueuer(
393 Compiler compiler, this.emitter, this._resolutionEnqueuer) 228 Compiler compiler, this._emitter, this._resolutionEnqueuer)
394 : super(compiler, compiler.options.enableNativeLiveTypeAnalysis) {} 229 : super(compiler, compiler.options.enableNativeLiveTypeAnalysis) {}
395 230
396 NativeData get _nativeData => _backend.nativeData; 231 NativeData get _nativeData => _backend.nativeData;
397 232
398 WorldImpact processNativeClasses(Iterable<LibraryElement> libraries) { 233 WorldImpact processNativeClasses(Iterable<LibraryElement> libraries) {
399 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl(); 234 WorldImpactBuilderImpl impactBuilder = new WorldImpactBuilderImpl();
400 _unusedClasses.addAll(_resolutionEnqueuer._nativeClasses); 235 _unusedClasses.addAll(_resolutionEnqueuer._nativeClasses);
401 236
402 if (!enableLiveTypeAnalysis) { 237 if (!enableLiveTypeAnalysis) {
403 _registerTypeUses( 238 _registerTypeUses(
(...skipping 14 matching lines...) Expand all
418 return impactBuilder; 253 return impactBuilder;
419 } 254 }
420 255
421 void _registerTypeUses( 256 void _registerTypeUses(
422 WorldImpactBuilder impactBuilder, Set<ClassElement> classes, cause) { 257 WorldImpactBuilder impactBuilder, Set<ClassElement> classes, cause) {
423 super._registerTypeUses(impactBuilder, classes, cause); 258 super._registerTypeUses(impactBuilder, classes, cause);
424 259
425 for (ClassElement classElement in classes) { 260 for (ClassElement classElement in classes) {
426 // Add the information that this class is a subtype of its supertypes. The 261 // Add the information that this class is a subtype of its supertypes. The
427 // code emitter and the ssa builder use that information. 262 // code emitter and the ssa builder use that information.
428 _addSubtypes(classElement, emitter.nativeEmitter); 263 _addSubtypes(classElement, _emitter.nativeEmitter);
429 } 264 }
430 } 265 }
431 266
432 void _addSubtypes(ClassElement cls, NativeEmitter emitter) { 267 void _addSubtypes(ClassElement cls, NativeEmitter emitter) {
433 if (!_nativeData.isNativeClass(cls)) return; 268 if (!_nativeData.isNativeClass(cls)) return;
434 if (doneAddSubtypes.contains(cls)) return; 269 if (_doneAddSubtypes.contains(cls)) return;
435 doneAddSubtypes.add(cls); 270 _doneAddSubtypes.add(cls);
436 271
437 // Walk the superclass chain since classes on the superclass chain might not 272 // Walk the superclass chain since classes on the superclass chain might not
438 // be instantiated (abstract or simply unused). 273 // be instantiated (abstract or simply unused).
439 _addSubtypes(cls.superclass, emitter); 274 _addSubtypes(cls.superclass, emitter);
440 275
441 for (ResolutionInterfaceType type in cls.allSupertypes) { 276 for (ResolutionInterfaceType type in cls.allSupertypes) {
442 List<ClassEntity> subtypes = 277 List<ClassEntity> subtypes =
443 emitter.subtypes.putIfAbsent(type.element, () => <ClassEntity>[]); 278 emitter.subtypes.putIfAbsent(type.element, () => <ClassEntity>[]);
444 subtypes.add(cls); 279 subtypes.add(cls);
445 } 280 }
(...skipping 10 matching lines...) Expand all
456 List<ClassEntity> directSubtypes = 291 List<ClassEntity> directSubtypes =
457 emitter.directSubtypes.putIfAbsent(superclass, () => <ClassEntity>[]); 292 emitter.directSubtypes.putIfAbsent(superclass, () => <ClassEntity>[]);
458 directSubtypes.add(cls); 293 directSubtypes.add(cls);
459 } 294 }
460 295
461 void logSummary(log(message)) { 296 void logSummary(log(message)) {
462 log('Compiled ${_registeredClasses.length} native classes, ' 297 log('Compiled ${_registeredClasses.length} native classes, '
463 '${_unusedClasses.length} native classes omitted.'); 298 '${_unusedClasses.length} native classes omitted.');
464 } 299 }
465 } 300 }
OLDNEW
« no previous file with comments | « pkg/compiler/lib/src/js_backend/backend.dart ('k') | pkg/compiler/lib/src/native/resolver.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698