| 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 |