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

Unified Diff: pkg/compiler/lib/src/js_backend/backend.dart

Issue 2688413003: Extract BackendUsage, MirrorsData, and CheckedModeHelpers from Backend. (Closed)
Patch Set: Cleanup Created 3 years, 10 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « pkg/compiler/lib/src/deferred_load.dart ('k') | pkg/compiler/lib/src/js_backend/backend_helpers.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/compiler/lib/src/js_backend/backend.dart
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index c881cb9c29b2a2a3e0a705c2709daa2180f1173a..a10055ea2440b60d832213eb9181b7f13a866f02 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -68,6 +68,7 @@ import '../world.dart' show ClosedWorld, ClosedWorldRefiner;
import 'backend_helpers.dart';
import 'backend_impact.dart';
import 'backend_serialization.dart' show JavaScriptBackendSerialization;
+import 'backend_usage.dart';
import 'checked_mode_helpers.dart';
import 'constant_handler_javascript.dart';
import 'custom_elements_analysis.dart';
@@ -76,6 +77,7 @@ import 'interceptor_data.dart' show InterceptorData;
import 'js_interop_analysis.dart' show JsInteropAnalysis;
import 'lookup_map_analysis.dart' show LookupMapAnalysis;
import 'mirrors_analysis.dart';
+import 'mirrors_data.dart';
import 'namer.dart';
import 'native_data.dart' show NativeData;
import 'no_such_method_registry.dart';
@@ -342,9 +344,6 @@ class JavaScriptBackend extends Target {
/// Maps special classes to their implementation (JSXxx) class.
Map<ClassElement, ClassElement> implementationClasses;
- bool needToInitializeIsolateAffinityTag = false;
- bool needToInitializeDispatchProperty = false;
-
Namer _namer;
Namer get namer {
@@ -374,32 +373,10 @@ class JavaScriptBackend extends Target {
final RuntimeTypes rti;
final RuntimeTypesEncoder rtiEncoder;
- /// True if a call to preserveMetadataMarker has been seen. This means that
- /// metadata must be retained for dart:mirrors to work correctly.
- bool mustRetainMetadata = false;
-
- /// True if any metadata has been retained. This is slightly different from
- /// [mustRetainMetadata] and tells us if any metadata was retained. For
- /// example, if [mustRetainMetadata] is true but there is no metadata in the
- /// program, this variable will stil be false.
- bool hasRetainedMetadata = false;
-
/// True if a call to preserveUris has been seen and the preserve-uris flag
/// is set.
bool mustPreserveUris = false;
- /// True if a call to preserveLibraryNames has been seen.
- bool mustRetainLibraryNames = false;
-
- /// True if a call to preserveNames has been seen.
- bool mustPreserveNames = false;
-
- /// True if a call to disableTreeShaking has been seen.
- bool isTreeShakingDisabled = false;
-
- /// True if there isn't sufficient @MirrorsUsed data.
- bool hasInsufficientMirrorsUsed = false;
-
/// True if a core-library function requires the preamble file to function.
bool requiresPreamble = false;
@@ -428,35 +405,6 @@ class JavaScriptBackend extends Target {
/// Set of elements for which metadata has been registered as dependencies.
final Set<Element> _registeredMetadata = new Set<Element>();
- /// List of elements that the user has requested for reflection.
- final Set<Element> targetsUsed = new Set<Element>();
-
- /// List of annotations provided by user that indicate that the annotated
- /// element must be retained.
- final Set<Element> metaTargetsUsed = new Set<Element>();
-
- /// Set of methods that are needed by reflection. Computed using
- /// [computeMembersNeededForReflection] on first use.
- Set<Element> _membersNeededForReflection = null;
- Iterable<Element> get membersNeededForReflection {
- assert(_membersNeededForReflection != null);
- return _membersNeededForReflection;
- }
-
- /// List of symbols that the user has requested for reflection.
- final Set<String> symbolsUsed = new Set<String>();
-
- /// List of elements that the backend may use.
- final Set<Element> helpersUsed = new Set<Element>();
-
- /// All the checked mode helpers.
- static const checkedModeHelpers = CheckedModeHelper.helpers;
-
- // Checked mode helpers indexed by name.
- Map<String, CheckedModeHelper> checkedModeHelperByName =
- new Map<String, CheckedModeHelper>.fromIterable(checkedModeHelpers,
- key: (helper) => helper.name);
-
TypeVariableHandler typeVariableHandler;
/// Number of methods compiled before considering reflection.
@@ -508,6 +456,9 @@ class JavaScriptBackend extends Target {
final NativeData nativeData = new NativeData();
InterceptorData _interceptorData;
+ BackendUsage _backendUsage;
+ final MirrorsData mirrorsData;
+ CheckedModeHelpers _checkedModeHelpers;
BackendHelpers helpers;
final BackendImpacts impacts;
@@ -535,8 +486,11 @@ class JavaScriptBackend extends Target {
: const JavaScriptSourceInformationStrategy(),
impacts = new BackendImpacts(compiler),
frontend = new JSFrontendAccess(compiler),
+ mirrorsData = new MirrorsData(compiler),
this.compiler = compiler {
helpers = new BackendHelpers(compiler.elementEnvironment, commonElements);
+ _backendUsage = new BackendUsage(commonElements, helpers);
+ _checkedModeHelpers = new CheckedModeHelpers(commonElements, helpers);
emitter =
new CodeEmitterTask(compiler, generateSourceMap, useStartupEmitter);
typeVariableHandler = new TypeVariableHandler(compiler);
@@ -570,6 +524,10 @@ class JavaScriptBackend extends Target {
InterceptorData get interceptorData => _interceptorData;
+ BackendUsage get backendUsage => _backendUsage;
+
+ CheckedModeHelpers get checkedModeHelpers => _checkedModeHelpers;
+
/// Returns constant environment for the JavaScript interpretation of the
/// constants.
JavaScriptConstantCompiler get constants {
@@ -614,95 +572,13 @@ class JavaScriptBackend extends Target {
: new Namer(this, closedWorld, codegenWorldBuilder);
}
- /// The backend must *always* call this method when enqueuing an
- /// element. Calls done by the backend are not seen by global
- /// optimizations, so they would make these optimizations unsound.
- /// Therefore we need to collect the list of helpers the backend may
- /// use.
- // TODO(johnniwinther): Replace this with a more precise modelling; type
- // inference of these elements is disabled.
- Element registerBackendUse(Element element) {
- if (element == null) return null;
- assert(invariant(element, _isValidBackendUse(element),
- message: "Backend use of $element is not allowed."));
- helpersUsed.add(element.declaration);
- if (element.isClass && element.isPatched) {
- // Both declaration and implementation may declare fields, so we
- // add both to the list of helpers.
- helpersUsed.add(element.implementation);
- }
- return element;
- }
-
- bool _isValidBackendUse(Element element) {
- assert(invariant(element, element.isDeclaration, message: ""));
- if (element is ConstructorElement &&
- (element == helpers.streamIteratorConstructor ||
- compiler.commonElements.isSymbolConstructor(element) ||
- helpers.isSymbolValidatedConstructor(element) ||
- element == helpers.syncCompleterConstructor)) {
- // TODO(johnniwinther): These are valid but we could be more precise.
- return true;
- } else if (element == commonElements.symbolClass ||
- element == helpers.objectNoSuchMethod) {
- // TODO(johnniwinther): These are valid but we could be more precise.
- return true;
- } else if (element.implementationLibrary.isPatch ||
- // Needed to detect deserialized injected elements, that is
- // element declared in patch files.
- (element.library.isPlatformLibrary &&
- element.sourcePosition.uri.path
- .contains('_internal/js_runtime/lib/')) ||
- element.library == helpers.jsHelperLibrary ||
- element.library == helpers.interceptorsLibrary ||
- element.library == helpers.isolateHelperLibrary) {
- // TODO(johnniwinther): We should be more precise about these.
- return true;
- } else if (element == commonElements.listClass ||
- element == helpers.mapLiteralClass ||
- element == commonElements.functionClass ||
- element == commonElements.stringClass) {
- // TODO(johnniwinther): Avoid these.
- return true;
- } else if (element == helpers.genericNoSuchMethod ||
- element == helpers.unresolvedConstructorError ||
- element == helpers.malformedTypeError) {
- return true;
- }
- return false;
- }
-
- bool usedByBackend(Element element) {
- if (element.isRegularParameter ||
- element.isInitializingFormal ||
- element.isField) {
- if (usedByBackend(element.enclosingElement)) return true;
- }
- return helpersUsed.contains(element.declaration);
- }
-
- bool invokedReflectively(Element element) {
- if (element.isRegularParameter || element.isInitializingFormal) {
- ParameterElement parameter = element;
- if (invokedReflectively(parameter.functionDeclaration)) return true;
- }
-
- if (element.isField) {
- if (Elements.isStaticOrTopLevel(element) &&
- (element.isFinal || element.isConst)) {
- return false;
- }
- }
-
- return isAccessibleByReflection(element.declaration);
- }
-
/// Returns true if global optimizations such as type inferencing
/// can apply to this element. One category of elements that do not
/// apply is runtime helpers that the backend calls, but the
/// optimizations don't see those calls.
bool canBeUsedForGlobalOptimizations(Element element) {
- return !usedByBackend(element) && !invokedReflectively(element);
+ return !backendUsage.usedByBackend(element) &&
+ !mirrorsData.invokedReflectively(element);
}
/**
@@ -888,7 +764,7 @@ class JavaScriptBackend extends Target {
// TODO(johnniwinther): Find the right [CallStructure].
helper,
null));
- registerBackendUse(helper);
+ backendUsage.registerBackendUse(helper);
}
impactBuilder
.registerTypeUse(new TypeUse.instantiation(backendClasses.typeType));
@@ -1095,7 +971,7 @@ class JavaScriptBackend extends Target {
for (Entity entity in compiler.enqueuer.resolution.processedEntities) {
processAnnotations(entity, closedWorldRefiner);
}
- computeMembersNeededForReflection(closedWorld);
+ mirrorsData.computeMembersNeededForReflection(closedWorld);
rti.computeClassesNeedingRti(
compiler.enqueuer.resolution.worldBuilder, closedWorld);
_registeredMetadata.clear();
@@ -1403,150 +1279,12 @@ class JavaScriptBackend extends Target {
return element;
}
- /**
- * Returns the checked mode helper that will be needed to do a type check/type
- * cast on [type] at runtime. Note that this method is being called both by
- * the resolver with interface types (int, String, ...), and by the SSA
- * backend with implementation types (JSInt, JSString, ...).
- */
- CheckedModeHelper getCheckedModeHelper(ResolutionDartType type,
- {bool typeCast}) {
- return getCheckedModeHelperInternal(type,
- typeCast: typeCast, nativeCheckOnly: false);
- }
-
- /**
- * Returns the native checked mode helper that will be needed to do a type
- * check/type cast on [type] at runtime. If no native helper exists for
- * [type], [:null:] is returned.
- */
- CheckedModeHelper getNativeCheckedModeHelper(ResolutionDartType type,
- {bool typeCast}) {
- return getCheckedModeHelperInternal(type,
- typeCast: typeCast, nativeCheckOnly: true);
- }
-
- /**
- * Returns the checked mode helper for the type check/type cast for [type]. If
- * [nativeCheckOnly] is [:true:], only names for native helpers are returned.
- */
- CheckedModeHelper getCheckedModeHelperInternal(ResolutionDartType type,
- {bool typeCast, bool nativeCheckOnly}) {
- String name = getCheckedModeHelperNameInternal(type,
- typeCast: typeCast, nativeCheckOnly: nativeCheckOnly);
- if (name == null) return null;
- CheckedModeHelper helper = checkedModeHelperByName[name];
- assert(helper != null);
- return helper;
- }
-
- String getCheckedModeHelperNameInternal(ResolutionDartType type,
- {bool typeCast, bool nativeCheckOnly}) {
- assert(type.kind != ResolutionTypeKind.TYPEDEF);
- if (type.isMalformed) {
- // The same error is thrown for type test and type cast of a malformed
- // type so we only need one check method.
- return 'checkMalformedType';
- }
-
- if (type.isVoid) {
- assert(!typeCast); // Cannot cast to void.
- if (nativeCheckOnly) return null;
- return 'voidTypeCheck';
- }
-
- if (type.isTypeVariable) {
- return typeCast
- ? 'subtypeOfRuntimeTypeCast'
- : 'assertSubtypeOfRuntimeType';
- }
-
- if (type.isFunctionType) return null;
-
- assert(invariant(NO_LOCATION_SPANNABLE, type.isInterfaceType,
- message: "Unexpected type: $type (${type.kind})"));
- ClassElement element = type.element;
- bool nativeCheck =
- nativeCheckOnly || emitter.nativeEmitter.requiresNativeIsCheck(element);
-
- // TODO(13955), TODO(9731). The test for non-primitive types should use an
- // interceptor. The interceptor should be an argument to HTypeConversion so
- // that it can be optimized by standard interceptor optimizations.
- nativeCheck = true;
-
- var suffix = typeCast ? 'TypeCast' : 'TypeCheck';
- if (element == helpers.jsStringClass ||
- element == commonElements.stringClass) {
- if (nativeCheckOnly) return null;
- return 'string$suffix';
- }
-
- if (element == helpers.jsDoubleClass ||
- element == commonElements.doubleClass) {
- if (nativeCheckOnly) return null;
- return 'double$suffix';
- }
-
- if (element == helpers.jsNumberClass ||
- element == commonElements.numClass) {
- if (nativeCheckOnly) return null;
- return 'num$suffix';
- }
-
- if (element == helpers.jsBoolClass || element == commonElements.boolClass) {
- if (nativeCheckOnly) return null;
- return 'bool$suffix';
- }
-
- if (element == helpers.jsIntClass ||
- element == commonElements.intClass ||
- element == helpers.jsUInt32Class ||
- element == helpers.jsUInt31Class ||
- element == helpers.jsPositiveIntClass) {
- if (nativeCheckOnly) return null;
- return 'int$suffix';
- }
-
- if (commonElements.isNumberOrStringSupertype(element)) {
- return nativeCheck
- ? 'numberOrStringSuperNative$suffix'
- : 'numberOrStringSuper$suffix';
- }
-
- if (commonElements.isStringOnlySupertype(element)) {
- return nativeCheck ? 'stringSuperNative$suffix' : 'stringSuper$suffix';
- }
-
- if ((element == commonElements.listClass ||
- element == helpers.jsArrayClass) &&
- type.treatAsRaw) {
- if (nativeCheckOnly) return null;
- return 'list$suffix';
- }
-
- if (commonElements.isListSupertype(element)) {
- return nativeCheck ? 'listSuperNative$suffix' : 'listSuper$suffix';
- }
-
- if (type.isInterfaceType && !type.treatAsRaw) {
- return typeCast ? 'subtypeCast' : 'assertSubtype';
- }
-
- if (nativeCheck) {
- // TODO(karlklose): can we get rid of this branch when we use
- // interceptors?
- return 'intercepted$suffix';
- } else {
- return 'property$suffix';
- }
- }
-
void _registerCheckedModeHelpers(WorldImpactBuilder impactBuilder) {
// We register all the helpers in the resolution queue.
// TODO(13155): Find a way to register fewer helpers.
List<Element> staticUses = <Element>[];
- for (CheckedModeHelper helper in checkedModeHelpers) {
- staticUses.add(helper.getStaticUse(compiler).element);
+ for (CheckedModeHelper helper in CheckedModeHelpers.helpers) {
+ staticUses.add(helper.getStaticUse(helpers).element);
}
impactTransformer.registerBackendImpact(
impactBuilder, new BackendImpact(globalUses: staticUses));
@@ -1585,17 +1323,17 @@ class JavaScriptBackend extends Target {
WorldImpact registerUsedElement(MemberElement element, {bool forResolution}) {
WorldImpactBuilderImpl worldImpact = new WorldImpactBuilderImpl();
if (element == helpers.disableTreeShakingMarker) {
- isTreeShakingDisabled = true;
+ mirrorsData.isTreeShakingDisabled = true;
} else if (element == helpers.preserveNamesMarker) {
- mustPreserveNames = true;
+ mirrorsData.mustPreserveNames = true;
} else if (element == helpers.preserveMetadataMarker) {
- mustRetainMetadata = true;
+ mirrorsData.mustRetainMetadata = true;
} else if (element == helpers.preserveUrisMarker) {
if (compiler.options.preserveUris) mustPreserveUris = true;
} else if (element == helpers.preserveLibraryNamesMarker) {
- mustRetainLibraryNames = true;
+ mirrorsData.mustRetainLibraryNames = true;
} else if (element == helpers.getIsolateAffinityTagMarker) {
- needToInitializeIsolateAffinityTag = true;
+ backendUsage.needToInitializeIsolateAffinityTag = true;
} else if (element.isDeferredLoaderGetter) {
// TODO(sigurdm): Create a function registerLoadLibraryAccess.
if (!isLoadLibraryFunctionResolved) {
@@ -1664,47 +1402,6 @@ class JavaScriptBackend extends Target {
return worldImpact;
}
- /// Called when [:const Symbol(name):] is seen.
- void registerConstSymbol(String name) {
- symbolsUsed.add(name);
- if (name.endsWith('=')) {
- symbolsUsed.add(name.substring(0, name.length - 1));
- }
- }
-
- /// Should [element] (a getter) that would normally not be generated due to
- /// treeshaking be retained for reflection?
- bool shouldRetainGetter(Element element) {
- return isTreeShakingDisabled && isAccessibleByReflection(element);
- }
-
- /// Should [element] (a setter) hat would normally not be generated due to
- /// treeshaking be retained for reflection?
- bool shouldRetainSetter(Element element) {
- return isTreeShakingDisabled && isAccessibleByReflection(element);
- }
-
- /// Should [name] be retained for reflection?
- bool shouldRetainName(String name) {
- if (hasInsufficientMirrorsUsed) return mustPreserveNames;
- if (name == '') return false;
- return symbolsUsed.contains(name);
- }
-
- bool retainMetadataOf(Element element) {
- if (mustRetainMetadata) hasRetainedMetadata = true;
- if (mustRetainMetadata && referencedFromMirrorSystem(element)) {
- for (MetadataAnnotation metadata in element.metadata) {
- metadata.ensureResolved(resolution);
- ConstantValue constant =
- constants.getConstantValueForMetadata(metadata);
- constants.addCompileTimeConstantForEmission(constant);
- }
- return true;
- }
- return false;
- }
-
/// This method is called immediately after the [library] and its parts have
/// been scanned.
Future onLibraryScanned(LibraryElement library, LibraryLoader loader) {
@@ -1784,260 +1481,6 @@ class JavaScriptBackend extends Target {
return new Future.value();
}
- /// Called by [MirrorUsageAnalyzerTask] after it has merged all @MirrorsUsed
- /// annotations. The arguments corresponds to the unions of the corresponding
- /// fields of the annotations.
- void registerMirrorUsage(
- Set<String> symbols, Set<Element> targets, Set<Element> metaTargets) {
- if (symbols == null && targets == null && metaTargets == null) {
- // The user didn't specify anything, or there are imports of
- // 'dart:mirrors' without @MirrorsUsed.
- hasInsufficientMirrorsUsed = true;
- return;
- }
- if (symbols != null) symbolsUsed.addAll(symbols);
- if (targets != null) {
- for (Element target in targets) {
- if (target.isAbstractField) {
- AbstractFieldElement field = target;
- targetsUsed.add(field.getter);
- targetsUsed.add(field.setter);
- } else {
- targetsUsed.add(target);
- }
- }
- }
- if (metaTargets != null) metaTargetsUsed.addAll(metaTargets);
- }
-
- /**
- * Returns `true` if [element] can be accessed through reflection, that is,
- * is in the set of elements covered by a `MirrorsUsed` annotation.
- *
- * This property is used to tag emitted elements with a marker which is
- * checked by the runtime system to throw an exception if an element is
- * accessed (invoked, get, set) that is not accessible for the reflective
- * system.
- */
- bool isAccessibleByReflection(Element element) {
- if (element.isClass) {
- element = getDartClass(element);
- }
- return membersNeededForReflection.contains(element);
- }
-
- /// Returns `true` if this member element needs reflection information at
- /// runtime.
- bool isMemberAccessibleByReflection(MemberElement element) {
- return membersNeededForReflection.contains(element);
- }
-
- /// Returns true if this element has to be enqueued due to
- /// mirror usage. Might be a subset of [referencedFromMirrorSystem] if
- /// normal tree shaking is still active ([isTreeShakingDisabled] is false).
- bool requiredByMirrorSystem(Element element) {
- return hasInsufficientMirrorsUsed && isTreeShakingDisabled ||
- matchesMirrorsMetaTarget(element) ||
- targetsUsed.contains(element);
- }
-
- /// Returns true if this element is covered by a mirrorsUsed annotation.
- ///
- /// Note that it might still be ok to tree shake the element away if no
- /// reflection is used in the program (and thus [isTreeShakingDisabled] is
- /// still false). Therefore _do not_ use this predicate to decide inclusion
- /// in the tree, use [requiredByMirrorSystem] instead.
- bool referencedFromMirrorSystem(Element element, [recursive = true]) {
- Element enclosing = recursive ? element.enclosingElement : null;
-
- return hasInsufficientMirrorsUsed ||
- matchesMirrorsMetaTarget(element) ||
- targetsUsed.contains(element) ||
- (enclosing != null && referencedFromMirrorSystem(enclosing));
- }
-
- /**
- * Returns `true` if the element is needed because it has an annotation
- * of a type that is used as a meta target for reflection.
- */
- bool matchesMirrorsMetaTarget(Element element) {
- if (metaTargetsUsed.isEmpty) return false;
- for (MetadataAnnotation metadata in element.metadata) {
- // TODO(kasperl): It would be nice if we didn't have to resolve
- // all metadata but only stuff that potentially would match one
- // of the used meta targets.
- metadata.ensureResolved(resolution);
- ConstantValue value =
- compiler.constants.getConstantValue(metadata.constant);
- if (value == null) continue;
- ResolutionDartType type = value.getType(compiler.commonElements);
- if (metaTargetsUsed.contains(type.element)) return true;
- }
- return false;
- }
-
- /**
- * Visits all classes and computes whether its members are needed for
- * reflection.
- *
- * We have to precompute this set as we cannot easily answer the need for
- * reflection locally when looking at the member: We lack the information by
- * which classes a member is inherited. Called after resolution is complete.
- *
- * We filter out private libraries here, as their elements should not
- * be visible by reflection unless some other interfaces makes them
- * accessible.
- */
- void computeMembersNeededForReflection(ClosedWorld closedWorld) {
- if (_membersNeededForReflection != null) return;
- if (closedWorld.commonElements.mirrorsLibrary == null) {
- _membersNeededForReflection = const ImmutableEmptySet<Element>();
- return;
- }
- // Compute a mapping from class to the closures it contains, so we
- // can include the correct ones when including the class.
- Map<ClassElement, List<LocalFunctionElement>> closureMap =
- new Map<ClassElement, List<LocalFunctionElement>>();
- for (LocalFunctionElement closure
- in compiler.resolutionWorldBuilder.allClosures) {
- closureMap.putIfAbsent(closure.enclosingClass, () => []).add(closure);
- }
- bool foundClosure = false;
- Set<Element> reflectableMembers = new Set<Element>();
- ResolutionEnqueuer resolution = compiler.enqueuer.resolution;
- for (ClassElement cls
- in resolution.worldBuilder.directlyInstantiatedClasses) {
- // Do not process internal classes.
- if (cls.library.isInternalLibrary || cls.isInjected) continue;
- if (referencedFromMirrorSystem(cls)) {
- Set<Name> memberNames = new Set<Name>();
- // 1) the class (should be resolved)
- assert(invariant(cls, cls.isResolved));
- reflectableMembers.add(cls);
- // 2) its constructors (if resolved)
- cls.constructors.forEach((Element constructor) {
- if (resolution.hasBeenProcessed(constructor)) {
- reflectableMembers.add(constructor);
- }
- });
- // 3) all members, including fields via getter/setters (if resolved)
- cls.forEachClassMember((Member member) {
- MemberElement element = member.element;
- if (resolution.hasBeenProcessed(element)) {
- memberNames.add(member.name);
- reflectableMembers.add(element);
- element.nestedClosures
- .forEach((SynthesizedCallMethodElementX callFunction) {
- reflectableMembers.add(callFunction);
- reflectableMembers.add(callFunction.closureClass);
- });
- }
- });
- // 4) all overriding members of subclasses/subtypes (should be resolved)
- if (closedWorld.hasAnyStrictSubtype(cls)) {
- closedWorld.forEachStrictSubtypeOf(cls, (ClassElement subcls) {
- subcls.forEachClassMember((Member member) {
- if (memberNames.contains(member.name)) {
- // TODO(20993): find out why this assertion fails.
- // assert(invariant(member.element,
- // resolution.hasBeenProcessed(member.element)));
- if (resolution.hasBeenProcessed(member.element)) {
- reflectableMembers.add(member.element);
- }
- }
- });
- });
- }
- // 5) all its closures
- List<LocalFunctionElement> closures = closureMap[cls];
- if (closures != null) {
- reflectableMembers.addAll(closures);
- foundClosure = true;
- }
- } else {
- // check members themselves
- cls.constructors.forEach((ConstructorElement element) {
- if (!resolution.hasBeenProcessed(element)) return;
- if (referencedFromMirrorSystem(element, false)) {
- reflectableMembers.add(element);
- }
- });
- cls.forEachClassMember((Member member) {
- if (!resolution.hasBeenProcessed(member.element)) return;
- if (referencedFromMirrorSystem(member.element, false)) {
- reflectableMembers.add(member.element);
- }
- });
- // Also add in closures. Those might be reflectable is their enclosing
- // member is.
- List<LocalFunctionElement> closures = closureMap[cls];
- if (closures != null) {
- for (LocalFunctionElement closure in closures) {
- MemberElement member = closure.memberContext;
- if (referencedFromMirrorSystem(member, false)) {
- reflectableMembers.add(closure);
- foundClosure = true;
- }
- }
- }
- }
- }
- // We also need top-level non-class elements like static functions and
- // global fields. We use the resolution queue to decide which elements are
- // part of the live world.
- for (LibraryElement lib in compiler.libraryLoader.libraries) {
- if (lib.isInternalLibrary) continue;
- lib.forEachLocalMember((Element member) {
- if (!(member.isClass || member.isTypedef) &&
- resolution.hasBeenProcessed(member) &&
- referencedFromMirrorSystem(member)) {
- reflectableMembers.add(member);
- }
- });
- }
- // And closures inside top-level elements that do not have a surrounding
- // class. These will be in the [:null:] bucket of the [closureMap].
- if (closureMap.containsKey(null)) {
- for (Element closure in closureMap[null]) {
- if (referencedFromMirrorSystem(closure)) {
- reflectableMembers.add(closure);
- foundClosure = true;
- }
- }
- }
- // As we do not think about closures as classes, yet, we have to make sure
- // their superclasses are available for reflection manually.
- if (foundClosure) {
- ClassElement cls = helpers.closureClass;
- reflectableMembers.add(cls);
- }
- Set<Element> closurizedMembers =
- compiler.resolutionWorldBuilder.closurizedMembers;
- if (closurizedMembers.any(reflectableMembers.contains)) {
- ClassElement cls = helpers.boundClosureClass;
- reflectableMembers.add(cls);
- }
- // Add typedefs.
- reflectableMembers
- .addAll(closedWorld.allTypedefs.where(referencedFromMirrorSystem));
- // Register all symbols of reflectable elements
- for (Element element in reflectableMembers) {
- symbolsUsed.add(element.name);
- }
- _membersNeededForReflection = reflectableMembers;
- }
-
- // TODO(20791): compute closure classes after resolution and move this code to
- // [computeMembersNeededForReflection].
- void maybeMarkClosureAsNeededForReflection(
- ClosureClassElement globalizedElement,
- FunctionElement callFunction,
- FunctionElement function) {
- if (!_membersNeededForReflection.contains(function)) return;
- _membersNeededForReflection.add(callFunction);
- _membersNeededForReflection.add(globalizedElement);
- }
-
jsAst.Call generateIsJsIndexableCall(
jsAst.Expression use1, jsAst.Expression use2) {
String dispatchPropertyName = embeddedNames.DISPATCH_PROPERTY_NAME;
@@ -2072,7 +1515,7 @@ class JavaScriptBackend extends Target {
});
}
- for (Element target in targetsUsed) {
+ for (Element target in mirrorsData.targetsUsed) {
if (target == null) continue;
if (target.isField) {
staticFields.add(target);
@@ -2145,13 +1588,13 @@ class JavaScriptBackend extends Target {
preMirrorsMethodCount = generatedCode.length;
}
- if (isTreeShakingDisabled) {
+ if (mirrorsData.isTreeShakingDisabled) {
enqueuer.applyImpact(mirrorsAnalysis.computeImpactForReflectiveElements(
recentClasses,
enqueuer.processedClasses,
compiler.libraryLoader.libraries,
forResolution: enqueuer.isResolutionQueue));
- } else if (!targetsUsed.isEmpty && enqueuer.isResolutionQueue) {
+ } else if (!mirrorsData.targetsUsed.isEmpty && enqueuer.isResolutionQueue) {
// Add all static elements (not classes) that have been requested for
// reflection. If there is no mirror-usage these are probably not
// necessary, but the backend relies on them being resolved.
@@ -2160,12 +1603,12 @@ class JavaScriptBackend extends Target {
forResolution: enqueuer.isResolutionQueue));
}
- if (mustPreserveNames) reporter.log('Preserving names.');
+ if (mirrorsData.mustPreserveNames) reporter.log('Preserving names.');
- if (mustRetainMetadata) {
+ if (mirrorsData.mustRetainMetadata) {
reporter.log('Retaining metadata.');
- compiler.libraryLoader.libraries.forEach(retainMetadataOf);
+ compiler.libraryLoader.libraries.forEach(mirrorsData.retainMetadataOf);
StagedWorldImpactBuilder impactBuilder = enqueuer.isResolutionQueue
? constantImpactsForResolution
@@ -2767,7 +2210,7 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
if (worldImpact.constSymbolNames.isNotEmpty) {
registerBackendImpact(transformed, impacts.constSymbol);
for (String constSymbolName in worldImpact.constSymbolNames) {
- backend.registerConstSymbol(constSymbolName);
+ backend.mirrorsData.registerConstSymbol(constSymbolName);
}
}
@@ -2828,7 +2271,7 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
void registerBackendStaticUse(
WorldImpactBuilder worldImpact, MethodElement element,
{bool isGlobal: false}) {
- backend.registerBackendUse(element);
+ backend.backendUsage.registerBackendUse(element);
worldImpact.registerStaticUse(
// TODO(johnniwinther): Store the correct use in impacts.
new StaticUse.foreignUse(element));
@@ -2841,7 +2284,7 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
WorldImpactBuilder worldImpact, ClassElement cls,
{bool isGlobal: false}) {
cls.ensureResolved(backend.resolution);
- backend.registerBackendUse(cls);
+ backend.backendUsage.registerBackendUse(cls);
worldImpact.registerTypeUse(new TypeUse.instantiation(cls.rawType));
if (isGlobal) {
backend.compiler.globalDependencies.registerDependency(cls);
@@ -2864,7 +2307,7 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
}
for (ResolutionInterfaceType instantiatedType
in backendImpact.instantiatedTypes) {
- backend.registerBackendUse(instantiatedType.element);
+ backend.backendUsage.registerBackendUse(instantiatedType.element);
worldImpact.registerTypeUse(new TypeUse.instantiation(instantiatedType));
}
for (ClassElement cls in backendImpact.instantiatedClasses) {
@@ -2879,10 +2322,10 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
for (BackendFeature feature in backendImpact.features) {
switch (feature) {
case BackendFeature.needToInitializeDispatchProperty:
- backend.needToInitializeDispatchProperty = true;
+ backend.backendUsage.needToInitializeDispatchProperty = true;
break;
case BackendFeature.needToInitializeIsolateAffinityTag:
- backend.needToInitializeIsolateAffinityTag = true;
+ backend.backendUsage.needToInitializeIsolateAffinityTag = true;
break;
}
}
@@ -2951,19 +2394,20 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
// calls to [enqueue] with the resolution enqueuer serve as assertions
// that the helper was in fact added.
// TODO(13155): Find a way to enqueue helpers lazily.
- CheckedModeHelper helper =
- backend.getCheckedModeHelper(type, typeCast: false);
+ CheckedModeHelper helper = backend.checkedModeHelpers
+ .getCheckedModeHelper(type, typeCast: false);
if (helper != null) {
- StaticUse staticUse = helper.getStaticUse(backend.compiler);
+ StaticUse staticUse = helper.getStaticUse(backend.helpers);
transformed.registerStaticUse(staticUse);
- backend.registerBackendUse(staticUse.element);
+ backend.backendUsage.registerBackendUse(staticUse.element);
}
// We also need the native variant of the check (for DOM types).
- helper = backend.getNativeCheckedModeHelper(type, typeCast: false);
+ helper = backend.checkedModeHelpers
+ .getNativeCheckedModeHelper(type, typeCast: false);
if (helper != null) {
- StaticUse staticUse = helper.getStaticUse(backend.compiler);
+ StaticUse staticUse = helper.getStaticUse(backend.helpers);
transformed.registerStaticUse(staticUse);
- backend.registerBackendUse(staticUse.element);
+ backend.backendUsage.registerBackendUse(staticUse.element);
}
}
if (!type.treatAsRaw || type.containsTypeVariables) {
@@ -3021,7 +2465,7 @@ class JavaScriptImpactTransformer extends ImpactTransformer {
}
for (String name in impact.constSymbols) {
- backend.registerConstSymbol(name);
+ backend.mirrorsData.registerConstSymbol(name);
}
for (Set<ClassElement> classes in impact.specializedGetInterceptors) {
« no previous file with comments | « pkg/compiler/lib/src/deferred_load.dart ('k') | pkg/compiler/lib/src/js_backend/backend_helpers.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698