OLD | NEW |
1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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.mirrors_handler; | 5 library dart2js.mirrors_handler; |
6 | 6 |
7 import '../common.dart'; | 7 import '../common.dart'; |
8 import '../common/resolution.dart'; | 8 import '../common/resolution.dart'; |
9 import '../compiler.dart'; | 9 import '../compiler.dart'; |
10 import '../constants/values.dart'; | 10 import '../constants/values.dart'; |
(...skipping 278 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 } | 289 } |
290 | 290 |
291 /** | 291 /** |
292 * Decides whether an element should be included to satisfy requirements | 292 * Decides whether an element should be included to satisfy requirements |
293 * of the mirror system. | 293 * of the mirror system. |
294 * | 294 * |
295 * During resolution, we have to resort to matching elements against the | 295 * During resolution, we have to resort to matching elements against the |
296 * [MirrorsUsed] pattern, as we do not have a complete picture of the world, | 296 * [MirrorsUsed] pattern, as we do not have a complete picture of the world, |
297 * yet. | 297 * yet. |
298 */ | 298 */ |
299 bool _shouldIncludeElementDueToMirrors(Element element, | 299 bool _shouldIncludeLibraryDueToMirrors(LibraryElement element, |
300 {bool includedEnclosing}) { | 300 {bool includedEnclosing}) { |
301 return includedEnclosing || | 301 return includedEnclosing || |
302 _backend.mirrorsData.requiredByMirrorSystem(element); | 302 _backend.mirrorsData.isLibraryRequiredByMirrorSystem(element); |
| 303 } |
| 304 |
| 305 bool _shouldIncludeClassDueToMirrors(ClassElement element, |
| 306 {bool includedEnclosing}) { |
| 307 return includedEnclosing || |
| 308 _backend.mirrorsData.isClassRequiredByMirrorSystem(element); |
| 309 } |
| 310 |
| 311 bool _shouldIncludeMemberDueToMirrors(MemberElement element, |
| 312 {bool includedEnclosing}) { |
| 313 return includedEnclosing || |
| 314 _backend.mirrorsData.isMemberRequiredByMirrorSystem(element); |
303 } | 315 } |
304 | 316 |
305 /// Enqueue the constructor [ctor] if it is required for reflection. | 317 /// Enqueue the constructor [ctor] if it is required for reflection. |
306 /// | 318 /// |
307 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 319 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
308 /// needed for reflection. | 320 /// needed for reflection. |
309 void _enqueueReflectiveConstructor(ConstructorElement constructor, | 321 void _enqueueReflectiveConstructor(ConstructorElement constructor, |
310 {bool enclosingWasIncluded}) { | 322 {bool enclosingWasIncluded}) { |
311 assert(constructor.isDeclaration); | 323 assert(constructor.isDeclaration); |
312 if (_shouldIncludeElementDueToMirrors(constructor, | 324 if (_shouldIncludeMemberDueToMirrors(constructor, |
313 includedEnclosing: enclosingWasIncluded)) { | 325 includedEnclosing: enclosingWasIncluded)) { |
314 if (constructor.isFromEnvironmentConstructor) return; | 326 if (constructor.isFromEnvironmentConstructor) return; |
315 _logEnqueueReflectiveAction(constructor); | 327 _logEnqueueReflectiveAction(constructor); |
316 ClassElement cls = constructor.enclosingClass; | 328 ClassElement cls = constructor.enclosingClass; |
317 impactBuilder | 329 impactBuilder |
318 .registerTypeUse(new TypeUse.mirrorInstantiation(cls.rawType)); | 330 .registerTypeUse(new TypeUse.mirrorInstantiation(cls.rawType)); |
319 impactBuilder.registerStaticUse(new StaticUse.mirrorUse(constructor)); | 331 impactBuilder.registerStaticUse(new StaticUse.mirrorUse(constructor)); |
320 } | 332 } |
321 } | 333 } |
322 | 334 |
323 /// Enqueue the member [element] if it is required for reflection. | 335 /// Enqueue the member [element] if it is required for reflection. |
324 /// | 336 /// |
325 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 337 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
326 /// needed for reflection. | 338 /// needed for reflection. |
327 void _enqueueReflectiveMember( | 339 void _enqueueReflectiveMember( |
328 MemberElement element, bool enclosingWasIncluded) { | 340 MemberElement element, bool enclosingWasIncluded) { |
329 assert(element.isDeclaration); | 341 assert(element.isDeclaration); |
330 if (_shouldIncludeElementDueToMirrors(element, | 342 if (_shouldIncludeMemberDueToMirrors(element, |
331 includedEnclosing: enclosingWasIncluded)) { | 343 includedEnclosing: enclosingWasIncluded)) { |
332 _logEnqueueReflectiveAction(element); | 344 _logEnqueueReflectiveAction(element); |
333 if (Elements.isStaticOrTopLevel(element)) { | 345 if (Elements.isStaticOrTopLevel(element)) { |
334 impactBuilder.registerStaticUse(new StaticUse.mirrorUse(element)); | 346 impactBuilder.registerStaticUse(new StaticUse.mirrorUse(element)); |
335 } else if (element.isInstanceMember) { | 347 } else if (element.isInstanceMember) { |
336 // We need to enqueue all members matching this one in subclasses, as | 348 // We need to enqueue all members matching this one in subclasses, as |
337 // well. | 349 // well. |
338 // TODO(herhut): Use TypedSelector.subtype for enqueueing | 350 // TODO(herhut): Use TypedSelector.subtype for enqueueing |
339 DynamicUse dynamicUse = | 351 DynamicUse dynamicUse = |
340 new DynamicUse(new Selector.fromElement(element), null); | 352 new DynamicUse(new Selector.fromElement(element), null); |
341 impactBuilder.registerDynamicUse(dynamicUse); | 353 impactBuilder.registerDynamicUse(dynamicUse); |
342 if (element.isField) { | 354 if (element.isField) { |
343 DynamicUse dynamicUse = new DynamicUse( | 355 DynamicUse dynamicUse = new DynamicUse( |
344 new Selector.setter(element.memberName.setter), null); | 356 new Selector.setter(element.memberName.setter), null); |
345 impactBuilder.registerDynamicUse(dynamicUse); | 357 impactBuilder.registerDynamicUse(dynamicUse); |
346 } | 358 } |
347 } | 359 } |
348 } | 360 } |
349 } | 361 } |
350 | 362 |
351 /// Enqueue the member [element] if it is required for reflection. | 363 /// Enqueue the member [element] if it is required for reflection. |
352 /// | 364 /// |
353 /// [enclosingWasIncluded] provides a hint whether the enclosing element was | 365 /// [enclosingWasIncluded] provides a hint whether the enclosing element was |
354 /// needed for reflection. | 366 /// needed for reflection. |
355 void _enqueueReflectiveElementsInClass( | 367 void _enqueueReflectiveElementsInClass( |
356 ClassElement cls, Iterable<ClassEntity> recents, | 368 ClassElement cls, Iterable<ClassEntity> recents, |
357 {bool enclosingWasIncluded}) { | 369 {bool enclosingWasIncluded}) { |
358 assert(cls.isDeclaration); | 370 assert(cls.isDeclaration); |
359 if (cls.library.isInternalLibrary || cls.isInjected) return; | 371 if (cls.library.isInternalLibrary || cls.isInjected) return; |
360 bool includeClass = _shouldIncludeElementDueToMirrors(cls, | 372 bool includeClass = _shouldIncludeClassDueToMirrors(cls, |
361 includedEnclosing: enclosingWasIncluded); | 373 includedEnclosing: enclosingWasIncluded); |
362 if (includeClass) { | 374 if (includeClass) { |
363 _logEnqueueReflectiveAction(cls, "register"); | 375 _logEnqueueReflectiveAction(cls, "register"); |
364 ClassElement declaration = cls.declaration; | 376 ClassElement declaration = cls.declaration; |
365 declaration.ensureResolved(_resolution); | 377 declaration.ensureResolved(_resolution); |
366 impactBuilder.registerTypeUse( | 378 impactBuilder.registerTypeUse( |
367 new TypeUse.mirrorInstantiation(declaration.rawType)); | 379 new TypeUse.mirrorInstantiation(declaration.rawType)); |
368 } | 380 } |
369 // If the class is never instantiated, we know nothing of it can possibly | 381 // If the class is never instantiated, we know nothing of it can possibly |
370 // be reflected upon. | 382 // be reflected upon. |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
409 } | 421 } |
410 } | 422 } |
411 } | 423 } |
412 | 424 |
413 /// Enqueue all local members of the library [lib] if they are required for | 425 /// Enqueue all local members of the library [lib] if they are required for |
414 /// reflection. | 426 /// reflection. |
415 void _enqueueReflectiveElementsInLibrary( | 427 void _enqueueReflectiveElementsInLibrary( |
416 LibraryElement lib, Iterable<ClassEntity> recents) { | 428 LibraryElement lib, Iterable<ClassEntity> recents) { |
417 assert(lib.isDeclaration); | 429 assert(lib.isDeclaration); |
418 bool includeLibrary = | 430 bool includeLibrary = |
419 _shouldIncludeElementDueToMirrors(lib, includedEnclosing: false); | 431 _shouldIncludeLibraryDueToMirrors(lib, includedEnclosing: false); |
420 lib.forEachLocalMember((Element member) { | 432 lib.forEachLocalMember((Element member) { |
421 if (member.isInjected) return; | 433 if (member.isInjected) return; |
422 if (member.isClass) { | 434 if (member.isClass) { |
423 ClassElement cls = member; | 435 ClassElement cls = member; |
424 cls.ensureResolved(_resolution); | 436 cls.ensureResolved(_resolution); |
425 do { | 437 do { |
426 _enqueueReflectiveElementsInClass(cls, recents, | 438 _enqueueReflectiveElementsInClass(cls, recents, |
427 enclosingWasIncluded: includeLibrary); | 439 enclosingWasIncluded: includeLibrary); |
428 cls = cls.superclass; | 440 cls = cls.superclass; |
429 } while (cls != null && cls.isUnnamedMixinApplication); | 441 } while (cls != null && cls.isUnnamedMixinApplication); |
(...skipping 29 matching lines...) Expand all Loading... |
459 _enqueueReflectiveSpecialClasses(); | 471 _enqueueReflectiveSpecialClasses(); |
460 hasEnqueuedReflectiveElements = true; | 472 hasEnqueuedReflectiveElements = true; |
461 hasEnqueuedReflectiveStaticFields = true; | 473 hasEnqueuedReflectiveStaticFields = true; |
462 _logEnqueueReflectiveAction("!DONE enqueueAll"); | 474 _logEnqueueReflectiveAction("!DONE enqueueAll"); |
463 } else if (recents.isNotEmpty) { | 475 } else if (recents.isNotEmpty) { |
464 // Keep looking at new classes until fixpoint is reached. | 476 // Keep looking at new classes until fixpoint is reached. |
465 _logEnqueueReflectiveAction("!START enqueueRecents"); | 477 _logEnqueueReflectiveAction("!START enqueueRecents"); |
466 recents.forEach((ClassEntity _cls) { | 478 recents.forEach((ClassEntity _cls) { |
467 ClassElement cls = _cls; | 479 ClassElement cls = _cls; |
468 _enqueueReflectiveElementsInClass(cls, recents, | 480 _enqueueReflectiveElementsInClass(cls, recents, |
469 enclosingWasIncluded: _shouldIncludeElementDueToMirrors(cls.library, | 481 enclosingWasIncluded: _shouldIncludeLibraryDueToMirrors(cls.library, |
470 includedEnclosing: false)); | 482 includedEnclosing: false)); |
471 }); | 483 }); |
472 _logEnqueueReflectiveAction("!DONE enqueueRecents"); | 484 _logEnqueueReflectiveAction("!DONE enqueueRecents"); |
473 } | 485 } |
474 } | 486 } |
475 | 487 |
476 /// Enqueue the static fields that have been marked as used by reflective | 488 /// Enqueue the static fields that have been marked as used by reflective |
477 /// usage through `MirrorsUsed`. | 489 /// usage through `MirrorsUsed`. |
478 // TODO(johnniwinther): Compute [WorldImpact] instead of enqueuing directly. | 490 // TODO(johnniwinther): Compute [WorldImpact] instead of enqueuing directly. |
479 void enqueueReflectiveStaticFields(Iterable<Element> elements) { | 491 void enqueueReflectiveStaticFields(Iterable<Element> elements) { |
480 if (hasEnqueuedReflectiveStaticFields) return; | 492 if (hasEnqueuedReflectiveStaticFields) return; |
481 hasEnqueuedReflectiveStaticFields = true; | 493 hasEnqueuedReflectiveStaticFields = true; |
482 for (Element element in elements) { | 494 for (Element element in elements) { |
483 _enqueueReflectiveMember(element, true); | 495 _enqueueReflectiveMember(element, true); |
484 } | 496 } |
485 } | 497 } |
486 } | 498 } |
487 | 499 |
488 /// Records that [constant] is used by the element behind [registry]. | 500 /// Records that [constant] is used by the element behind [registry]. |
489 class Dependency { | 501 class Dependency { |
490 final ConstantValue constant; | 502 final ConstantValue constant; |
491 final Element annotatedElement; | 503 final Element annotatedElement; |
492 | 504 |
493 const Dependency(this.constant, this.annotatedElement); | 505 const Dependency(this.constant, this.annotatedElement); |
494 | 506 |
495 String toString() => '$annotatedElement:${constant.toStructuredText()}'; | 507 String toString() => '$annotatedElement:${constant.toStructuredText()}'; |
496 } | 508 } |
OLD | NEW |